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.

306 lines
14 KiB

  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 - 1, max.column - 1);
  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(unlockedDoors), [](cell c) {
  33. return c.type == Type::Door;
  34. });
  35. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(goals), [](cell c) {
  36. return c.type == Type::Goal;
  37. });
  38. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(keys), [this](cell c) {
  39. for (auto const& key : keys) {
  40. if (key.color == c.color && key.type == c.type) {
  41. throw std::logic_error("Multiple keys with same color not supported " + key.getColor() + "\n");
  42. }
  43. }
  44. return c.type == Type::Key;
  45. });
  46. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(boxes), [](cell c) {
  47. return c.type == Type::Box;
  48. });
  49. agent = *std::find_if(gridCells.begin(), gridCells.end(), [](cell c) {
  50. return c.type == Type::Agent;
  51. });
  52. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(adversaries), [](cell c) {
  53. return c.type == Type::Adversary;
  54. });
  55. agentNameAndPositionMap.insert({ "Agent", agent.getCoordinates() });
  56. for(auto const& adversary : adversaries) {
  57. std::string color = adversary.getColor();
  58. color.at(0) = std::toupper(color.at(0));
  59. try {
  60. if(gridOptions.agentsToBeConsidered.size() != 0 && std::find(gridOptions.agentsToBeConsidered.begin(), gridOptions.agentsToBeConsidered.end(), color) == gridOptions.agentsToBeConsidered.end()) continue;
  61. auto success = agentNameAndPositionMap.insert({ color, adversary.getCoordinates() });
  62. if(!success.second) {
  63. throw std::logic_error("Agent with " + color + " already present\n");
  64. }
  65. } catch(const std::logic_error& e) {
  66. std::cerr << "Expected agents colors to be different. Agent with color : '" << color << "' already present." << std::endl;
  67. throw;
  68. }
  69. }
  70. for(auto const& color : allColors) {
  71. cells cellsOfColor;
  72. std::copy_if(background.begin(), background.end(), std::back_inserter(cellsOfColor), [&color](cell c) {
  73. return c.type == Type::Floor && c.color == color;
  74. });
  75. if(cellsOfColor.size() > 0) {
  76. backgroundTiles.emplace(color, cellsOfColor);
  77. }
  78. }
  79. }
  80. std::ostream& operator<<(std::ostream& os, const Grid& grid) {
  81. int lastRow = 1;
  82. for(auto const& cell : grid.allGridCells) {
  83. if(lastRow != cell.row)
  84. os << std::endl;
  85. os << static_cast<char>(cell.type) << static_cast<char>(cell.color);
  86. lastRow = cell.row;
  87. }
  88. return os;
  89. }
  90. cells Grid::getGridCells() {
  91. return allGridCells;
  92. }
  93. bool Grid::isBlocked(coordinates p) {
  94. return isWall(p); //|| isLockedDoor(p) || isKey(p);
  95. }
  96. bool Grid::isWall(coordinates p) {
  97. return std::find_if(walls.begin(), walls.end(),
  98. [p](cell cell) {
  99. return cell.row == p.first && cell.column == p.second;
  100. }) != walls.end();
  101. }
  102. bool Grid::isLockedDoor(coordinates p) {
  103. return std::find_if(lockedDoors.begin(), lockedDoors.end(),
  104. [p](cell cell) {
  105. return cell.row == p.first && cell.column == p.second;
  106. }) != lockedDoors.end();
  107. }
  108. bool Grid::isUnlockedDoor(coordinates p) {
  109. return std::find_if(unlockedDoors.begin(), unlockedDoors.end(),
  110. [p](cell cell) {
  111. return cell.row == p.first && cell.column == p.second;
  112. }) != unlockedDoors.end();
  113. }
  114. bool Grid::isKey(coordinates p) {
  115. return std::find_if(keys.begin(), keys.end(),
  116. [p](cell cell) {
  117. return cell.row == p.first && cell.column == p.second;
  118. }) != keys.end();
  119. }
  120. bool Grid::isBox(coordinates p) {
  121. return std::find_if(boxes.begin(), boxes.end(),
  122. [p](cell cell) {
  123. return cell.row == p.first && cell.column == p.second;
  124. }) != boxes.end();
  125. }
  126. void Grid::applyOverwrites(std::string& str, std::vector<Configuration>& configuration) {
  127. for (auto& config : configuration) {
  128. if (!config.overwrite_) {
  129. continue;
  130. }
  131. size_t start_pos;
  132. if (config.type_ == ConfigType::Formula) {
  133. start_pos = str.find("formula " + config.identifier_);
  134. } else if (config.type_ == ConfigType::Label) {
  135. start_pos = str.find("label " + config.identifier_);
  136. } else if (config.type_ == ConfigType::Module) {
  137. start_pos = str.find(config.identifier_);
  138. }
  139. size_t end_pos = str.find(';', start_pos) + 1;
  140. std::string expression = config.expression_;
  141. str.replace(start_pos, end_pos - start_pos , expression);
  142. }
  143. }
  144. void Grid::printToPrism(std::ostream& os, std::vector<Configuration>& configuration ,const prism::ModelType& modelType) {
  145. cells northRestriction;
  146. cells eastRestriction;
  147. cells southRestriction;
  148. cells westRestriction;
  149. cells walkable = floor;
  150. cells conditionallyWalkable;
  151. walkable.insert(walkable.end(), goals.begin(), goals.end());
  152. walkable.insert(walkable.end(), boxes.begin(), boxes.end());
  153. walkable.push_back(agent);
  154. walkable.insert(walkable.end(), adversaries.begin(), adversaries.end());
  155. walkable.insert(walkable.end(), lava.begin(), lava.end());
  156. conditionallyWalkable.insert(conditionallyWalkable.end(), keys.begin(), keys.end());
  157. conditionallyWalkable.insert(conditionallyWalkable.end(), lockedDoors.begin(), lockedDoors.end());
  158. conditionallyWalkable.insert(conditionallyWalkable.end(), unlockedDoors.begin(), unlockedDoors.end());
  159. for(auto const& c : walkable) {
  160. if(isBlocked(c.getNorth())) northRestriction.push_back(c);
  161. if(isBlocked(c.getEast())) eastRestriction.push_back(c);
  162. if(isBlocked(c.getSouth())) southRestriction.push_back(c);
  163. if(isBlocked(c.getWest())) westRestriction.push_back(c);
  164. }
  165. // TODO Add doors here (list of doors keys etc)
  166. // walkable.insert(walkable.end(), lockedDoors.begin(), lockedDoors.end());
  167. // walkable.insert(walkable.end(), unlockedDoors.begin(), unlockedDoors.end());
  168. for(auto const& c : conditionallyWalkable) {
  169. if(isBlocked(c.getNorth())) northRestriction.push_back(c);
  170. if(isBlocked(c.getEast())) eastRestriction.push_back(c);
  171. if(isBlocked(c.getSouth())) southRestriction.push_back(c);
  172. if(isBlocked(c.getWest())) westRestriction.push_back(c);
  173. }
  174. prism::PrismModulesPrinter printer(modelType, agentNameAndPositionMap.size(), configuration, gridOptions.enforceOneWays);
  175. printer.printModel(os, modelType);
  176. if(modelType == prism::ModelType::SMG) {
  177. printer.printGlobalMoveVariable(os, agentNameAndPositionMap.size());
  178. }
  179. for(auto const &backgroundTilesOfColor : backgroundTiles) {
  180. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) {
  181. printer.printBackgroundLabels(os, agentNameAndPosition->first, backgroundTilesOfColor);
  182. }
  183. }
  184. cells noTurnFloor;
  185. if(gridOptions.enforceOneWays) {
  186. for(auto const& c : floor) {
  187. cell east = c.getEast(allGridCells);
  188. cell south = c.getSouth(allGridCells);
  189. cell west = c.getWest(allGridCells);
  190. cell north = c.getNorth(allGridCells);
  191. if( (east.type == Type::Wall && west.type == Type::Wall) or
  192. (north.type == Type::Wall && south.type == Type::Wall) ) {
  193. noTurnFloor.push_back(c);
  194. }
  195. }
  196. }
  197. cells doors;
  198. doors.insert(doors.end(), lockedDoors.begin(), lockedDoors.end());
  199. doors.insert(doors.end(), unlockedDoors.begin(), unlockedDoors.end());
  200. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) {
  201. printer.printFormulas(os, agentNameAndPosition->first, northRestriction, eastRestriction, southRestriction, westRestriction, { slipperyNorth, slipperyEast, slipperySouth, slipperyWest }, lava, walls, noTurnFloor, slipperyNorth, slipperyEast, slipperySouth, slipperyWest, keys, doors);
  202. printer.printGoalLabel(os, agentNameAndPosition->first, goals);
  203. printer.printKeysLabels(os, agentNameAndPosition->first, keys);
  204. }
  205. std::vector<AgentName> agentNames;
  206. std::transform(agentNameAndPositionMap.begin(),
  207. agentNameAndPositionMap.end(),
  208. std::back_inserter(agentNames),
  209. [](const std::map<AgentNameAndPosition::first_type,AgentNameAndPosition::second_type>::value_type &pair){return pair.first;});
  210. if(modelType == prism::ModelType::SMG) {
  211. printer.printCrashLabel(os, agentNames);
  212. }
  213. size_t agentIndex = 0;
  214. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition, agentIndex++) {
  215. AgentName agentName = agentNameAndPosition->first;
  216. //std::cout << "Agent Name: " << agentName << std::endl;
  217. bool agentWithView = std::find(gridOptions.agentsWithView.begin(), gridOptions.agentsWithView.end(), agentName) != gridOptions.agentsWithView.end();
  218. bool agentWithProbabilisticBehaviour = std::find(gridOptions.agentsWithProbabilisticBehaviour.begin(), gridOptions.agentsWithProbabilisticBehaviour.end(), agentName) != gridOptions.agentsWithProbabilisticBehaviour.end();
  219. std::set<std::string> slipperyActions;
  220. printer.printInitStruct(os, agentName, keys, lockedDoors, unlockedDoors);
  221. if(agentWithProbabilisticBehaviour) printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView, gridOptions.probabilitiesForActions);
  222. else printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView);
  223. for(auto const& c : slipperyNorth) {
  224. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North);
  225. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North);
  226. }
  227. for(auto const& c : slipperyEast) {
  228. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East);
  229. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East);
  230. }
  231. for(auto const& c : slipperySouth) {
  232. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South);
  233. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South);
  234. }
  235. for(auto const& c : slipperyWest) {
  236. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West);
  237. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West);
  238. }
  239. printer.printEndmodule(os);
  240. if(modelType == prism::ModelType::SMG) {
  241. if(agentWithProbabilisticBehaviour) printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, gridOptions.probabilitiesForActions, slipperyActions);
  242. else printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, {}, slipperyActions);
  243. }
  244. //if(!stateRewards.empty()) {
  245. printer.printRewards(os, agentName, stateRewards, lava, goals, backgroundTiles);
  246. //}
  247. if (!configuration.empty()) {
  248. printer.printConfiguration(os, configuration);
  249. }
  250. }
  251. // TODO CHANGE HANDLING
  252. std::string agentName = agentNames.at(0);
  253. for (auto const & key : keys) {
  254. os << "\n";
  255. printer.printKeyModule(os, key, maxBoundaries, agentName);
  256. printer.printEndmodule(os);
  257. }
  258. for (auto const& door : lockedDoors) {
  259. os << "\n";
  260. printer.printDoorModule(os, door, maxBoundaries, agentName);
  261. printer.printEndmodule(os);
  262. }
  263. }
  264. std::array<bool, 8> Grid::getWalkableDirOf8Neighborhood(cell c) /* const */ {
  265. return (std::array<bool, 8>)
  266. {
  267. !isBlocked(c.getNorth()),
  268. !isBlocked(c.getNorth(allGridCells).getEast()),
  269. !isBlocked(c.getEast()),
  270. !isBlocked(c.getSouth(allGridCells).getEast()),
  271. !isBlocked(c.getSouth()),
  272. !isBlocked(c.getSouth(allGridCells).getWest()),
  273. !isBlocked(c.getWest()),
  274. !isBlocked(c.getNorth(allGridCells).getWest())
  275. };
  276. }