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.

293 lines
15 KiB

11 months ago
  1. #include "Grid.h"
  2. #include <boost/algorithm/string/find.hpp>
  3. #include <algorithm>
  4. prism::ModelType GridOptions::getModelType() const
  5. {
  6. if (agentsWithView.size() > 1) {
  7. return prism::ModelType::SMG;
  8. }
  9. return prism::ModelType::MDP;
  10. }
  11. Grid::Grid(cells gridCells, cells background, const GridOptions &gridOptions, const std::map<coordinates, float> &stateRewards, const double faultyProbability)
  12. : allGridCells(gridCells), background(background), gridOptions(gridOptions), stateRewards(stateRewards), faultyProbability(faultyProbability)
  13. {
  14. cell max = allGridCells.at(allGridCells.size() - 1);
  15. maxBoundaries = std::make_pair(max.row - 1, max.column - 1);
  16. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(walls), [](cell c) { return c.type == Type::Wall; });
  17. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lava), [](cell c) { return c.type == Type::Lava; });
  18. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(floor), [](cell c) { return c.type == Type::Floor; }); // TODO Add agent cells to floor
  19. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyNorth), [](cell c) { return c.type == Type::SlipperyNorth; });
  20. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyEast), [](cell c) { return c.type == Type::SlipperyEast; });
  21. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperySouth), [](cell c) { return c.type == Type::SlipperySouth; });
  22. std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyWest), [](cell c) { return c.type == Type::SlipperyWest; });
  23. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lockedDoors), [](cell c) { return c.type == Type::LockedDoor; });
  24. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(unlockedDoors), [](cell c) { return c.type == Type::Door; });
  25. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(goals), [](cell c) { return c.type == Type::Goal; });
  26. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(keys), [](cell c) { return c.type == Type::Key; });
  27. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(boxes), [](cell c) { return c.type == Type::Box; });
  28. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(balls), [](cell c) { return c.type == Type::Ball; });
  29. std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(adversaries), [](cell c) { return c.type == Type::Adversary; });
  30. agent = *std::find_if(gridCells.begin(), gridCells.end(), [](cell c) { return c.type == Type::Agent; });
  31. floor.push_back(agent);
  32. agentNameAndPositionMap.insert({ "Agent", agent.getCoordinates() });
  33. for(auto const& adversary : adversaries) {
  34. std::string color = adversary.getColor();
  35. color.at(0) = std::toupper(color.at(0));
  36. try {
  37. if(gridOptions.agentsToBeConsidered.size() != 0 && std::find(gridOptions.agentsToBeConsidered.begin(), gridOptions.agentsToBeConsidered.end(), color) == gridOptions.agentsToBeConsidered.end()) continue;
  38. auto success = agentNameAndPositionMap.insert({ color, adversary.getCoordinates() });
  39. floor.push_back(adversary);
  40. if(!success.second) {
  41. throw std::logic_error("Agent with " + color + " already present\n");
  42. }
  43. } catch(const std::logic_error& e) {
  44. std::cerr << "Expected agents colors to be different. Agent with color : '" << color << "' already present." << std::endl;
  45. throw;
  46. }
  47. }
  48. for(auto const& key : keys) {
  49. std::string color = key.getColor();
  50. try {
  51. auto success = keyNameAndPositionMap.insert({color, key.getCoordinates() });
  52. if (!success.second) {
  53. throw std::logic_error("Multiple keys with same color not supported " + color + "\n");
  54. }
  55. } catch(const std::logic_error& e) {
  56. std::cerr << "Expected key colors to be different. Key with color : '" << color << "' already present." << std::endl;
  57. throw;
  58. }
  59. }
  60. for(auto const& color : allColors) {
  61. cells cellsOfColor;
  62. std::copy_if(background.begin(), background.end(), std::back_inserter(cellsOfColor), [&color](cell c) {
  63. return c.type == Type::Floor && c.color == color;
  64. });
  65. if(cellsOfColor.size() > 0) {
  66. backgroundTiles.emplace(color, cellsOfColor);
  67. }
  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);
  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.second && cell.column == p.first;
  90. }) != walls.end();
  91. }
  92. void Grid::applyOverwrites(std::string& str, std::vector<Configuration>& configuration) {
  93. for (auto& config : configuration) {
  94. if (!config.overwrite_) {
  95. continue;
  96. }
  97. size_t start_pos;
  98. if (config.type_ == ConfigType::Formula) {
  99. start_pos = str.find("formula " + config.identifier_);
  100. } else if (config.type_ == ConfigType::Label) {
  101. start_pos = str.find("label " + config.identifier_);
  102. } else if (config.type_ == ConfigType::Module) {
  103. auto iter = boost::find_nth(str, config.identifier_, config.index_);
  104. start_pos = std::distance(str.begin(), iter.begin());
  105. }
  106. else if (config.type_ == ConfigType::Constant) {
  107. start_pos = str.find(config.identifier_);
  108. if (start_pos == std::string::npos) {
  109. std::cout << "Couldn't find overwrite:" << config.expression_ << std::endl;
  110. }
  111. }
  112. size_t end_pos = str.find(';', start_pos) + 1;
  113. std::string expression = config.expression_;
  114. str.replace(start_pos, end_pos - start_pos , expression);
  115. }
  116. }
  117. void Grid::printToPrism(std::ostream& os, std::vector<Configuration>& configuration ,const prism::ModelType& modelType) {
  118. cells northRestriction;
  119. cells eastRestriction;
  120. cells southRestriction;
  121. cells westRestriction;
  122. cells walkable = floor;
  123. cells conditionallyWalkable;
  124. walkable.insert(walkable.end(), goals.begin(), goals.end());
  125. walkable.insert(walkable.end(), boxes.begin(), boxes.end());
  126. walkable.push_back(agent);
  127. walkable.insert(walkable.end(), adversaries.begin(), adversaries.end());
  128. walkable.insert(walkable.end(), lava.begin(), lava.end());
  129. conditionallyWalkable.insert(conditionallyWalkable.end(), keys.begin(), keys.end());
  130. conditionallyWalkable.insert(conditionallyWalkable.end(), lockedDoors.begin(), lockedDoors.end());
  131. conditionallyWalkable.insert(conditionallyWalkable.end(), unlockedDoors.begin(), unlockedDoors.end());
  132. for(auto const& c : walkable) {
  133. if(isBlocked(c.getNorth())) northRestriction.push_back(c);
  134. if(isBlocked(c.getEast())) eastRestriction.push_back(c);
  135. if(isBlocked(c.getSouth())) southRestriction.push_back(c);
  136. if(isBlocked(c.getWest())) westRestriction.push_back(c);
  137. }
  138. // TODO Add doors here (list of doors keys etc)
  139. // walkable.insert(walkable.end(), lockedDoors.begin(), lockedDoors.end());
  140. // walkable.insert(walkable.end(), unlockedDoors.begin(), unlockedDoors.end());
  141. for(auto const& c : conditionallyWalkable) {
  142. if(isBlocked(c.getNorth())) northRestriction.push_back(c);
  143. if(isBlocked(c.getEast())) eastRestriction.push_back(c);
  144. if(isBlocked(c.getSouth())) southRestriction.push_back(c);
  145. if(isBlocked(c.getWest())) westRestriction.push_back(c);
  146. }
  147. prism::PrismModulesPrinter printer(modelType, agentNameAndPositionMap.size(), configuration, gridOptions.enforceOneWays);
  148. printer.printModel(os, modelType);
  149. if(modelType == prism::ModelType::SMG) {
  150. printer.printGlobalMoveVariable(os, agentNameAndPositionMap.size());
  151. }
  152. for(auto const &backgroundTilesOfColor : backgroundTiles) {
  153. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) {
  154. printer.printBackgroundLabels(os, agentNameAndPosition->first, backgroundTilesOfColor);
  155. }
  156. }
  157. cells noTurnFloor;
  158. if(gridOptions.enforceOneWays) {
  159. for(auto const& c : floor) {
  160. cell east = c.getEast(allGridCells);
  161. cell south = c.getSouth(allGridCells);
  162. cell west = c.getWest(allGridCells);
  163. cell north = c.getNorth(allGridCells);
  164. if( (east.type == Type::Wall && west.type == Type::Wall) or
  165. (north.type == Type::Wall && south.type == Type::Wall) ) {
  166. noTurnFloor.push_back(c);
  167. }
  168. }
  169. }
  170. cells doors;
  171. doors.insert(doors.end(), lockedDoors.begin(), lockedDoors.end());
  172. doors.insert(doors.end(), unlockedDoors.begin(), unlockedDoors.end());
  173. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) {
  174. printer.printFormulas(os, agentNameAndPosition->first, northRestriction, eastRestriction, southRestriction, westRestriction, { slipperyNorth, slipperyEast, slipperySouth, slipperyWest }, lava, walls, noTurnFloor, slipperyNorth, slipperyEast, slipperySouth, slipperyWest, keys, doors);
  175. printer.printGoalLabel(os, agentNameAndPosition->first, goals);
  176. printer.printKeysLabels(os, agentNameAndPosition->first, keys);
  177. }
  178. std::vector<std::string> constants {"const double prop_zero = 0/9;",
  179. "const double prop_intended = 6/9;",
  180. "const double prop_turn_intended = 6/9;",
  181. "const double prop_displacement = 3/9;",
  182. "const double prop_turn_displacement = 3/9;",
  183. "const int width = " + std::to_string(maxBoundaries.first) + ";",
  184. "const int height = " + std::to_string(maxBoundaries.second) + ";"
  185. };
  186. printer.printConstants(os, constants);
  187. std::vector<AgentName> agentNames;
  188. std::transform(agentNameAndPositionMap.begin(),
  189. agentNameAndPositionMap.end(),
  190. std::back_inserter(agentNames),
  191. [](const std::map<AgentNameAndPosition::first_type,AgentNameAndPosition::second_type>::value_type &pair){return pair.first;});
  192. if(modelType == prism::ModelType::SMG) {
  193. printer.printCrashLabel(os, agentNames);
  194. }
  195. size_t agentIndex = 0;
  196. printer.printInitStruct(os, agentNameAndPositionMap, keyNameAndPositionMap, lockedDoors, unlockedDoors, modelType);
  197. for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition, agentIndex++) {
  198. AgentName agentName = agentNameAndPosition->first;
  199. //std::cout << "Agent Name: " << agentName << std::endl;
  200. bool agentWithView = std::find(gridOptions.agentsWithView.begin(), gridOptions.agentsWithView.end(), agentName) != gridOptions.agentsWithView.end();
  201. bool agentWithProbabilisticBehaviour = std::find(gridOptions.agentsWithProbabilisticBehaviour.begin(), gridOptions.agentsWithProbabilisticBehaviour.end(), agentName) != gridOptions.agentsWithProbabilisticBehaviour.end();
  202. std::set<std::string> slipperyActions; // TODO AGENT POSITION INITIALIZATIN
  203. if(agentWithProbabilisticBehaviour) printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView, gridOptions.probabilitiesForActions);
  204. else printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView, {} ,faultyProbability);
  205. for(auto const& c : slipperyNorth) {
  206. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North);
  207. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North);
  208. }
  209. for(auto const& c : slipperyEast) {
  210. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East);
  211. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East);
  212. }
  213. for(auto const& c : slipperySouth) {
  214. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South);
  215. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South);
  216. }
  217. for(auto const& c : slipperyWest) {
  218. printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West);
  219. if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West);
  220. }
  221. printer.printEndmodule(os);
  222. if(modelType == prism::ModelType::SMG) {
  223. if(agentWithProbabilisticBehaviour) printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, gridOptions.probabilitiesForActions, slipperyActions);
  224. else printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, {}, slipperyActions);
  225. }
  226. //if(!stateRewards.empty()) {
  227. printer.printRewards(os, agentName, stateRewards, lava, goals, backgroundTiles);
  228. //}
  229. }
  230. if (!configuration.empty()) {
  231. printer.printConfiguration(os, configuration);
  232. }
  233. // TODO CHANGE HANDLING
  234. std::string agentName = agentNames.at(0);
  235. for (auto const & key : keys) {
  236. os << "\n";
  237. printer.printKeyModule(os, key, maxBoundaries, agentName);
  238. printer.printEndmodule(os);
  239. }
  240. for (auto const& door : lockedDoors) {
  241. os << "\n";
  242. printer.printDoorModule(os, door, maxBoundaries, agentName);
  243. printer.printEndmodule(os);
  244. }
  245. }
  246. std::array<bool, 8> Grid::getWalkableDirOf8Neighborhood(cell c) /* const */ {
  247. return (std::array<bool, 8>)
  248. {
  249. !isBlocked(c.getNorth()),
  250. !isBlocked(c.getNorth(allGridCells).getEast()),
  251. !isBlocked(c.getEast()),
  252. !isBlocked(c.getSouth(allGridCells).getEast()),
  253. !isBlocked(c.getSouth()),
  254. !isBlocked(c.getSouth(allGridCells).getWest()),
  255. !isBlocked(c.getWest()),
  256. !isBlocked(c.getNorth(allGridCells).getWest())
  257. };
  258. }