Karn Liberated - improved game restart support in commander games (#11628, #11081);

This commit is contained in:
Oleg Agafonov 2024-01-15 05:03:06 +04:00
parent 08b99fcbf7
commit 482a56f3ea
2 changed files with 22 additions and 21 deletions

View file

@ -11,7 +11,6 @@ import mage.constants.*;
import mage.game.ExileZone; import mage.game.ExileZone;
import mage.game.Game; import mage.game.Game;
import mage.game.GameImpl; import mage.game.GameImpl;
import mage.game.command.Commander;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentImpl; import mage.game.permanent.PermanentImpl;
@ -79,14 +78,14 @@ class KarnLiberatedEffect extends OneShotEffect {
if (sourceObject == null) { if (sourceObject == null) {
return false; return false;
} }
List<Card> exiledCards = new ArrayList<>(); List<Card> keepExiled = new ArrayList<>();
for (ExileZone zone : game.getExile().getExileZones()) { for (ExileZone zone : game.getExile().getExileZones()) {
exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
if (zone.getId().equals(exileId)) { if (zone.getId().equals(exileId)) {
for (Card card : zone.getCards(game)) { for (Card card : zone.getCards(game)) {
if (!card.hasSubtype(SubType.AURA, game) if (!card.hasSubtype(SubType.AURA, game)
&& card.isPermanent(game)) { && card.isPermanent(game)) {
exiledCards.add(card); keepExiled.add(card);
} }
} }
} }
@ -106,32 +105,30 @@ class KarnLiberatedEffect extends OneShotEffect {
// TODO: miss copied cards? // TODO: miss copied cards?
for (Player player : game.getPlayers().values()) { for (Player player : game.getPlayers().values()) {
// TODO: why it keep old players with old data (need reset and lose call for it???)
if (player.canRespond()) { // only players alive are in the restarted game if (player.canRespond()) { // only players alive are in the restarted game
player.getGraveyard().clear(); // reset all player cards
player.getHand().clear(); // P.S. Time limits store in match player, so it will be kept for restarted game
player.getLibrary().clear();
for (Card card : game.getCards()) {
if (card.isOwnedBy(player.getId()) && !card.isCopy() // no copies
&& !player.getSideboard().contains(card.getId())
&& !exiledCards.contains(card)) {
if (game.getCommandersIds(player, CommanderCardType.ANY, false).contains(card.getId())) {
game.addCommander(new Commander(card)); // TODO: check restart and init
// no needs in initCommander call -- it's used on game startup (init)
game.setZone(card.getId(), Zone.COMMAND);
} else {
player.getLibrary().putOnTop(card, game);
}
}
}
((GameImpl) game).initPlayerDefaultWatchers(player.getId());
player.init(game); player.init(game);
// simulate GameState::addPlayer
player.useDeck(player.getMatchPlayer().getDeck(), game);
((GameImpl) game).initPlayerDefaultWatchers(player.getId());
// warning, xmage uses a deck's sideboard for commander init
// if you add commander in cheat/test mode then it will be a normal card after restart (it's not a bug)
// must use real commander decks for testing
} }
} }
for (Card card : exiledCards) {
// prepare exiled cards for moving to battlefield on new game
for (Card card : keepExiled) {
game.getState().setZone(card.getId(), Zone.EXILED); game.getState().setZone(card.getId(), Zone.EXILED);
game.getExile().add(exileId, sourceObject.getIdName(), card); game.getExile().add(exileId, sourceObject.getIdName(), card);
} }
game.addDelayedTriggeredAbility(new KarnLiberatedDelayedTriggeredAbility(exileId), source); game.addDelayedTriggeredAbility(new KarnLiberatedDelayedTriggeredAbility(exileId), source);
// start new game
game.setStartingPlayerId(source.getControllerId()); game.setStartingPlayerId(source.getControllerId());
game.start(null); game.start(null);
return true; return true;

View file

@ -1,5 +1,6 @@
package org.mage.test.commander.duel; package org.mage.test.commander.duel;
import mage.constants.CommanderCardType;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
@ -137,6 +138,9 @@ public class CastBRGCommanderTest extends CardTestCommanderDuelBase {
assertCommandZoneCount(playerB, "Daxos of Meletis", 0); assertCommandZoneCount(playerB, "Daxos of Meletis", 0);
assertPermanentCount(playerA, "Daxos of Meletis", 1); // Karn brings back the cards under the control of Karn's controller assertPermanentCount(playerA, "Daxos of Meletis", 1); // Karn brings back the cards under the control of Karn's controller
Assert.assertEquals("B commander must be on battlefield", 0, currentGame.getCommanderCardsFromCommandZone(playerB, CommanderCardType.COMMANDER_OR_OATHBREAKER).size());
Assert.assertEquals("B commander must be on battlefield", 1, currentGame.getCommanderCardsFromAnyZones(playerB, CommanderCardType.COMMANDER_OR_OATHBREAKER, Zone.BATTLEFIELD).size());
CommanderInfoWatcher watcher = currentGame.getState().getWatcher(CommanderInfoWatcher.class, playerB.getCommandersIds().iterator().next()); CommanderInfoWatcher watcher = currentGame.getState().getWatcher(CommanderInfoWatcher.class, playerB.getCommandersIds().iterator().next());
Assert.assertEquals("Watcher is reset to 0 commander damage", 0, watcher.getDamageToPlayer().size()); Assert.assertEquals("Watcher is reset to 0 commander damage", 0, watcher.getDamageToPlayer().size());
} }