PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Library/Game/CommandParser.php

https://github.com/NickBelhomme/Game
PHP | 256 lines | 126 code | 24 blank | 106 comment | 17 complexity | 62e1043aec3f8748ba9b571e3631af8f MD5 | raw file
  1. <?php
  2. namespace Game;
  3. use Game\Grid,
  4. Game\AbstractItem,
  5. Game\Inventory;
  6. class CommandParser
  7. {
  8. /**
  9. * The response
  10. *
  11. * @var Game\Response
  12. */
  13. protected $response;
  14. /**
  15. * The user input
  16. *
  17. * @var string
  18. */
  19. protected $input;
  20. /**
  21. *
  22. * Input after Game\Actions are applied to Game\AbstractItem(s)
  23. * When such a thing has happened the reference to the item / action
  24. * is removed from the string. Making the string ready for further parsing
  25. *
  26. * @var string
  27. */
  28. protected $parsedInput;
  29. /**
  30. * the current tile on which the player is
  31. *
  32. * @var Game\Tile
  33. */
  34. protected $tile;
  35. /**
  36. * The personal inventory of the player
  37. *
  38. * @var Game\Inventory
  39. */
  40. protected $personalInventory;
  41. /**
  42. *
  43. * The object which implements Game\Action\AcceptAction
  44. *
  45. * @var mixed
  46. */
  47. protected $itemPrimary = false;
  48. /**
  49. *
  50. * The primary item its inventory
  51. *
  52. * @var Game\Inventory
  53. */
  54. protected $itemPrimaryInventory = false;
  55. /**
  56. *
  57. * The second object which implements Game\Action\AcceptAction so it can be inspected for a potential
  58. * itemcombination
  59. *
  60. * @var mixed
  61. */
  62. protected $itemSecondary = false;
  63. /**
  64. *
  65. * The second item its inventory
  66. *
  67. * @var Game\Inventory
  68. */
  69. protected $itemSecondaryInventory = false;
  70. /**
  71. * The grid of the game
  72. * @var Game\Grid
  73. */
  74. protected $grid;
  75. /**
  76. *
  77. * a itemcombination factory name taking care of creating and
  78. * registering all the item combinations in the game
  79. *
  80. * @var string
  81. */
  82. protected $combinationRegistryClass;
  83. /**
  84. * Constructor
  85. * Will setup the entire parser and run it automatically
  86. *
  87. * @param Game\Request $request
  88. * @param Game\Response $response
  89. * @param Game\Grid $grid
  90. * @param Game\Inventory $personalInventory
  91. * @return void
  92. */
  93. public function __construct(Request $request, Response $response, Grid $grid, Inventory $personalInventory)
  94. {
  95. $this->response = $response;
  96. $this->input = trim($request->getCmd());
  97. $this->parsedInput = $this->input;
  98. $this->personalInventory = $personalInventory;
  99. $this->grid = $grid;
  100. $this->tile = $grid->getTileFromPosition();
  101. }
  102. /**
  103. * Parses the input
  104. *
  105. * @return Game\Response
  106. */
  107. public function parseCommand()
  108. {
  109. if (empty($this->input)) {
  110. return $this->response;
  111. }
  112. $completeInventoryList = $this->getItemListFromInventory($this->tile->getInventory()) + $this->getItemListFromInventory($this->personalInventory);
  113. ksort($completeInventoryList);
  114. $completeInventoryList = array_reverse($completeInventoryList);
  115. if (!is_null($this->combinationRegistryClass)) {
  116. new $this->combinationRegistryClass($completeInventoryList);
  117. }
  118. foreach ($completeInventoryList as $itemInfo) {
  119. if ($this->itemPrimary = $this->getItemForAction($itemInfo['item'])) {
  120. $this->itemPrimaryInventory = $itemInfo['inventory'];
  121. unset($completeInventoryList[$itemInfo['item']->getName()]);
  122. break;
  123. }
  124. }
  125. foreach ($completeInventoryList as $itemInfo) {
  126. if ($this->itemSecondary = $this->getItemForAction($itemInfo['item'])) {
  127. $this->itemSecondaryInventory = $itemInfo['inventory'];
  128. unset($completeInventoryList[$itemInfo['item']->getName()]);
  129. break;
  130. }
  131. }
  132. if (!$this->itemPrimary) {
  133. $this->itemPrimary = $this->tile;
  134. }
  135. if (!$action = $this->getAction()) {
  136. $this->itemPrimary = $this->grid;
  137. $action = $this->getAction();
  138. }
  139. if ($action) {
  140. $action->setGrid($this->grid);
  141. $action->setPersonalInventory($this->personalInventory);
  142. if ($message = $action->execute()) {
  143. $this->response->addMessage($message);
  144. }
  145. return $this->response;
  146. }
  147. $this->response->addMessage('you cannot do that');
  148. return $this->response;
  149. }
  150. /**
  151. * Get the itemlist from the inventory while keeping an item-inventory reference
  152. *
  153. * @param $inventory
  154. * @return array
  155. */
  156. protected function getItemListFromInventory(Inventory $inventory)
  157. {
  158. $inventoryList = array();
  159. foreach ($inventory->getItems() as $item) {
  160. $inventoryList[$item->getName()] = array('item' => $item, 'inventory' => $inventory);
  161. $inventoryList = $inventoryList + $this->getItemListFromInventory($item->getInventory());
  162. }
  163. return $inventoryList;
  164. }
  165. /**
  166. * Will extract the Game\Action from the input
  167. *
  168. * @return Game\Action
  169. */
  170. protected function getAction()
  171. {
  172. if ($action = $this->getActionFromInput()) {
  173. if($action instanceof Game_Action_Combine) {
  174. if ($this->itemSecondary !== $action->getCombination()->getItemTwo()) {
  175. $action = false;
  176. }
  177. }
  178. }
  179. return $action;
  180. }
  181. /**
  182. * Will extract the Game\Action from the primary item using the input
  183. *
  184. * @return Game\Action
  185. */
  186. protected function getActionFromInput()
  187. {
  188. if ($actions = $this->itemPrimary->getActions()) {
  189. foreach ($actions as $action) {
  190. foreach ($action->getSynonyms() as $synonym) {
  191. if (preg_match('#^'.$synonym.'#i', $this->parsedInput)) {
  192. if ('conversate' === $action->getName()) {
  193. if (preg_match('#say (\d)+#', $this->parsedInput, $match)) {
  194. $action->setSelectedOptionId($match[1]);
  195. }
  196. }
  197. return $action;
  198. }
  199. }
  200. }
  201. }
  202. return false;
  203. }
  204. /**
  205. * Get the Game\AbstractItem from the inventory depending on the input
  206. * @param Game\Inventory $itemsAvailable
  207. * @return Game\AbstractItem
  208. */
  209. protected function getItemForActionFromInventory(Inventory $itemsAvailable)
  210. {
  211. foreach ($itemsAvailable->getItems() as $item) {
  212. if ($item = $this->getItemForAction($item)) {
  213. return $item;
  214. }
  215. }
  216. return false;
  217. }
  218. /**
  219. * Check whether an item matches a specific input
  220. * @param Game\AbstractItem $item
  221. *
  222. * @return Game\AbstractItem
  223. */
  224. protected function getItemForAction(AbstractItem $item)
  225. {
  226. if (stripos($this->parsedInput, $item->getName()) !== false) {
  227. $this->parsedInput = str_ireplace($item->getName(), '', $this->parsedInput);
  228. return $item;
  229. }
  230. return false;
  231. }
  232. }