mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Merge branch 'pfps_master' into 'master'
GameAction: add PlayerController:confirmMulliganScry See merge request pfps/forge!1
This commit is contained in:
@@ -1209,8 +1209,7 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||||
ApiType api = (sa == null ) ? null : sa.getApi();
|
ApiType api = sa.getApi();
|
||||||
if ( api == null && mode == PlayerActionConfirmMode.Scry ) return true; // special hack for mulligan
|
|
||||||
|
|
||||||
// Abilities without api may also use this routine, However they should provide a unique mode value ?? How could this work?
|
// Abilities without api may also use this routine, However they should provide a unique mode value ?? How could this work?
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
|
|||||||
@@ -1164,4 +1164,10 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
|
|
||||||
return chosenOptCosts;
|
return chosenOptCosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean confirmMulliganScry(Player p) {
|
||||||
|
// Always true?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1714,14 +1714,17 @@ public class GameAction {
|
|||||||
} while (!allKept);
|
} while (!allKept);
|
||||||
|
|
||||||
//Vancouver Mulligan as a scry with the decisions inside
|
//Vancouver Mulligan as a scry with the decisions inside
|
||||||
ArrayList<Player> scryers = new ArrayList<Player>();
|
List<Player> scryers = Lists.newArrayList();
|
||||||
for(Player p : whoCanMulligan) {
|
for(Player p : whoCanMulligan) {
|
||||||
if (p.getStartingHandSize() > p.getZone(ZoneType.Hand).size()) {
|
if (p.getStartingHandSize() > p.getZone(ZoneType.Hand).size()) {
|
||||||
scryers.add(p);
|
scryers.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( scryers.size() > 0 ) {
|
|
||||||
scry(scryers,1,true,null);
|
for(Player p : scryers) {
|
||||||
|
if (p.getController().confirmMulliganScry(p)) {
|
||||||
|
scry(ImmutableList.of(p), 1, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1830,51 +1833,56 @@ public class GameAction {
|
|||||||
// 701.17c If multiple players scry at once, each of those players looks at the top cards of their library
|
// 701.17c If multiple players scry at once, each of those players looks at the top cards of their library
|
||||||
// at the same time. Those players decide in APNAP order (see rule 101.4) where to put those
|
// at the same time. Those players decide in APNAP order (see rule 101.4) where to put those
|
||||||
// cards, then those cards move at the same time.
|
// cards, then those cards move at the same time.
|
||||||
public void scry(List<Player>players,int numScry, boolean isOptional, SpellAbility cause) {
|
public void scry(List<Player> players, int numScry, SpellAbility cause) {
|
||||||
if ( numScry == 0 ) { return; }
|
if (numScry == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// reveal the top N library cards to the player (only)
|
// reveal the top N library cards to the player (only)
|
||||||
if ( players.size() > 1 ) { // no real need to separate out the look if there is only one player scrying
|
// no real need to separate out the look if
|
||||||
for ( final Player p : players ) {
|
// there is only one player scrying
|
||||||
|
if (players.size() > 1) {
|
||||||
|
for (final Player p : players) {
|
||||||
final CardCollection topN = new CardCollection(p.getCardsIn(ZoneType.Library, numScry));
|
final CardCollection topN = new CardCollection(p.getCardsIn(ZoneType.Library, numScry));
|
||||||
p.getGame().getAction().revealTo(topN,p);
|
revealTo(topN, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// make the decisions
|
// make the decisions
|
||||||
ArrayList<ImmutablePair<CardCollection, CardCollection>> decisions =
|
List<ImmutablePair<CardCollection, CardCollection>> decisions = Lists.newArrayList();
|
||||||
new ArrayList<ImmutablePair<CardCollection, CardCollection>>();
|
for (final Player p : players) {
|
||||||
for ( final Player p : players ) {
|
|
||||||
if (isOptional && !p.getController().confirmAction(cause, PlayerActionConfirmMode.Scry, "Do you want to scry?")) {
|
|
||||||
decisions.add(new ImmutablePair<CardCollection, CardCollection>(new CardCollection(),new CardCollection()));
|
|
||||||
} else {
|
|
||||||
final CardCollection topN = new CardCollection(p.getCardsIn(ZoneType.Library, numScry));
|
final CardCollection topN = new CardCollection(p.getCardsIn(ZoneType.Library, numScry));
|
||||||
ImmutablePair<CardCollection, CardCollection> decision = p.getController().arrangeForScry(topN);
|
ImmutablePair<CardCollection, CardCollection> decision = p.getController().arrangeForScry(topN);
|
||||||
decisions.add(decision);
|
decisions.add(decision);
|
||||||
int numToTop = decision.getLeft()==null ? 0 : decision.getLeft().size();
|
int numToTop = decision.getLeft() == null ? 0 : decision.getLeft().size();
|
||||||
int numToBottom = decision.getRight()==null ? 0 : decision.getRight().size();
|
int numToBottom = decision.getRight() == null ? 0 : decision.getRight().size();
|
||||||
p.getGame().fireEvent(new GameEventScry(p, numToTop, numToBottom)); // publicize the decision
|
|
||||||
|
// publicize the decision
|
||||||
|
game.fireEvent(new GameEventScry(p, numToTop, numToBottom));
|
||||||
}
|
}
|
||||||
}
|
// do the moves after all the decisions (maybe not necesssary, but let's
|
||||||
// do the moves after all the decisions (maybe not necesssary, but let's do it the official way)
|
// do it the official way)
|
||||||
for ( int i = 0; i<players.size(); i++ ) { // no good iterate simultaneously in Java
|
for (int i = 0; i < players.size(); i++) {
|
||||||
|
// no good iterate simultaneously in Java
|
||||||
final Player p = players.get(i);
|
final Player p = players.get(i);
|
||||||
final CardCollection toTop = decisions.get(i).getLeft();
|
final CardCollection toTop = decisions.get(i).getLeft();
|
||||||
final CardCollection toBottom = decisions.get(i).getRight();
|
final CardCollection toBottom = decisions.get(i).getRight();
|
||||||
if (toTop != null) {
|
if (toTop != null) {
|
||||||
Collections.reverse(toTop); // reverse to get the correct order
|
Collections.reverse(toTop); // reverse to get the correct order
|
||||||
for(Card c : toTop) {
|
for (Card c : toTop) {
|
||||||
p.getGame().getAction().moveToLibrary(c, cause, null);
|
moveToLibrary(c, cause, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (toBottom != null) {
|
if (toBottom != null) {
|
||||||
for(Card c : toBottom) {
|
for (Card c : toBottom) {
|
||||||
p.getGame().getAction().moveToBottomOfLibrary(c, cause, null);
|
moveToBottomOfLibrary(c, cause, null);
|
||||||
}
|
|
||||||
}
|
|
||||||
// set up triggers (but not actually do them until later)
|
|
||||||
final Map<String, Object> runParams = Maps.newHashMap();
|
|
||||||
runParams.put("Player", p);
|
|
||||||
p.getGame().getTriggerHandler().runTrigger(TriggerType.Scry, runParams, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cause != null) {
|
||||||
|
// set up triggers (but not actually do them until later)
|
||||||
|
final Map<String, Object> runParams = Maps.newHashMap();
|
||||||
|
runParams.put("Player", p);
|
||||||
|
game.getTriggerHandler().runTrigger(TriggerType.Scry, runParams, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,18 +4,17 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
|
||||||
public class ScryEffect extends SpellAbilityEffect {
|
public class ScryEffect extends SpellAbilityEffect {
|
||||||
@Override
|
@Override
|
||||||
protected String getStackDescription(SpellAbility sa) {
|
protected String getStackDescription(SpellAbility sa) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
for (final Player p : getTargetPlayers(sa)) {
|
||||||
|
|
||||||
for (final Player p : tgtPlayers) {
|
|
||||||
sb.append(p.toString()).append(" ");
|
sb.append(p.toString()).append(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,18 +36,16 @@ public class ScryEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
boolean isOptional = sa.hasParam("Optional");
|
boolean isOptional = sa.hasParam("Optional");
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final List<Player> players = Lists.newArrayList(); // players really affected
|
||||||
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
|
||||||
final ArrayList<Player> players = new ArrayList<Player>(); // players really affected
|
|
||||||
|
|
||||||
// Optional here for spells that have optional multi-player scrying
|
// Optional here for spells that have optional multi-player scrying
|
||||||
for (final Player p : tgtPlayers) {
|
for (final Player p : getTargetPlayers(sa)) {
|
||||||
if ( ((tgt == null) || p.canBeTargetedBy(sa)) &&
|
if ( (!sa.usesTargeting() || p.canBeTargetedBy(sa)) &&
|
||||||
(!isOptional || p.getController().confirmAction(sa, null, "Do you want to scry?")) ) {
|
(!isOptional || p.getController().confirmAction(sa, null, "Do you want to scry?")) ) {
|
||||||
players.add(p);
|
players.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sa.getActivatingPlayer().getGame().getAction().scry(players,num,false,sa);
|
sa.getActivatingPlayer().getGame().getAction().scry(players, num, sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ public enum PlayerActionConfirmMode {
|
|||||||
OptionalChoose,
|
OptionalChoose,
|
||||||
Tribute,
|
Tribute,
|
||||||
// Ripple;
|
// Ripple;
|
||||||
Scry;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,4 +260,6 @@ public abstract class PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract List<OptionalCostValue> chooseOptionalCosts(SpellAbility choosen, List<OptionalCostValue> optionalCostValues);
|
public abstract List<OptionalCostValue> chooseOptionalCosts(SpellAbility choosen, List<OptionalCostValue> optionalCostValues);
|
||||||
|
|
||||||
|
public abstract boolean confirmMulliganScry(final Player p);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -678,4 +678,10 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean confirmMulliganScry(Player p) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2889,4 +2889,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
optionalCost, choosen.getHostCard().getView());
|
optionalCost, choosen.getHostCard().getView());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean confirmMulliganScry(Player p) {
|
||||||
|
return InputConfirm.confirm(this, (SpellAbility)null, "Do you want to scry?");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user