示例#1
0
        //
        //         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);
        }
示例#2
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);
        }