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)); }
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> ProduceRefinePlans(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++) { CardAIPlanData d = ProduceSingleRefination(ai, entryState, plans[i]); 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)); }
static CardAIPlanData CastSkillOnece(CardAI ai, NetSkill ns, NetCard nc, CardAIPlanData data, NetBattlefield bf, IEnumerator <List <int> > targetEnumerator) { //structure makes a new copy CardAIPlanData result = data; //using previous bf allows to utilize already cached data, as well as share caching with following casts. //later we will use new bf to ensure we do not override the same bf. NetBattlefield prevBf = data.bf; IList <int> targets = GetPlayCardTargets(ai.FriendlyTurn, ns, nc, prevBf); if (targets == null || targets.Count < 1) { return(new CardAIPlanData()); } if (targetEnumerator == null) { targetEnumerator = GetTargetEnumerator(ns, nc, targets, ai); if (targetEnumerator == null) { return(new CardAIPlanData()); } } targetEnumerator.MoveNext(); List <int> selectedTargets = targetEnumerator.Current; if (selectedTargets == null || selectedTargets.Count == 0) { return(new CardAIPlanData()); } List <int> secTargets = GetSecondaryPlayTargets(ns, nc, prevBf, selectedTargets, ai.r); FInt skillDelay = ns.GetSkillDelay(prevBf); int cost = prevBf.GetCardCastingCostFast(ns.GetOwner(prevBf).CardID); //add cost if something need to be casted next turn by AI var ncp = bf.GetPlayerByPlayerID(ai.playerID); if (cost > ncp.ApLeft) { skillDelay += 2; } //operate from now on its own bf result.bf = bf; NetQueueItem q; if (ns.IsCastingSpell()) { q = new NetQueueItem(bf, ns, new NetListInt(selectedTargets), new NetListInt(secTargets), skillDelay, -1); } else { q = new NetQueueItem(bf, ns, null, null, skillDelay, selectedTargets[0]); } //if ap cost were larger than current ap then we will result in negative ap. //because its just simulation we do not care for that now, as the sum of this and next turn ap //for estimating cost would be identical ncp.ApLeft -= nc.GetCastingCost(); bf.PlayCard(q, ai.r); float value = bf.GetValueByCloneSimulation(ai.iterations, ai.r); result.value = value; result.AddCardPlay(nc.CardID, ns.SkillInBattleID, q); result.SetEnumerator(targetEnumerator); result.valid = true; return(result); }