示例#1
0
    private static Location GetNearestFreeHighProductionDirection(Map map, short[,] gaussianValueMap, Location startLocation) //TODO: This needs to take into account the allowed directions.
    {
        //I think it should value the production as Max production value - distance * 2....
        //A production value of 10 that is 5 spaces away would be valued at 10 - (5*2) = 0
        //A production value of 10 that is 4 spaces away would be valued at 10 - (4*2) = 2
        //A production value of 7 that is 4 spaces away would be 7-(4*2) = -1
        //A production value of 7 that is 3 spaces away would be 7- (3*2) = 1

        Location?bestDestination        = null;
        var      valueAtBestDestination = short.MinValue;


        DarreksLog.AppendLog(string.Format("GetNearestFreeHighProductionDirection... Active site is [{0},{1}]", startLocation.X, startLocation.Y));

        for (var x = _MaxScanDistance * -1; x <= _MaxScanDistance; x++)
        {
            for (var y = _MaxScanDistance * -1; y <= _MaxScanDistance; y++)
            {
                //DarreksLog.AppendLog("Checking Space Relative By: " + x + ", " + y);

                var mapX = (ushort)((((int)startLocation.X) + x + map.Width) % map.Width);
                var mapY = (ushort)((((int)startLocation.Y) + y + map.Height) % map.Height);

                //DarreksLog.AppendLog(string.Format("Checking map[{0},{1}]...", mapX, mapY));

                var toCheck = map[mapX, mapY];


                if (toCheck.Owner != _MyID)// == 0)
                {
                    //TODO: return this to normal... just for testing I am making this find the closest production zone to me with the max production.

                    short valueToMe;
                    var   temp = (gaussianValueMap[mapX, mapY] - (35 * ((Math.Abs(x) + Math.Abs(y))))); //No matter how awesome a location is, if it's too far away, you'll never get there.
                    if (temp < short.MinValue)
                    {
                        valueToMe = short.MinValue;
                    }
                    else if (temp > short.MaxValue)
                    {
                        valueToMe = short.MaxValue;
                    }
                    else
                    {
                        valueToMe = (short)temp; //(short)(toCheck.Production - ((Math.Abs(x) + Math.Abs(y)) * 0.6));
                    }
                    //DarreksLog.AppendLog(string.Format("This space has production {0}, and is valued to me at {1}", toCheck.Production, valueToMe));

                    if (valueToMe > valueAtBestDestination)
                    {
                        DarreksLog.AppendLog(string.Format("This is the best site I've checked yet: {0},{1}. It has a gaussian value of {2} and a value to me of {3}!", mapX, mapY, gaussianValueMap[mapX, mapY], valueToMe));

                        bestDestination = new Location()
                        {
                            X = mapX, Y = mapY
                        };
                        valueAtBestDestination = valueToMe;
                    }
                }
            }
        }


        if (!bestDestination.HasValue)
        {
            throw new Exception("How is there not a best destination?");
        }

        return(bestDestination.Value);
    }
示例#2
0
    public static LinkedList <Location> GetBestPathToLocation(Map map, short[,] gaussianValueMap, Location startLocation, Location destinationLocation)
    {
        //var path = Pathing.FindQuickestPath(gaussianValueMap, new Tuple<int, int>(startLocation.X, startLocation.Y),
        //    new Tuple<int, int>(destinationLocation.X, destinationLocation.Y));



        //could use solely the sites in a box surrounding the start and destination, then grabbing the smallest



        //TODO: find cheapest route.
        DarreksLog.AppendLog(string.Format("Getting Best Path From {0},{1} to {2},{3}...", startLocation.X, startLocation.Y, destinationLocation.X, destinationLocation.Y));

        var path = new LinkedList <Location>();

        path.AddFirst(startLocation);

        var positionOnPath = startLocation;

        while (!positionOnPath.Equals(destinationLocation))
        {
            var xDistance       = positionOnPath.X - destinationLocation.X;
            var yDistance       = positionOnPath.Y - destinationLocation.Y;
            var crossesMapEdgeX = false;
            var crossesMapEdgeY = false;

            if (Math.Abs(xDistance) > map.Width / 2)
            {
                crossesMapEdgeX = true;
            }
            if (Math.Abs(yDistance) > map.Height / 2)
            {
                crossesMapEdgeY = true;
            }

            DarreksLog.AppendLog(string.Format("From {0},{1} to {2},{3}...", positionOnPath.X, positionOnPath.Y, destinationLocation.X, destinationLocation.Y));
            DarreksLog.AppendLog(string.Format("xDistance = {0}, yDistance = {1}, crossesXEdge = {2}, crossesYEdge = {3}", xDistance, yDistance, crossesMapEdgeX, crossesMapEdgeY));


            Location?potentialPositionMovingHorizontally = null;
            Location?potentialPositionMovingVertically   = null;

            if (xDistance != 0)
            {
                bool moveWest = false;

                if (positionOnPath.X > destinationLocation.X)
                {
                    DarreksLog.AppendLog("The destination is to the west.");
                    moveWest = !crossesMapEdgeX;
                }
                else
                {
                    DarreksLog.AppendLog("The destination is to the east.");
                    moveWest = crossesMapEdgeX;
                }

                DarreksLog.AppendLog(string.Format("I am {0}moving to the west", moveWest ? "" : "not "));

                if (!moveWest)
                {
                    potentialPositionMovingHorizontally = new Location((ushort)((positionOnPath.X + 1 + map.Width) % map.Width), positionOnPath.Y);
                }
                else
                {
                    potentialPositionMovingHorizontally = new Location((ushort)((positionOnPath.X - 1 + map.Width) % map.Width), positionOnPath.Y);
                }
            }
            if (yDistance != 0)
            {
                bool moveNorth = false;

                if (positionOnPath.Y > destinationLocation.Y)
                {
                    DarreksLog.AppendLog("The destination is to the north.");
                    moveNorth = !crossesMapEdgeY;
                }
                else
                {
                    DarreksLog.AppendLog("The destination is to the south.");
                    moveNorth = crossesMapEdgeY;
                }

                DarreksLog.AppendLog(string.Format("I am {0}moving to the north", moveNorth ? "" : "not "));

                if (!moveNorth)
                {
                    potentialPositionMovingVertically = new Location(positionOnPath.X, (ushort)((positionOnPath.Y + 1 + map.Height) % map.Height));
                }
                else
                {
                    potentialPositionMovingVertically = new Location(positionOnPath.X, (ushort)((positionOnPath.Y - 1 + map.Height) % map.Height));
                }
            }

            if (potentialPositionMovingHorizontally.HasValue && potentialPositionMovingVertically.HasValue)
            {
                //Make a decision here to go vertically or horizontally first.
                var verticalMoveValue =
                    gaussianValueMap[potentialPositionMovingVertically.Value.X, potentialPositionMovingVertically.Value.Y];
                var horizontalMoveValue =
                    gaussianValueMap[potentialPositionMovingHorizontally.Value.X, potentialPositionMovingHorizontally.Value.Y];

                if (verticalMoveValue > horizontalMoveValue)
                {
                    path.AddAfter(path.Last, potentialPositionMovingVertically.Value);
                }
                else
                {
                    path.AddAfter(path.Last, potentialPositionMovingHorizontally.Value);
                }
            }
            else if (potentialPositionMovingVertically.HasValue)
            {
                path.AddAfter(path.Last, potentialPositionMovingVertically.Value);
            }
            else if (potentialPositionMovingHorizontally.HasValue)
            {
                path.AddAfter(path.Last, potentialPositionMovingHorizontally.Value);
            }

            positionOnPath = path.Last.Value;
            DarreksLog.AppendLog(string.Format("Added {0},{1} to Path.", positionOnPath.X, positionOnPath.Y));
        }
        return(path);
    }
示例#3
0
    private static bool MakeSnakeMovements(LinkedList <Location> currentSnakePath, Map map, bool currentSnakePathIsCompleted, HashSet <Move> moves)
    {
        var numberOfFeetToTrimSnake = 0;

        if (currentSnakePath == null)
        {
            DarreksLog.AppendLog("SnakePath cannot be null.");
        }

        DarreksLog.AppendLog("Performing Snake Movement...");

        var positionOnPath = currentSnakePath.Last;

        if (map[positionOnPath.Value].Owner == _MyID)
        {
            DarreksLog.AppendLog("It appears we have navigated to the destination! HUZZAH!");
            currentSnakePathIsCompleted = true;
        }
        else
        {
            var numSnakePieces = 0;

            while (positionOnPath != null)
            {
                var activeSite = map[positionOnPath.Value];
                //if a site on the path is mine, move it along the path if strong enough.
                if (activeSite.Owner == _MyID)
                {
                    var thisGuysDestination = positionOnPath.Next;

                    if ((thisGuysDestination == null) || (activeSite.Strength == 0))
                    {
                        //Don't move a snake that doesn't have any strength.
                    }
                    else
                    {
                        numSnakePieces++;

                        if (numSnakePieces > MAX_SNAKE_LENGTH)
                        {
                            numberOfFeetToTrimSnake++;
                        }

                        var dir             = GetMoveDirection(map, positionOnPath.Value, thisGuysDestination.Value);
                        var destinationSite = GetNeighbor(map, positionOnPath.Value, dir);

                        if ((destinationSite.Owner != _MyID && destinationSite.Strength > activeSite.Strength) ||
                            (activeSite.Strength < activeSite.Production * 3))
                        {
                            DarreksLog.AppendLog(string.Format("Staying Here at {0},{1}.", positionOnPath.Value.X,
                                                               positionOnPath.Value.Y));

                            //Don't move if this will kill the site.
                            //Also don't move if we are super small.
                            //A still move to override other movements if they exist.
                            moves.Add(new Move
                            {
                                Location  = positionOnPath.Value,
                                Direction = Direction.Still
                            });
                        }
                        else
                        {
                            DarreksLog.AppendLog(string.Format("Moving {2} from {0},{1}.", positionOnPath.Value.X,
                                                               positionOnPath.Value.Y, dir));
                            moves.Add(new Move
                            {
                                Location  = positionOnPath.Value,
                                Direction = dir
                            });
                        }
                    }
                }

                positionOnPath = positionOnPath.Previous;
            }

            DarreksLog.AppendLog(string.Format("The Snake is {0} feet long!", numSnakePieces));
        }

        if (numberOfFeetToTrimSnake > 0)
        {
            DarreksLog.AppendLog(string.Format("The Snake is too long. Trimming by {0} Feet", numberOfFeetToTrimSnake));
            for (var i = 0; i < numberOfFeetToTrimSnake; i++)
            {
                currentSnakePath.RemoveFirst();
            }
        }

        DarreksLog.AppendLog("Done Performing Snake Movement.");
        return(currentSnakePathIsCompleted);
    }
示例#4
0
    private static Move?GetProductionSeekerBotMove(Map map, ushort x, ushort y)
    {
        //Borrows the code from ProductionSeekerBot2

        var activeSite = new SiteEx(map, x, y);

        if ((activeSite.Strength < activeSite.Production * 3) && (activeSite.Strength < MAX_STRENGTH / 12))
        {
            return(null);
        }

        var neighbors = new List <SiteEx>()
        {
            GetNeighbor(map, activeSite.Location, Direction.West),
            GetNeighbor(map, activeSite.Location, Direction.East),
            GetNeighbor(map, activeSite.Location, Direction.North),
            GetNeighbor(map, activeSite.Location, Direction.South)
        };

        var friendlySites = neighbors.Where(c => c.Owner == _MyID);
        var friendlySitesWorthVisiting =
            friendlySites.Where(
                f =>
                f.Strength > 0 && f.Strength + activeSite.Strength <MAX_STRENGTH &&
                                                                    f.Production> (_MaxProductionValue / 4));
        var neutralNeighbors  = neighbors.Where(c => c.Owner == 0);
        var weakNeighborSites = neighbors.Where(c => (activeSite.Strength == MAX_STRENGTH || c.Production > 0) && c.Strength < activeSite.Strength && c.Owner == 0);

        bool shouldCombine = false;

        if (!weakNeighborSites.Any())
        {
            if (activeSite.X + activeSite.Y % 2 == 1) //Only combine from every other square to prevent dancing.
            {
                shouldCombine = true;
            }
        }

        //Combine forces if we are a thin line.
        if (shouldCombine && friendlySitesWorthVisiting.Any())
        {
            var destination = friendlySitesWorthVisiting.FirstOrDefault(f => f.Production > activeSite.Production);
            if (destination != null)
            {
                var directionToMove = GetMoveDirection(map, activeSite.Location, destination.Location);
                DarreksLog.AppendLog("Combine Forces!");

                return(new Move
                {
                    Location = activeSite.Location,
                    Direction = directionToMove
                });
            }
        }

        //1. Try to grow
        if (weakNeighborSites.Any())
        {
            SiteEx lunchSiteToAttack = null;

            //Move Between enemies if possible for maximum damage!
            foreach (var pls in weakNeighborSites)
            {
                var nW = GetNeighbor(map, pls.Location, Direction.West);
                var nE = GetNeighbor(map, pls.Location, Direction.East);
                var nS = GetNeighbor(map, pls.Location, Direction.South);
                var nN = GetNeighbor(map, pls.Location, Direction.North);

                var enemyNeighborsCount = ((nW.Owner != _MyID && nW.Owner != 0) ? 1 : 0) +
                                          ((nE.Owner != _MyID && nE.Owner != 0) ? 1 : 0) +
                                          ((nS.Owner != _MyID && nS.Owner != 0) ? 1 : 0) +
                                          ((nN.Owner != _MyID && nN.Owner != 0) ? 1 : 0);

                if (enemyNeighborsCount > 1)
                {
                    lunchSiteToAttack = pls;
                }
            }

            if (lunchSiteToAttack == null)
            {
                lunchSiteToAttack = weakNeighborSites.OrderByDescending(s => s.Production - s.Strength / 10).First();
            }

            var directionToMove = GetMoveDirection(map, activeSite.Location, lunchSiteToAttack.Location);

            if (lunchSiteToAttack.Strength < activeSite.Strength)
            {
                return(new Move
                {
                    Location = activeSite.Location,
                    Direction = directionToMove
                });
            }
        }


        //2. If all neighbors are friendly, move towards nearest edge.
        else if (activeSite.Strength > 0 && friendlySites.Count() == neighbors.Count && ((activeSite.Strength >= (activeSite.Production * 3)) || activeSite.Strength > HALF_STRENGTH / 2))
        {
            ushort distanceFromEdge;
            var    nearestNonPlayerDirection = GetNearestNonPlayerDirection(map, activeSite, _MyID, out distanceFromEdge);
            if (nearestNonPlayerDirection != Direction.Still)
            {
                return(new Move
                {
                    Location = activeSite.Location,
                    Direction = nearestNonPlayerDirection
                });
            }
            else //All orthagonal directions are occupied.
            {
                return(new Move
                {
                    Location = activeSite.Location,
                    Direction = x % 2 == 1 ? Direction.North : Direction.South
                });
                //TODO: could have logic here to find enemies or something, or go diagonally.
            }
        }

        return(null);
    }
示例#5
0
    public static void Main(string[] args)
    {
        Console.SetIn(Console.In);
        Console.SetOut(Console.Out);

        try
        {
            var map = Networking.getInit(out _MyID);
            DarreksLog.LogFileName = String.Format("log{0}.txt", _MyID);
            _MaxScanDistance       = (ushort)(map.Width / 4);



            #region Check Production before game start

            var sb = new StringBuilder();
            sb.Append("production values:");

            //TODO: find nearest high production zone and head there.
            for (ushort y = 0; y < map.Height; y++)
            {
                sb.Append("\r\n");
                for (ushort x = 0; x < map.Width; x++)
                {
                    var prodVal = map[x, y].Production;

                    sb.Append(prodVal + " ");

                    if (_MaxProductionValue < prodVal)
                    {
                        _MaxProductionValue = prodVal;
                    }
                }
            }

            //DarreksLog.AppendLog(sb.ToString());

            _TopProductionValuesGreaterThan = (ushort)(_MaxProductionValue * .75);

            DarreksLog.AppendLog(string.Format("Max Production Value Found = {0}", _MaxProductionValue));
            DarreksLog.AppendLog(string.Format("Top Production Values >= {0}", _TopProductionValuesGreaterThan));

            #endregion



            LinkedList <Location> currentSnakePath = null;
            bool currentSnakePathIsCompleted       = true;

            /* ------
            *   Do more prep work, see rules for time limit
            *  ------ */

            sb.Clear();
            sb.Append("Value to Me:");
            var valueMap = new short[map.Width, map.Height];
            for (ushort y = 0; y < map.Height; y++)
            {
                sb.Append("\r\n");
                for (ushort x = 0; x < map.Width; x++)
                {
                    var activeSite = map[x, y];
                    valueMap[x, y] = GetValueOfSite(activeSite);
                    sb.Append(valueMap[x, y] + " ");
                }
            }
            //DarreksLog.AppendLog(sb.ToString());

            var gaussianValueMap = GetGaussianValueMap(valueMap, map.Width, map.Height);

            sb.Clear();
            sb.Append("Gaussian Values:");
            for (ushort y = 0; y < map.Height; y++)
            {
                sb.Append("\r\n");
                for (ushort x = 0; x < map.Width; x++)
                {
                    sb.Append(gaussianValueMap[x, y] + " ");
                }
            }

            DarreksLog.AppendLog(sb.ToString());

            Networking.SendInit(MyBotName); // Acknoweldge the init and begin the game

            var random = new Random();

            DarreksLog.AppendLog("Starting battle!");
            int      frameNumber   = 0;
            Location startLocation = new Location(0, 0);

            while (true)
            {
                try
                {
                    Networking.getFrame(ref map); // Update the map to reflect the moves before this turn
                }
                catch (Exception)
                {
                    return;
                }

                frameNumber++;
                DarreksLog.AppendLog(string.Format("Frame {0}", frameNumber));

                var moves = new HashSet <Move>();


                for (ushort x = 0; x < map.Width; x++)
                {
                    for (ushort y = 0; y < map.Height; y++)
                    {
                        if (map[x, y].Owner == _MyID)
                        {
                            //DarreksLog.AppendLog("GetProductionSeekerBotMove...");
                            var move = GetProductionSeekerBotMove(map, x, y);
                            if (move.HasValue)
                            {
                                //DarreksLog.AppendLog(String.Format("Added Move {0},{1}->{2}...", move.Value.Location.X, move.Value.Location.Y, move.Value.Direction));
                                moves.Add(move.Value);
                            }

                            if (frameNumber == 1)
                            {
                                startLocation = new Location(x, y);
                            }
                        }
                    }
                }



                #region Pick new Snake Destination

                if (currentSnakePathIsCompleted && frameNumber < 10)
                {
                    //we have a notion of the "head" of the line (linkedlist), and also which locations are feeding into it. These locations should all just send their resources through towards the head.
                    //TODO: when the snake moves, the new location becomes the head, and drop the tail if longer than the limit

                    //TODO: as the size grows, multiple lines could exist to search out the best production zones.


                    currentSnakePathIsCompleted = false;

                    DarreksLog.AppendLog("Setting Snake Destination...");

                    var snakeStartLocation = currentSnakePath == null
                        ? startLocation
                        : currentSnakePath.Last.Value;

                    DarreksLog.AppendLog(string.Format("Starting at {0},{1}", snakeStartLocation.X, snakeStartLocation.Y));
                    var snakeDestination = GetNearestFreeHighProductionDirection(map, gaussianValueMap, snakeStartLocation);
                    DarreksLog.AppendLog(string.Format("Snake Destination Set to {0},{1}. Production there is {2}", snakeDestination.X, snakeDestination.Y, map[snakeDestination].Production));

                    DarreksLog.AppendLog("Getting Snake's Best Path To Destination...");

                    var newPathBits = GetBestPathToLocation(map, gaussianValueMap, snakeStartLocation, snakeDestination);
                    if (currentSnakePath == null)
                    {
                        currentSnakePath = newPathBits;
                    }
                    else
                    {
                        foreach (var newPathBit in newPathBits)
                        {
                            if (!currentSnakePath.Last.Value.Equals(newPathBit))
                            {
                                currentSnakePath.AddLast(newPathBit);
                            }
                        }


                        //Remove duplicates in the path
                        var locationsInSnake = new HashSet <Location>();
                        var looker           = currentSnakePath.Last;

                        do
                        {
                            DarreksLog.AppendLog("Checking for looping in the snake.");

                            if (locationsInSnake.Contains(looker.Value))
                            {
                                DarreksLog.AppendLog(string.Format("Found a loop on {0},{1}.", looker.Value.X, looker.Value.Y));
                                do
                                {
                                    currentSnakePath.RemoveFirst();
                                } while (!currentSnakePath.First.Value.Equals(looker.Value));
                                currentSnakePath.RemoveFirst();
                                if (currentSnakePath.Count <= 1)
                                {
                                    currentSnakePathIsCompleted = true;
                                }
                            }
                            else
                            {
                                locationsInSnake.Add(looker.Value);
                            }

                            looker = looker.Previous;
                        } while (looker != null);


                        DarreksLog.AppendLog("Path To Destination:");

                        foreach (var node in currentSnakePath)
                        {
                            DarreksLog.AppendLog(string.Format("{0},{1}", node.X, node.Y));
                        }
                    }

                    DarreksLog.AppendLog(string.Format("The New Snake Path is {0} feet long!", currentSnakePath.Count));
                }

                #endregion

                #region Snake Movement

                currentSnakePathIsCompleted = MakeSnakeMovements(currentSnakePath, map, currentSnakePathIsCompleted, moves);

                #endregion Snake Movement

                Networking.SendMoves(moves); // Send moves
            }
        }
        catch (Exception ex)
        {
            DarreksLog.AppendLog("Exception Happened: " + ex.Message + "\r\nat\r\n" + ex.StackTrace);
        }
    }