/// <summary> /// Check if the move is valid, i.e. not colliding into walls or other agents. /// </summary> /// <param name="possibleMove">The proposed move (to check if it is valid)</param> /// <param name="agentNum">The index of the agent that is proposed to perform the move</param> /// <param name="previousAgentMoves">A collection of moves that will be done by the other agents</param> /// <returns></returns> private bool IsValid(Move possibleMove, int agentNum, ICollection <Move> previousAgentMoves) { // If the tile is not free (out of the grid or with an obstacle) if (m_Problem.IsValid(possibleMove) == false) { return(false); } // If previous move of another agent will collide with this move if (previousAgentMoves.Contains(possibleMove) || previousAgentMoves.Contains(possibleMove.GetOppositeMove())) { return(false); } return(true); }
private void Generate ( MAM_AgentState node, MAM_AgentState child ) { if (expandedNodes.Contains(child)) { return; } Move childMove = child.lastMove; if (!instance.IsValid(childMove)) // Not a valid location { return; } if (!closed(child)) { if (child.f >= getBestCost()) { return; } child.numOfAgentsInBestHeuristic = instance.m_vAgents.Length; if (openList.Contains(child)) { child.h = ((MAM_AgentState)openList.Get(child)).h; child.heuristics = ((MAM_AgentState)openList.Get(child)).heuristics; } else { CalculateH(child, node); } CalculateF(child); openList.Add(child); UpdateBestCost(child); nodesGenerated++; } }
/// <summary> /// Generates a problem instance based on a DAO map file. /// TODO: Fix code dup with GenerateProblemInstance and Import later. /// </summary> /// <param name="agentsNum"></param> /// <returns></returns> public ProblemInstance GenerateDragonAgeProblemInstance(string mapFileName, int agentsNum) { /** * Randomization based on timer is disabled for purposes of getting * reproducible experiments. */ //Random rand = new Random(); m_mapFileName = mapFileName; m_agentNum = agentsNum; TextReader input = new StreamReader(mapFileName); string[] lineParts; string line; line = input.ReadLine(); Debug.Assert(line.StartsWith("type octile")); // Read grid dimensions line = input.ReadLine(); lineParts = line.Split(' '); Debug.Assert(lineParts[0].StartsWith("height")); int maxX = int.Parse(lineParts[1]); line = input.ReadLine(); lineParts = line.Split(' '); Debug.Assert(lineParts[0].StartsWith("width")); int maxY = int.Parse(lineParts[1]); line = input.ReadLine(); Debug.Assert(line.StartsWith("map")); bool[][] grid = new bool[maxX][]; char cell; for (int i = 0; i < maxX; i++) { grid[i] = new bool[maxY]; line = input.ReadLine(); for (int j = 0; j < maxY; j++) { cell = line.ElementAt(j); if (cell == '@' || cell == 'O' || cell == 'T' || cell == 'W' /* Water isn't traversable from land */) { grid[i][j] = true; } else { grid[i][j] = false; } } } int x; int y; Agent[] agentGoals = new Agent[agentsNum]; AgentState[] agentStates = new AgentState[agentsNum]; bool[][] goals = new bool[maxX][]; for (int i = 0; i < maxX; i++) { goals[i] = new bool[maxY]; } // Choose random valid unclaimed goal locations for (int i = 0; i < agentsNum; i++) { x = rand.Next(maxX); y = rand.Next(maxY); if (goals[x][y] || grid[x][y]) { i--; } else { goals[x][y] = true; agentGoals[i] = new Agent(x, y, i); } } // Select random start/goal locations for every agent by performing a random walk for (int i = 0; i < agentsNum; i++) { agentStates[i] = new AgentState(agentGoals[i].Goal.x, agentGoals[i].Goal.y, agentGoals[i]); } ProblemInstance problem = new ProblemInstance(); problem.parameters[ProblemInstance.GRID_NAME_KEY] = Path.GetFileNameWithoutExtension(mapFileName); problem.Init(agentStates, grid); for (int j = 0; j < RANDOM_WALK_STEPS; j++) { for (int i = 0; i < agentsNum; i++) { goals[agentStates[i].lastMove.x][agentStates[i].lastMove.y] = false; // We're going to move the goal somewhere else // Move in a random legal direction: while (true) { Move.Direction op = (Move.Direction)rand.Next(0, 5); // TODO: fixme agentStates[i].lastMove.Update(op); if (problem.IsValid(agentStates[i].lastMove) && !goals[agentStates[i].lastMove.x][agentStates[i].lastMove.y]) // This spot isn't another agent's goal { break; } else { agentStates[i].lastMove.setOppositeMove(); // Rollback } } goals[agentStates[i].lastMove.x][agentStates[i].lastMove.y] = true; // Claim agent's new goal } } // Zero the agents' timesteps foreach (AgentState agentStart in agentStates) { agentStart.lastMove.time = 0; } return(problem); }
/// <summary> /// Generates a problem instance, including a board, start and goal locations of desired number of agents /// and desired precentage of obstacles /// TODO: Refactor to use operators. /// </summary> /// <param name="gridSize"></param> /// <param name="agentsNum"></param> /// <param name="obstaclesNum"></param> /// <returns></returns> public ProblemInstance GenerateProblemInstance(int gridSize, int agentsNum, int obstaclesNum) { m_mapFileName = "GRID" + gridSize + "X" + gridSize; m_agentNum = agentsNum; /** * Randomization based on timer is disabled for purposes of getting * reproducible experiments. */ //Random rand = new Random(); if (agentsNum + obstaclesNum + 1 > gridSize * gridSize) { throw new Exception("Not enough room for " + agentsNum + ", " + obstaclesNum + " and one empty space in a " + gridSize + "x" + gridSize + "map."); } int x; int y; Agent[] aGoals = new Agent[agentsNum]; AgentState[] aStart = new AgentState[agentsNum]; bool[][] grid = new bool[gridSize][]; bool[][] goals = new bool[gridSize][]; // Generate a random grid for (int i = 0; i < gridSize; i++) { grid[i] = new bool[gridSize]; goals[i] = new bool[gridSize]; } for (int i = 0; i < obstaclesNum; i++) { x = rand.Next(gridSize); y = rand.Next(gridSize); if (grid[x][y]) // Already an obstacle { i--; } grid[x][y] = true; } // Choose random goal locations for (int i = 0; i < agentsNum; i++) { x = rand.Next(gridSize); y = rand.Next(gridSize); if (goals[x][y] || grid[x][y]) { i--; } else { goals[x][y] = true; aGoals[i] = new Agent(x, y, i); } } // Select random start/goal locations for every agent by performing a random walk for (int i = 0; i < agentsNum; i++) { aStart[i] = new AgentState(aGoals[i].Goal.x, aGoals[i].Goal.y, aGoals[i]); } // Initialized here only for the IsValid() call. TODO: Think how this can be sidestepped elegantly. ProblemInstance problem = new ProblemInstance(); problem.Init(aStart, grid); for (int j = 0; j < RANDOM_WALK_STEPS; j++) { for (int i = 0; i < agentsNum; i++) { goals[aStart[i].lastMove.x][aStart[i].lastMove.y] = false; // We're going to move the goal somewhere else while (true) { Move.Direction op = (Move.Direction)rand.Next(0, 5); // TODO: fixme aStart[i].lastMove.Update(op); if (problem.IsValid(aStart[i].lastMove) && !goals[aStart[i].lastMove.x][aStart[i].lastMove.y]) // this spot isn't another agent's goal { break; } else { aStart[i].lastMove.setOppositeMove(); // Rollback } } goals[aStart[i].lastMove.x][aStart[i].lastMove.y] = true; // Claim agent's new goal } } // Zero the agents' timesteps foreach (AgentState agentStart in aStart) { agentStart.lastMove.time = 0; } // TODO: There is some repetition here of previous instantiation of ProblemInstance. Think how to elegantly bypass this. problem = new ProblemInstance(); problem.Init(aStart, grid); return(problem); }