static public List <CardAIPlanData> ProduceCastPlans(CardAI ai, CardAIPlanData data, List <NetSkill> skills, int count) { List <CardAIPlanData> plans = new List <CardAIPlanData>(skills.Count); NetBattlefield bf = data.bf; for (int i = 0; i < skills.Count; i++) { NetSkill ns = skills[i]; IEnumerator <List <int> > targetEnumerator = null; for (int k = 0; k < count; k++) { CardAIPlanData d = CastSkillOnece(ai, ns, ns.GetOwner(bf), data, bf.CloneAndRemember(), targetEnumerator); if (d.valid) { if (targetEnumerator == null) { targetEnumerator = d.GetTopCardPlay().targetEnumerator; } plans.Add(d); } } } return(plans); }
static NetBattlefield ProduceFakeBFIfNeeded(int playerID, NetBattlefield bf) { //fake battlefield will contain all friendly cards currently not on battlefield //positioned on free positions so that AI can see if it can produce //any targets. there is no simulation involved so fake state should not harm "thinking" //we will not need fake BF IF all owned cards are already on BF. HashSet <NetCard> ownCastedCards = bf.GetCardsOnBattelfield(playerID); NetCardPlayerData ncd = bf.GetPlayerByPlayerID(playerID); if (ncd == null || NetType.IsNullOrEmpty(ncd.HandCards)) { return(bf); } List <int> ownCardsAtHand = ncd.HandCards.value; List <NetCard> cardsToCast = new List <NetCard>(); //this is different set than just cards which were used, because card which casts summons or //does support will not be present on battlefield and still cost more than base AP foreach (var v in ownCardsAtHand) { NetCard nc = bf.GetCardByID(v); if (!ownCastedCards.Contains(nc)) { cardsToCast.Add(nc); } } if (cardsToCast.Count == 0) { return(bf); } //there are cards which should be represented on battle positions //which requires new BF //we would do simple but fake casts NetBattlefield bf2 = bf.CloneAndRemember(); int halfSize = bf2.BattlefieldSize / 2; int start = playerID == 0 ? 0 : halfSize; int cardListIndex = 0; for (int i = 0; i < halfSize; i++) { if (cardListIndex == cardsToCast.Count) { break; } int index = i + start; if (bf2.BattlefieldPositions.value[index] == 0) { bf2.BattlefieldPositions.value[index] = cardsToCast[cardListIndex].CardID; } } return(bf2); }
static CardAIPlanData ProduceSingleRefination(CardAI ai, CardAIPlanData entryState, CardAIPlanData plan) { NetBattlefield bf = entryState.bf; NetSkill ns = bf.GetSkillByID(plan.GetTopCardPlay().skill); //cast form the source plan data so that it is not casted "after" action we want to reiterate to different targets CardAIPlanData d = CastSkillOnece(ai, ns, ns.GetOwner(bf), entryState, bf.CloneAndRemember(), plan.GetTopCardPlay().targetEnumerator); if (d.valid && plan.value < d.value) { d.SetEnumerator(plan.GetTopCardPlay().targetEnumerator); } return(d); }
static List <CardAIPlanData> RefineMultiCastPlan(CardAI ai, CardAIPlanData entryState, List <CardAIPlanData> plans) { NetBattlefield bf = entryState.bf; //get top plans and try to refine them int min = Mathf.Min(plans.Count, ai.refiningSize); for (int i = 0; i < min; i++) { for (int k = 0; k < ai.intensity; k++) { //prepare source for cast copying target enumerator so that it can be reused by the further casts CardAIPlanData source = entryState; NetSkill ns = bf.GetSkillByID(plans[i].GetTopCardPlay().skill); //cast form the source plan data so that it is not casted "after" action we want to reiterate to different targets CardAIPlanData d = CastSkillOnece(ai, ns, ns.GetOwner(bf), source, bf.CloneAndRemember(), plans[i].GetTopCardPlay().targetEnumerator); if (d.valid && plans[i].value < d.value) { d.SetEnumerator(plans[i].GetTopCardPlay().targetEnumerator); plans[i] = d; } } } //select best plan per skill return(plans.GetRange(0, min)); }