コード例 #1
0
ファイル: Debug.cs プロジェクト: Norman1/Multiattack-Bot
        public static void PrintTerritories(BotMap map, BotMain BotState)
        {
            List <BotTerritory> territories = map.Territories.Values.ToList();

            //List<BotTerritory> opponentTerritories = territories.Where(o => o.OwnerPlayerID == BotState.Opponents.First().ID).ToList();
            AILog.Log("Debug", "Territories:");
            foreach (BotTerritory territory in territories)
            {
                string player = "fog";
                if (territory.OwnerPlayerID == TerritoryStanding.NeutralPlayerID)
                {
                    player = "neutral";
                }
                else if (territory.OwnerPlayerID == BotState.Me.ID)
                {
                    player = "Me";
                }
                else if (territory.OwnerPlayerID == BotState.Opponents.First().ID)
                {
                    player = "opponent";
                }

                AILog.Log("Debug", territory.Details.Name + ": (" + player + " | " + territory.IsOwnershipHeuristic + ")  --> " + territory.Armies.AttackPower);
            }
        }
コード例 #2
0
        /// <summary>
        /// Runs the commander away from opponents
        /// </summary>
        private static void DoCommander(BotMain bot, TerritoryStanding cmdrTerritory, Commander cmdr)
        {
            var directive = CommanderDirective(bot, cmdrTerritory.ID);

            if (directive.HasValue)
            {
                AILog.Log("SpecialUnits", "Directive directs us to move the commander from " + bot.TerrString(cmdrTerritory.ID) + " to " + bot.TerrString(directive.Value));

                if (directive.Value != cmdrTerritory.ID)
                {
                    bot.Orders.AddAttack(cmdrTerritory.ID, directive.Value, AttackTransferEnum.AttackTransfer, cmdrTerritory.NumArmies.NumArmies, false, commanders: true);
                }
                bot.AvoidTerritories.Add(cmdrTerritory.ID); //add this so we don't deploy there, we want the commander to stay alone
                return;
            }

            var powerDiff = bot.Map.Territories[cmdrTerritory.ID].ConnectedTo.Keys
                            .Select(o => bot.Standing.Territories[o])
                            .Where(o => bot.IsOpponent(o.OwnerPlayerID) && o.NumArmies.Fogged == false)
                            .Sum(o => o.NumArmies.AttackPower)
                            - cmdrTerritory.NumArmies.DefensePower;
            var toDeploy = Math.Max(0, powerDiff);

            if (powerDiff > 0)
            {
                if (bot.UseRandomness)
                {
                    toDeploy = SharedUtility.Round(toDeploy * RandomUtility.BellRandom(0.5, 1.5));
                }
                if (toDeploy > bot.MakeOrders.IncomeTracker.RemainingUndeployed)
                {
                    toDeploy = bot.MakeOrders.IncomeTracker.RemainingUndeployed;
                }

                if (toDeploy > 0 && bot.Orders.TryDeploy(cmdrTerritory.ID, toDeploy))
                {
                    AILog.Log("SpecialUnits", "Deployed " + toDeploy + " to defend commander");
                }
            }

            //Consider this territory and all adjacent territories.  Which is the furthest from any enemy?
            var terrDistances = bot.Map.Territories[cmdrTerritory.ID].ConnectedTo.Keys.ConcatOne(cmdrTerritory.ID)
                                .Where(o => bot.Standing.Territories[o].OwnerPlayerID == bot.PlayerID || bot.Standing.Territories[o].NumArmies.DefensePower <= 4) //don't go somewhere that's defended heavily
                                .ToDictionary(o => o, o => bot.DistanceFromEnemy(o));

            AILog.Log("SpecialUnits", "Commander run options: " + terrDistances.Select(o => bot.TerrString(o.Key) + " dist=" + o.Value).JoinStrings(", "));

            var sorted = terrDistances.OrderByDescending(o => o.Value).ToList();

            sorted.RemoveWhere(o => o.Value < sorted[0].Value);

            var runTo = bot.UseRandomness ? sorted.Random().Key : sorted[0].Key;

            if (runTo == cmdrTerritory.ID)
            {
                return; //already there
            }
            AILog.Log("SpecialUnits", "Moving commander from " + bot.TerrString(cmdrTerritory.ID) + " to " + bot.TerrString(runTo));
            bot.Orders.AddAttack(cmdrTerritory.ID, runTo, AttackTransferEnum.AttackTransfer, cmdrTerritory.NumArmies.NumArmies + toDeploy, false, commanders: true);
        }
コード例 #3
0
        public static List <TerritoryIDType> Go(BotMain bot, HashSet <TerritoryIDType> allAvailable, int maxPicks)
        {
            var expansionWeights = allAvailable.ToDictionary(o => o, o => GetExpansionWeight(bot, o));

            var ordered = expansionWeights.OrderByDescending(o => o.Value).ToList();

            AILog.Log("PickTerritories", "Came up with " + expansionWeights.Count + " expansion weights: ");
            foreach (var e in ordered.Take(30))
            {
                AILog.Log("PickTerritories", " - " + bot.TerrString(e.Key) + ": " + e.Value);
            }

            if (!bot.UseRandomness)
            {
                return(ordered.Select(o => o.Key).Take(maxPicks).ToList());
            }

            //Normalize weights
            var top        = ordered.Take(maxPicks * 2);
            var sub        = top.Min(o => o.Value) - 1;
            var normalized = top.ToDictionary(o => o.Key, o => o.Value - sub);

            var picks = new List <TerritoryIDType>();

            while (picks.Count < maxPicks && normalized.Count > 0)
            {
                var pick = RandomUtility.WeightedRandom(normalized.Keys, o => normalized[o]);
                picks.Add(pick);
                normalized.Remove(pick);
            }
            return(picks);
        }
コード例 #4
0
ファイル: Debug.cs プロジェクト: Norman1/WarLightAI
        public static void PrintTerritoryValues(BotMap map, BotMain BotState)
        {
            AILog.Log("Territory attack values:");
            foreach (BotTerritory territory in map.Territories.Values)
            {
                if (territory.IsVisible && BotState.IsOpponent(territory.OwnerPlayerID))
                {
                    AILog.Log(territory.Details.Name + ": " + territory.AttackTerritoryValue);
                }
            }

            AILog.Log("Territory expansion values:");
            foreach (BotTerritory territory in map.Territories.Values)
            {
                if (territory.IsVisible && territory.OwnerPlayerID == TerritoryStanding.NeutralPlayerID)
                {
                    AILog.Log(territory.Details.Name + ": " + territory.ExpansionTerritoryValue);
                }
            }

            AILog.Log("Territory defend values:");
            foreach (BotTerritory territory in map.Territories.Values)
            {
                if (territory.OwnerPlayerID == BotState.Me.ID && territory.GetOpponentNeighbors().Count > 0)
                {
                    AILog.Log(territory.Details.Name + ": " + territory.DefenceTerritoryValue);
                }
            }
        }
コード例 #5
0
ファイル: Moves.cs プロジェクト: Joi179/WarLight.AI
        public void DumpToLog()
        {
            AILog.Log("MovesCalculator", "Final " + Orders.Count + " orders:");

            foreach (var order in Orders)
            {
                if (order is BotOrderDeploy)
                {
                    var dep = (BotOrderDeploy)order;
                    AILog.Log("MovesCalculator", " - " + dep.Armies + " on " + dep.Territory.Details.Name + " " + dep.Territory.ToString());
                }
                else if (order is BotOrderAttackTransfer)
                {
                    var attack = (BotOrderAttackTransfer)order;

                    AILog.Log("MovesCalculator", " - " + attack.From.Details.Name + " -> " + attack.To.Details.Name + " " + attack.Armies + " Message=" + attack.Message + ", Source=" + attack.Source);
                }
                else if (order is BotOrderGeneric)
                {
                    AILog.Log("MovesCalculator", " - " + order.As <BotOrderGeneric>().Order.ToString());
                }
                else
                {
                    throw new Exception("Unexpected order type");
                }
            }
        }
コード例 #6
0
        private static bool PlayBombCard(BotMain bot, CardInstance card)
        {
            var allBombableEnemyTerritories = bot.Standing.Territories.Values
                                              .Where(o => o.OwnerPlayerID == bot.PlayerID)
                                              .SelectMany(o => bot.Map.Territories[o.ID].ConnectedTo.Keys)
                                              .Distinct()
                                              .Select(o => bot.Standing.Territories[o])
                                              .Where(o => bot.IsOpponent(o.OwnerPlayerID) && o.NumArmies.Fogged == false)
                                              .ToList();

            var minArmies = !bot.UseRandomness ? bot.BaseIncome.Total * 2 : SharedUtility.Round(bot.BaseIncome.Total * RandomUtility.BellRandom(1, 3));

            var weights = allBombableEnemyTerritories.Where(o => o.NumArmies.NumArmies > minArmies).ToDictionary(o => o.ID, o => o.NumArmies.NumArmies - minArmies);

            if (weights.Count == 0)
            {
                return(false);
            }

            var bomb = bot.UseRandomness ? RandomUtility.WeightedRandom(weights.Keys, o => weights[o]) : weights.OrderByDescending(o => o.Value).First().Key;

            AILog.Log("PlayCards", "Bombing " + bot.TerrString(bomb));
            bot.Orders.AddOrder(GameOrderPlayCardBomb.Create(card.ID, bot.PlayerID, bomb));
            return(true);
        }
コード例 #7
0
        public void PrintReport()
        {
            var bonusIds = new List <BonusIDType>(Bot.BotMap.Bonuses.Keys);

            bonusIds.Sort();
            AILog.Log("BonusAnalyzer", "Expected troops: " + TroopEstimate);
            foreach (var i in bonusIds)
            {
                var s   = Bot.BotMap.GetBonus(i);
                var msg = s.ToString();
                if (MightBeOwned(s))
                {
                    msg += "YES:";
                }
                else
                {
                    msg += "NO:";
                }

                msg += " " + BonusBuckets[s.ID] + " / " + BonusCosts[s.ID];
                if (SoonBeOwned(s))
                {
                    msg += " SOON";
                }

                AILog.Log("BonusAnalyzer", msg);
            }
        }
コード例 #8
0
 public void Init(GameIDType gameID, PlayerIDType myPlayerID, Dictionary <PlayerIDType, GamePlayer> players, MapDetails map, GameStanding distributionStanding, GameSettings gameSettings, int numberOfTurns, Dictionary <PlayerIDType, PlayerIncome> incomes, GameOrder[] prevTurn, GameStanding latestTurnStanding, GameStanding previousTurnStanding, Dictionary <PlayerIDType, TeammateOrders> teammatesOrders, List <CardInstance> cards, int cardsMustPlay, Stopwatch timer, List <string> directives)
 {
     this.DistributionStandingOpt = distributionStanding;
     this.Standing          = latestTurnStanding;
     this.PlayerID          = myPlayerID;
     this.Players           = players;
     this.Map               = map;
     this.Settings          = gameSettings;
     this.TeammatesOrders   = teammatesOrders;
     this.Cards             = cards;
     this.CardsMustPlay     = cardsMustPlay;
     this.Incomes           = incomes;
     this.BaseIncome        = Incomes[PlayerID];
     this.EffectiveIncome   = BaseIncome.Clone();
     this.Neighbors         = players.Keys.ExceptOne(PlayerID).ConcatOne(TerritoryStanding.NeutralPlayerID).ToDictionary(o => o, o => new Neighbor(this, o));
     this.Opponents         = players.Values.Where(o => o.State == GamePlayerState.Playing && !IsTeammateOrUs(o.ID)).ToList();
     this.IsFFA             = Opponents.Count > 1 && (Opponents.Any(o => o.Team == PlayerInvite.NoTeam) || Opponents.GroupBy(o => o.Team).Count() > 1);
     this.WeightedNeighbors = WeightNeighbors();
     this.Timer             = timer;
     this.Directives        = directives;
     if (tracker.isInit())
     {
         tracker.update(this);
     }
     else
     {
         tracker.init(this);
     }
     AILog.Log("BotMain", "PyBot initialized.  Starting at " + timer.Elapsed.TotalSeconds + " seconds");
 }
コード例 #9
0
        private static float GetExpansionWeight(BotMain bot, TerritoryIDType terrID)
        {
            var td = bot.Map.Territories[terrID];

            var bonusPaths = td.PartOfBonuses
                             .Where(o => bot.BonusValue(o) > 0)
                             .Select(o => BonusPath.TryCreate(bot, o, ts => ts.ID == terrID))
                             .Where(o => o != null)
                             .ToDictionary(o => o.BonusID, o => o);

            var turnsToTake = bonusPaths.Keys.ToDictionary(o => o, o => TurnsToTake(bot, td.ID, o, bonusPaths[o]));

            foreach (var cannotTake in turnsToTake.Where(o => o.Value == null).ToList())
            {
                turnsToTake.Remove(cannotTake.Key);
                bonusPaths.Remove(cannotTake.Key);
            }

            var bonusWeights = bonusPaths.Keys.ToDictionary(o => o, o => ExpansionHelper.WeighBonus(bot, o, ts => ts.ID == terrID, turnsToTake[o].NumTurns));

            var weight = 0.0f;

            weight += ExpansionHelper.WeighMultipleBonuses(td.PartOfBonuses.Where(o => bonusWeights.ContainsKey(o)).ToDictionary(o => o, o => bonusWeights[o]));

            AILog.Log("PickTerritories", "Expansion weight for terr " + bot.TerrString(terrID) + " is " + weight + ". " + td.PartOfBonuses.Select(b => "Bonus " + bot.BonusString(b) + " Weight=" + (bonusWeights.ContainsKey(b) ? bonusWeights[b] : 0) + " TurnsToTake=" + (turnsToTake.ContainsKey(b) ? turnsToTake[b].ToString() : "") + " Path=" + (bonusPaths.ContainsKey(b) ? bonusPaths[b].ToString() : "")).JoinStrings(", "));

            return(weight);
        }
コード例 #10
0
        private void DoOffense(int armiesToOffense, List <PossibleAttack> orderedAttacks)
        {
            AILog.Log("Offense", orderedAttacks.Count + " attack ops: ");
            foreach (var attack in orderedAttacks.Take(10))
            {
                AILog.Log("Offense", " - " + attack);
            }

            var armiesLeft = armiesToOffense;


            if (!Bot.UseRandomness)
            {
                int attackIndex = 0;
                while (attackIndex < orderedAttacks.Count)
                {
                    TryDoAttack(orderedAttacks[attackIndex], ref armiesLeft);
                    attackIndex++;
                }
            }
            else
            {
                while (orderedAttacks.Count > 0)
                {
                    if (armiesLeft == 0 && Bot.PastTime(8))
                    {
                        return; //if we're running slowly and have no armies to deploy, just skip attacks.  We just miss out on attacks that we could have done with standing armies.
                    }
                    var i = RandomUtility.WeightedRandomIndex(orderedAttacks, o => o.OffenseImportance);
                    TryDoAttack(orderedAttacks[i], ref armiesLeft);
                    orderedAttacks.RemoveAt(i);
                }
            }
        }
コード例 #11
0
        public void Go(int incomeToUse)
        {
            if (WeightedMoves.None())
            {
                AILog.Log("DefendAttack", "No attacks or defenses to do, skipping DefendAttack");
                return; //No attacks possible
            }

            //Divide between offense and defense.  Defense armies could still be used for offense if we happen to attack there
            var baseOffenseRatio = (Bot.IsFFA ? 0.3 : 0.6);

            if (Bot.Settings.MultiAttack)
            {
                baseOffenseRatio = 0; //in MA, our expansion routine is actually our primary attack weapon.  Therefore, set offense ratio to 0 so that we skip the routine that tries to attack one territory at a time.
            }
            var offenseRatio    = baseOffenseRatio + (Bot.UseRandomness ? RandomUtility.BellRandom(-.15, .15) : 0);
            int armiesToOffense = SharedUtility.Round(incomeToUse * offenseRatio);
            int armiesToDefense = incomeToUse - armiesToOffense;

            AILog.Log("DefendAttack", "offenseRatio=" + offenseRatio + ": " + armiesToOffense + " armies go to offense, " + armiesToDefense + " armies go to defense");

            //Find defensive opportunities.
            var orderedDefenses = WeightedMoves.OrderByDescending(o => o.DefenseImportance).ToList();
            var orderedAttacks  = WeightedMoves.OrderByDescending(o => o.OffenseImportance).ToList();


            DoDefense(armiesToDefense, orderedDefenses);
            DoOffense(armiesToOffense, orderedAttacks);
        }
コード例 #12
0
        private void BuildSign(TileIndex tile, string text)
        {
            AILog.Info("Sign (" + AIMap.GetTileX(tile) + ", " + AIMap.GetTileY(tile) + "): " + text);
            var signId = AISign.BuildSign(tile, "" + text);

            this.signs.AddItem(signId, 0);
        }
コード例 #13
0
        private void TryDoAttack(PossibleAttack attack, ref int armiesToOffense)
        {
            bool commanders = true;
            var  toTS       = Bot.Standing.Territories[attack.To];

            int attackWith = Bot.ArmiesToTake(toTS.NumArmies.Fogged == false ? toTS.NumArmies : ExpansionHelper.GuessNumberOfArmies(Bot, toTS.ID));

            //Add a few more to what's required so we're not as predictable.
            if (Bot.UseRandomness)
            {
                attackWith += SharedUtility.Round(attackWith * (RandomUtility.RandomPercentage() * .2));

                //Once in a while, be willing to do a stupid attack.  Sometimes it will work out, sometimes it will fail catastrophically
                if (RandomUtility.RandomNumber(20) == 0)
                {
                    var origAttackWith = attackWith;
                    attackWith = SharedUtility.Round(attackWith * RandomUtility.RandomPercentage());
                    commanders = false;
                    if (attackWith != origAttackWith)
                    {
                        AILog.Log("Offense", "Willing to do a \"stupid\" attack from " + Bot.TerrString(attack.From) + " to " + Bot.TerrString(attack.To) + ": attacking with " + attackWith + " instead of our planned " + origAttackWith);
                    }
                }
            }
            else
            {
                attackWith += SharedUtility.Round(attackWith * 0.1);
            }

            int have = Bot.MakeOrders.GetArmiesAvailable(attack.From);
            int need = Math.Max(0, attackWith - have);

            if (need > armiesToOffense)
            {
                //We can't swing it. Just deploy the rest and quit. Will try again next turn.
                if (armiesToOffense > 0 && Bot.Orders.TryDeploy(attack.From, armiesToOffense))
                {
                    AILog.Log("Offense", "Could not attack from " + Bot.TerrString(attack.From) + " to " + Bot.TerrString(attack.To) + " with " + attackWith + ". Short by " + need + ".  Just deploying " + armiesToOffense + " to the source.");
                    armiesToOffense = 0;
                }
            }
            else
            {
                //We can attack.  First deploy however many we needed
                if (need > 0)
                {
                    if (!Bot.Orders.TryDeploy(attack.From, need))
                    {
                        return;
                    }
                    armiesToOffense -= need;
                    Assert.Fatal(armiesToOffense >= 0);
                }

                //Now issue the attack
                Bot.Orders.AddAttack(attack.From, attack.To, AttackTransferEnum.AttackTransfer, attackWith, false, commanders: commanders);
                AILog.Log("Offense", "Attacking from " + Bot.TerrString(attack.From) + " to " + Bot.TerrString(attack.To) + " with " + attackWith + " by deploying " + need);
            }
        }
コード例 #14
0
        internal static bool BuildRail(TileIndex previous, TileIndex from, TileIndex to, TileIndex next, HashSet <TileIndex> forbidden, int railCount = 1, Action <TileIndex, string> sign = null)
        {
            var path = RailBuilder.FindPath(from, to, previous, forbidden, sign);

            if (path == null)
            {
                return(false);
            }

            for (var i = 0; i < path.Count - 1; i++)
            {
                var p  = i == 0 ? next : path[i - 1].Tile;
                var c  = path[i].Tile;
                var n  = i == path.Count - 1 ? previous : path[i + 1].Tile;
                var nt = i == 0 ? BuildType.Basic : path[i - 1].Type;
                //sign(c, "[" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "] " + path[i].type);
                bool good = false;
                switch (path[i].Type)
                {
                case BuildType.Basic:
                    if (path[i].Length > 1)
                    {
                        throw new Exception("Should not be rail");
                    }

                    if (nt != BuildType.Basic)
                    {
                        continue;
                    }

                    //AILog.Info("Build a rail  from [" + AIMap.GetTileX(p) + ", " + AIMap.GetTileY(p) + "] via [" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "] to [" + AIMap.GetTileX(n) + ", " + AIMap.GetTileY(n) + "].");
                    good = AIRail.BuildRail(p, c, n);
                    break;

                case BuildType.Bridge:
                    var bridgeTypes = new AIBridgeList_Length(path[i].Length);
                    //AILog.Info("Build a bridge " + bridgeTypes.Begin() + " from [" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "] to [" + AIMap.GetTileX(n) + ", " + AIMap.GetTileY(n) + "].");
                    good = AIBridge.BuildBridge(AIVehicle.VT_RAIL, bridgeTypes.Begin(), c, n);
                    if (!good)
                    {
                        sign(p, "s");
                        sign(c, "e");
                    }

                    break;

                case BuildType.Tunnel:
                    throw new Exception("Tunnels not supported");
                }

                if (!good)
                {
                    AILog.Error("Failed to build on [" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "]. Reason: " + AIError.GetLastErrorString());
                }
            }

            return(true);
        }
コード例 #15
0
        public static void LogBeginGame()
        {
            var territories = GameState.Map.Territories.Values.ToList();

            foreach (var territory in territories)
            {
                AILog.Log("Debug", territory.ID + " --> " + territory.Name);
            }
        }
コード例 #16
0
        private static bool PlayReinforcementCard(BotMain bot, CardInstance card)
        {
            var numArmies = card.As <ReinforcementCardInstance>().Armies;

            AILog.Log("PlayCards", "Playing reinforcement card for " + numArmies);
            bot.Orders.AddOrder(GameOrderPlayCardReinforcement.Create(card.ID, bot.PlayerID));
            bot.EffectiveIncome.FreeArmies += numArmies;
            return(true);
        }
コード例 #17
0
ファイル: Debug.cs プロジェクト: Norman1/WarLightAI
        private static void PrintDistances(BotMain state)
        {
            AILog.Log("Territory distances:");
            foreach (var territory in state.VisibleMap.GetOwnedTerritories())
            {
                var message = territory.ID + " --> " + territory.DirectDistanceToOpponentBorder + " | " + territory.DistanceToUnimportantSpot + " | " + territory.DistanceToImportantSpot + " | " + territory.DistanceToHighlyImportantSpot + " | " + territory.DistanceToOpponentBorder + " | " + territory.DistanceToImportantOpponentBorder + " || " + TransferMovesChooser.GetAdjustedDistance(territory);

                AILog.Log(message);
            }
        }
コード例 #18
0
        public virtual void Update(PlayerIDType opponentID, int opponentDeployment)
        {
            AILog.Log("DeploymentHistory", "VisibleDeployment for " + opponentID + ": " + opponentDeployment);
            OpponentDeployments[opponentID] = opponentDeployment;

            if (BotState.NumberOfTurns > 0)
            {
                Memory.DeploymentTracker.SetDeploys(opponentID, opponentDeployment, BotState.NumberOfTurns - 1);
            }
        }
コード例 #19
0
        public static void Go(BotMain bot)
        {
            if (bot.GamePlayerReference.Team != PlayerInvite.NoTeam && bot.Players.Values.Any(o => o.ID != bot.PlayerID && !o.IsAIOrHumanTurnedIntoAI && o.Team == bot.GamePlayerReference.Team && o.State == GamePlayerState.Playing && !o.HasCommittedOrders))
            {
                return; //If there are any humans on our team that have yet to take their turn, do not play cards.
            }
            var cardsPlayedByTeammate =
                bot.TeammatesSubmittedOrders.OfType <GameOrderPlayCard>().Select(o => o.CardInstanceID)
                .Concat(bot.TeammatesSubmittedOrders.OfType <GameOrderDiscard>().Select(o => o.CardInstanceID))
                .ToHashSet(true);

            int numMustPlay = bot.CardsMustPlay;

            if (numMustPlay > 0)
            {
                AILog.Log("PlayCards", "Must play " + numMustPlay + " cards, have " + bot.Cards.Count + ", teammate played " + cardsPlayedByTeammate.Count);
            }

            var availableCards = bot.Cards.ToDictionary(o => o.ID, o => o);


            foreach (var card in bot.Cards)
            {
                if (cardsPlayedByTeammate.Contains(card.ID))
                {
                    //Teammate played it
                    availableCards.Remove(card.ID);
                    continue;
                }

                Action <CardType, Func <BotMain, CardInstance, bool> > tryPlay = (cardType, playFn) =>
                {
                    if (card.CardID == cardType.CardID && playFn(bot, card))
                    {
                        availableCards.Remove(card.ID);
                        numMustPlay--;
                    }
                };

                tryPlay(CardType.Reinforcement, PlayReinforcementCard);
                tryPlay(CardType.Sanctions, PlaySanctionsCard);
                tryPlay(CardType.Bomb, PlayBombCard);
                tryPlay(CardType.Blockade, PlayBlockadeCard);
                tryPlay(CardType.Diplomacy, PlayDiplomacyCard);
            }

            while (numMustPlay > 0)
            {
                var card = availableCards.First().Value;
                AILog.Log("PlayCards", "Discarding card " + card + ", type=" + card.CardID);
                bot.Orders.AddOrder(GameOrderDiscard.Create(bot.PlayerID, card.ID));
                numMustPlay--;
                availableCards.Remove(card.ID);
            }
        }
コード例 #20
0
        private void AssignExpansionWeights(Dictionary <TerritoryIDType, int> attackableNeutrals)
        {
            AILog.Log("AssignExpansionWeights called with " + attackableNeutrals.Count + " neutrals");

            foreach (var attackableNeutral in attackableNeutrals.Keys.ToList())
            {
                int weight = 0;

                foreach (var bonusID in Map.Territories[attackableNeutral].PartOfBonuses)
                {
                    int bonusValue = BonusValue(bonusID);

                    if (bonusValue == 0)
                    {
                        continue; //Don't even consider bonuses with no worth
                    }
                    if (bonusValue < 0)
                    {
                        weight -= 50; //Don't want negative bonuses
                    }
                    //Is it part of a bonus? Add ArmiesPerTurn * 3.  TODO: We should weight income higher in big FFA games
                    weight += 3 * bonusValue;

                    //How many territories do we need to take to get it? Subtract one weight for each army standing in our way
                    foreach (var terrInBonus in Map.Bonuses[bonusID].Territories)
                    {
                        var ts = Standing.Territories[terrInBonus];

                        if (ts.OwnerPlayerID == PlayerID)
                        {
                            continue; //Already own it
                        }
                        else if (ts.OwnerPlayerID == TerritoryStanding.FogPlayerID)
                        {
                            weight -= Settings.InitialNonDistributionArmies; //assume neutral on fogged items
                        }
                        else if (IsTeammateOrUs(ts.OwnerPlayerID))
                        {
                            weight -= ts.NumArmies.NumArmies * 4; //Teammate in it
                        }
                        else if (ts.IsNeutral)
                        {
                            weight -= ts.NumArmies.NumArmies; //Neutral in it
                        }
                        else
                        {
                            weight -= ts.NumArmies.NumArmies * 2; //Opponent in it - expansion less likely
                        }
                    }
                }


                attackableNeutrals[attackableNeutral] = weight;
            }
        }
コード例 #21
0
ファイル: Debug.cs プロジェクト: Norman1/WarLightAI
 public static void printExpandBonusValues(BotMap map, BotMain BotState)
 {
     AILog.Log("Bonus expansion values:");
     foreach (BotBonus bonus in map.Bonuses.Values)
     {
         if (bonus.GetOwnedTerritoriesAndNeighbors().Count > 0 && !bonus.IsOwnedByMyself())
         {
             AILog.Log(bonus.Details.Name + ": " + bonus.GetExpansionValue());
         }
     }
 }
コード例 #22
0
ファイル: BotMain.cs プロジェクト: Norman1/Multiattack-Bot
        public bool PastTime(double seconds)
        {
            var ret = Timer.Elapsed.TotalSeconds >= seconds;

            if (ret)
            {
                AILog.Log("BotMain", "PastTime " + seconds + " seconds, at " + Timer.Elapsed.TotalSeconds + " seconds");
            }

            return(ret);
        }
コード例 #23
0
ファイル: Debug.cs プロジェクト: Norman1/Multiattack-Bot
 public static void PrintAllTerritories(BotMain state, BotMap map)
 {
     AILog.Log("Debug", "Territories:");
     foreach (var territory in map.Territories.Values)
     {
         var id                 = territory.ID;
         var player             = territory.OwnerPlayerID;
         var armies             = territory.Armies;
         var ownershipHeuristic = territory.IsOwnershipHeuristic;
         var deployment         = territory.GetTotalDeployment(BotTerritory.DeploymentType.Normal);
         AILog.Log("Debug", " - Territory " + id + " (" + player + " | " + armies + " | " + ownershipHeuristic + " | " + deployment + ")");
     }
 }
コード例 #24
0
        protected override void Start()
        {
            AICompany.SetLoanAmount(0);
            SignManager signManager = new SignManager();
            TownNetwork tn          = new TownNetwork();

            try
            {
                AICompany.SetLoanAmount(AICompany.GetMaxLoanAmount());
                AIRoad.SetCurrentRoadType(AIRoad.ROADTYPE_ROAD);
                foreach (var edge in tn.Graph.Edges)
                {
                    AILog.Info($"Build road from {edge.Node1.Name} to {edge.Node2.Name}.");
                    var stationInfo1 = tn.EnsureStation(edge.Node1);
                    var stationInfo2 = tn.EnsureStation(edge.Node2);

                    RoadBuilder.BuildRoad(
                        stationInfo1.tile,
                        stationInfo1.entryPoint,
                        stationInfo2.entryPoint,
                        stationInfo2.tile,
                        new HashSet <TileIndex>()
                        );

                    var depotInfo1 = tn.EnsureDepot(edge.Node1);
                    var depotInfo2 = tn.EnsureDepot(edge.Node2);

                    tn.MakeRoute(edge.Node1, edge.Node2);
                    tn.MakeRoute(edge.Node2, edge.Node1);
                }
            }
            catch
            {
            }

            Sleep(50);
            signManager.ClearSigns();
            var step = 0;

            while (true)
            {
                // Main loop
                //this.setMinLoan();
                CsTestAi.SetMinimumLoanAmount();

                tn.UpdateRoutes();

                Sleep(100);
                step++;
            }
        }
コード例 #25
0
        public static void Go(BotMain bot)
        {
            var terrs = bot.Standing.Territories.Values.Where(o => bot.IsTeammateOrUs(o.OwnerPlayerID) && o.NumArmies.NumArmies == bot.Settings.OneArmyMustStandGuardOneOrZero && o.NumArmies.SpecialUnits.Length == 0).Select(o => o.ID).ToHashSet(true);

            foreach (var bonus in bot.Map.Bonuses.Values)
            {
                if (bonus.Territories.All(o => terrs.Contains(o)) && bonus.ControlsBonus(bot.Standing).HasValue == false)
                {
                    //bot bonus is entirely controlled by our team with 1s, but not by a single player. The player with the most territories should take it.
                    var owners = bonus.Territories.GroupBy(o => bot.Standing.Territories[o].OwnerPlayerID).ToList();
                    owners.Sort((f, s) => SharedUtility.CompareInts(s.Count(), f.Count()));

                    Assert.Fatal(owners.Count >= 2);

                    var attacks = bonus.Territories
                                  .Where(o => bot.Standing.Territories[o].OwnerPlayerID != bot.PlayerID)                                                   //Territories in the bonus by our teammate
                                  .Where(o => bot.Map.Territories[o].ConnectedTo.Keys.Any(c => bot.Standing.Territories[c].OwnerPlayerID == bot.PlayerID)) //Where we control an adjacent
                                  .Select(o => new PossibleAttack(bot, bot.Map.Territories[o].ConnectedTo.Keys.First(c => bot.Standing.Territories[c].OwnerPlayerID == bot.PlayerID), o));

                    if (owners[0].Count() == owners[1].Count())
                    {
                        //The top two players have the same number of terrs.  50% chance we should try taking one.
                        if (attacks.Any() && RandomUtility.RandomNumber(2) == 0)
                        {
                            var doAttack1 = bot.UseRandomness ? attacks.Random() : attacks.First();
                            var numArmies = bot.ArmiesToTake(bot.Standing.Territories[doAttack1.To].NumArmies);
                            if (bot.Orders.TryDeploy(doAttack1.From, numArmies))
                            {
                                AILog.Log("ResolveTeamBonuses", "Detected a split bonus " + bot.BonusString(bonus) + ", and we're attempting to break the split by doing a small attack from " + bot.TerrString(doAttack1.From) + " to " + bot.TerrString(doAttack1.To) + " with " + numArmies);
                                bot.Orders.AddAttack(doAttack1.From, doAttack1.To, AttackTransferEnum.Attack, numArmies, true);
                            }
                        }
                    }
                    else if (owners[0].Key == bot.PlayerID)
                    {
                        //We should take the bonus
                        foreach (var doAttack2 in attacks)
                        {
                            var numArmies = bot.ArmiesToTake(bot.Standing.Territories[doAttack2.To].NumArmies);

                            if (bot.Orders.TryDeploy(doAttack2.From, numArmies))
                            {
                                AILog.Log("ResolveTeamBonuses", "Detected we should take bonus " + bot.BonusString(bonus) + ", so we're attacking from " + bot.TerrString(doAttack2.From) + " to " + bot.TerrString(doAttack2.To) + " with " + numArmies);
                                bot.Orders.AddAttack(doAttack2.From, doAttack2.To, AttackTransferEnum.Attack, 2, true);
                            }
                        }
                    }
                }
            }
        }
コード例 #26
0
        public List <TerritoryIDType> GetPicks()
        {
            var territoryList = DistributionStanding.Territories.Values.Where(o => o.OwnerPlayerID == TerritoryStanding.AvailableForDistribution).Select(o => BotMap.Territories[o.ID]).ToList();

            territoryList.Sort(new StartingTerritoryComparator(this));

            AILog.Log("Picking " + territoryList.Count + " territories: ");
            foreach (var terr in territoryList)
            {
                AILog.Log(" - " + terr);
            }

            return(territoryList.Select(o => o.ID).ToList());
        }
コード例 #27
0
ファイル: Debug.cs プロジェクト: Norman1/Multiattack-Bot
        private static void PrintOpponentBonuses(PlayerIDType opponentID, BotMain state)
        {
            var message = new StringBuilder();

            message.Append("Opponent owns Bonuses: ");
            foreach (var bonus in state.VisibleMap.Bonuses.Values)
            {
                if (bonus.IsOwnedByOpponent(opponentID))
                {
                    message.Append(bonus.Details.Name + ", ");
                }
            }
            AILog.Log("Debug", message.ToString());
        }
コード例 #28
0
        public List <GameOrder> GetOrders()
        {
            var deploys = GetPlaceArmiesMoves();
            var attacks = GetAttackTransferMoves();

            var final = deploys.Cast <BotOrder>().Concat(attacks).ToList();

            AILog.Log("Final " + final.Count + " orders: ");
            foreach (var order in final)
            {
                AILog.Log(" - " + order);
            }

            return(BotOrder.Convert(final));
        }
コード例 #29
0
        private static bool PlaySanctionsCard(BotMain bot, CardInstance card)
        {
            var canSanction = bot.Players.Values.Where(o => o.State == GamePlayerState.Playing && bot.IsOpponent(o.ID)).Select(o => o.ID).ToList();

            if (canSanction.Count == 0)
            {
                return(false);
            }

            var sanction = bot.UseRandomness ? RandomUtility.WeightedRandom(canSanction, o => bot.WeightedNeighbors[o]) : canSanction.OrderByDescending(o => bot.WeightedNeighbors[o]).First();

            AILog.Log("PlayCards", "Sanctioning " + sanction);
            bot.Orders.AddOrder(GameOrderPlayCardSanctions.Create(card.ID, bot.PlayerID, sanction));
            return(true);
        }
コード例 #30
0
        private Dictionary <TerritoryIDType, PossibleExpandTarget> GetExpansionWeights(HashSet <TerritoryIDType> terrs)
        {
            var bonusPaths = terrs
                             .SelectMany(o => Bot.Map.Territories[o].PartOfBonuses)
                             .Where(o => Bot.BonusValue(o) > 0)
                             .Distinct()
                             .Select(o =>
            {
                if (Bot.PastTime(7))
                {
                    return(null);    //stop trying to expand if we're slow
                }
                return(BonusPath.TryCreate(Bot, o, ts => ts.OwnerPlayerID == Bot.PlayerID));
            })
                             .Where(o => o != null)
                             .ToDictionary(o => o.BonusID, o => o);

            var turnsToTake = bonusPaths.Keys.ToDictionary(o => o, o => TurnsToTake(o, bonusPaths[o]));

            foreach (var cannotTake in turnsToTake.Where(o => o.Value == null).ToList())
            {
                turnsToTake.Remove(cannotTake.Key);
                bonusPaths.Remove(cannotTake.Key);
            }

            var bonusWeights = bonusPaths.Keys.ToDictionary(o => o, o => ExpansionHelper.WeighBonus(Bot, o, ts => ts.OwnerPlayerID == Bot.PlayerID, turnsToTake[o].NumTurns));

            AILog.Log("Expand", "GetExpansionWeights called with " + terrs.Count + " territories.  Weighted " + bonusWeights.Count + " bonuses:");
            foreach (var bw in bonusWeights.OrderByDescending(o => o.Value).Take(10))
            {
                AILog.Log("Expand", " - " + Bot.BonusString(bw.Key) + " Weight=" + bw.Value + " " + turnsToTake[bw.Key] + " TurnsToTakeByDistance=" + bonusPaths[bw.Key].TurnsToTakeByDistance + " CriticalPath=" + bonusPaths[bw.Key].TerritoriesOnCriticalPath.Select(o => Bot.TerrString(o)).JoinStrings(", "));
            }

            var ret = new Dictionary <TerritoryIDType, PossibleExpandTarget>();

            foreach (var terr in terrs)
            {
                ret[terr] = new PossibleExpandTarget(Bot, terr, Bot.Map.Territories[terr].PartOfBonuses.Where(b => bonusPaths.ContainsKey(b)).ToDictionary(b => b, b => new PossibleExpandTargetBonus(bonusWeights[b], bonusPaths[b], turnsToTake[b])));
            }

            AILog.Log("Expand", "Finished weighing " + terrs.Count + " territories:");
            foreach (var terr in ret.OrderByDescending(o => o.Value.Weight).Take(10))
            {
                AILog.Log("Expand", " - " + Bot.TerrString(terr.Key) + " Weight=" + terr.Value);
            }

            return(ret);
        }