/// <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.CarryingTreasure) // can't move = can't dodge / if I'm shielded no point in dodging { return; } TreasureDancingState treasureDancingState = statesManager.GetState <TreasureDancingState>(); bool dodgedLastTurn = treasureDancingState.IsPirateDancing(this.myPirate); List <Pirate> enemies = game.GetEnemyPirates(PirateState.Free); if (enemies.Count == 0) // no enemies = no threat { return; } if (!dodgedLastTurn) //Pirate is carrying Treasure - can only move 1 step { foreach (var pair in GetTreasureDodgeOptions(this.myPirate, game)) { ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(this.myPirate, pair.Key), base.Id); double distanceLeft = Game.ManhattanDistance(pair.Key, this.myPirate.InitialLocation); double getCloserPrioritize = (distanceLeft == 0 ? myPirate.CarriedTreasureValue * 65536 : (distanceLeft + 1.0) / (distanceLeft)); //This is so it would prioritize moving in the direction that makes us closer. double value = myPirate.CarriedTreasureValue * PIRATE_WITH_TREASURE_DODGING - pair.Value / (pair.Value + 1.0) + getCloserPrioritize; ap.BurnInformation("Made by DodgeEvent - case: dodge attack, Value: {0:F3}", value); chooser.AddActionsPack(ap, value); } } else { ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(this.myPirate, this.myPirate), base.Id); double value = myPirate.CarriedTreasureValue * PIRATE_WITH_TREASURE_DODGING - 0.1; ap.BurnInformation("Made by DodgeEvent - case: dodge ram stage 2, Value: {0:F3}", value); chooser.AddActionsPack(ap, value); } foreach (var pair in GetRamDodgeOptions(this.myPirate, game)) { ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(this.myPirate, pair.Key), base.Id); double value = myPirate.CarriedTreasureValue * PIRATE_WITH_TREASURE_DODGING - pair.Value / (pair.Value + 1.0); ap.BurnInformation("Made by DodgeEvent - case: dodge ram stage 1, Value: {0:F3}", 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.treasurePirate.State != PirateState.CarryingTreasure) { return; } //Counts how many of the pirates in the cluster carry treasure, will be used for event value. List <Pirate> enemyPirates = new List <Pirate>(); foreach (Pirate enemy in game.GetEnemyPirates(PirateState.Free)) { if (Game.InAttackRange(enemy, treasurePirate, enemy.AttackRadius + enemy.MaxSpeed)) { enemyPirates.Add(enemy); } } enemyPirates = enemyPirates.OrderBy(p => Game.EuclideanDistance(p, this.treasurePirate)).ToList(); if (enemyPirates.Count == 0) //No threats { return; } TreasureDancingState treasureDancingState = statesManager.GetState <TreasureDancingState>(); ImpendingVictoryState impendingVictory = statesManager.GetState <ImpendingVictoryState>(); //Sends in an escort to destory/block an enemy foreach (Pirate myPirate in game.GetMyPirates(PirateState.Free)) { //Bodyguard foreach (Pirate enemy in enemyPirates) // try to block an enemy's path/destroy it { //1st priority - shoot him! if (game.IsAttackPossible(myPirate, enemy) && !game.IsAttackPossible(enemy, treasurePirate)) { ActionsPack ap = ActionsPack.NewCommandPack(game, new AttackCommand(myPirate, enemy), base.Id); double value = ESCORT_GUARD_VALUE - Game.EuclideanDistance(enemy, this.treasurePirate); if (impendingVictory.IsVictoryIncoming) { value = value * IMPENDING_VICTORY_MULTIPLYER; } value *= this.treasurePirate.CarriedTreasureValue; ap.BurnInformation("Made in EscortEvent - case: shoot threat, Value: {0:F3}", value); chooser.AddActionsPack(ap, value); } //2nd priority - ram him! if (Game.ManhattanDistance(enemy, myPirate) <= myPirate.MaxSpeed) { ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(myPirate, enemy), base.Id); ap.AddEnemyPirate(enemy); double value = ESCORT_GUARD_VALUE - Game.EuclideanDistance(enemy, this.treasurePirate) - Game.ManhattanDistance(enemy, myPirate); if (impendingVictory.IsVictoryIncoming) { value = value * IMPENDING_VICTORY_MULTIPLYER; } value *= this.treasurePirate.CarriedTreasureValue; ap.BurnInformation("Made in EscortEvent - case: ram enemy {0}, Value: {1:F3}", enemy.Id, value); chooser.AddActionsPack(ap, value); } //3rd priority - body block him if (Game.EuclideanDistance(enemy, treasurePirate) >= game.AttackRadius) { foreach (var pair in game.GetCompleteSailOptions(myPirate, ClosestOnCircle(myPirate.AttackRadius, this.treasurePirate, enemy), 0, 1, Terrain.CurrentTreasureLocation, Terrain.EnemyLocation)) { ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(myPirate, pair.Key), base.Id); double value = ESCORT_VALUE - Game.EuclideanDistance(enemy, this.treasurePirate) - Utils.Pow(pair.Value, 1.3); if (impendingVictory.IsVictoryIncoming) { value = value * IMPENDING_VICTORY_MULTIPLYER; } value *= this.treasurePirate.CarriedTreasureValue; ap.BurnInformation("Made in EscortEvent - case: block enemy {0}, Value: {1:F3}", enemy.Id, value); chooser.AddActionsPack(ap, value); } } } //This code does escorts even if there are no enemies close, currently not implemented /*else if (enemyPirates.Count <= 0) * { * foreach (var pair in game.GetCompleteSailOptions(myPirate, treasurePirate, Terrain.CurrentTreasureLocation, Terrain.EnemyLocation)) * { * ActionsPack ap = ActionsPack.NewCommandPack(game, new SailCommand(myPirate, pair.Key), base.Id); * * double value = 0.8 * (ESCORT_VALUE - Utils.Pow(Game.ManhattanDistance(myPirate, pair.Key), 1.3)); * if (impendingVictory.IsVictoryIncoming) * value = value * IMPENDING_VICTORY_MULTIPLYER; * value *= this.treasurePirate.CarriedTreasureValue; * * ap.BurnInformation("Made in EscortEvent - case: become escort, Value: {0:F3}", value); * * chooser.AddActionsPack(ap, value); * } * }*/ } }