Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Room: First Spell Part #6044

Merged
merged 28 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d034e24
Room: First Spell Part
Hanmac Sep 3, 2024
b77b57e
Add Unlock Static Action
Hanmac Sep 8, 2024
82f1c62
Update dollmakers_shop_porcelain_gallery.txt
tool4ever Sep 8, 2024
e6406c6
~ fix sorcery speed
Hanmac Sep 8, 2024
353621f
Fix unlock original state with Copy Enchantment
Sep 15, 2024
5c816ea
Fix noname room crash
Sep 15, 2024
700adfa
Fix script
Sep 16, 2024
217e854
Update TriggerUnlockDoor.java
Hanmac Sep 16, 2024
ad90c16
Update TriggerUnlockDoor.java
Hanmac Sep 16, 2024
d9454a9
Card: add lockRoom
Hanmac Sep 18, 2024
394d624
Use ApiType for UnlockDoor
Hanmac Sep 27, 2024
670c74c
~ add ghostly keybearer
Hanmac Sep 27, 2024
15e1859
~ fix import
Hanmac Sep 27, 2024
b86bba9
Update ghostly_keybearer.txt
tool4ever Sep 28, 2024
51daf48
PlayerController: add chooseSingleCardState
Hanmac Oct 3, 2024
7611458
UnlockEffect: LockOrUnlock mode
Hanmac Oct 5, 2024
7476b5f
~ fix import
Hanmac Oct 5, 2024
46421bd
View room fixes
Oct 5, 2024
18e9f6f
update manacost for room
kevlahnota Oct 5, 2024
045868b
remove redundant check
kevlahnota Oct 5, 2024
5e47664
fix CardStateView hashCode and params for chooseCardState
Hanmac Oct 5, 2024
d43e37a
~ remove isSplitCard for getLockedRooms
Hanmac Oct 5, 2024
0f70374
Fix doubled type for rooms
Oct 5, 2024
5c8bcc9
~ fix sharesNameWith for Split/Room
Hanmac Oct 6, 2024
9abe505
Always unlocking better than never for AI
Oct 6, 2024
66b6880
Unlock doesn't need to be a Room
Hanmac Oct 6, 2024
f21871b
fix isSplitCard for normal Splits
Hanmac Oct 6, 2024
4e6c110
check left and right state only if no Name Overwrite
Hanmac Oct 6, 2024
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
18 changes: 18 additions & 0 deletions forge-ai/src/main/java/forge/ai/PlayerControllerAi.java
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,24 @@ public String chooseCardName(SpellAbility sa, List<ICardFace> faces, String mess
return SpellApiToAi.Converter.get(api).chooseCardName(player, sa, faces);
}

@Override
public ICardFace chooseSingleCardFace(SpellAbility sa, List<ICardFace> faces, String message) {
ApiType api = sa.getApi();
if (null == api) {
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
}
return SpellApiToAi.Converter.get(api).chooseCardFace(player, sa, faces);
}

@Override
public CardState chooseSingleCardState(SpellAbility sa, List<CardState> states, String message, Map<String, Object> params) {
ApiType api = sa.getApi();
if (null == api) {
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
}
return SpellApiToAi.Converter.get(api).chooseCardState(player, sa, states, params);
}

@Override
public Card chooseDungeon(Player ai, List<PaperCard> dungeonCards, String message) {
// TODO: improve the conditions that define which dungeon is a viable option to choose
Expand Down
13 changes: 13 additions & 0 deletions forge-ai/src/main/java/forge/ai/SpellAbilityAi.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import forge.card.mana.ManaCostParser;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.game.card.CardState;
import forge.game.card.CounterType;
import forge.game.cost.Cost;
import forge.game.mana.ManaCostBeingPaid;
Expand Down Expand Up @@ -365,6 +366,18 @@ public String chooseCardName(Player ai, SpellAbility sa, List<ICardFace> faces)
return face == null ? "" : face.getName();
}

public ICardFace chooseCardFace(Player ai, SpellAbility sa, List<ICardFace> faces) {
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseCardFace is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");

return Iterables.getFirst(faces, null);
}

public CardState chooseCardState(Player ai, SpellAbility sa, List<CardState> faces, Map<String, Object> params) {
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseCardState is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");

return Iterables.getFirst(faces, null);
}

public int chooseNumber(Player player, SpellAbility sa, int min, int max, Map<String, Object> params) {
return max;
}
Expand Down
1 change: 1 addition & 0 deletions forge-ai/src/main/java/forge/ai/SpellApiToAi.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public enum SpellApiToAi {
.put(ApiType.TwoPiles, TwoPilesAi.class)
.put(ApiType.Unattach, CannotPlayAi.class)
.put(ApiType.UnattachAll, UnattachAllAi.class)
.put(ApiType.UnlockDoor, AlwaysPlayAi.class)
.put(ApiType.Untap, UntapAi.class)
.put(ApiType.UntapAll, UntapAllAi.class)
.put(ApiType.Venture, VentureAi.class)
Expand Down
1 change: 1 addition & 0 deletions forge-core/src/main/java/forge/card/CardStateName.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum CardStateName {
RightSplit,
Adventure,
Modal,
EmptyRoom,
SpecializeW,
SpecializeU,
SpecializeB,
Expand Down
10 changes: 9 additions & 1 deletion forge-game/src/main/java/forge/game/GameAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer
// Make sure the card returns from the battlefield as the original card with two halves
resetToOriginal = true;
}
} else if (!zoneTo.is(ZoneType.Stack)) {
} else if (zoneTo.is(ZoneType.Battlefield) && c.isRoom()) {
if (c.getCastSA() == null) {
// need to set as empty room
c.updateRooms();
}
} else if (!zoneTo.is(ZoneType.Stack) && !zoneTo.is(ZoneType.Battlefield)) {
// For regular splits, recreate the original state unless the card is going to stack as one half
resetToOriginal = true;
}
Expand Down Expand Up @@ -604,6 +609,9 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer
// CR 603.6b
if (toBattlefield) {
zoneTo.saveLKI(copied, lastKnownInfo);
if (copied.isRoom() && copied.getCastSA() != null) {
copied.unlockRoom(copied.getCastSA().getActivatingPlayer(), copied.getCastSA().getCardStateName());
}
}

// only now that the LKI preserved it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum AbilityKey {
Blockers("Blockers"),
CanReveal("CanReveal"),
Card("Card"),
CardState("CardState"),
Cards("Cards"),
CardsFiltered("CardsFiltered"),
CardLKI("CardLKI"),
Expand Down
1 change: 1 addition & 0 deletions forge-game/src/main/java/forge/game/ability/ApiType.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ public enum ApiType {
TwoPiles (TwoPilesEffect.class),
Unattach (UnattachEffect.class),
UnattachAll (UnattachAllEffect.class),
UnlockDoor (UnlockDoorEffect.class),
Untap (UntapEffect.class),
UntapAll (UntapAllEffect.class),
Venture (VentureEffect.class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ public void resolve(SpellAbility sa) {

final long ts = game.getNextTimestamp();
tgtCard.addCloneState(CardFactory.getCloneStates(cardToCopy, tgtCard, sa), ts);
tgtCard.updateRooms();

// set ETB tapped of clone
if (sa.hasParam("IntoPlayTapped")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package forge.game.ability.effects;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import forge.card.CardStateName;
import forge.game.Game;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.card.CardState;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.Localizer;

public class UnlockDoorEffect extends SpellAbilityEffect {

@Override
public void resolve(SpellAbility sa) {
final Card source = sa.getHostCard();
final Game game = source.getGame();
final Player activator = sa.getActivatingPlayer();

CardCollection list;

if (sa.hasParam("Choices")) {
Player chooser = activator;
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : Localizer.getInstance().getMessage("lblChoose") + " ";

CardCollection choices = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), sa.getParam("Choices"), activator, source, sa);

Card c = chooser.getController().chooseSingleEntityForEffect(choices, sa, title, Maps.newHashMap());
if (c == null) {
return;
}
list = new CardCollection(c);
} else {
list = getTargetCards(sa);
}

for (Card c : list) {
Map<String, Object> params = Maps.newHashMap();
params.put("Object", c);
switch (sa.getParamOrDefault("Mode", "ThisDoor")) {
case "ThisDoor":
c.unlockRoom(activator, sa.getCardStateName());
break;
case "Unlock":
List<CardState> states = c.getLockedRooms().stream().map(stateName -> c.getState(stateName)).collect(Collectors.toList());

// need to choose Room Name
CardState chosen = activator.getController().chooseSingleCardState(sa, states, "Choose Room to unlock", params);
if (chosen == null) {
continue;
}
c.unlockRoom(activator, chosen.getStateName());
break;
case "LockOrUnlock":
switch (c.getLockedRooms().size()) {
case 0:
// no locked, all unlocked, can only lock door
List<CardState> unlockStates = c.getUnlockedRooms().stream().map(stateName -> c.getState(stateName)).collect(Collectors.toList());
CardState chosenUnlock = activator.getController().chooseSingleCardState(sa, unlockStates, "Choose Room to lock", params);
if (chosenUnlock == null) {
continue;
}
c.lockRoom(activator, chosenUnlock.getStateName());
break;
case 1:
// TODO check for Lock vs Unlock first?
List<CardState> bothStates = Lists.newArrayList();
bothStates.add(c.getState(CardStateName.LeftSplit));
bothStates.add(c.getState(CardStateName.RightSplit));
CardState chosenBoth = activator.getController().chooseSingleCardState(sa, bothStates, "Choose Room to lock or unlock", params);
if (chosenBoth == null) {
continue;
}
if (c.getLockedRooms().contains(chosenBoth.getStateName())) {
c.unlockRoom(activator, chosenBoth.getStateName());
} else {
c.lockRoom(activator, chosenBoth.getStateName());
}
break;
case 2:
List<CardState> lockStates = c.getLockedRooms().stream().map(stateName -> c.getState(stateName)).collect(Collectors.toList());

// need to choose Room Name
CardState chosenLock = activator.getController().chooseSingleCardState(sa, lockStates, "Choose Room to unlock", params);
if (chosenLock == null) {
continue;
}
c.unlockRoom(activator, chosenLock.getStateName());
break;
}
break;
}
}
}

}
Loading
Loading