mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
- Improved useRemovalNow AI function.
This commit is contained in:
@@ -134,6 +134,10 @@ public class AiAttackController {
|
|||||||
return defenders;
|
return defenders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeBlocker(Card blocker) {
|
||||||
|
this.oppList.remove(blocker);
|
||||||
|
}
|
||||||
|
|
||||||
/** Choose opponent for AI to attack here. Expand as necessary. */
|
/** Choose opponent for AI to attack here. Expand as necessary. */
|
||||||
private Player choosePreferredDefenderPlayer() {
|
private Player choosePreferredDefenderPlayer() {
|
||||||
Player defender = ai.getWeakestOpponent(); //Gets opponent with the least life
|
Player defender = ai.getWeakestOpponent(); //Gets opponent with the least life
|
||||||
|
|||||||
@@ -822,8 +822,24 @@ public class ComputerUtilCard {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//interrupt 1:remove blocker to save my attacker
|
//interrupt 1: Check whether a possible blocker will be killed for the AI to make a bigger attack
|
||||||
if (ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
if (ph.is(PhaseType.MAIN1) && ph.isPlayerTurn(ai) && c.isCreature()) {
|
||||||
|
AiAttackController aiAtk = new AiAttackController(ai);
|
||||||
|
final Combat combat = new Combat(ai);
|
||||||
|
aiAtk.removeBlocker(c);
|
||||||
|
aiAtk.declareAttackers(combat);
|
||||||
|
if (!combat.getAttackers().isEmpty()) {
|
||||||
|
AiAttackController aiAtk2 = new AiAttackController(ai);
|
||||||
|
final Combat combat2 = new Combat(ai);
|
||||||
|
aiAtk2.declareAttackers(combat2);
|
||||||
|
if (combat.getAttackers().size() > combat2.getAttackers().size()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// interrupt 2: remove blocker to save my attacker
|
||||||
|
if (ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS) && !ph.isPlayerTurn(ai)) {
|
||||||
Combat currCombat = game.getCombat();
|
Combat currCombat = game.getCombat();
|
||||||
if (currCombat != null && !currCombat.getAllBlockers().isEmpty() && currCombat.getAllBlockers().contains(c)) {
|
if (currCombat != null && !currCombat.getAllBlockers().isEmpty() && currCombat.getAllBlockers().contains(c)) {
|
||||||
for (Card attacker : currCombat.getAttackersBlockedBy(c)) {
|
for (Card attacker : currCombat.getAttackersBlockedBy(c)) {
|
||||||
@@ -846,6 +862,29 @@ public class ComputerUtilCard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// interrupt 3: two for one = good
|
||||||
|
if (c.isEnchanted()) {
|
||||||
|
boolean myEnchants = false;
|
||||||
|
for (Card enc : c.getEnchantedBy(false)) {
|
||||||
|
if (enc.getOwner().equals(ai)) {
|
||||||
|
myEnchants = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!myEnchants) {
|
||||||
|
return true; //card advantage > tempo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//interrupt 4: opponent pumping target (only works if the pump target is the chosen best target to begin with)
|
||||||
|
final MagicStack stack = game.getStack();
|
||||||
|
if (!stack.isEmpty()) {
|
||||||
|
final SpellAbility topStack = stack.peekAbility();
|
||||||
|
if (topStack.getActivatingPlayer().equals(opp) && c.equals(topStack.getTargetCard()) && topStack.isSpell()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//burn and curse spells
|
//burn and curse spells
|
||||||
float valueBurn = 0;
|
float valueBurn = 0;
|
||||||
if (dmg > 0) {
|
if (dmg > 0) {
|
||||||
@@ -857,6 +896,9 @@ public class ComputerUtilCard {
|
|||||||
if (sa.getTargetRestrictions().canTgtPlayer()) {
|
if (sa.getTargetRestrictions().canTgtPlayer()) {
|
||||||
valueBurn /= 2; //preserve option to burn to the face
|
valueBurn /= 2; //preserve option to burn to the face
|
||||||
}
|
}
|
||||||
|
if (valueBurn >= 0.8 && ph.getPhase().isBefore(PhaseType.COMBAT_END)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//evaluate tempo gain
|
//evaluate tempo gain
|
||||||
@@ -880,37 +922,29 @@ public class ComputerUtilCard {
|
|||||||
if (c.isLand()) {
|
if (c.isLand()) {
|
||||||
valueTempo += 0.5f / opp.getLandsInPlay().size(); //set back opponent's mana
|
valueTempo += 0.5f / opp.getLandsInPlay().size(); //set back opponent's mana
|
||||||
}
|
}
|
||||||
if (c.isEnchanted()) {
|
|
||||||
boolean myEnchants = false;
|
|
||||||
for (Card enc : c.getEnchantedBy(false)) {
|
|
||||||
if (enc.getOwner().equals(ai)) {
|
|
||||||
myEnchants = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!myEnchants) {
|
|
||||||
valueTempo += 1; //card advantage > tempo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ph.isPlayerTurn(ai) && ph.getPhase().equals(PhaseType.END_OF_TURN)) {
|
if (!ph.isPlayerTurn(ai) && ph.getPhase().equals(PhaseType.END_OF_TURN)) {
|
||||||
valueTempo *= 2; //prefer to cast at opponent EOT
|
valueTempo *= 2; //prefer to cast at opponent EOT
|
||||||
}
|
}
|
||||||
|
if (valueTempo >= 0.8 && ph.getPhase().isBefore(PhaseType.COMBAT_END)) {
|
||||||
//interrupt 2:opponent pumping target (only works if the pump target is the chosen best target to begin with)
|
return true;
|
||||||
final MagicStack stack = ai.getGame().getStack();
|
|
||||||
if (!stack.isEmpty()) {
|
|
||||||
final SpellAbility topStack = stack.peekAbility();
|
|
||||||
if (topStack.getActivatingPlayer().equals(opp) && c.equals(topStack.getTargetCard()) && topStack.isSpell()) {
|
|
||||||
valueTempo += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//evaluate threat of targeted card
|
//evaluate threat of targeted card
|
||||||
float threat = 0;
|
float threat = 0;
|
||||||
if (c.isCreature() && ai.getLife() > 0) {
|
if (c.isCreature()) {
|
||||||
Combat combat = ai.getGame().getCombat();
|
// the base value for evaluate creature is 100
|
||||||
threat = 1.0f * ComputerUtilCombat.damageIfUnblocked(c, opp, combat, true) / ai.getLife();
|
threat += (-1 + 1.0f * ComputerUtilCard.evaluateCreature(c) / 100) / costRemoval;
|
||||||
|
if (ai.getLife() > 0 && ComputerUtilCombat.canAttackNextTurn(c)) {
|
||||||
|
Combat combat = game.getCombat();
|
||||||
|
threat += 1.0f * ComputerUtilCombat.damageIfUnblocked(c, opp, combat, true) / ai.getLife();
|
||||||
//TODO:add threat from triggers and other abilities (ie. Master of Cruelties)
|
//TODO:add threat from triggers and other abilities (ie. Master of Cruelties)
|
||||||
|
}
|
||||||
|
if (ph.isPlayerTurn(ai) && ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
||||||
|
threat *= 0.1;
|
||||||
|
}
|
||||||
|
if (!ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_BEGIN)) {
|
||||||
|
threat *= 0.1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (final StaticAbility stAb : c.getStaticAbilities()) {
|
for (final StaticAbility stAb : c.getStaticAbilities()) {
|
||||||
final Map<String, String> params = stAb.getMapParams();
|
final Map<String, String> params = stAb.getMapParams();
|
||||||
|
|||||||
Reference in New Issue
Block a user