diff --git a/main.py b/main.py index d0e2683..2760996 100644 --- a/main.py +++ b/main.py @@ -1,22 +1,39 @@ +import sys +import os +sys.path.append(f'{os.getcwd()}/src') + import domdiv.main -base_args = [ - "--papersize", "A4", - "--language", "de", - "--size", "9.5x6.25", - "--types", - "--tab-side", "left-alternate", - "--tabwidth", "4.0", - "--tab-name-align", "center", - "--order", "cost", - "--expansion-dividers", - "--centre-expansion-dividers", - "--expansion-reset-tabs", - "--expansions", "base", "alchemy", "cornucopia", "dark ages", "dominion2ndEdition", "empires", "promo", - "--no-trash", - "--group-kingdom", - "--group-special", -] +HELP = False + +if HELP: + base_args = ["--help"] +else: + base_args = [ + "--papersize", "A4", + "--language", "de", + "--size", "9.5x6.25", + "--types", + "--tab-side", "left-alternate", + "--tabwidth", "4.0", + "--tab-name-align", "center", + "--order", "cost", + "--expansion-dividers", + "--centre-expansion-dividers", + "--expansion-reset-tabs", + "--expansions", "base", + #"alchemy", "cornucopia", "dark ages", "dominion2ndEdition", "empires", + "prosperity", "promo", + + "--no-trash", + "--group-kingdom", + "--group-special", + + "--curse10", + "--start-decks", + "--victory8_4split", + "--only-promo", "Prince", "Sauna", "Courtier" + ] opts = domdiv.main.parse_opts(base_args) opts = domdiv.main.clean_opts(opts) domdiv.main.generate(opts) diff --git a/src/domdiv/card_db/cards_db.json b/src/domdiv/card_db/cards_db.json index 0e52d45..ec2a756 100644 --- a/src/domdiv/card_db/cards_db.json +++ b/src/domdiv/card_db/cards_db.json @@ -3448,6 +3448,7 @@ { "card_tag": "Courtier", "cardset_tags": [ + "promo", "intrigue2ndEdition", "intrigue2ndEditionUpgrade" ], diff --git a/src/domdiv/card_db/de/cards_de.json b/src/domdiv/card_db/de/cards_de.json index 9885fa6..a1535dc 100644 --- a/src/domdiv/card_db/de/cards_de.json +++ b/src/domdiv/card_db/de/cards_de.json @@ -407,7 +407,7 @@ "Start Deck": { "description": "Startkarten jedes Spielers:7 Kupfer Karten3 Anwesen Karten", "extra": "", - "name": "Startkarten jedes Spielers" + "name": "Startkarten" }, "Trash": { "description": "Müllstapel.", @@ -416,7 +416,7 @@ }, "Colony": { "description": "10 <*VP*>", - "extra": "Diese Karte ist eine Basiskarte und keine Königreichkarte. Spielt ihr ausschließlich mit Königreichkarten aus Blütezeit, wird diese Karte zusätzlich zu den Basis-Punktekarten ANWESEN, HERZOGTUM und PROVINZ in der Spielvorbereitung in den Vorrat gelegt. Bei Spielen mit Königreichkarten aus verschiedenen Editionen oder Erweiterungen entscheidet vor Spielbeginn, ob ihr die KOLONIE in den Vorrat legen wollt oder nicht. Achtet darauf, dass in diesem Fall das Spiel auch endet, wenn der Vorratsstapel KOLONIE leer ist.", + "extra": "2 Spieler: 8 Kolonien
3+ Spieler: 12 Kolonien", "name": "Kolonie" }, "Platinum": { diff --git a/src/domdiv/draw.py b/src/domdiv/draw.py index e358b9a..0cda9e0 100644 --- a/src/domdiv/draw.py +++ b/src/domdiv/draw.py @@ -483,6 +483,7 @@ class DividerDrawer(object): "MinionPro-Regular.ttf", "MinionPro-Bold.ttf", "MinionPro-It.ttf", + "MinionPro-Italic.ttf", "Minion Pro Regular.ttf", "Minion Pro Bold.ttf", "Minion Pro Italic.ttf", diff --git a/src/domdiv/fonts/minion-pro-bold.zip b/src/domdiv/fonts/minion-pro-bold.zip new file mode 100644 index 0000000..27c12dc Binary files /dev/null and b/src/domdiv/fonts/minion-pro-bold.zip differ diff --git a/src/domdiv/fonts/minion-pro-italic.zip b/src/domdiv/fonts/minion-pro-italic.zip new file mode 100644 index 0000000..4ff459b Binary files /dev/null and b/src/domdiv/fonts/minion-pro-italic.zip differ diff --git a/src/domdiv/fonts/minion-pro-regular.zip b/src/domdiv/fonts/minion-pro-regular.zip new file mode 100644 index 0000000..872c263 Binary files /dev/null and b/src/domdiv/fonts/minion-pro-regular.zip differ diff --git a/src/domdiv/main.py b/src/domdiv/main.py index 0572cbd..b0542fb 100644 --- a/src/domdiv/main.py +++ b/src/domdiv/main.py @@ -115,6 +115,43 @@ def get_global_groups(): GROUP_GLOBAL_CHOICES, GROUP_GLOBAL_VALID = get_global_groups() + +def load_cards(): + types_db_filepath = os.path.join("card_db", "types_db.json") + with get_resource_stream(types_db_filepath) as typefile: + Card.types = json.loads( + typefile.read().decode("utf-8"), object_hook=CardType.decode_json + ) + assert Card.types, "Could not load any card types from database" + + # extract unique types + type_list = [] + for c in Card.types: + type_list = list(set(c.getTypeNames()) | set(type_list)) + # set up the basic type translation. The actual language will be added later. + Card.type_names = {} + for t in type_list: + Card.type_names[t] = t + + # turn Card.types into a dictionary for later + Card.types = dict(((c.getTypeNames(), c) for c in Card.types)) + + # Read in the card database + card_db_filepath = os.path.join("card_db", "cards_db.json") + with get_resource_stream(card_db_filepath) as cardfile: + cards = json.loads( + cardfile.read().decode("utf-8"), object_hook=Card.decode_json + ) + assert cards, "Could not load any cards from database" + return cards + + +def get_promos(): + cards = load_cards() + return [c.card_tag for c in cards if "promo" in c.cardset_tags] + +PROMOS = get_promos() + def get_types(language="en_us"): # get a list of valid types language = language.lower() @@ -525,6 +562,12 @@ def parse_opts(cmdline_args=None): dest="start_decks", help="Include four start decks with the Base cards.", ) + group_select.add_argument( + "--victory8_4split", + action="store_true", + dest="victory8_4split", + help="Split Base victory cards into two groups of 8 and 4 cards.", + ) group_select.add_argument( "--include-blanks", type=int, @@ -585,6 +628,15 @@ def parse_opts(cmdline_args=None): ", ".join("%s" % x for x in TYPE_CHOICES) ), ) + group_select.add_argument( + "--only-promo", + nargs="*", + action="append", + dest="only_promo", + help="Limit promos. Available cards: {}".format( + ", ".join("%s" % x for x in PROMOS) + ), + ) # Divider Sleeves/Wrappers group_wrapper = parser.add_argument_group( @@ -934,6 +986,15 @@ def clean_opts(options): set([item.lower() for sublist in options.only_type_all for item in sublist]) ) + if options.only_promo is None: + # No instance given, so default to empty list + options.only_promo = [] + else: + # options.only_promo is a list of lists. Reduce to single lowercase list + options.only_promo = list( + set([item for sublist in options.only_promo for item in sublist]) + ) + if options.group_global is None: options.group_global = [] elif not any(options.group_global): @@ -1132,36 +1193,8 @@ def find_index_of_object(lst=[], attributes={}): # nothing matched return None - def read_card_data(options): - - # Read in the card types - types_db_filepath = os.path.join("card_db", "types_db.json") - with get_resource_stream(types_db_filepath) as typefile: - Card.types = json.loads( - typefile.read().decode("utf-8"), object_hook=CardType.decode_json - ) - assert Card.types, "Could not load any card types from database" - - # extract unique types - type_list = [] - for c in Card.types: - type_list = list(set(c.getTypeNames()) | set(type_list)) - # set up the basic type translation. The actual language will be added later. - Card.type_names = {} - for t in type_list: - Card.type_names[t] = t - - # turn Card.types into a dictionary for later - Card.types = dict(((c.getTypeNames(), c) for c in Card.types)) - - # Read in the card database - card_db_filepath = os.path.join("card_db", "cards_db.json") - with get_resource_stream(card_db_filepath) as cardfile: - cards = json.loads( - cardfile.read().decode("utf-8"), object_hook=Card.decode_json - ) - assert cards, "Could not load any cards from database" + cards = load_cards() set_db_filepath = os.path.join("card_db", "sets_db.json") with get_resource_stream(set_db_filepath) as setfile: @@ -1221,6 +1254,7 @@ def read_card_data(options): ) cards.append(c) + # Create Start Deck dividers. 4 sets. Adjust totals for other cards, too. # Do early before propagating to various sets. # The card database contains one prototype divider that needs to be either duplicated or deleted. @@ -1267,6 +1301,25 @@ def read_card_data(options): if StartDeck_index is not None: del cards[StartDeck_index] + + # Move 12er packs of base victory cards into two stacks of 8 and 4. Can only be used together with start_decks + if options.victory8_4split: + for card_tag in ("Duchy", "Estate", "Province", "Colony"): + i = find_index_of_object(cards, {"card_tag": card_tag}) + if i is None: + raise "Error 1!" + card = cards[i] + if card.getCardCount() != 12: + raise "Error 2!" + card.setCardCount(8) + + new_card = copy.deepcopy(card) + new_card.setCardCount(4) + cards.append(new_card) + + if options.only_promo: + cards = [c for c in cards if ("promo" not in c.cardset_tags or c.card_tag in options.only_promo)] + # Set cardset_tag and expand cards that are used in multiple sets new_cards = [] for card in cards: @@ -1303,6 +1356,7 @@ class CardSorter(object): self.sort_key = self.by_expansion_sort_key self.baseOrder = [ + "Start Deck", "Copper", "Silver", "Gold", @@ -1314,16 +1368,17 @@ class CardSorter(object): "Province", "Colony", "Trash", - "Start Deck", ] self.baseCards = [] for tag in self.baseOrder: if tag in baseCards: - self.baseCards.append(baseCards[tag]) + for name in baseCards[tag]: + self.baseCards.append(name) del baseCards[tag] # now pick up those that have not been specified for tag in baseCards: - self.baseCards.append(baseCards[tag]) + for name in baseCards[tag]: + self.baseCards.append(name) # When sorting cards, want to always put "base" cards after all # kingdom cards, and order the base cards in a particular order @@ -1359,6 +1414,7 @@ class CardSorter(object): def by_cost_sort_key(self, card): """ Enforce color order: + 0 Start Deck 1 Action 2 Treasure 3 Curse @@ -1377,7 +1433,9 @@ class CardSorter(object): """ types = card.getType().getTypeNames() # order of if-statements matters! - if "Ruins" in types: + if "Start Deck" in types: + type_index = 0 + elif "Ruins" in types: type_index = 9 elif "Shelter" in types: type_index = 10 @@ -1435,7 +1493,7 @@ class CardSorter(object): return self.sort_key(card) -def add_card_text(cards, language="en_us"): +def add_card_text(cards, victory8_4split, language="en_us"): language = language.lower() # Read in the card text file card_text_filepath = os.path.join( @@ -1450,6 +1508,10 @@ def add_card_text(cards, language="en_us"): if card.card_tag in card_text: if "name" in card_text[card.card_tag].keys(): card.name = card_text[card.card_tag]["name"] + + if victory8_4split and card.card_tag in ("Duchy", "Estate", "Province", "Colony"): + card.name = card.name + f" ({card.getCardCount()})" + if "description" in card_text[card.card_tag].keys(): card.description = card_text[card.card_tag]["description"] if "extra" in card_text[card.card_tag].keys(): @@ -1803,9 +1865,9 @@ def filter_sort_cards(cards, options): cards = keep_cards # Now add text to the cards. Waited as long as possible to catch all groupings - cards = add_card_text(cards, LANGUAGE_DEFAULT) + cards = add_card_text(cards, options.victory8_4split, LANGUAGE_DEFAULT) if options.language != LANGUAGE_DEFAULT: - cards = add_card_text(cards, options.language) + cards = add_card_text(cards, options.victory8_4split, options.language) # Get list of cards from a file if options.cardlist: @@ -1817,13 +1879,21 @@ def filter_sort_cards(cards, options): cards = [card for card in cards if card.name in cardlist] # Set up the card sorter + basecards = {} + for card in cards: + if "base" in [set_name.lower() for set_name in card.cardset_tags]: + if card.card_tag not in basecards: + basecards[card.card_tag] = [] + basecards[card.card_tag].append(card.name) + cardSorter = CardSorter( options.order, - { - card.card_tag: card.name - for card in cards - if "base" in [set_name.lower() for set_name in card.cardset_tags] - }, + #{ + # card.card_tag: card.name + # for card in cards + # if "base" in [set_name.lower() for set_name in card.cardset_tags] + #}, + basecards ) # Optionally remove base cards from expansions that have them