Ejemplo n.º 1
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));
        }
Ejemplo n.º 2
0
        private List <GameState> computeFutureStates(Point plantBomb)
        {
            const int Exploded     = 99;
            GameState currentState = States[States.Count() - 1];

            GameState.Entity my           = currentState.Entities.First(e => e.Type == GameState.EntityType.Player && e.Team == Team);
            List <GameState> futureStates = new List <GameState>();

            for (int count = 0; count < 8; count++)
            {
                //Calculate bomb explosions and blast map
                GameState futureState = new GameState(currentState);
                futureState.Entities = futureState.Entities.Where(e => e.Type != GameState.EntityType.Player).ToList();
                //Countdown
                foreach (GameState.Entity bomb in futureState.Entities.Where(e => e.Type == GameState.EntityType.Bomb))
                {
                    bomb.Rounds--;
                }
                //Add a bomb
                if (count == 0 && plantBomb.X >= 0 && plantBomb.Y >= 0)
                {
                    futureState.Entities.Add(new GameState.Entity()
                    {
                        Type = GameState.EntityType.Bomb, Team = Team, Position = plantBomb, Range = my.Range, Rounds = 8
                    });
                }
                //Explode the bombs
                List <Point> boxes = new List <Point>();
                while (futureState.Entities.Exists(e => e.Type == GameState.EntityType.Bomb && e.Rounds == 0))
                {
                    GameState.Entity bomb = futureState.Entities.First(e => e.Type == GameState.EntityType.Bomb && e.Rounds == 0);
                    bomb.Rounds = Exploded;
                    //
                    foreach (Point p in Directions)
                    {
                        //Start from 0 to include blast map and trigger bombs at the same location
                        for (int i = 0; i < bomb.Range; i++)
                        {
                            //
                            Point candidate = new Point(bomb.Position.X + p.X * i, bomb.Position.Y + p.Y * i);
                            if (candidate.X < 0 || candidate.X >= GameState.W || candidate.Y < 0 || candidate.Y >= GameState.H)
                            {
                                break;
                            }
                            futureState.Blasts.Add(candidate);
                            //Trigger nearby bombs
                            if (futureState.Entities.Exists(e => e.Type == GameState.EntityType.Bomb && e.Position == candidate && e.Rounds != Exploded))
                            {
                                futureState.Entities.First(e => e.Type == GameState.EntityType.Bomb && e.Position == candidate && e.Rounds != Exploded).Rounds = 0;
                                if (i > 0)
                                {
                                    break;
                                }
                            }
                            //Mark boxes and stop the blast
                            if ("012".Contains(futureState.Board[candidate.X, candidate.Y]))
                            {
                                boxes.Add(candidate);
                                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);
                                futureState.Entities.Remove(item);
                                break;
                            }
                            //Stop at walls
                            if (futureState.Board[candidate.X, candidate.Y] == 'X')
                            {
                                break;
                            }
                        }
                    }
                }
                //Remove bombs
                futureState.Entities = futureState.Entities.Where(e => e.Rounds != Exploded).ToList();

                //Boxes and items
                foreach (Point box in boxes.Distinct())
                {
                    //Drop items
                    if ("12".Contains(futureState.Board[box.X, box.Y]))
                    {
                        futureState.Entities.Add(new GameState.Entity()
                        {
                            Type     = GameState.EntityType.Item,
                            Team     = 0,
                            Position = box,
                            Rounds   = int.Parse("" + futureState.Board[box.X, box.Y]),
                            Range    = 0
                        });
                    }
                    //Remove box
                    futureState.Board[box.X, box.Y] = '.';
                }

                //
                futureStates.Add(futureState);
                currentState = futureState;
            }

            //Visualize blast maps
            for (int i = 0; i < 8; i++)
            {
                //debug("Future state " + i + "\n" + futureStates[i].Visualize());
            }

            //
            return(futureStates);
        }
Ejemplo n.º 3
0
        private Tuple <List <MapPoint>, List <MapPoint> > computeMap(List <GameState> futureStates)
        {
            //
            GameState currentState = States[States.Count() - 1];

            GameState.Entity my = currentState.Entities.First(e => e.Type == GameState.EntityType.Player && e.Team == Team);
            //
            List <Point> Movements5 = new List <Point>();

            Movements5.Add(new Point(1, 0));
            Movements5.Add(new Point(-1, 0));
            Movements5.Add(new Point(0, 1));
            Movements5.Add(new Point(0, -1));
            Movements5.Add(new Point(0, 0));
            //
            int             depth = 0;
            int             count = 0; const int Limit = 200;
            List <MapPoint> map       = new List <MapPoint>();
            List <MapPoint> culledMap = new List <MapPoint>();

            map.Add(new MapPoint()
            {
                Position = my.Position, Trail = new List <Point>(), Depth = depth
            });
            Dictionary <int, int> culling = new Dictionary <int, int>();
            bool timeout = false;

            //
            while (depth < 8 && !timeout)
            {
                //Wipe out cells covered by bomb blasts
                GameState futureState = futureStates[depth];
                if (map.Exists(p => p.Depth == depth && futureState.Blasts.Contains(p.Position)))
                {
                    culling[depth] = map.Count(p => p.Depth == depth && futureState.Blasts.Contains(p.Position));
                    map            = map.Where(p => !(p.Depth == depth && futureState.Blasts.Contains(p.Position))).ToList();
                    culledMap      = new List <MapPoint>();
                    foreach (MapPoint mp in map.Where(mpp => mpp.Depth == depth))
                    {
                        culledMap.Add(mp);
                    }
                }
                //Stop if certain death
                if (map.Count(p => p.Depth == depth) == 0)
                {
                    return(new Tuple <List <MapPoint>, List <MapPoint> >(null, null));
                }
                //
                if (count > Limit)
                {
                    timeout = true;
                    break;
                }
                //Spawn children
                List <MapPoint> newPoints = new List <MapPoint>();
                foreach (MapPoint mapPoint in map.Where(m => m.Depth == depth))
                {
                    foreach (Point d in Movements5)
                    {
                        Point candidate = new Point(mapPoint.Position.X + d.X, mapPoint.Position.Y + d.Y);
                        //Out of bounds
                        if (candidate.X < 0 || candidate.X >= GameState.W || candidate.Y < 0 || candidate.Y >= GameState.H)
                        {
                            continue;
                        }
                        //A bomb
                        if (d != new Point(0, 0))
                        {
                            if (futureState.Entities.Exists(e => e.Type == GameState.EntityType.Bomb && e.Position == candidate))
                            {
                                continue;
                            }
                        }
                        //A box or a wall
                        if (futureState.Board[candidate.X, candidate.Y] != '.')
                        {
                            continue;
                        }
                        //Add
                        List <Point> trail = new List <Point>();
                        foreach (Point t in mapPoint.Trail)
                        {
                            trail.Add(t);
                        }
                        trail.Add(mapPoint.Position);
                        newPoints.Add(new MapPoint()
                        {
                            Position = candidate, Trail = trail, Depth = depth + 1
                        });
                        count++;
                    }
                }
                foreach (MapPoint p in newPoints)
                {
                    map.Add(p);
                }
                depth++;
            }

            //Visualize the map
            debug("culledMap.Count() " + culledMap.Count());
            if (culledMap.Count() > 0)
            {
                foreach (MapPoint point in culledMap)
                {
                    string line = "(" + point.Position.X + ", " + point.Position.Y + ") ";
                    foreach (Point p in point.Trail)
                    {
                        line += "" + p.X + "," + p.Y + "->";
                    }
                    //debug(line);
                }
            }
            bool dump = false;

            if (dump)
            {
                debug("map.Count() " + map.Count());
                int maxDepth = -1;
                if (map.Count() > 0)
                {
                    maxDepth = map.Max(p => p.Depth);
                }
                for (int d = 0; d <= maxDepth; d++)
                {
                    //debug("Points for d=" + d + (culling.ContainsKey(d) ? ", " + culling[d] + " culled" : ""));
                    foreach (MapPoint point in map.Where(p => p.Depth == d))
                    {
                        string line = "(" + point.Position.X + ", " + point.Position.Y + ") ";
                        foreach (Point p in point.Trail)
                        {
                            line += "" + p.X + "," + p.Y + "->";
                        }
                        debug(line);
                    }
                }
            }

            //
            return(new Tuple <List <MapPoint>, List <MapPoint> >(map, culledMap));
        }
Ejemplo n.º 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);
        }