Example #1
0
        /// <summary>
        /// Add possible responses to "chooser", based on the situation in "game" and in "statesManager"
        /// </summary>
        public override void AddResponseOptions(Game game, StatesManager statesManager, ActionsChooser chooser)
        {
            if (!this.myPirate.CanMove || this.myPirate.State != PirateState.Free)
            {
                return;
            }

            int myMaxSteps = myPirate.MaxSpeed;
            int enemyMaxSteps;

            double multiplyer = Utils.Pow(1 - ((double)game.GetMyPiratesCount(PirateState.CarryingTreasure)) / game.GetMyPiratesCount(PirateState.Free, PirateState.CarryingTreasure), 2);

            ThreatenedTreasureState treasureState = statesManager.GetState <ThreatenedTreasureState>();
            List <Treasure>         treasures     = treasureState.GetThreatenedTreasures().OrderBy(t => Game.ManhattanDistance(t, this.myPirate)).ToList();

            while (treasures.Count > 0 && game.GetPirateOn(treasures[0]) != null)
            {
                treasures.Remove(treasures[0]);
            }

            if (treasures.Count == 0)
            {
                return;
            }

            if (Game.ManhattanDistance(this.myPirate, treasures[0]) > myMaxSteps) //only do area clear if close enough to capture treasure
            {
                return;
            }

            Treasure closestTreasure = treasures[0];

            multiplyer *= closestTreasure.Value;

            foreach (Pirate enemy in game.GetEnemyPirates(PirateState.Free))
            {
                enemyMaxSteps = enemy.MaxSpeed;

                if (Game.ManhattanDistance(enemy, closestTreasure) > enemyMaxSteps)//only do area clear if enemy is close enough to capture treasure
                {
                    continue;
                }

                if (!Game.InAttackRange(this.myPirate, closestTreasure, this.myPirate.AttackRadius + 1)) //Get closer.
                {
                    var sailOptions = game.GetCompleteSailOptions(this.myPirate, closestTreasure, (int)this.myPirate.AttackRadius + 1, (int)this.myPirate.AttackRadius + 1, Terrain.InEnemyRange, Terrain.CurrentTreasureLocation);
                    foreach (var pair in sailOptions)
                    {
                        ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(this.myPirate, pair.Key), this.Id);

                        ap.AddTreasure(treasures[0]);

                        double value = CLEAR_VALUE * multiplyer;

                        ap.BurnInformation("Made in AreaClearEvent on Treasure {0} - case: not close enough, Value {1:F3}", closestTreasure.Id, value);

                        chooser.AddActionsPack(ap, value);
                    }
                }
                else if (Game.InAttackRange(this.myPirate, closestTreasure, this.myPirate.AttackRadius) && this.myPirate.CanAttack && enemy.DefenseDuration == 0 && Game.InAttackRange(this.myPirate, enemy, this.myPirate.AttackRadius)) //Attack enemy.
                {
                    ActionsPack ap = ActionsPack.NewCommandPack(game, new AttackCommand(this.myPirate, enemy), this.Id);

                    ap.AddTreasure(treasures[0]);
                    ap.AddEnemyPirate(enemy);

                    double value = CLEAR_VALUE * multiplyer;

                    ap.BurnInformation("Made in AreaClearEvent on Treasure {0} - case: too close, attack pirate {1}, Value: {2:F3}", closestTreasure.Id, enemy.Id, value);

                    chooser.AddActionsPack(ap, value);
                }
                else if (Game.InAttackRange(this.myPirate, closestTreasure, this.myPirate.AttackRadius + 1)) //Stay Still. TODO: ask Adi/Itai why isn't this an else
                {
                    ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(this.myPirate, this.myPirate), this.Id);
                    ap.AddTreasure(closestTreasure);

                    double value = CLEAR_VALUE * multiplyer;

                    ap.BurnInformation("Made in AreaClearEvent on Treasure {0} - case: close enough, Value {1:F3}", closestTreasure.Id, value);

                    chooser.AddActionsPack(ap, value);
                }
            }
        }
        /// <summary>
        /// Add possible responses to "chooser", based on the situation in "game" and in "statesManager"
        /// </summary>
        public override void AddResponseOptions(Game game, StatesManager statesManager, ActionsChooser chooser)
        {
            if (!this.myPirate.CanMove || this.myPirate.State != PirateState.Free) //If my pirate can't move or isn't free, he can't go to fetch treasures.
            {
                return;
            }

            // Get threatened treasure state
            ThreatenedTreasureState treasureState = statesManager.GetState <ThreatenedTreasureState>();
            // Get all the free treasures and sort them by manhattan distance to me
            List <Treasure> freeTreasures = treasureState.GetSafeTreasures().OrderBy(t => Game.ManhattanDistance(t, this.myPirate)).ToList();


            // calculate the maximum amount of treasures to check
            int maxTreasuresToCheck = (int)Utils.Min(freeTreasures.Count, game.GetMyPiratesCount(PirateState.Free), game.ActionsPerTurn, game.MaxCommandsPerTurn);

            // remove all the excess treasures, based on their value
            Dictionary <int, int> usedTreasuresDict = new Dictionary <int, int>();   // the key is the value of the treasure, and the value is how many treasures with the value are already in the list

            for (int i = 0; i < freeTreasures.Count;)
            {
                if (usedTreasuresDict.ContainsKey(freeTreasures[i].Value))
                {
                    usedTreasuresDict[freeTreasures[i].Value]++;
                    if (usedTreasuresDict[freeTreasures[i].Value] > maxTreasuresToCheck)
                    {
                        freeTreasures.RemoveAt(i);
                    }
                    else
                    {
                        i++;
                    }
                }
                else
                {
                    usedTreasuresDict.Add(freeTreasures[i].Value, 1);
                    i++;
                }
            }


            double multiplyer = Utils.Pow(1 - ((double)game.GetMyPiratesCount(PirateState.CarryingTreasure)) / game.GetMyPiratesCount(PirateState.Free, PirateState.CarryingTreasure), 2);

            // try to sail to each treasure
            foreach (Treasure t in freeTreasures)
            {
                if (game.GetPirateOn(t) != null) // there is a pirate where the treasure is, most likely a drunk one. Leave it be.
                {
                    continue;
                }

                ILocateable dest = t;
                // search for a speed powerup on the way to the treasure
                foreach (Powerup up in game.GetPowerups())
                {
                    if (up is SpeedPowerup && Game.OnTrack(myPirate, t, up))
                    {
                        dest = up;
                        break;
                    }
                }

                var sailOptions    = game.GetCompleteSailOptions(this.myPirate, dest, Terrain.EnemyLocation, Terrain.CurrentTreasureLocation);
                int maxActionsUsed = (int)Utils.Min(this.myPirate.MaxSpeed, game.ActionsPerTurn, Game.ManhattanDistance(this.myPirate, dest));

                foreach (var pair in sailOptions)
                {
                    if (sailOptions[0].Value > pair.Value) //sail only if it's actually better than staying in place
                    {
                        ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(this.myPirate, pair.Key), base.Id);

                        ap.AddTreasure(t);

                        double returnDistance = Game.ManhattanDistance(this.myPirate.InitialLocation, t);
                        double maxDistance    = game.Rows + game.Collumns;
                        double value          = (FETCH_VALUE - Utils.Pow(pair.Value, 0.9)) * multiplyer * ((maxDistance - returnDistance) / (maxDistance));
                        if (game.GetTreasuresCount(TreasureState.BeingCarried, TreasureState.Taken) == 0 && Game.ManhattanDistance(pair.Key, this.myPirate) == maxActionsUsed)
                        {
                            value += GAME_START_MULT;
                        }
                        value *= t.Value;
                        if (myPirate.HasPowerup(SpeedPowerup.NAME))
                        {
                            value *= SPEED_POWERUP_MULTIPLYER;
                        }

                        ap.BurnInformation("Made in FetchTreasureEvent. Fetching Treasure: {0}, value: {1:F3}", t.Id, value);

                        chooser.AddActionsPack(ap, value);
                    }
                }
            }
        }