public override Dictionary <QFeature, decimal> GetFeatures(QAction action) { Point self = ((Maze_With_No_Walls)GetNewState(action)).self; QSearch qsearch = new QSearch(this); Maze_With_No_Walls simpleMaze = new Maze_With_No_Walls() { maze = maze, self = self, goal = goal, width = width, height = height }; QSearchResult bestPath = qsearch.AStar(simpleMaze); return(QFeature_String.FromStringDecimalDictionary(new Dictionary <string, decimal>() { //{this.GetHashCode().ToString()+"_"+action, 1}, // Identity to convert this back to QLearning { "Goal", goal == self? 1:0 }, { "Distance_To_Goal", bestPath == null? 1:(decimal)bestPath.Count / (decimal)(width * height) }, })); }
public override Dictionary <QFeature, decimal> GetFeatures(QAction action) { int newVal = value; if (action == UP) { newVal++; } else { newVal--; } return(QFeature_String.FromStringDecimalDictionary(new Dictionary <string, decimal>() { //{value.ToString()+"_"+action, 1}, // Identity for sanity check //{"Distance", (decimal)Math.Abs(end-newVal)} { "Distance_Change", Math.Abs(end - newVal) - Math.Abs(end - value) } })); }
public override Dictionary <QFeature, decimal> GetFeatures(QAction action) { Point self = ((Maze)GetNewState(action)).self; QSearch qsearch = new QSearch(this); Maze simpleMaze = new Maze() { maze = maze, self = self, goal = goal, width = width, height = height, walls = walls.ToArray() }; QSearchResult bestPath = qsearch.AStar(simpleMaze); List <Point> bestOppMoves = new List <Point>(); foreach (Point o in opponent) { bestOppMoves.Add(o); bestOppMoves.Add(new Point(o.X + 1, o.Y)); bestOppMoves.Add(new Point(o.X - 1, o.Y)); bestOppMoves.Add(new Point(o.X, o.Y + 1)); bestOppMoves.Add(new Point(o.X, o.Y - 1)); } foreach (Point o in bestOppMoves.ToArray()) { bestOppMoves.Add(new Point(o.X + 1, o.Y)); bestOppMoves.Add(new Point(o.X - 1, o.Y)); bestOppMoves.Add(new Point(o.X, o.Y + 1)); bestOppMoves.Add(new Point(o.X, o.Y - 1)); } Maze safeMaze = new Maze() { maze = maze, self = self, goal = goal, width = width, height = height, walls = walls.Concat(bestOppMoves).ToArray() }; QSearchResult safePath = qsearch.AStar(safeMaze); Dictionary <string, decimal> features = new Dictionary <string, decimal>() { //{this.GetHashCode().ToString()+"_"+action, 1}, // Identity to convert this back to QLearning { "Goal", goal == self? 1:0 }, { "Direct_Distance_To_Goal", bestPath == null? 1:(decimal)bestPath.Count / (decimal)(width * height) }, { "Safe_Distance_To_Goal", (safePath == null? 1: (decimal)safePath.Count / (decimal)(width * height)) } }; decimal distanceToOpponent = decimal.MaxValue; if (opponent.Any()) { features["Opponent"] = goal != self && opponent.Where(p => (Math.Abs(p.X - self.X) <= 1 && p.Y == self.Y) || (Math.Abs(p.Y - self.Y) <= 1 && p.X == self.X)).Any() ? 1 : 0; distanceToOpponent = opponent.Select(o => qsearch.AStar(new Maze() { maze = maze, self = self, goal = o, width = width, height = height, walls = walls })).Select(x => x == null? width * height:x.Count).Min(); features["Distance_To_Opponent"] = distanceToOpponent >= 5? 1:distanceToOpponent / (decimal)(width * height); if (goal != self) { Maze deadEnd = new Maze() { maze = maze, self = self, goal = goal, width = width, height = height, walls = walls.Concat(new Point[] { new Point(this.self.X - 1, this.self.Y), new Point(this.self.X + 1, this.self.Y), new Point(this.self.X, this.self.Y - 1), new Point(this.self.X, this.self.Y + 1) }).ToArray() }; QSearchResult deadPath = qsearch.Depth_First(deadEnd); if (deadPath == null) { features["Dead_End"] = 1; } } } return(QFeature_String.FromStringDecimalDictionary(features)); }