Basic groundwork for extra decks (contraptions, attractions) (#10378)

* extra deck cards not counted in deck size

* extra deck handling in deckbuilder

* move responsibility for extraDeckCard boolean to CardImpl

* remove redundant field copy
This commit is contained in:
Artemis Kearney 2023-08-06 20:06:32 -05:00 committed by GitHub
parent 978ebfc873
commit 9ba0da00ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 97 additions and 47 deletions

View file

@ -1920,7 +1920,15 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
} }
private void updateCounts() { private void updateCounts() {
deckNameAndCountLabel.setText(role.getName() + " - " + allCards.size()); int extraDeckCount = allCards.stream()
.filter(c -> c.isExtraDeckCard())
.collect(Collectors.toSet())
.size();
int maindeckCount = allCards.size() - extraDeckCount;
deckNameAndCountLabel.setText(role.getName() + " - " + maindeckCount + (
extraDeckCount > 0 ? " (" + extraDeckCount + ")"
: ""
));
creatureCountLabel.setText(String.valueOf(creatureCounter.get())); creatureCountLabel.setText(String.valueOf(creatureCounter.get()));
landCountLabel.setText(String.valueOf(landCounter.get())); landCountLabel.setText(String.valueOf(landCounter.get()));
for (CardType cardType : selectByTypeButtons.keySet()) { for (CardType cardType : selectByTypeButtons.keySet()) {

View file

@ -473,7 +473,7 @@ public class AddLandDialog extends MageDialog {
private void autoAddLands() { private void autoAddLands() {
int deckSize = ((Number) spnDeckSize.getValue()).intValue(); int deckSize = ((Number) spnDeckSize.getValue()).intValue();
int[] lands = DeckBuildUtils.landCountSuggestion(deckSize, deck.getCards()); int[] lands = DeckBuildUtils.landCountSuggestion(deckSize, deck.getMaindeckCards());
spnPlains.setValue(lands[0]); spnPlains.setValue(lands[0]);
spnIsland.setValue(lands[1]); spnIsland.setValue(lands[1]);
spnSwamp.setValue(lands[2]); spnSwamp.setValue(lands[2]);

View file

@ -77,8 +77,8 @@ public final class DeckBuilder {
addCardsToDeck(remainingCards, min, max, deckCount[index]); addCardsToDeck(remainingCards, min, max, deckCount[index]);
min = max + 1; min = max + 1;
} }
addCardsToDeck(remainingCards, 0, 4, deckSpells - deck.getCards().size()); addCardsToDeck(remainingCards, 0, 4, deckSpells - deck.getMaindeckCards().size());
addCardsToDeck(remainingCards, 5, 10, deckSpells - deck.getCards().size()); addCardsToDeck(remainingCards, 5, 10, deckSpells - deck.getMaindeckCards().size());
addLandsToDeck(allowedColors, setsToUse, landCardPool, callback); addLandsToDeck(allowedColors, setsToUse, landCardPool, callback);
Deck returnedDeck = deck; Deck returnedDeck = deck;
@ -174,7 +174,7 @@ public final class DeckBuilder {
} }
// Add optimal basic lands to deck. // Add optimal basic lands to deck.
while (deck.getCards().size() < deckSize) { while (deck.getMaindeckCards().size() < deckSize) {
ColoredManaSymbol bestColor = null; ColoredManaSymbol bestColor = null;
//Default to a color in the allowed colors //Default to a color in the allowed colors
if (allowedColors != null && !allowedColors.isEmpty()) { if (allowedColors != null && !allowedColors.isEmpty()) {

View file

@ -88,6 +88,7 @@ public class CardView extends SimpleCardView {
protected CardView ability; protected CardView ability;
protected int imageNumber; protected int imageNumber;
protected boolean extraDeckCard;
protected boolean transformable; // can toggle one card side to another (transformable cards, modal double faces) protected boolean transformable; // can toggle one card side to another (transformable cards, modal double faces)
protected CardView secondCardFace; protected CardView secondCardFace;
protected boolean transformed; protected boolean transformed;
@ -198,6 +199,7 @@ public class CardView extends SimpleCardView {
this.isToken = cardView.isToken; this.isToken = cardView.isToken;
this.ability = cardView.ability; // reference, not copy this.ability = cardView.ability; // reference, not copy
this.extraDeckCard = cardView.extraDeckCard;
this.transformable = cardView.transformable; this.transformable = cardView.transformable;
this.secondCardFace = cardView.secondCardFace == null ? null : new CardView(cardView.secondCardFace); this.secondCardFace = cardView.secondCardFace == null ? null : new CardView(cardView.secondCardFace);
this.transformed = cardView.transformed; this.transformed = cardView.transformed;
@ -500,6 +502,8 @@ public class CardView extends SimpleCardView {
this.isToken = false; this.isToken = false;
} }
this.extraDeckCard = card.isExtraDeckCard();
// transformable, double faces cards // transformable, double faces cards
this.transformable = card.isTransformable(); this.transformable = card.isTransformable();
@ -1246,6 +1250,9 @@ public class CardView extends SimpleCardView {
return typeText.toString(); return typeText.toString();
} }
public boolean isExtraDeckCard() {
return this.extraDeckCard;
}
public boolean isLand() { public boolean isLand() {
return cardTypes.contains(CardType.LAND); return cardTypes.contains(CardType.LAND);
} }

View file

@ -186,11 +186,11 @@ public abstract class AbstractCommander extends Constructed {
valid = false; valid = false;
} }
if (companion != null && deck.getCards().size() + deck.getSideboard().size() != 101) { if (companion != null && deck.getMaindeckCards().size() + deck.getSideboard().size() != 101) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 101 + " cards (companion doesn't count for deck size): has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 101 + " cards (companion doesn't count for deck size): has " + (deck.getMaindeckCards().size() + deck.getSideboard().size()) + " cards");
valid = false; valid = false;
} else if (companion == null && deck.getCards().size() + deck.getSideboard().size() != 100) { } else if (companion == null && deck.getMaindeckCards().size() + deck.getSideboard().size() != 100) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 100 + " cards: has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 100 + " cards: has " + (deck.getMaindeckCards().size() + deck.getSideboard().size()) + " cards");
valid = false; valid = false;
} }

View file

@ -103,8 +103,8 @@ public class AusHighlander extends Constructed {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
if (deck.getCards().size() != getDeckMinSize()) { if (deck.getMaindeckCards().size() != getDeckMinSize()) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " singleton cards: has " + (deck.getCards().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " singleton cards: has " + (deck.getMaindeckCards().size()) + " cards");
valid = false; valid = false;
} }
if (deck.getSideboard().size() > 15) { if (deck.getSideboard().size() > 15) {

View file

@ -89,11 +89,11 @@ public class Brawl extends Constructed {
} }
} }
if (companion != null && deck.getCards().size() + deck.getSideboard().size() != getDeckMinSize() + 1) { if (companion != null && deck.getMaindeckCards().size() + deck.getSideboard().size() != getDeckMinSize() + 1) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + (getDeckMinSize() + 1) + " cards (companion doesn't count in deck size requirement): has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + (getDeckMinSize() + 1) + " cards (companion doesn't count in deck size requirement): has " + (deck.getMaindeckCards().size() + deck.getSideboard().size()) + " cards");
valid = false; valid = false;
} else if (companion == null && deck.getCards().size() + deck.getSideboard().size() != getDeckMinSize()) { } else if (companion == null && deck.getMaindeckCards().size() + deck.getSideboard().size() != getDeckMinSize()) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " cards: has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " cards: has " + (deck.getMaindeckCards().size() + deck.getSideboard().size()) + " cards");
valid = false; valid = false;
} }

View file

@ -73,8 +73,8 @@ public class CanadianHighlander extends Constructed {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
if (deck.getCards().size() < 100) { if (deck.getMaindeckCards().size() < 100) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain 100 or more singleton cards: has " + (deck.getCards().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain 100 or more singleton cards: has " + (deck.getMaindeckCards().size()) + " cards");
valid = false; valid = false;
} }

View file

@ -78,8 +78,8 @@ public class EuropeanHighlander extends Constructed {
// Parent class checks the banned list // Parent class checks the banned list
boolean valid = super.validate(deck); boolean valid = super.validate(deck);
if (deck.getCards().size() < 100) { if (deck.getMaindeckCards().size() < 100) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain 100 or more singleton cards: has " + (deck.getCards().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain 100 or more singleton cards: has " + (deck.getMaindeckCards().size()) + " cards");
valid = false; valid = false;
} }

View file

@ -32,8 +32,8 @@ public class Freeform extends DeckValidator {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
// http://magic.wizards.com/en/gameinfo/gameplay/formats/freeform // http://magic.wizards.com/en/gameinfo/gameplay/formats/freeform
if (deck.getCards().size() < getDeckMinSize()) { if (deck.getMaindeckCards().size() < getDeckMinSize()) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getCards().size() + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getMaindeckCards().size() + " cards");
valid = false; valid = false;
} }
return valid; return valid;

View file

@ -33,8 +33,8 @@ public class Momir extends DeckValidator {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
if (deck.getCards().size() != getDeckMinSize()) { if (deck.getMaindeckCards().size() != getDeckMinSize()) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " cards: has " + deck.getCards().size() + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " cards: has " + deck.getMaindeckCards().size() + " cards");
valid = false; valid = false;
} }

View file

@ -84,8 +84,8 @@ public class Oathbreaker extends Constructed {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
if (deck.getCards().size() + deck.getSideboard().size() != 60) { if (deck.getMaindeckCards().size() + deck.getSideboard().size() != 60) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 60 + " cards: has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 60 + " cards: has " + (deck.getMaindeckCards().size() + deck.getSideboard().size()) + " cards");
valid = false; valid = false;
} }

View file

@ -105,8 +105,8 @@ public class TinyLeaders extends Constructed {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
if (deck.getCards().size() != getDeckMinSize()) { if (deck.getMaindeckCards().size() != getDeckMinSize()) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " cards: has " + deck.getCards().size() + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + getDeckMinSize() + " cards: has " + deck.getMaindeckCards().size() + " cards");
valid = false; valid = false;
} }

View file

@ -31,8 +31,8 @@ public class Limited extends DeckValidator {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
//20091005 - 100.2b //20091005 - 100.2b
if (deck.getCards().size() < getDeckMinSize()) { if (deck.getMaindeckCards().size() < getDeckMinSize()) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getCards().size() + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getMaindeckCards().size() + " cards");
valid = false; valid = false;
} }
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();

View file

@ -2257,7 +2257,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Card> sortedCards = new ArrayList<>(cardPool); List<Card> sortedCards = new ArrayList<>(cardPool);
if (!sortedCards.isEmpty()) { if (!sortedCards.isEmpty()) {
while (deck.getCards().size() < DECK_SIZE) { while (deck.getMaindeckCards().size() < DECK_SIZE) {
deck.getCards().add(sortedCards.get(RandomUtil.nextInt(sortedCards.size()))); deck.getCards().add(sortedCards.get(RandomUtil.nextInt(sortedCards.size())));
} }
return deck; return deck;
@ -2287,7 +2287,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
// get top cards // get top cards
int cardNum = 0; int cardNum = 0;
while (deck.getCards().size() < DECK_CARDS_COUNT && sortedCards.size() > cardNum) { while (deck.getMaindeckCards().size() < DECK_CARDS_COUNT && sortedCards.size() > cardNum) {
Card card = sortedCards.get(cardNum); Card card = sortedCards.get(cardNum);
if (!card.isBasic()) { if (!card.isBasic()) {
deck.getCards().add(card); deck.getCards().add(card);
@ -2349,7 +2349,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
// adds remaining lands (most popular name) // adds remaining lands (most popular name)
addBasicLands(deck, mostLandName, DECK_SIZE - deck.getCards().size()); addBasicLands(deck, mostLandName, DECK_SIZE - deck.getMaindeckCards().size());
return deck; return deck;
} }
@ -2359,7 +2359,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
DeckValidator deckValidator = DeckValidatorFactory.instance.createDeckValidator(tournament.getOptions().getMatchOptions().getDeckType()); DeckValidator deckValidator = DeckValidatorFactory.instance.createDeckValidator(tournament.getOptions().getMatchOptions().getDeckType());
int deckMinSize = deckValidator != null ? deckValidator.getDeckMinSize() : 0; int deckMinSize = deckValidator != null ? deckValidator.getDeckMinSize() : 0;
if (deck != null && deck.getCards().size() < deckMinSize && !deck.getSideboard().isEmpty()) { if (deck != null && deck.getMaindeckCards().size() < deckMinSize && !deck.getSideboard().isEmpty()) {
if (chosenColors == null) { if (chosenColors == null) {
for (Card card : deck.getSideboard()) { for (Card card : deck.getSideboard()) {
rememberPick(card, RateCard.rateCard(card, null)); rememberPick(card, RateCard.rateCard(card, null));

View file

@ -43,8 +43,8 @@ public class PlayGameTest extends MageTestBase {
// Deck deck = Deck.load(Sets.loadDeck("RB Aggro.dck")); // Deck deck = Deck.load(Sets.loadDeck("RB Aggro.dck"));
Deck deck = generateRandomDeck(); Deck deck = generateRandomDeck();
if (deck.getCards().size() < DECK_SIZE) { if (deck.getMaindeckCards().size() < DECK_SIZE) {
throw new IllegalArgumentException("Couldn't load deck, deck size = " + deck.getCards().size() + ", but must be " + DECK_SIZE); throw new IllegalArgumentException("Couldn't load deck, deck size = " + deck.getMaindeckCards().size() + ", but must be " + DECK_SIZE);
} }
game.addPlayer(computerA, deck); game.addPlayer(computerA, deck);
game.loadCards(deck.getCards(), computerA.getId()); game.loadCards(deck.getCards(), computerA.getId());
@ -53,8 +53,8 @@ public class PlayGameTest extends MageTestBase {
// Player playerB = createPlayer("ComputerB", "Computer - mad"); // Player playerB = createPlayer("ComputerB", "Computer - mad");
// Deck deck2 = Deck.load(Sets.loadDeck("RB Aggro.dck")); // Deck deck2 = Deck.load(Sets.loadDeck("RB Aggro.dck"));
Deck deck2 = generateRandomDeck(); Deck deck2 = generateRandomDeck();
if (deck2.getCards().size() < DECK_SIZE) { if (deck2.getMaindeckCards().size() < DECK_SIZE) {
throw new IllegalArgumentException("Couldn't load deck, deck size = " + deck2.getCards().size() + ", but must be " + DECK_SIZE); throw new IllegalArgumentException("Couldn't load deck, deck size = " + deck2.getMaindeckCards().size() + ", but must be " + DECK_SIZE);
} }
game.addPlayer(computerB, deck2); game.addPlayer(computerB, deck2);
game.loadCards(deck2.getCards(), computerB.getId()); game.loadCards(deck2.getCards(), computerB.getId());

View file

@ -219,8 +219,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
} }
Deck deck = Deck.load(list, false, false, loadedCardInfo); Deck deck = Deck.load(list, false, false, loadedCardInfo);
logger.debug("Done!"); logger.debug("Done!");
if (deck.getCards().size() < 40) { if (deck.getMaindeckCards().size() < 40) {
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck.getCards().size()); throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck.getMaindeckCards().size());
} }
game.loadCards(deck.getCards(), player.getId()); game.loadCards(deck.getCards(), player.getId());

View file

@ -144,7 +144,7 @@ public class RandomTest {
Player player = new HumanPlayer("random", RangeOfInfluence.ALL, 1); Player player = new HumanPlayer("random", RangeOfInfluence.ALL, 1);
Game game = new TwoPlayerDuel(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, MulliganType.GAME_DEFAULT.getMulligan(0), 50); Game game = new TwoPlayerDuel(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, MulliganType.GAME_DEFAULT.getMulligan(0), 50);
Deck deck = DeckTestUtils.buildRandomDeck("WGUBR", false, "GRN"); Deck deck = DeckTestUtils.buildRandomDeck("WGUBR", false, "GRN");
player.getLibrary().addAll(deck.getCards(), game); player.getLibrary().addAll(deck.getMaindeckCards(), game);
// multiple cards analyze // multiple cards analyze
for (int i = 0; i < player.getLibrary().size(); i++) { for (int i = 0; i < player.getLibrary().size(); i++) {

View file

@ -584,6 +584,8 @@ public class VerifyCardDataTest {
} }
if ((deckCards.getCards().size() + deckCards.getSideboard().size()) < 10) { if ((deckCards.getCards().size() + deckCards.getSideboard().size()) < 10) {
// note: does not check whether cards are extra deck cards (contraptions/attractions);
// may succeed for decks with such cards when it should fail
errorsList.add("Error: sample deck contains too little cards (" + deckCards.getSideboard().size() + ") " + deckName); errorsList.add("Error: sample deck contains too little cards (" + deckCards.getSideboard().size() + ") " + deckName);
totalErrorFiles++; totalErrorFiles++;
continue; continue;

View file

@ -80,6 +80,13 @@ public interface Card extends MageObject {
return null; return null;
} }
/**
* Is this an extra deck card? (such as contraptions and attractions)
* @return true if this is an extra deck card, false otherwise
*/
default boolean isExtraDeckCard() {
return false;
}
void assignNewId(); void assignNewId();
void addInfo(String key, String value, Game game); void addInfo(String key, String value, Game game);

View file

@ -53,6 +53,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
protected boolean usesVariousArt = false; protected boolean usesVariousArt = false;
protected boolean morphCard; protected boolean morphCard;
protected List<UUID> attachments = new ArrayList<>(); protected List<UUID> attachments = new ArrayList<>();
protected boolean extraDeckCard = false;
protected CardImpl(UUID ownerId, CardSetInfo setInfo, CardType[] cardTypes, String costs) { protected CardImpl(UUID ownerId, CardSetInfo setInfo, CardType[] cardTypes, String costs) {
this(ownerId, setInfo, cardTypes, costs, SpellAbilityType.BASE); this(ownerId, setInfo, cardTypes, costs, SpellAbilityType.BASE);
@ -130,6 +131,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
flipCardName = card.flipCardName; flipCardName = card.flipCardName;
usesVariousArt = card.usesVariousArt; usesVariousArt = card.usesVariousArt;
morphCard = card.morphCard; morphCard = card.morphCard;
extraDeckCard = card.extraDeckCard;
this.attachments.addAll(card.attachments); this.attachments.addAll(card.attachments);
} }
@ -952,4 +954,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
// Only way to get here is if none of the effects on the card care about mana color. // Only way to get here is if none of the effects on the card care about mana color.
return false; return false;
} }
@Override
public boolean isExtraDeckCard() {
return extraDeckCard;
}
} }

View file

@ -214,8 +214,8 @@ public class Constructed extends DeckValidator {
boolean valid = true; boolean valid = true;
errorsList.clear(); errorsList.clear();
//20091005 - 100.2a //20091005 - 100.2a
if (deck.getCards().size() < getDeckMinSize()) { if (deck.getMaindeckCards().size() < getDeckMinSize()) {
addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getCards().size() + " cards"); addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getMaindeckCards().size() + " cards");
valid = false; valid = false;
} }
//20130713 - 100.4a //20130713 - 100.4a

View file

@ -227,6 +227,13 @@ public class Deck implements Serializable, Copyable<Deck> {
return cards; return cards;
} }
public Set<Card> getMaindeckCards() {
return cards
.stream()
.filter(card -> !card.isExtraDeckCard())
.collect(Collectors.toSet());
}
public Card findCard(UUID cardId) { public Card findCard(UUID cardId) {
return cards return cards
.stream() .stream()

View file

@ -88,6 +88,8 @@ public class MockCard extends CardImpl {
for (String ruleText : card.getRules()) { for (String ruleText : card.getRules()) {
this.addAbility(textAbilityFromString(ruleText)); this.addAbility(textAbilityFromString(ruleText));
} }
this.extraDeckCard = card.isExtraDeckCard();
} }
protected MockCard(final MockCard card) { protected MockCard(final MockCard card) {

View file

@ -19,7 +19,6 @@ import java.util.List;
* @author North * @author North
*/ */
public class MockSplitCard extends SplitCard { public class MockSplitCard extends SplitCard {
public MockSplitCard(CardInfo card) { public MockSplitCard(CardInfo card) {
super(null, new CardSetInfo(card.getName(), card.getSetCode(), card.getCardNumber(), card.getRarity()), super(null, new CardSetInfo(card.getName(), card.getSetCode(), card.getCardNumber(), card.getRarity()),
card.getTypes().toArray(new CardType[0]), card.getTypes().toArray(new CardType[0]),
@ -62,6 +61,8 @@ public class MockSplitCard extends SplitCard {
this.rightHalfCard = new MockSplitCardHalf(rightHalf); this.rightHalfCard = new MockSplitCardHalf(rightHalf);
((SplitCardHalf) this.rightHalfCard).setParentCard(this); ((SplitCardHalf) this.rightHalfCard).setParentCard(this);
} }
this.extraDeckCard = card.isExtraDeckCard();
} }
protected MockSplitCard(final MockSplitCard card) { protected MockSplitCard(final MockSplitCard card) {

View file

@ -113,6 +113,8 @@ public class CardInfo {
protected String modalDoubleFacedSecondSideName; protected String modalDoubleFacedSecondSideName;
@DatabaseField @DatabaseField
protected String meldsToCardName; protected String meldsToCardName;
@DatabaseField
protected boolean isExtraDeckCard;
// if you add new field with card side name then update CardRepository.addNewNames too // if you add new field with card side name then update CardRepository.addNewNames too
@ -232,6 +234,8 @@ public class CardInfo {
// Starting loyalty // Starting loyalty
this.startingLoyalty = CardUtil.convertLoyaltyOrDefense(card.getStartingLoyalty()); this.startingLoyalty = CardUtil.convertLoyaltyOrDefense(card.getStartingLoyalty());
this.startingDefense = CardUtil.convertLoyaltyOrDefense(card.getStartingDefense()); this.startingDefense = CardUtil.convertLoyaltyOrDefense(card.getStartingDefense());
this.isExtraDeckCard = card.isExtraDeckCard();
} }
public Card getCard() { public Card getCard() {
@ -482,4 +486,8 @@ public class CardInfo {
public String toString() { public String toString() {
return String.format("%s (%s, %s)", getName(), getSetCode(), getCardNumber()); return String.format("%s (%s, %s)", getName(), getSetCode(), getCardNumber());
} }
public boolean isExtraDeckCard() {
return isExtraDeckCard;
}
} }

View file

@ -95,7 +95,7 @@ public class MatchPlayer implements Serializable {
public Deck generateDeck(DeckValidator deckValidator) { public Deck generateDeck(DeckValidator deckValidator) {
// auto complete deck // auto complete deck
while (deck.getCards().size() < deckValidator.getDeckMinSize() && !deck.getSideboard().isEmpty()) { while (deck.getMaindeckCards().size() < deckValidator.getDeckMinSize() && !deck.getSideboard().isEmpty()) {
Card card = deck.getSideboard().iterator().next(); Card card = deck.getSideboard().iterator().next();
deck.getCards().add(card); deck.getCards().add(card);
deck.getSideboard().remove(card); deck.getSideboard().remove(card);

View file

@ -105,8 +105,8 @@ public class TournamentPlayer {
If user fails to submit deck on time, submit deck as is if meets minimum size, If user fails to submit deck on time, submit deck as is if meets minimum size,
else add basic lands per suggested land counts else add basic lands per suggested land counts
*/ */
if (deck.getCards().size() < minDeckSize) { if (deck.getMaindeckCards().size() < minDeckSize) {
int[] lands = DeckBuildUtils.landCountSuggestion(minDeckSize, deck.getCards()); int[] lands = DeckBuildUtils.landCountSuggestion(minDeckSize, deck.getMaindeckCards());
Set<String> landSets = TournamentUtil.getLandSetCodeForDeckSets(deck.getExpansionSetCodes()); Set<String> landSets = TournamentUtil.getLandSetCodeForDeckSets(deck.getExpansionSetCodes());
deck.getCards().addAll(TournamentUtil.getLands("Plains", lands[0], landSets)); deck.getCards().addAll(TournamentUtil.getLands("Plains", lands[0], landSets));
deck.getCards().addAll(TournamentUtil.getLands("Island", lands[1], landSets)); deck.getCards().addAll(TournamentUtil.getLands("Island", lands[1], landSets));

View file

@ -388,11 +388,12 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override @Override
public void useDeck(Deck deck, Game game) { public void useDeck(Deck deck, Game game) {
library.clear(); library.clear();
library.addAll(deck.getCards(), game); library.addAll(deck.getMaindeckCards(), game);
sideboard.clear(); sideboard.clear();
for (Card card : deck.getSideboard()) { for (Card card : deck.getSideboard()) {
sideboard.add(card); sideboard.add(card);
} }
//TODO ARTI initialize extra decks here!
} }
/** /**