mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
GameLog: quest listener is registered in MatchClass, Mulligan logs from events
PhaseHandler - half-measures to handle close window during turn-based actions (like declare combatants) getAllPossibleAbilites method moved from game to card removed 5 calls to isHuman/Computer
This commit is contained in:
@@ -63,6 +63,7 @@ import forge.card.trigger.Trigger;
|
|||||||
import forge.card.trigger.TriggerType;
|
import forge.card.trigger.TriggerType;
|
||||||
import forge.card.trigger.ZCTrigger;
|
import forge.card.trigger.ZCTrigger;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.GlobalRuleChange;
|
import forge.game.GlobalRuleChange;
|
||||||
import forge.game.event.GameEventCardDamaged;
|
import forge.game.event.GameEventCardDamaged;
|
||||||
import forge.game.event.GameEventCardDamaged.DamageType;
|
import forge.game.event.GameEventCardDamaged.DamageType;
|
||||||
@@ -72,6 +73,7 @@ import forge.game.event.GameEventCounterRemoved;
|
|||||||
import forge.game.event.GameEventCardTapped;
|
import forge.game.event.GameEventCardTapped;
|
||||||
import forge.game.phase.Combat;
|
import forge.game.phase.Combat;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.CardDb;
|
import forge.item.CardDb;
|
||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
@@ -8287,4 +8289,41 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
throw new IllegalStateException("Card " + toString() + " has no means to determine the game it belongs to!");
|
throw new IllegalStateException("Card " + toString() + " has no means to determine the game it belongs to!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write javadoc for this method.
|
||||||
|
* @param card
|
||||||
|
* @param game TODO
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<SpellAbility> getAllPossibleAbilites(Player player) {
|
||||||
|
// this can only be called by the Human
|
||||||
|
final Zone zone = player.getGame().getZoneOf(this);
|
||||||
|
|
||||||
|
final List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
||||||
|
for (SpellAbility sa : getSpellAbilities()) {
|
||||||
|
//add alternative costs as additional spell abilities
|
||||||
|
abilities.add(sa);
|
||||||
|
abilities.addAll(GameActionUtil.getAlternativeCosts(sa));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int iSa = 0; iSa < abilities.size();) {
|
||||||
|
SpellAbility sa = abilities.get(iSa);
|
||||||
|
sa.setActivatingPlayer(player);
|
||||||
|
if (!sa.canPlay())
|
||||||
|
abilities.remove(iSa);
|
||||||
|
else
|
||||||
|
iSa++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLand() && player.canPlayLand(this)) {
|
||||||
|
if (zone.is(ZoneType.Hand) || (!zone.is(ZoneType.Battlefield) && hasStartOfKeyword("May be played"))) {
|
||||||
|
Ability.PLAY_LAND_SURROGATE.setSourceCard(this);
|
||||||
|
abilities.add(Ability.PLAY_LAND_SURROGATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return abilities;
|
||||||
|
}
|
||||||
|
|
||||||
} // end Card class
|
} // end Card class
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import forge.game.event.GameEventBlockersDeclared;
|
|||||||
import forge.game.event.GameEventCardDamaged;
|
import forge.game.event.GameEventCardDamaged;
|
||||||
import forge.game.event.GameEventCardDamaged.DamageType;
|
import forge.game.event.GameEventCardDamaged.DamageType;
|
||||||
import forge.game.event.GameEventLandPlayed;
|
import forge.game.event.GameEventLandPlayed;
|
||||||
|
import forge.game.event.GameEventMulligan;
|
||||||
import forge.game.event.GameEventPlayerDamaged;
|
import forge.game.event.GameEventPlayerDamaged;
|
||||||
import forge.game.event.GameEventPlayerPoisoned;
|
import forge.game.event.GameEventPlayerPoisoned;
|
||||||
import forge.game.event.GameEventSpellAbilityCast;
|
import forge.game.event.GameEventSpellAbilityCast;
|
||||||
@@ -27,6 +28,7 @@ import forge.game.event.GameEventPlayerControl;
|
|||||||
import forge.game.player.LobbyPlayer;
|
import forge.game.player.LobbyPlayer;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerStatistics;
|
import forge.game.player.PlayerStatistics;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
import forge.util.maps.MapOfLists;
|
import forge.util.maps.MapOfLists;
|
||||||
|
|
||||||
@@ -231,6 +233,12 @@ public class GameLogFormatter extends IGameEventVisitor.Base<GameLogEntry> {
|
|||||||
|
|
||||||
return new GameLogEntry(GameLogEntryType.COMBAT, sb.toString());
|
return new GameLogEntry(GameLogEntryType.COMBAT, sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameLogEntry visit(GameEventMulligan ev) {
|
||||||
|
String message = String.format( "%s has mulliganed down to %d cards.", ev.player, ev.player.getZone(ZoneType.Hand).size());
|
||||||
|
return new GameLogEntry(GameLogEntryType.MULLIGAN, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import forge.game.ai.ComputerUtilMana;
|
|||||||
import forge.game.phase.Combat;
|
import forge.game.phase.Combat;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
@@ -1372,4 +1373,13 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
} // end changeHiddenOriginResolveAI
|
} // end changeHiddenOriginResolveAI
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||||
|
// AI was never asked
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import forge.card.spellability.SpellAbilityStackInstance;
|
|||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
import forge.card.trigger.TriggerType;
|
import forge.card.trigger.TriggerType;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.ai.ComputerUtilCard;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -428,10 +427,11 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
if (tgt != null && tgtC.isInPlay() && !tgtC.canBeTargetedBy(sa)) {
|
if (tgt != null && tgtC.isInPlay() && !tgtC.canBeTargetedBy(sa)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final String prompt = "Do you want to move " + tgtC + " from " + origin + " to " + destination + "?";
|
|
||||||
if (player.isHuman() && optional && !GuiDialog.confirm(hostCard, prompt)) {
|
final String prompt = String.format("Do you want to move %s from %s to %s?", tgtC, origin, destination);
|
||||||
|
if (optional && false == player.getController().confirmAction(sa, null, prompt) )
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
final Zone originZone = game.getZoneOf(tgtC);
|
final Zone originZone = game.getZoneOf(tgtC);
|
||||||
|
|
||||||
// if Target isn't in the expected Zone, continue
|
// if Target isn't in the expected Zone, continue
|
||||||
@@ -472,16 +472,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
list = CardLists.getValidCards(list, sa.getParam("AttachedTo"), tgtC.getController(), tgtC);
|
list = CardLists.getValidCards(list, sa.getParam("AttachedTo"), tgtC.getController(), tgtC);
|
||||||
}
|
}
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
Card attachedTo = null;
|
Card attachedTo = player.getController().chooseSingleCardForEffect(list, sa, tgtC + " - Select a card to attach to.");
|
||||||
if (player.isHuman()) {
|
|
||||||
if (list.size() > 1) {
|
|
||||||
attachedTo = GuiChoose.one(tgtC + " - Select a card to attach to.", list);
|
|
||||||
} else {
|
|
||||||
attachedTo = list.get(0);
|
|
||||||
}
|
|
||||||
} else { // AI player
|
|
||||||
attachedTo = ComputerUtilCard.getBestAI(list);
|
|
||||||
}
|
|
||||||
if (tgtC.isAura()) {
|
if (tgtC.isAura()) {
|
||||||
if (tgtC.isEnchanting()) {
|
if (tgtC.isEnchanting()) {
|
||||||
// If this Card is already Enchanting something, need
|
// If this Card is already Enchanting something, need
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package forge.card.cardfactory;
|
package forge.card.cardfactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
@@ -31,14 +30,10 @@ import forge.card.mana.ManaCost;
|
|||||||
import forge.card.spellability.Spell;
|
import forge.card.spellability.Spell;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.ai.AiController;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerControllerAi;
|
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.gui.input.InputPayManaExecuteCommands;
|
import forge.gui.input.InputPayManaExecuteCommands;
|
||||||
import forge.gui.input.InputSelectCards;
|
|
||||||
import forge.gui.input.InputSelectCardsFromList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -52,39 +47,24 @@ public class CardFactorySorceries {
|
|||||||
|
|
||||||
private static final void balanceLands(Game game, Spell card) {
|
private static final void balanceLands(Game game, Spell card) {
|
||||||
|
|
||||||
List<List<Card>> lands = new ArrayList<List<Card>>();
|
int minLands = Integer.MAX_VALUE;
|
||||||
for (Player p : game.getPlayers()) {
|
for (Player p : game.getPlayers()) {
|
||||||
|
int pL = p.getLandsInPlay().size();
|
||||||
lands.add(p.getLandsInPlay());
|
if( pL < minLands )
|
||||||
|
minLands = pL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int min = Integer.MAX_VALUE;
|
|
||||||
for (List<Card> l : lands) {
|
|
||||||
int s = l.size();
|
|
||||||
min = Math.min(min, s);
|
|
||||||
}
|
|
||||||
Iterator<List<Card>> ll = lands.iterator();
|
|
||||||
for (Player p : game.getPlayers()) {
|
for (Player p : game.getPlayers()) {
|
||||||
|
|
||||||
List<Card> l = ll.next();
|
List<Card> l = p.getLandsInPlay();
|
||||||
int sac = l.size() - min;
|
int sac = l.size() - minLands;
|
||||||
if (sac == 0) {
|
if (sac == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p.isComputer()) {
|
|
||||||
CardLists.shuffle(l);
|
List<Card> toSac = p.getController().choosePermanentsToSacrifice(card, sac, sac, l, "Select %d more land(s) to sacrifice");
|
||||||
for (int i = 0; i < sac; i++) {
|
for( Card crd : toSac )
|
||||||
game.getAction().sacrifice(l.get(i), card);
|
p.getGame().getAction().sacrifice(crd, card);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final List<Card> list = CardLists.getType(p.getCardsIn(ZoneType.Battlefield), "Land");
|
|
||||||
|
|
||||||
InputSelectCards inp = new InputSelectCardsFromList(sac, sac, list);
|
|
||||||
inp.setMessage("Select %d more land(s) to sacrifice");
|
|
||||||
Singletons.getControl().getInputQueue().setInputAndWait(inp);
|
|
||||||
for( Card crd : inp.getSelected() )
|
|
||||||
p.getGame().getAction().sacrifice(crd, card);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,26 +80,16 @@ public class CardFactorySorceries {
|
|||||||
if (sac == 0) {
|
if (sac == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p.isHuman()) {
|
|
||||||
InputSelectCards sc = new InputSelectCardsFromList(sac, sac, hand);
|
List<Card> toDiscard = p.getController().chooseCardsToDiscardFrom(p, spell, hand, sac, sac); // "Select %d more card(s) to discard"
|
||||||
sc.setMessage("Select %d more card(s) to discard");
|
for (Card c : toDiscard)
|
||||||
Singletons.getControl().getInputQueue().setInputAndWait(sc);
|
p.discard(c, spell);
|
||||||
for( Card c : sc.getSelected())
|
|
||||||
p.discard(c, spell);
|
|
||||||
} else {
|
|
||||||
final AiController ai = ((PlayerControllerAi)p.getController()).getAi();
|
|
||||||
final List<Card> toDiscard = ai.getCardsToDiscard(sac, (String[])null, spell);
|
|
||||||
for (int i = 0; i < toDiscard.size(); i++) {
|
|
||||||
p.discard(toDiscard.get(i), spell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final void balanceCreatures(Game game, Spell card) {
|
private static final void balanceCreatures(Game game, Spell card) {
|
||||||
List<List<Card>> creats = new ArrayList<List<Card>>();
|
List<List<Card>> creats = new ArrayList<List<Card>>();
|
||||||
for (Player p : game.getPlayers()) {
|
for (Player p : game.getPlayers()) {
|
||||||
|
|
||||||
creats.add(p.getCreaturesInPlay());
|
creats.add(p.getCreaturesInPlay());
|
||||||
}
|
}
|
||||||
int min = Integer.MAX_VALUE;
|
int min = Integer.MAX_VALUE;
|
||||||
@@ -135,22 +105,10 @@ public class CardFactorySorceries {
|
|||||||
if (sac == 0) {
|
if (sac == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p.isComputer()) {
|
List<Card> toSac = p.getController().choosePermanentsToSacrifice(card, sac, sac, c, "Select %d more creature(s) to sacrifice");
|
||||||
CardLists.sortByPowerAsc(c);
|
|
||||||
CardLists.sortByCmcDesc(c);
|
for( Card crd : toSac )
|
||||||
Collections.reverse(c);
|
p.getGame().getAction().sacrifice(crd, card);
|
||||||
for (int i = 0; i < sac; i++) {
|
|
||||||
p.getGame().getAction().sacrifice(c.get(i), card);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final List<Card> list = CardLists.getType(p.getCardsIn(ZoneType.Battlefield), "Creature");
|
|
||||||
InputSelectCards inp = new InputSelectCardsFromList(sac, sac, list);
|
|
||||||
inp.setMessage("Select %d more creature(s) to sacrifice");
|
|
||||||
Singletons.getControl().getInputQueue().setInputAndWait(inp);
|
|
||||||
for( Card crd : inp.getSelected() )
|
|
||||||
p.getGame().getAction().sacrifice(crd, card);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import forge.Card;
|
|||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.game.event.GameEvent;
|
import forge.game.event.GameEvent;
|
||||||
import forge.game.event.GameEventAnteCardsSelected;
|
import forge.game.event.GameEventAnteCardsSelected;
|
||||||
import forge.game.event.GameEventAttackersDeclared;
|
|
||||||
import forge.game.event.GameEventGameFinished;
|
import forge.game.event.GameEventGameFinished;
|
||||||
import forge.game.event.GameEventGameOutcome;
|
import forge.game.event.GameEventGameOutcome;
|
||||||
import forge.game.event.GameEventPlayerControl;
|
import forge.game.event.GameEventPlayerControl;
|
||||||
|
|||||||
@@ -30,11 +30,8 @@ import forge.Card;
|
|||||||
import forge.CardLists;
|
import forge.CardLists;
|
||||||
import forge.ColorChanger;
|
import forge.ColorChanger;
|
||||||
import forge.GameLog;
|
import forge.GameLog;
|
||||||
import forge.Singletons;
|
|
||||||
import forge.StaticEffects;
|
import forge.StaticEffects;
|
||||||
import forge.card.replacement.ReplacementHandler;
|
import forge.card.replacement.ReplacementHandler;
|
||||||
import forge.card.spellability.Ability;
|
|
||||||
import forge.card.spellability.SpellAbility;
|
|
||||||
import forge.card.spellability.SpellAbilityStackInstance;
|
import forge.card.spellability.SpellAbilityStackInstance;
|
||||||
import forge.card.trigger.TriggerHandler;
|
import forge.card.trigger.TriggerHandler;
|
||||||
import forge.card.trigger.TriggerType;
|
import forge.card.trigger.TriggerType;
|
||||||
@@ -122,9 +119,6 @@ public class Game {
|
|||||||
endOfTurn = new EndOfTurn(this);
|
endOfTurn = new EndOfTurn(this);
|
||||||
endOfCombat = new EndOfCombat(this);
|
endOfCombat = new EndOfCombat(this);
|
||||||
|
|
||||||
if ( match0.getGameType() == GameType.Quest)
|
|
||||||
events.register(Singletons.getModel().getQuest()); // this one listens to player's mulligans ATM
|
|
||||||
|
|
||||||
subscribeToEvents(gameLog.getEventVisitor());
|
subscribeToEvents(gameLog.getEventVisitor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,42 +543,6 @@ public class Game {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for this method.
|
|
||||||
* @param card
|
|
||||||
* @param player
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public List<SpellAbility> getAbilitesOfCard(Card c, Player player) {
|
|
||||||
// this can only be called by the Human
|
|
||||||
final Zone zone = this.getZoneOf(c);
|
|
||||||
|
|
||||||
final List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
|
||||||
for (SpellAbility sa : c.getSpellAbilities()) {
|
|
||||||
//add alternative costs as additional spell abilities
|
|
||||||
abilities.add(sa);
|
|
||||||
abilities.addAll(GameActionUtil.getAlternativeCosts(sa));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int iSa = 0; iSa < abilities.size();) {
|
|
||||||
SpellAbility sa = abilities.get(iSa);
|
|
||||||
sa.setActivatingPlayer(player);
|
|
||||||
if (!sa.canPlay())
|
|
||||||
abilities.remove(iSa);
|
|
||||||
else
|
|
||||||
iSa++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.isLand() && player.canPlayLand(c)) {
|
|
||||||
if (zone.is(ZoneType.Hand) || (!zone.is(ZoneType.Battlefield) && c.hasStartOfKeyword("May be played"))) {
|
|
||||||
Ability.PLAY_LAND_SURROGATE.setSourceCard(c);
|
|
||||||
abilities.add(Ability.PLAY_LAND_SURROGATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return abilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the activePlane
|
* @return the activePlane
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -82,7 +82,10 @@ public class Match {
|
|||||||
public void startRound() {
|
public void startRound() {
|
||||||
|
|
||||||
currentGame = new Game(players, gameType, this);
|
currentGame = new Game(players, gameType, this);
|
||||||
|
|
||||||
|
if ( getGameType() == GameType.Quest)
|
||||||
|
currentGame.subscribeToEvents(Singletons.getModel().getQuest()); // this one listens to player's mulligans ATM
|
||||||
|
|
||||||
Singletons.getControl().attachToGame(currentGame);
|
Singletons.getControl().attachToGame(currentGame);
|
||||||
|
|
||||||
final boolean canRandomFoil = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL) && gameType == GameType.Constructed;
|
final boolean canRandomFoil = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL) && gameType == GameType.Constructed;
|
||||||
|
|||||||
@@ -695,6 +695,9 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
return choice;
|
return choice;
|
||||||
|
|
||||||
|
case ChangeZone: // called when permanent ETB 'AttachedTo' something
|
||||||
|
return ComputerUtilCard.getBestAI(options);
|
||||||
|
|
||||||
default: throw new InvalidParameterException("AI chooseSingleCard does not know how to choose card for " + api);
|
default: throw new InvalidParameterException("AI chooseSingleCard does not know how to choose card for " + api);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -465,6 +465,9 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
private void declareAttackersTurnBasedActions() {
|
private void declareAttackersTurnBasedActions() {
|
||||||
Player whoDeclares = playerDeclaresAttackers == null || playerDeclaresAttackers.hasLost() ? playerTurn : playerDeclaresAttackers;
|
Player whoDeclares = playerDeclaresAttackers == null || playerDeclaresAttackers.hasLost() ? playerTurn : playerDeclaresAttackers;
|
||||||
whoDeclares.getController().declareAttackers(playerTurn);
|
whoDeclares.getController().declareAttackers(playerTurn);
|
||||||
|
|
||||||
|
if ( game.isGameOver() ) // they just like to close window at any moment
|
||||||
|
return;
|
||||||
|
|
||||||
game.getCombat().removeAbsentCombatants();
|
game.getCombat().removeAbsentCombatants();
|
||||||
CombatUtil.checkAttackOrBlockAlone(game.getCombat());
|
CombatUtil.checkAttackOrBlockAlone(game.getCombat());
|
||||||
@@ -518,7 +521,10 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
// Apply Odric's effect here
|
// Apply Odric's effect here
|
||||||
Player whoDeclaresBlockers = playerDeclaresBlockers == null || playerDeclaresBlockers.hasLost() ? p : playerDeclaresBlockers;
|
Player whoDeclaresBlockers = playerDeclaresBlockers == null || playerDeclaresBlockers.hasLost() ? p : playerDeclaresBlockers;
|
||||||
if ( combat.isPlayerAttacked(p) )
|
if ( combat.isPlayerAttacked(p) )
|
||||||
whoDeclaresBlockers.getController().declareBlockers(p);
|
whoDeclaresBlockers.getController().declareBlockers(p);
|
||||||
|
|
||||||
|
if ( game.isGameOver() ) // they just like to close window at any moment
|
||||||
|
return;
|
||||||
} while(p != playerTurn);
|
} while(p != playerTurn);
|
||||||
|
|
||||||
combat.removeAbsentCombatants();
|
combat.removeAbsentCombatants();
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import forge.Constant.Preferences;
|
|||||||
import forge.CounterType;
|
import forge.CounterType;
|
||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.GameLogEntryType;
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.card.ability.AbilityFactory;
|
import forge.card.ability.AbilityFactory;
|
||||||
@@ -3137,7 +3136,6 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
public void onMulliganned() {
|
public void onMulliganned() {
|
||||||
game.fireEvent(new GameEventMulligan(this)); // quest listener may interfere here
|
game.fireEvent(new GameEventMulligan(this)); // quest listener may interfere here
|
||||||
final int newHand = getCardsIn(ZoneType.Hand).size();
|
final int newHand = getCardsIn(ZoneType.Hand).size();
|
||||||
game.getGameLog().add(GameLogEntryType.MULLIGAN, this + " has mulliganed down to " + newHand + " cards.");
|
|
||||||
stats.notifyHasMulliganed();
|
stats.notifyHasMulliganed();
|
||||||
stats.notifyOpeningHandSize(newHand);
|
stats.notifyOpeningHandSize(newHand);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,6 +200,9 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Card> chooseCardsToDiscardFrom(Player p, SpellAbility sa, List<Card> validCards, int min, int max) {
|
public List<Card> chooseCardsToDiscardFrom(Player p, SpellAbility sa, List<Card> validCards, int min, int max) {
|
||||||
|
if ( p == player )
|
||||||
|
return brains.getCardsToDiscard(min, max, validCards, sa);
|
||||||
|
|
||||||
boolean isTargetFriendly = !p.isOpponentOf(player);
|
boolean isTargetFriendly = !p.isOpponentOf(player);
|
||||||
|
|
||||||
return isTargetFriendly
|
return isTargetFriendly
|
||||||
|
|||||||
@@ -263,8 +263,10 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
// Human is supposed to read the message and understand from it what to choose
|
// Human is supposed to read the message and understand from it what to choose
|
||||||
if ( isOptional )
|
if ( isOptional )
|
||||||
return GuiChoose.oneOrNone(title, options);
|
return GuiChoose.oneOrNone(title, options);
|
||||||
else
|
else if ( options.size() > 2 )
|
||||||
return GuiChoose.one(title, options);
|
return GuiChoose.one(title, options);
|
||||||
|
else
|
||||||
|
return options.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class InputPassPriority extends InputSyncronizedBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(Card card, boolean isRmb) {
|
protected void onCardSelected(Card card, boolean isRmb) {
|
||||||
final SpellAbility ab = player.getController().getAbilityToPlay(player.getGame().getAbilitesOfCard(card, player));
|
final SpellAbility ab = player.getController().getAbilityToPlay(card.getAllPossibleAbilites(player));
|
||||||
if ( null != ab) {
|
if ( null != ab) {
|
||||||
chosenSa = ab;
|
chosenSa = ab;
|
||||||
stop();
|
stop();
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public class CField implements ICDoc {
|
|||||||
// TODO: "can play" check needed!
|
// TODO: "can play" check needed!
|
||||||
|
|
||||||
// should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard?
|
// should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard?
|
||||||
final SpellAbility ab = player.getController().getAbilityToPlay(game.getAbilitesOfCard(c, player));
|
final SpellAbility ab = player.getController().getAbilityToPlay(c.getAllPossibleAbilites(player));
|
||||||
if ( null != ab) {
|
if ( null != ab) {
|
||||||
game.getAction().invoke(new Runnable(){ @Override public void run(){
|
game.getAction().invoke(new Runnable(){ @Override public void run(){
|
||||||
HumanPlay.playSpellAbility(player, ab);
|
HumanPlay.playSpellAbility(player, ab);
|
||||||
|
|||||||
Reference in New Issue
Block a user