Merge pull request #7499 from spjspj/master

Adding in Jumpstart Elimination Custom Tournament option.  Creator of the table will be able to upload a Jumpstart Pack text file that uses the same format as here: https://github.com/magefree/mage/blob/master/Mage/src/main/resources/jumpstart/jumpstart.txt
This commit is contained in:
spjspj 2021-02-06 00:57:25 +11:00 committed by GitHub
commit 7d267061d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 238 additions and 86 deletions

View file

@ -1,5 +1,8 @@
package mage.game.jumpstart;
import com.google.common.base.Charsets;
import com.google.common.io.CharSource;
import com.google.common.io.Resources;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.SecureRandom;
@ -7,11 +10,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.google.common.base.Charsets;
import com.google.common.io.CharSource;
import com.google.common.io.Resources;
import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardInfo;
@ -20,7 +18,7 @@ import mage.game.GameException;
public class JumpstartPoolGenerator {
/**
/**
* "Jumpstart is a new way to play Magic that mashes together themes from throughout the history of the game and
* lets you skip the deckbuilding part. Grab two boosters, shuffle them into a 40-card deck, and start playing.
* The set contains almost 500 reprints but also introduces 37 new cards that were designed to help fill out some
@ -30,7 +28,7 @@ public class JumpstartPoolGenerator {
* symbol, while new cards and other reprints will have the Jumpstart symbol. Reprints have a Post-M15 card frame.
* The new cards and cards with new art are numbered #1/78 to #78/78 (40 basic lands, TBA common, TBA uncommon,
* TBA rare, and TBA mythic rare). The other reprints with the Jumpstart expansion symbol are numbered #79 to 495."
*
*
* "Jumpstart is sold in 20-card boosters, and booster boxes contain 24 boosters.[9] All 20 cards in a booster fit a
* theme, and most themes are mono-color and have multiple variations of cards included in the pack, totaling 121
* different possible pack contents. Special "Mythic Rare" packs don't have variations at all, but just one possible
@ -42,46 +40,69 @@ public class JumpstartPoolGenerator {
* themed land art created for the set. The booster pack is wrapped like a regular pack, but the set of cards is
* packed in an additional plastic wrap, with a face card (the "Pack Summary card") that indicates the theme and
* the color of the half-deck."
*
* Source: https://mtg.gamepedia.com/Jumpstart
*
*
* Source: https://mtg.gamepedia.com/Jumpstart
*
* Announcement: https://magic.wizards.com/en/articles/archive/news/introducing-jumpstart-new-way-play-magic-2020-02-20
* Card Pool: https://magic.wizards.com/en/articles/archive/card-image-gallery/jumpstart
* Deck Lists: https://magic.wizards.com/en/articles/archive/feature/jumpstart-decklists-2020-06-18
*/
*/
private static final String RESOURCE_NAME = "jumpstart/jumpstart.txt";
private static final List<JumpstartPack> JUMPSTART_PACKS;
private static final String RESOURCE_NAME = "jumpstart/jumpstart.txt";
private static final List<JumpstartPack> JUMPSTART_PACKS;
static {
try {
CharSource source = Resources.asCharSource(Resources.getResource(RESOURCE_NAME), Charsets.UTF_8);
List<JumpstartPack> packs = new ArrayList<>();
JumpstartPack pack = new JumpstartPack();
packs.add(pack);
for (String line : source.readLines()) {
if (line.isEmpty()) {
if (!pack.isEmpty()) {
pack = new JumpstartPack();
packs.add(pack);
}
} else if (line.startsWith("#")) {
// skip comment
} else {
String[] ls = line.split(" ", 4);
int quantity = Integer.parseInt(ls[0]);
for (int i = 0; i < quantity; i++) {
pack.add(new DeckCardInfo(ls[3], ls[2], ls[1]));
}
}
}
JUMPSTART_PACKS = Collections.unmodifiableList(packs);
} catch (IOException e) {
throw new UncheckedIOException(e);
static {
List<JumpstartPack> packs = getPacks ("", true);
JUMPSTART_PACKS = Collections.unmodifiableList(packs);
}
}
/* Notes
private static List<JumpstartPack> getPacks(String jumpstartPacks, boolean useDefault) {
try {
CharSource source;
if (useDefault) {
source = Resources.asCharSource(Resources.getResource(RESOURCE_NAME), Charsets.UTF_8);
} else {
source = CharSource.wrap(jumpstartPacks);
}
List<JumpstartPack> packs = new ArrayList<>();
JumpstartPack pack = new JumpstartPack();
packs.add(pack);
for (String line : source.readLines()) {
if (line.isEmpty()) {
if (!pack.isEmpty()) {
pack = new JumpstartPack();
packs.add(pack);
}
} else if (line.startsWith("#")) {
// skip comment
} else {
String[] ls = line.split(" ", 4);
int quantity = Integer.parseInt(ls[0]);
for (int i = 0; i < quantity; i++) {
pack.add(new DeckCardInfo(ls[3], ls[2], ls[1]));
}
}
}
return packs;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private static Set<Card> doGeneratePool(List<JumpstartPack> packs) {
try {
DeckCardLists list = new DeckCardLists();
SecureRandom random = new SecureRandom();
for (int i = 0; i < 2; i++) {
int index = random.nextInt(packs.size());
list.getCards().addAll(packs.get(index).getCards());
}
return Deck.load(list, false, false).getCards();
} catch (GameException e) {
throw new RuntimeException(e);
}
}
/* Notes
*
* 1) the pools generated by this method are for how the prerelease will be played (see https://mtg.gamepedia.com/Jumpstart#Events)
* In order to support the 4 pack version, xmage would need to support editing multiple decks and some Duo format
@ -93,37 +114,35 @@ public class JumpstartPoolGenerator {
*
* 3) this does not attempt to add an additional rare 1/3 of the time as described here:
* https://mtg.gamepedia.com/Jumpstart#Marketing
*/
public static Set<Card> generatePool() {
try {
DeckCardLists list = new DeckCardLists();
SecureRandom random = new SecureRandom();
for (int i = 0; i < 2; i++) {
int index = random.nextInt(JUMPSTART_PACKS.size());
list.getCards().addAll(JUMPSTART_PACKS.get(index).getCards());
}
return Deck.load(list, false, false).getCards();
} catch (GameException e) {
throw new RuntimeException(e);
}
}
public static class JumpstartPack {
private final List<DeckCardInfo> cards = new ArrayList<>();
public void add(DeckCardInfo card) {
cards.add(card);
*/
public static Set<Card> generatePool() {
return doGeneratePool(JUMPSTART_PACKS);
}
public boolean isEmpty() {
return cards.isEmpty();
public static Set<Card> generatePool(String userJumpstartPacks) {
if (userJumpstartPacks == null || userJumpstartPacks.length() > 300000) {
return generatePool();
}
List<JumpstartPack> packs = getPacks(userJumpstartPacks, false);
return doGeneratePool(packs);
}
public List<DeckCardInfo> getCards() {
return Collections.unmodifiableList(cards);
}
public static class JumpstartPack {
}
private final List<DeckCardInfo> cards = new ArrayList<>();
public void add(DeckCardInfo card) {
cards.add(card);
}
public boolean isEmpty() {
return cards.isEmpty();
}
public List<DeckCardInfo> getCards() {
return Collections.unmodifiableList(cards);
}
}
}

View file

@ -1,11 +1,10 @@
package mage.game.tournament;
import mage.cards.decks.Deck;
import mage.game.draft.DraftCube;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import mage.cards.decks.Deck;
import mage.game.draft.DraftCube;
/**
* @author BetaSteward_at_googlemail.com
@ -20,6 +19,20 @@ public class LimitedOptions implements Serializable {
protected boolean isRandom;
protected boolean isRichMan;
protected Deck cubeFromDeck;
protected String jumpstartPacks;
// Eg of jumpstartPacks - uploaded by user
/*
# Minions
1 JMP 236 Ghoulcaller Gisa
1 JMP 226 Dutiful Attendant
1 M21 126 Village Rites
# Phyrexian
1 JMP 278 Sheoldred, Whispering One
1 JMP 227 Entomber Exarch
1 JMP 265 Phyrexian Gargantua
*/
protected boolean isJumpstart;
public List<String> getSetCodes() {
@ -50,6 +63,14 @@ public class LimitedOptions implements Serializable {
return cubeFromDeck;
}
public void setJumpstartPacks(String jumpstartPacks) {
this.jumpstartPacks = jumpstartPacks;
}
public String getJumpstartPacks() {
return jumpstartPacks;
}
public DraftCube getDraftCube() {
return draftCube;
}

View file

@ -1,4 +1,3 @@
package mage.game.tournament;
import java.util.ArrayList;
@ -12,9 +11,6 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.log4j.Logger;
import mage.cards.ExpansionSet;
import mage.cards.decks.Deck;
import mage.constants.TournamentPlayerState;
@ -37,6 +33,7 @@ import mage.game.result.ResultProtos.TourneyRoundProto;
import mage.players.Player;
import mage.players.PlayerType;
import mage.util.RandomUtil;
import org.apache.log4j.Logger;
/**
*
@ -411,7 +408,11 @@ public abstract class TournamentImpl implements Tournament {
player.getDeck().getSideboard().addAll(cube.createBooster());
}
} else if (options.getLimitedOptions().getIsJumpstart()) {
player.getDeck().getCards().addAll(JumpstartPoolGenerator.generatePool());
if (options.getLimitedOptions().jumpstartPacks == null) {
player.getDeck().getCards().addAll(JumpstartPoolGenerator.generatePool());
} else {
player.getDeck().getCards().addAll(JumpstartPoolGenerator.generatePool(options.getLimitedOptions().jumpstartPacks));
}
} else {
for (ExpansionSet set : sets) {
player.getDeck().getSideboard().addAll(set.createBooster());