You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
10 KiB

1 year ago
  1. #include "Grid.h"
  2. #include <algorithm>
  3. Grid::Grid(cells gridCells, cells background, const GridOptions &gridOptions, const std::map<coordinates, float> &stateRewards)
  4. : allGridCells(gridCells), background(background), gridOptions(gridOptions), stateRewards(stateRewards)
  5. {
  6. cell max = allGridCells.at(allGridCells.size() - 1);
  7. maxBoundaries = std::make_pair(max.row, max.column);
  8. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(walls), [](cell c) {
  9. return c.type == Type::Wall;
  10. });
  11. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lava), [](cell c) {
  12. return c.type == Type::Lava;
  13. });
  14. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(floor), [](cell c) {
  15. return c.type == Type::Floor;
  16. });
  17. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyNorth), [](cell c) {
  18. return c.type == Type::SlipperyNorth;
  19. });
  20. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyEast), [](cell c) {
  21. return c.type == Type::SlipperyEast;
  22. });
  23. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperySouth), [](cell c) {
  24. return c.type == Type::SlipperySouth;
  25. });
  26. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyWest), [](cell c) {
  27. return c.type == Type::SlipperyWest;
  28. });
  29. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lockedDoors), [](cell c) {
  30. return c.type == Type::LockedDoor;
  31. });
  32. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(goals), [](cell c) {
  33. return c.type == Type::Goal;
  34. });
  35. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(keys), [](cell c) {
  36. return c.type == Type::Key;
  37. });
  38. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(boxes), [](cell c) {
  39. return c.type == Type::Box;
  40. });
  41. agent = *std::find_if(gridCells.begin(), gridCells.end(), [](cell c) {
  42. return c.type == Type::Agent;
  43. });
  44. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(adversaries), [](cell c) {
  45. return c.type == Type::Adversary;
  46. });
  47. agentNameAndPositionMap.insert({ "Agent", agent.getCoordinates() });
  48. for(auto const& adversary : adversaries) {
  49. std::string color = adversary.getColor();
  50. color.at(0) = std::toupper(color.at(0));
  51. try {
  52. if(gridOptions.agentsToBeConsidered.size() != 0 && std::find(gridOptions.agentsToBeConsidered.begin(), gridOptions.agentsToBeConsidered.end(), color) == gridOptions.agentsToBeConsidered.end()) continue;
  53. auto success = agentNameAndPositionMap.insert({ color, adversary.getCoordinates() });
  54. if(!success.second) {
  55. throw std::logic_error("Agent with " + color + " already present\n");
  56. }
  57. } catch(const std::logic_error& e) {
  58. std::cerr << "Expected agents colors to be different. Agent with color : '" << color << "' already present." << std::endl;
  59. throw;
  60. }
  61. }
  62. for(auto const& color : allColors) {
  63. cells cellsOfColor;
  64. std::copy_if(background.begin(), background.end(), std::back_inserter(cellsOfColor), [&color](cell c) {
  65. return c.type == Type::Floor && c.color == color;
  66. });
  67. backgroundTiles.emplace(color, cellsOfColor);
  68. }
  69. }
  70. std::ostream& operator<<(std::ostream& os, const Grid& grid) {
  71. int lastRow = 1;
  72. for(auto const& cell : grid.allGridCells) {
  73. if(lastRow != cell.row)
  74. os << std::endl;
  75. os << static_cast<char>(cell.type) << static_cast<char>(cell.color);
  76. lastRow = cell.row;
  77. }
  78. return os;
  79. }
  80. cells Grid::getGridCells() {
  81. return allGridCells;
  82. }
  83. bool Grid::isBlocked(coordinates p) {
  84. return isWall(p) || isLockedDoor(p) || isKey(p);
  85. }
  86. bool Grid::isWall(coordinates p) {
  87. return std::find_if(walls.begin(), walls.end(),
  88. [p](cell cell) {
  89. return cell.row == p.first && cell.column == p.second;
  90. }) != walls.end();
  91. }
  92. bool Grid::isLockedDoor(coordinates p) {
  93. return std::find_if(lockedDoors.begin(), lockedDoors.end(),
  94. [p](cell cell) {
  95. return cell.row == p.first && cell.column == p.second;
  96. }) != lockedDoors.end();
  97. }
  98. bool Grid::isKey(coordinates p) {
  99. return std::find_if(keys.begin(), keys.end(),
  100. [p](cell cell) {
  101. return cell.row == p.first && cell.column == p.second;
  102. }) != keys.end();
  103. }
  104. bool Grid::isBox(coordinates p) {
  105. return std::find_if(boxes.begin(), boxes.end(),
  106. [p](cell cell) {
  107. return cell.row == p.first && cell.column == p.second;
  108. }) != boxes.end();
  109. }
  110. void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) {
  111. cells northRestriction;
  112. cells eastRestriction;
  113. cells southRestriction;
  114. cells westRestriction;
  115. cells walkable = floor;
  116. walkable.insert(walkable.end(), goals.begin(), goals.end());
  117. walkable.insert(walkable.end(), boxes.begin(), boxes.end());
  118. walkable.push_back(agent);
  119. walkable.insert(walkable.end(), adversaries.begin(), adversaries.end());
  120. walkable.insert(walkable.end(), lava.begin(), lava.end());
  121. for(auto const& c : walkable) {
  122. if(isBlocked(c.getNorth())) northRestriction.push_back(c);
  123. if(isBlocked(c.getEast())) eastRestriction.push_back(c);
  124. if(isBlocked(c.getSouth())) southRestriction.push_back(c);
  125. if(isBlocked(c.getWest())) westRestriction.push_back(c);
  126. }
  127. prism::PrismModulesPrinter printer(modelType, agentNameAndPositionMap.size());
  128. printer.printModel(os, modelType);
  129. if(modelType == prism::ModelType::SMG) {
  130. printer.printGlobalMoveVariable(os, agentNameAndPositionMap.size());
  131. }
  132. for(auto const &backgroundTilesOfColor : backgroundTiles) {
  133. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) {
  134. printer.printBackgroundLabels(os, agentNameAndPosition->first, backgroundTilesOfColor);
  135. }
  136. }
  137. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) {
  138. printer.printFormulas(os, agentNameAndPosition->first, northRestriction, eastRestriction, southRestriction, westRestriction, { slipperyNorth, slipperyEast, slipperySouth, slipperyWest }, lava);
  139. printer.printGoalLabel(os, agentNameAndPosition->first, goals);
  140. printer.printKeysLabels(os, agentNameAndPosition->first, keys);
  141. }
  142. std::vector<AgentName> agentNames;
  143. std::transform(agentNameAndPositionMap.begin(),
  144. agentNameAndPositionMap.end(),
  145. std::back_inserter(agentNames),
  146. [](const std::map<AgentNameAndPosition::first_type,AgentNameAndPosition::second_type>::value_type &pair){return pair.first;});
  147. if(modelType == prism::ModelType::SMG) {
  148. printer.printCrashLabel(os, agentNames);
  149. }
  150. size_t agentIndex = 0;
  151. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition, agentIndex++) {
  152. AgentName agentName = agentNameAndPosition->first;
  153. bool agentWithView = std::find(gridOptions.agentsWithView.begin(), gridOptions.agentsWithView.end(), agentName) != gridOptions.agentsWithView.end();
  154. bool agentWithProbabilisticBehaviour = std::find(gridOptions.agentsWithProbabilisticBehaviour.begin(), gridOptions.agentsWithProbabilisticBehaviour.end(), agentName) != gridOptions.agentsWithProbabilisticBehaviour.end();
  155. std::set<std::string> slipperyActions;
  156. if(agentWithProbabilisticBehaviour) printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, agentWithView, gridOptions.probabilitiesForActions);
  157. else printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, agentWithView);
  158. for(auto const& c : slipperyNorth) {
  159. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North);
  160. printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North);
  161. }
  162. for(auto const& c : slipperyEast) {
  163. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East);
  164. printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East);
  165. }
  166. for(auto const& c : slipperySouth) {
  167. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South);
  168. printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South);
  169. }
  170. for(auto const& c : slipperyWest) {
  171. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West);
  172. printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West);
  173. }
  174. printer.printEndmodule(os);
  175. if(modelType == prism::ModelType::SMG) {
  176. if(agentWithProbabilisticBehaviour) printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, gridOptions.probabilitiesForActions, slipperyActions);
  177. else printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, {}, slipperyActions);
  178. }
  179. if(!stateRewards.empty()) {
  180. printer.printRewards(os, stateRewards, lava, goals);
  181. }
  182. }
  183. }
  184. std::array<bool, 8> Grid::getWalkableDirOf8Neighborhood(cell c) /* const */ {
  185. return (std::array<bool, 8>)
  186. {
  187. !isBlocked(c.getNorth()),
  188. !isBlocked(c.getNorth(allGridCells).getEast()),
  189. !isBlocked(c.getEast()),
  190. !isBlocked(c.getSouth(allGridCells).getEast()),
  191. !isBlocked(c.getSouth()),
  192. !isBlocked(c.getSouth(allGridCells).getWest()),
  193. !isBlocked(c.getWest()),
  194. !isBlocked(c.getNorth(allGridCells).getWest())
  195. };
  196. }