Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions forge-ai/src/main/java/forge/ai/GameState.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ static class PlayerState {
private String counters = "";
private String manaPool = "";
private String persistentMana = "";
private int landsPlayed = 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems too essential to lose support for

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't used anywhere
The puzzle all use 0 value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well it's not only about GameState since you're also removing it from GameSimulator and rollback:
so you're essentially degrading 3 different features for what - future refactor potential? 👎

Land MayPlay count works fine right now and the field could surely stay on the StaticAbility if the approach gets adjusted 🤷‍♂️

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other properties like sacrificed Or Discarded this Turn aren't part of Rollback either

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea but land plays remaining is one of the most important ones lol

private int landsPlayedLastTurn = 0;
private int numRingTemptedYou = 0;
private int speed = 0;
private String precast = null;
Expand Down Expand Up @@ -136,8 +134,6 @@ public String toString() {
for (PlayerState p : playerStates) {
String prefix = "p" + playerIndex++;
sb.append(TextUtil.concatNoSpace(prefix + "life=", String.valueOf(p.life), "\n"));
sb.append(TextUtil.concatNoSpace(prefix + "landsplayed=", String.valueOf(p.landsPlayed), "\n"));
sb.append(TextUtil.concatNoSpace(prefix + "landsplayedlastturn=", String.valueOf(p.landsPlayedLastTurn), "\n"));
sb.append(TextUtil.concatNoSpace(prefix + "numringtemptedyou=", String.valueOf(p.numRingTemptedYou), "\n"));
sb.append(TextUtil.concatNoSpace(prefix + "speed=", String.valueOf(p.speed), "\n"));
if (!p.counters.isEmpty()) {
Expand Down Expand Up @@ -165,8 +161,6 @@ public void initFromGame(Game game) {
for (Player player : game.getPlayers()) {
PlayerState p = new PlayerState();
p.life = player.getLife();
p.landsPlayed = player.getLandsPlayedThisTurn();
p.landsPlayedLastTurn = player.getLandsPlayedLastTurn();
p.counters = countersToString(player.getCounters());
p.manaPool = processManaPool(player.getManaPool());
p.numRingTemptedYou = player.getNumRingTemptedYou();
Expand Down Expand Up @@ -545,10 +539,6 @@ else if (categoryName.endsWith("phaseadvance"))
getPlayerState(categoryName).life = Integer.parseInt(categoryValue);
} else if (categoryName.endsWith("counters")) {
getPlayerState(categoryName).counters = categoryValue;
} else if (categoryName.endsWith("landsplayed")) {
getPlayerState(categoryName).landsPlayed = Integer.parseInt(categoryValue);
} else if (categoryName.endsWith("landsplayedlastturn")) {
getPlayerState(categoryName).landsPlayedLastTurn = Integer.parseInt(categoryValue);
} else if (categoryName.endsWith("numringtemptedyou")) {
getPlayerState(categoryName).numRingTemptedYou = Integer.parseInt(categoryValue);
} else if (categoryName.endsWith("speed")) {
Expand Down Expand Up @@ -1156,8 +1146,6 @@ private void setupPlayerState(final Player p, final PlayerState state) {
}

if (state.life >= 0) p.setLife(state.life, null);
p.setLandsPlayedThisTurn(state.landsPlayed);
p.setLandsPlayedLastTurn(state.landsPlayedLastTurn);
p.setNumRingTemptedYou(state.numRingTemptedYou);
p.setSpeed(state.speed);

Expand Down
4 changes: 2 additions & 2 deletions forge-ai/src/main/java/forge/ai/SpecialCardAi.java
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,7 @@ public static AiAbilityDecision consider(final Player ai, final SpellAbility sa)
if (ph.getNextTurn().equals(ai) && ph.is(PhaseType.MAIN2)
&& ai.getSpellsCastLastTurn() == 0
&& ai.getSpellsCastThisTurn() == 0
&& ai.getLandsPlayedLastTurn() == 0) {
&& ai.getLandsPlayedMyLastTurn() == 0) {
// We're in a situation when we have nothing castable in hand, something needs to be done
if (!blackViseOTB) {
// exile-loot +1 card when at max hand size, hoping to get a workable spell or land
Expand Down Expand Up @@ -2067,7 +2067,7 @@ public static boolean consider(final Player ai, final SpellAbility sa) {
if (ph.getNextTurn().equals(ai) && ph.is(PhaseType.END_OF_TURN)
&& ai.getSpellsCastLastTurn() == 0
&& ai.getSpellsCastThisTurn() == 0
&& ai.getLandsPlayedLastTurn() == 0) {
&& ai.getLandsPlayedMyLastTurn() == 0) {
// We're in a situation when we have nothing castable in hand, something needs to be done
if (!blackViseOTB) {
// draw +1 card when at max hand size, hoping to draw a workable spell or land
Expand Down
2 changes: 1 addition & 1 deletion forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ private static AiAbilityDecision hiddenOriginCanPlayAI(final Player ai, final Sp
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
}
if ("Atarka's Command".equals(sourceName)
&& (list.size() < 2 || ai.getLandsPlayedThisTurn() < 1)) {
&& (list.size() < 2 || ai.getLandsPlayedThisTurn().isEmpty())) {
// be strict on playing lands off charms
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
}
Expand Down
4 changes: 2 additions & 2 deletions forge-ai/src/main/java/forge/ai/ability/DestroyAi.java
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,8 @@ public boolean doLandForLandRemovalLogic(SpellAbility sa, Player ai, Card tgtLan

// if the opponent didn't play a land and has few lands OTB, might be worth mana-locking him
PhaseHandler ph = ai.getGame().getPhaseHandler();
boolean oppSkippedLandDrop = (tgtPlayer.getLandsPlayedLastTurn() == 0 && ph.isPlayerTurn(ai))
|| (tgtPlayer.getLandsPlayedThisTurn() == 0 && ph.isPlayerTurn(tgtPlayer) && ph.getPhase().isAfter(PhaseType.MAIN2));
boolean oppSkippedLandDrop = (tgtPlayer.getLandsPlayedMyLastTurn() == 0 && ph.isPlayerTurn(ai))
|| (tgtPlayer.getLandsPlayedThisTurn().isEmpty() && ph.isPlayerTurn(tgtPlayer) && ph.getPhase().isAfter(PhaseType.MAIN2));
boolean canManaLock = oppLandsOTB <= amountLandsToManalock && oppSkippedLandDrop;

// Best target is a basic land, and there's only one of it, so destroying it may potentially color-lock the opponent
Expand Down
1 change: 0 additions & 1 deletion forge-ai/src/main/java/forge/ai/simulation/GameCopier.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ public Game makeCopy(PhaseType advanceToPhase, Player aiPlayer) {
newPlayer.setCommitedCrimeThisTurn(origPlayer.getCommittedCrimeThisTurn());
newPlayer.setLifeStartedThisTurnWith(origPlayer.getLifeStartedThisTurnWith());
newPlayer.setDamageReceivedThisTurn(origPlayer.getDamageReceivedThisTurn());
newPlayer.setLandsPlayedThisTurn(origPlayer.getLandsPlayedThisTurn());
newPlayer.setCounters(Maps.newHashMap(origPlayer.getCounters()));
newPlayer.setSpeed(origPlayer.getSpeed());
newPlayer.setBlessing(origPlayer.hasBlessing(), null);
Expand Down
2 changes: 1 addition & 1 deletion forge-game/src/main/java/forge/game/GameAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ public final Card moveTo(final ZoneType name, final Card c, final int libPositio
case Stack -> moveToStack(c, cause, params);
case PlanarDeck, SchemeDeck, AttractionDeck, ContraptionDeck -> moveToVariantDeck(c, name, libPosition, cause, params);
case Junkyard -> moveToJunkyard(c, cause, params);
default -> moveTo(c.getOwner().getZone(name), c, cause); // sideboard will also get there
default -> moveTo(c.getOwner().getZone(name), c, cause, params); // sideboard will also get there
};
} catch (Exception e) {
String msg = "GameAction:moveTo: Exception occurred";
Expand Down
1 change: 0 additions & 1 deletion forge-game/src/main/java/forge/game/GameSnapshot.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ public void assignPlayerState(Player origPlayer, Player newPlayer) {
newPlayer.setLifeGainedThisTurn(origPlayer.getLifeGainedThisTurn());
newPlayer.setLifeStartedThisTurnWith(origPlayer.getLifeStartedThisTurnWith());
newPlayer.setDamageReceivedThisTurn(origPlayer.getDamageReceivedThisTurn());
newPlayer.setLandsPlayedThisTurn(origPlayer.getLandsPlayedThisTurn());
newPlayer.setCounters(Maps.newHashMap(origPlayer.getCounters()));
newPlayer.setBlessing(origPlayer.hasBlessing(), null);
newPlayer.setLibrarySearched(origPlayer.getLibrarySearched());
Expand Down
12 changes: 10 additions & 2 deletions forge-game/src/main/java/forge/game/ability/AbilityUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3523,8 +3523,16 @@ public static int playerXProperty(final Player player, final String s, final Car
return doXMath(Aggregates.sum(player.getCardsIn(ZoneType.Library, 1), Card::getCMC), m, source, ctb);
}

if (value.contains("LandsPlayed")) {
return doXMath(player.getLandsPlayedThisTurn(), m, source, ctb);
if (value.startsWith("LandsPlayed")) {
List<SpellAbility> list = player.getLandsPlayedThisTurn();
if (l[0].contains(" ")) {
String[] lparts = l[0].split(" ", 2);
String restrictions = TextUtil.fastReplace(l[0], TextUtil.addSuffix(lparts[0]," "), "");
list = list.stream()
.filter(SpellAbilityPredicates.isValid(restrictions.split(","), player, source, ctb))
.collect(Collectors.toList());
}
return doXMath(list.size(), m, source, ctb);
}

if (value.contains("SpellsCastThisTurn")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void resolve(SpellAbility sa) {
p.clearCounters();
p.resetSpellCastThisGame();
p.onCleanupPhase();
p.setLandsPlayedLastTurn(0);
p.setLandsPlayedMyLastTurn(0);
p.setSpellsCastLastTurn(0);
p.setLifeLostLastTurn(0);
p.resetCommanderStats();
Expand Down
7 changes: 0 additions & 7 deletions forge-game/src/main/java/forge/game/card/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -3897,12 +3897,6 @@ public final Map<StaticAbility, CardPlayOption> setMayPlay(Map<StaticAbility, Ca
return mayPlay = mp;
}

public void resetMayPlayTurn() {
for (StaticAbility sta : getStaticAbilities()) {
sta.resetMayPlayTurn();
}
}

public final CardCollectionView getEquippedBy() {
return CardLists.filter(getAttachedCards(), Card::isEquipment);
}
Expand Down Expand Up @@ -7317,7 +7311,6 @@ public void onCleanupPhase(final Player turn) {
resetCrewed();
resetSaddled();
visitedThisTurn = false;
resetMayPlayTurn();
resetChosenModeTurn();
resetAbilityResolvedThisTurn();
}
Expand Down
46 changes: 24 additions & 22 deletions forge-game/src/main/java/forge/game/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ public class Player extends GameEntity implements Comparable<Player> {
private int numExploredThisTurn;
private int numTokenCreatedThisTurn;
private int numForetoldThisTurn;
private int landsPlayedThisTurn;
private int landsPlayedLastTurn;
private int landsPlayedMyLastTurn;
private int numPowerSurgeLands;
private int spellsCastThisTurn;
private int spellsCastThisGame;
Expand All @@ -122,6 +121,7 @@ public class Player extends GameEntity implements Comparable<Player> {

private List<Card> discardedThisTurn = new ArrayList<>();
private List<Card> sacrificedThisTurn = new ArrayList<>();
private List<SpellAbility> landsPlayedThisTurn = new ArrayList<>();

private int simultaneousDamage = 0;

Expand Down Expand Up @@ -1627,27 +1627,34 @@ public final void shuffle(final SpellAbility sa) {
}

public final Card playLand(final Card land, SpellAbility cause) {

land.setController(this, 0);
if (land.isFaceDown()) {
land.turnFaceUp(null);
if (cause.isLandAbility()) {
land.changeToState(cause.getCardStateName());
}
}
Card lki = CardCopyService.getLKICopy(land);

Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(land);
runParams.put(AbilityKey.Origin, land.getZone().getZoneType().name());

Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.CardLKI, lki);

game.copyLastState();
final Card c = game.getAction().moveTo(getZone(ZoneType.Battlefield), land, cause);
final Card c = game.getAction().moveTo(getZone(ZoneType.Battlefield), land, cause, moveParams);
game.updateLastStateForCard(c);

SpellAbility causeLKI = cause.copy(lki, true);

// Run triggers
runParams.put(AbilityKey.SpellAbility, cause);
game.getTriggerHandler().runTrigger(TriggerType.LandPlayed, runParams, false);

game.getStack().unfreezeStack();
addLandPlayedThisTurn();
addLandPlayedThisTurn(causeLKI);

// play a sound
game.fireEvent(new GameEventLandPlayed(PlayerView.get(this), CardView.get(c)));
Expand Down Expand Up @@ -1689,7 +1696,7 @@ public final boolean canPlayLand(final Card land, final boolean ignoreZoneAndTim
}

// check for adjusted max lands play per turn
return getLandsPlayedThisTurn() < getMaxLandPlays();
return getLandsPlayedThisTurn().size() < getMaxLandPlays();
}

public final int getMaxLandPlays() {
Expand Down Expand Up @@ -2229,32 +2236,26 @@ public void setStartingHandSize(int shs) {
startingHandSize = shs;
}

public final int getLandsPlayedThisTurn() {
public final List<SpellAbility> getLandsPlayedThisTurn() {
return landsPlayedThisTurn;
}
public final int getLandsPlayedLastTurn() {
return landsPlayedLastTurn;
public final int getLandsPlayedMyLastTurn() {
return landsPlayedMyLastTurn;
}
public final void addLandPlayedThisTurn() {
landsPlayedThisTurn++;
public final void addLandPlayedThisTurn(SpellAbility landLki) {
landsPlayedThisTurn.add(landLki);
achievementTracker.landsPlayed++;
view.updateNumLandThisTurn(this);
}
public final void resetLandsPlayedThisTurn() {
landsPlayedThisTurn = 0;
view.updateNumLandThisTurn(this);
}
public final void setLandsPlayedThisTurn(int num) {
// This method should only be used directly when setting up the game state.
landsPlayedThisTurn = num;

landsPlayedThisTurn.clear();
view.updateNumLandThisTurn(this);
}
public final void setLandsPlayedLastTurn(int num) {
landsPlayedLastTurn = num;
public final void setLandsPlayedMyLastTurn(int num) {
landsPlayedMyLastTurn = num;
}
public final void setNumDrawnLastTurn(int num) {
numDrawnLastTurn= num;
numDrawnLastTurn = num;
}

public final int getInvestigateNumThisTurn() {
Expand Down Expand Up @@ -2486,8 +2487,7 @@ public void onCleanupPhase() {
resetNumTokenCreatedThisTurn();
setNumCardsInHandStartedThisTurnWith(getCardsIn(ZoneType.Hand).size());
setTappedLandForManaThisTurn(false);
setLandsPlayedLastTurn(getLandsPlayedThisTurn());
resetLandsPlayedThisTurn();

resetInvestigatedThisTurn();
resetSurveilThisTurn();
resetDiscardedThisTurn();
Expand Down Expand Up @@ -2518,9 +2518,11 @@ public void onCleanupPhase() {
if (game.getPhaseHandler().isPlayerTurn(this)) {
setBeenDealtCombatDamageSinceLastTurn(false);
setAttackedPlayersMyLastTurn(getAttackedPlayersMyTurn());
setLandsPlayedMyLastTurn(getLandsPlayedThisTurn().size());
clearAttackedMyTurn();
this.lastTurnNr = game.getPhaseHandler().getTurn();
}
resetLandsPlayedThisTurn();
}

public boolean canCastSorcery() {
Expand Down
2 changes: 1 addition & 1 deletion forge-game/src/main/java/forge/game/player/PlayerView.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ public int getNumLandThisTurn() {
return get(TrackableProperty.NumLandThisTurn);
}
void updateNumLandThisTurn(Player p) {
set(TrackableProperty.NumLandThisTurn, p.getLandsPlayedThisTurn());
set(TrackableProperty.NumLandThisTurn, p.getLandsPlayedThisTurn().size());
}

public int getNumManaShards() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ public void resolve() {
getHostCard().setSplitStateToPlayAbility(this);
final Card result = getActivatingPlayer().playLand(getHostCard(), this);

// increase mayplay used
if (getMayPlay() != null) {
getMayPlay().incMayPlayTurn();
}
// if land isn't in battlefield try to reset the card state
if (result != null && !result.isInPlay()) {
result.setState(CardStateName.Original, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
private Set<StaticAbilityLayer> layers;
private CardCollectionView ignoreEffectCards = new CardCollection();
private final List<Player> ignoreEffectPlayers = Lists.newArrayList();
private int mayPlayTurn = 0;

private SpellAbility payingTrigSA;
private StaticAbilityView view = null;
Expand Down Expand Up @@ -551,16 +550,12 @@ public Set<StaticAbilityLayer> getLayers() {
return layers;
}

public int getMayPlayTurn() {
return mayPlayTurn;
}

public void incMayPlayTurn() {
this.mayPlayTurn++;
}

public void resetMayPlayTurn() {
this.mayPlayTurn = 0;
public int getMayPlayTurn(final Player player) {
int castSpells = (int) this.getHostCard().getGame().getStack().getSpellsCastThisTurn().stream()
.map(Card::getCastSA).filter(s -> s != null && s.getActivatingPlayer().equals(player) && this.equals(s.getMayPlay()))
.count();
int landPlayed = (int) player.getLandsPlayedThisTurn().stream().filter(s -> this.equals(s.getMayPlay())).count();
return castSpells + landPlayed;
}

@Override
Expand Down Expand Up @@ -600,10 +595,6 @@ public StaticAbility copy(Card host, final boolean lki, boolean keepTextChanges)
// reset to force refresh if needed
clone.payingTrigSA = null;

if (!lki) {
clone.mayPlayTurn = 0;
}

clone.layers = this.generateLayer();
if (validHostZones != null) {
clone.setActiveZone(EnumSet.copyOf(validHostZones));
Expand Down
Loading
Loading