Пример #1
0
        private string compute()
        {
            //
            GameState currentState = States[States.Count() - 1];
            Point     myPosition   = currentState.Entities.First(e => e.Type == GameState.EntityType.Player && e.Team == Team).Position;

            //
            Timer.Reset();
            Timer.Start();
            //
            List <GameState> futureStatesBomb = computeFutureStates(myPosition);
            Tuple <List <MapPoint>, List <MapPoint> > mapsBomb = computeMap(futureStatesBomb);
            //
            List <GameState> futureStates = computeFutureStates(new Point(-1, -1));
            Tuple <List <MapPoint>, List <MapPoint> > maps = computeMap(futureStates);

            if (maps.Item1 == null)
            {
                maps = new Tuple <List <MapPoint>, List <MapPoint> >(new List <MapPoint>(), new List <MapPoint>());
            }
            //
            double planningTime = Timer.ElapsedMilliseconds;

            debug("Planning - " + planningTime + "ms");
            //
            List <Point> around = new List <Point>();

            for (int i = 0; i < GameState.W; i++)
            {
                for (int j = 0; j < GameState.H; j++)
                {
                    around.Add(new Point(i, j));
                }
            }
            around = around.OrderBy(p => Manhattan(p, myPosition)).ToList();
            //
            int pointer = 0;
            List <Tuple <GameState.Option, Tuple <double, Point> > > options = new List <Tuple <GameState.Option, Tuple <double, Point> > >();

            while ((options.Count() < 20) || (Timer.ElapsedMilliseconds < 90 && pointer < around.Count()))
            {
                Point            p    = around[pointer];
                GameState.Option bomb = new GameState.Option()
                {
                    Location = p, Bomb = true
                };
                GameState.Option move = new GameState.Option()
                {
                    Location = p, Bomb = false
                };
                options.Add(new Tuple <GameState.Option, Tuple <double, Point> >(bomb, calcScore(bomb, futureStates, maps.Item1)));
                options.Add(new Tuple <GameState.Option, Tuple <double, Point> >(move, calcScore(move, futureStates, maps.Item1)));
                pointer++;
            }
            //
            options = options.OrderByDescending(o => o.Item2.Item1).ToList();
            GameState.Option strategy = options[0].Item1;
            currentState.Strategy = strategy;

            //
            Timer.Stop();
            long time = Timer.ElapsedMilliseconds;

            debug("Options  - " + time + "ms, " + options.Count() + " items");
            for (int i = 0; i < 8; i++)
            {
                debug((options[i].Item1.Bomb ? "BOMB " : "MOVE ") + options[i].Item1.Location.X + "," + options[i].Item1.Location.Y + " => " + options[i].Item2);
            }

            //Determine action
            string action = "MOVE";

            if (States.Count() >= 2 && States[States.Count() - 2].Strategy.Bomb && States[States.Count() - 2].Strategy.Location == myPosition)
            {
                action = "BOMB";
            }
            debug("Original action is " + action);
            //Target is the strategy's <Score, Nextstep>.Nextstep
            Point target = options[0].Item2.Item2;

            //Evasion
            if (mapsBomb.Item2 == null)
            {
                action = "MOVE";
                debug("Cannot BOMB and run, change to MOVE");
            }
            //
            List <MapPoint> culled = (action == "BOMB") ? mapsBomb.Item2 : maps.Item2;

            if (culled != null && culled.Count() > 0)
            {
                List <Point> validMoves;
                bool         hasTrail1 = culled.First().Trail.Count() > 1;
                if (hasTrail1)
                {
                    validMoves = culled.Select(trail => trail.Trail[1]).Distinct().ToList();
                }
                else
                {
                    validMoves = culled.Select(trail => trail.Position).Distinct().ToList();
                }
                if (!validMoves.Contains(target))
                {
                    debug("Evasion from " + target + " to " + validMoves[0]);
                    target = validMoves[0];
                }
            }

            //Leaving a bomb
            if (Manhattan(target, myPosition) == 1 &&
                (currentState.Entities.Exists(b => b.Type == GameState.EntityType.Bomb && b.Position == myPosition) || action == "BOMB"))
            {
                //
                List <Point> availableDirections = new List <Point>();
                int          range  = (action == "BOMB") ? currentState.Entities.First(e => e.Type == GameState.EntityType.Player && e.Team == Team).Range : currentState.Entities.Where(b => b.Type == GameState.EntityType.Bomb && b.Position == myPosition).Select(b => b.Range).Max();
                int          rounds = (action == "BOMB") ? 8 : currentState.Entities.Where(b => b.Type == GameState.EntityType.Bomb && b.Position == myPosition).Select(b => b.Rounds).Min();
                //Check if in each direction has a corridor and turnaround
                foreach (Point d in Directions)
                {
                    //Corridor must be long enough
                    bool existsCorridor = true;
                    for (int c = 1; c <= range; c++)
                    {
                        Point check = new Point(myPosition.X + d.X * c, myPosition.Y + d.Y * c);
                        if (check.X < 0 || check.X >= GameState.W || check.Y < 0 || check.Y >= GameState.H)
                        {
                            existsCorridor = false;
                            break;
                        }
                        if (currentState.Board[check.X, check.Y] != '.')
                        {
                            existsCorridor = false;
                        }
                    }
                    //Or have turnaround within time
                    int  mustHaveTurnWithin = rounds - 2;
                    bool hasTurnAround      = false;
                    for (int offset = 1; offset <= mustHaveTurnWithin; offset++)
                    {
                        //Corridor must exist
                        Point check = new Point(myPosition.X + d.X * offset, myPosition.Y + d.Y * offset);
                        if (check.X < 0 || check.X >= GameState.W || check.Y < 0 || check.Y >= GameState.H)
                        {
                            break;
                        }
                        if (currentState.Board[check.X, check.Y] != '.')
                        {
                            break;
                        }
                        //Sides
                        bool  checkHorizontal = (check.X != myPosition.X);
                        Point upperLeft       = checkHorizontal ? new Point(check.X, check.Y + 1) : new Point(check.X + 1, check.Y);
                        Point lowerRight      = checkHorizontal ? new Point(check.X, check.Y - 1) : new Point(check.X - 1, check.Y);
                        bool  noUpperLeft     = upperLeft.X < 0 || upperLeft.X >= GameState.W || upperLeft.Y < 0 || upperLeft.Y >= GameState.H;
                        bool  noLowerRight    = lowerRight.X < 0 || lowerRight.X >= GameState.W || lowerRight.Y < 0 || lowerRight.Y >= GameState.H;
                        if ((!noUpperLeft && (currentState.Board[upperLeft.X, upperLeft.Y] == '.')) ||
                            (!noLowerRight && (currentState.Board[lowerRight.X, lowerRight.Y] == '.')))
                        {
                            hasTurnAround = true;
                            break;
                        }
                    }
                    //
                    if (existsCorridor || hasTurnAround)
                    {
                        availableDirections.Add(new Point(myPosition.X + d.X, myPosition.Y + d.Y));
                    }
                }
                //
                if (availableDirections.Count() > 0 && (!availableDirections.Contains(target)))
                {
                    debug("Changed target from " + target + " to " + availableDirections[0]);
                    target = availableDirections[0];
                }
            }

            //
            int myBombsCount = currentState.Entities.Count(e => e.Team == Team && e.Type == GameState.EntityType.Bomb);

            if (myBombsCount >= 3)
            {
                action = "MOVE";
            }

            if (options[0].Item2.Item1 < -50)
            {
                action = "MOVE";
            }

            //
            return(action + " " + target.X + " " + target.Y);
        }
Пример #2
0
        private string compute()
        {
            //
            Timer.Reset();
            Timer.Start();
            //
            GameState    currentState = States[States.Count() - 1];
            Point        myPosition   = currentState.Entities.First(e => e.Type == GameState.EntityType.Player && e.Team == Team).Position;
            List <Point> around       = new List <Point>();

            for (int i = 0; i < GameState.W; i++)
            {
                for (int j = 0; j < GameState.H; j++)
                {
                    around.Add(new Point(i, j));
                }
            }
            around = around.OrderBy(p => Manhattan(p, myPosition)).ToList();
            //
            int pointer = 0;
            List <Tuple <GameState.Option, double> > options = new List <Tuple <GameState.Option, double> >();

            while (Timer.ElapsedMilliseconds < 85 && pointer < around.Count())
            {
                Point            p    = around[pointer];
                GameState.Option bomb = new GameState.Option()
                {
                    Location = p, Bomb = true
                };
                GameState.Option move = new GameState.Option()
                {
                    Location = p, Bomb = false
                };
                options.Add(new Tuple <GameState.Option, double>(bomb, calcScore(bomb)));
                options.Add(new Tuple <GameState.Option, double>(move, calcScore(move)));
                pointer++;
            }
            //
            options = options.OrderByDescending(o => o.Item2).ToList();
            GameState.Option strategy = options[0].Item1;
            currentState.Strategy = strategy;

            //
            Timer.Stop();
            long time = Timer.ElapsedMilliseconds;

            debug("Options - " + options.Count() + " items, " + time + "ms");
            for (int i = 0; i < 8; i++)
            {
                debug((options[i].Item1.Bomb ? "BOMB " : "MOVE ") + options[i].Item1.Location.X + "," + options[i].Item1.Location.Y + " => " + options[i].Item2);
            }

            //
            string action = "MOVE";

            if (States.Count() >= 2 && States[States.Count() - 2].Strategy.Bomb && States[States.Count() - 2].Strategy.Location == myPosition)
            {
                action = "BOMB";
            }
            Point target = strategy.Location;

            if (myPosition != target)
            {
                List <Point> path = GetPath(currentState, myPosition, target);
                target = path[path.Count() - 1];
            }

            return(action + " " + target.X + " " + target.Y);
        }
Пример #3
0
        private Tuple <double, Point> calcScore(GameState.Option option, List <GameState> futureStates, List <MapPoint> map)
        {
            GameState currentState = States[States.Count() - 1];

            GameState.Entity my = currentState.Entities.First(e => e.Type == GameState.EntityType.Player && e.Team == Team);
            Point            p  = option.Location;

            //
            if (option.Bomb && (option.Location == new Point(0, 0) || option.Location == new Point(12, 0) || option.Location == new Point(12, 10) || option.Location == new Point(0, 10)))
            {
                return(new Tuple <double, Point>(Invalid, my.Position));
            }

            //The tile is not worth visiting if it has a bomb, it will kill you
            if (currentState.Entities.Exists(e => e.Position.Equals(p) && e.Type == GameState.EntityType.Bomb))
            {
                return(new Tuple <double, Point>(Invalid, my.Position));
            }
            //Is the tile reachable?
            int distance = 0; bool reachable = false; Point nextStep = my.Position;

            if (my.Position == p)
            {
                reachable = true;
            }
            if (map.Exists(mp => mp.Position == p))
            {
                MapPoint best = map.Where(mp => mp.Position == p).OrderBy(mp => mp.Depth).First();
                distance  = best.Depth;
                nextStep  = best.Trail.Count() < 2 ? p : best.Trail[1];
                reachable = true;
            }
            //The tile is not covered by the map, so it's either not free or is very far, check with A* provided the tile is empty
            else if (currentState.Board[p.X, p.Y] == '.')
            {
                List <Point> path = GetPath(currentState, my.Position, p);
                distance = path.Count();
                if (distance > 0)
                {
                    reachable = true;
                    nextStep  = path[path.Count() - 1];
                }
            }
            if (!reachable)
            {
                return(new Tuple <double, Point>(Invalid, my.Position));
            }

            //Calc bombing score
            GameState futureState = futureStates[Math.Min(distance, 7)];
            int       score       = 0;

            if (option.Bomb)
            {
                foreach (Point d in Directions)
                {
                    for (int i = 1; i < my.Range; i++)
                    {
                        //
                        Point candidate = new Point(p.X + d.X * i, p.Y + d.Y * i);
                        if (candidate.X < 0 || candidate.X >= GameState.W || candidate.Y < 0 || candidate.Y >= GameState.H)
                        {
                            break;
                        }
                        //Mark boxes
                        if ("012".Contains(futureState.Board[candidate.X, candidate.Y]))
                        {
                            //Powerups count more
                            if ("12".Contains(futureState.Board[candidate.X, candidate.Y]))
                            {
                                score++;
                            }
                            score++; break;
                        }
                        //Attack other players
                        if (currentState.Entities.Exists(e => e.Type == GameState.EntityType.Player && e.Team != Team && e.Position == candidate))
                        {
                            if (Manhattan(my.Position, candidate) >= 2)
                            {
                                score++;
                            }
                        }
                        //Stop at items
                        if (futureState.Entities.Exists(e => e.Type == GameState.EntityType.Item && e.Position == candidate))
                        {
                            break;
                        }
                        //Stop at walls
                        if (futureState.Board[candidate.X, candidate.Y] == 'X')
                        {
                            break;
                        }
                    }
                }
            }
            //Calc power-up score
            if (futureState.Entities.Exists(e => e.Type == GameState.EntityType.Item && e.Position == p))
            {
                score += 3;
            }
            //
            if (score == 0)
            {
                return(new Tuple <double, Point>(Invalid, my.Position));
            }

            //Factor in the distance
            int waitTurns = 0;

            if (option.Bomb)
            {
                int countBombs = currentState.Entities.Count(e => e.Type == GameState.EntityType.Bomb && e.Team == Team);
                if (countBombs >= my.Rounds)
                {
                    waitTurns = currentState.Entities.Where(e => e.Type == GameState.EntityType.Bomb && e.Team == Team)
                                .OrderBy(e => e.Rounds).First().Rounds;
                }
            }
            int delay = Math.Max(waitTurns, distance);

            //
            return(new Tuple <double, Point>(1.5 * score - delay, nextStep));
        }
Пример #4
0
        private double calcScore(GameState.Option option)
        {
            Point     p            = option.Location;
            GameState currentState = States[States.Count() - 1];

            GameState.Entity my = currentState.Entities.First(e => e.Type == GameState.EntityType.Player && e.Team == Team);
            if (my.Position == p)
            {
                return(Invalid);
            }
            //Is the tile empty?
            if (currentState.Board[p.X, p.Y] != '.')
            {
                return(Invalid);
            }
            if (currentState.Entities.Exists(e => e.Position.Equals(p) && e.Type == GameState.EntityType.Bomb))
            {
                return(Invalid);
            }
            //Is the tile reachable?
            int distance = GetPath(currentState, my.Position, p).Count();

            if (distance == 0)
            {
                return(Invalid);
            }
            //Calc future state - explode all the bombs and mark all the boxes
            GameState futureState = new GameState(currentState);

            //Place a bomb in future state if previous strategy is to bomb
            if (States.Count() >= 2 && States[States.Count() - 2].Strategy.Bomb)
            {
                futureState.Entities.Add(new GameState.Entity()
                {
                    Team = Team, Type = GameState.EntityType.Bomb, Position = my.Position, Range = my.Range, Rounds = 8
                });
            }
            //
            foreach (GameState.Entity bomb in futureState.Entities.Where(e => e.Type == GameState.EntityType.Bomb))
            {
                foreach (Point d in Directions)
                {
                    for (int i = 1; i < bomb.Range; i++)
                    {
                        //
                        Point candidate = new Point(bomb.Position.X + d.X * i, bomb.Position.Y + d.Y * i);
                        if (candidate.X < 0 || candidate.X >= GameState.W || candidate.Y < 0 || candidate.Y >= GameState.H)
                        {
                            break;
                        }
                        //Mark boxes and stop the blast
                        if ("012".Contains(futureState.Board[candidate.X, candidate.Y]))
                        {
                            futureState.Board[candidate.X, candidate.Y] = '.';
                            break;
                        }
                        //Stop at items
                        if (futureState.Entities.Exists(e => e.Type == GameState.EntityType.Item && e.Position == candidate))
                        {
                            GameState.Entity item = futureState.Entities.First(e => e.Type == GameState.EntityType.Item && e.Position == candidate);
                            break;
                        }
                        //Stop at walls
                        if (futureState.Board[candidate.X, candidate.Y] == 'X')
                        {
                            break;
                        }
                    }
                }
            }
            //Calc bombing score
            int score = 0;

            if (option.Bomb)
            {
                foreach (Point d in Directions)
                {
                    for (int i = 1; i < my.Range; i++)
                    {
                        //
                        Point candidate = new Point(p.X + d.X * i, p.Y + d.Y * i);
                        if (candidate.X < 0 || candidate.X >= GameState.W || candidate.Y < 0 || candidate.Y >= GameState.H)
                        {
                            break;
                        }
                        //Mark boxes
                        if ("012".Contains(futureState.Board[candidate.X, candidate.Y]))
                        {
                            if ("12".Contains(futureState.Board[candidate.X, candidate.Y]))
                            {
                                score++;
                            }
                            score++; break;
                        }
                        //Stop at items
                        if (futureState.Entities.Exists(e => e.Type == GameState.EntityType.Item && e.Position == candidate))
                        {
                            break;
                        }
                        //Stop at walls
                        if (futureState.Board[candidate.X, candidate.Y] == 'X')
                        {
                            break;
                        }
                    }
                }
            }
            //Calc power-up score
            if (currentState.Entities.Exists(e => e.Type == GameState.EntityType.Item && e.Position == p))
            {
                score += 3;
            }
            //
            if (score == 0)
            {
                if (option.Bomb)
                {
                    return(2 * Invalid);
                }
                return(Invalid);
            }

            //Factor in the distance
            int waitTurns = 0;

            if (option.Bomb)
            {
                int countBombs = currentState.Entities.Count(e => e.Type == GameState.EntityType.Bomb && e.Team == Team);
                if (countBombs >= my.Rounds)
                {
                    waitTurns = currentState.Entities.Where(e => e.Type == GameState.EntityType.Bomb && e.Team == Team)
                                .OrderBy(e => e.Rounds).First().Rounds;
                }
            }
            int delay = Math.Max(waitTurns, distance);

            //
            return(1.5 * score - delay);
        }