package yourock import . "github.com/golangconf/gophers-and-dragons/game" const MagicArrowMP = 1 const FireboltMP = 3 const HealMP = 4 const RestMP = 2 const HealAvg = 12.5 const DragonDmgAvg = 5.5 const PowerAttackDmgAvg = 4.5 const AttackDmgAvg = 3 func heroCanSurviveDragon(s State) bool { dragonHP := float64(s.Creep.HP) myHP := float64(s.Avatar.HP) manaLeft := s.Avatar.MP healsLeft := s.Deck[CardHeal].Count parriesLeft := s.Deck[CardParry].Count powersLeft := s.Deck[CardPowerAttack].Count stunsLeft := s.Deck[CardStun].Count for dragonHP > 0 && myHP > 0 { if myHP <= 25 && healsLeft > 0 && manaLeft >= HealMP { myHP += HealAvg - DragonDmgAvg healsLeft-- manaLeft -= HealMP continue } if parriesLeft > 0 { dragonHP -= DragonDmgAvg continue } if stunsLeft > 0 { stunsLeft-- if powersLeft > 0 { powersLeft-- dragonHP -= PowerAttackDmgAvg } else { dragonHP -= AttackDmgAvg } continue } myHP -= DragonDmgAvg if powersLeft > 0 { powersLeft-- dragonHP -= PowerAttackDmgAvg continue } dragonHP -= AttackDmgAvg } return myHP > 0 && dragonHP < 0 } func fightDragon(s State) CardType { if s.Creep.IsFull() && !heroCanSurviveDragon(s) { if s.Can(CardHeal) { return CardHeal } return CardRetreat } if s.Avatar.HP <= 25 && s.Can(CardHeal) { return CardHeal } if !s.Creep.IsStunned() && s.Can(CardParry) { return CardParry } if !s.Creep.IsStunned() && s.Can(CardStun) { return CardStun } if s.Can(CardPowerAttack) { return CardPowerAttack } return CardAttack } func fightMummy(s State) CardType { if s.Creep.IsFull() { if s.Avatar.MP >= 2*FireboltMP && s.Deck[CardFirebolt].Count >= 2 { return CardFirebolt } return CardRetreat } if s.Creep.HP <= 2 { return CardAttack } else if s.Creep.HP <= 3 && s.Avatar.MP >= HealMP+MagicArrowMP { return CardMagicArrow } else if s.Can(CardFirebolt) { return CardFirebolt } return CardRetreat } func fightClaws(s State) CardType { if s.Creep.IsFull() { potentialHPLeft := float64(s.Avatar.HP) mpLeft := s.Avatar.MP for i := 0; i < s.Deck[CardHeal].Count && mpLeft >= HealMP; i++ { mpLeft -= HealMP potentialHPLeft += HealAvg } // Each turn Claws takes out 3 HP but only until your HP >= 20. // This variable estimates how many turns we have to kill Claws until // our HP drops below 20 and we would have to retreat. maxTurnsToFight := int((potentialHPLeft - 20.0) / 3.0) turnsToKillClaws := s.Creep.HP / AttackDmgAvg // should be precisely 4 if turnsToKillClaws > maxTurnsToFight { return CardRetreat } } if s.Avatar.HP <= 20 && s.Creep.HP > 3 { return CardRetreat } if s.Creep.HP == 3 && s.Avatar.MP >= MagicArrowMP+HealMP && s.Can(CardMagicArrow) { return CardMagicArrow } return CardAttack } func fightKubus(s State) CardType { // not worth it most of the time return CardRetreat } func ChooseCard(s State) CardType { if s.Creep.Type == CreepCheepy { if s.Creep.IsFull() && s.Avatar.HP <= 25 && s.Can(CardHeal) { return CardHeal } if s.Creep.IsFull() && s.Avatar.HP <= 20 && s.Can(CardRest) { return CardRest } return CardAttack } if s.Creep.Type == CreepDragon { return fightDragon(s) } minHealHP := 10 if s.Creep.Damage.High() <= 4 { minHealHP = 25 } else if s.Creep.Traits.Has(TraitBloodlust) { minHealHP = 20 } if s.Avatar.HP <= minHealHP && s.Can(CardHeal) { return CardHeal } if s.Creep.Type == CreepClaws { return fightClaws(s) } if s.Creep.Type == CreepKubus { return fightKubus(s) } if s.Creep.Type == CreepMummy { return fightMummy(s) } if s.Round >= 10 && s.Avatar.MP >= FireboltMP+HealMP && s.Can(CardFirebolt) { return CardFirebolt } if s.Creep.Damage.High() >= 5 && s.Can(CardPowerAttack) { return CardPowerAttack } if s.Creep.HP == 3 && s.Avatar.MP >= MagicArrowMP+HealMP && s.Can(CardMagicArrow) { return CardMagicArrow } return CardAttack }