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.

337 lines
15 KiB

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