protected virtual ActionBase PlayCardsToField() { // Get all available cards... List <HRCard> availableCards = HRCard.GetCards(HRPlayer.GetLocalPlayer(), HRCardZone.HAND); if (availableCards.Count > 0) { HRCard coin = null; foreach (var item in availableCards) { #region Skip The Coin string cardID = item.GetEntity().GetCardId(); if (cardID == "GAME_005" || cardID == "GAME_005e") { coin = item; continue; } #endregion if (item.GetEntity().GetCost() <= HRPlayer.GetLocalPlayer().GetNumAvailableResources()) { if (HRBattle.CanUseCard(item.GetEntity()) && HRCardManager.IsCardAllowedByRule(item)) { return(new PlayCardAction(item)); } } } #region The Coin Feature // Feature: The Coin // https://github.com/juce-mmocrawlerbots/HREngine/issues/13 if (coin != null) { foreach (var card in availableCards) { if (card.GetEntity().GetCardId() != coin.GetEntity().GetCardId()) { if (card.GetEntity().IsMinion() || card.GetEntity().IsSpell() || (!HRPlayer.GetLocalPlayer().HasWeapon() && card.GetEntity().IsWeapon())) { if (card.GetEntity().GetCost() <= (HRPlayer.GetLocalPlayer().GetNumAvailableResources() + 1)) { HRLog.Write( String.Format("Spawn [{0}] and then [{1}]", coin.GetEntity().GetName(), card.GetEntity().GetName())); NextFixedAction = new PlayCardAction(card); return(new PlayCardAction(coin)); } } } } } #endregion } return(null); }
public static PlayerPossibleAttack GetPossibleAttack(HRPlayer Player, int RequiredAttack, int Limit = -1) { var result = new PlayerPossibleAttack(); var playerState = new PlayerState(Player); var minions = playerState.ReadyMinions; // FIX: Only use cards to attack that are really needed to defeat somone. // (sorted by attack) var sorting = new Sorting(); sorting.SortByAttack(ref minions, Sorting.SortMode.Descending); // Loop through all minions that can attack.. foreach (var item in minions) { if (HRCardManager.CanAttackWithCard(item.GetCard())) { if (Limit == -1) { result.Attack += item.GetATK(); result.Cards.Add(item); } else if (result.Cards.Count + 1 == Limit) { // Try to find a combination that matches... if (result.Attack + item.GetATK() >= RequiredAttack) { result.Attack += item.GetATK(); result.Cards.Add(item); } } else { result.Attack += item.GetATK(); result.Cards.Add(item); } } } if (result.Attack < RequiredAttack) { int remainingMana = Player.GetNumAvailableResources(); // Check other resources that can deal damage. // Deal damage with hero power? if (Player.GetHeroPower().GetATK() > 0) { if (Player.GetHeroPower().GetCost() <= remainingMana) { result.Attack += Player.GetHeroPower().GetATK(); result.Cost += Player.GetHeroPower().GetCost(); result.Cards.Add(Player.GetHeroPower()); remainingMana -= Player.GetHeroPower().GetCost(); } } // Hero Card most times: Weapons and other special stuff. if (Player.HasWeapon() && Player.GetWeaponCard().GetEntity().GetATK() > 0 && Player.GetWeaponCard().GetEntity().CanAttack() && Player.GetWeaponCard().GetEntity().GetCost() <= remainingMana) { if (HRCardManager.CanAttackWithCard(Player.GetHero().GetCard())) { result.Attack += Player.GetWeaponCard().GetEntity().GetATK(); result.Cost += Player.GetWeaponCard().GetEntity().GetCost(); result.Cards.Add(Player.GetWeaponCard().GetEntity()); remainingMana -= Player.GetHero().GetCost(); } } // Remaining cards on hand? List <HRCard> playerHand = HRCard.GetCards(Player, HRCardZone.HAND); foreach (var item in playerHand) { if ((item.GetEntity().IsSpell() || (item.GetEntity().IsMinion() && item.GetEntity().HasCharge())) && item.GetEntity().GetATK() > 0) { int cost = item.GetEntity().GetCost(); if (cost <= remainingMana) { result.Attack += item.GetEntity().GetATK(); result.Cost += cost; result.Cards.Add(item.GetEntity()); remainingMana -= cost; } } } } return(result); }
protected virtual HREngine.API.Actions.ActionBase UpdateBattleState() { HREngine.API.Actions.ActionBase result = NextFixedAction; if (result != null) { NextFixedAction = null; return(result); } // If a previous action was not handled successful the Bot remains // in target mode. // Target here with 'LastTarget'. If the specified Target is null // the bot automatically selects the best target based on a rule // or enemy condition. if (HRBattle.IsInTargetMode()) { HRLog.Write("Targeting..."); HREntity TargetEntity = PlayCardAction.LastTarget; if (TargetEntity == null) { HRCardManager.GetTargetForCard(PlayCardAction.LastPlayedCard); if (TargetEntity == null) { TargetEntity = GetNextAttackToAttack(); } } return(new TargetAction(TargetEntity)); } var localPlayerState = new PlayerState(HRPlayer.GetLocalPlayer()); var enemyPlayerState = new PlayerState(HRPlayer.GetEnemyPlayer()); // Fix: Druid: doesn't attack (and even other) // https://github.com/Hearthcrawler/HREngine/issues/40 if (!localPlayerState.Player.HasWeapon() && localPlayerState.Player.GetHero().CanAttack() && localPlayerState.Player.GetHero().GetATK() > 0 && HRBattle.CanUseCard(localPlayerState.Player.GetHero())) { return(new AttackAction( localPlayerState.Player.GetHero(), GetNextAttackToAttack())); } if (!enemyPlayerState.Player.HasATauntMinion()) { if (enemyPlayerState.Player.GetHero().CanBeAttacked()) { var current = PlayerState.GetPossibleAttack( localPlayerState.Player, enemyPlayerState.Health); if (current.Attack >= enemyPlayerState.Health) { if (current.Cards.Count > 0) { return(new AttackAction(current.Cards[0], enemyPlayerState.Player.GetHero())); } } } } if (IsDefaultHealingEnabled()) { if (localPlayerState.Player.GetHero().GetClass() == HRClass.PRIEST) { if (localPlayerState.Player.GetHeroPower().GetCost() <= localPlayerState.Mana) { if (localPlayerState.Health <= 17) { if (HRBattle.CanUseCard(localPlayerState.Player.GetHeroPower())) { return(new PlayCardAction( localPlayerState.Player.GetHeroPower().GetCard(), HRPlayer.GetLocalPlayer().GetHero())); } } else { // FIX: Heal minions if possible // https://github.com/Hearthcrawler/HREngine/issues/27 foreach (var item in localPlayerState.ReadyMinions) { if (item.GetRemainingHP() < item.GetHealth()) { // Heal damaged minions... if (HRBattle.CanUseCard(localPlayerState.Player.GetHeroPower())) { return(new PlayCardAction( localPlayerState.Player.GetHeroPower().GetCard(), HRPlayer.GetLocalPlayer().GetHero())); } } } } } } } // Next cards to push... if (HRPlayer.GetLocalPlayer().GetNumFriendlyMinionsInPlay() < 7) { result = PlayCardsToField(); if (result != null) { return(result); } else { // There are no cards to play.. if (localPlayerState.Player.GetHero().GetClass() == HRClass.WARLOCK) { // Can we use our hero power? // Warlock should not suicide. // FIX: https://github.com/Hearthcrawler/HREngine/issues/30 if (localPlayerState.Health >= 10) { // At least 3 mana left if we draw a card, okay? if (localPlayerState.Player.GetHeroPower().GetCost() + 3 <= localPlayerState.Mana) { if (HRBattle.CanUseCard(localPlayerState.Player.GetHeroPower())) { return(new PlayCardAction(localPlayerState.Player.GetHeroPower().GetCard())); } } } } } } // Priority: Always attack taunt minions first. if (enemyPlayerState.TauntMinions.Count > 0) { result = AttackTauntMinions(enemyPlayerState); if (result != null) { return(result); } } // Bot does not attack when there is stealthed taunts // Fix: https://github.com/Hearthcrawler/HREngine/issues/60 // If AttackTauntMinions() cannot attack because of stealthed - the action is null // and the bot should continue with default attack routine. // // Attack other minions or hero... result = Attack(); if (result != null) { return(result); } // Use Hero Power that make sense at last... if (localPlayerState.Player.GetHeroPower().GetCost() <= localPlayerState.Mana) { switch (localPlayerState.Player.GetHero().GetClass()) { case HRClass.DRUID: case HRClass.WARRIOR: case HRClass.MAGE: case HRClass.PALADIN: case HRClass.HUNTER: case HRClass.SHAMAN: case HRClass.ROGUE: { if (HRBattle.CanUseCard(localPlayerState.Player.GetHeroPower())) { return(new PlayCardAction(localPlayerState.Player.GetHeroPower().GetCard())); } } break; default: break; } } return(null); }