Compare commits

...

2 Commits

Author SHA1 Message Date
Finn Stutzenstein
1499f3f637 wip 2022-02-19 12:03:14 +01:00
Finn Stutzenstein
b1273ca19f more customizing 2022-02-18 19:03:54 +01:00
10 changed files with 202 additions and 64 deletions

54
main.py
View File

@ -1,22 +1,42 @@
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",
"--shelters-as-startdecks",
"--only-promo", "Prince", "Sauna", "Courtier"
]
opts = domdiv.main.parse_opts(base_args)
opts = domdiv.main.clean_opts(opts)
domdiv.main.generate(opts)

View File

@ -975,6 +975,18 @@
"Start Deck"
]
},
{
"card_tag": "Shelter Start Deck",
"cardset_tags": [
"dark ages"
],
"cost": "",
"count": "0",
"randomizer": false,
"types": [
"Shelter Start Deck"
]
},
{
"card_tag": "Trash",
"cardset_tags": [
@ -3448,6 +3460,7 @@
{
"card_tag": "Courtier",
"cardset_tags": [
"promo",
"intrigue2ndEdition",
"intrigue2ndEditionUpgrade"
],

View File

@ -407,7 +407,12 @@
"Start Deck": {
"description": "Startkarten jedes Spielers:<n>7 Kupfer Karten<n>3 Anwesen Karten",
"extra": "",
"name": "Startkarten jedes Spielers"
"name": "Startkarten"
},
"Shelter Start Deck": {
"description": "Startkarten jedes spieleres, falls mit Unterschlüpfen anstatt Anwesen gespielt wird.",
"extra": "",
"name": "Unterschlupf"
},
"Trash": {
"description": "Müllstapel.",
@ -416,7 +421,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<br>3+ Spieler: 12 Kolonien",
"name": "Kolonie"
},
"Platinum": {
@ -680,7 +685,7 @@
"name": "Schurke"
},
"Ruins": {
"description": "<left><u>Verlassene Mine</u>: +1 Coin</left><left><u>Zerstörte Bibliothek</u>: +1 Karte</left><left><u>Zerstörter Markt</u>: +1 Kauf</left><left><u>Zerstörtes Dorf</u>: +1 Aktion</left><left><u>Überlebende</u>: Sieh dir die obersten beiden Karten von deinem Nachziehstapel an. Lege beide Karten ab oder lege beide Karten in beliebiger Reihenfolge zurück auf deinen Nachziehstapel.</left>",
"description": "<left>2 Spieler: 10 Karten, 3 Spieler: 20 Karten, ...</left><left><u>Verlassene Mine</u>: +1 Coin</left><left><u>Zerstörte Bibliothek</u>: +1 Karte</left><left><u>Zerstörter Markt</u>: +1 Kauf</left><left><u>Zerstörtes Dorf</u>: +1 Aktion</left><left><u>Überlebende</u>: Sieh dir die obersten beiden Karten von deinem Nachziehstapel an. Lege beide Karten ab oder lege beide Karten in beliebiger Reihenfolge zurück auf deinen Nachziehstapel.</left>",
"extra": "Der Ruinen-Stapel besteht aus bis zu 5 unterschiedlichen Karten. Siehe hierzu auch unter Spielvorbereitung 'gemischte Stapel' und 'Ruinen'. Der Ruinen-Stapel ist Teil des Vorrats. Die offenliegende Karte (und nur diese) kann bzw. muss durch eine entsprechende Kartenanweisung genommen oder auch gekauft werden. Wenn du die Überlebenden ausspielst, siehst du dir die obersten beiden Karten von deinem Nachziehstapel an und entscheidest dich dann, ob du beide Karten auf deinen Ablagestapel legst oder ob du beide Karten in beliebiger Reihenfolge zurück auf deinen Nachziehstapel legst. Du darfst nicht eine Karte ablegen und die andere zurück auf den Nachziehstapel legen. Die übrigen 4 Ruinen-Karten sind selbsterklärend.",
"name": "Ruinen"
},

View File

@ -30,6 +30,7 @@
"Shelters": "Unterschlüpfe",
"Spirit": "Erscheinung",
"Start Deck": "Startkarten",
"Shelter Start Deck": "Unterschlupf",
"State": "Zustand",
"Trash": "Müll",
"Traveller": "Reisender",

View File

@ -503,6 +503,15 @@
"tabCostHeightOffset": -1,
"tabTextHeightOffset": 0
},
{
"card_type": [
"Shelter Start Deck"
],
"card_type_image": "action-shelter.png",
"defaultCardCount": 0,
"tabCostHeightOffset": -1,
"tabTextHeightOffset": 0
},
{
"card_type": [
"State"

View File

@ -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",

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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()
@ -519,12 +556,24 @@ def parse_opts(cmdline_args=None):
dest="curse10",
help="Package Curse cards into groups of ten cards.",
)
group_select.add_argument(
"--shelters-as-startdecks",
action="store_true",
dest="shelters_as_startdecks",
help="Package Curse cards into groups of ten cards.",
)
group_select.add_argument(
"--start-decks",
action="store_true",
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 +634,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 +992,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 +1199,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:
@ -1208,6 +1247,17 @@ def read_card_data(options):
# Add the new dividers
cards.extend(new_cards)
if options.shelters_as_startdecks:
cards = [c for c in cards if "Shelter" not in c.types]
ShelterStartDeck_index = find_index_of_object(cards, {"card_tag": "Shelter Start Deck"})
for i in range(3): ## add 3 more card (sum=4)
cards.append(copy.deepcopy(cards[ShelterStartDeck_index]))
else:
# Remove Shelter Start Deck prototype. It is not needed.
ShelterStartDeck_index = find_index_of_object(cards, {"card_tag": "Shelter Start Deck"})
if ShelterStartDeck_index is not None:
del cards[ShelterStartDeck_index]
# Add any blank cards
if options.include_blanks > 0:
for x in range(0, options.include_blanks):
@ -1221,6 +1271,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 +1318,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 +1373,7 @@ class CardSorter(object):
self.sort_key = self.by_expansion_sort_key
self.baseOrder = [
"Start Deck",
"Copper",
"Silver",
"Gold",
@ -1314,16 +1385,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 +1431,7 @@ class CardSorter(object):
def by_cost_sort_key(self, card):
"""
Enforce color order:
0 Start Deck / Shelter Start Deck
1 Action
2 Treasure
3 Curse
@ -1367,7 +1440,7 @@ class CardSorter(object):
6 Landmark
7 Way (?)
8 Project (?)
9 Ruine
9 Ruins
10 Hideout
11 Hex (?)
12 Night (?)
@ -1377,7 +1450,11 @@ 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 "Shelter Start Deck" in types:
type_index = 0
elif "Ruins" in types:
type_index = 9
elif "Shelter" in types:
type_index = 10
@ -1435,7 +1512,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 +1527,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 +1884,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 +1898,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
@ -1854,7 +1943,7 @@ def filter_sort_cards(cards, options):
# Use the base card ordering
order = 100 + cardSorter.baseOrder.index(c.card_tag)
cardnamesByExpansion[c.cardset][c.card_tag] = {
"name": c.name.strip().replace(" ", "&nbsp;"),
"name": c.name.strip().replace(" (4)", "").replace(" (8)", "").replace(" ", "&nbsp;"),
"randomizer": c.randomizer,
"count": 1,
"sort": "%03d%s"
@ -1883,7 +1972,7 @@ def filter_sort_cards(cards, options):
if not n["randomizer"]:
# Highlight cards without Randomizers
n["name"] = "<i>" + n["name"] + "</i>"
if n["count"] > 1:
if n["count"] > 1 and exp_name != "Basis":
# Add number of copies
n["name"] = (
"{}&nbsp;\u00d7&nbsp;".format(n["count"]) + n["name"]