- Fix for Combat issues that were noticed through flanking. Blocking was changing mid-block because the Stack wasn't frozen.

- Added TradeUp Blocking situation for when the AI can kill a better creature and dying in the process.
This commit is contained in:
jendave
2011-08-06 10:30:55 +00:00
parent 1445f8cc01
commit ba3b9d82b7
3 changed files with 156 additions and 114 deletions

View File

@@ -196,7 +196,8 @@ public class ComputerAI_General implements Computer {
} }
public void declare_blockers() { public void declare_blockers() {
CardList blockers = new CardList(AllZone.Computer_Play.getCards()); CardList blockers = AllZoneUtil.getCreaturesInPlay(AllZone.ComputerPlayer);
Combat combat = getCombat(AllZone.pwCombat.getAttackers(), blockers); Combat combat = getCombat(AllZone.pwCombat.getAttackers(), blockers);
combat.setPlaneswalker(AllZone.pwCombat.getPlaneswalker()); combat.setPlaneswalker(AllZone.pwCombat.getPlaneswalker());

View File

@@ -101,7 +101,7 @@ public class ComputerUtil_Block2
//finds a blocker, both the attacker and blocker are destroyed //finds a blocker, both the attacker and blocker are destroyed
//returns null if no blocker is found //returns null if no blocker is found
Card tradeSingleBlock(Card attacker) Card tradeDownSingleBlock(Card attacker)
{ {
CardList c = getPossibleBlockers(attacker); CardList c = getPossibleBlockers(attacker);
@@ -115,6 +115,21 @@ public class ComputerUtil_Block2
return null; return null;
}//tradeSingleBlock() }//tradeSingleBlock()
Card tradeUpSingleBlock(Card attacker)
{
CardList c = getPossibleBlockers(attacker);
for(int i = 0; i < c.size(); i++){
Card defender = c.get(i);
if(CombatUtil.canDestroyAttacker(attacker, defender))
{
// If Attacker has a higher Evaluation then defender, trade up!
if (CardFactoryUtil.evaluateCreature(defender) <= CardFactoryUtil.evaluateCreature(attacker))
return defender;
}
}
return null;
}//tradeSingleBlock()
//finds a blocker, neither attacker and blocker are destroyed //finds a blocker, neither attacker and blocker are destroyed
@@ -237,19 +252,20 @@ public class ComputerUtil_Block2
public Combat getBlockers() public Combat getBlockers()
{ {
//if this method is called multiple times during a turn, // TODO: this function fucking sucks
//it will always return the same value
//randomInt is used so that the computer doesn't always
//do the same thing on turn 3 if he had the same creatures in play
//I know this is a little confusing
random.setSeed(AllZone.Phase.getTurn() + randomInt);
Card c;
Combat combat = new Combat(); Combat combat = new Combat();
if (attackers.size() == 0)
return combat;
// Random seed set with time, turn and a randomInt. Should be random enough
random.setSeed(AllZone.Phase.getTurn() + System.currentTimeMillis() + randomInt );
boolean shouldBlock; boolean shouldBlock;
//if this isn't done, the attackers are shown backwards 3,2,1, //if this isn't done, the attackers are shown backwards 3,2,1,
//reverse the order here because below reverses the order again //reverse the order here because below reverses the order again
attackers.reverse(); //attackers.reverse();
//add attackers to combat //add attackers to combat
//this has to be done before the code below because sumUnblockedAttackers() //this has to be done before the code below because sumUnblockedAttackers()
@@ -259,25 +275,27 @@ public class ComputerUtil_Block2
for(int i = 0; i < attackers.size(); i++) for(int i = 0; i < attackers.size(); i++)
{ {
Card c = null;
Card attack = attackers.get(i);
boolean doubleStrike = attackers.get(i).hasDoubleStrike(); boolean doubleStrike = attack.hasDoubleStrike();
boolean trample = attackers.get(i).getKeyword().contains("Trample"); boolean trample = attack.getKeyword().contains("Trample");
//the computer blocks 50% of the time or if the computer would lose the game //the computer blocks 50% of the time or if the computer would lose the game
shouldBlock = random.nextBoolean() || blockersLife <= sumUnblockedAttackers(combat); shouldBlock = random.nextBoolean() || blockersLife <= sumUnblockedAttackers(combat);
testing("shouldBlock - " +shouldBlock); testing("shouldBlock - " +shouldBlock);
c = null;
System.out.println("Computer checking to block: "+attackers.get(i).getName());
//System.out.println("Computer checking to block: "+attack.getName());
//Lure //Lure
if(attackers.get(i).isEnchantedBy("Lure")) { if(attack.isEnchantedBy("Lure")) {
for(Card blocker:possibleBlockers) { for(Card blocker:possibleBlockers) {
if(CombatUtil.canBlock(attackers.get(i), blocker)) { if(CombatUtil.canBlock(attack, blocker)) {
System.out.println("Computer adding "+blocker+" to block "+attackers.get(i)); System.out.println("Computer adding "+blocker+" to block "+attack);
possibleBlockers.remove(blocker); possibleBlockers.remove(blocker);
combat.addBlocker(attackers.get(i), blocker); combat.addBlocker(attack, blocker);
} }
} }
} }
@@ -289,75 +307,85 @@ public class ComputerUtil_Block2
Random random = new Random(); Random random = new Random();
int randomInt = random.nextInt(100); int randomInt = random.nextInt(100);
boolean multiTrample = false;
//multiblocks for trample //multiblocks for trample
if (trample && AllZone.ComputerPlayer.getLife() <= getAttack(attackers.get(i)) ) if (trample && AllZone.ComputerPlayer.getLife() <= getAttack(attack) )
{ {
Card[] m = multipleTrampleBlock(attackers.get(i)); // If attacker has trample, block with a few creatures to prevent damage to player
Card[] m = multipleTrampleBlock(attack);
for(int inner = 0; inner < m.length; inner++) for(int inner = 0; inner < m.length; inner++)
{ {
if(m.length != 1) if(m.length != 1)
{ {
possibleBlockers.remove(m[inner]); possibleBlockers.remove(m[inner]);
combat.addBlocker(attackers.get(i), m[inner]); combat.addBlocker(attack, m[inner]);
multiTrample = true; System.out.println(m[inner].toString() + " is blocking " + attack.toString());
} }
}//for }//for
continue;
} }
if (!multiTrample) do{ // inside a do-while "loop", so we can break out of it
{
if (randomInt >= 10) if (randomInt >= 10)
{ {
c = safeSingleBlock(attackers.get(i)); // Safe Block - Attacker dies, blocker lives
c = safeSingleBlock(attack);
if(c != null) if(c != null)
testing("safe"); break;
} }
if(c == null && randomInt >= 15) if(randomInt >= 15)
{ {
//shield block - attacker lives, blocker lives //shield block - attacker lives, blocker lives
c = shieldSingleBlock(attackers.get(i)); c = shieldSingleBlock(attack);
if(c != null) if(c != null)
testing("shield"); break;
} }
if(c == null && shouldBlock) if(randomInt >= 20)
{ {
//trade block - attacker dies, blocker dies //trade block - attacker dies, blocker dies
c = tradeSingleBlock(attackers.get(i)); c = tradeUpSingleBlock(attack);
if(c != null) if(c != null)
testing("trading"); break;
} }
if(randomInt >= 25)
{
//trade block - attacker dies, blocker dies
c = tradeDownSingleBlock(attack);
if(c == null && shouldBlock) if(c != null)
break;
}
if(shouldBlock)
{ {
//chump block - attacker lives, blocker dies //chump block - attacker lives, blocker dies
c = chumpSingleBlock(attackers.get(i)); c = chumpSingleBlock(attack);
if(c != null) if(c != null)
testing("chumping"); break;
} }
if(c == null && doubleStrike && AllZone.ComputerPlayer.getLife() <= (getAttack(attackers.get(i))*2)) if(doubleStrike && AllZone.ComputerPlayer.getLife() <= (getAttack(attack)*2))
{ {
c = forceBlock(attackers.get(i)); c = forceBlock(attack);
if (c != null) if (c != null)
testing("forcing"); break;
} }
}while(false);
if(c != null) if(c != null)
{ {
// TODO: creatures that can block more than one don't necessarily get removed
//if (!c.getKeyword().contains("This card can block any number of creatures."))
possibleBlockers.remove(c); possibleBlockers.remove(c);
combat.addBlocker(attackers.get(i), c); combat.addBlocker(attack, c);
System.out.println(c.toString() + " is blocking " + attack.toString());
} }
//multiple blockers //multiple blockers
if(c == null && shouldBlock) else if(shouldBlock)
{ {
Card[] m = multipleBlock(attackers.get(i)); Card[] m = multipleBlock(attack);
for(int inner = 0; inner < m.length; inner++) for(int inner = 0; inner < m.length; inner++)
{ {
//to prevent a single flyer from blocking a single non-flyer //to prevent a single flyer from blocking a single non-flyer
@@ -365,10 +393,13 @@ public class ComputerUtil_Block2
if(m.length != 1) if(m.length != 1)
{ {
possibleBlockers.remove(m[inner]); possibleBlockers.remove(m[inner]);
combat.addBlocker(attackers.get(i), m[inner]); System.out.println(c.toString() + " is blocking " + attack.toString());
combat.addBlocker(attack, m[inner]);
} }
}//for }//for
}//if }//if
else{
System.out.println(attack.toString() + " is unblocked");
} }
}//for attackers }//for attackers

View File

@@ -206,8 +206,7 @@ public class Phase extends MyObservable
} }
// we can skip AfterBlockers and AfterAttackers if necessary // we can skip AfterBlockers and AfterAttackers if necessary
else if(phase.equals(Constant.Phase.Combat_Declare_Blockers) || else if(phase.equals(Constant.Phase.Combat_Declare_Blockers)){
phase.equals(Constant.Phase.Combat_Declare_Blockers_InstantAbility)){
if(inCombat()) { if(inCombat()) {
AllZone.Combat.verifyCreaturesInPlay(); AllZone.Combat.verifyCreaturesInPlay();
CombatUtil.showCombat(); CombatUtil.showCombat();
@@ -216,6 +215,48 @@ public class Phase extends MyObservable
AllZone.Phase.setNeedToNextPhase(true); AllZone.Phase.setNeedToNextPhase(true);
} }
else if (phase.equals(Constant.Phase.Combat_Declare_Blockers_InstantAbility)){
// After declare blockers are finished being declared mark them blocked and trigger blocking things
if(!inCombat())
AllZone.Phase.setNeedToNextPhase(true);
else{
AllZone.Combat.verifyCreaturesInPlay();
AllZone.Stack.freezeStack();
CardList list = new CardList();
list.addAll(AllZone.Combat.getAllBlockers().toArray());
list.addAll(AllZone.pwCombat.getAllBlockers().toArray());
list = list.filter(new CardListFilter(){
public boolean addCard(Card c)
{
return !c.getCreatureBlockedThisCombat();
}
});
CardList attList = new CardList();
attList.addAll(AllZone.Combat.getAttackers());
CardList pwAttList = new CardList();
pwAttList.addAll(AllZone.pwCombat.getAttackers());
CombatUtil.checkDeclareBlockers(list);
for (Card a:attList){
CardList blockList = AllZone.Combat.getBlockers(a);
for (Card b:blockList)
CombatUtil.checkBlockedAttackers(a, b);
}
for (Card a:pwAttList){
CardList blockList = AllZone.pwCombat.getBlockers(a);
for (Card b:blockList)
CombatUtil.checkBlockedAttackers(a, b);
}
AllZone.Stack.unfreezeStack();
CombatUtil.showCombat();
}
}
else if (phase.equals(Constant.Phase.Combat_FirstStrikeDamage)){ else if (phase.equals(Constant.Phase.Combat_FirstStrikeDamage)){
if(!inCombat()) if(!inCombat())
AllZone.Phase.setNeedToNextPhase(true); AllZone.Phase.setNeedToNextPhase(true);
@@ -350,38 +391,7 @@ public class Phase extends MyObservable
AllZone.Phase.setPlayerTurn(handleNextTurn()); AllZone.Phase.setPlayerTurn(handleNextTurn());
if (is(Constant.Phase.Combat_Declare_Blockers)){ if (is(Constant.Phase.Combat_Declare_Blockers)){
// Before damage is assigned, confirm how things are blocked/blocking
AllZone.Stack.unfreezeStack(); AllZone.Stack.unfreezeStack();
CardList list = new CardList();
list.addAll(AllZone.Combat.getAllBlockers().toArray());
list.addAll(AllZone.pwCombat.getAllBlockers().toArray());
list = list.filter(new CardListFilter(){
public boolean addCard(Card c)
{
return !c.getCreatureBlockedThisCombat();
}
});
CardList attList = new CardList();
attList.addAll(AllZone.Combat.getAttackers());
CardList pwAttList = new CardList();
pwAttList.addAll(AllZone.pwCombat.getAttackers());
CombatUtil.checkDeclareBlockers(list);
for (Card a:attList){
CardList blockList = AllZone.Combat.getBlockers(a);
for (Card b:blockList)
CombatUtil.checkBlockedAttackers(a, b);
}
for (Card a:pwAttList){
CardList blockList = AllZone.pwCombat.getBlockers(a);
for (Card b:blockList)
CombatUtil.checkBlockedAttackers(a, b);
}
} }
if (is(Constant.Phase.Combat_End) && extraCombats > 0){ if (is(Constant.Phase.Combat_End) && extraCombats > 0){