/// <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);
 }
Beispiel #2
0
        /// <summary>
        /// alpha * (score + 0.5*distance_to_dest)) - beta * (time_to_location + pickup_time + time_to_dest)
        /// </summary>
        /// <param name="passenger"></param>
        /// <returns></returns>
        private double SinglePassengerWeight(Player player, Passenger passenger)
        {
            // get the wiehgts from the configuration file
            double ALPHA = 7.0;
            double BETA = 1.0;
            double DIST_CONTSTANT = 0.5;
            // time to perform pickup of player
            int PICKUP_TIME = 130;

            if (passenger.Lobby != null ) {
                return ALPHA * (passenger.PointsDelivered + DIST_CONTSTANT
                    * pFinder.DistanceSrcDest(passenger.Lobby.BusStop, passenger.Destination.BusStop))
                    - BETA * (pFinder.getTimeForPath(pFinder.computeFastestPath(player.Limo.TilePosition, passenger.Lobby.BusStop)) + PICKUP_TIME + pFinder.getTimeForPath(pFinder.computeFastestPath(passenger.Lobby.BusStop, passenger.Route[0].BusStop))
                );
            } else {
                return -1.0F;
            }
        }
        /// <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);
        }
Beispiel #4
0
 /// <summary>
 /// A dictionary containing values of all passengers that are not in limos
 /// </summary>
 /// <param name="passengers"></param>
 /// <returns></returns>
 private SortedDictionary<float, Passenger> GetPassengerWeights(Player player, List<Passenger> passengers)
 {
     SortedDictionary<float, Passenger> weights = new SortedDictionary<float, Passenger>();
     for (int i = 0; i < passengers.Count; i++)
     {
         if (passengers[i].Lobby != null) {
             weights.Add((float)SinglePassengerWeight(player, passengers[i]), passengers[i]);
         }
     }
     return weights;
 }
Beispiel #5
0
        private List<Passenger> MakeDecision(PlayerAIBase.STATUS status, Player plyrStatus, List<Player> players, List<Passenger> passengers)
        {
            if (Me.Limo.Passenger != null)
                return Me.PickUp;
            switch (status)
            {
                // action should always be :
                // make sure action is still the desired one
                // if not, compare the scores of top actions
                // if there's not a big difference, stay on current action
                case PlayerAIBase.STATUS.UPDATE:
                // default action
                case PlayerAIBase.STATUS.NO_PATH:
                // that's fine, default action
                case PlayerAIBase.STATUS.PASSENGER_NO_ACTION:
                // if we have no passenger, decide who we want.
                // if we have a passenger, make sure we still want them.
                // that's the default action
                case PlayerAIBase.STATUS.PASSENGER_DELIVERED:
                // default action
                case PlayerAIBase.STATUS.PASSENGER_ABANDONED:
                // default action
                case PlayerAIBase.STATUS.PASSENGER_REFUSED:
                // default action
                case PlayerAIBase.STATUS.PASSENGER_DELIVERED_AND_PICKED_UP:
                //default action
                case PlayerAIBase.STATUS.PASSENGER_PICKED_UP:
                // default action
                default:
                    {

                        // Go to the best-expected company.
                        SortedDictionary<float, Company> bestBusStop = new SortedDictionary<float, Company>();
                        foreach (Company company in GameInfo.activeBusStops())
                        {
                            // Sort passengers at this stop.
                            SortedDictionary<float, Passenger> passengersAtStop = GetPassengerWeights(Me, GameInfo.PassengerAtLocation(company));

                            // TODO: Ensure descending order.
                            // Time for us to get there
                            float our_time = (float)pFinder.getTimeForPath(pFinder.computeFastestPath(Me.Limo.TilePosition, company.BusStop));
                            // Number of other players closer/same than us. Buffer time of 100sec.
                            int other_players = GameInfo.OtherPlayersWithinTimeToLocation(our_time+100f, company.BusStop).Count;

                            // If there's one enemy within range, the 2nd highest has to be good enough. If 3rd, they have to be high enough. Etc.
                            int minCount = Math.Min(other_players, passengersAtStop.Count);
                            float average = 0;
                            // have to go in descending order for this.
                            for (int i = passengersAtStop.Count-1; i >= passengersAtStop.Count-minCount; i--) {
                                average += passengersAtStop.Keys.ToList()[i];
                            }
                           /* for (int i = 0; i < minCount; i++)
                            {
                                average += passengersAtStop.Keys.ToList()[i];
                            }*/
                            average /= minCount;

                            // Add the average value & company to result
                            bestBusStop.Add(average, company);
                        }
                        // go to the best bus stop. Set the desired player_list to the top at the bus stop
                        int numberOfResults = bestBusStop.Count;
                        Company winningCompany = bestBusStop.Values.ToList()[numberOfResults-1];

                        //List<Point> path = pFinder.computeFastestPath(Me.Limo.TilePosition, winningCompany.BusStop);
                        List<Passenger> passengerList = GetPassengerWeights(Me, GameInfo.PassengerAtLocation(winningCompany)).Values.ToList();
                        passengerList.Reverse();

                        return passengerList;

                    }

            }
        }
Beispiel #6
0
 private List<Point> CalculatePathPlus1(Player me, Point ptDest)
 {
     List<Point> path = SimpleAStar.CalculatePath(GameMap, me.Limo.TilePosition, ptDest);
     // add in leaving the bus stop so it has orders while we get the message saying it got there and are deciding what to do next.
     if (path.Count > 1)
         path.Add(path[path.Count - 2]);
     return path;
 }
Beispiel #7
0
 /// <summary>
 /// Returns the time it will take for a player to get to destination point
 /// </summary>
 /// <param name="me">Player object</param>
 /// <param name="ptDest">Destination Point</param>
 /// <returns></returns>
 private int CalculateDestTime(Player me, Point ptDest)
 {
     return -1;
 }
Beispiel #8
0
 private static List<Passenger> AllPickups(Player me, IEnumerable<Passenger> passengers)
 {
     List<Passenger> pickup = new List<Passenger>();
     pickup.AddRange(passengers.Where(
             psngr =>
             (!me.PassengersDelivered.Contains(psngr)) && (psngr != me.Limo.Passenger) && (psngr.Car == null) &&
             (psngr.Lobby != null) && (psngr.Destination != null)).OrderBy(psngr => rand.Next()));
     return pickup;
 }
Beispiel #9
0
        /// <summary>
        /// Called at the start of the game.
        /// </summary>
        /// <param name="map">The game map.</param>
        /// <param name="me">You. This is also in the players list.</param>
        /// <param name="players">All players (including you).</param>
        /// <param name="companies">The companies on the map.</param>
        /// <param name="passengers">The passengers that need a lift.</param>
        /// <param name="ordersEvent">Method to call to send orders to the server.</param>
        public void Setup(Map map, Player me, List<Player> players, List<Company> companies, List<Passenger> passengers,
            PlayerAIBase.PlayerOrdersEvent ordersEvent)
        {
            try
            {
                pFinder = new PathFinder();
                GameMap = map;
                GameInfo = new GameStatusInfo();
                GameInfo.Setup(map, pFinder);
                Players = players;
                Me = me;
                Companies = companies;
                Passengers = passengers;
                sendOrders = ordersEvent;

                List<Passenger> pickup = AllPickups(me, passengers);
                pFinder.computeAllPaths(map);
                pFinder.generateAdjacencyMatrix();

                // get the path from where we are to the dest.
                List<Point> path = CalculatePathPlus1(me, pickup[0].Lobby.BusStop);
                sendOrders("ready", path, pickup);
            }
            catch (Exception ex)
            {
                log.Fatal(string.Format("Setup({0}, ...", me == null ? "{null}" : me.Name), ex);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Called to send an update message to this A.I. We do NOT have to send orders in response. 
        /// </summary>
        /// <param name="status">The status message.</param>
        /// <param name="plyrStatus">The player this status is about. THIS MAY NOT BE YOU.</param>
        /// <param name="players">The status of all players.</param>
        /// <param name="passengers">The status of all passengers.</param>
        public void GameStatus(PlayerAIBase.STATUS status, Player plyrStatus, List<Player> players, List<Passenger> passengers)
        {
            // bugbug - Framework.cs updates the object's in this object's Players, Passengers, and Companies lists. This works fine as long
            // as this app is single threaded. However, if you create worker thread(s) or respond to multiple status messages simultaneously
            // then you need to split these out and synchronize access to the saved list objects.

            try
            {
                // bugbug - we return if not us because the below code is only for when we need a new path or our limo hit a bus stop.
                // if you want to act on other players arriving at bus stops, you need to remove this. But make sure you use Me, not
                // plyrStatus for the Player you are updatiing (particularly to determine what tile to start your path from).
                if (plyrStatus != Me)
                    return;

                GameInfo.update(players, passengers);

                Point ptDest;
                List<Passenger> pickup = new List<Passenger>();

               				// determine where we want to go and who we want to pick up
                switch (status)
                {
                    case PlayerAIBase.STATUS.UPDATE:
                        return;
                    case PlayerAIBase.STATUS.NO_PATH:
                    case PlayerAIBase.STATUS.PASSENGER_NO_ACTION:
                        if (plyrStatus.Limo.Passenger == null)
                        {
                            pickup = MakeDecision(status, plyrStatus, players, passengers);
                            ptDest = pickup[0].Lobby.BusStop;
                        }
                        else
                            ptDest = plyrStatus.Limo.Passenger.Destination.BusStop;
                        break;
                    case PlayerAIBase.STATUS.PASSENGER_DELIVERED:
                    case PlayerAIBase.STATUS.PASSENGER_ABANDONED:
                        pickup = MakeDecision(status, plyrStatus, players, passengers);
                        ptDest = pickup[0].Lobby.BusStop;
                        break;
                    case PlayerAIBase.STATUS.PASSENGER_REFUSED:
                        pickup = MakeDecision(status, plyrStatus, players, passengers);
                        ptDest = pickup[0].Lobby.BusStop;
                        break;
                    case PlayerAIBase.STATUS.PASSENGER_DELIVERED_AND_PICKED_UP:
                    case PlayerAIBase.STATUS.PASSENGER_PICKED_UP:
                        pickup = MakeDecision(status, plyrStatus, players, passengers);
                        ptDest = pickup[0].Lobby.BusStop;
                        break;
                    default:
                        throw new ApplicationException("unknown status");
                }

                // get the path from where we are to the dest.
                List<Point> path = CalculatePathPlus1(plyrStatus, ptDest);

                if (log.IsDebugEnabled)
                    log.Debug(string.Format("{0}; Path:{1}-{2}, {3} steps; Pickup:{4}, {5} total",
                        status,
                        path.Count > 0 ? path[0].ToString() : "{n/a}",
                        path.Count > 0 ? path[path.Count - 1].ToString() : "{n/a}",
                        path.Count,
                        pickup.Count == 0 ? "{none}" : pickup[0].Name,
                        pickup.Count));

                // update our saved Player to match new settings
                if (path.Count > 0)
                {
                    Me.Limo.Path.Clear();
                    Me.Limo.Path.AddRange(path);
                }
                if (pickup.Count > 0)
                {
                    Me.PickUp.Clear();
                    Me.PickUp.AddRange(pickup);
                }

                sendOrders("move", path, pickup);
            }
            catch (Exception ex)
            {
                log.Error(string.Format("GameStatus({0}, {1}, ...", status, plyrStatus == null ? "{null}" : plyrStatus.Name), ex);
            }
        }