/// <summary> /// Prints the best path /// </summary> private static void PrintPath(MazeEnvironment environment, MazeAgent agent) { var learner = agent.Learner as QLearning <MazeState>; var path = new HashSet <MazeState>(); MazeState state = environment.GetDefaultState(agent); path.Add(state); while (true) { MazeAction action = (MazeAction)learner.SelectAction(state); switch (action) { case MazeAction.Up: state = state.Add(y: -1); break; case MazeAction.Down: state = state.Add(y: 1); break; case MazeAction.Right: state = state.Add(x: 1); break; case MazeAction.Left: state = state.Add(x: -1); break;; } path.Add(state); if (environment.Tiles[state.PositionX, state.PositionY] == MazeTile.Goal) { break; } } for (int y = 0; y < environment.Length; y++) { for (int x = 0; x < environment.Width; x++) { switch (environment.Tiles[x, y]) { case MazeTile.Floor: if (path.Contains(new MazeState(x, y))) { Console.Write("x"); } else { Console.Write(" "); } break; case MazeTile.Wall: Console.Write("W"); break; case MazeTile.Agent: Console.Write("A"); break; case MazeTile.Goal: Console.Write("G"); break; } } Console.WriteLine(); } }
/// <summary> /// Executes the given action for the given agent /// </summary> /// <param name="agent">The agent</param> /// <param name="actionNumber">The index of the action</param> /// <param name="episode">The current episode number</param> public override void Execute(MazeAgent agent, int actionNumber, int episode) { MazeAction action = (MazeAction)actionNumber; int newPosX = agent.State.PositionX; int newPosY = agent.State.PositionY; switch (action) { case MazeAction.Up: newPosY--; break; case MazeAction.Down: newPosY++; break; case MazeAction.Right: newPosX++; break; case MazeAction.Left: newPosX--; break; } //Check if the new position is valid bool valid = true; if ((newPosX >= 0 && newPosX < this.Width) && (newPosY >= 0 && newPosY < this.Length)) { var newTileType = this.tiles[newPosX, newPosY]; if (newTileType != MazeTile.Wall) { var newState = new MazeState(newPosX, newPosY); bool isTerminal = newTileType == MazeTile.Goal; //Update the world & agent this.tiles[agent.State.PositionX, agent.State.PositionY] = MazeTile.Floor; this.tiles[newPosX, newPosY] = MazeTile.Agent; agent.State = newState; //Calculate the reward agent.Reward(this.CalculateReward(isTerminal), isTerminal, episode); } else { valid = false; } } else { valid = false; } if (!valid) { agent.State = agent.State; agent.Reward(this.CalculateReward(false), false, episode); } }