#include "Grid.h" #include Grid::Grid(cells gridCells, cells background, const GridOptions &gridOptions, const std::map &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(cell.type) << static_cast(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 agentNames; std::transform(agentNameAndPositionMap.begin(), agentNameAndPositionMap.end(), std::back_inserter(agentNames), [](const std::map::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 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 Grid::getWalkableDirOf8Neighborhood(cell c) /* const */ { return (std::array) { !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()) }; }