示例#1
0
 /// <summary>
 /// Destination for a movement. Ignores all robots on the map but does take into account walls, conveyor belts and gears. Returns
 /// the final location of the move.
 /// </summary>
 /// <param name="map">The game map.</param>
 /// <param name="startLocation">Where the unit starts.</param>
 /// <param name="cards">The cards to apply.</param>
 /// <returns>The final location of the move.</returns>
 public static MovePoint CardDestination(GameMap map, BoardLocation startLocation, IEnumerable<Card> cards)
 {
     List<MovePoint> points = CardPath(map, startLocation, cards);
     if ((points == null) || (points.Count == 0))
         return null;
     return points[points.Count - 1];
 }
示例#2
0
 /// <summary>
 /// Calculates what damage a unit will receive from lasers at a given location.
 /// </summary>
 /// <param name="map">The game map.</param>
 /// <param name="location">Where the unit is located.</param>
 /// <returns>The amount of damage. Will be 0 or 1.</returns>
 public static int CalcLaserDamage(GameMap map, BoardLocation location)
 {
     int damage = 0;
     damage += _CalcLaserDamage(map, location.MapPosition, 0, -1, MapSquare.DIRECTION.SOUTH, MapSquare.SIDE.NORTH, MapSquare.SIDE.SOUTH);
     damage += _CalcLaserDamage(map, location.MapPosition, 0, 1, MapSquare.DIRECTION.NORTH, MapSquare.SIDE.SOUTH, MapSquare.SIDE.NORTH);
     damage += _CalcLaserDamage(map, location.MapPosition, -1, 0, MapSquare.DIRECTION.EAST, MapSquare.SIDE.WEST, MapSquare.SIDE.EAST);
     damage += _CalcLaserDamage(map, location.MapPosition, 1, 0, MapSquare.DIRECTION.WEST, MapSquare.SIDE.EAST, MapSquare.SIDE.WEST);
     return damage;
 }
示例#3
0
        /// <summary>
        /// Destination for a movement. Ignores all robots on the map but does take into account walls, conveyor belts and gears. Returns
        /// every step of the move.
        /// </summary>
        /// <param name="map">The game map.</param>
        /// <param name="startLocation">Where the unit starts.</param>
        /// <param name="cards">The cards to apply.</param>
        /// <returns>Every step of the move.</returns>
        public static List<MovePoint> CardPath(GameMap map, BoardLocation startLocation, IEnumerable<Card> cards)
        {
            // if we can't move, we end up where we started
            List<MovePoint> points = new List<MovePoint> {new MovePoint(startLocation)};

            foreach (Card cardOn in cards)
            {
                // move robot
                MovePoint endLocation = Move(map, startLocation, cardOn.Move);
                if (endLocation.Dead)
                {
                    points.Add(endLocation);
                    return points;
                }
                if (! endLocation.Location.Equals(startLocation))
                {
                    startLocation = endLocation.Location;
                    points.Add(new MovePoint(startLocation));
                }

                // conveyor belt - may cause a 1/4 turn.
                MapSquare sq = map.GetSquare(startLocation.MapPosition);
                for (int speed=1; (sq.Conveyor != null) && (speed <= sq.Conveyor.Speed); speed++)
                {
                    endLocation = Move(map, startLocation.MapPosition, sq.Conveyor.Direction);
                    BoardLocation locMove = new BoardLocation(endLocation.Location.MapPosition, startLocation.Direction);
                    sq = map.GetSquare(endLocation.Location.MapPosition);
                    if (sq.Conveyor != null)
                    {
                        MapSquare.DIRECTION dirEnter = MoveDirection(startLocation.MapPosition, endLocation.Location.MapPosition);
                        locMove = locMove.Rotate((int)sq.Conveyor.Direction - (int)dirEnter);
                    }
                    startLocation = locMove;
                    points.Add(new MovePoint(startLocation));
                }

                // gears
                if (sq.Type == MapSquare.TYPE.ROTATE_CLOCKWISE)
                {
                    startLocation = startLocation.Rotate(1);
                    points.Add(new MovePoint(startLocation));
                }
                if (sq.Type == MapSquare.TYPE.ROTATE_COUNTERCLOCKWISE)
                {
                    startLocation = startLocation.Rotate(-1);
                    points.Add(new MovePoint(startLocation));
                }

                // damage
                int damage = CalcLaserDamage(map, startLocation);
                if (damage != 0)
                    points[points.Count - 1].Damage = damage;
            }

            return points;
        }
示例#4
0
 /// <summary>
 /// Called when your robot must be placed on the board. This is called at the start of the game and each time your robot dies.
 /// </summary>
 /// <param name="map">The game map. There will be no units on this map.</param>
 /// <param name="you">Your player object.</param>
 /// <param name="players">All players (including you).</param>
 /// <param name="robotStart">The position(s) on the map where you can place your robot. This will be a single point unless another robot is on your archive point.</param>
 /// <param name="gameStart">true if start of a game. false if re-entering the game.</param>
 /// <returns>Where to place your unit (location and direction.</returns>
 public BoardLocation Setup(GameMap map, Player you, List<Player> players, List<Point> robotStart, bool gameStart)
 {
     return new BoardLocation(robotStart[0], MapSquare.DIRECTION.NORTH);
 }
示例#5
0
        /// <summary>
        /// Called each time the system needs another turn. If you do not return a valid turn, the game will randomly move one of your units.
        /// This call must return in under 1 second. If it has not returned in 1 second the call will be aborted and a random move will be assigned.
        /// </summary>
        /// <param name="map">The game map with all units on it.</param>
        /// <param name="you">Your player object. This is created for each call.</param>
        /// <param name="allPlayers">All players including you. This is created for each call.</param>
        /// <param name="cards">The cards you get to pick from. This does not include locked cards.</param>
        /// <returns>Your requested turn.</returns>
        public PlayerTurn Turn(GameMap map, Player you, List<Player> allPlayers, List<Card> cards)
        {
            // if hurt bad, consider power down
            bool powerDown = false;
            if ((you.Damage > 5) && (rand.Next(4) == 0))
                powerDown = true;

            // get 40 sets, pick the one that's closest to the flag (middle of the board if got all flags)
            List<Card> best = null;
            int bestDiff = int.MaxValue;
            int okDiff = rand.Next(0, 3);
            FlagState fs = you.FlagStates.FirstOrDefault(fsOn => !fsOn.Touched);
            Point ptFlag = fs == null ? new Point(map.Width / 2, map.Height / 2) : fs.Position;
            for (int turnOn = 0; turnOn < 40; turnOn++)
            {
                // pick NUM_CARDS (or fewer if locked) random cards
                List<Card> moveCards = new List<Card>();
                bool[] cardUsed = new bool[cards.Count];
                for (int ind = 0; ind < NUM_CARDS - you.NumLockedCards; ind++)
                    for (int iter = 0; iter < 100; iter++) // in case can't work it with these cards
                        {
                            int index = rand.Next(cards.Count);
                            if (cardUsed[index])
                                continue;
                            moveCards.Add(cards[index]);
                            cardUsed[index] = true;
                            break;
                        }

                // add in the locked cards
                for (int ind = NUM_CARDS - you.NumLockedCards; ind < NUM_CARDS; ind++)
                    moveCards.Add(you.Cards[ind]);

                // If all we have are rotates, we add in a move forward 1 so that a card that is a turn can then take into account next time we get a forward 1.
                bool addMove = moveCards.All(card => card.IsRotate);
                if (addMove)
                    moveCards.Add(new Card(Card.ROBOT_MOVE.FORWARD_ONE, 500));

                // run it
                Utilities.MovePoint mp = Utilities.CardDestination(map, you.Robot.Location, moveCards);

                // if it kills us we don't want it
                if (mp.Dead)
                    continue;

                // if better than before, use it
                if (addMove)
                    moveCards.RemoveAt(moveCards.Count - 1);
                int diff = Math.Abs(ptFlag.X - mp.Location.MapPosition.X) + Math.Abs(ptFlag.Y - mp.Location.MapPosition.Y);
                if (diff <= okDiff)
                    return new PlayerTurn(new List<Card>(moveCards), powerDown);
                if (diff < bestDiff)
                {
                    bestDiff = diff;
                    best = moveCards;
                }
            }

            return new PlayerTurn(best == null ? new List<Card>() : new List<Card>(best), powerDown);
        }
示例#6
0
        private static int _CalcLaserDamage(GameMap map, Point position, int xAdd, int yAdd, MapSquare.DIRECTION laserDirection, MapSquare.SIDE wallExit, MapSquare.SIDE wallEnter)
        {
            int damage = 0;
            int x = position.X;
            int y = position.Y;
            bool startSquare = true;

            while ((0 <= x) && (x < map.Width) && (0 <= y) && (y < map.Height))
            {
                MapSquare sq = map.Squares[x][y];
                // can we move into this square?
                if ((! startSquare) && ((sq.Walls & wallEnter) != 0))
                    break;
                startSquare = false;

                if ((sq.Laser != null) && (sq.Laser.Location.Direction == laserDirection))
                {
                    damage++;
                    break;
                }

                // can we move out of this square?
                if ((sq.Walls & wallExit) != 0)
                    break;
                x += xAdd;
                y += yAdd;
            }
            return damage;
        }
示例#7
0
        /// <summary>
        /// Move a unit one square in the requested direction. Ignores all robots on the map but does take into account walls, conveyor belts and gears.
        /// </summary>
        /// <param name="map">The game map.</param>
        /// <param name="position">The map square to start the move from.</param>
        /// <param name="direction">The direction to move.</param>
        /// <returns>The final location of the move.</returns>
        public static MovePoint Move(GameMap map, Point position, MapSquare.DIRECTION direction)
        {
            // watch for wall in this direction
            MapSquare.SIDE sideExit = sideMoveOut[(int) direction];
            MapSquare.SIDE sideEnter = sideMoveIn[(int) direction];
            BoardLocation location = new BoardLocation(position, direction);

            // can we exit this square?
            MapSquare sq = map.GetSquare(position);
            if ((sq.Walls & sideExit) != 0)
                return new MovePoint(location);
            BoardLocation moveTo = location.Move(1);

            // did we go off the board?
            if ((moveTo.MapPosition.X < 0) || (map.Width <= moveTo.MapPosition.X) ||
                (moveTo.MapPosition.Y < 0) || (map.Height <= moveTo.MapPosition.Y))
                return new MovePoint(location, true);

            // did we go into a pit?
            if (map.GetSquare(moveTo.MapPosition).Type == MapSquare.TYPE.PIT)
                return new MovePoint(moveTo, true);

            // can we enter the new square?
            sq = map.GetSquare(moveTo.MapPosition);
            if ((sq.Walls & sideEnter) != 0)
                return new MovePoint(location);

            return new MovePoint(moveTo);
        }
示例#8
0
        /// <summary>
        /// Move a unit one card move. Ignores all robots on the map but does take into account walls, conveyor belts and gears.
        /// </summary>
        /// <param name="map">The game map.</param>
        /// <param name="startLocation">Where the unit starts.</param>
        /// <param name="move">The move to apply.</param>
        /// <returns>The final location of the move.</returns>
        public static MovePoint Move(GameMap map, BoardLocation startLocation, Card.ROBOT_MOVE move)
        {
            int steps = 0;
            switch (move)
            {
                case Card.ROBOT_MOVE.BACKWARD_ONE:
                    steps = -1;
                    break;
                case Card.ROBOT_MOVE.FORWARD_ONE:
                    steps = 1;
                    break;
                case Card.ROBOT_MOVE.FORWARD_TWO:
                    steps = 2;
                    break;
                case Card.ROBOT_MOVE.FORWARD_THREE:
                    steps = 3;
                    break;
                case Card.ROBOT_MOVE.ROTATE_LEFT:
                    return new MovePoint(startLocation.Rotate(-1));
                case Card.ROBOT_MOVE.ROTATE_RIGHT:
                    return new MovePoint(startLocation.Rotate(1));
                case Card.ROBOT_MOVE.ROTATE_UTURN:
                    return new MovePoint(startLocation.Rotate(2));
            }

            MapSquare.DIRECTION dir = steps >= 0 ? startLocation.Direction : startLocation.Rotate(2).Direction;
            Point position = startLocation.MapPosition;
            while (steps != 0)
            {
                MovePoint mp = Move(map, position, dir);
                if (mp.Dead)
                    return new MovePoint(new BoardLocation(mp.Location.MapPosition, startLocation.Direction), true);
                position = mp.Location.MapPosition;
                int singleStep = Math.Max(-1, Math.Min(1, steps));
                steps -= singleStep;
            }
            return new MovePoint(new BoardLocation(position, startLocation.Direction));
        }