// // static public CardAIPlanData _ProducePlan(int playerID, CardAIPlanData data, int avaliableAP, MHRandom r, int calculationIntensity = 1) // { // if (calculationIntensity < 1 ) // { // Debug.LogError("[ERROR]0 level for AI will nto produce any plans!, Increase calculation intensity to minimum 1!"); // return new CardAIPlanData(); // } // // NetBattlefield bf = data.bf; // // List<NetCard> cards = CardsWithinAPRange(playerID, bf, avaliableAP); // if (cards == null) return new CardAIPlanData(); // // List<NetSkill> skills = SelectSkillsToCast(cards); // if (skills == null || skills.Count == 0) return new CardAIPlanData(); // // bool friendlyTurn = playerID > 0; // // //Do single cast of all skills to build some expectations // CardAIPlanData[] plans = new CardAIPlanData[skills.Count]; // // for (int i=0; i<skills.Count; i++) // { // NetSkill ns = skills[i]; // CardAIPlanData d = CastSkillOnece(friendlyTurn, ns, ns.GetOwner(bf), data, bf.CloneAndRemember(), r); // if (d.valid) // { // plans[i] = d; // } // } // // //sort result based on their value // List<CardAIPlanData> plansL = new List<CardAIPlanData>(plans); // plansL.Sort(delegate (CardAIPlanData a, CardAIPlanData b) // { // return a.value.CompareTo(b.value); // }); // // //get top plans and try to refine them before selecting the best // int min = Mathf.Min(plansL.Count, calculationIntensity); // plansL = plansL.GetRange(0, min); // // int refiningLevel = 8; // plans = new CardAIPlanData[plansL.Count * refiningLevel]; // for(int i=0; i < plansL.Count; i++) // { // for(int k=0; k< refiningLevel; k++) // { // //plansL[i].validTargets // } // } // // // Start secondary plans from the selected plans // return new CardAIPlanData(); // } static public List <NetCard> CardsWithinAPRange(CardAI ai, NetBattlefield bf, int testedAPRange) { NetListInt ni = bf.GetPlayerByPlayerID(ai.playerID).HandCards; if (NetType.IsNullOrEmpty(ni)) { return(null); } List <NetCard> ncs = new List <NetCard>(); foreach (var v in ni.value) { NetCard nc = bf.GetCardByID(v); if (nc.GetCastingCost() <= testedAPRange) { ncs.Add(nc); } } return(ncs); }
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); }