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.

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