Пример #1
0
        public int GetDestinationCost(Pos destination)
        {
            openList.Clear();
            closedList.Clear();

            int _destinationX = destination.x;
            int _destinationY = destination.y;

            openList.Add(globalMap[gameInfo.myHero.pos.x, gameInfo.myHero.pos.y]);

            PathfinderTile lastTileAddedToClosedList;

            do
            {
                AddLowestHeuristicToClosedListFromOpenList(_destinationX, _destinationY);
                lastTileAddedToClosedList = closedList.ElementAt(closedList.Count - 1);
                openList.Remove(lastTileAddedToClosedList);
                AddSurroundingTilesToOpenList(lastTileAddedToClosedList.x, lastTileAddedToClosedList.y, globalMap[_destinationX, _destinationY]);
            } while (openList.Count > 0 && (lastTileAddedToClosedList.x != _destinationX || lastTileAddedToClosedList.y != _destinationY));

            if (openList.Count == 0)
                return 9999;

            List<PathfinderTile> finalPath = new List<PathfinderTile>();

            do
            {
                finalPath.Add(lastTileAddedToClosedList);
                lastTileAddedToClosedList = lastTileAddedToClosedList.parent;
            } while (lastTileAddedToClosedList != null);

            finalPath.RemoveAt(finalPath.Count - 1);

            return finalPath.Count;
        }
            public TargetInfo(Pos pos, int distance, Tile tile)
            {
                Debug.Assert(pos != null);

                this.pos = pos;
                this.distance = distance;
                this.tile = tile;
            }
 public PathData pathTo(Pos target, Pos currentLocation, Tile[][] board, int spikeCost = 5)
 {
     PathData pathData = null;
     foreach (IPathfinder pathfinder in pathfinders) {
         PathData newPathData = pathfinder.pathTo(target, currentLocation, board, spikeCost);
         if (pathData == null || pathData.lostHealth > newPathData.lostHealth) {
             pathData = newPathData;
         }
     }
     return pathData;
 }
Пример #4
0
        public PathData pathTo(Pos target, Pos currentLocation, Tile[][] board, int spikeCost = 5)
        {
            Dictionary<string, InternalTile> Navigated = new Dictionary<string, InternalTile>();
            HashSet<InternalTile> Closed = new HashSet<InternalTile>();

            InternalTile beginning = new InternalTile() { TilePos = currentLocation, Weight = 0 };
            HashSet<InternalTile> Opened = new HashSet<InternalTile> {
                beginning
            };

            Dictionary<string, int> Scores = new Dictionary<string, int> {
                {GetKey(beginning.TilePos.x, beginning.TilePos.y), beginning.Weight}
            };


            Dictionary<string, float> FullScores = new Dictionary<string, float> {
                {GetKey(beginning.TilePos.x, beginning.TilePos.y), GetDistance(currentLocation, target)}
            };

            while (Opened.Any()) {
                InternalTile lowest = Opened.First(tile => GetKey(tile.TilePos.x, tile.TilePos.y) == GetLowestCostTile(FullScores, Opened));

                if (lowest.TilePos.x == target.x && lowest.TilePos.y == target.y) {
                    return ReconstructPath(Navigated, target);
                }

                Opened.Remove(lowest);
                Closed.Add(lowest);

                foreach (Pos neighbor in GetNeighbors(lowest.TilePos, board.Length, board[0].Length)) {
                    if (Closed.Any(tile => tile.TilePos.x == neighbor.x && tile.TilePos.y == neighbor.y)) {
                        continue;
                    }

                    string neighborKey = GetKey(neighbor.x, neighbor.y);
                    int curScore = Scores[GetKey(lowest.TilePos.x, lowest.TilePos.y)] + 1;
                    if (!Opened.Any(tile => tile.TilePos.x == neighbor.x && tile.TilePos.y == neighbor.y)) {
                        Opened.Add(new InternalTile { TilePos = new Pos { x = neighbor.x, y = neighbor.y } });
                    } else if (curScore >= (Scores.ContainsKey(neighborKey) ? Scores[neighborKey] : int.MaxValue)) {
                        continue;
                    }

                    Navigated.Add(neighborKey, lowest);
                    Scores.Add(neighborKey, curScore);
                    FullScores.Add(neighborKey, curScore + GetDistance(neighbor, target));
                }
            }

            return null;
        }
        private string OneBestMove(GameState gameState, IPathfinder pathfinder)
        {
            string murderDirection = murderAlgo(gameState);
            if (!string.IsNullOrEmpty(murderDirection)) {
                Console.Out.WriteLine("WARWARWAR");
                return murderDirection;
            }

            // If we suddenly lost a lot of life, maybe we should reconsider.
            if (heroLife.HasValue && heroLife.Value >= (gameState.myHero.life + 20)) {
                Console.WriteLine("EvenBestChoice: LOW ON LIFE! Maybe we were attacked?");
                target = null;
            }
            heroLife = gameState.myHero.life;

            // If we suddenly moved a lot, maybe we should reconsider.
            if (heroPos != null && Pos.DistanceBetween(heroPos, gameState.myHero.pos) >= 2) {
                Console.WriteLine("EvenBestChoice: TELEPORTED! Maybe we were killed?");
                target = null;
            }
            heroPos = gameState.myHero.pos;

            Tuple<PathData, TargetInfo> pathDataAndTarget = null;
            if (target != null) {
                Console.WriteLine("EvenBestChoice: Current target: ({0},{1}) [tile {2}]", target.pos.x, target.pos.y, target.tile);
                pathDataAndTarget = Tuple.Create(pathfinder.pathTo(target.pos, gameState.myHero.pos, gameState.board, SPIKE_COST), target);
            } else {
                // Seek mine if possible, otherwise seek a tavern
                if (gameState.myHero.life >= 35) {
                    pathDataAndTarget = SeekMine(gameState, pathfinder);
                }
                if (pathDataAndTarget == null || pathDataAndTarget.Item1.lostHealth >= gameState.myHero.life) {
                    pathDataAndTarget = SeekTavern(gameState, pathfinder);
                }
            }

            // If this is the last move, release target unless it's a tavern and we're < 90 life
            if (target != null && pathDataAndTarget != null && pathDataAndTarget.Item1.nextDirection != Direction.Stay &&
                Pos.DistanceBetween(target.pos, gameState.myHero.pos) <= 1 && (target.tile != Tile.TAVERN || gameState.myHero.life >= 90)) {

                Console.WriteLine("EvenBestChoice: Reached destination ({0},{1}) [{2}], releasing target",
                    target.pos.x, target.pos.y, target.tile);
                target = null;
            }
            string nextDirection = pathDataAndTarget != null ? pathDataAndTarget.Item1.nextDirection : null;
            return !String.IsNullOrEmpty(nextDirection) ? nextDirection : Direction.Stay;
        }
Пример #6
0
        public string WhatShouldIDo(GameState state)
        {
            gState = state;
            Dictionary<Pos, Tile> POI = new Dictionary<Pos, Tile>();
            numberOfMinePlayer1 = 0;
            numberOfMinePlayer2 = 0;
            numberOfMinePlayer3 = 0;
            numberOfMinePlayer4 = 0;

            for (int i = 0; i < state.board.Length; i++)
            {
                for (int j = 0; j < state.board[i].Length; j++)
                {
                    if (state.board[i][j] != Tile.FREE && state.board[i][j] != Tile.IMPASSABLE_WOOD)
                    {
                        POI.Add(new Pos() { x = i, y = j }, state.board[i][j]);
                    }
                    if (state.board[i][j] == Tile.GOLD_MINE_1)
                        numberOfMinePlayer1++;
                    else if (state.board[i][j] == Tile.GOLD_MINE_2)
                        numberOfMinePlayer2++;
                    else if (state.board[i][j] == Tile.GOLD_MINE_3)
                        numberOfMinePlayer3++;
                    else if (state.board[i][j] == Tile.GOLD_MINE_4)
                        numberOfMinePlayer4++;
                }
            }
            Pos bestPoiPos = new Pos();
            int bestScore = Int32.MaxValue;

            Pathfinder pathfinder = new Pathfinder(state);

            foreach (var poi in POI)
            {
                int cost = WhatsMyScore(pathfinder.GetDestinationCost(poi.Key), poi.Value);
                if (cost < bestScore)
                {
                    bestPoiPos = poi.Key;
                    bestScore = cost;
                }
            }

            return pathfinder.GetNextMoveToGetToDestination(bestPoiPos.x, bestPoiPos.y);
        }
Пример #7
0
        public PathData pathTo(Pos target, Pos currentLocation, Tile[][] board, int spikeCost = 10)
        {
            spikePrice = spikeCost;
            //int resultCost = 0;
            PathData pathData = new PathData();
            int size = board.GetLength(0);
            int[][] pointValues = new int[size][];
            for (int x = 0; x < size; x++) 
            {
               pointValues[x] = new int[size];
            }
            pointValues[currentLocation.x][currentLocation.y] = 1;
            SortedList<int, Pos> newMarkedPoints = new SortedList<int, Pos>(new DuplicateKeyComparer<int>());
            newMarkedPoints.Add(1, currentLocation);
            size--;
            while (newMarkedPoints.Count() != 0) {
                Pos pos = newMarkedPoints.First().Value;
                newMarkedPoints.RemoveAt(0);
                int basecost = pointValues[pos.x][pos.y];
                int x;
                int y;
                x = pos.x;
                y = pos.y + 1;
                if(x<= size && x >=0 && y <= size && y >=0) {
                    if (target.x == x && target.y == y) {
                        pathData.distance = tilePrice(board[x][y]) + basecost + 1;
                        break;
                    }
                    if (tilePrice(board[x][y]) != -1 && pointValues[x][y] == 0) {
                        pointValues[x][y] = tilePrice(board[x][y]) + basecost + 1;
                        newMarkedPoints.Add(pointValues[x][y], new Pos(x, y));
                    }
                }
                x = pos.x + 1;
                y = pos.y;
                if(x<= size && x >=0 && y <= size && y >=0) {
                    if (target.x == x && target.y == y) {
                        pathData.distance = tilePrice(board[x][y]) + basecost + 1;
                        break;
                    }
                    if (tilePrice(board[x][y]) != -1 && pointValues[x][y] == 0) {
                        pointValues[x][y] = tilePrice(board[x][y]) + basecost + 1;
                        newMarkedPoints.Add(pointValues[x][y], new Pos(x, y));
                    }
                }
                x = pos.x - 1;
                y = pos.y;
                if(x<= size && x >=0 && y <= size && y >=0) {
                    if (target.x == x && target.y == y) {
                        pathData.distance = tilePrice(board[x][y]) + basecost + 1;
                        break;
                    }
                    if (tilePrice(board[x][y]) != -1 && pointValues[x][y] == 0) {
                        pointValues[x][y] = tilePrice(board[x][y]) + basecost + 1;
                        newMarkedPoints.Add(pointValues[x][y], new Pos(x, y));
                    }
                }
                x = pos.x;
                y = pos.y - 1;
                if(x<= size && x >=0 && y <= size && y >=0) {
                    if (target.x == x && target.y == y) {
                        pathData.distance = tilePrice(board[x][y]) + basecost + 1;
                        break;
                    }
                    if (tilePrice(board[x][y]) != -1 && pointValues[x][y] == 0) {
                        pointValues[x][y] = tilePrice(board[x][y]) + basecost + 1;
                        newMarkedPoints.Add(pointValues[x][y], new Pos(x, y));
                    }
                }
            }
            //Console.Out.WriteLine(resultCost);

            //backtrace
            Pos currentPos = target;
            while (true) {
                //Console.Out.WriteLine(currentPos.x + "," + currentPos.y);
                int x, y, a=99999,b=99999,c=99999,d=99999;
                
                x = currentPos.x - 1;
                y = currentPos.y;
                if (x <= size && x >= 0 && y <= size && y >= 0) {
                    if (currentLocation.x == x && currentLocation.y == y) {
                        pathData.nextDirection = Direction.South;
                        break;
                    }
                    a = pointValues[x][y];

                }
                    x = currentPos.x;
                    y = currentPos.y - 1;
                if (x <= size && x >= 0 && y <= size && y >= 0) {
                    if (currentLocation.x == x && currentLocation.y == y) {
                        pathData.nextDirection = Direction.East;
                        break;
                    }
                    b = pointValues[x][y];
                }

                x = currentPos.x;
                y = currentPos.y + 1;
                    if (x <= size && x >= 0 && y <= size && y >= 0) {
                    if (currentLocation.x == x && currentLocation.y == y) {
                        pathData.nextDirection = Direction.West;
                        break;
                    }
                    c = pointValues[x][y];
                }

                x = currentPos.x + 1;
                y = currentPos.y;
                if (x <= size && x >= 0 && y <= size && y >= 0) {
                    if (currentLocation.x == x && currentLocation.y == y) {
                        pathData.nextDirection = Direction.North;
                        break;
                    }
                    d = pointValues[x][y];
                }
                if (a == 0) { a = 10000; }
                if (b == 0) { b = 10000; }
                if (c == 0) { c = 10000; }
                if (d == 0) { d = 10000; }
                try {
                    if (a <= b && a <= c && a <= d) {
                        pointValues[currentPos.x - 1][currentPos.y] = 123456789;// taken path
                        currentPos = new Pos(currentPos.x - 1, currentPos.y);
                    } else if (b <= a && b <= c && b <= d) {
                        pointValues[currentPos.x][currentPos.y - 1] = 123456789;
                        currentPos = new Pos(currentPos.x, currentPos.y - 1);
                    } else if (c <= b && c <= a && c <= d) {
                        pointValues[currentPos.x][currentPos.y + 1] = 123456789;
                        currentPos = new Pos(currentPos.x, currentPos.y + 1);
                    } else if (d <= b && d <= c && d <= a) {
                        pointValues[currentPos.x + 1][currentPos.y] = 123456789;
                        currentPos = new Pos(currentPos.x + 1, currentPos.y);
                    }
                } catch (Exception) {
                    Console.Out.WriteLine("Couldn't find path and had to abandon.");
                    return pathData;
                } 
            }
            Console.Out.WriteLine("Move to " + pathData.nextDirection + " with cost " + pathData.distance + " to go to" + target.x + "," + target.y);
            pathData.lostHealth = pathData.distance;
            return pathData;
        }
        public static int DistanceBetween(Pos p1, Pos p2)
        {
            Debug.Assert(p1 != null);
            Debug.Assert(p2 != null);

            int xDist = p1.x < p2.x ? p2.x - p1.x : p1.x - p2.x;
            int yDist = p1.y < p2.y ? p2.y - p1.y : p1.y - p2.y;
            return xDist + yDist;
        }
Пример #9
0
        private PathData ReconstructPath(Dictionary<string, InternalTile> navigated,
            Pos current)
        {
            Stack<Pos> totalPath = new Stack<Pos>();
            totalPath.Push(current);

            while (navigated.ContainsKey(GetKey(current.x, current.y))) {
                current = navigated[GetKey(current.x, current.y)].TilePos;
                totalPath.Push(current);
            }

            return new PathData { distance = navigated.Count, lostHealth = 0, nextDirection = GetDirectionOfPos(totalPath.Pop(), totalPath.Pop()) };
        }
Пример #10
0
 public float GetDistance(Pos a,
     Pos b)
 {
     return (float) Math.Sqrt(Math.Pow(Math.Abs(b.x - a.x), 2) + Math.Pow(Math.Abs(b.y - a.y), 2));
 }
Пример #11
0
        private List<Pos> GetNeighbors(Pos current, int maxX, int maxY)
        {
            List<Pos> lst = new List<Pos>();

            if (current.x + 1 < maxX)
                lst.Add(new Pos { x = current.x + 1, y = current.y });

            if (current.x - 1 >= 0) {
                lst.Add(new Pos { x = current.x - 1, y = current.y });
            }

            if (current.y + 1 < maxY) {
                lst.Add(new Pos { x = current.x, y = current.y + 1 });
            }

            if(current.y - 1 >= 0)
                lst.Add(new Pos { x = current.x, y = current.y - 1 });

            return lst;
        }
Пример #12
0
        private string GetDirectionOfPos(Pos a,
            Pos b)
        {
            if (a.x > b.x) {
                return Direction.North;
            }

            if (a.x < b.x) {
                return Direction.South;
            }

            if (a.y > b.y) {
                return Direction.West;
            }

            if(a.y < b.y)
                return Direction.East;

            return Direction.Stay;
        }
        private Tuple<PathData, TargetInfo> SeekTiles(GameState gameState, IPathfinder pathfinder, int tileCost, params Tile[] soughtTiles)
        {
            // Scan game board and find path data to all matching tiles
            List<Tuple<Pos, Tile, PathData>> moves = new List<Tuple<Pos, Tile, PathData>>();
            SortedSet<Tile> tiles = new SortedSet<Tile>(soughtTiles);
            for (int x = 0; x < gameState.board.Length; ++x) {
                for (int y = 0; y < gameState.board[x].Length; ++y) {
                    Tile tile = gameState.board[x][y];
                    if (tiles.Contains(tile)) {
                        Pos pos = new Pos(x, y);
                        PathData curPathData = pathfinder.pathTo(pos, gameState.myHero.pos, gameState.board, SPIKE_COST);
                        
                        // Fix health if we don't have one
                        if (curPathData.lostHealth == 0) {
                            curPathData.lostHealth = curPathData.distance;
                        }

                        // Add tile cost to health cost
                        curPathData.lostHealth += tileCost;
                        
                        // Add potential target.
                        moves.Add(Tuple.Create(pos, tile, curPathData));
                    }
                }
            }

            // Seek to minimize lost health.
            moves.Sort((a, b) => a.Item3.lostHealth - b.Item3.lostHealth);

            // Find a move that will take us to the target.
            Tuple<PathData, TargetInfo> res = null;
            if (moves.Count != 0 && moves[0].Item3.distance < 1000) {
                res = Tuple.Create(moves[0].Item3, new TargetInfo(moves[0].Item1, moves[0].Item3.distance, moves[0].Item2));
                if (res.Item1.lostHealth >= gameState.myHero.life) {
                    Console.WriteLine("EvenBestChoice: WARNING: current choice will kill us: costs {0}, remaining life {1}",
                        res.Item1.lostHealth, gameState.myHero.life);
                }
            }
            if (res != null && res.Item1 == null) {
                res = null;
            }
            return res;
        }
Пример #14
0
        static void Main(string[] args)
        {
            AStar lol = new AStar();

            float dist = lol.GetDistance(new Pos { x=4, y=4 }, new Pos { x = 0, y = 0 });
            Console.WriteLine(dist);


            Tile[][] tiles = {
                new [] { Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE },
                new [] { Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE },
                new [] { Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE },
                new [] { Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE },
                new [] { Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE, Tile.FREE }
            };

            foreach (Tile[] row in tiles) {
                foreach (Tile tile in row) {
                    Console.Write(tile);
                }
                Console.WriteLine();
            }

            

            PathData result = lol.pathTo(new Pos { x = 0, y = 0 }, new Pos { x = 4, y = 4 }, tiles);
            Console.WriteLine("Dist:{0} - Direction: {1}", result.distance, result.nextDirection);

            result = lol.pathTo(new Pos { x = 4, y = 0 }, new Pos { x = 4, y = 4 }, tiles);
            Console.WriteLine("Dist:{0} - Direction: {1}", result.distance, result.nextDirection);

            result = lol.pathTo(new Pos { x = 0, y = 4 }, new Pos { x = 4, y = 4 }, tiles);
            Console.WriteLine("Dist:{0} - Direction: {1}", result.distance, result.nextDirection);

            result = lol.pathTo(new Pos { x = 4, y = 4 }, new Pos { x = 4, y = 0 }, tiles);
            Console.WriteLine("Dist:{0} - Direction: {1}", result.distance, result.nextDirection);

            result = lol.pathTo(new Pos { x = 4, y = 4 }, new Pos { x = 0, y = 4 }, tiles);
            Console.WriteLine("Dist:{0} - Direction: {1}", result.distance, result.nextDirection);

            result = lol.pathTo(new Pos { x = 4, y = 4 }, new Pos { x = 0, y = 0 }, tiles);
            Console.WriteLine("Dist:{0} - Direction: {1}", result.distance, result.nextDirection);

            Console.WriteLine("=====================");
            Pos cur = new Pos() {x = 0, y=0};
            Pos target = new Pos() {x = 4, y=4};

            int nbTours = 0;

            while (cur.x != target.x || cur.y != target.y) {
                result = lol.pathTo(target, cur, tiles);

                switch(result.nextDirection) {
                    case Direction.East:
                        cur.y += 1;
                        break;
                    case Direction.West:
                        cur.y -= 1;
                        break;
                    case Direction.North:
                        cur.x -= 1;
                        break;
                    case Direction.South:
                        cur.x += 1;
                        break;
                }

                Console.WriteLine("Dist:{0} - Direction: {1}", result.distance, result.nextDirection);
                Console.WriteLine("CurPos = {0}-{1}", cur.x, cur.y);

                if (nbTours++ > 10) {
                    break;
                }
            }

            Console.ReadKey();
        }