"take priority" changed: now on priority SBA is checked, triggers are ordered, then player is asked for spell they want to play, then spell is played. Until player refuses to choose a spell, that means "I pass"

This commit is contained in:
Maxmtg
2014-02-01 20:43:20 +00:00
parent 2ea69dde48
commit da3b2c1dc1
6 changed files with 69 additions and 82 deletions

View File

@@ -55,6 +55,7 @@ import forge.game.cost.CostPart;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.Ability;
import forge.game.spellability.AbilityManaPart;
import forge.game.spellability.Spell;
import forge.game.spellability.SpellAbility;
@@ -735,20 +736,24 @@ public class AiController {
return null;
}
public void onPriorityRecieved() {
public SpellAbility choooseSpellAbilityToPlay() {
final PhaseType phase = game.getPhaseHandler().getPhase();
switch(phase) {
case MAIN1:
case MAIN2:
Log.debug("Computer " + phase.nameForUi);
if (game.getStack().isEmpty())
playLands();
// fall through is intended
default:
playSpellAbilities(game);
break;
if (game.getStack().isEmpty() && phase.isMain()) {
Log.debug("Computer " + phase.nameForUi);
List<Card> landsWannaPlay = getLandsToPlay();
if(landsWannaPlay != null && !landsWannaPlay.isEmpty() && player.canPlayLand(null)) {
Card land = chooseBestLandToPlay(landsWannaPlay);
if (ComputerUtil.damageFromETB(player, land) < player.getLife() || !player.canLoseLife()) {
Ability.PLAY_LAND_SURROGATE.setSourceCard(land);
return Ability.PLAY_LAND_SURROGATE;
}
}
}
SpellAbility sa = getSpellAbilityToPlay();
// System.out.println("Chosen to play: " + sa);
return sa;
}
// declares blockers for given defender in a given combat
@@ -778,37 +783,6 @@ public class AiController {
return combat;
}
private void playLands() {
final Player player = getPlayer();
List<Card> landsWannaPlay = getLandsToPlay();
while(landsWannaPlay != null && !landsWannaPlay.isEmpty() && player.canPlayLand(null)) {
Card land = chooseBestLandToPlay(landsWannaPlay);
if (ComputerUtil.damageFromETB(player, land) >= player.getLife() && player.canLoseLife()) {
break;
}
landsWannaPlay.remove(land);
player.playLand(land, false);
game.getPhaseHandler().setPriority(player);
game.getAction().checkStateEffects();
}
}
private void playSpellAbilities(final Game game)
{
SpellAbility sa;
do {
if ( game.isGameOver() )
return;
sa = getSpellAbilityToPlay();
if ( sa == null ) break;
//System.out.println("Playing sa: " + sa);
if (!ComputerUtil.handlePlayingSpellAbility(player, sa, game)) {
break;
}
} while ( sa != null );
}
private final SpellAbility getSpellAbilityToPlay() {
// if top of stack is owned by me
if (!game.getStack().isEmpty() && game.getStack().peekAbility().getActivatingPlayer().equals(player)) {

View File

@@ -975,15 +975,23 @@ public class PhaseHandler implements java.io.Serializable {
sw.start();
}
// Rule 704.3 Whenever a player would get priority, the game checks ... for state-based actions,
game.getAction().checkStateEffects();
game.fireEvent(new GameEventPlayerPriority(getPlayerTurn(), getPhase(), getPriorityPlayer()));
SpellAbility chosenSa = null;
// SBA could lead to game over
if (game.isGameOver()) { return; }
do {
// Rule 704.3 Whenever a player would get priority, the game checks ... for state-based actions,
game.getAction().checkStateEffects();
if (game.isGameOver())
return; // state-based effects check could lead to game over
game.getStack().chooseOrderOfSimultaneousStackEntry(pPlayerPriority);
pPlayerPriority.getController().takePriority();
game.getStack().chooseOrderOfSimultaneousStackEntry(pPlayerPriority);
chosenSa = pPlayerPriority.getController().chooseSpellAbilityToPlay();
if( null == chosenSa )
break; // that means 'I pass'
pPlayerPriority.getController().playChosenSpellAbility(chosenSa);
} while (chosenSa != null);
if (DEBUG_PHASES) {
sw.stop();
@@ -1006,18 +1014,7 @@ public class PhaseHandler implements java.io.Serializable {
if( DEBUG_PHASES )
System.out.println(String.format("%s %s: %s passes priority to %s", playerTurn, phase, pPlayerPriority, nextPlayer));
if (getFirstPriority() == nextPlayer) {
if (game.getStack().hasSimultaneousStackEntries() && givePriorityToPlayer)
{
Player ap = nextPlayer;
Player nap = game.getNextPlayerAfter(ap);
game.getStack().chooseOrderOfSimultaneousStackEntry(ap);
do {
game.getStack().chooseOrderOfSimultaneousStackEntry(nap);
nap = game.getNextPlayerAfter(nap);
} while( nap != ap);
// All have passed, but there's something waiting to be added to stack. After that and give them priority again
} else if (game.getStack().isEmpty()) {
if (game.getStack().isEmpty()) {
this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase
// end phase

View File

@@ -180,7 +180,8 @@ public abstract class PlayerController {
public abstract void declareAttackers(Player attacker, Combat combat);
public abstract void declareBlockers(Player defender, Combat combat);
public abstract void takePriority();
public abstract SpellAbility chooseSpellAbilityToPlay();
public abstract void playChosenSpellAbility(SpellAbility sa);
public abstract List<Card> chooseCardsToDiscardToMaximumHandSize(int numDiscard);
public abstract boolean payManaOptional(Card card, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose);

View File

@@ -394,12 +394,19 @@ public class PlayerControllerAi extends PlayerController {
}
@Override
public void takePriority() {
if (!game.isGameOver()) {
brains.onPriorityRecieved();
}
// use separate thread for AI?
public SpellAbility chooseSpellAbilityToPlay() {
return brains.choooseSpellAbilityToPlay();
}
@Override
public void playChosenSpellAbility(SpellAbility sa)
{
// System.out.println("Playing sa: " + sa);
if ( sa == Ability.PLAY_LAND_SURROGATE )
player.playLand(sa.getSourceCard(), false);
else
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
}
@Override
public List<Card> chooseCardsToDiscardToMaximumHandSize(int numDiscard) {