コード例 #1
0
        public override float getPlayfieldValue(Playfield p)
        {
            if (p.value >= -2000000) return p.value;
            int retval = 0;
            retval -= p.evaluatePenality;
            retval += p.owncards.Count * 3;

            retval += p.ownHero.Hp + p.ownHero.armor;
            retval += -(p.enemyHero.Hp + p.enemyHero.armor);

            // a mix of control and face -- when our own hp is low, we need more control (increased penalty)
            int hpboarder = 15;
            if (p.ownHeroName == HeroEnum.warlock && p.enemyHeroName != HeroEnum.mage && p.enemyHeroName != HeroEnum.hunter) hpboarder = 10;
            if (p.turnCounter == 0 && (p.ownHero.Hp + p.ownHero.armor) < hpboarder)
            {
                float multiplier = 1 + ((float)p.enemyMaxMana / 10) + ((float)p.enemyAnzCards / 5); // more potential for burst dmg with higher mana + cards
                retval -= (int)(multiplier * (hpboarder - p.ownHero.Hp - p.ownHero.armor));
            }

            // when enemy hp is low, we need more face (decreased penalty)
            if (p.enemyHero.Hp + p.enemyHero.armor < 15)
            {
                retval += 15 - p.enemyHero.Hp - p.enemyHero.armor;
            }

            retval += p.ownMaxMana * 15 - p.enemyMaxMana * 15;

            if (p.ownWeaponAttack >= 1)
            {
                retval += p.ownWeaponAttack * p.ownWeaponDurability;
            }

            if (!p.enemyHero.frozen)
            {
                retval -= p.enemyWeaponDurability * p.enemyWeaponAttack;
            }
            else
            {
                if (p.enemyHeroName != HeroEnum.mage && p.enemyHeroName != HeroEnum.priest && p.enemyHeroName != HeroEnum.warlock)
                {
                    retval += 11;
                }
            }

            //RR card draw value depending on the turn and distance to lethal
            //RR if lethal is close, carddraw value is increased


            if (p.turnCounter == 0 && Ai.Instance.lethalMissing <= 5) //RR
            {
                retval += p.owncarddraw * 100;
            }
            if (p.ownMaxMana < 4)
            {
                retval += p.owncarddraw * 2;
            }
            else
            {
                // value card draw this turn > card draw next turn (the sooner the better)
                retval += (p.turnCounter < 2 ? p.owncarddraw * 5 : p.owncarddraw * 3);
            }
            //retval += p.owncarddraw * 5;
            retval -= p.enemycarddraw * 15;

            bool useAbili = false;
            int usecoin = 0;
            foreach (Action a in p.playactions)
            {
                if (a.actionType == actionEnum.attackWithHero && p.enemyHero.Hp <= p.attackFaceHP) retval++;
                if (a.actionType == actionEnum.useHeroPower) useAbili = true;
                if (p.ownHeroName == HeroEnum.warrior && a.actionType == actionEnum.attackWithHero && useAbili) retval -= 1;
                //if (a.actionType == actionEnum.useHeroPower && a.card.card.name == CardDB.cardName.lesserheal && (!a.target.own)) retval -= 5;
                if (a.actionType != actionEnum.playcard) continue;
                if (a.card.card.name == CardDB.cardName.thecoin)
                {
                    usecoin = 1;
                }
                if (a.card.card.name == CardDB.cardName.innervate)
                {
                    usecoin = 2;
                }
            }
            if (usecoin >= 1 && useAbili && p.ownMaxMana <= 2) retval -= 40;
            if (usecoin >= 1 && p.manaTurnEnd >= usecoin && p.owncards.Count <= 8) retval -= 100 * p.manaTurnEnd;
            int heropowermana = p.ownHeroAblility.card.getManaCost(p, 2);

            if (p.manaTurnEnd >= heropowermana && !useAbili && p.ownAbilityReady)
            {
                if (!(p.ownHeroName == HeroEnum.thief && (p.ownWeaponDurability >= 2 || p.ownWeaponAttack >= 2))) retval -= 20;
            }
            if (useAbili) retval -= 3;  // penalty in case the hero power was chosen over playing a card (penalty == card count bonus)
            if (useAbili && usecoin == 2) retval -= 5;  // prevent being wasteful with innervate if we could've just not used hero power for 2mana
            //if (usecoin && p.mana >= 1) retval -= 20;

            if (p.ownHeroName == HeroEnum.pala)
            {
                foreach (Handmanager.Handcard hc in p.owncards)
                {
                    if (hc.card.name == CardDB.cardName.avenge && p.manaTurnEnd >= hc.getManaCost(p))
                    {
                        retval -= 8;
                        break;
                    }
                }
            }

            foreach (Minion m in p.ownMinions)
            {
                retval += (m.Angr < 4 ? m.Hp * 1 : m.Hp * 2);
                retval += m.Angr * 2;
                retval += m.handcard.card.rarity;
                if (m.windfury) retval += m.Angr;
                if (m.divineshild) retval += ((m.Angr + 2) / 3) + ((m.Hp + 2) / 3);
                if (m.stealth) retval += 1;
                if (m.taunt) retval += 1;
                if (m.handcard.card.isSpecialMinion)
                {
                    retval += 1;
                    if (!m.taunt && m.stealth) retval += (m.Angr < 4 ? 10 : 20);
                }
                //if (m.handcard.card.name == CardDB.cardName.silverhandrecruit && m.Angr == 1 && m.Hp == 1) retval -= 5;
                if (m.handcard.card.name == CardDB.cardName.direwolfalpha || m.handcard.card.name == CardDB.cardName.flametonguetotem || m.handcard.card.name == CardDB.cardName.stormwindchampion || m.handcard.card.name == CardDB.cardName.raidleader) retval += 10;
                if (m.handcard.card.name == CardDB.cardName.nerubianegg)
                {
                    if (m.Angr >= 1) retval += 2;
                    if ((!m.taunt && m.Angr == 0) && (m.divineshild || m.maxHp > 2)) retval -= 10;
                    if (p.ownMinions.Count >= 3) retval += 15;
                }
            }

            bool canPingMinions = (p.ownHeroName == HeroEnum.mage);
            bool hasPingedMinion = false;

            foreach (Minion m in p.enemyMinions)
            {
                int currMinionValue = this.getEnemyMinionValue(m, p);

                // Give a bonus for 1 hp minions as a mage, since we can remove it easier in the future with ping.
                // But we make sure we only give this bonus once among all enemies. We also give another +1 bonus once if the atk >= 4.
                if (canPingMinions && !hasPingedMinion && currMinionValue > 2 && m.Hp == 1)
                {
                    currMinionValue -= 1;
                    canPingMinions = false;  // only 1 per turn (-1 bonus regardless of atk)
                    hasPingedMinion = true;
                }
                if (hasPingedMinion && currMinionValue > 2 && m.Hp == 1 && m.Angr >= 4)
                {
                    currMinionValue -= 1;
                    hasPingedMinion = false;  // only 1 per turn (-1 bonus additional for atk >= 4)
                }

                retval -= currMinionValue;
            }

            retval -= p.enemySecretCount;
            retval -= p.numEnemySecretsTurnEnd * 50;
            retval -= p.lostDamage;//damage which was to high (like killing a 2/1 with an 3/3 -> => lostdamage =2
            retval -= p.lostWeaponDamage;
            if (p.ownMinions.Count == 0) retval -= 20;
            if (p.enemyMinions.Count >= 4) retval -= 20;
            if (p.enemyHero.Hp <= 0)
            {
                if (p.turnCounter <= 1)
                {
                    retval = 10000;
                }
                else
                {
                    retval += 50;//10000
                    if (p.numPlayerMinionsAtTurnStart == 0) retval += 50; // if we can kill the enemy even after a board clear, bigger bonus
                    if (p.loathebLastTurn > 0) retval += 50;  // give a bonus to turn 2 sims where we played loatheb in turn 1 to protect our lethal board
                }
            }
            else if (p.ownHero.Hp > 0)
            {
                // if our damage on board is lethal, give a strong bonus so enemy AI avoids this outcome in its turn (i.e. AI will clear our minions if it can instead of ignoring them)
                if (p.turnCounter == 1 && p.guessHeroDamage(true) >= p.enemyHero.Hp + p.enemyHero.armor) retval += 100;
            }

            //soulfire etc
            int deletecardsAtLast = 0;
            foreach (Action a in p.playactions)
            {
                if (a.actionType != actionEnum.playcard) continue;
                if (a.card.card.name == CardDB.cardName.soulfire || a.card.card.name == CardDB.cardName.doomguard || a.card.card.name == CardDB.cardName.succubus) deletecardsAtLast = 1;
                if (deletecardsAtLast == 1 && !(a.card.card.name == CardDB.cardName.soulfire || a.card.card.name == CardDB.cardName.doomguard || a.card.card.name == CardDB.cardName.succubus)) retval -= 20;
            }

            if (p.enemyHero.Hp >= 1 && p.ownHero.Hp <= 0)
            {
                //Helpfunctions.Instance.ErrorLog("turncounter " + p.turnCounter);

                if (p.turnCounter == 0) // own turn 
                {
                    //worst case: we die on own turn
                    retval += p.owncarddraw * 500;
                    retval = -10000;
                }
                else
                {
                    if (p.turnCounter == 1) // enemys first turn
                    {
                        retval += p.owncarddraw * 500;
                        retval -= 1000;
                    }
                    if (p.turnCounter >= 2)
                    {
                        //carddraw next turn doesnt count this turn :D
                        retval -= 100;
                    }
                }



            }

            /*
            if (p.enemyHero.Hp >= 1 && p.ownHero.Hp <= 0)
            {
                if (p.turnCounter < 2) retval += p.owncarddraw * 500;
                retval -= 1000;
            }
            if (p.ownHero.Hp <= 0) retval = -10000;*/

            // give a bonus for making the enemy spend more mana dealing with our board, so boards where the enemy makes different plays
            // aren't considered as equal value (i.e. attacking the enemy and making him spend mana to heal vs not attacking at all)
            if (p.turnCounter == 1 || p.turnCounter == 3) retval += p.enemyMaxMana - p.mana;

            p.value = retval;
            return retval;
        }
コード例 #2
0
ファイル: BehaviourMana.cs プロジェクト: noHero123/silverfish
        public override float getPlayfieldValue(Playfield p)
        {

            if (p.value >= -2000000) return p.value;
            int retval = 0;
            int hpboarder = 10;
            if (p.ownHeroName == HeroEnum.warlock && p.enemyHeroName != HeroEnum.mage) hpboarder = 6;
            int aggroboarder = 11;
            retval -= p.evaluatePenality;
            retval += p.owncards.Count * 5;

            retval += p.ownMaxMana;
            retval -= p.enemyMaxMana;

            retval += p.ownMaxMana * 20 - p.enemyMaxMana * 20;


            if (p.enemyHeroName == HeroEnum.mage || p.enemyHeroName == HeroEnum.druid) retval -= 2 * p.enemyspellpower;

            if (p.ownHero.Hp + p.ownHero.armor > hpboarder)
            {
                retval += p.ownHero.Hp + p.ownHero.armor;
            }
            else
            {
                retval -= 2 * (hpboarder + 1 - p.ownHero.Hp - p.ownHero.armor) * (hpboarder + 1 - p.ownHero.Hp - p.ownHero.armor);
            }

            if (p.enemyHero.Hp + p.enemyHero.armor > aggroboarder)
            {
                retval += -p.enemyHero.Hp - p.enemyHero.armor;
            }
            else
            {
                retval += 3 * (aggroboarder + 1 - p.enemyHero.Hp - p.enemyHero.armor);
            }

            if (p.ownWeaponAttack >= 1)
            {
                retval += p.ownWeaponAttack * p.ownWeaponDurability;
            }

            if (!p.enemyHero.frozen)
            {
                retval -= p.enemyWeaponDurability * p.enemyWeaponAttack;
            }
            else
            {
                if (p.enemyWeaponDurability >= 1)
                {
                    retval += 12;
                }
            }

            //RR card draw value depending on the turn and distance to lethal
            //RR if lethal is close, carddraw value is increased
            if (Ai.Instance.lethalMissing <= 5 && p.turnCounter == 0) //RR
            {
                retval += p.owncarddraw * 100;
            }
            if (p.ownMaxMana <= 4)
            {
                retval += p.owncarddraw * 2;
            }
            else
            {
                //retval += p.owncarddraw * 5;
                // value card draw this turn > card draw next turn (the sooner the better)
                retval += (p.turnCounter < 2 ? p.owncarddraw * 5 : p.owncarddraw * 3);
            }

            //retval += p.owncarddraw * 5;
            retval -= (p.enemycarddraw - p.anzEnemyCursed) * 10;

            //int owntaunt = 0;
            int readycount = 0;
            int ownMinionsCount = 0;

            bool enemyhaspatron = false;

            //
            bool canPingMinions = (p.ownHeroAblility.card.name == CardDB.cardName.fireblast);
            bool hasPingedMinion = false;


            foreach (Minion m in p.enemyMinions)
            {
                if (m.name == CardDB.cardName.grimpatron && !m.silenced) enemyhaspatron = true;

                int currMinionValue = this.getEnemyMinionValue(m, p);

                // Give a bonus for 1 hp minions as a mage, since we can remove it easier in the future with ping.
                // But we make sure we only give this bonus once among all enemies. We also give another +1 bonus once if the atk >= 4.
                if (canPingMinions && !hasPingedMinion && currMinionValue > 2 && m.Hp == 1)
                {
                    currMinionValue -= 1;
                    canPingMinions = false;  // only 1 per turn (-1 bonus regardless of atk)
                    hasPingedMinion = true;
                }
                if (hasPingedMinion && currMinionValue > 2 && m.Hp == 1 && m.Angr >= 4)
                {
                    currMinionValue -= 1;
                    hasPingedMinion = false;  // only 1 per turn (-1 bonus additional for atk >= 4)
                }

                retval -= currMinionValue;

                //hasTank = hasTank || m.taunt;
            }

            foreach (Minion m in p.ownMinions)
            {
                retval += 5;
                retval += m.Hp * 2;
                retval += m.Angr * 2;
                retval += m.handcard.card.rarity;
                if (!m.playedThisTurn && m.windfury) retval += m.Angr;
                if (m.divineshild) retval += 1;
                if (m.stealth) retval += 1;
                if (m.handcard.card.isSpecialMinion)
                {
                    retval += 1;
                    if (!m.taunt && m.stealth) retval += 20;
                }
                else
                {
                    if (m.Angr <= 2 && m.Hp <= 2 && !m.divineshild) retval -= 5;
                }
                //if (m.Angr <= m.Hp + 1) retval += m.Angr;
                //if (!m.taunt && m.stealth && penman.specialMinions.ContainsKey(m.name)) retval += 20;
                //if (m.poisonous) retval += 1;
                if (m.divineshild && m.taunt) retval += 4;
                //if (m.taunt && m.handcard.card.name == CardDB.cardName.frog) owntaunt++;
                //if (m.handcard.card.isToken && m.Angr <= 2 && m.Hp <= 2) retval -= 5;
                //if (!penman.specialMinions.ContainsKey(m.name) && m.Angr <= 2 && m.Hp <= 2) retval -= 5;
                if (m.handcard.card.name == CardDB.cardName.direwolfalpha || m.handcard.card.name == CardDB.cardName.flametonguetotem || m.handcard.card.name == CardDB.cardName.stormwindchampion || m.handcard.card.name == CardDB.cardName.raidleader) retval += 10;
                if (m.handcard.card.name == CardDB.cardName.bloodmagethalnos) retval += 10;
                if (m.handcard.card.name == CardDB.cardName.nerubianegg)
                {
                    if (m.Angr >= 1) retval += 2;
                    if (m.divineshild || (m.maxHp > 2 && !m.destroyOnOwnTurnEnd)) retval -= 10;
                    if (p.ownMinions.Count >= 3) retval += 15;
                }
                if (m.Ready) readycount++;
                if (m.maxHp >= 4 && (m.Angr > 2 || m.Hp > 3)) ownMinionsCount++;
            }



            /*if (p.enemyMinions.Count >= 0)
            {
                int anz = p.enemyMinions.Count;
                if (owntaunt == 0) retval -= 10 * anz;
                retval += owntaunt * 10 - 11 * anz;
            }*/

            bool useAbili = false;
            int usecoin = 0;
            //bool lastCoin = false;
            foreach (Action a in p.playactions)
            {
                //lastCoin = false;
                if (a.actionType == actionEnum.attackWithHero && p.enemyHero.Hp <= p.attackFaceHP) retval++;
                if (a.actionType == actionEnum.useHeroPower) useAbili = true;
                if (p.ownHeroName == HeroEnum.warrior && a.actionType == actionEnum.attackWithHero && useAbili) retval -= 1;
                //if (a.actionType == actionEnum.useHeroPower && a.card.card.name == CardDB.cardName.lesserheal && (!a.target.own)) retval -= 5;
                if (a.actionType != actionEnum.playcard) continue;
                if (a.card.card.name == CardDB.cardName.thecoin)
                {
                    usecoin = 1;
                }
                if (a.card.card.name == CardDB.cardName.innervate)
                {
                    usecoin = 2;
                }
                //save spell for all classes: (except for rouge if he has no combo)
                if (a.target == null) continue;
                if (p.ownHeroName != HeroEnum.thief && a.card.card.type == CardDB.cardtype.SPELL && (!a.target.own && a.target.isHero) && a.card.card.name != CardDB.cardName.shieldblock) retval -= 11;
                if (p.ownHeroName == HeroEnum.thief && a.card.card.type == CardDB.cardtype.SPELL && (a.target.isHero && !a.target.own)) retval -= 11;
            }
            //dont waste mana!!
            if (usecoin >= 1 && useAbili && p.ownMaxMana <= 2) retval -= 40;
            if (usecoin >= 1 && p.manaTurnEnd >= usecoin && p.owncards.Count <= 8) retval -= 100 * p.manaTurnEnd;
            int heropowermana = p.ownHeroAblility.card.getManaCost(p, 2);
            if (p.manaTurnEnd >= heropowermana && !useAbili && p.ownAbilityReady)
            {
                if (!(p.ownHeroName == HeroEnum.thief && (p.ownWeaponDurability >= 2 || p.ownWeaponAttack >= 2))) retval -= 20;
                if (p.ownHeroName == HeroEnum.pala && enemyhaspatron) retval += 20;
            }
            if (useAbili && usecoin == 2) retval -= 5;
            //if (usecoin && p.manaTurnEnd >= 1 && p.owncards.Count <= 8) retval -= 100;

            int mobsInHand = 0;
            int bigMobsInHand = 0;
            foreach (Handmanager.Handcard hc in p.owncards)
            {
                if (hc.card.type == CardDB.cardtype.MOB)
                {
                    mobsInHand++;
                    if (hc.card.Attack >= 3 && hc.card.Health >= 3) bigMobsInHand++;
                }
            }

            //stuff for not flooding board
            int mobsturnbegin = Hrtprozis.Instance.ownMinions.Count;
            if (ownMinionsCount > mobsturnbegin)
            {
                if (ownMinionsCount - p.enemyMinions.Count >= 3)
                {
                    retval += bigMobsInHand * 50 + mobsInHand * 10;
                }

                if (p.turnCounter <= 1 && p.ownMinions.Count - p.enemyMinions.Count >= 4)
                {
                    retval -= (p.ownMinions.Count - p.enemyMinions.Count - 3) * 10;
                }
            }


            //bool hasTank = false;


            /*foreach (SecretItem si in p.enemySecretList)
            {
                if (readycount >= 1 && !hasTank && si.canbeTriggeredWithAttackingHero)
                {
                    retval -= 100;
                }
                if (readycount >= 1 && p.enemyMinions.Count >= 1 && si.canbeTriggeredWithAttackingMinion)
                {
                    retval -= 100;
                }
                if (si.canbeTriggeredWithPlayingMinion && mobsInHand >= 1)
                {
                    retval -= 25;
                }
            }*/
            retval -= p.enemySecretCount;
            retval -= p.numEnemySecretsTurnEnd * 50;
            //Helpfunctions.Instance.ErrorLog("sc:" + p.enemySecretCount+ " " + p.numEnemySecretsTurnEnd);

            //testing eval without lostdmg
            //retval -= p.lostDamage;//damage which was to high (like killing a 2/1 with an 3/3 -> => lostdamage =2

            retval -= p.lostWeaponDamage;

            //if (p.ownMinions.Count == 0) retval -= 20;
            //if (p.enemyMinions.Count == 0) retval += 20;

            if (p.enemyHero.Hp <= 0)
            {
                if (p.turnCounter <= 1)
                {
                    retval = 10000;
                }
                else
                {
                    retval += 50;//10000
                    if (p.numPlayerMinionsAtTurnStart == 0) retval += 50; // if we can kill the enemy even after a board clear, bigger bonus
                    if (p.loathebLastTurn > 0) retval += 50;  // give a bonus to turn 2 sims where we played loatheb in turn 1 to protect our lethal board

                }
            }
            else if (p.ownHero.Hp > 0)
            {
                // if our damage on board is lethal, give a strong bonus so enemy AI avoids this outcome in its turn (i.e. AI will clear our minions if it can instead of ignoring them)
                if (p.turnCounter == 1 && p.guessHeroDamage(true) >= p.enemyHero.Hp + p.enemyHero.armor) retval += 100;
            }


            //soulfire etc
            int deletecardsAtLast = 0;
            foreach (Action a in p.playactions)
            {
                if (a.actionType != actionEnum.playcard) continue;
                if (a.card.card.name == CardDB.cardName.soulfire || a.card.card.name == CardDB.cardName.doomguard || a.card.card.name == CardDB.cardName.succubus) deletecardsAtLast = 1;
                if (deletecardsAtLast == 1 && !(a.card.card.name == CardDB.cardName.soulfire || a.card.card.name == CardDB.cardName.doomguard || a.card.card.name == CardDB.cardName.succubus)) retval -= 20;
            }

            if (p.enemyHero.Hp >= 1 && p.ownHero.Hp <= 0)
            {
                //Helpfunctions.Instance.ErrorLog("turncounter " + p.turnCounter + " " + retval);
                if (p.turnCounter == 0) // own turn 
                {
                    //worst case: we die on own turn
                    retval += p.owncarddraw * 100;
                    retval = -10000;
                }
                else
                {
                    if (p.turnCounter == 1) // enemys first turn
                    {
                        retval += p.owncarddraw * 100;
                        retval -= 1000;
                    }
                    if (p.turnCounter >= 2)
                    {
                        //carddraw next turn doesnt count this turn :D
                        retval -= 100;
                    }
                }



            }

            //if (p.ownHero.Hp <= 0 && p.turnCounter < 2) retval = -10000;

            // give a bonus for making the enemy spend more mana dealing with our board, so boards where the enemy makes different plays
            // aren't considered as equal value (i.e. attacking the enemy and making him spend mana to heal vs not attacking at all)
            if (p.turnCounter == 1 || p.turnCounter == 3) retval += p.enemyMaxMana - p.mana;

            p.value = retval;
            return retval;
        }