- Re-factored AiBlockController.shouldThisBlock() into ComputerUtilCard.doesSpecifiedCreatureBlock()

- Changed Outlast AI to use doesSpecifiedCreatureBlock()
This commit is contained in:
excessum
2014-09-24 13:04:46 +00:00
parent 2813896e6b
commit 14c4b95658
4 changed files with 43 additions and 21 deletions

View File

@@ -927,23 +927,6 @@ public class AiBlockController {
return first; return first;
} }
/**
* Decide if a creature is going to be used as a blocker (is only used for AnimateAi so far)
* @param ai controller of creature
* @param blocker creature to be evaluated (must NOT already be in combat)
* @return creature will be a blocker
*/
public static boolean shouldThisBlock(final Player ai, Card blocker) {
AiBlockController aiBlk = new AiBlockController(ai);
Combat combat = ai.getGame().getCombat();
aiBlk.assignBlockers(combat, blocker, null);
if (combat.getAllBlockers().isEmpty()) {
return false;
} else {
combat.removeFromCombat(blocker);
return true;
}
}
/** /**
* Check if an attacker can be blocked profitably (ie. kill attacker) * Check if an attacker can be blocked profitably (ie. kill attacker)
* @param ai controller of attacking creature * @param ai controller of attacking creature

View File

@@ -15,6 +15,7 @@ import forge.game.Game;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.*; import forge.game.card.*;
import forge.game.combat.Combat; import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
@@ -627,12 +628,51 @@ public class ComputerUtilCard {
aiAtk.declareAttackers(combat); aiAtk.declareAttackers(combat);
return combat.isAttacking(card); return combat.isAttacking(card);
} }
/**
* Extension of doesCreatureAttackAI() for "virtual" creatures that do not actually exist on the battlefield yet
* such as unanimated manlands.
* @param ai controller of creature
* @param card creature to be evaluated
* @return creature will be attack
*/
public static boolean doesSpecifiedCreatureAttackAI(final Player ai, final Card card) { public static boolean doesSpecifiedCreatureAttackAI(final Player ai, final Card card) {
AiAttackController aiAtk = new AiAttackController(ai, card); AiAttackController aiAtk = new AiAttackController(ai, card);
Combat combat = new Combat(ai); Combat combat = new Combat(ai);
aiAtk.declareAttackers(combat); aiAtk.declareAttackers(combat);
return combat.isAttacking(card); return combat.isAttacking(card);
} }
/**
* Decide if a creature is going to be used as a blocker.
* @param ai controller of creature
* @param blocker creature to be evaluated
* @return creature will be a blocker
*/
public static boolean doesSpecifiedCreatureBlock(final Player ai, Card blocker) {
AiBlockController aiBlk = new AiBlockController(ai);
Combat combat = ai.getGame().getCombat();
if (combat == null) {
final Player opp = ai.getOpponent();
combat = new Combat(opp);
for (Card c : opp.getCreaturesInPlay()) {
if (CombatUtil.canAttackNextTurn(c, ai)) {
combat.addAttacker(c, ai);
}
}
} else {
if (combat.getAllBlockers().contains(blocker)) {
return true;
}
}
aiBlk.assignBlockers(combat, blocker, null);
if (!combat.getAllBlockers().contains(blocker)) {
return false;
} else {
combat.removeFromCombat(blocker);
return true;
}
}
/** /**
* getMostExpensivePermanentAI. * getMostExpensivePermanentAI.

View File

@@ -3,7 +3,6 @@ package forge.ai.ability;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.ai.AiBlockController;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCost; import forge.ai.ComputerUtilCost;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
@@ -171,7 +170,7 @@ public class AnimateAi extends SpellAbilityAi {
if (ph.isPlayerTurn(aiPlayer) && !ComputerUtilCard.doesSpecifiedCreatureAttackAI(aiPlayer, animatedCopy)) { if (ph.isPlayerTurn(aiPlayer) && !ComputerUtilCard.doesSpecifiedCreatureAttackAI(aiPlayer, animatedCopy)) {
return false; return false;
} }
if (ph.getPlayerTurn().isOpponentOf(aiPlayer) && !AiBlockController.shouldThisBlock(aiPlayer, animatedCopy)) { if (ph.getPlayerTurn().isOpponentOf(aiPlayer) && !ComputerUtilCard.doesSpecifiedCreatureBlock(aiPlayer, animatedCopy)) {
return false; return false;
} }
} }

View File

@@ -168,8 +168,8 @@ public class CountersPutAi extends SpellAbilityAi {
if (sa.isOutlast()) { if (sa.isOutlast()) {
if (ph.is(PhaseType.MAIN2, ai)) { //applicable to non-attackers only if (ph.is(PhaseType.MAIN2, ai)) { //applicable to non-attackers only
float chance = 0.8f; float chance = 0.8f;
if (!ai.getOpponent().getCreaturesInPlay().isEmpty()) { if (ComputerUtilCard.doesSpecifiedCreatureBlock(ai, source)) {
chance /= 2; //needs a better way to check if target is required as a blocker return false;
} }
return chance > r.nextFloat(); return chance > r.nextFloat();
} else { } else {