commit
						85d0cbc81f
					
				 15 changed files with 2937 additions and 0 deletions
			
			
		- 
					34.gitignore
- 
					22CMakeLists.txt
- 
					171main.cpp
- 
					8util/CMakeLists.txt
- 
					229util/Grid.cpp
- 
					63util/Grid.h
- 
					102util/MinigridGrammar.h
- 
					32util/OptionParser.cpp
- 
					13util/OptionParser.h
- 
					681util/PrismModulesPrinter.cpp
- 
					91util/PrismModulesPrinter.h
- 
					15util/PrismPrinter.h
- 
					83util/cell.cpp
- 
					62util/cell.h
- 
					1331util/popl.hpp
| @ -0,0 +1,34 @@ | |||||
|  | # Prerequisites | ||||
|  | *.d | ||||
|  | 
 | ||||
|  | # Compiled Object files | ||||
|  | *.slo | ||||
|  | *.lo | ||||
|  | *.o | ||||
|  | *.obj | ||||
|  | 
 | ||||
|  | # Precompiled Headers | ||||
|  | *.gch | ||||
|  | *.pch | ||||
|  | 
 | ||||
|  | # Compiled Dynamic libraries | ||||
|  | *.so | ||||
|  | *.dylib | ||||
|  | *.dll | ||||
|  | 
 | ||||
|  | # Fortran module files | ||||
|  | *.mod | ||||
|  | *.smod | ||||
|  | 
 | ||||
|  | # Compiled Static libraries | ||||
|  | *.lai | ||||
|  | *.la | ||||
|  | *.a | ||||
|  | *.lib | ||||
|  | 
 | ||||
|  | # Executables | ||||
|  | *.exe | ||||
|  | *.out | ||||
|  | *.app | ||||
|  | 
 | ||||
|  | build/* | ||||
| @ -0,0 +1,22 @@ | |||||
|  | include(util/CMakeLists.txt) | ||||
|  | 
 | ||||
|  | set(CMAKE_CXX_STANDARD 20) | ||||
|  | 
 | ||||
|  | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") | ||||
|  | add_definitions(-DLOG_DEBUG) | ||||
|  | 
 | ||||
|  | cmake_minimum_required(VERSION 3.0...3.22) | ||||
|  | 
 | ||||
|  | set(CMAKE_BUILD_TYPE Debug) | ||||
|  | 
 | ||||
|  | project( | ||||
|  |   Minigrid2PRISM | ||||
|  |   VERSION 0.1 | ||||
|  |   LANGUAGES CXX) | ||||
|  | 
 | ||||
|  | add_executable(main | ||||
|  |                ${SRCS} | ||||
|  |                main.cpp | ||||
|  |                ) | ||||
|  | 
 | ||||
|  | target_link_libraries(main pthread) | ||||
| @ -0,0 +1,171 @@ | |||||
|  | #include "util/OptionParser.h"
 | ||||
|  | #include "util/MinigridGrammar.h"
 | ||||
|  | #include "util/Grid.h"
 | ||||
|  | 
 | ||||
|  | #include <iostream>
 | ||||
|  | #include <fstream>
 | ||||
|  | #include <filesystem>
 | ||||
|  | #include <sstream>
 | ||||
|  | 
 | ||||
|  | std::vector<std::string> parseCommaSeparatedString(std::string const& str) { | ||||
|  |   std::vector<std::string> result; | ||||
|  |   std::stringstream stream(str); | ||||
|  |   while(stream.good()) { | ||||
|  |     std::string substr; | ||||
|  |     getline(stream, substr, ','); | ||||
|  |     substr.at(0) = std::toupper(substr.at(0)); | ||||
|  |     result.push_back(substr); | ||||
|  |   } | ||||
|  |   return result; | ||||
|  | } | ||||
|  | 
 | ||||
|  | struct printer { | ||||
|  |     typedef boost::spirit::utf8_string string; | ||||
|  | 
 | ||||
|  |     void element(string const& tag, string const& value, int depth) const { | ||||
|  |         for (int i = 0; i < (depth*4); ++i) std::cout << ' '; | ||||
|  | 
 | ||||
|  |         std::cout << "tag: " << tag; | ||||
|  |         if (value != "") std::cout << ", value: " << value; | ||||
|  |         std::cout << std::endl; | ||||
|  |     } | ||||
|  | }; | ||||
|  | 
 | ||||
|  | void print_info(boost::spirit::info const& what) { | ||||
|  |   using boost::spirit::basic_info_walker; | ||||
|  | 
 | ||||
|  |   printer pr; | ||||
|  |   basic_info_walker<printer> walker(pr, what.tag, 0); | ||||
|  |   boost::apply_visitor(walker, what.value); | ||||
|  | } | ||||
|  | 
 | ||||
|  | int main(int argc, char* argv[]) { | ||||
|  |   popl::OptionParser optionParser("Allowed options"); | ||||
|  | 
 | ||||
|  |   auto helpOption = optionParser.add<popl::Switch>("h", "help", "Print this help message."); | ||||
|  |   auto inputFilename = optionParser.add<popl::Value<std::string>>("i", "input-file", "Filename of the input file."); | ||||
|  |   auto outputFilename = optionParser.add<popl::Value<std::string>>("o", "output-file", "Filename for the output file."); | ||||
|  | 
 | ||||
|  |   auto agentsToBeConsidered = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("a", "agents", "Which parsed agents should be considered in the output. WIP."); | ||||
|  |   auto viewForAgents = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("v", "view", "Agents for which the 'view'('direction') variable should be included. WIP."); | ||||
|  | 
 | ||||
|  |   auto probabilisticBehaviourAgents = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("p", "prob-beh", "Agents for which we want to include probabilistic actions"); | ||||
|  |   auto probabilities = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("q", "probs", "The probabilities for which probabilistic actions should be added. WIP"); | ||||
|  | 
 | ||||
|  |   auto enforceOneWays = optionParser.add<popl::Switch>("f", "force-oneways", "Enforce encoding of oneways. This entails that slippery tiles do not allow turning and have prob 1 to shift the agent by one and makes turning impossible if in a one tile wide section of the grid."); | ||||
|  | 
 | ||||
|  |   try { | ||||
|  |     optionParser.parse(argc, argv); | ||||
|  | 
 | ||||
|  |     if(helpOption->count() > 0) { | ||||
|  |       std::cout << optionParser << std::endl; | ||||
|  |       return EXIT_SUCCESS; | ||||
|  |     } | ||||
|  |   } catch (const popl::invalid_option &e) { | ||||
|  |     return io::printPoplException(e); | ||||
|  |   } catch (const std::exception &e) { | ||||
|  | 		std::cerr << "Exception: " << e.what() << "\n"; | ||||
|  | 		return EXIT_FAILURE; | ||||
|  | 	} | ||||
|  | 
 | ||||
|  |   GridOptions gridOptions = { {}, {} }; | ||||
|  |   if(agentsToBeConsidered->is_set()) { | ||||
|  |     gridOptions.agentsToBeConsidered = parseCommaSeparatedString(agentsToBeConsidered->value(0)); | ||||
|  |   } | ||||
|  |   if(viewForAgents->is_set()) { | ||||
|  |     gridOptions.agentsWithView = parseCommaSeparatedString(viewForAgents->value(0)); | ||||
|  |   } | ||||
|  |   if(enforceOneWays->is_set()) { | ||||
|  |     gridOptions.enforceOneWays = true; | ||||
|  |   } | ||||
|  |   if(probabilisticBehaviourAgents->is_set()) { | ||||
|  |     gridOptions.agentsWithProbabilisticBehaviour = parseCommaSeparatedString(probabilisticBehaviourAgents->value(0)); | ||||
|  |     for(auto const& a : gridOptions.agentsWithProbabilisticBehaviour) { | ||||
|  |       std::cout << a << std::endl; | ||||
|  |     } | ||||
|  |     if(probabilities->is_set()) { | ||||
|  |       std::vector<std::string> parsedStrings = parseCommaSeparatedString(probabilities->value(0)); | ||||
|  | 
 | ||||
|  |       std::transform(parsedStrings.begin(), parsedStrings.end(), std::back_inserter(gridOptions.probabilitiesForActions), [](const std::string& string) { | ||||
|  |         return std::stof(string); | ||||
|  |       }); | ||||
|  |       for(auto const& a : gridOptions.probabilitiesForActions) { | ||||
|  |         std::cout << a << std::endl; | ||||
|  |       } | ||||
|  |     } else { | ||||
|  |       throw std::logic_error{ "When adding agents with probabilistic behaviour, you also need to specify a list of probabilities via --probs." }; | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |   std::fstream file {outputFilename->value(0), file.trunc | file.out}; | ||||
|  |   std::fstream infile {inputFilename->value(0), infile.in}; | ||||
|  |   std::string line, content, background, rewards; | ||||
|  |   std::cout << "\n"; | ||||
|  |   bool parsingBackground = false; | ||||
|  |   bool parsingStateRewards = false; | ||||
|  |   while (std::getline(infile, line) && !line.empty()) { | ||||
|  |     if(line.at(0) == '-' && line.at(line.size() - 1) == '-' && parsingBackground) { | ||||
|  |       parsingStateRewards = true; | ||||
|  |       parsingBackground = false; | ||||
|  |       continue; | ||||
|  |     } else if(line.at(0) == '-' && line.at(line.size() - 1) == '-') { | ||||
|  |       parsingBackground = true; | ||||
|  |       continue; | ||||
|  |     } | ||||
|  |     if(!parsingBackground && !parsingStateRewards) { | ||||
|  |       std::cout << "Reading   :\t" << line << "\n"; | ||||
|  |       content += line + "\n"; | ||||
|  |     } else if (parsingBackground) { | ||||
|  |       std::cout << "Background:\t" << line << "\n"; | ||||
|  |       background += line + "\n"; | ||||
|  |     } else if(parsingStateRewards) { | ||||
|  |       rewards += line + "\n"; | ||||
|  |     } | ||||
|  |   } | ||||
|  |   std::cout << "\n"; | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |   pos_iterator_t contentFirst(content.begin()); | ||||
|  |   pos_iterator_t contentIter = contentFirst; | ||||
|  |   pos_iterator_t contentLast(content.end()); | ||||
|  |   MinigridParser<pos_iterator_t> contentParser(contentFirst); | ||||
|  |   pos_iterator_t backgroundFirst(background.begin()); | ||||
|  |   pos_iterator_t backgroundIter = backgroundFirst; | ||||
|  |   pos_iterator_t backgroundLast(background.end()); | ||||
|  |   MinigridParser<pos_iterator_t> backgroundParser(backgroundFirst); | ||||
|  | 
 | ||||
|  |   cells contentCells; | ||||
|  |   cells backgroundCells; | ||||
|  |   std::map<coordinates, float> stateRewards; | ||||
|  |   try { | ||||
|  |     bool ok = phrase_parse(contentIter, contentLast, contentParser, qi::space, contentCells); | ||||
|  |     // TODO if(background is not empty) {
 | ||||
|  |     ok     &= phrase_parse(backgroundIter, backgroundLast, backgroundParser, qi::space, backgroundCells); | ||||
|  |     // TODO }
 | ||||
|  | 
 | ||||
|  |     boost::escaped_list_separator<char> seps('\\', ';', '\n'); | ||||
|  |     Tokenizer csvParser(rewards, seps); | ||||
|  |     for(auto iter = csvParser.begin(); iter != csvParser.end(); ++iter) { | ||||
|  |       int x = std::stoi(*iter); | ||||
|  |       int y = std::stoi(*(++iter)); | ||||
|  |       float reward = std::stof(*(++iter)); | ||||
|  |       stateRewards[std::make_pair(x,y)] = reward; | ||||
|  |     } | ||||
|  |     if(ok) { | ||||
|  |       Grid grid(contentCells, backgroundCells, gridOptions, stateRewards); | ||||
|  |       //grid.printToPrism(std::cout, prism::ModelType::MDP);
 | ||||
|  |       grid.printToPrism(file, prism::ModelType::MDP); | ||||
|  |     } | ||||
|  |   } catch(qi::expectation_failure<pos_iterator_t> const& e) { | ||||
|  |     std::cout << "expected: "; print_info(e.what_); | ||||
|  |     std::cout << "got: \"" << std::string(e.first, e.last) << '"' << std::endl; | ||||
|  |     std::cout << "Expectation failure: " << e.what() << " at '" << std::string(e.first,e.last) << "'\n"; | ||||
|  |   } catch(const std::exception& e) { | ||||
|  |     std::cerr << "Exception '" << typeid(e).name() << "' caught:" << std::endl; | ||||
|  |     std::cerr << "\t" << e.what() << std::endl; | ||||
|  |     std::exit(EXIT_FAILURE); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   return 0; | ||||
|  | } | ||||
| @ -0,0 +1,8 @@ | |||||
|  | list(APPEND SRCS | ||||
|  |   ${CMAKE_CURRENT_LIST_DIR}/cell.cpp | ||||
|  |   ${CMAKE_CURRENT_LIST_DIR}/MinigridGrammar.h | ||||
|  |   ${CMAKE_CURRENT_LIST_DIR}/Grid.cpp | ||||
|  |   ${CMAKE_CURRENT_LIST_DIR}/PrismModulesPrinter.cpp | ||||
|  |   ${CMAKE_CURRENT_LIST_DIR}/popl.hpp | ||||
|  |   ${CMAKE_CURRENT_LIST_DIR}/OptionParser.cpp | ||||
|  | ) | ||||
| @ -0,0 +1,229 @@ | |||||
|  | #include "Grid.h"
 | ||||
|  | 
 | ||||
|  | #include <algorithm>
 | ||||
|  | 
 | ||||
|  | Grid::Grid(cells gridCells, cells background, const GridOptions &gridOptions, const std::map<coordinates, float> &stateRewards) | ||||
|  |   : allGridCells(gridCells), background(background), gridOptions(gridOptions), stateRewards(stateRewards) | ||||
|  | { | ||||
|  |   cell max = allGridCells.at(allGridCells.size() - 1); | ||||
|  |   maxBoundaries = std::make_pair(max.row - 1, max.column - 1); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(walls), [](cell c) { | ||||
|  |       return c.type == Type::Wall; | ||||
|  |   }); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lava), [](cell c) { | ||||
|  |       return c.type == Type::Lava; | ||||
|  |   }); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(floor), [](cell c) { | ||||
|  |       return c.type == Type::Floor; | ||||
|  |   }); | ||||
|  |   std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyNorth), [](cell c) { | ||||
|  |       return c.type == Type::SlipperyNorth; | ||||
|  |   }); | ||||
|  |   std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyEast), [](cell c) { | ||||
|  |       return c.type == Type::SlipperyEast; | ||||
|  |   }); | ||||
|  |   std::copy_if(background.begin(), background.end(), std::back_inserter(slipperySouth), [](cell c) { | ||||
|  |       return c.type == Type::SlipperySouth; | ||||
|  |   }); | ||||
|  |   std::copy_if(background.begin(), background.end(), std::back_inserter(slipperyWest), [](cell c) { | ||||
|  |       return c.type == Type::SlipperyWest; | ||||
|  |   }); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lockedDoors), [](cell c) { | ||||
|  |       return c.type == Type::LockedDoor; | ||||
|  |   }); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(goals), [](cell c) { | ||||
|  |       return c.type == Type::Goal; | ||||
|  |   }); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(keys), [](cell c) { | ||||
|  |       return c.type == Type::Key; | ||||
|  |   }); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(boxes), [](cell c) { | ||||
|  |       return c.type == Type::Box; | ||||
|  |   }); | ||||
|  |   agent = *std::find_if(gridCells.begin(), gridCells.end(), [](cell c) { | ||||
|  |       return c.type == Type::Agent; | ||||
|  |   }); | ||||
|  |   std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(adversaries), [](cell c) { | ||||
|  |       return c.type == Type::Adversary; | ||||
|  |   }); | ||||
|  |   agentNameAndPositionMap.insert({ "Agent", agent.getCoordinates() }); | ||||
|  |   for(auto const& adversary : adversaries) { | ||||
|  |     std::string color = adversary.getColor(); | ||||
|  |     color.at(0) = std::toupper(color.at(0)); | ||||
|  |     try { | ||||
|  |       if(gridOptions.agentsToBeConsidered.size() != 0 && std::find(gridOptions.agentsToBeConsidered.begin(), gridOptions.agentsToBeConsidered.end(), color) == gridOptions.agentsToBeConsidered.end()) continue; | ||||
|  |       auto success = agentNameAndPositionMap.insert({ color, adversary.getCoordinates() }); | ||||
|  |       if(!success.second) { | ||||
|  |         throw std::logic_error("Agent with " + color + " already present\n"); | ||||
|  |       } | ||||
|  |     } catch(const std::logic_error& e) { | ||||
|  |       std::cerr << "Expected agents colors to be different. Agent with color : '" << color << "' already present." << std::endl; | ||||
|  |       throw; | ||||
|  |     } | ||||
|  |   } | ||||
|  |   for(auto const& color : allColors) { | ||||
|  |     cells cellsOfColor; | ||||
|  |     std::copy_if(background.begin(), background.end(), std::back_inserter(cellsOfColor), [&color](cell c) { | ||||
|  |         return c.type == Type::Floor && c.color == color; | ||||
|  |     }); | ||||
|  |     if(cellsOfColor.size() > 0) { | ||||
|  |       backgroundTiles.emplace(color, cellsOfColor); | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | std::ostream& operator<<(std::ostream& os, const Grid& grid) { | ||||
|  |   int lastRow = 1; | ||||
|  |   for(auto const& cell : grid.allGridCells) { | ||||
|  |     if(lastRow != cell.row) | ||||
|  |       os << std::endl; | ||||
|  |     os << static_cast<char>(cell.type) << static_cast<char>(cell.color); | ||||
|  |     lastRow = cell.row; | ||||
|  |   } | ||||
|  |   return os; | ||||
|  | } | ||||
|  | 
 | ||||
|  | cells Grid::getGridCells() { | ||||
|  |   return allGridCells; | ||||
|  | } | ||||
|  | 
 | ||||
|  | bool Grid::isBlocked(coordinates p) { | ||||
|  |   return isWall(p) || isLockedDoor(p) || isKey(p); | ||||
|  | } | ||||
|  | 
 | ||||
|  | bool Grid::isWall(coordinates p) { | ||||
|  |   return std::find_if(walls.begin(), walls.end(), | ||||
|  |       [p](cell cell) { | ||||
|  |         return cell.row == p.first && cell.column == p.second; | ||||
|  |       }) != walls.end(); | ||||
|  | } | ||||
|  | 
 | ||||
|  | bool Grid::isLockedDoor(coordinates p) { | ||||
|  |   return std::find_if(lockedDoors.begin(), lockedDoors.end(), | ||||
|  |       [p](cell cell) { | ||||
|  |         return cell.row == p.first && cell.column == p.second; | ||||
|  |       }) != lockedDoors.end(); | ||||
|  | } | ||||
|  | 
 | ||||
|  | bool Grid::isKey(coordinates p) { | ||||
|  |   return std::find_if(keys.begin(), keys.end(), | ||||
|  |       [p](cell cell) { | ||||
|  |         return cell.row == p.first && cell.column == p.second; | ||||
|  |       }) != keys.end(); | ||||
|  | } | ||||
|  | 
 | ||||
|  | bool Grid::isBox(coordinates p) { | ||||
|  |   return std::find_if(boxes.begin(), boxes.end(), | ||||
|  |       [p](cell cell) { | ||||
|  |         return cell.row == p.first && cell.column == p.second; | ||||
|  |       }) != boxes.end(); | ||||
|  | } | ||||
|  | 
 | ||||
|  | void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) { | ||||
|  |   cells northRestriction; | ||||
|  |   cells eastRestriction; | ||||
|  |   cells southRestriction; | ||||
|  |   cells westRestriction; | ||||
|  |   cells walkable = floor; | ||||
|  |   walkable.insert(walkable.end(), goals.begin(), goals.end()); | ||||
|  |   walkable.insert(walkable.end(), boxes.begin(), boxes.end()); | ||||
|  |   walkable.push_back(agent); | ||||
|  |   walkable.insert(walkable.end(), adversaries.begin(), adversaries.end()); | ||||
|  |   walkable.insert(walkable.end(), lava.begin(), lava.end()); | ||||
|  |   for(auto const& c : walkable) { | ||||
|  |     if(isBlocked(c.getNorth())) northRestriction.push_back(c); | ||||
|  |     if(isBlocked(c.getEast()))   eastRestriction.push_back(c); | ||||
|  |     if(isBlocked(c.getSouth())) southRestriction.push_back(c); | ||||
|  |     if(isBlocked(c.getWest()))   westRestriction.push_back(c); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   prism::PrismModulesPrinter printer(modelType, agentNameAndPositionMap.size(), gridOptions.enforceOneWays); | ||||
|  |   printer.printModel(os, modelType); | ||||
|  |   if(modelType == prism::ModelType::SMG) { | ||||
|  |     printer.printGlobalMoveVariable(os, agentNameAndPositionMap.size()); | ||||
|  |   } | ||||
|  |   for(auto const &backgroundTilesOfColor : backgroundTiles) { | ||||
|  |     for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) { | ||||
|  |       printer.printBackgroundLabels(os, agentNameAndPosition->first, backgroundTilesOfColor); | ||||
|  |     } | ||||
|  |   } | ||||
|  |   cells noTurnFloor; | ||||
|  |   if(gridOptions.enforceOneWays) { | ||||
|  |     for(auto const& c : floor) { | ||||
|  |       cell east =  c.getEast(allGridCells); | ||||
|  |       cell south = c.getSouth(allGridCells); | ||||
|  |       cell west =  c.getWest(allGridCells); | ||||
|  |       cell north = c.getNorth(allGridCells); | ||||
|  |       if( (east.type == Type::Wall && west.type == Type::Wall) or | ||||
|  |           (north.type == Type::Wall && south.type == Type::Wall) ) { | ||||
|  |         noTurnFloor.push_back(c); | ||||
|  |       } | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition) { | ||||
|  |     printer.printFormulas(os, agentNameAndPosition->first, northRestriction, eastRestriction, southRestriction, westRestriction, { slipperyNorth, slipperyEast, slipperySouth, slipperyWest }, lava, walls, noTurnFloor, slipperyNorth, slipperyEast, slipperySouth, slipperyWest); | ||||
|  |     printer.printGoalLabel(os, agentNameAndPosition->first, goals); | ||||
|  |     printer.printKeysLabels(os, agentNameAndPosition->first, keys); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::vector<AgentName> agentNames; | ||||
|  |   std::transform(agentNameAndPositionMap.begin(), | ||||
|  |                  agentNameAndPositionMap.end(), | ||||
|  |                  std::back_inserter(agentNames), | ||||
|  |                  [](const std::map<AgentNameAndPosition::first_type,AgentNameAndPosition::second_type>::value_type &pair){return pair.first;}); | ||||
|  |   if(modelType == prism::ModelType::SMG) { | ||||
|  |     printer.printCrashLabel(os, agentNames); | ||||
|  |   } | ||||
|  |   size_t agentIndex  = 0; | ||||
|  |   for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition, agentIndex++) { | ||||
|  |     AgentName agentName = agentNameAndPosition->first; | ||||
|  |     bool agentWithView = std::find(gridOptions.agentsWithView.begin(), gridOptions.agentsWithView.end(), agentName) != gridOptions.agentsWithView.end(); | ||||
|  |     bool agentWithProbabilisticBehaviour = std::find(gridOptions.agentsWithProbabilisticBehaviour.begin(), gridOptions.agentsWithProbabilisticBehaviour.end(), agentName) != gridOptions.agentsWithProbabilisticBehaviour.end(); | ||||
|  |     std::set<std::string> slipperyActions; | ||||
|  |     printer.printInitStruct(os, agentName); | ||||
|  |     if(agentWithProbabilisticBehaviour) printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView, gridOptions.probabilitiesForActions); | ||||
|  |     else                                printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView); | ||||
|  |     for(auto const& c : slipperyNorth) { | ||||
|  |       printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North); | ||||
|  |       if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North); | ||||
|  | 
 | ||||
|  |     } | ||||
|  |     for(auto const& c : slipperyEast) { | ||||
|  |       printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East); | ||||
|  |       if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East); | ||||
|  |     } | ||||
|  |     for(auto const& c : slipperySouth) { | ||||
|  |       printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South); | ||||
|  |       if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South); | ||||
|  |     } | ||||
|  |     for(auto const& c : slipperyWest) { | ||||
|  |       printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West); | ||||
|  |       if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     printer.printEndmodule(os); | ||||
|  |     if(modelType == prism::ModelType::SMG) { | ||||
|  |       if(agentWithProbabilisticBehaviour) printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, gridOptions.probabilitiesForActions, slipperyActions); | ||||
|  |       else                                printer.printPlayerStruct(os, agentNameAndPosition->first, agentWithView, {}, slipperyActions); | ||||
|  |     } | ||||
|  |     //if(!stateRewards.empty()) {
 | ||||
|  |     printer.printRewards(os, agentName, stateRewards, lava, goals, backgroundTiles); | ||||
|  |     //}
 | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | std::array<bool, 8> Grid::getWalkableDirOf8Neighborhood(cell c) /* const */ { | ||||
|  |   return (std::array<bool, 8>) | ||||
|  |          { | ||||
|  |            !isBlocked(c.getNorth()), | ||||
|  |            !isBlocked(c.getNorth(allGridCells).getEast()), | ||||
|  |            !isBlocked(c.getEast()), | ||||
|  |            !isBlocked(c.getSouth(allGridCells).getEast()), | ||||
|  |            !isBlocked(c.getSouth()), | ||||
|  |            !isBlocked(c.getSouth(allGridCells).getWest()), | ||||
|  |            !isBlocked(c.getWest()), | ||||
|  |            !isBlocked(c.getNorth(allGridCells).getWest()) | ||||
|  |          }; | ||||
|  | } | ||||
| @ -0,0 +1,63 @@ | |||||
|  | #pragma once | ||||
|  | 
 | ||||
|  | #include <iostream> | ||||
|  | #include <fstream> | ||||
|  | #include <map> | ||||
|  | #include <utility> | ||||
|  | 
 | ||||
|  | #include "MinigridGrammar.h" | ||||
|  | #include "PrismModulesPrinter.h" | ||||
|  | 
 | ||||
|  | struct GridOptions { | ||||
|  |   std::vector<AgentName> agentsToBeConsidered; | ||||
|  |   std::vector<AgentName> agentsWithView; | ||||
|  |   std::vector<AgentName> agentsWithProbabilisticBehaviour; | ||||
|  |   std::vector<float>     probabilitiesForActions; | ||||
|  |   bool                   enforceOneWays; | ||||
|  | }; | ||||
|  | 
 | ||||
|  | class Grid { | ||||
|  |   public: | ||||
|  |     Grid(cells gridCells, cells background, const GridOptions &gridOptions, const std::map<coordinates, float> &stateRewards = {}); | ||||
|  | 
 | ||||
|  |     cells getGridCells(); | ||||
|  | 
 | ||||
|  |     bool isBlocked(coordinates p); | ||||
|  |     bool isWall(coordinates p); | ||||
|  |     bool isLockedDoor(coordinates p); | ||||
|  |     bool isKey(coordinates p); | ||||
|  |     bool isBox(coordinates p); | ||||
|  |     void printToPrism(std::ostream &os, const prism::ModelType& modelType); | ||||
|  | 
 | ||||
|  |     std::array<bool, 8> getWalkableDirOf8Neighborhood(cell c); | ||||
|  | 
 | ||||
|  |     friend std::ostream& operator<<(std::ostream& os, const Grid &grid); | ||||
|  | 
 | ||||
|  |   private: | ||||
|  |     GridOptions gridOptions; | ||||
|  | 
 | ||||
|  |     cells allGridCells; | ||||
|  |     cells background; | ||||
|  |     coordinates maxBoundaries; | ||||
|  | 
 | ||||
|  |     cell agent; | ||||
|  |     cells adversaries; | ||||
|  |     AgentNameAndPositionMap agentNameAndPositionMap; | ||||
|  | 
 | ||||
|  |     cells walls; | ||||
|  |     cells floor; | ||||
|  |     cells slipperyNorth; | ||||
|  |     cells slipperyEast; | ||||
|  |     cells slipperySouth; | ||||
|  |     cells slipperyWest; | ||||
|  |     cells lockedDoors; | ||||
|  |     cells boxes; | ||||
|  |     cells lava; | ||||
|  | 
 | ||||
|  |     cells goals; | ||||
|  |     cells keys; | ||||
|  | 
 | ||||
|  |     std::map<Color, cells> backgroundTiles; | ||||
|  | 
 | ||||
|  |     std::map<coordinates, float> stateRewards; | ||||
|  | }; | ||||
| @ -0,0 +1,102 @@ | |||||
|  | #pragma once | ||||
|  | 
 | ||||
|  | #include "cell.h" | ||||
|  | 
 | ||||
|  | #include <vector> | ||||
|  | 
 | ||||
|  | #include <boost/tokenizer.hpp> | ||||
|  | #include <boost/fusion/adapted/struct.hpp> | ||||
|  | #include <boost/spirit/include/qi.hpp> | ||||
|  | #include <boost/spirit/include/phoenix.hpp> | ||||
|  | #include <boost/spirit/include/phoenix_operator.hpp> | ||||
|  | #include <boost/variant/recursive_wrapper.hpp> | ||||
|  | #include <boost/spirit/include/support_line_pos_iterator.hpp> | ||||
|  | 
 | ||||
|  | namespace qi      = boost::spirit::qi; | ||||
|  | namespace phoenix = boost::phoenix; | ||||
|  | 
 | ||||
|  | typedef boost::spirit::line_pos_iterator<std::string::const_iterator> pos_iterator_t; | ||||
|  | 
 | ||||
|  | typedef std::vector<cell> row; | ||||
|  | typedef std::vector<cell> cells; | ||||
|  | 
 | ||||
|  | BOOST_FUSION_ADAPT_STRUCT( | ||||
|  |     cell, | ||||
|  |     (Type, type) | ||||
|  |     (Color, color) | ||||
|  | ) | ||||
|  | 
 | ||||
|  | template<typename It> | ||||
|  | struct annotation_f { | ||||
|  |     typedef void result_type; | ||||
|  | 
 | ||||
|  |     annotation_f(It first) : first(first) {} | ||||
|  |     It const first; | ||||
|  | 
 | ||||
|  |     template<typename Val, typename First, typename Last> | ||||
|  |     void operator()(Val& v, First f, Last l) const { | ||||
|  |         do_annotate(v, f, l, first); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |   private: | ||||
|  |     void static do_annotate(cell& c, It f, It l, It first) { | ||||
|  |         c.row    = get_line(f) - 1; | ||||
|  |         c.column = get_column(first, f) / 2; | ||||
|  |     } | ||||
|  |     static void do_annotate(...) { std::cerr << "(not having LocationInfo)\n"; } | ||||
|  | }; | ||||
|  | 
 | ||||
|  | template <typename It> | ||||
|  |     struct MinigridParser : qi::grammar<It, row()> | ||||
|  | { | ||||
|  |   MinigridParser(It first) : MinigridParser::base_type(row_), annotate(first) | ||||
|  |   { | ||||
|  |     using namespace qi; | ||||
|  |     type_.add | ||||
|  |       ("W", Type::Wall) | ||||
|  |       (" ", Type::Floor) | ||||
|  |       ("D", Type::Door) | ||||
|  |       ("L", Type::LockedDoor) | ||||
|  |       ("K", Type::Key) | ||||
|  |       ("A", Type::Ball) | ||||
|  |       ("B", Type::Box) | ||||
|  |       ("G", Type::Goal) | ||||
|  |       ("V", Type::Lava) | ||||
|  |       ("n", Type::SlipperyNorth) | ||||
|  |       ("e", Type::SlipperyEast) | ||||
|  |       ("s", Type::SlipperySouth) | ||||
|  |       ("w", Type::SlipperyWest) | ||||
|  |       ("X", Type::Agent) | ||||
|  |       ("Z", Type::Adversary); | ||||
|  |     color_.add | ||||
|  |       ("R", Color::Red) | ||||
|  |       ("G", Color::Green) | ||||
|  |       ("B", Color::Blue) | ||||
|  |       ("P", Color::Purple) | ||||
|  |       ("Y", Color::Yellow) | ||||
|  |       (" ", Color::None); | ||||
|  | 
 | ||||
|  |     cell_ = type_ > color_; | ||||
|  | 
 | ||||
|  |     row_ = (cell_ % -qi::char_("\n")); | ||||
|  | 
 | ||||
|  |     auto set_location_info = annotate(_val, _1, _3); | ||||
|  |     on_success(cell_, set_location_info); | ||||
|  | 
 | ||||
|  |     BOOST_SPIRIT_DEBUG_NODE(type_); | ||||
|  |     BOOST_SPIRIT_DEBUG_NODE(color_); | ||||
|  |     BOOST_SPIRIT_DEBUG_NODE(cell_); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   private: | ||||
|  |     phoenix::function<annotation_f<It>> annotate; | ||||
|  | 
 | ||||
|  |     qi::symbols<char, Type>  type_; | ||||
|  |     qi::symbols<char, Color> color_; | ||||
|  | 
 | ||||
|  |     qi::rule<It, cell()> cell_; | ||||
|  |     qi::rule<It, row()>  row_; | ||||
|  | }; | ||||
|  | 
 | ||||
|  | typedef boost::tokenizer< boost::escaped_list_separator<char> , std::string::const_iterator, std::string> Tokenizer; | ||||
|  | //std::ostream& operator<<(std::ostream& os, const row& r); | ||||
| @ -0,0 +1,32 @@ | |||||
|  | #include <iostream>
 | ||||
|  | 
 | ||||
|  | #include "popl.hpp"
 | ||||
|  | #include "OptionParser.h"
 | ||||
|  | 
 | ||||
|  | namespace io { | ||||
|  |   int printPoplException(const popl::invalid_option &e) { | ||||
|  |     std::cerr << "Invalid Option Exception: " << e.what() << "\n"; | ||||
|  | 		std::cerr << "error:  "; | ||||
|  | 		if (e.error() == popl::invalid_option::Error::missing_argument) { | ||||
|  | 			std::cerr << "missing_argument\n"; | ||||
|  |     } else if (e.error() == popl::invalid_option::Error::invalid_argument) { | ||||
|  | 			std::cerr << "invalid_argument\n"; | ||||
|  |     } else if (e.error() == popl::invalid_option::Error::too_many_arguments) { | ||||
|  | 			std::cerr << "too_many_arguments\n"; | ||||
|  |     } else if (e.error() == popl::invalid_option::Error::missing_option) { | ||||
|  | 			std::cerr << "missing_option\n"; | ||||
|  |     } | ||||
|  | 
 | ||||
|  | 		if (e.error() == popl::invalid_option::Error::missing_option) { | ||||
|  |       std::string option_name(e.option()->name(popl::OptionName::short_name, true)); | ||||
|  | 			if (option_name.empty()) | ||||
|  | 				option_name = e.option()->name(popl::OptionName::long_name, true); | ||||
|  | 			std::cerr << "option: " << option_name << "\n"; | ||||
|  | 		} | ||||
|  | 		else { | ||||
|  | 			std::cerr << "option: " << e.option()->name(e.what_name()) << "\n"; | ||||
|  | 			std::cerr << "value:  " << e.value() << "\n"; | ||||
|  | 		} | ||||
|  | 		return EXIT_FAILURE; | ||||
|  |   } | ||||
|  | } | ||||
| @ -0,0 +1,13 @@ | |||||
|  | #pragma once | ||||
|  | 
 | ||||
|  | #include <iostream> | ||||
|  | 
 | ||||
|  | #include "popl.hpp" | ||||
|  | 
 | ||||
|  | #define INPUT_ERROR 1 | ||||
|  | #define INPUT_OK 0 | ||||
|  | 
 | ||||
|  | namespace io { | ||||
|  |   int printPoplException(const popl::invalid_option &e); | ||||
|  | 
 | ||||
|  | } | ||||
| @ -0,0 +1,681 @@ | |||||
|  | #include "PrismModulesPrinter.h"
 | ||||
|  | 
 | ||||
|  | #include <map>
 | ||||
|  | #include <string>
 | ||||
|  | 
 | ||||
|  | namespace prism { | ||||
|  | 
 | ||||
|  |   PrismModulesPrinter::PrismModulesPrinter(const ModelType &modelType, const size_t &numberOfPlayer, const bool enforceOneWays) | ||||
|  |     : modelType(modelType), numberOfPlayer(numberOfPlayer), enforceOneWays(enforceOneWays) { | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printModel(std::ostream &os, const ModelType &modelType) { | ||||
|  |     switch(modelType) { | ||||
|  |       case(ModelType::MDP): | ||||
|  |         os << "mdp"; | ||||
|  |         break; | ||||
|  |       case(ModelType::SMG): | ||||
|  |         os << "smg"; | ||||
|  |         break; | ||||
|  |     } | ||||
|  |     os << "\n\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printBackgroundLabels(std::ostream &os, const AgentName &agentName, const std::pair<Color, cells> &backgroundTiles) { | ||||
|  |     if(backgroundTiles.second.size() == 0) return os; | ||||
|  | 
 | ||||
|  |     bool first = true; | ||||
|  |     std::string color = getColor(backgroundTiles.first); | ||||
|  |     color.at(0) = std::toupper(color.at(0)); | ||||
|  |     os << "formula " << agentName << "On" << color << " = "; | ||||
|  |     for(auto const& cell : backgroundTiles.second) { | ||||
|  |       if(first) first = false; else os << " | "; | ||||
|  |       os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |     } | ||||
|  |     os << ";\n"; | ||||
|  |     os << "label \"" << agentName << "On" << color << "\" = " << agentName << "On" << color << ";\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printRestrictionFormula(std::ostream& os, const AgentName &agentName, const std::string &direction,  const cells &cells) { | ||||
|  |     bool first = true; | ||||
|  |     os << "formula " << agentName << "CannotMove" << direction << " = " ; | ||||
|  |     for(auto const& cell : cells) { | ||||
|  |       if(first) first = false; | ||||
|  |       else os << " | "; | ||||
|  |       os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |     } | ||||
|  |     os << ";\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printIsOnSlipperyFormula(std::ostream& os, const AgentName &agentName, const std::vector<std::reference_wrapper<cells>> &slipperyCollection, const cells &slipperyNorth, const cells &slipperyEast, const cells &slipperySouth, const cells &slipperyWest) { | ||||
|  |     if(std::find_if(slipperyCollection.cbegin(), slipperyCollection.cend(), [=](const std::reference_wrapper<cells>& c) { return !c.get().empty(); }) == slipperyCollection.cend()) { | ||||
|  |       os << "formula " << agentName << "IsOnSlippery = false;\n"; | ||||
|  |       return os; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     bool first = true; | ||||
|  |     os << "formula " << agentName << "IsOnSlippery = "; | ||||
|  | 
 | ||||
|  |     for (const auto& slippery: slipperyCollection) { | ||||
|  |       for(const auto& cell : slippery.get()) { | ||||
|  |         if(first) first = false; else os << " | "; | ||||
|  |         os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |       } | ||||
|  |     } | ||||
|  |     os << ";\n"; | ||||
|  |     if(enforceOneWays) { | ||||
|  |       first = true; | ||||
|  |       os << "formula " << agentName << "IsOnSlipperyNorth = "; | ||||
|  | 
 | ||||
|  |       for (const auto& cell: slipperyNorth) { | ||||
|  |         if(first) first = false; else os << " | "; | ||||
|  |         os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |       } | ||||
|  |       os << ";\n"; | ||||
|  |       first = true; | ||||
|  |       os << "formula " << agentName << "IsOnSlipperyEast = "; | ||||
|  | 
 | ||||
|  |       for (const auto& cell: slipperyEast) { | ||||
|  |         if(first) first = false; else os << " | "; | ||||
|  |         os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |       } | ||||
|  |       os << ";\n"; | ||||
|  |       first = true; | ||||
|  |       os << "formula " << agentName << "IsOnSlipperySouth = "; | ||||
|  | 
 | ||||
|  |       for (const auto& cell: slipperySouth) { | ||||
|  |         if(first) first = false; else os << " | "; | ||||
|  |         os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |       } | ||||
|  |       os << ";\n"; | ||||
|  |       first = true; | ||||
|  |       os << "formula " << agentName << "IsOnSlipperyWest = "; | ||||
|  |       for (const auto& cell: slipperyWest) { | ||||
|  |         if(first) first = false; else os << " | "; | ||||
|  |         os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |       } | ||||
|  |       os << ";\n"; | ||||
|  |     } | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printIsInLavaFormula(std::ostream& os, const AgentName &agentName, const cells &lava) { | ||||
|  |     if(lava.size() == 0) { | ||||
|  |       os << "formula " << agentName << "IsInLava = false;\n"; | ||||
|  |       return os; | ||||
|  |     } | ||||
|  |     bool first = true; | ||||
|  |     os << "formula " << agentName << "IsInLava = "; | ||||
|  |     for(auto const& cell : lava) { | ||||
|  |       if(first) first = false; else os << " | "; | ||||
|  |       os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |     } | ||||
|  |     os << ";\n"; | ||||
|  |     os << "formula " << agentName << "IsInLavaAndNotDone = " << agentName << "IsInLava & !" << agentName << "Done;\n"; | ||||
|  |     os << "label \"" << agentName << "IsInLavaAndNotDone\" = " << agentName << "IsInLava & !" << agentName << "Done;\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printTurningNotAllowedFormulas(std::ostream& os, const AgentName &agentName, const cells &noTurnFloor) { | ||||
|  |     if( (!enforceOneWays or noTurnFloor.size() == 0) or (noTurnFloor.size() == 0) ) { | ||||
|  |       os << "formula " << agentName << "CannotTurn = false;\n"; | ||||
|  |       return os; | ||||
|  |     } | ||||
|  |     bool first = true; | ||||
|  |     os << "formula " << agentName << "CannotTurn = "; | ||||
|  |     for(auto const& cell : noTurnFloor) { | ||||
|  |       if(first) first = false; else os << " | "; | ||||
|  |       os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |     } | ||||
|  |     os << " | " << agentName << "IsOnSlippery;\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printIsFixedFormulas(std::ostream& os, const AgentName &agentName) { | ||||
|  |     os << "formula " << agentName << "IsFixed = false;\n"; | ||||
|  |     os << "formula " << agentName << "SlipperyTurnLeftAllowed = true;\n"; | ||||
|  |     os << "formula " << agentName << "SlipperyTurnRightAllowed = true;\n"; | ||||
|  |     os << "formula " << agentName << "SlipperyMoveForwardAllowed = true;\n"; | ||||
|  |     os << "label \"FixedStates\" = " << agentName << "IsFixed | !" << agentName << "SlipperyTurnRightAllowed | !" << agentName << "SlipperyTurnLeftAllowed | !" << agentName << "SlipperyMoveForwardAllowed | " << agentName << "IsInGoal | " << agentName << "IsInLava"; | ||||
|  |     if(enforceOneWays) { | ||||
|  |       os << " | " << agentName << "CannotTurn"; | ||||
|  |     } | ||||
|  |     os << ";\n"; | ||||
|  |     //os << "label \"FixedStates\" = " << agentName << "IsFixed | " << agentName << "IsOnSlippery  | " << agentName << "IsInGoal | " << agentName << "IsInLava;\n";
 | ||||
|  | 
 | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printWallFormula(std::ostream& os, const AgentName &agentName, const cells &walls) { | ||||
|  |     os << "formula " << agentName << "IsOnWall = "; | ||||
|  |     bool first = true; | ||||
|  |     for(auto const& cell : walls) { | ||||
|  |       if(first) first = false; else os << " | "; | ||||
|  |       os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |     } | ||||
|  |     os << ";\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printFormulas(std::ostream& os, | ||||
|  |                               const AgentName &agentName, | ||||
|  |                               const cells &restrictionNorth, | ||||
|  |                               const cells &restrictionEast, | ||||
|  |                               const cells &restrictionSouth, | ||||
|  |                               const cells &restrictionWest, | ||||
|  |                               const std::vector<std::reference_wrapper<cells>> &slipperyCollection, | ||||
|  |                               const cells &lava, | ||||
|  |                               const cells &walls, | ||||
|  |                               const cells &noTurnFloor, | ||||
|  |                               const cells &slipperyNorth, | ||||
|  |                               const cells &slipperyEast, | ||||
|  |                               const cells &slipperySouth, | ||||
|  |                               const cells &slipperyWest) { | ||||
|  |     printRestrictionFormula(os, agentName, "North", restrictionNorth); | ||||
|  |     printRestrictionFormula(os, agentName, "East ", restrictionEast); | ||||
|  |     printRestrictionFormula(os, agentName, "South", restrictionSouth); | ||||
|  |     printRestrictionFormula(os, agentName, "West ", restrictionWest); | ||||
|  |     printIsOnSlipperyFormula(os, agentName, slipperyCollection, slipperyNorth, slipperyEast, slipperySouth, slipperyWest); | ||||
|  |     printIsInLavaFormula(os, agentName, lava); | ||||
|  |     printWallFormula(os, agentName, walls); | ||||
|  |     printTurningNotAllowedFormulas(os, agentName, noTurnFloor); | ||||
|  |     printIsFixedFormulas(os, agentName); | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printGoalLabel(std::ostream& os, const AgentName &agentName, const cells &goals) { | ||||
|  |     if(goals.size() == 0) { | ||||
|  |       os << "formula " << agentName << "IsInGoal = false;\n"; | ||||
|  |       return os; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     bool first = true; | ||||
|  |     os << "formula " << agentName << "IsInGoal = "; | ||||
|  |     for(auto const& cell : goals) { | ||||
|  |       if(first) first = false; else os << " | "; | ||||
|  |       os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")"; | ||||
|  |     } | ||||
|  |     os << ";\n"; | ||||
|  |     os << "formula " << agentName << "IsInGoalAndNotDone = " << agentName << "IsInGoal & !" << agentName << "Done;\n"; | ||||
|  |     os << "label \"" << agentName << "IsInGoalAndNotDone\" = " << agentName << "IsInGoal & !" << agentName << "Done;\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printCrashLabel(std::ostream &os, const std::vector<AgentName> agentNames) { | ||||
|  |     os << "label crash = "; | ||||
|  |     bool first = true; | ||||
|  |     for(auto const& agentName : agentNames) { | ||||
|  |       if(agentName == "Agent") continue; | ||||
|  |       if(first) first = false; else os << " | "; | ||||
|  |       os << "(xAgent=x" << agentName << ")&(yAgent=y" << agentName << ")"; | ||||
|  |     } | ||||
|  |     os << ";\n\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printAvoidanceLabel(std::ostream &os, const std::vector<AgentName> agentNames, const int &distance) { | ||||
|  |     os << "label avoidance = "; | ||||
|  |     bool first = true; | ||||
|  |     for(auto const& agentName : agentNames) { | ||||
|  |       if(agentName == "Agent") continue; | ||||
|  |       if(first) first = false; else os << " | "; | ||||
|  |       os << "max(xAgent-x" << agentName << ",x" << agentName << "-xAgent)+"; | ||||
|  |       os << "max(yAgent-y" << agentName << ",y" << agentName << "-yAgent) "; | ||||
|  |     } | ||||
|  |     os << ";\n\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   // TODO this does not account for multiple agents yet, i.e. key can be picked up multiple times
 | ||||
|  |   std::ostream& PrismModulesPrinter::printKeysLabels(std::ostream& os, const AgentName &agentName, const cells &keys) { | ||||
|  |     if(keys.size() == 0) return os; | ||||
|  | 
 | ||||
|  |     for(auto const& key : keys) { | ||||
|  |       int xKey = key.getCoordinates().first; | ||||
|  |       int yKey = key.getCoordinates().second; | ||||
|  |       std::string keyColor = key.getColor(); | ||||
|  |       os << "label \"" << agentName << "PickedUp" << keyColor << "Key\" = " << agentName << "_has_" << keyColor << "_key = true;\n"; | ||||
|  |       os << "formula " << agentName << "CanPickUp" << keyColor << "Key = "; | ||||
|  |       os << "((x" << agentName << "-1 = " << xKey << "&y" << agentName << "   = " << yKey << "&view" << agentName << " = 1) |"; | ||||
|  |       os << " (x" << agentName << "+1 = " << xKey << "&y" << agentName << "   = " << yKey << "&view" << agentName << " = 3) |"; | ||||
|  |       os << " (x" << agentName << "   = " << xKey << "&y" << agentName << "-1 = " << yKey << "&view" << agentName << " = 0) |"; | ||||
|  |       os << " (x" << agentName << "   = " << xKey << "&y" << agentName << "+1 = " << yKey << "&view" << agentName << " = 2) ) &"; | ||||
|  |       os << "!" << agentName << "_has_" << keyColor << "_key;"; | ||||
|  |     } | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printBooleansForKeys(std::ostream &os, const AgentName &agentName, const cells &keys) { | ||||
|  |     for(auto const& key : keys) { | ||||
|  |       os << "\t" << agentName << "_has_"<< key.getColor() << "_key : bool init false;\n"; | ||||
|  |     } | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printBooleansForBackground(std::ostream &os, const AgentName &agentName, const std::map<Color, cells> &backgroundTiles) { | ||||
|  |     for(auto const& [color, cells] : backgroundTiles) { | ||||
|  |       if(cells.size() == 0) continue; | ||||
|  |       std::string c = getColor(color); | ||||
|  |       c.at(0) = std::toupper(c.at(0)); | ||||
|  |       os << "\t" << agentName << "_picked_up_" << c << " : bool init false;\n"; | ||||
|  |     } | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printActionsForKeys(std::ostream &os, const AgentName &agentName, const cells &keys) { | ||||
|  |     for(auto const& key : keys) { | ||||
|  |       std::string keyColor = key.getColor(); | ||||
|  |       os << "\t[pickup_" << keyColor << "_key] " << agentName << "CanPickUp" << keyColor << "Key -> "; | ||||
|  |       os << "(" << agentName << "_has_" << keyColor << "_key'=true);"; | ||||
|  |     } | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printActionsForBackground(std::ostream &os, const AgentName &agentName, const std::map<Color, cells> &backgroundTiles) { | ||||
|  |     for(auto const& [color, cells] : backgroundTiles) { | ||||
|  |       if(cells.size() == 0) continue; | ||||
|  |       std::string c = getColor(color); | ||||
|  |       c.at(0) = std::toupper(c.at(0)); | ||||
|  |       os << "\t[" << agentName << "_pickup_" << c << "] " << agentName << "On" << c << " & !" << agentName << "_picked_up_" << c << " -> "; | ||||
|  |       os << "(" << agentName << "_picked_up_" << c << "'=true);\n"; | ||||
|  |     } | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printInitStruct(std::ostream &os, const AgentName &agentName) { | ||||
|  |     os << "init\n"; | ||||
|  |     os << "\t(!AgentIsInGoal & !AgentIsInLava & !AgentDone & !AgentIsOnWall)"; | ||||
|  |     if(enforceOneWays) { | ||||
|  |       os << " & ( !AgentCannotTurn ) "; | ||||
|  |     } else { | ||||
|  |       os << " & ( !AgentIsOnSlippery ) "; | ||||
|  |     } | ||||
|  |     os << "\nendinit\n\n"; | ||||
|  | 
 | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printModule(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &boundaries, const coordinates& initialPosition, const cells &keys, const std::map<Color, cells> &backgroundTiles, const bool agentWithView, const std::vector<float> &probabilities) { | ||||
|  |     os << "module " << agentName << "\n"; | ||||
|  |     os << "\tx" << agentName << " : [1.." << boundaries.second  << "];\n"; | ||||
|  |     os << "\ty" << agentName << " : [1.." << boundaries.first << "];\n"; | ||||
|  |     printBooleansForKeys(os, agentName, keys); | ||||
|  |     printBooleansForBackground(os, agentName, backgroundTiles); | ||||
|  |     os << "\t" << agentName << "Done : bool;\n"; | ||||
|  |     if(agentWithView) { | ||||
|  |       os << "\tview" << agentName << " : [0..3];\n"; | ||||
|  |     os << "\n"; | ||||
|  |     os << "\t[" << agentName << "_turn_right] " << moveGuard(agentIndex) << " !" << agentName << "CannotTurn & " << " !" << agentName << "IsFixed & " << " !" << agentName << "IsInGoal & !" << agentName << "IsInLava & !" << agentName << "IsOnSlippery -> (view" << agentName << "'=mod(view" << agentName << " + 1, 4)) " << moveUpdate(agentIndex) << ";\n"; | ||||
|  |     os << "\t[" << agentName << "_turn_left]  " << moveGuard(agentIndex) << " !" << agentName << "CannotTurn & " << " !" << agentName << "IsFixed & " << " !" << agentName << "IsInGoal & !" << agentName << "IsInLava & !" << agentName << "IsOnSlippery & view" << agentName << ">0 -> (view" << agentName << "'=view" << agentName << " - 1) " << moveUpdate(agentIndex) << ";\n"; | ||||
|  |     os << "\t[" << agentName << "_turn_left]  " << moveGuard(agentIndex) << " !" << agentName << "CannotTurn & " << " !" << agentName << "IsFixed & " << " !" << agentName << "IsInGoal & !" << agentName << "IsInLava & !" << agentName << "IsOnSlippery & view" << agentName << "=0 -> (view" << agentName << "'=3) " << moveUpdate(agentIndex) << ";\n"; | ||||
|  |       if(enforceOneWays) { | ||||
|  |         os << "\t[" << agentName << "_stuck]        !" << agentName << "IsFixed & " << agentName << "CannotTurn & view" << agentName << " = 0 & " << agentName << "CannotMoveEast -> true;\n"; | ||||
|  |         os << "\t[" << agentName << "_stuck]        !" << agentName << "IsFixed & " << agentName << "CannotTurn & view" << agentName << " = 1 & " << agentName << "CannotMoveSouth -> true;\n"; | ||||
|  |         os << "\t[" << agentName << "_stuck]        !" << agentName << "IsFixed & " << agentName << "CannotTurn & view" << agentName << " = 2 & " << agentName << "CannotMoveWest -> true;\n"; | ||||
|  |         os << "\t[" << agentName << "_stuck]        !" << agentName << "IsFixed & " << agentName << "CannotTurn & view" << agentName << " = 3 & " << agentName << "CannotMoveNorth -> true;\n"; | ||||
|  |       } | ||||
|  |     } else { | ||||
|  |       os << "\t[" << agentName << "_turns]  " << " !" << agentName << "CannotTurn & " << " !" << agentName << "IsFixed & " <<  moveGuard(agentIndex) << " true -> (x" << agentName << "'=x" << agentName << ")" << moveUpdate(agentIndex) << ";\n"; | ||||
|  |     } | ||||
|  |     printActionsForKeys(os, agentName, keys); | ||||
|  |     printActionsForBackground(os, agentName, backgroundTiles); | ||||
|  |     os << "\n"; | ||||
|  |     printMovementActions(os, agentName, agentIndex, agentWithView); | ||||
|  |     for(auto const& probability : probabilities) { | ||||
|  |       printMovementActions(os, agentName, agentIndex, agentWithView, probability); | ||||
|  |     } | ||||
|  |     printDoneActions(os, agentName, agentIndex); | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printMovementActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const bool agentWithView, const float &probability) { | ||||
|  |     if(probability >= 1) { | ||||
|  |       os << "\t[" << agentName << "_move_north]" << moveGuard(agentIndex) << viewVariable(agentName, 3, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal &  !" << agentName << "CannotMoveNorth -> (y" << agentName << "'=y" << agentName << "-1)" << moveUpdate(agentIndex) << ";\n"; | ||||
|  |       os << "\t[" << agentName << "_move_east] " << moveGuard(agentIndex) << viewVariable(agentName, 0, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal &  !" << agentName << "CannotMoveEast  -> (x" << agentName << "'=x" << agentName << "+1)" << moveUpdate(agentIndex) << ";\n"; | ||||
|  |       os << "\t[" << agentName << "_move_south]" << moveGuard(agentIndex) << viewVariable(agentName, 1, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal &  !" << agentName << "CannotMoveSouth -> (y" << agentName << "'=y" << agentName << "+1)" << moveUpdate(agentIndex) << ";\n"; | ||||
|  |       os << "\t[" << agentName << "_move_west] " << moveGuard(agentIndex) << viewVariable(agentName, 2, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal &  !" << agentName << "CannotMoveWest  -> (x" << agentName << "'=x" << agentName << "-1)" << moveUpdate(agentIndex) << ";\n"; | ||||
|  |     } else { | ||||
|  |       std::string probabilityString = std::to_string(probability); | ||||
|  |       std::string percentageString = std::to_string((int)(100 * probability)); | ||||
|  |       std::string complementProbabilityString = std::to_string(1 - probability); | ||||
|  |       os << "\t[" << agentName << "_move_north_" << percentageString << "] "; | ||||
|  |       os << moveGuard(agentIndex) << viewVariable(agentName, 3, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveNorth -> "; | ||||
|  |       os << probabilityString << ": (y" << agentName << "'=y" << agentName << "-1)" << moveUpdate(agentIndex) << " + "; | ||||
|  |       os << complementProbabilityString << ": (y" << agentName << "'=y" << agentName << ") " << moveUpdate(agentIndex) << ";\n"; | ||||
|  | 
 | ||||
|  |       os << "\t[" << agentName << "_move_east_" << percentageString << "] "; | ||||
|  |       os << moveGuard(agentIndex) << viewVariable(agentName, 0, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveEast  -> "; | ||||
|  |       os << probabilityString << ": (x" << agentName << "'=x" << agentName << "+1)" << moveUpdate(agentIndex) << " + "; | ||||
|  |       os << complementProbabilityString << ": (x" << agentName << "'=x" << agentName << ") " << moveUpdate(agentIndex) << ";\n"; | ||||
|  | 
 | ||||
|  |       os << "\t[" << agentName << "_move_south_" << percentageString << "] "; | ||||
|  |       os << moveGuard(agentIndex) << viewVariable(agentName, 1, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveSouth -> "; | ||||
|  |       os << probabilityString << ": (y" << agentName << "'=y" << agentName << "+1)" << moveUpdate(agentIndex) << " + "; | ||||
|  |       os << complementProbabilityString << ": (y" << agentName << "'=y" << agentName << ") " << moveUpdate(agentIndex) << ";\n"; | ||||
|  | 
 | ||||
|  |       os << "\t[" << agentName << "_move_west_" << percentageString << "] "; | ||||
|  |       os << moveGuard(agentIndex) << viewVariable(agentName, 2, agentWithView) << " !" << agentName << "IsFixed & " << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveWest  -> "; | ||||
|  |       os << probabilityString << ": (x" << agentName << "'=x" << agentName << "-1)" << moveUpdate(agentIndex) << " + "; | ||||
|  |       os << complementProbabilityString << ": (x" << agentName << "'=x" << agentName << ") " << moveUpdate(agentIndex) << ";\n"; | ||||
|  |     } | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printDoneActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex) { | ||||
|  |     os << "\t[" << agentName << "_done]" << moveGuard(agentIndex) << agentName << "IsInGoal | " << agentName << "IsInLava -> (" << agentName << "Done'=true);\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printSlipperyTurn(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation) { | ||||
|  |     constexpr std::size_t PROB_PIECES = 9, ALL_POSS_DIRECTIONS = 9; | ||||
|  | 
 | ||||
|  |     std::array<std::string, ALL_POSS_DIRECTIONS> positionTransition = { | ||||
|  |       /* north      */                                                "(y" + agentName + "'=y" + agentName + "-1)", | ||||
|  |       /* north east */   "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "-1)", | ||||
|  |       /* east       */   "(x" + agentName + "'=x" + agentName + "+1)", | ||||
|  |       /* east south */   "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "+1)", | ||||
|  |       /* south      */                                                "(y" + agentName + "'=y" + agentName + "+1)", | ||||
|  |       /* south west */   "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "+1)", | ||||
|  |       /* west       */   "(x" + agentName + "'=x" + agentName + "-1)", | ||||
|  |       /* north west */   "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "-1)", | ||||
|  |       /* own position */ "(x" + agentName + "'=x" + agentName + ") & (y" + agentName + "'=y" + agentName + ")" | ||||
|  |     }; | ||||
|  | 
 | ||||
|  |     // view transition appdx in form (guard, update part)
 | ||||
|  |     // IMPORTANT: No mod() usage for turn left due to bug in mod() function for decrement
 | ||||
|  | 
 | ||||
|  |     std::array<std::pair<std::string, std::string>, 3> viewTransition = { | ||||
|  |         /* turn to right */ std::make_pair(" & " + agentName + "SlipperyTurnRightAllowed ",                           " & (view" + agentName + "'=mod(view" + agentName + " + 1, 4))"), | ||||
|  |         /* turn to left  */ std::make_pair(" & " + agentName + "SlipperyTurnLeftAllowed & view" + agentName + ">0", " & (view" + agentName + "'=view" + agentName + " - 1)"), | ||||
|  |         /* turn to left  */ std::make_pair(" & " + agentName + "SlipperyTurnLeftAllowed & view" + agentName + "=0", " & (view" + agentName + "'=3)") | ||||
|  |     }; | ||||
|  | 
 | ||||
|  |     // direction specifics
 | ||||
|  | 
 | ||||
|  |     std::string actionName; | ||||
|  |     std::size_t remainPosIndex = 8; | ||||
|  |     std::array<std::size_t, ALL_POSS_DIRECTIONS> prob_piece_dir; // { n, ne, w, se, s, sw, w, nw, CURRENT POS }
 | ||||
|  | 
 | ||||
|  |     switch (orientation) | ||||
|  |     { | ||||
|  |       case SlipperyType::North: | ||||
|  |         actionName = "\t[" + agentName + "turn_at_slip_north]"; | ||||
|  |         prob_piece_dir = { 0, 0, 0, 1, 1, 1, 0, 0, 0 /* <- R */ }; | ||||
|  |         break; | ||||
|  | 
 | ||||
|  |       case SlipperyType::South: | ||||
|  |         actionName = "\t[" + agentName + "turn_at_slip_south]"; | ||||
|  |         prob_piece_dir = { 1, 1, 0, 0, 0, 0, 0, 1, 0 /* <- R */ }; | ||||
|  |         break; | ||||
|  | 
 | ||||
|  |       case SlipperyType::East: | ||||
|  |         actionName = "\t[" + agentName + "turn_at_slip_east]"; | ||||
|  |         prob_piece_dir = { 0, 0, 0, 0, 0, 1, 1, 1, 0 /* <- R */ }; | ||||
|  |         break; | ||||
|  | 
 | ||||
|  |       case SlipperyType::West: | ||||
|  |         actionName = "\t[" + agentName + "turn_at_slip_west]"; | ||||
|  |         prob_piece_dir = { 0, 1, 1, 1, 0, 0, 0, 0, 0 /* <- R */ }; | ||||
|  |         break; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     slipperyActions.insert(actionName); | ||||
|  | 
 | ||||
|  |     // override probability to 0 if corresp. direction is blocked
 | ||||
|  | 
 | ||||
|  |     for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS - 1; i++) { | ||||
|  |       if (!neighborhood.at(i)) | ||||
|  |         prob_piece_dir.at(i) = 0; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     // determine residual probability (R) by replacing 0 with (1 - overall sum)
 | ||||
|  | 
 | ||||
|  |     prob_piece_dir.at(remainPosIndex) = PROB_PIECES - std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0); | ||||
|  | 
 | ||||
|  |     // <DEBUG_AREA>
 | ||||
|  |     { | ||||
|  |       assert(prob_piece_dir.at(remainPosIndex) <= 9 && prob_piece_dir.at(remainPosIndex) >= 6 && "Value not in Range!"); | ||||
|  |       assert(std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0) == PROB_PIECES && "Does not sum up to 1!"); | ||||
|  |     } | ||||
|  |     // </DEBUG_AREA>
 | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |     // generic output (for every view transition)
 | ||||
|  |     for (std::size_t v = 0; v < viewTransition.size(); v++) { | ||||
|  | 
 | ||||
|  |         os << actionName << moveGuard(agentIndex) << " x" << agentName << "=" << c.second << " & y" << agentName << "=" << c.first << viewTransition.at(v).first; | ||||
|  |         for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) { | ||||
|  |           os << (i == 0 ? " -> " : " + ") << prob_piece_dir.at(i) << "/" << PROB_PIECES << " : " << positionTransition.at(i) << viewTransition.at(v).second << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); | ||||
|  |         } | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printSlipperyMove(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation) { | ||||
|  |     constexpr std::size_t PROB_PIECES = 9, ALL_POSS_DIRECTIONS = 8; | ||||
|  | 
 | ||||
|  |     std::array<std::string, ALL_POSS_DIRECTIONS> positionTransition = { | ||||
|  |       /* north      */                                              "(y" + agentName + "'=y" + agentName + "-1)", | ||||
|  |       /* north east */ "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "-1)", | ||||
|  |       /* east       */ "(x" + agentName + "'=x" + agentName + "+1)", | ||||
|  |       /* east south */ "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "+1)", | ||||
|  |       /* south      */                                              "(y" + agentName + "'=y" + agentName + "+1)", | ||||
|  |       /* south west */ "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "+1)", | ||||
|  |       /* west       */ "(x" + agentName + "'=x" + agentName + "-1)", | ||||
|  |       /* north west */ "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "-1)" | ||||
|  |     }; | ||||
|  | 
 | ||||
|  |     // direction specifics
 | ||||
|  | 
 | ||||
|  |     std::size_t straightPosIndex; | ||||
|  |     std::string actionName, specialTransition; // if straight ahead is blocked
 | ||||
|  |     std::array<std::size_t, ALL_POSS_DIRECTIONS> prob_piece_dir; // { n, ne, w, se, s, sw, w, nw }
 | ||||
|  | 
 | ||||
|  |     switch (orientation) | ||||
|  |     { | ||||
|  |       case SlipperyType::North: | ||||
|  |         actionName = "\t[" + agentName + "move_on_slip_north]"; | ||||
|  |         prob_piece_dir = { 0, 0, 1, 2, 0 /* <- R */, 2, 1, 0 }; | ||||
|  |         straightPosIndex = 4; | ||||
|  |         specialTransition = "(y" + agentName + "'=y" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "+1)"); | ||||
|  |         break; | ||||
|  | 
 | ||||
|  |       case SlipperyType::South: | ||||
|  |         actionName = "\t[" + agentName + "move_on_slip_south]"; | ||||
|  |         prob_piece_dir = { 0 /* <- R */, 2, 1, 0, 0, 0, 1, 2 }; | ||||
|  |         straightPosIndex = 0; // always north
 | ||||
|  |         specialTransition = "(y" + agentName + "'=y" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "-1)"); | ||||
|  |         break; | ||||
|  | 
 | ||||
|  |       case SlipperyType::East: | ||||
|  |         actionName = "\t[" + agentName + "move_on_slip_east]"; | ||||
|  |         prob_piece_dir = { 1, 0, 0, 0, 1, 2, 0 /* <- R */, 2 }; | ||||
|  |         straightPosIndex = 6; | ||||
|  |         specialTransition = "(x" + agentName + "'=x" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "-1)"); | ||||
|  |         break; | ||||
|  | 
 | ||||
|  |       case SlipperyType::West: | ||||
|  |         actionName = "\t[" + agentName + "move_on_slip_west]"; | ||||
|  |         prob_piece_dir = { 1, 2, 0 /* <- R */, 2, 1, 0, 0, 0 }; | ||||
|  |         straightPosIndex = 2; | ||||
|  |         specialTransition = "(x" + agentName + "'=x" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "+1)"); | ||||
|  |         break; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     slipperyActions.insert(actionName); | ||||
|  | 
 | ||||
|  |     // override probability to 0 if corresp. direction is blocked
 | ||||
|  | 
 | ||||
|  |     for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) { | ||||
|  |       if (!neighborhood.at(i)) | ||||
|  |         prob_piece_dir.at(i) = 0; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     // determine residual probability (R) by replacing 0 with (1 - overall sum)
 | ||||
|  |     if(enforceOneWays) { | ||||
|  |       prob_piece_dir = {0,0,0,0,0,0,0,0}; | ||||
|  |     } | ||||
|  |     prob_piece_dir.at(straightPosIndex) = PROB_PIECES - std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0); | ||||
|  | 
 | ||||
|  |     // <DEBUG_AREA>
 | ||||
|  |     { | ||||
|  |       assert(prob_piece_dir.at(straightPosIndex) <= 9 && prob_piece_dir.at(straightPosIndex) >= 3 && "Value not in Range!"); | ||||
|  |       assert(std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0) == PROB_PIECES && "Does not sum up to 1!"); | ||||
|  |       assert(orientation != SlipperyType::North || (prob_piece_dir.at(7) == 0 && prob_piece_dir.at(0) == 0 && prob_piece_dir.at(1) == 0 && "Slippery up should be impossible!")); | ||||
|  |       assert(orientation != SlipperyType::South || (prob_piece_dir.at(3) == 0 && prob_piece_dir.at(4) == 0 && prob_piece_dir.at(5) == 0 && "Slippery down should be impossible!")); | ||||
|  |       assert(orientation != SlipperyType::East  || (prob_piece_dir.at(1) == 0 && prob_piece_dir.at(2) == 0 && prob_piece_dir.at(3) == 0 && "Slippery right should be impossible!")); | ||||
|  |       assert(orientation != SlipperyType::West  || (prob_piece_dir.at(5) == 0 && prob_piece_dir.at(6) == 0 && prob_piece_dir.at(7) == 0 && "Slippery left should be impossible!")); | ||||
|  |     } | ||||
|  |     // </DEBUG_AREA>
 | ||||
|  | 
 | ||||
|  |     // special case: straight forward is blocked (then remain in same position)
 | ||||
|  | 
 | ||||
|  |     positionTransition.at(straightPosIndex) = specialTransition; | ||||
|  | 
 | ||||
|  |     // generic output (for every view and every possible view direction)
 | ||||
|  | 
 | ||||
|  |     os << actionName << moveGuard(agentIndex) << " x" << agentName << "=" << c.second << " & y" << agentName << "=" << c.first << " & " << agentName << "SlipperyMoveForwardAllowed "; | ||||
|  | 
 | ||||
|  |     for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) { | ||||
|  |       os << (i == 0 ? " -> " : " + ") << prob_piece_dir.at(i) << "/" << PROB_PIECES << " : " << positionTransition.at(i) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printEndmodule(std::ostream &os) { | ||||
|  |     os << "endmodule\n"; | ||||
|  |     os << "\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printPlayerStruct(std::ostream &os, const AgentName &agentName, const bool agentWithView, const std::vector<float> &probabilities, const std::set<std::string> &slipperyActions) { | ||||
|  |     os << "player " << agentName << "\n\t"; | ||||
|  |     bool first = true; | ||||
|  |     std::list<std::string> allActions = { "_move_north", "_move_east", "_move_south", "_move_west" }; | ||||
|  |     std::list<std::string> movementActions = allActions; | ||||
|  |     for(auto const& probability : probabilities) { | ||||
|  |       std::string percentageString = std::to_string((int)(100 * probability)); | ||||
|  |       for(auto const& movement : movementActions) { | ||||
|  |         allActions.push_back(movement + "_" + percentageString); | ||||
|  |       } | ||||
|  |     } | ||||
|  |     if(agentWithView) { | ||||
|  |       allActions.push_back("_turn_left"); | ||||
|  |       allActions.push_back("_turn_right"); | ||||
|  |     } else { | ||||
|  |       allActions.push_back("_turns"); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     for(auto const& action : allActions) { | ||||
|  |       if(first) first = false; else os << ", "; | ||||
|  |       os << "[" << agentName << action << "]"; | ||||
|  |     } | ||||
|  |     for(auto const& action : slipperyActions) { | ||||
|  |       os << ", " << action; | ||||
|  |     } | ||||
|  |     os << "\nendplayer\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printGlobalMoveVariable(std::ostream &os, const size_t &numberOfPlayer) { | ||||
|  |     os << "\nglobal move : [0.." << std::to_string(numberOfPlayer - 1) << "] init 0;\n\n"; | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::ostream& PrismModulesPrinter::printRewards(std::ostream &os, const AgentName &agentName, const std::map<coordinates, float> &stateRewards, const cells &lava, const cells &goals, const std::map<Color, cells> &backgroundTiles) { | ||||
|  |     if(lava.size() != 0) { | ||||
|  |       os << "rewards \"SafetyNoBFS\"\n"; | ||||
|  |       os << "\tAgentIsInLavaAndNotDone: -100;\n"; | ||||
|  |       os << "endrewards\n"; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     os << "rewards \"SafetyNoBFSAndGoal\"\n"; | ||||
|  |     if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone:  100;\n"; | ||||
|  |     if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; | ||||
|  |     os << "endrewards\n"; | ||||
|  | 
 | ||||
|  |     os << "rewards \"Time\"\n"; | ||||
|  |     os << "\t!AgentIsInGoal : -1;\n"; | ||||
|  |     if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone:  100;\n"; | ||||
|  |     if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; | ||||
|  |     os << "endrewards\n"; | ||||
|  | 
 | ||||
|  |     if(stateRewards.size() > 0) { | ||||
|  |       os << "rewards \"SafetyWithBFS\"\n"; | ||||
|  |       if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; | ||||
|  |       for(auto const [coordinates, reward] : stateRewards) { | ||||
|  |         os << "\txAgent=" << coordinates.first << "&yAgent=" << coordinates.second << " : " << reward << ";\n"; | ||||
|  |       } | ||||
|  |       os << "endrewards\n"; | ||||
|  |     } | ||||
|  |     if(stateRewards.size() > 0) { | ||||
|  |       os << "rewards \"SafetyWithBFSAndGoal\"\n"; | ||||
|  |       if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone:  100;\n"; | ||||
|  |       if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; | ||||
|  |       for(auto const [coordinates, reward] : stateRewards) { | ||||
|  |         os << "\txAgent=" << coordinates.first << "&yAgent=" << coordinates.second << " : " << reward << ";\n"; | ||||
|  |       } | ||||
|  |       os << "endrewards\n"; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     for(auto const entry : backgroundTiles) | ||||
|  |     { | ||||
|  |       std::cout << getColor(entry.first) << " "; | ||||
|  |       for(auto const cell : entry.second){ | ||||
|  |         std::cout << cell.getCoordinates().first << " " << cell.getCoordinates().second << std::endl; | ||||
|  |       } | ||||
|  |     } | ||||
|  |     if(backgroundTiles.size() > 0) { | ||||
|  |       os << "rewards \"TaxiReward\"\n"; | ||||
|  |       os << "\t!AgentIsInGoal : -1;\n"; | ||||
|  |       std::string allPassengersPickedUp = ""; | ||||
|  |       bool first = true; | ||||
|  |       for(auto const [color, cells] : backgroundTiles) { | ||||
|  |         if(cells.size() == 0) continue; | ||||
|  |         if(first) first = false; else allPassengersPickedUp += "&"; | ||||
|  |         std::string c = getColor(color); | ||||
|  |         c.at(0) = std::toupper(c.at(0)); | ||||
|  |         std::string visitedLabel = agentName + "_picked_up_" + c; | ||||
|  |         allPassengersPickedUp += visitedLabel; | ||||
|  |         os << "[" << agentName << "_pickup_" << c << "] true : 100;\n"; | ||||
|  |       } | ||||
|  |       if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone & " << allPassengersPickedUp << " :  100;\n"; | ||||
|  |       if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone & !(" << allPassengersPickedUp << ") :  -100;\n"; | ||||
|  |       os << "endrewards"; | ||||
|  |     } | ||||
|  |     return os; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::string PrismModulesPrinter::moveGuard(const size_t &agentIndex) { | ||||
|  |     return isGame() ? " move=" + std::to_string(agentIndex) + " & " : " "; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::string PrismModulesPrinter::moveUpdate(const size_t &agentIndex) { | ||||
|  |     return isGame() ? | ||||
|  |              (agentIndex == numberOfPlayer - 1) ? | ||||
|  |                " & (move'=0) " : | ||||
|  |                " & (move'=" + std::to_string(agentIndex + 1) + ") " : | ||||
|  |                ""; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   std::string PrismModulesPrinter::viewVariable(const AgentName &agentName, const size_t &agentDirection, const bool agentWithView) { | ||||
|  |     return agentWithView ? " view" + agentName + "=" + std::to_string(agentDirection) + " & " : " "; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   bool PrismModulesPrinter::isGame() const { | ||||
|  |     return modelType == ModelType::SMG; | ||||
|  |   } | ||||
|  | } | ||||
| @ -0,0 +1,91 @@ | |||||
|  | #pragma once | ||||
|  | 
 | ||||
|  | #include <iostream> | ||||
|  | #include <functional> | ||||
|  | #include "MinigridGrammar.h" | ||||
|  | #include "PrismPrinter.h" | ||||
|  | 
 | ||||
|  | namespace prism { | ||||
|  |   class PrismModulesPrinter { | ||||
|  |     public: | ||||
|  |       PrismModulesPrinter(const ModelType &modelType, const size_t &numberOfPlayer, const bool enforceOneWays = false); | ||||
|  | 
 | ||||
|  |       std::ostream& printRestrictionFormula(std::ostream& os, const AgentName &agentName, const std::string &direction, const cells &cells); | ||||
|  |       std::ostream& printIsOnSlipperyFormula(std::ostream& os, const AgentName &agentName, const std::vector<std::reference_wrapper<cells>> &slipperyCollection, const cells &slipperyNorth, const cells &slipperyEast, const cells &slipperySouth, const cells &slipperyWest); | ||||
|  |       std::ostream& printGoalLabel(std::ostream& os, const AgentName&agentName, const cells &goals); | ||||
|  |       std::ostream& printCrashLabel(std::ostream &os, const std::vector<AgentName> agentNames); | ||||
|  |       std::ostream& printAvoidanceLabel(std::ostream &os, const std::vector<AgentName> agentNames, const int &distance); | ||||
|  |       std::ostream& printKeysLabels(std::ostream& os, const AgentName&agentName, const cells &keys); | ||||
|  |       std::ostream& printBackgroundLabels(std::ostream &os, const AgentName &agentName, const std::pair<Color, cells> &backgroundTiles); | ||||
|  |       std::ostream& printIsInLavaFormula(std::ostream& os, const AgentName &agentName, const cells &lava); | ||||
|  |       std::ostream& printIsFixedFormulas(std::ostream& os, const AgentName &agentName); | ||||
|  |       std::ostream& printTurningNotAllowedFormulas(std::ostream& os, const AgentName &agentName, const cells &floor); | ||||
|  |       std::ostream& printWallFormula(std::ostream& os, const AgentName &agentName, const cells &walls); | ||||
|  |       std::ostream& printFormulas(std::ostream& os, | ||||
|  |                                   const AgentName&agentName, | ||||
|  |                                   const cells &restrictionNorth, | ||||
|  |                                   const cells &restrictionEast, | ||||
|  |                                   const cells &restrictionSouth, | ||||
|  |                                   const cells &restrictionWest, | ||||
|  |                                   const std::vector<std::reference_wrapper<cells>> &slipperyCollection, | ||||
|  |                                   const cells &lava, | ||||
|  |                                   const cells &walls, | ||||
|  |                                   const cells &noTurnFloor, | ||||
|  |                                   const cells &slipperyNorth, | ||||
|  |                                   const cells &slipperyEast, | ||||
|  |                                   const cells &slipperySouth, | ||||
|  |                                   const cells &slipperyWest); | ||||
|  | 
 | ||||
|  |        /* | ||||
|  |         * Representation for Slippery Tile. | ||||
|  |         *  -) North: Slips from North to South | ||||
|  |         *  -) East: Slips from East to West | ||||
|  |         *  -) South: Slips from South to North | ||||
|  |         *  -) West: Slips from West to East | ||||
|  |         */ | ||||
|  |       enum class SlipperyType { North, East, South, West }; | ||||
|  | 
 | ||||
|  |       /* | ||||
|  |        * Prints Slippery on move action. | ||||
|  |        * | ||||
|  |        * @param neighborhood: Information of wall-blocks in 8-neighborhood { n, nw, e, se, s, sw, w, nw }. If entry is false, then corresponding neighboorhood position is a wall. | ||||
|  |        * @param orientation: Information of slippery type (either north, south, east, west). | ||||
|  |        */ | ||||
|  |       std::ostream& printSlipperyMove(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation); | ||||
|  | 
 | ||||
|  |       /* | ||||
|  |        * Prints Slippery on turn action. | ||||
|  |        * | ||||
|  |        * @param neighborhood: Information of wall-blocks in 8-neighborhood { n, nw, e, se, s, sw, w, nw }. If entry is false, then corresponding neighboorhood position is a wall. | ||||
|  |        * @param orientation: Information of slippery type (either north, south, east, west). | ||||
|  |        */ | ||||
|  |       std::ostream& printSlipperyTurn(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation); | ||||
|  | 
 | ||||
|  |       std::ostream& printModel(std::ostream &os, const ModelType &modelType); | ||||
|  |       std::ostream& printBooleansForKeys(std::ostream &os, const AgentName &agentName, const cells &keys); | ||||
|  |       std::ostream& printActionsForKeys(std::ostream &os, const AgentName &agentName, const cells &keys); | ||||
|  |       std::ostream& printBooleansForBackground(std::ostream &os, const AgentName &agentName, const std::map<Color, cells> &backgroundTiles); | ||||
|  |       std::ostream& printActionsForBackground(std::ostream &os, const AgentName &agentName, const std::map<Color, cells> &backgroundTiles); | ||||
|  |       std::ostream& printInitStruct(std::ostream &os, const AgentName &agentName); | ||||
|  |       std::ostream& printModule(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &boundaries, const coordinates& initialPosition, const cells &keys, const std::map<Color, cells> &backgroundTiles, const bool agentWithView, const std::vector<float> &probabilities = {}); | ||||
|  |       std::ostream& printMovementActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const bool agentWithView, const float &probability = 1.0); | ||||
|  |       std::ostream& printDoneActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex); | ||||
|  |       std::ostream& printEndmodule(std::ostream &os); | ||||
|  |       std::ostream& printPlayerStruct(std::ostream &os, const AgentName &agentName, const bool agentWithView, const std::vector<float> &probabilities = {}, const std::set<std::string> &slipperyActions = {}); | ||||
|  |       std::ostream& printGlobalMoveVariable(std::ostream &os, const size_t &numberOfPlayer); | ||||
|  | 
 | ||||
|  |       std::ostream& printRewards(std::ostream &os, const AgentName &agentName, const std::map<coordinates, float> &stateRewards, const cells &lava, const cells &goals, const std::map<Color, cells> &backgroundTiles); | ||||
|  | 
 | ||||
|  |       std::string moveGuard(const size_t &agentIndex); | ||||
|  |       std::string moveUpdate(const size_t &agentIndex); | ||||
|  | 
 | ||||
|  |       std::string viewVariable(const AgentName &agentName, const size_t &agentDirection, const bool agentWithView); | ||||
|  | 
 | ||||
|  |       bool isGame() const; | ||||
|  |     private: | ||||
|  | 
 | ||||
|  |       ModelType const& modelType; | ||||
|  |       const size_t numberOfPlayer; | ||||
|  |       bool enforceOneWays; | ||||
|  |   }; | ||||
|  | } | ||||
| @ -0,0 +1,15 @@ | |||||
|  | #pragma once | ||||
|  | 
 | ||||
|  | #include <string> | ||||
|  | 
 | ||||
|  | #include "cell.h" | ||||
|  | 
 | ||||
|  | typedef std::string AgentName; | ||||
|  | typedef std::pair<std::string, coordinates> AgentNameAndPosition; | ||||
|  | typedef std::map<AgentNameAndPosition::first_type, AgentNameAndPosition::second_type> AgentNameAndPositionMap; | ||||
|  | 
 | ||||
|  | namespace prism { | ||||
|  |   enum class ModelType { | ||||
|  |     MDP, SMG | ||||
|  |   }; | ||||
|  | } | ||||
| @ -0,0 +1,83 @@ | |||||
|  | #include "cell.h"
 | ||||
|  | 
 | ||||
|  | #include <stdexcept>
 | ||||
|  | 
 | ||||
|  | std::ostream &operator<<(std::ostream &os, const cell &c) { | ||||
|  |   os << static_cast<char>(c.type) << static_cast<char>(c.color); | ||||
|  |   os <<  " at (" << c.row << "," << c.column << ")"; | ||||
|  |   return os; | ||||
|  | } | ||||
|  | 
 | ||||
|  | cell cell::getNorth(const std::vector<cell> &grid) const { | ||||
|  |   auto north = std::find_if(grid.begin(), grid.end(), [this](const cell &c) { | ||||
|  |         return this->row - 1 == c.row && this->column == c.column; | ||||
|  |       }); | ||||
|  |   if(north == grid.end()) { | ||||
|  |     throw std::logic_error{ "Cannot get cell north of (" + std::to_string(row) + "," + std::to_string(column) + ")"}; | ||||
|  |     std::exit(EXIT_FAILURE); | ||||
|  |   } | ||||
|  |   return *north; | ||||
|  | } | ||||
|  | 
 | ||||
|  | cell cell::getEast(const std::vector<cell> &grid) const { | ||||
|  |   auto east = std::find_if(grid.begin(), grid.end(), [this](const cell &c) { | ||||
|  |         return this->row == c.row && this->column + 1 == c.column; | ||||
|  |       }); | ||||
|  |   if(east == grid.end()) { | ||||
|  |     throw std::logic_error{ "Cannot get cell east of (" + std::to_string(row) + "," + std::to_string(column) + ")"}; | ||||
|  |     std::exit(EXIT_FAILURE); | ||||
|  |   } | ||||
|  |   return *east; | ||||
|  | } | ||||
|  | 
 | ||||
|  | cell cell::getSouth(const std::vector<cell> &grid) const { | ||||
|  |   auto south = std::find_if(grid.begin(), grid.end(), [this](const cell &c) { | ||||
|  |         return this->row + 1 == c.row && this->column == c.column; | ||||
|  |       }); | ||||
|  |   if(south == grid.end()) { | ||||
|  |     throw std::logic_error{ "Cannot get cell south of (" + std::to_string(row) + "," + std::to_string(column) + ")"}; | ||||
|  |     std::exit(EXIT_FAILURE); | ||||
|  |   } | ||||
|  |   return *south; | ||||
|  | } | ||||
|  | 
 | ||||
|  | cell cell::getWest(const std::vector<cell> &grid) const { | ||||
|  |   auto west = std::find_if(grid.begin(), grid.end(), [this](const cell &c) { | ||||
|  |         return this->row == c.row && this->column - 1 == c.column; | ||||
|  |       }); | ||||
|  |   if(west == grid.end()) { | ||||
|  |     throw std::logic_error{ "Cannot get cell west of (" + std::to_string(row) + "," + std::to_string(column) + ")"}; | ||||
|  |     std::exit(EXIT_FAILURE); | ||||
|  |   } | ||||
|  |   return *west; | ||||
|  | } | ||||
|  | 
 | ||||
|  | coordinates cell::getCoordinates() const { | ||||
|  |   return std::make_pair(row, column); | ||||
|  | } | ||||
|  | 
 | ||||
|  | std::string cell::getColor() const { | ||||
|  |   switch(color) { | ||||
|  |     case Color::Red:    return "red"; | ||||
|  |     case Color::Green:  return "green"; | ||||
|  |     case Color::Blue:   return "blue"; | ||||
|  |     case Color::Purple: return "purple"; | ||||
|  |     case Color::Yellow: return "yellow"; | ||||
|  |     case Color::None:   return "transparent"; | ||||
|  |     default: return ""; | ||||
|  |     //case Color::Grey   = 'G',
 | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | std::string getColor(Color color) { | ||||
|  |   switch(color) { | ||||
|  |     case Color::Red:    return "red"; | ||||
|  |     case Color::Green:  return "green"; | ||||
|  |     case Color::Blue:   return "blue"; | ||||
|  |     case Color::Purple: return "purple"; | ||||
|  |     case Color::Yellow: return "yellow"; | ||||
|  |     case Color::None:   return "transparent"; | ||||
|  |     default: return ""; | ||||
|  |     //case Color::Grey   = 'G',
 | ||||
|  |   } | ||||
|  | } | ||||
| @ -0,0 +1,62 @@ | |||||
|  | #pragma once | ||||
|  | 
 | ||||
|  | #include <iostream> | ||||
|  | #include <utility> | ||||
|  | #include <vector> | ||||
|  | 
 | ||||
|  | typedef std::pair<int, int> coordinates; | ||||
|  | 
 | ||||
|  | class Grid; | ||||
|  | 
 | ||||
|  | enum class Type : char { | ||||
|  |   Wall       = 'W', | ||||
|  |   Floor      = ' ', | ||||
|  |   Door       = 'D', | ||||
|  |   LockedDoor = 'L', | ||||
|  |   Key        = 'K', | ||||
|  |   Ball       = 'A', | ||||
|  |   Box        = 'B', | ||||
|  |   Goal       = 'G', | ||||
|  |   Lava       = 'V', | ||||
|  |   Agent      = 'X', | ||||
|  |   Adversary  = 'Z', | ||||
|  |   SlipperyNorth = 'n', | ||||
|  |   SlipperySouth = 's', | ||||
|  |   SlipperyEast  = 'e', | ||||
|  |   SlipperyWest  = 'w' | ||||
|  | }; | ||||
|  | enum class Color : char { | ||||
|  |   Red    = 'R', | ||||
|  |   Green  = 'G', | ||||
|  |   Blue   = 'B', | ||||
|  |   Purple = 'P', | ||||
|  |   Yellow = 'Y', | ||||
|  |   //Grey   = 'G', | ||||
|  |   None   = ' ' | ||||
|  | }; | ||||
|  | 
 | ||||
|  | constexpr std::initializer_list<Color> allColors = {Color::Red, Color::Green, Color::Blue, Color::Purple, Color::Yellow}; | ||||
|  | std::string getColor(Color color); | ||||
|  | 
 | ||||
|  | class cell { | ||||
|  |   public: | ||||
|  |     coordinates getNorth() const { return std::make_pair(row - 1, column); } | ||||
|  |     coordinates getSouth() const { return std::make_pair(row + 1, column); } | ||||
|  |     coordinates getEast()  const { return std::make_pair(row, column + 1); } | ||||
|  |     coordinates getWest()  const { return std::make_pair(row, column - 1); } | ||||
|  | 
 | ||||
|  |     cell getNorth(const std::vector<cell> &grid) const; | ||||
|  |     cell getEast(const std::vector<cell> &grid) const; | ||||
|  |     cell getSouth(const std::vector<cell> &grid) const; | ||||
|  |     cell getWest(const std::vector<cell> &grid) const; | ||||
|  | 
 | ||||
|  |     friend std::ostream& operator<<(std::ostream& os, const cell& cell); | ||||
|  | 
 | ||||
|  |     coordinates getCoordinates() const; | ||||
|  |     std::string getColor() const; | ||||
|  | 
 | ||||
|  |     int row; | ||||
|  |     int column; | ||||
|  |     Type type; | ||||
|  |     Color color; | ||||
|  | }; | ||||
						
							
						
						
							1331
	
						
						util/popl.hpp
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue