public override QState Run(QState currentState, int trialNum, decimal learn, decimal discount, decimal explore)
 {
     QSearch qsearch = new QSearch(this);
     QSearchResult actions = qsearch.Breadth_First(currentState, true);
     if (actions != null)
     {
         foreach (QAction action in actions.actionsList)
         {
             if (!currentState.IsEnd() && isRunning && currentState.GetActions().Contains(action))
             {
                 WriteOutput(currentState + ": " + action);
                 QState newState = currentState.GetNewState(action);
                 newState.Inherit(currentState);
                 newState.Step();
                 currentState = newState;
             }
         }
         if (currentState.IsEnd()) WriteOutput(currentState + ": End");
         else
         {
             WriteOutput("Existing solution no longer applicable.  Re-solving...");
             return Run(currentState, trialNum, learn, discount, explore);
         }
     }
     else WriteOutput("No solution found.", true);
     return currentState;
 }
Exemple #2
0
        public override QState Initialize()
        {
            WriteOutput("Dimensions: " + width + "x" + height);
            self = new Point(start.X, start.Y);
            score = 0;

            walls = new Point[] { };

            // Generate Walls Randomly
            if (wallDensity > 0)
            {
                
                HashSet<Point> bestPathSoFar = new HashSet<Point>();
                WriteOutput("Generating walls randomly with density target of " + wallDensity + "...");
                for (int w = 0; w < width; w++)
                {
                    for (int h = 0; h < height; h++)
                    {
                        double r = random.NextDouble();
                        //WriteOutput("Wall Probability for " + w + "x" + h + ": " + r+" vs threshold "+walls);
                        if (r < wallDensity)
                        {
                            //WriteOutput("Wall created at " + w + "x" + h);
                            Point newWall = new Point(w, h);
                            if (start == newWall || goal == newWall) continue;
                            Point[] tempWalls = walls.Concat(new Point[] { newWall }).ToArray();
                            QState tempState = new Maze() { maze = maze, self = self, goal = goal, width = width, height = height, walls = tempWalls};
                            if (!bestPathSoFar.Any() || bestPathSoFar.Contains(newWall))
                            {
                                QSearchResult path = new QSearch().AStar(tempState);
                                if (path != null)
                                {
                                    bestPathSoFar.Clear();
                                    foreach (QState q in path.QStatesList)
                                        bestPathSoFar.Add(((Maze)q).self);
                                    walls = tempWalls;
                                }
                            }
                            else walls = tempWalls;
                        }

                    }
                }
                WriteOutput("Maze generation complete.");
            }

            opponent = new List<Point>();
            for (int i = 0; i < opponents; i++)
                opponent.Add(new Point(goal.X, goal.Y));

            if (!HideOutput)
            {
                ManualResetEvent wait = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(new WaitCallback(CreateGUI), new object[] { width, height, self.X, self.Y, goal.X, goal.Y, walls, this, wait });
                wait.WaitOne();
            }

            return new Maze() { width = width, height = height, self = self, goal = goal, walls = walls, wallDensity = wallDensity, opponent = opponent, opponentDifficulty = opponentDifficulty, random = random, maze = maze, start = start, opponents = opponents, bestOpponentPath = bestOpponentPath, score = score };
        }
        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)},
            });
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        public override void Step()
        {

            if (!HideOutput && maze!=null)
            {
                try
                {
                    maze.SetSelf(self.X, self.Y);
                }
                catch (Exception e)
                {
                    WriteOutput("" + e, true);
                }
            }

            if (opponent.Any() && goal!=self)
            {
                for (int i = 0; i < opponent.Count; i++)
                {
                    QState tempState = new Maze() { maze = maze, self = opponent[i], goal = self, width = width, height = height, walls = walls};
                    QSearchResult opponentPath;
                    if (bestOpponentPath.ContainsKey(tempState)) opponentPath = bestOpponentPath[tempState];
                    else
                    {
                        opponentPath = new QSearch().AStar(tempState);
                        bestOpponentPath[tempState] = opponentPath;
                    }
                    if (opponentPath!=null && opponentPath.Any())
                    {
                        int newX = opponent[i].X, newY = opponent[i].Y;

                        QAction action = opponentPath.actionsList.First();

                        if (random.NextDouble() > opponentDifficulty)
                        {
                            QAction[] allActions = tempState.GetActions();
                            action = allActions.ElementAt(random.Next(allActions.Length));
                        }

                        // Translate decision to new coordinate
                        if (action.ToString() == "up") newY--;
                        else if (action.ToString() == "down") newY++;
                        else if (action.ToString() == "left") newX--;
                        else if (action.ToString() == "right") newX++;

                        //WriteOutput("Moving adversary at " + opponent[i] + " " + action + " to "+newX+", "+newY+"...");
                        opponent[i] = new Point(newX, newY);
                        if (!HideOutput && maze!=null)
                        {
                            maze.SetOpponent(i, newX, newY);
                        }
                    }
                }
            }

            if (goal == self)
            {
                score += 100;
            }
            else if (opponent.Contains(self))
            {
                score -= 100;
            }

            if (!HideOutput && CurrentMode == AWAKEN) Thread.Sleep(100);
        }