- Human may now declare attacks in a band

- Added Benalish Hero
This commit is contained in:
Sol
2013-06-14 15:19:21 +00:00
parent 8eedf4b3f1
commit 5f508e5d17
5 changed files with 119 additions and 20 deletions

1
.gitattributes vendored
View File

@@ -912,6 +912,7 @@ res/cardsfolder/b/benalish_cavalry.txt svneol=native#text/plain
res/cardsfolder/b/benalish_commander.txt -text res/cardsfolder/b/benalish_commander.txt -text
res/cardsfolder/b/benalish_emissary.txt svneol=native#text/plain res/cardsfolder/b/benalish_emissary.txt svneol=native#text/plain
res/cardsfolder/b/benalish_heralds.txt svneol=native#text/plain res/cardsfolder/b/benalish_heralds.txt svneol=native#text/plain
res/cardsfolder/b/benalish_hero.txt -text
res/cardsfolder/b/benalish_knight.txt svneol=native#text/plain res/cardsfolder/b/benalish_knight.txt svneol=native#text/plain
res/cardsfolder/b/benalish_lancer.txt -text res/cardsfolder/b/benalish_lancer.txt -text
res/cardsfolder/b/benalish_missionary.txt svneol=native#text/plain res/cardsfolder/b/benalish_missionary.txt svneol=native#text/plain

View File

@@ -0,0 +1,7 @@
Name:Benalish Hero
ManaCost:W
Types:Creature Human Soldier
PT:1/1
K:Banding
SVar:Picture:http://www.wizards.com/global/images/magic/general/benalish_hero.jpg
Oracle:Banding (Any creatures with banding, and up to one without, can attack in a band. Bands are blocked as a group. If any creatures with banding you control are blocking or being blocked by a creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.)

View File

@@ -207,6 +207,16 @@ public class Combat {
return defenderMap.get(defender); return defenderMap.get(defender);
} }
public final List<AttackingBand> getAttackingBandsOf(GameEntity defender) {
List<AttackingBand> bands = new ArrayList<AttackingBand>();
for(AttackingBand band : this.attackingBands) {
if (band.getDefender().equals(defender)) {
bands.add(band);
}
}
return bands;
}
/** /**
* <p> * <p>
* isAttacking. * isAttacking.
@@ -503,11 +513,17 @@ public class Combat {
this.blockerToBandsMap.get(b).remove(c); this.blockerToBandsMap.get(b).remove(c);
} }
// Clear removed attacker from assignment order // Clear removed attacker from assignment order
if (this.blockerDamageAssignmentOrder.containsKey(b)) {
this.blockerDamageAssignmentOrder.get(b).remove(c); this.blockerDamageAssignmentOrder.get(b).remove(c);
} }
}
this.defenderMap.get(band.getDefender()).remove(c); this.defenderMap.get(band.getDefender()).remove(c);
} else if (this.blockerDamageAssignmentOrder.containsKey(c)) { // card is a blocker
if (band.getAttackers().isEmpty() && band.getBlockers().isEmpty()) {
this.getAttackingBands().remove(band);
}
} else if (this.blockerToBandsMap.containsKey(c)) { // card is a blocker
List<AttackingBand> attackers = this.blockerToBandsMap.get(c); List<AttackingBand> attackers = this.blockerToBandsMap.get(c);
this.blockerToBandsMap.remove(c); this.blockerToBandsMap.remove(c);
@@ -515,10 +531,12 @@ public class Combat {
for (AttackingBand a : attackers) { for (AttackingBand a : attackers) {
a.removeBlocker(c); a.removeBlocker(c);
for(Card atk : a.getAttackers()) { for(Card atk : a.getAttackers()) {
if (this.attackerDamageAssignmentOrder.containsKey(atk)) {
this.attackerDamageAssignmentOrder.get(atk).remove(c); this.attackerDamageAssignmentOrder.get(atk).remove(c);
} }
} }
} }
}
} // removeFromCombat() } // removeFromCombat()
/** /**

View File

@@ -26,6 +26,7 @@ import com.google.common.collect.Iterables;
import forge.Card; import forge.Card;
import forge.CardPredicates; import forge.CardPredicates;
import forge.GameEntity; import forge.GameEntity;
import forge.game.combat.AttackingBand;
import forge.game.phase.Combat; import forge.game.phase.Combat;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.player.Player; import forge.game.player.Player;
@@ -52,6 +53,7 @@ public class InputAttack extends InputSyncronizedBase {
private GameEntity currentDefender; private GameEntity currentDefender;
private final Player playerAttacks; private final Player playerAttacks;
private final Player playerDeclares; private final Player playerDeclares;
private AttackingBand activeBand = null;
public InputAttack(Player attacks, Player declares, Combat combat) { public InputAttack(Player attacks, Player declares, Combat combat) {
this.playerAttacks = attacks; this.playerAttacks = attacks;
@@ -97,8 +99,10 @@ public class InputAttack extends InputSyncronizedBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
protected final void onOk() { protected final void onOk() {
// TODO Add check to see if each must attack creature is attacking
// Propaganda costs could have been paid here. // Propaganda costs could have been paid here.
setCurrentDefender(null); // remove highlights setCurrentDefender(null); // remove highlights
activateBand(null);
stop(); stop();
} }
@@ -115,12 +119,33 @@ public class InputAttack extends InputSyncronizedBase {
protected final void onCardSelected(final Card card, boolean isMetaDown) { protected final void onCardSelected(final Card card, boolean isMetaDown) {
final List<Card> att = combat.getAttackers(); final List<Card> att = combat.getAttackers();
if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) { if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) {
// TODO Is there no way to attacks each turn cards to attack Planeswalkers?
combat.removeFromCombat(card); combat.removeFromCombat(card);
card.setUsedToPay(false);
showCombat(); showCombat();
// When removing an attacker should I clear the attacking band?
this.activateBand(this.activeBand);
return; return;
} }
if (card.isAttacking(currentDefender)) { if (card.isAttacking(currentDefender)) {
// Activate band by selecting/deselecting a band member
if (this.activeBand == null) {
this.activateBand(combat.getBandByAttacker(card));
} else if (this.activeBand.getAttackers().contains(card)) {
this.activateBand(null);
} else { // Join a band by selecting a non-active band member after activating a band
if (this.activeBand.canJoinBand(card)) {
combat.removeFromCombat(card);
combat.addAttacker(card, currentDefender, this.activeBand);
this.activateBand(this.activeBand);
updateMessage();
} else {
flashIncorrectAction();
}
}
updateMessage();
return; return;
} }
@@ -132,10 +157,20 @@ public class InputAttack extends InputSyncronizedBase {
} }
if (playerAttacks.getZone(ZoneType.Battlefield).contains(card) && CombatUtil.canAttack(card, currentDefender, combat)) { if (playerAttacks.getZone(ZoneType.Battlefield).contains(card) && CombatUtil.canAttack(card, currentDefender, combat)) {
if( combat.isAttacking(card)) { if (this.activeBand != null && !this.activeBand.canJoinBand(card)) {
this.activateBand(null);
updateMessage();
flashIncorrectAction();
return;
}
if(combat.isAttacking(card)) {
combat.removeFromCombat(card); combat.removeFromCombat(card);
} }
combat.addAttacker(card, currentDefender);
combat.addAttacker(card, currentDefender, this.activeBand);
this.activateBand(this.activeBand);
updateMessage();
showCombat(); showCombat();
} }
else { else {
@@ -157,13 +192,45 @@ public class InputAttack extends InputSyncronizedBase {
} }
} }
String header = playerAttacks == playerDeclares ? "declare attackers." : "declare attackers for " + playerAttacks.getName(); updateMessage();
showMessage(playerDeclares.getName() + ", " + header + "\nSelecting Creatures to Attack " + currentDefender +
"\n\nTo attack other players or their planewalkers just click on them");
// This will instantly highlight targets // This will instantly highlight targets
for(MyObservable updateable : toUpdate) { for(MyObservable updateable : toUpdate) {
updateable.updateObservers(); updateable.updateObservers();
} }
} }
private final void activateBand(AttackingBand band) {
Set<MyObservable> toUpdate = new HashSet<MyObservable>();
if (this.activeBand != null) {
for(Card card : this.activeBand.getAttackers()) {
card.setUsedToPay(false);
toUpdate.add(card.getController().getZone(ZoneType.Battlefield));
}
}
this.activeBand = band;
if (this.activeBand != null) {
for(Card card : this.activeBand.getAttackers()) {
card.setUsedToPay(true);
toUpdate.add(card.getController().getZone(ZoneType.Battlefield));
}
}
// This will instantly highlight targets
for(MyObservable updateable : toUpdate) {
updateable.updateObservers();
}
}
private void updateMessage() {
StringBuilder sb = new StringBuilder();
sb.append(playerDeclares.getName()).append(", ");
sb.append(playerAttacks == playerDeclares ? "declare attackers." : "declare attackers for " + playerAttacks.getName()).append("\n");
sb.append("Selecting Creatures to Attack ").append(currentDefender).append("\n\n");
sb.append("To change the current defender, click on the player or planeswalker you wish to attack.\n");
sb.append("To attack as a band, click an attacking creature to activate its 'band', select another to join the band.");
showMessage(sb.toString());
}
} }

View File

@@ -6,6 +6,7 @@ import forge.Card;
import forge.Command; import forge.Command;
import forge.GameEntity; import forge.GameEntity;
import forge.game.Game; import forge.game.Game;
import forge.game.combat.AttackingBand;
import forge.game.phase.Combat; import forge.game.phase.Combat;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -70,8 +71,8 @@ public enum CCombat implements ICDoc {
// Not a big fan of the triple nested loop here // Not a big fan of the triple nested loop here
for (GameEntity defender : combat.getDefenders()) { for (GameEntity defender : combat.getDefenders()) {
List<Card> atk = combat.getAttackersOf(defender); List<AttackingBand> bands = combat.getAttackingBandsOf(defender);
if (atk == null || atk.isEmpty()) { if (bands == null || bands.isEmpty()) {
continue; continue;
} }
@@ -86,18 +87,23 @@ public enum CCombat implements ICDoc {
display.append(defender.getName()).append(" is attacked by:\n"); display.append(defender.getName()).append(" is attacked by:\n");
for (final Card c : atk) { // Associate Bands, Attackers Blockers
// loop through attackers for(AttackingBand band : bands) {
display.append(" BAND");
if (band.getBlocked()) {
display.append(" (blocked)");
}
display.append("\n");
for (final Card c : band.getAttackers()) {
display.append(" > "); display.append(" > ");
display.append(combatantToString(c)).append("\n"); display.append(combatantToString(c)).append("\n");
}
List<Card> blockers = combat.getBlockers(c, true); for (final Card element : band.getBlockers()) {
// loop through blockers
for (final Card element : blockers) {
display.append(" < ").append(combatantToString(element)).append("\n"); display.append(" < ").append(combatantToString(element)).append("\n");
} }
} // loop through attackers }
} }
return display.toString().trim(); return display.toString().trim();
} }