mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
- Cleanup and updates of AI blocking.
This commit is contained in:
@@ -453,6 +453,56 @@ public class CombatUtil {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This function take Doran and Double Strike into account
|
||||||
|
public static int getAttack(Card c)
|
||||||
|
{
|
||||||
|
int n = c.getNetAttack();
|
||||||
|
|
||||||
|
if(CombatUtil.isDoranInPlay())
|
||||||
|
n = c.getNetDefense();
|
||||||
|
|
||||||
|
if(c.hasDoubleStrike())
|
||||||
|
n *= 2;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Checks if the life of the attacked Player/Planeswalker is in danger
|
||||||
|
public static boolean lifeInDanger(Combat combat) {
|
||||||
|
|
||||||
|
int damage = 0;
|
||||||
|
int poison = 0;
|
||||||
|
CardList attackers = new CardList(combat.getAttackers());
|
||||||
|
CardList unblocked = new CardList(combat.getAttackers());
|
||||||
|
CardList blockers = new CardList();
|
||||||
|
Card attacker = new Card();
|
||||||
|
|
||||||
|
for(int i = 0; i < attackers.size(); i++) {
|
||||||
|
attacker = attackers.get(i);
|
||||||
|
|
||||||
|
blockers = combat.getBlockers(attacker);
|
||||||
|
|
||||||
|
if(blockers.size() == 0) unblocked.add(attacker);
|
||||||
|
else if(attacker.hasKeyword("Trample") && getAttack(attacker) > CombatUtil.totalShieldDamage(attacker,blockers)) {
|
||||||
|
if(!attacker.hasKeyword("Infect"))
|
||||||
|
damage += getAttack(attacker) - CombatUtil.totalShieldDamage(attacker,blockers);
|
||||||
|
if(attacker.hasKeyword("Infect"))
|
||||||
|
poison += getAttack(attacker) - CombatUtil.totalShieldDamage(attacker,blockers);
|
||||||
|
if(attacker.hasKeyword("Poisonous"))
|
||||||
|
poison += attacker.getKeywordMagnitude("Poisonous");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (combat.getPlaneswalker() == null) {
|
||||||
|
if (damage + 3 > AllZone.ComputerPlayer.getLife() || poison + 2 > 10 - AllZone.ComputerPlayer.getPoisonCounters())
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (damage + 1 > combat.getPlaneswalker().getCounters(Counters.LOYALTY))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static int totalDamageOfBlockers(Card attacker, CardList defenders) {
|
public static int totalDamageOfBlockers(Card attacker, CardList defenders) {
|
||||||
int damage = 0;
|
int damage = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -198,6 +198,15 @@ public class ComputerAI_General implements Computer {
|
|||||||
public void declare_blockers() {
|
public void declare_blockers() {
|
||||||
CardList blockers = AllZoneUtil.getCreaturesInPlay(AllZone.ComputerPlayer);
|
CardList blockers = AllZoneUtil.getCreaturesInPlay(AllZone.ComputerPlayer);
|
||||||
|
|
||||||
|
//If Player life is in danger protect it first
|
||||||
|
if(CombatUtil.lifeInDanger(AllZone.Combat)) {
|
||||||
|
AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers);
|
||||||
|
CardList remove = AllZone.Combat.getAllBlockers();
|
||||||
|
for(int i = 0; i < remove.size(); i++)
|
||||||
|
blockers.remove(remove.get(i));
|
||||||
|
|
||||||
|
AllZone.pwCombat = ComputerUtil_Block2.getBlockers(AllZone.pwCombat, blockers);
|
||||||
|
} else { // Otherwise protect Planeswalkers first
|
||||||
AllZone.pwCombat = ComputerUtil_Block2.getBlockers(AllZone.pwCombat, blockers);
|
AllZone.pwCombat = ComputerUtil_Block2.getBlockers(AllZone.pwCombat, blockers);
|
||||||
|
|
||||||
CardList remove = AllZone.pwCombat.getAllBlockers();
|
CardList remove = AllZone.pwCombat.getAllBlockers();
|
||||||
@@ -205,6 +214,7 @@ public class ComputerAI_General implements Computer {
|
|||||||
blockers.remove(remove.get(i));
|
blockers.remove(remove.get(i));
|
||||||
|
|
||||||
AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers);
|
AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers);
|
||||||
|
}
|
||||||
|
|
||||||
CombatUtil.showCombat();
|
CombatUtil.showCombat();
|
||||||
|
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ public class ComputerUtil_Block2
|
|||||||
{
|
{
|
||||||
return c.getNetDefense();
|
return c.getNetDefense();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
//this doesn't take into account first strike,
|
//this doesn't take into account first strike,
|
||||||
//use CombatUtil.canDestroyAttacker()
|
//use CombatUtil.canDestroyAttacker()
|
||||||
@@ -468,7 +468,7 @@ public class ComputerUtil_Block2
|
|||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//finds the creatures able to block the attacker
|
//finds the creatures able to block the attacker
|
||||||
private static CardList getPossibleBlockers(Card attacker, CardList blockersLeft) {
|
private static CardList getPossibleBlockers(Card attacker, CardList blockersLeft) {
|
||||||
@@ -506,22 +506,6 @@ public class ComputerUtil_Block2
|
|||||||
return blockers;
|
return blockers;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Checks if the life of the Player/Planeswalker is in danger
|
|
||||||
private static boolean lifeInDanger(Combat combat, int anticipatedDamage, int anticipatedPoison , CardList attackersLeft) {
|
|
||||||
|
|
||||||
if (combat.getPlaneswalker() == null) {
|
|
||||||
if (anticipatedDamage + sumAttack(attackersLeft) + 3 > AllZone.ComputerPlayer.getLife()
|
|
||||||
|| anticipatedPoison + sumPoison(attackersLeft) + 2 > 10 - AllZone.ComputerPlayer.getPoisonCounters())
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if (anticipatedDamage + sumAttack(attackersLeft) +1 > combat.getPlaneswalker().getCounters(Counters.LOYALTY))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Combat getBlockers(Combat originalCombat, CardList possibleBlockers) {
|
public static Combat getBlockers(Combat originalCombat, CardList possibleBlockers) {
|
||||||
|
|
||||||
Combat combat = originalCombat;
|
Combat combat = originalCombat;
|
||||||
@@ -531,13 +515,6 @@ public class ComputerUtil_Block2
|
|||||||
if (attackers.size() == 0)
|
if (attackers.size() == 0)
|
||||||
return combat;
|
return combat;
|
||||||
|
|
||||||
/*
|
|
||||||
for(int i = 0; i < attackers.size(); i++) {
|
|
||||||
Card a = attackers.get(i);
|
|
||||||
combat.addAttacker(a);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
CardList attackersLeft = attackers; //keeps track of all currently unblocked attackers
|
CardList attackersLeft = attackers; //keeps track of all currently unblocked attackers
|
||||||
CardList blockedButUnkilled = new CardList(); //keeps track of all blocked attackers that currently wouldn't be destroyed
|
CardList blockedButUnkilled = new CardList(); //keeps track of all blocked attackers that currently wouldn't be destroyed
|
||||||
CardList tramplingAttackers = new CardList();
|
CardList tramplingAttackers = new CardList();
|
||||||
@@ -546,8 +523,6 @@ public class ComputerUtil_Block2
|
|||||||
CardList safeBlockers = new CardList();
|
CardList safeBlockers = new CardList();
|
||||||
CardList killingBlockers = new CardList();
|
CardList killingBlockers = new CardList();
|
||||||
CardList chumpBlockers = new CardList();
|
CardList chumpBlockers = new CardList();
|
||||||
int anticipatedDamage = 0; //this is the anticipated damage to the computer player
|
|
||||||
int anticipatedPoison = 0; //this is the anticipated poison to the computer player
|
|
||||||
int diff = AllZone.ComputerPlayer.getLife() * 2 + 5; //This is the minimal gain for an unnecessary trade
|
int diff = AllZone.ComputerPlayer.getLife() * 2 + 5; //This is the minimal gain for an unnecessary trade
|
||||||
Card a = new Card();
|
Card a = new Card();
|
||||||
Card b = new Card();
|
Card b = new Card();
|
||||||
@@ -560,8 +535,6 @@ public class ComputerUtil_Block2
|
|||||||
a = attackers.get(i);
|
a = attackers.get(i);
|
||||||
if(!CombatUtil.canBeBlocked(a)) {
|
if(!CombatUtil.canBeBlocked(a)) {
|
||||||
attackersLeft.remove(a);
|
attackersLeft.remove(a);
|
||||||
anticipatedDamage += getAttack(a);
|
|
||||||
//anticipatedPoison += a.getNetAttack(); //TODO Poison
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,6 +553,9 @@ public class ComputerUtil_Block2
|
|||||||
//Begin with the attackers that pose the biggest thread
|
//Begin with the attackers that pose the biggest thread
|
||||||
CardListUtil.sortAttack(attackersLeft);
|
CardListUtil.sortAttack(attackersLeft);
|
||||||
|
|
||||||
|
//Begin with the weakest blockers
|
||||||
|
CardListUtil.sortAttackLowFirst(blockersLeft);
|
||||||
|
|
||||||
CardList currentAttackers = attackersLeft;
|
CardList currentAttackers = attackersLeft;
|
||||||
|
|
||||||
//first choose good blocks only
|
//first choose good blocks only
|
||||||
@@ -611,8 +587,6 @@ public class ComputerUtil_Block2
|
|||||||
|
|
||||||
if(CardFactoryUtil.evaluateCreature(worst) + diff < CardFactoryUtil.evaluateCreature(attacker)) {
|
if(CardFactoryUtil.evaluateCreature(worst) + diff < CardFactoryUtil.evaluateCreature(attacker)) {
|
||||||
blocker = worst;
|
blocker = worst;
|
||||||
anticipatedDamage += anticipateDamage(attacker, blocker);
|
|
||||||
anticipatedPoison += anticipatePoison(attacker, blocker);
|
|
||||||
}
|
}
|
||||||
// TODO: 4.good Gangblocks
|
// TODO: 4.good Gangblocks
|
||||||
}
|
}
|
||||||
@@ -629,14 +603,12 @@ public class ComputerUtil_Block2
|
|||||||
if(blockersLeft.size() == 0) return combat;
|
if(blockersLeft.size() == 0) return combat;
|
||||||
|
|
||||||
//choose necessary trade blocks if life is in danger
|
//choose necessary trade blocks if life is in danger
|
||||||
if (lifeInDanger(combat, anticipatedDamage, anticipatedPoison, attackersLeft))
|
if (CombatUtil.lifeInDanger(combat))
|
||||||
for(int i = 0; i < attackersLeft.size(); i++) {
|
for(int i = 0; i < attackersLeft.size(); i++) {
|
||||||
attacker = attackersLeft.get(i);
|
attacker = attackersLeft.get(i);
|
||||||
killingBlockers = getKillingBlockers(attacker, getPossibleBlockers(attacker, blockersLeft));
|
killingBlockers = getKillingBlockers(attacker, getPossibleBlockers(attacker, blockersLeft));
|
||||||
if(killingBlockers.size() > 0) {
|
if(killingBlockers.size() > 0) {
|
||||||
blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
|
blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
|
||||||
if (attacker.hasKeyword("Trample") && getAttack(attacker) > blocker.getNetDefense())
|
|
||||||
anticipatedDamage += getAttack(attacker) - blocker.getNetDefense();
|
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
currentAttackers.remove(attacker);
|
currentAttackers.remove(attacker);
|
||||||
blockersLeft.remove(blocker);
|
blockersLeft.remove(blocker);
|
||||||
@@ -646,14 +618,12 @@ public class ComputerUtil_Block2
|
|||||||
attackersLeft = currentAttackers;
|
attackersLeft = currentAttackers;
|
||||||
|
|
||||||
//choose necessary chump blocks if life is still in danger
|
//choose necessary chump blocks if life is still in danger
|
||||||
if (lifeInDanger(combat, anticipatedDamage, anticipatedPoison, attackersLeft))
|
if (CombatUtil.lifeInDanger(combat))
|
||||||
for(int i = 0; i < attackersLeft.size(); i++) {
|
for(int i = 0; i < attackersLeft.size(); i++) {
|
||||||
attacker = attackersLeft.get(i);
|
attacker = attackersLeft.get(i);
|
||||||
chumpBlockers = getPossibleBlockers(attacker, blockersLeft);
|
chumpBlockers = getPossibleBlockers(attacker, blockersLeft);
|
||||||
if(chumpBlockers.size() > 0) {
|
if(chumpBlockers.size() > 0) {
|
||||||
blocker = CardFactoryUtil.AI_getWorstCreature(chumpBlockers);
|
blocker = CardFactoryUtil.AI_getWorstCreature(chumpBlockers);
|
||||||
if (attacker.hasKeyword("Trample") && getAttack(attacker) > blocker.getNetDefense())
|
|
||||||
anticipatedDamage += getAttack(attacker) - blocker.getNetDefense();
|
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
currentAttackers.remove(attacker);
|
currentAttackers.remove(attacker);
|
||||||
blockedButUnkilled.add(attacker);
|
blockedButUnkilled.add(attacker);
|
||||||
@@ -664,7 +634,7 @@ public class ComputerUtil_Block2
|
|||||||
attackersLeft = currentAttackers;
|
attackersLeft = currentAttackers;
|
||||||
|
|
||||||
//Reinforce blockers blocking attackers with trample if life is still in danger
|
//Reinforce blockers blocking attackers with trample if life is still in danger
|
||||||
if (lifeInDanger(combat, anticipatedDamage, anticipatedPoison, attackersLeft)) {
|
if (CombatUtil.lifeInDanger(combat)) {
|
||||||
tramplingAttackers = attackers.getKeyword("Trample");
|
tramplingAttackers = attackers.getKeyword("Trample");
|
||||||
tramplingAttackers = tramplingAttackers.getKeywordsDontContain("Rampage"); //Don't make it worse
|
tramplingAttackers = tramplingAttackers.getKeywordsDontContain("Rampage"); //Don't make it worse
|
||||||
for(int i = 0; i < tramplingAttackers.size(); i++) {
|
for(int i = 0; i < tramplingAttackers.size(); i++) {
|
||||||
@@ -673,7 +643,7 @@ public class ComputerUtil_Block2
|
|||||||
for(int j = 0; j < chumpBlockers.size(); j++) {
|
for(int j = 0; j < chumpBlockers.size(); j++) {
|
||||||
blocker = chumpBlockers.get(j);
|
blocker = chumpBlockers.get(j);
|
||||||
//Add an additional blocker if the current blockers are not enough and the new one would suck some of the damage
|
//Add an additional blocker if the current blockers are not enough and the new one would suck some of the damage
|
||||||
if(getAttack(attacker) > CombatUtil.totalShieldDamage(attacker,combat.getBlockers(attacker))
|
if(CombatUtil.getAttack(attacker) > CombatUtil.totalShieldDamage(attacker,combat.getBlockers(attacker))
|
||||||
&& CombatUtil.shieldDamage(attacker, blocker) > 0) {
|
&& CombatUtil.shieldDamage(attacker, blocker) > 0) {
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
blockersLeft.remove(blocker);
|
blockersLeft.remove(blocker);
|
||||||
|
|||||||
Reference in New Issue
Block a user