- Initial code to Combine Combat and pwCombat into a unified combat front.

- Human can now attack more than one Planeswalker.
This commit is contained in:
jendave
2011-08-06 14:15:37 +00:00
parent eea8f37930
commit 9cf0ec99ae
19 changed files with 441 additions and 710 deletions

2
.gitattributes vendored
View File

@@ -6367,9 +6367,7 @@ src/forge/ImagePreviewPanel.java -text svneol=native#text/plain
src/forge/Input.java svneol=native#text/plain
src/forge/InputControl.java svneol=native#text/plain
src/forge/Input_Attack.java svneol=native#text/plain
src/forge/Input_Attack_Planeswalker.java svneol=native#text/plain
src/forge/Input_Block.java svneol=native#text/plain
src/forge/Input_Block_Planeswalker.java svneol=native#text/plain
src/forge/Input_Cleanup.java svneol=native#text/plain
src/forge/Input_Mulligan.java svneol=native#text/plain
src/forge/Input_PassPriority.java -text svneol=native#text/plain

View File

@@ -346,9 +346,6 @@ public class AbilityFactory_GainControl {
CardList list = new CardList(AllZone.Combat.getAttackers());
if(list.contains(c)) AllZone.Combat.removeFromCombat(c);
CardList pwlist = new CardList(AllZone.pwCombat.getAttackers());
if(pwlist.contains(c)) AllZone.pwCombat.removeFromCombat(c);
PlayerZone to = AllZone.getZone(Constant.Zone.Battlefield, c.getOwner());
to.add(c);

View File

@@ -42,7 +42,6 @@ public class AllZone implements NewConstants {
//shared between Input_Attack, Input_Block, Input_CombatDamage , InputState_Computer
public static Combat Combat = new Combat();
public static Combat pwCombat = new Combat();//for Planeswalker combat
//Human_Play, Computer_Play is different because Card.comesIntoPlay() is called when a card is added by PlayerZone.add(Card)
public final static PlayerZone Human_Battlefield = new PlayerZone_ComesIntoPlay(Constant.Zone.Battlefield, AllZone.HumanPlayer);

View File

@@ -2710,14 +2710,11 @@ public class Card extends MyObservable {
}
public boolean isAttacking() {
CardList attackers = new CardList(AllZone.Combat.getAttackers());
attackers.addAll(AllZone.pwCombat.getAttackers());
return attackers.contains(this);
return AllZone.Combat.isAttacking(this);
}
public boolean isBlocking() {
CardList blockers = AllZone.Combat.getAllBlockers();
blockers.add(AllZone.pwCombat.getAllBlockers());
return blockers.contains(this);
}

View File

@@ -5802,9 +5802,6 @@ public class CardFactory_Creatures {
CardList list = new CardList(AllZone.Combat.getAttackers());
if(list.contains(c)) AllZone.Combat.removeFromCombat(c);
CardList pwlist = new CardList(AllZone.pwCombat.getAttackers());
if(pwlist.contains(c)) AllZone.pwCombat.removeFromCombat(c);
PlayerZone to = AllZone.getZone(Constant.Zone.Battlefield, c.getOwner());
to.add(c);

View File

@@ -2902,7 +2902,7 @@ class CardFactory_Planeswalkers {
{
public boolean addCard(Card crd)
{
return crd.isCreature() && CombatUtil.canAttack(crd);
return CombatUtil.canAttack(crd);
}
});

View File

@@ -13,31 +13,28 @@ public class Combat {
private HashMap<Card, Integer> defendingFirstStrikeDamageMap = new HashMap<Card, Integer>();
private HashMap<Card, Integer> defendingDamageMap = new HashMap<Card, Integer>();
// Defenders are the Defending Player + Each Planeswalker that player controls
private ArrayList<Object> defenders = new ArrayList<Object>();
private int currentDefender = 0;
private int nextDefender = 0;
// This Hash keeps track of
private HashMap<Card, Object> attackerToDefender = new HashMap<Card, Object>();
private int attackingDamage;
// private int defendingDamage;
// private int defendingFirstStrikeDamage;
// private int trampleDamage;
// private int trampleFirstStrikeDamage;
private Player attackingPlayer;
private Player defendingPlayer;
private int declaredAttackers;
private Card planeswalker;
private Player attackingPlayer = null;
private Player defendingPlayer = null;
private CardList attackersWithLure = new CardList();
private CardList canBlockAttackerWithLure = new CardList();
public Combat() {
reset();
// Let the Begin Turn/Untap Phase Reset Combat properly
}
public void reset() {
planeswalker = null;
map.clear();
resetAttackers();
blocked.clear();
unblockedMap.clear();
@@ -46,24 +43,70 @@ public class Combat {
defendingDamageMap.clear();
defendingFirstStrikeDamageMap.clear();
declaredAttackers = 0;
attackingPlayer = null;
defendingPlayer = null;
attackersWithLure = new CardList();
canBlockAttackerWithLure = new CardList();
attackersWithLure.clear();
canBlockAttackerWithLure.clear();
defenders.clear();
currentDefender = 0;
nextDefender = 0;
initiatePossibleDefenders(AllZone.Phase.getPlayerTurn().getOpponent());
}
public void setPlaneswalker(Card c) {
planeswalker = c;
public void initiatePossibleDefenders(Player defender){
defenders.add(defender);
CardList planeswalkers = AllZoneUtil.getPlayerCardsInPlay(defender);
planeswalkers = planeswalkers.getType("Planeswalker");
for(Card pw : planeswalkers)
defenders.add(pw);
}
public Card getPlaneswalker() {
return planeswalker;
public Object nextDefender(){
if (nextDefender >= defenders.size())
return null;
currentDefender = nextDefender;
nextDefender++;
return defenders.get(currentDefender);
}
public void setCurrentDefender(int def){
currentDefender = def;
}
public int getRemainingDefenders(){
return defenders.size() - nextDefender;
}
public ArrayList<Object> getDefenders(){
return defenders;
}
public void setDefenders(ArrayList<Object> newDef){
defenders = newDef;
}
public Card[] getDefendingPlaneswalkers(){
Card[] pwDefending = new Card[defenders.size()-1];
int i = 0;
for(Object o : defenders){
if (o instanceof Card){
pwDefending[i] = (Card)o;
i++;
}
}
return pwDefending;
}
public int getDeclaredAttackers() {
return declaredAttackers;
return attackerToDefender.size();
}
public void setAttackingPlayer(Player player) {
@@ -162,12 +205,9 @@ public class Combat {
damageDealt = att.get(i).getNetDefense();
if (damageDealt > 0) {
// if the creature has first strike do not do damage in the
// normal combat phase
// if(att.get(i).hasSecondStrike())
// if the creature has first strike do not do damage in the normal combat phase
if (!att.get(i).hasFirstStrike()
|| (att.get(i).hasFirstStrike() && att.get(i)
.hasDoubleStrike()))
|| (att.get(i).hasFirstStrike() && att.get(i).hasDoubleStrike()))
addDefendingDamage(damageDealt, att.get(i));
}
} // ! isBlocked...
@@ -185,8 +225,7 @@ public class Combat {
damageDealt = att.get(i).getNetDefense();
if (damageDealt > 0) {
// if the creature has first strike or double strike do
// damage in the first strike combat phase
// if the creature has first strike or double strike do damage in the first strike combat phase
if (att.get(i).hasFirstStrike()
|| att.get(i).hasDoubleStrike()) {
addDefendingFirstStrikeDamage(damageDealt, att.get(i));
@@ -197,6 +236,16 @@ public class Combat {
}
public void addDefendingDamage(int n, Card source) {
String slot = getDefenderByAttacker(source).toString();
Object o = defenders.get(Integer.parseInt(slot));
if (o instanceof Card){
Card pw = (Card)o;
pw.addAssignedDamage(n, source);
return;
}
if (!defendingDamageMap.containsKey(source))
defendingDamageMap.put(source, n);
else {
@@ -205,6 +254,16 @@ public class Combat {
}
public void addDefendingFirstStrikeDamage(int n, Card source) {
String slot = getDefenderByAttacker(source).toString();
Object o = defenders.get(Integer.parseInt(slot));
if (o instanceof Card){
Card pw = (Card)o;
pw.addAssignedDamage(n, source);
return;
}
if (!defendingFirstStrikeDamageMap.containsKey(source))
defendingFirstStrikeDamageMap.put(source, n);
else {
@@ -221,19 +280,41 @@ public class Combat {
return attackingDamage;
}
public CardList[] sortAttackerByDefender(){
CardList attackers[] = new CardList[defenders.size()];
for(int i = 0; i < attackers.length; i++)
attackers[i] = new CardList();
for(Card atk : attackerToDefender.keySet()){
Object o = attackerToDefender.get(atk);
int i = Integer.parseInt(o.toString());
attackers[i].add(atk);
}
return attackers;
}
public boolean isAttacking(Card c) {
return map.get(c) != null;
}
public void addAttacker(Card c) {
map.put(c, new CardList());
declaredAttackers++;
attackerToDefender.put(c, currentDefender);
}
public Object getDefenderByAttacker(Card c) {
return attackerToDefender.get(c);
}
public void resetAttackers() {
map.clear();
attackerToDefender.clear();
}
public Card[] getAttackers() {
CardList out = new CardList();
Iterator<Card> it = map.keySet().iterator();
// int i = 0; //unused
while (it.hasNext()) {
out.add((Card) it.next());
@@ -284,8 +365,10 @@ public class Combat {
public void removeFromCombat(Card c) {
// is card an attacker?
CardList att = new CardList(getAttackers());
if (att.contains(c))
if (att.contains(c)){
map.remove(c);
attackerToDefender.remove(c);
}
else// card is a blocker
{
for (int i = 0; i < att.size(); i++)
@@ -312,8 +395,6 @@ public class Combat {
CardList block;
CardList attacking = new CardList(getAttackers());
for (int i = 0; i < attacking.size(); i++) {
// if(attacking.get(i).hasFirstStrike() ||
// (attacking.get(i).hasDoubleStrike() )){
block = getBlockers(attacking.get(i));
// attacker always gets all blockers' attack
@@ -327,16 +408,12 @@ public class Combat {
}
}
if (block.size() == 0)// this damage is assigned to a player by
// setPlayerDamage()
{
// GameActionUtil.executePlayerCombatDamageEffects(attacking.get(i));
if (block.size() == 0){
// this damage is assigned to a player by setPlayerDamage()
addUnblockedAttacker(attacking.get(i));
}
else if (attacking.get(i).hasFirstStrike()
|| (attacking.get(i).hasDoubleStrike())) {
else if (attacking.get(i).hasFirstStrike() || (attacking.get(i).hasDoubleStrike())) {
if (block.size() == 1) {
if (attacking.get(i).hasFirstStrike()
|| attacking.get(i).hasDoubleStrike()) {
@@ -371,49 +448,20 @@ public class Combat {
addAssignedFirstStrikeDamage(attacking.get(i), block,
damageDealt);
}
} else// human
{
if (attacking.get(i).hasFirstStrike()
|| attacking.get(i).hasDoubleStrike()) {
// GuiDisplay2 gui = (GuiDisplay2) AllZone.Display;
}
else{
// human
if (attacking.get(i).hasFirstStrike() || attacking.get(i).hasDoubleStrike()) {
int damageDealt = attacking.get(i).getNetAttack();
if (CombatUtil.isDoranInPlay())
damageDealt = attacking.get(i).getNetDefense();
AllZone.Display.assignDamage(attacking.get(i), block,
damageDealt);
AllZone.Display.assignDamage(attacking.get(i), block, damageDealt);
/*
* for (Card b : block) {
* AllZone.Display.assignDamage(attacking.get(i), b,
* damageDealt);//System.out.println(
* "setAssignedFirstStrikeDmg called for:" + damageDealt
* + " damage."); }
* AllZone.Display.addAssignDamage(attacking
* .get(i),damageDealt);
*/
}
}
}// if(hasFirstStrike || doubleStrike)
}// for
// should first strike affect the following?
if (getPlaneswalker() != null) {
// System.out.println("defendingDmg (setAssignedFirstStrikeDamage) :"
// +defendingFirstStrikeDamage);
//
Iterator<Card> iter = defendingFirstStrikeDamageMap.keySet()
.iterator();
while (iter.hasNext()) {
Card crd = iter.next();
planeswalker.addAssignedDamage(defendingFirstStrikeDamageMap
.get(crd), crd);
}
defendingFirstStrikeDamageMap.clear();
}
}// setAssignedFirstStrikeDamage()
private void addAssignedFirstStrikeDamage(Card attacker, CardList block,
@@ -449,16 +497,9 @@ public class Combat {
CardList block;
CardList attacking = new CardList(getAttackers());
for (int i = 0; i < attacking.size(); i++) {
// if(!attacking.get(i).hasSecondStrike() ){
// if(!attacking.get(i).hasFirstStrike() ||
// (attacking.get(i).hasFirstStrike() &&
// attacking.get(i).hasDoubleStrike() )){
block = getBlockers(attacking.get(i));
// attacker always gets all blockers' attack
// attacking.get(i).setAssignedDamage(CardListUtil.sumAttack(block));
// AllZone.GameAction.setAssignedDamage(attacking.get(i), block,
// CardListUtil.sumAttack(block));
for (Card b : block) {
if (!b.hasFirstStrike()
@@ -470,17 +511,12 @@ public class Combat {
}
}
if (block.size() == 0)// this damage is assigned to a player by
// setPlayerDamage()
{
// GameActionUtil.executePlayerCombatDamageEffects(attacking.get(i));
if (block.size() == 0){
// this damage is assigned to a player by setPlayerDamage()
addUnblockedAttacker(attacking.get(i));
}
else if (!attacking.get(i).hasFirstStrike()
|| (attacking.get(i).hasFirstStrike() && attacking.get(i)
.hasDoubleStrike())) {
else if (!attacking.get(i).hasFirstStrike() || attacking.get(i).hasDoubleStrike()) {
if (block.size() == 1) {
int damageDealt = attacking.get(i).getNetAttack();
if (CombatUtil.isDoranInPlay())
@@ -503,70 +539,22 @@ public class Combat {
damageDealt = attacking.get(i).getNetDefense();
addAssignedDamage(attacking.get(i), block, damageDealt);
} else// human attacks
{
// GuiDisplay2 gui = (GuiDisplay2) AllZone.Display;
}
else{ // human attacks
int damageDealt = attacking.get(i).getNetAttack();
if (CombatUtil.isDoranInPlay())
damageDealt = attacking.get(i).getNetDefense();
AllZone.Display.assignDamage(attacking.get(i), block,
damageDealt);
AllZone.Display.assignDamage(attacking.get(i), block, damageDealt);
/*
*
*
* for (Card b :block)
* AllZone.Display.addAssignDamage(attacking.get(i), b,
* damageDealt);
* //System.out.println("setAssignedDmg called for:" +
* damageDealt + " damage.");
*/
}
}// if !hasFirstStrike ...
// hacky code, to ensure surviving non-first-strike blockers will
// hit first strike attackers:
/*
* else { block = getBlockers(attacking.get(i));
* //System.out.println("block size: " + block.size()); if(
* (attacking.get(i).hasFirstStrike() ||
* attacking.get(i).hasDoubleStrike()) ) { for(int j=0; j <
* block.size(); j++) { //blockerDamage +=
* block.get(j).getNetAttack(); int damage =
* block.get(j).getNetAttack(); if (CombatUtil.isDoranInPlay())
* damage = block.get(j).getNetDefense();
* AllZone.GameAction.addAssignedDamage(attacking.get(i),
* block.get(j), damage); }
* //attacking.get(i).setAssignedDamage(blockerDamage);
* //AllZone.GameAction.setAssignedDamage(attacking.get(i), block ,
* blockerDamage); } }
*/
}// for
// should first strike affect the following?
if (getPlaneswalker() != null) {
// System.out.println("defendingDmg (setAssignedDamage): " +
// defendingDamage);
Iterator<Card> iter = defendingDamageMap.keySet().iterator();
while (iter.hasNext()) {
Card crd = iter.next();
planeswalker
.addAssignedDamage(defendingDamageMap.get(crd), crd);
}
defendingDamageMap.clear();
}
}// assignDamage()
/*
* private void setAssignedDamage(Card attacker, CardList list, int damage)
* { CardListUtil.sortAttack(list); Card c; for(int i = 0; i < list.size();
* i++) { c = list.get(i); //if(!c.hasFirstStrike() || (c.hasFirstStrike()
* && c.hasDoubleStrike()) ){ if(c.getKillDamage() <= damage) { damage -=
* c.getKillDamage(); CardList cl = new CardList(); cl.add(attacker);
* AllZone.GameAction.addAssignedDamage(c, cl, c.getKillDamage());
* //c.setAssignedDamage(c.getKillDamage()); } //} }//for }//assignDamage()
*/
}// assignDamage()
private void addAssignedDamage(Card attacker, CardList block, int damage) {
Card c = attacker;
@@ -617,72 +605,21 @@ public class Combat {
}
}
/*
if (bFirstStrike){
CardList pwAttackers = new CardList(AllZone.pwCombat.getAttackers());
CardList pwBlockers = new CardList(AllZone.pwCombat.getAllBlockers().toArray());
for(int i = 0; i < pwAttackers.size(); i++) {
if((pwAttackers.getCard(i).hasFirstStrike() || pwAttackers.getCard(i).hasDoubleStrike())) {
CombatUtil.executeCombatDamageEffects(pwAttackers.getCard(i));
}
}
for(int i = 0; i < pwBlockers.size(); i++) {
if((pwBlockers.getCard(i).hasFirstStrike() || pwBlockers.getCard(i).hasDoubleStrike())) {
CombatUtil.executeCombatDamageEffects(pwBlockers.getCard(i));
}
}
}*/
//get all attackers and blockers
CardList check = new CardList();
check.addAll(AllZone.Human_Battlefield.getCards());
check.addAll(AllZone.Computer_Battlefield.getCards());
CardList all = check.getType("Creature");
if(AllZone.pwCombat.getPlaneswalker() != null) all.add(AllZone.pwCombat.getPlaneswalker());
CardList pwAttackers = new CardList(AllZone.pwCombat.getAttackers());
CardList pwBlockers = new CardList(AllZone.pwCombat.getAllBlockers().toArray());
if (!bFirstStrike){
/*
for(int i = 0; i < pwAttackers.size(); i++) {
//System.out.println("attacker #" + i + ": " + attackers.getCard(i).getName() +" " + attackers.getCard(i).getAttack());
if((!pwAttackers.getCard(i).hasFirstStrike() || (pwAttackers.getCard(i).hasFirstStrike() && pwAttackers.getCard(
i).hasDoubleStrike()))) {
CombatUtil.executeCombatDamageEffects(pwAttackers.getCard(i));
}
}
for(int i = 0; i < pwBlockers.size(); i++) {
if((!pwBlockers.getCard(i).hasFirstStrike() || (pwBlockers.getCard(i).hasFirstStrike() && pwBlockers.getCard(
i).hasDoubleStrike()))) {
CombatUtil.executeCombatDamageEffects(pwBlockers.getCard(i));
}
}
*/
//hacky stuff, hope it won't cause any bugs:
for(int i = 0; i < pwAttackers.size(); i++) {
AllZone.pwCombat.removeFromCombat(pwAttackers.get(i));
}
for(int i = 0; i < pwBlockers.size(); i++) {
AllZone.pwCombat.removeFromCombat(pwBlockers.get(i));
}
}
// this can be much better below here...
CardList combatants = new CardList();
combatants.addAll(AllZone.Combat.getAttackers());
combatants.add(AllZone.Combat.getAllBlockers());
combatants.addAll(AllZone.Combat.getDefendingPlaneswalkers());
Card c;
for(int i = 0; i < all.size(); i++) {
c = all.get(i);
//because this sets off Jackal Pup, and Filthly Cur damage ability
//and the stack says "Jack Pup causes 0 damage to the Computer"
if(c.getTotalAssignedDamage() != 0) {
for(int i = 0; i < combatants.size(); i++) {
c = combatants.get(i);
// if no assigned damage to resolve, move to next
if(c.getTotalAssignedDamage() == 0)
continue;
HashMap<Card, Integer> assignedDamageMap = c.getAssignedDamageHashMap();
HashMap<Card, Integer> damageMap = new HashMap<Card, Integer>();
@@ -697,7 +634,6 @@ public class Combat {
c.clearAssignedDamage();
}
}
}
public Card[] getUnblockedAttackers() {

View File

@@ -350,6 +350,7 @@ public class CombatUtil {
//can a creature attack att all?
public static boolean canAttack(Card c) {
if (!c.isCreature()) return false;
if(AllZoneUtil.isCardInPlay("Peacekeeper")) return false;
@@ -412,7 +413,7 @@ public class CombatUtil {
if(allislands.size() < 5) return false;
}
if(c.isTapped() || c.hasSickness()
if(c.isTapped() || c.isSick()
|| AllZoneUtil.isCardInPlay("Blazing Archon", c.getController().getOpponent())
|| c.getKeyword().contains("CARDNAME can't attack.")
|| c.getKeyword().contains("CARDNAME can't attack or block.")
@@ -459,7 +460,7 @@ public class CombatUtil {
return false;
}
}
//if Card has Haste, Card.hasSickness() will return false
return true;
}//canAttack()
@@ -522,10 +523,12 @@ public class CombatUtil {
//Checks if the life of the attacked Player/Planeswalker is in danger
public static boolean lifeInDanger(Combat combat) {
// life in danger only cares about the player's life. Not about a Planeswalkers life
int damage = 0;
int poison = 0;
CardList attackers = new CardList(combat.getAttackers());
CardList attackers = combat.sortAttackerByDefender()[0];
CardList unblocked = new CardList();
CardList blockers = new CardList();
Card attacker = new Card();
@@ -549,14 +552,7 @@ public class CombatUtil {
damage += sumAttack(unblocked, AllZone.ComputerPlayer);
poison += sumPoison(unblocked, AllZone.ComputerPlayer);
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;
return (damage + 3 > AllZone.ComputerPlayer.getLife() || poison + 2 > 10 - AllZone.ComputerPlayer.getPoisonCounters());
}
// This calculates the amount of damage a blockgang can deal to the attacker (first strike not supported)
@@ -816,104 +812,59 @@ public class CombatUtil {
}
public static void showCombat() {
//clear
AllZone.Display.showCombat("");
Card attack[] = AllZone.Combat.getAttackers();
Card defend[] = null;
StringBuilder display = new StringBuilder();
String attackerName = "";
String blockerName = "";
// Loop through Defenders
// Append Defending Player/Planeswalker
ArrayList<Object> defenders = AllZone.Combat.getDefenders();
CardList attackers[] = AllZone.Combat.sortAttackerByDefender();
// Not a big fan of the triple nested loop here
for(int def = 0; def < defenders.size(); def++){
if (attackers[def] == null || attackers[def].size() == 0)
continue;
if (def > 0)
display.append("\n");
display.append("Defender - ");
display.append(defenders.get(def).toString());
display.append("\n");
int len = attackers[def].size();
//loop through attackers
for(int i = 0; i < attack.length; i++) {
//GameActionUtil.executeExaltedEffects2(attack[i], AllZone.Combat);
//checkDeclareAttackers(attack[i]);
attackerName = attack[i].getName();
if(attack[i].isFaceDown()) attackerName = "Morph";
display.append(attackerName);
display.append(" (");
display.append(attack[i].getUniqueNumber());
display.append(") ");
display.append(attack[i].getNetAttack());
display.append("/");
display.append(attack[i].getNetDefense());
display.append(" is attacking \n");
for(int i = 0; i < len; i++) {
display.append("-> ");
display.append(combatantToString(attack[i])).append("\n");
defend = AllZone.Combat.getBlockers(attack[i]).toArray();
//loop through blockers
for(int inner = 0; inner < defend.length; inner++) {
//checkDeclareBlockers(defend[inner]);
blockerName = defend[inner].getName();
if(defend[inner].isFaceDown()) blockerName = "Morph";
display.append(" ");
display.append(blockerName);
display.append(" (");
display.append(defend[inner].getUniqueNumber());
display.append(") ");
display.append(defend[inner].getNetAttack());
display.append("/");
display.append(defend[inner].getNetDefense());
display.append(" is blocking \n");
display.append("---< ");
display.append(combatantToString(defend[inner])).append("\n");
}
}//while - loop through attackers
String s = display.toString() + getPlaneswalkerBlockers();
AllZone.Display.showCombat(s.trim());
}//loop through attackers
}
AllZone.Display.showCombat(display.toString().trim());
}//showBlockers()
private static String getPlaneswalkerBlockers() {
Card attack[] = AllZone.pwCombat.getAttackers();
Card defend[] = null;
StringBuilder display = new StringBuilder();
private static String combatantToString(Card c){
StringBuilder sb = new StringBuilder();
if(attack.length != 0) display.append("Planeswalker Combat\r\n");
String name = (c.isFaceDown()) ? "Morph" : c.getName();
String attackerName = "";
String blockerName = "";
//loop through attackers
for(int i = 0; i < attack.length; i++) {
//GameActionUtil.executeExaltedEffects2(attack[i], AllZone.pwCombat);
sb.append(name);
sb.append(" (").append(c.getUniqueNumber()).append(") ");
sb.append(c.getNetAttack()).append("/").append(c.getNetDefense());
//checkDeclareAttackers(attack[i]);
attackerName = attack[i].getName();
if(attack[i].isFaceDown()) attackerName = "Morph";
display.append(attackerName);
display.append(" (");
display.append(attack[i].getUniqueNumber());
display.append(") ");
display.append(attack[i].getNetAttack());
display.append("/");
display.append(attack[i].getNetDefense());
display.append(" is attacking \n");
defend = AllZone.pwCombat.getBlockers(attack[i]).toArray();
//loop through blockers
for(int inner = 0; inner < defend.length; inner++) {
//checkDeclareBlockers(defend[inner]);
blockerName = defend[inner].getName();
if(defend[inner].isFaceDown()) blockerName = "Morph";
display.append(" ");
display.append(blockerName);
display.append(" (");
display.append(defend[inner].getUniqueNumber());
display.append(") ");
display.append(defend[inner].getNetAttack());
display.append("/");
display.append(defend[inner].getNetDefense());
display.append(" is blocking \n");
return sb.toString();
}
}//while - loop through attackers
return display.toString();
}//getPlaneswalkerBlockers()
public static boolean isDoranInPlay() {
return AllZoneUtil.isCardInPlay("Doran, the Siege Tower");
@@ -921,14 +872,19 @@ public class CombatUtil {
public static boolean checkPropagandaEffects(Card c) {
String cost = CardFactoryUtil.getPropagandaCost(c);
if(cost.equals("0"))
if(cost.equals("0")){
if(!c.getKeyword().contains("Vigilance"))
c.tap();
return true;
}
final Card crd = c;
final boolean[] canAttack = new boolean[1];
canAttack[0] = false;
if( AllZone.Phase.getPhase().equals(Constant.Phase.Combat_Declare_Attackers)) {
String phase = AllZone.Phase.getPhase();
if(phase.equals(Constant.Phase.Combat_Declare_Attackers) || phase.equals(Constant.Phase.Combat_Declare_Attackers)) {
if(!cost.equals("0")) {
final Ability ability = new Ability(c, cost) {
@Override
@@ -943,8 +899,8 @@ public class CombatUtil {
public void execute() {
canAttack[0] = false;
// TODO: remove the below line after Propaganda occurs during Declare_Attackers
AllZone.Combat.removeFromCombat(crd);
crd.untap();
}
};
@@ -952,6 +908,9 @@ public class CombatUtil {
private static final long serialVersionUID = -8303368287601871955L;
public void execute() {
// if Propaganda is paid, tap this card
if(!crd.getKeyword().contains("Vigilance"))
crd.tap();
canAttack[0] = true;
}
};
@@ -959,13 +918,18 @@ public class CombatUtil {
if(c.getController().isHuman()) {
AllZone.InputControl.setInput(new Input_PayManaCost_Ability(c + " - Pay to Attack\r\n",
ability.getManaCost(), paidCommand, unpaidCommand));
} else //computer
{
if(ComputerUtil.canPayCost(ability)) ComputerUtil.playNoStack(ability);
}
else{ //computer
if(ComputerUtil.canPayCost(ability)){
ComputerUtil.playNoStack(ability);
if(!crd.getKeyword().contains("Vigilance"))
crd.tap();
}
else {
canAttack[0] = false;
// TODO: remove the below two lines after Propaganda occurs during Declare_Attackers
AllZone.Combat.removeFromCombat(crd);
crd.untap();
//crd.untap();
}
}
}
@@ -1105,7 +1069,7 @@ public class CombatUtil {
}
}//Raging Ravine
if ((AllZone.Combat.getAttackers().length + AllZone.pwCombat.getAttackers().length) == 1)
if (AllZone.Combat.getAttackers().length == 1)
{
if (c.getKeyword().contains("Whenever this creature attacks alone, it gets +2/+0 until end of turn.") ||
c.getKeyword().contains("Whenever CARDNAME attacks alone, it gets +2/+0 until end of turn."))
@@ -1568,13 +1532,9 @@ public class CombatUtil {
public void resolve() {
CardList list = new CardList();
list.addAll(AllZone.Combat.getAttackers());
list.addAll(AllZone.pwCombat.getAttackers());
list = list.filter(new CardListFilter() {
public boolean addCard(Card card) {
return (!card.equals(piledriver) && card.isCreature() && (card.getType().contains(
"Goblin") || card.getKeyword().contains("Changeling")));
}
});
list = list.getType("Goblin");
list.remove(piledriver);
final int otherGoblins = list.size();
final Command untilEOT = new Command() {

View File

@@ -183,25 +183,17 @@ public class ComputerAI_General implements Computer {
}
public void declare_attackers() {
final Combat c = ComputerUtil.getAttackers();
c.setAttackingPlayer(AllZone.Combat.getAttackingPlayer());
c.setDefendingPlayer(AllZone.Combat.getDefendingPlayer());
// 12/2/10(sol) the decision making here has moved to getAttackers()
//check for planeswalker
Card walker = AllZone.HumanPlayer.getPlaneswalker();
AllZone.Combat = ComputerUtil.getAttackers();
if(walker != null && MyRandom.random.nextBoolean()) {
c.setPlaneswalker(walker);
AllZone.pwCombat = c;
} else AllZone.Combat = c;
Card[] att = c.getAttackers();
Card[] att = AllZone.Combat.getAttackers();
if (att.length > 0)
AllZone.Phase.setCombat(true);
for(int i = 0; i < att.length; i++) {
if(!att[i].getKeyword().contains("Vigilance")) att[i].tap();
// tapping of attackers happens after Propaganda is paid for
//if(!att[i].getKeyword().contains("Vigilance")) att[i].tap();
Log.debug("Computer just assigned " + att[i].getName() + " as an attacker.");
}
@@ -219,23 +211,7 @@ public class ComputerAI_General implements Computer {
public void declare_blockers() {
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);
CardList remove = AllZone.pwCombat.getAllBlockers();
for(int i = 0; i < remove.size(); i++)
blockers.remove(remove.get(i));
AllZone.Combat = ComputerUtil_Block2.getBlockers(AllZone.Combat, blockers);
}
CombatUtil.showCombat();
@@ -246,26 +222,6 @@ public class ComputerAI_General implements Computer {
stackResponse();
}
/*
private Combat getCombat(Card[] attackers, CardList availableBlockers) {
ComputerUtil_Block2 com = new ComputerUtil_Block2(attackers, availableBlockers.toArray(),
AllZone.ComputerPlayer.getLife());
Combat c = com.getBlockers();
c.setAttackingPlayer(AllZone.Combat.getAttackingPlayer());
c.setDefendingPlayer(AllZone.Combat.getDefendingPlayer());
CardList attacks = new CardList(attackers);
Combat c = ComputerUtil_Block2.getBlockers(attacks,availableBlockers);
return c;
}
*/
public void end_of_combat(){
stackResponse();
}

View File

@@ -743,7 +743,7 @@ public class ComputerUtil
list = list.filter(new CardListFilter()
{
public boolean addCard(Card c) {
return c.isCreature() && CombatUtil.canAttack(c);
return CombatUtil.canAttack(c);
}
});
return list;

View File

@@ -32,6 +32,7 @@ public class ComputerUtil_Attack2 {
blockers = getPossibleBlockers(possibleBlockers);
this.blockerLife = blockerLife;
// todo: get rid of valuable
final ArrayList<String> valuable = new ArrayList<String>();
valuable.add("Kamahl, Pit Fighter");
valuable.add("Elvish Piper");
@@ -50,7 +51,7 @@ public class ComputerUtil_Attack2 {
CardList list = new CardList(in.toArray());
list = list.filter(new CardListFilter()
{
public boolean addCard(Card c) { return c.isCreature() && CombatUtil.canAttack(c); }
public boolean addCard(Card c) { return CombatUtil.canAttack(c); }
});
return list;
}//getUntappedCreatures()
@@ -159,6 +160,24 @@ public class ComputerUtil_Attack2 {
return blockerLife <= totalAttack;
}//doAssault()
public void chooseDefender(Combat c, boolean bAssault){
// TODO: split attackers to different planeswalker/human
// AI will only attack one Defender per combat for now
ArrayList<Object> defs = c.getDefenders();
if (defs.size() == 1 || bAssault){
c.setCurrentDefender(0);
return;
}
// Randomnly determine who EVERYONE is attacking
// would be better to determine more individually
int n = MyRandom.random.nextInt(defs.size());
c.setCurrentDefender(n);
return;
}
public Combat getAttackers()
{
//if this method is called multiple times during a turn,
@@ -169,11 +188,19 @@ public class ComputerUtil_Attack2 {
random.setSeed(AllZone.Phase.getTurn() + randomInt);
Combat combat = new Combat();
combat.setAttackingPlayer(AllZone.Combat.getAttackingPlayer());
combat.setDefendingPlayer(AllZone.Combat.getDefendingPlayer());
combat.setDefenders(AllZone.Combat.getDefenders());
boolean bAssault = doAssault();
// Determine who will be attacked
chooseDefender(combat, bAssault);
CardList attackersLeft = new CardList(attackers.toArray());
//Atackers that don't really have a choice
for (int i=0; i<attackersLeft.size();i++)
for (int i=0; i < attackersLeft.size(); i++)
{
Card attacker = attackersLeft.get(i);
if ( (attacker.getKeyword().contains("CARDNAME attacks each turn if able.")
@@ -192,8 +219,9 @@ public class ComputerUtil_Attack2 {
if (combat.getAttackers().length == 0 && (countExaltedBonus(AllZone.ComputerPlayer) >= 3 ||
AllZoneUtil.isCardInPlay("Rafiq of the Many", AllZone.ComputerPlayer) ||
AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer, "Battlegrace Angel").size() >= 2 ||
(AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer, "Finest Hour").size()>=1) && AllZone.Phase.isFirstCombat())
&& !doAssault())
(AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer, "Finest Hour").size()>=1) &&
AllZone.Phase.isFirstCombat())
&& !bAssault)
{
int biggest = 0;
Card att = null;
@@ -209,7 +237,7 @@ public class ComputerUtil_Attack2 {
//do assault (all creatures attack) if the computer would win the game
//or if the computer has 4 creatures and the player has 1
else if(doAssault() || (humanList.size() == 1 && 3 < attackers.size()))
else if(bAssault || (humanList.size() == 1 && 3 < attackers.size()))
{
CardListUtil.sortAttack(attackersLeft);
for(int i = 0; i < attackersLeft.size(); i++)
@@ -254,32 +282,11 @@ public class ComputerUtil_Attack2 {
}
}//getAttackers()
return combat;
}//getAttackers()
/*
//returns null if no blockers found
public Card getBiggestAttack(Card attack)
{
CardListUtil.sortAttack(blockers);
for(int i = 0; i < blockers.size(); i++)
if(CombatUtil.canBlock(attack, blockers.get(i)))
return blockers.get(i);
return null;
}
//returns null if no blockers found
public Card getBiggestDefense(Card attack)
{
CardListUtil.sortDefense(blockers);
for(int i = 0; i < blockers.size(); i++)
if(CombatUtil.canBlock(attack, blockers.get(i)))
return blockers.get(i);
return null;
}*/
public int countExaltedBonus(Player player)
{
PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, player);
@@ -349,8 +356,6 @@ public class ComputerUtil_Attack2 {
else if(CombatUtil.canBlock(c)) plannedBlockers.add(c);
}
return combat;
}
}

View File

@@ -1,6 +1,8 @@
package forge;
import java.util.ArrayList;
public class ComputerUtil_Block2
{
@@ -508,11 +510,46 @@ public class ComputerUtil_Block2
return blockers;
}
public static CardList sortPotentialAttackers(Combat combat){
CardList[] attackerLists = combat.sortAttackerByDefender();
CardList sortedAttackers = new CardList();
ArrayList<Object> defenders = combat.getDefenders();
// If I don't have any planeswalkers than sorting doesn't really matter
if (defenders.size() == 1)
return attackerLists[0];
boolean bLifeInDanger = CombatUtil.lifeInDanger(combat);
// todo: Add creatures attacking Planeswalkers in order of which we want to protect
// defend planeswalkers with more loyalty before planeswalkers with less loyalty
// if planeswalker will be too difficult to defend don't even bother
for(int i = 1; i < attackerLists.length; i++){
for(Card c : attackerLists[i])
sortedAttackers.add(c);
}
if(bLifeInDanger) {
// add creatures attacking the Player to the front of the list
for(Card c : attackerLists[0])
sortedAttackers.add(0, c);
}
else{
// add creatures attacking the Player to the back of the list
for(Card c : attackerLists[0])
sortedAttackers.add(c);
}
return sortedAttackers;
}
public static Combat getBlockers(Combat originalCombat, CardList possibleBlockers) {
Combat combat = originalCombat;
CardList attackers = new CardList(combat.getAttackers());
CardList attackers = sortPotentialAttackers(combat);
if (attackers.size() == 0)
return combat;
@@ -564,8 +601,10 @@ public class ComputerUtil_Block2
if(!CombatUtil.canBlock(b, combat)) blockersLeft.remove(b);
}
boolean bLifeInDanger = CombatUtil.lifeInDanger(combat);
//These creatures won't prevent any damage
if (CombatUtil.lifeInDanger(combat))
if (bLifeInDanger)
blockersLeft = blockersLeft.getNotKeyword("Whenever CARDNAME is dealt damage, you lose that much life.");
if (blockersLeft.size() == 0)
@@ -624,7 +663,7 @@ public class ComputerUtil_Block2
if(blockersLeft.size() == 0) return combat;
//choose necessary trade blocks if life is in danger
if (CombatUtil.lifeInDanger(combat))
if (bLifeInDanger)
for(int i = 0; i < attackersLeft.size(); i++) {
attacker = attackersLeft.get(i);
killingBlockers =
@@ -640,7 +679,7 @@ public class ComputerUtil_Block2
attackersLeft = new CardList(currentAttackers.toArray());
//choose necessary chump blocks if life is still in danger
if (CombatUtil.lifeInDanger(combat))
if (bLifeInDanger)
for(int i = 0; i < attackersLeft.size(); i++) {
attacker = attackersLeft.get(i);
chumpBlockers = getPossibleBlockers(attacker, blockersLeft, combat);
@@ -656,7 +695,7 @@ public class ComputerUtil_Block2
attackersLeft = new CardList(currentAttackers.toArray());
//Reinforce blockers blocking attackers with trample if life is still in danger
if (CombatUtil.lifeInDanger(combat)) {
if (bLifeInDanger) {
tramplingAttackers = attackers.getKeyword("Trample");
tramplingAttackers = tramplingAttackers.getKeywordsDontContain("Rampage"); //Don't make it worse
tramplingAttackers = tramplingAttackers.

View File

@@ -98,6 +98,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
// Special Inputs needed for the following phases:
if(phase.equals(Constant.Phase.Combat_Declare_Attackers)) {
AllZone.Stack.freezeStack();
if (playerTurn.isHuman())
return new Input_Attack();
}
@@ -109,11 +110,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
return null;
}
else{
// test this. probably should just call Input_Block and let block pass along?
if(AllZone.Combat.getAttackers().length == 0){
if (AllZone.pwCombat.getAttackers().length != 0)
return new Input_Block_Planeswalker();
// no active attackers, skip the Blocking phase
AllZone.Phase.setNeedToNextPhase(true);
return null;

View File

@@ -7,20 +7,31 @@ public class Input_Attack extends Input {
@Override
public void showMessage() {
// TODO: still seems to have some issues with multiple planeswalkers
ButtonUtil.enableOnlyOK();
AllZone.Display.showMessage("Declare Attackers: Select creatures that you want to attack with");
PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, AllZone.HumanPlayer);
CardList creats = new CardList(play.getCards());
creats = creats.getType("Creature");
Object o = AllZone.Combat.nextDefender();
if (o == null){
return;
}
if(getPlaneswalker() == null) {
for(int i = 0; i < creats.size(); i++) {
Card c = creats.get(i);
if(CombatUtil.canAttack(c) && c.getKeyword().contains("CARDNAME attacks each turn if able.")) {
StringBuilder sb = new StringBuilder();
sb.append("Declare Attackers: Select Creatures to Attack ");
sb.append(o.toString());
AllZone.Display.showMessage(sb.toString());
if(AllZone.Combat.getRemainingDefenders() == 0) {
// Nothing left to attack, has to attack this defender
CardList possibleAttackers = AllZoneUtil.getPlayerCardsInPlay(AllZone.HumanPlayer);
possibleAttackers = possibleAttackers.getType("Creature");
for(int i = 0; i < possibleAttackers.size(); i++) {
Card c = possibleAttackers.get(i);
if(c.getKeyword().contains("CARDNAME attacks each turn if able.") && CombatUtil.canAttack(c) && !c.isAttacking()) {
AllZone.Combat.addAttacker(c);
if(!c.getKeyword().contains("Vigilance")) c.tap();
//if(!c.getKeyword().contains("Vigilance"))
// c.tap();
}
}
}
@@ -31,37 +42,23 @@ public class Input_Attack extends Input {
if (AllZone.Combat.getAttackers().length > 0)
AllZone.Phase.setCombat(true);
Card check = getPlaneswalker();
if(check == null) {
if (AllZone.Combat.getRemainingDefenders() != 0)
AllZone.Phase.repeatPhase();
AllZone.Phase.setNeedToNextPhase(true);
} else {
AllZone.pwCombat.setPlaneswalker(check);
AllZone.InputControl.setInput(new Input_Attack_Planeswalker());
}
}
//return Computer's planeswalker if there is one
//just returns 1, does not return multiple planeswalkers
private Card getPlaneswalker() {
CardList c = new CardList(AllZone.Computer_Battlefield.getCards());
c = c.getType("Planeswalker");
if(c.isEmpty()) return null;
return c.get(0);
AllZone.InputControl.resetInput();
}
@Override
public void selectCard(Card card, PlayerZone zone) {
if(zone.is(Constant.Zone.Battlefield, AllZone.HumanPlayer) && card.isCreature() && card.isUntapped()
&& CombatUtil.canAttack(card)) {
if(zone.is(Constant.Zone.Battlefield, AllZone.HumanPlayer) && CombatUtil.canAttack(card) && !card.isAttacking()) {
// todo add the propaganda code here and remove it in Phase.nextPhase()
// if (!CombatUtil.checkPropagandaEffects(card))
// return;
if(!card.getKeyword().contains("Vigilance")) {
card.tap();
//otherwise cards stay untapped, not sure why this is needed but it works
AllZone.Human_Battlefield.updateObservers();
}
AllZone.Combat.addAttacker(card);
AllZone.Human_Battlefield.updateObservers(); // just to make sure the attack symbol is marked
//for Castle Raptors, since it gets a bonus if untapped
for(String effect:AllZone.StaticEffects.getStateBasedMap().keySet()) {

View File

@@ -1,60 +0,0 @@
package forge;
public class Input_Attack_Planeswalker extends Input {
private static final long serialVersionUID = 5738375759147611797L;
@Override
public void showMessage() {
ButtonUtil.enableOnlyOK();
AllZone.Display.showMessage("Planeswalker Declare Attackers:\r\nSelect creatures that you want to attack "
+ AllZone.pwCombat.getPlaneswalker());
PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, AllZone.HumanPlayer);
CardList creats = new CardList(play.getCards());
creats = creats.getType("Creature");
CardList attackers = new CardList(AllZone.Combat.getAttackers());
for(int i = 0; i < creats.size(); i++) {
Card c = creats.get(i);
if(CombatUtil.canAttack(c) && c.getKeyword().contains("CARDNAME attacks each turn if able.")
&& !attackers.contains(c)) {
AllZone.pwCombat.addAttacker(c);
if(!c.getKeyword().contains("Vigilance")) c.tap();
}
}
}
@Override
public void selectButtonOK() {
if (AllZone.pwCombat.getAttackers().length > 0)
AllZone.Phase.setCombat(true);
AllZone.Phase.setNeedToNextPhase(true);
this.stop();
}
@Override
public void selectCard(Card card, PlayerZone zone) {
if(zone.is(Constant.Zone.Battlefield, AllZone.HumanPlayer) && card.isCreature() && card.isUntapped()
&& CombatUtil.canAttack(card)) {
if(!card.getKeyword().contains("Vigilance")) {
card.tap();
//otherwise cards stay untapped, not sure why this is needed but it works
AllZone.Human_Battlefield.updateObservers();
}
AllZone.pwCombat.addAttacker(card);
//for Castle Raptors, since it gets a bonus if untapped
for(String effect:AllZone.StaticEffects.getStateBasedMap().keySet()) {
Command com = GameActionUtil.commands.get(effect);
com.execute();
}
GameActionUtil.executeCardStateEffects();
CombatUtil.showCombat();
}
}//selectCard()
}

View File

@@ -52,15 +52,10 @@ public class Input_Block extends Input {
@Override
public void selectButtonOK() {
// Done blocking
ButtonUtil.reset();
if(AllZone.pwCombat.getAttackers().length == 0) {
//AllZone.Phase.nextPhase();
//for debugging: System.out.println("need to nextPhase(Input_Cleanup.showMessage(), n<=7) = true");
AllZone.Phase.setNeedToNextPhase(true);
} else {
AllZone.InputControl.setInput(new Input_Block_Planeswalker());
}
}
@Override

View File

@@ -1,78 +0,0 @@
package forge;
import java.util.ArrayList;
public class Input_Block_Planeswalker extends Input {
private static final long serialVersionUID = 8504632360578751473L;
private Card currentAttacker = null;
private ArrayList<Card> allBlocking = new ArrayList<Card>();
@Override
public void showMessage() {
//for Castle Raptors, since it gets a bonus if untapped
for(String effect:AllZone.StaticEffects.getStateBasedMap().keySet()) {
Command com = GameActionUtil.commands.get(effect);
com.execute();
}
GameActionUtil.executeCardStateEffects();
//could add "Reset Blockers" button
ButtonUtil.enableOnlyOK();
if(currentAttacker == null) {
//Lure
CardList attackers = new CardList(AllZone.Combat.getAttackers());
for(Card attacker:attackers) {
if(attacker.hasKeyword("All creatures able to block CARDNAME do so.")) {
CardList bls = AllZoneUtil.getCreaturesInPlay(AllZone.HumanPlayer);
for(Card bl:bls) {
if(CombatUtil.canBlock(attacker, bl, AllZone.Combat)) {
allBlocking.add(bl);
AllZone.Combat.addBlocker(attacker, bl);
}
}
}
}
AllZone.Display.showMessage("Planeswalker Combat\r\nTo Block, click on your Opponents attacker first , then your blocker(s)");
}
else {
String attackerName = currentAttacker.isFaceDown() ? "Morph" : currentAttacker.getName();
AllZone.Display.showMessage("Select a creature to block " + attackerName + " ("
+ currentAttacker.getUniqueNumber() + ") ");
}
CombatUtil.showCombat();
}
@Override
public void selectButtonOK() {
if (AllZone.Combat.getAttackers().length > 0)
AllZone.Phase.setCombat(true);
ButtonUtil.reset();
//AllZone.Phase.nextPhase();
//for debugging: System.out.println("need to nextPhase(Input_Block_Planeswalker.selectButtonOK) = true; Note, this has not been tested, did it work?");
AllZone.Phase.setNeedToNextPhase(true);
this.stop();
}
@Override
public void selectCard(Card card, PlayerZone zone) {
//is attacking?
if(CardUtil.toList(AllZone.pwCombat.getAttackers()).contains(card)) {
currentAttacker = card;
} else if(zone.is(Constant.Zone.Battlefield, AllZone.HumanPlayer) && card.isCreature()
&& CombatUtil.canBlock(currentAttacker, card, AllZone.Combat)) {
if(currentAttacker != null && (!allBlocking.contains(card))) {
allBlocking.add(card);
AllZone.pwCombat.addBlocker(currentAttacker, card);
}
}
showMessage();
}//selectCard()
}

View File

@@ -191,8 +191,7 @@ public class Phase extends MyObservable
else if(phase.equals(Constant.Phase.Combat_Begin)){
if (AllZone.Display.stopAtPhase(turn, phase)){
AllZone.Combat.verifyCreaturesInPlay();
CombatUtil.showCombat();
PhaseUtil.verifyCombat();
}
else {
this.setNeedToNextPhase(true);
@@ -201,8 +200,7 @@ public class Phase extends MyObservable
else if (phase.equals(Constant.Phase.Combat_Declare_Attackers_InstantAbility)){
if(inCombat()) {
AllZone.Combat.verifyCreaturesInPlay();
CombatUtil.showCombat();
PhaseUtil.handleDeclareAttackers();
}
else
AllZone.Phase.setNeedToNextPhase(true);
@@ -211,8 +209,7 @@ public class Phase extends MyObservable
// we can skip AfterBlockers and AfterAttackers if necessary
else if(phase.equals(Constant.Phase.Combat_Declare_Blockers)){
if(inCombat()) {
AllZone.Combat.verifyCreaturesInPlay();
CombatUtil.showCombat();
PhaseUtil.verifyCombat();
}
else
AllZone.Phase.setNeedToNextPhase(true);
@@ -223,40 +220,7 @@ public class Phase extends MyObservable
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();
PhaseUtil.handleDeclareBlockers();
}
}
@@ -265,10 +229,8 @@ public class Phase extends MyObservable
AllZone.Phase.setNeedToNextPhase(true);
else{
AllZone.Combat.verifyCreaturesInPlay();
AllZone.pwCombat.verifyCreaturesInPlay();
AllZone.Combat.setAssignedFirstStrikeDamage();
AllZone.pwCombat.setAssignedFirstStrikeDamage();
if (!AllZone.GameInfo.isPreventCombatDamageThisTurn())
Combat.dealAssignedDamage();
@@ -283,10 +245,8 @@ public class Phase extends MyObservable
AllZone.Phase.setNeedToNextPhase(true);
else{
AllZone.Combat.verifyCreaturesInPlay();
AllZone.pwCombat.verifyCreaturesInPlay();
AllZone.Combat.setAssignedDamage();
AllZone.pwCombat.setAssignedDamage();
if (!AllZone.GameInfo.isPreventCombatDamageThisTurn())
Combat.dealAssignedDamage();
@@ -350,33 +310,6 @@ public class Phase extends MyObservable
if (getPhase().equals(Constant.Phase.Combat_Declare_Attackers)) {
AllZone.Stack.unfreezeStack();
nCombatsThisTurn++;
CardList list = new CardList();
list.addAll(AllZone.Combat.getAttackers());
// Remove illegal Propaganda attacks first only for attacking the Player
for(Card c:list)
CombatUtil.checkPropagandaEffects(c);
list.addAll(AllZone.pwCombat.getAttackers());
// Then run other Attacker bonuses
//check for exalted:
if (list.size() == 1){
AllZone.GameAction.checkWheneverKeyword(list.get(0), "Attack - Alone", null);
Player attackingPlayer = AllZone.Combat.getAttackingPlayer();
PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, attackingPlayer);
CardList exalted = new CardList(play.getCards());
exalted = exalted.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.getKeyword().contains("Exalted");
}
});
if(exalted.size() > 0) CombatUtil.executeExaltedAbility(list.get(0), exalted.size());
// Make sure exalted effects get applied only once per combat
}
for(Card c:list)
CombatUtil.checkDeclareAttackers(c);
}
else if (getPhase().equals(Constant.Phase.Untap)) {
nCombatsThisTurn = 0;
@@ -384,7 +317,6 @@ public class Phase extends MyObservable
if (getPhase().equals(Constant.Phase.Combat_End)) {
AllZone.Combat.reset();
AllZone.pwCombat.reset();
AllZone.Display.showCombat("");
resetAttackedThisCombat(getPlayerTurn());
this.bCombat = false;
@@ -410,9 +342,6 @@ public class Phase extends MyObservable
AllZone.Combat.reset();
AllZone.Combat.setAttackingPlayer(player);
AllZone.Combat.setDefendingPlayer(opp);
AllZone.pwCombat.reset();
AllZone.Combat.setAttackingPlayer(player);
AllZone.Combat.setDefendingPlayer(opp);
phaseIndex = findIndex(Constant.Phase.Combat_Declare_Attackers);
}
else {

View File

@@ -30,10 +30,6 @@ public class PhaseUtil {
AllZone.Combat.setAttackingPlayer(turn);
AllZone.Combat.setDefendingPlayer(turn.getOpponent());
AllZone.pwCombat.reset();
AllZone.pwCombat.setAttackingPlayer(turn);
AllZone.pwCombat.setDefendingPlayer(turn.getOpponent());
// For tokens a player starts the game with they don't recover from Sum. Sickness on first turn
if (turn.getTurn() > 0){
for(int i = 0; i < c.length; i++)
@@ -349,6 +345,77 @@ public class PhaseUtil {
return false;
}
// ********* Declare Attackers ***********
public static void verifyCombat(){
AllZone.Combat.verifyCreaturesInPlay();
CombatUtil.showCombat();
}
public static void handleDeclareAttackers(){
verifyCombat();
CardList list = new CardList();
list.addAll(AllZone.Combat.getAttackers());
// TODO move propaganda to happen as the Attacker is Declared
// Remove illegal Propaganda attacks first only for attacking the Player
for(Card c:list)
CombatUtil.checkPropagandaEffects(c);
AllZone.Stack.freezeStack();
// Then run other Attacker bonuses
//check for exalted:
if (list.size() == 1){
AllZone.GameAction.checkWheneverKeyword(list.get(0), "Attack - Alone", null);
Player attackingPlayer = AllZone.Combat.getAttackingPlayer();
PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, attackingPlayer);
CardList exalted = new CardList(play.getCards());
exalted = exalted.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.getKeyword().contains("Exalted");
}
});
if(exalted.size() > 0) CombatUtil.executeExaltedAbility(list.get(0), exalted.size());
// Make sure exalted effects get applied only once per combat
}
for(Card c:list)
CombatUtil.checkDeclareAttackers(c);
AllZone.Stack.unfreezeStack();
}
public static void handleDeclareBlockers(){
verifyCombat();
AllZone.Stack.freezeStack();
CardList list = new CardList();
list.addAll(AllZone.Combat.getAllBlockers().toArray());
list = list.filter(new CardListFilter(){
public boolean addCard(Card c)
{
return !c.getCreatureBlockedThisCombat();
}
});
CardList attList = new CardList();
attList.addAll(AllZone.Combat.getAttackers());
CombatUtil.checkDeclareBlockers(list);
for (Card a:attList){
CardList blockList = AllZone.Combat.getBlockers(a);
for (Card b:blockList)
CombatUtil.checkBlockedAttackers(a, b);
}
AllZone.Stack.unfreezeStack();
CombatUtil.showCombat();
}
// ***** Combat Utility **********
// todo: the below functions should be removed and the code blocks that use them should instead use SA_Restriction
public static boolean isBeforeAttackersAreDeclared() {
String phase = AllZone.Phase.getPhase();
return phase.equals(Constant.Phase.Untap) || phase.equals(Constant.Phase.Upkeep)