Advertisement
Guest User

Untitled

a guest
Jul 28th, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.37 KB | None | 0 0
  1. using System;
  2. using System.Data;
  3. using System.Text;
  4. using System.Threading;
  5. using System.Collections;
  6.  
  7. using Holo.Virtual.Users;
  8. using Holo.Virtual.Rooms.Pathfinding;
  9. using Ion.Storage;
  10. namespace Holo.Virtual.Rooms.Pets
  11. {
  12. /// <summary>
  13. /// Represents a computer controlled virtual user with an artifical intelligence (AI). The bot walks around in virtual rooms on specified coordinates, interacts with other virtual users and serves drinks and food.
  14. /// </summary>
  15. internal class virtualPet
  16. {
  17. #region Declares
  18. /// <summary>
  19. /// The database ID of the pet.
  20. /// </summary>
  21. internal int ID;
  22. /// <summary>
  23. /// The ID of the bot in the virtual room.
  24. /// </summary>
  25. internal int roomUID;
  26. /// <summary>
  27. /// The virtual room the bot roams in.
  28. /// </summary>
  29. internal virtualRoom Room;
  30. /// <summary>
  31. /// The name of the bot.
  32. /// </summary>
  33. internal string Name;
  34. /// <summary>
  35. /// The name of the bot.
  36. /// </summary>
  37. internal string Colour;
  38. /// <summary>
  39. /// The bot's figure string.
  40. /// </summary>
  41. internal string Figure
  42. {
  43. get
  44. {
  45. return Type.Substring(3, 1) + " " + Race + " " + Colour;
  46. }
  47. set
  48. {
  49. Figure = value;
  50. }
  51. }
  52. /// <summary>
  53. /// The bot's figure string.
  54. /// </summary>
  55. internal string Race;
  56. /// <summary>
  57. /// The bot's figure string.
  58. /// </summary>
  59. internal string Type;
  60.  
  61. /// <summary>
  62. /// The X position of the bot in the virtual room.
  63. /// </summary>
  64. internal int X;
  65. /// <summary>
  66. /// The Y position of the bot in the virtual room.
  67. /// </summary>
  68. internal int Y;
  69. /// <summary>
  70. /// The height of the bot in the virtual room.
  71. /// </summary>
  72. internal double H;
  73. /// <summary>
  74. /// The rotation of the bot's head in the virtual room.
  75. /// </summary>
  76. internal byte Z1;
  77. /// <summary>
  78. /// The rotation of the bot's body in the virtual room.
  79. /// </summary>
  80. internal byte Z2;
  81. /// <summary>
  82. /// Used for pathfinding. The X coordinate of the bot's target square in the virtual room.
  83. /// </summary>
  84. internal int goalX;
  85. /// <summary>
  86. /// Used for pathfinding. The Y coordinate of the bot's target square in the virtual room.
  87. /// </summary>
  88. internal int goalY;
  89.  
  90. private delegate void statusVoid(string Key, string Value, int Length);
  91. /// <summary>
  92. /// Handles the random determining of actions.
  93. /// </summary>
  94. private Thread aiHandler;
  95. /// <summary>
  96. /// Contains the texts that the bot can 'say' on random.
  97. /// </summary>
  98. private string[] Sayings;
  99. /// <summary>
  100. /// Contains the texts that the bot can 'shout' on random.
  101. /// </summary>
  102. private string[] Shouts;
  103. /// <summary>
  104. /// Contains the coordinate's where the bot can walk to. Ignored if freeroam is enabled.
  105. /// </summary>
  106. private Coord[] Coords;
  107. /// <summary>
  108. /// Contains the chat triggers where the bot reacts on.
  109. /// </summary>
  110. private chatTrigger[] chatTriggers;
  111. #endregion
  112.  
  113. #region Constructors/destructors
  114. /// <summary>
  115. /// Contains the bot's animation statuses.
  116. /// </summary>
  117. private Hashtable Statuses;
  118. /// <summary>
  119. /// Initializes a new virtualBot object, loading the walk squares, chat texts etc.
  120. /// </summary>
  121. /// <param name="botID">The database ID of the bot.</param>
  122. /// <param name="roomUID">The ID that identifies this bot in room.</param>
  123. /// <param name="Room">The virtualRoom object where the bot is in.</param>
  124. internal virtualPet(int petID, int roomUID, virtualRoom Room, int mX, int mY)
  125. {
  126. this.roomUID = roomUID;
  127. this.Room = Room;
  128. this.ID = petID;
  129.  
  130. DataRow dRow;
  131. using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
  132. {
  133. dRow = dbClient.getRow("SELECT ownerid,name,type,colour,race,x,y,z FROM pets WHERE id = '" + petID + "'");
  134. dbClient.runQuery("UPDATE pets SET roomid = '" + Room.roomID + "' WHERE id = '" + ID + "'");
  135. }
  136. this.Name = Convert.ToString(dRow["name"]);
  137. this.Type = Convert.ToString(dRow["type"]);
  138. this.Race = Convert.ToString(dRow["race"]);
  139. this.Colour = Convert.ToString(dRow["colour"]);
  140. if (mX == 0 && mY == 0)
  141. {
  142. this.X = Convert.ToInt32(dRow["x"]);
  143. this.Y = Convert.ToInt32(dRow["y"]);
  144. this.Z1 = Convert.ToByte(dRow["z"]);
  145. }
  146. else
  147. {
  148. this.X = mX;
  149. this.Y = mY;
  150. this.Z1 = 1;
  151. }
  152. this.Z2 = Z1;
  153. this.goalX = -1;
  154. DataColumn dCol;
  155. using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
  156. {
  157. dCol = dbClient.getColumn("SELECT text FROM pets_texts WHERE animal = '" + Type + "' AND type = 'say'");
  158. }
  159. this.Sayings = (string[])dataHandling.dColToArray(dCol);
  160. using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
  161. {
  162. dCol = dbClient.getColumn("SELECT text FROM pets_texts WHERE animal = '" + Type + "' AND type = 'shout'");
  163. }
  164. this.Shouts = (string[])dataHandling.dColToArray(dCol);
  165.  
  166. DataTable dTable;
  167. //using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
  168. //{
  169. // dTable = dbClient.getTable("SELECT words, replies, action FROM pets_texts_triggers");
  170. //}
  171. //this.chatTriggers = new chatTrigger[dTable.Rows.Count];
  172. int i = 0;
  173. //foreach (DataRow dbRow in dTable.Rows)
  174. //{
  175. // // this.chatTriggers[i] = new chatTrigger((Convert.ToString(dbRow["words"]).ToLower()).Split('}'), (Convert.ToString(dbRow["replies"])).Split('}'), (Convert.ToString(dbRow["serve_replies"])).Split('}'), Convert.ToString(dbRow["serve_item"]));
  176. // i++;
  177. //}
  178. using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
  179. {
  180. dTable = dbClient.getTable("SELECT x,y FROM roombots_coords WHERE id = '" + petID + "'");
  181. }
  182.  
  183. Coords = new Coord[dTable.Rows.Count];
  184. i = 0;
  185.  
  186. foreach (DataRow dbRow in dTable.Rows)
  187. {
  188. Coords[i] = new Coord(Convert.ToInt32(dbRow["x"]), Convert.ToInt32(dbRow["y"]));
  189. i++;
  190. }
  191.  
  192. Statuses = new Hashtable();
  193. aiHandler = new Thread(new ThreadStart(AI));
  194. aiHandler.Priority = ThreadPriority.BelowNormal;
  195. aiHandler.Start();
  196. }
  197. /// <summary>
  198. /// Safely shuts this virtualBot down and tidies up all resources.
  199. /// </summary>
  200. internal void Kill()
  201. {
  202. using (DatabaseClient dbClient = (Eucalypt.dbManager.GetClient()))
  203. {
  204. dbClient.runQuery("UPDATE pets SET x = '" + X + "', y = '" + Y + "', z = '" + Z1 + "' WHERE id = '" + ID + "'");
  205. }
  206. try { aiHandler.Abort(); }
  207. catch { }
  208.  
  209. aiHandler = null;
  210. Room = null;
  211. Statuses = null;
  212. Coords = null;
  213. Sayings = null;
  214. Shouts = null;
  215. chatTriggers = null;
  216. }
  217. #endregion
  218.  
  219. #region Bot properties
  220. /// <summary>
  221. /// The details string of the bot, containing room identifier ID, name, motto, figure etc.
  222. /// </summary>
  223. internal string detailsString
  224. {
  225. get
  226. {
  227. string s = "i:" + roomUID + Convert.ToChar(13) + "n:" + roomUID + Convert.ToChar(4) + Name + Convert.ToChar(13) + "f:" + Figure + Convert.ToChar(13) + "l:" + X + " " + Y + " " + H + Convert.ToChar(13);
  228. s += "c:" + Convert.ToChar(13);
  229. return s;
  230. }
  231. }
  232. /// <summary>
  233. /// The status string of the bot, containing positions, movements, statuses (animations) etc.
  234. /// </summary>
  235. internal string statusString
  236. {
  237. get
  238. {
  239. string s = roomUID + " " + X + "," + Y + "," + H.ToString().Replace(",", ".") + "," + Z1 + "," + Z2 + "/";
  240. foreach (string Key in Statuses.Keys)
  241. {
  242. s += Key;
  243. string Value = (string)Statuses[Key];
  244. if (Value != "")
  245. s += " " + Value;
  246. s += "/";
  247. }
  248. return s;
  249. }
  250. }
  251. #endregion
  252.  
  253. #region Actions
  254. /// <summary>
  255. /// Invoked by a virtualRoomUser. There is checked if this bot reacts on a certain chat message, if so, then replies/orders etc are processed.
  256. /// </summary>
  257. /// <param name="roomUser">The virtualRoomUser object that interacts with this bot by saying a message.</param>
  258. /// <param name="Message">The message that the virtualRoomUser said to this bot.</param>
  259. internal void Interact(virtualRoomUser roomUser, string Message)
  260. {
  261. Message = Message.ToLower();
  262. string[] messageWords = Message.Split(' ');
  263. if (/*chatTriggers != null && */messageWords[0] == this.Name)
  264. {
  265. //foreach (chatTrigger Trigger in chatTriggers)
  266. //{
  267. // for (int i = 0; i < messageWords.Length; i++)
  268. // {
  269. // if (Trigger.containsWord(messageWords[i]))
  270. // {
  271. // this.Z1 = Rotation.Calculate(X, Y, roomUser.X, roomUser.Y);
  272. // this.Z2 = this.Z1;
  273. // Room.sendSaying(this, Trigger.Reply);
  274. // return; // One trigger per time
  275. // }
  276. // }
  277. //}
  278. switch (messageWords[1])
  279. {
  280. case "spill død":
  281. case "død":
  282. case "play dead":
  283. case "dã¸d":
  284. {
  285. Statuses.Remove("sit");
  286. Statuses.Remove("jmp");
  287. addStatus("ded", "");
  288. break;
  289. }
  290. case "jump":
  291. case "hopp":
  292. {
  293. Statuses.Remove("sit");
  294. Statuses.Remove("ded");
  295. addStatus("jmp", "");
  296. break;
  297. }
  298. case "kom":
  299. {
  300. Coord Next = new Coord();
  301. int[] Borders = Room.getMapBorders();
  302. Next = new Coord(roomUser.X - 1, roomUser.Y);
  303. goalX = Next.X;
  304. goalY = Next.Y;
  305. break;
  306. }
  307. }
  308. }
  309. }
  310. /// <summary>
  311. /// Rotates the bot to a certain X and Y coordinate and refreshes it in the room. If the bot is sitting, then rotating will be ignored.
  312. /// </summary>
  313. /// <param name="toX">The X coordinate to face.</param>
  314. /// <param name="toY">The Y coordinate to face.</param>
  315. internal void Rotate(int toX, int toY)
  316. {
  317. Rotate(Rotation.Calculate(X, Y, toX, toY));
  318. }
  319. /// <summary>
  320. /// Sets a new rotation for the bot and refreshes it in the room. If the bot is sitting, then rotating will be ignored.
  321. /// </summary>
  322. /// <param name="R">The new rotation to use.</param>
  323. internal void Rotate(byte R)
  324. {
  325. if (R != Z1 && Statuses.ContainsKey("sit") == false)
  326. {
  327. Z1 = R;
  328. Z2 = R;
  329. Refresh();
  330. }
  331. }
  332. /// <summary>
  333. /// Returns a Coord object with the X and Y of the walkcoord that is as closest to the given position.
  334. /// </summary>
  335. /// <param name="X">The X position.</param>
  336. /// <param name="Y">The Y position.</param>
  337. internal Coord getClosestWalkCoordTo(int X, int Y)
  338. {
  339. int minDistance = 6;
  340. Coord Closest = new Coord(-1, 0);
  341.  
  342. foreach (Coord Coord in Coords)
  343. {
  344. int curDistance = Math.Abs(X - Coord.X) + Math.Abs(Y - Coord.Y);
  345. if (curDistance < minDistance)
  346. {
  347. minDistance = curDistance;
  348. Closest = Coord;
  349. }
  350. }
  351.  
  352. return Closest;
  353. }
  354. #endregion
  355.  
  356. #region Status management
  357. /// <summary>
  358. /// Adds a status key and a value to the bot's statuses. If the status is already inside, then the previous one will be removed.
  359. /// </summary>
  360. /// <param name="Key">The key of the status.</param>
  361. /// <param name="Value">The value of the status.</param>
  362. internal void addStatus(string Key, string Value)
  363. {
  364. if (Statuses.ContainsKey(Key))
  365. Statuses.Remove(Key);
  366. Statuses.Add(Key, Value);
  367. }
  368. /// <summary>
  369. /// Removes a certain status from the bot's statuses.
  370. /// </summary>
  371. /// <param name="Key">The key of the status to remove.</param>
  372. internal void removeStatus(string Key)
  373. {
  374. try
  375. {
  376. if (Statuses.ContainsKey(Key))
  377. Statuses.Remove(Key);
  378. }
  379. catch { }
  380. }
  381. /// <summary>
  382. /// Returns a bool that indicates if the bot has a certain status at the moment.
  383. /// </summary>
  384. /// <param name="Key">The key of the status to check.</param>
  385. internal bool containsStatus(string Key)
  386. {
  387. return Statuses.ContainsKey(Key);
  388. }
  389. /// <summary>
  390. /// Refreshes the status of the bot in the virtual room.
  391. /// </summary>
  392. internal void Refresh()
  393. {
  394. Room.Refresh(this);
  395. }
  396. /// <summary>
  397. /// Adds a status to the bot, keeps it for a specified amount of time [in ms] and removes the status. Refreshes at add and remove.
  398. /// </summary>
  399. /// <param name="Key">The key of the status, eg, 'sit'.</param>
  400. /// <param name="Value">The value of the status, eg, '1.0'.</param>
  401. /// <param name="Length">The amount of milliseconsd to keep the status before removing it again.</param>
  402. internal void handleStatus(string Key, string Value, int Length)
  403. {
  404. if (Statuses.ContainsKey(Key))
  405. Statuses.Remove(Key);
  406. new statusVoid(HANDLESTATUS).BeginInvoke(Key, Value, Length, null, null);
  407. }
  408. private void HANDLESTATUS(string Key, string Value, int Length)
  409. {
  410. try
  411. {
  412. Statuses.Add(Key, Value);
  413. Refresh();
  414. Thread.Sleep(Length);
  415. Statuses.Remove(Key);
  416. Refresh();
  417. }
  418. catch { }
  419. }
  420. #endregion
  421.  
  422. #region Misc
  423. /// <summary>
  424. /// Ran on a thread. Handles the bot's artifical intelligence, by interacting with users and using random values etc.
  425. /// </summary>
  426. private void AI()
  427. {
  428. int lastMessageID = -1;
  429. Random RND = new Random(roomUID * DateTime.Now.Millisecond);
  430. //try
  431. {
  432. while (true)
  433. {
  434. int ACTION = RND.Next(0, 6);
  435. switch (ACTION)
  436. {
  437. case 1: // Move
  438. {
  439. Statuses.Remove("jmp");
  440. Statuses.Remove("sit");
  441. Statuses.Remove("ded");
  442. Coord Next = new Coord();
  443. int[] Borders = Room.getMapBorders();
  444. Next = new Coord(RND.Next(0, Borders[0]), RND.Next(0, Borders[1]));
  445. if (Next.X == X && Next.Y == Y) // Coord didn't changed
  446. {
  447. Z1 = (byte)RND.Next(0, 10);
  448. Z2 = Z1;
  449. Refresh();
  450. }
  451. else
  452. {
  453. goalX = Next.X;
  454. goalY = Next.Y;
  455. }
  456. break;
  457. }
  458.  
  459. case 2: // Rotate
  460. {
  461. byte R = (byte)RND.Next(0, 10);
  462. while (R == Z2)
  463. R = (byte)RND.Next(0, 10);
  464. Rotate(R);
  465. break;
  466. }
  467.  
  468. case 3: // Shout
  469. {
  470. if (Shouts.Length > 0)
  471. {
  472. int messageID = RND.Next(0, Shouts.Length);
  473. if (Shouts.Length > 1) // More than one shout assigned
  474. {
  475. while (messageID == lastMessageID) // Avoid shouting the same sentence two times in a row
  476. messageID = RND.Next(0, Shouts.Length);
  477. lastMessageID = messageID;
  478. }
  479. Room.sendShout(this, Shouts[messageID]);
  480. }
  481. break;
  482. }
  483.  
  484. case 4: // Say
  485. {
  486. if (Sayings.Length > 0)
  487. {
  488. int messageID = RND.Next(0, Sayings.Length);
  489. if (Sayings.Length > 1) // More than one saying assigned
  490. {
  491. while (messageID == lastMessageID) // Avoid saying the same sentence two times in a row
  492. messageID = RND.Next(0, Sayings.Length);
  493. lastMessageID = messageID;
  494. }
  495. Room.sendSaying(this, Sayings[messageID]);
  496. }
  497. break;
  498. }
  499.  
  500. case 5: // Status
  501. {
  502. /* if (RND.Next(0, 2) == 0)
  503. {
  504. Statuses.Remove("sit");
  505. Statuses.Remove("ded");
  506. handleStatus("jmp", "", 4000);
  507. }
  508. else
  509. {
  510. Statuses.Remove("sit");
  511. Statuses.Remove("jmp");
  512. addStatus("ded", "");
  513. Refresh();
  514. }*/
  515. break;
  516. }
  517. }
  518. Thread.Sleep(3000);
  519. Out.WriteTrace("Bot AI loop");
  520. }
  521. }
  522. //catch { aiHandler.Abort(); }
  523. }
  524. #endregion
  525.  
  526. #region Private objects
  527. /// <summary>
  528. /// Represents a trigger that can be invoked by a chat message. Results in a reply and/or an order confirmation.
  529. /// </summary>
  530. private class chatTrigger
  531. {
  532. /// <summary>
  533. /// A System.String array with words that invoke this trigger.
  534. /// </summary>
  535. private string[] Words;
  536. /// <summary>
  537. /// A System.String array with replies that are used when this trigger is invoked.
  538. /// </summary>
  539. private string[] Replies;
  540. internal chatTrigger(string[] Words, string[] Replies)
  541. {
  542. this.Words = Words;
  543. this.Replies = Replies;
  544. }
  545. /// <summary>
  546. /// Returns a boolean that indicates if this trigger replies on a certain word.
  547. /// </summary>
  548. /// <param name="Word">The word to check.</param>
  549. internal bool containsWord(string Word)
  550. {
  551. if (Word.Substring(Word.Length - 1, 1) == "?")
  552. Word = Word.Substring(0, Word.Length - 1);
  553.  
  554. for (int i = 0; i < Words.Length; i++)
  555. if (Words[i] == Word)
  556. return true;
  557. return false;
  558. }
  559. /// <summary>
  560. /// Returns a random reply from the replies array.
  561. /// </summary>
  562. internal string Reply
  563. {
  564. get
  565. {
  566. return Replies[new Random(DateTime.Now.Millisecond).Next(0, Replies.Length)];
  567. }
  568. }
  569. }
  570. #endregion
  571. }
  572. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement