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.

325 lines
14 KiB

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