- Basic and conservative prediction of the total number of available blockers with vehicles in mind for the purpose of AI alpha-strike: the AI will try to acknowledge the fact that for the vehicle to become active, generally at least one other creature will need to tap. This should allow the AI to somewhat better predict when it can alpha strike for lethal in presence of vehicles.

- Crew prediction needs to be somehow expanded in general: in all other attack routines the AI assumes that each vehicle on the battlefield will activate and the human will not tap anything to activate them, which leads to the AI becoming very "scared" of inactive vehicles on the battlefield.
This commit is contained in:
Agetian
2017-01-30 17:48:39 +00:00
parent c3cbeb3efd
commit 3e325d243a

View File

@@ -25,12 +25,14 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.ai.ability.AnimateAi; import forge.ai.ability.AnimateAi;
import forge.card.CardTypeView;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.ability.effects.ProtectEffect; import forge.game.ability.effects.ProtectEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CounterType; import forge.game.card.CounterType;
import forge.game.combat.Combat; import forge.game.combat.Combat;
import forge.game.combat.CombatUtil; import forge.game.combat.CombatUtil;
@@ -399,6 +401,25 @@ public class AiAttackController {
final List<Card> remainingAttackers = new ArrayList<Card>(this.attackers); final List<Card> remainingAttackers = new ArrayList<Card>(this.attackers);
final List<Card> remainingBlockers = new ArrayList<Card>(this.blockers); final List<Card> remainingBlockers = new ArrayList<Card>(this.blockers);
final List<Card> blockedAttackers = new ArrayList<Card>(); final List<Card> blockedAttackers = new ArrayList<Card>();
// Conservative prediction for vehicles: the AI tries to acknowledge the fact that
// at least one creature will tap to crew a blocking vehicle when predicting if an
// alpha strike for lethal is viable
int maxBlockersAfterCrew = remainingBlockers.size();
for (Card c : this.blockers) {
CardTypeView cardType = c.getCurrentState().getType();
boolean oppControlsPW = !CardLists.filter(c.getController().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.PLANEWALKERS).isEmpty();
if (c.getName().equals("Heart of Kirin") && oppControlsPW) {
continue;
} else if (c.getName().equals("Peacewalker Colossus")) {
// TODO: the AI should probably predict if the human can actually use its activated ability
continue;
} else if (cardType.hasSubtype("Vehicle") && !cardType.isCreature()) {
maxBlockersAfterCrew--;
}
}
final Player opp = this.defendingOpponent; final Player opp = this.defendingOpponent;
for (Card attacker : attackers) { for (Card attacker : attackers) {
@@ -423,18 +444,20 @@ public class AiAttackController {
// presumes the Human will block // presumes the Human will block
for (Card blocker : remainingBlockers) { for (Card blocker : remainingBlockers) {
if (remainingAttackers.isEmpty()) { if (remainingAttackers.isEmpty() || maxBlockersAfterCrew == 0) {
break; break;
} }
if (blocker.hasKeyword("CARDNAME can block an additional creature.")) { if (blocker.hasKeyword("CARDNAME can block an additional creature.")) {
blockedAttackers.add(remainingAttackers.get(0)); blockedAttackers.add(remainingAttackers.get(0));
remainingAttackers.remove(0); remainingAttackers.remove(0);
maxBlockersAfterCrew--;
if (remainingAttackers.isEmpty()) { if (remainingAttackers.isEmpty()) {
break; break;
} }
} }
blockedAttackers.add(remainingAttackers.get(0)); blockedAttackers.add(remainingAttackers.get(0));
remainingAttackers.remove(0); remainingAttackers.remove(0);
maxBlockersAfterCrew--;
} }
unblockedAttackers.addAll(remainingAttackers); unblockedAttackers.addAll(remainingAttackers);