예제 #1
0
        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));
        }
예제 #2
0
        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);
        }
예제 #3
0
        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));
        }
예제 #4
0
        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);
        }