From 236feff33c2320995a0c7935503bf35c07a76862 Mon Sep 17 00:00:00 2001 From: Wendel Voigt Date: Mon, 30 Apr 2018 12:11:01 -0500 Subject: [PATCH] Additional Divider Options: Curse, Trash, Start Decks - 2nd attempt (#201) * Trash, Curse, Start Deck Options --- domdiv/card_db/cards_db.json | 13 +++ domdiv/card_db/cz/cards_cz.json | 6 ++ domdiv/card_db/cz/types_cz.json | 1 + domdiv/card_db/de/cards_de.json | 44 +++++------ domdiv/card_db/de/types_de.json | 1 + domdiv/card_db/en_us/cards_en_us.json | 5 ++ domdiv/card_db/en_us/types_en_us.json | 1 + domdiv/card_db/fr/cards_fr.json | 7 +- domdiv/card_db/fr/types_fr.json | 1 + domdiv/card_db/it/cards_it.json | 6 ++ domdiv/card_db/it/types_it.json | 1 + domdiv/card_db/nl_du/cards_nl_du.json | 6 ++ domdiv/card_db/nl_du/types_nl_du.json | 1 + domdiv/card_db/sets_db.json | 1 + domdiv/card_db/types_db.json | 8 ++ domdiv/card_db/xx/cards_xx.json | 6 ++ domdiv/card_db/xx/types_xx.json | 1 + domdiv/cards.py | 14 ++-- domdiv/main.py | 109 +++++++++++++++++++++++++- domdiv/tests/carddb_tests.py | 11 ++- 20 files changed, 207 insertions(+), 36 deletions(-) diff --git a/domdiv/card_db/cards_db.json b/domdiv/card_db/cards_db.json index ea1c99a..ee0efc8 100644 --- a/domdiv/card_db/cards_db.json +++ b/domdiv/card_db/cards_db.json @@ -878,6 +878,19 @@ "types": [ "Treasure" ] +},{ + "card_tag": "Start Deck", + "cardset_tags": [ + "base", + "dominion1stEdition", + "dominion2ndEdition", + "intrigue1stEdition" + ], + "cost": "", + "count": "0", + "types": [ + "Start Deck" + ] },{ "card_tag": "Trash", "cardset_tags": [ diff --git a/domdiv/card_db/cz/cards_cz.json b/domdiv/card_db/cz/cards_cz.json index ee84e92..bb7e16f 100644 --- a/domdiv/card_db/cz/cards_cz.json +++ b/domdiv/card_db/cz/cards_cz.json @@ -485,6 +485,12 @@ "name": "Medák", "untranslated": "description, extra" }, + "Start Deck": { + "description": "Player's starting deck of cards:7 Copper cards3 Estate cards", + "extra": "", + "name": "Player Start Deck", + "untranslated": "description, extra, name" + }, "Trash": { "description": "Pile of trash.", "extra": "", diff --git a/domdiv/card_db/cz/types_cz.json b/domdiv/card_db/cz/types_cz.json index 076c840..7c8584d 100644 --- a/domdiv/card_db/cz/types_cz.json +++ b/domdiv/card_db/cz/types_cz.json @@ -26,6 +26,7 @@ "Shelter": "Shelter", "Shelters": "Shelters", "Spirit": "Spirit", + "Start Deck": "Start Deck", "State": "State", "Trash": "Trash", "Traveller": "Traveller", diff --git a/domdiv/card_db/de/cards_de.json b/domdiv/card_db/de/cards_de.json index e1d7ac0..f2df2cd 100644 --- a/domdiv/card_db/de/cards_de.json +++ b/domdiv/card_db/de/cards_de.json @@ -424,6 +424,12 @@ "name": "Silber", "untranslated": "extra" }, + "Start Deck": { + "description": "Player's starting deck of cards:7 Copper cards3 Estate cards", + "extra": "", + "name": "Player Start Deck", + "untranslated": "description, extra, name" + }, "Trash": { "description": "Pile of trash.", "extra": "", @@ -907,44 +913,37 @@ "Artisan": { "description": "Nimm eine Karte vom Vorrat auf die Hand, die bis zu 5 kostet.Lege eine Handkarte auf deinen Nachziehstapel.", "extra": "Nimm eine Karte vom Vorrat, die zu diesem Zeitpunkt maximal 5 kostet.Du darfst kein zusätzliches _ Coin  einsetzen, um dir eine teurere Karte zu nehmen.Außer _ Coin  darf die Karte keine zusätzlichen Kosten enthalten.Du darfst dir zum Beispiel keine Karte mit Trank (aus Alchemie) oder Schulden (aus Empires) in den Kosten nehmen.Die genommene Karte nimmst du direkt auf die Hand.Anschließend legst du eine beliebige Handkarte (das kann die gerade genommene oder eine andere sein) oben auf deinen Nachziehstapel.", - "name": "Töpferei" - + "name": "Töpferei" }, "Bandit": { "description": "Nimm ein Gold vom Vorrat.Jeder Mitspieler deckt die obersten 2 Karten seines Nachziehstapels auf, entsorgt eine aufgedeckte Geldkarte nach seiner Wahl – außer Kupfer – und legt den Rest ab.", "extra": "Zuerst nimmst du ein Gold vom Vorrat und legst es auf deinen Ablagestapel.Dann deckt jeder Mitspieler – beginnend bei deinem linken Mitspieler – die obersten zwei Karten seines Nachziehstapels auf.Deckt ein Spieler zwei Geldkarten (auch ggf. kombinierte) außer Kupfer auf, muss er eine davon entsorgen.Dabei darf er selbst entscheiden, welche Geldkarte er entsorgt.Die andere Geldkarte wird – genauso wie alle anderen Karten – abgelegt.Deckt ein Spieler eine Geldkarte außer Kupfer sowie eine andere Karte (z.B. ein Kupfer oder eine beliebige Aktionskarte) auf, wird diese Geldkarte entsorgt.Die andere aufgedeckte Karte wird abgelegt.", - "name": "Banditin" - + "name": "Banditin" }, "Harbinger": { "description": "+1 Karte
+1 AktionSieh deinen Ablagestapel durch.Du darfst eine Karte daraus auf deinen Nachziehstapel legen.", "extra": "Du ziehst 1 Karte und erhälst +1 Aktion. Schau dir deinen Ablagestapel an.Du darfst eine Karte daraus auswählen und oben auf deinen Nachziehstapel legen. Die restlichen Karten (oder alle) legst du in beliebiger Reihenfolge zurück auf den Ablagestapel.Ist dein Ablagestapel leer, passiert nichts.", - "name": "Vorbotin" - + "name": "Vorbotin" }, "Merchant": { "description": "+1 Karte
+1 AktionSpielst du in diesem Zug das erste Mal ein Silber aus: +1 Geld", "extra": "Du ziehst 1 Karte und erhälst +1 Aktion.Wenn du in diesem Zug vor dem Ausspielen dieser Händlerin noch kein Silber ausgespielt hast, erhälst du für das erste danach ausgespielte Silber +1 Geld.Für jedes weitere ausgespielte Silber erhälst du keinen zusätzlichen Bonus.Hast du mehrere Händlerinnen ausgespielt, erhälst du pro Händlerin +1 Geld.", - "name": "Händlerin" - + "name": "Händlerin" }, "Poacher": { "description": "+1 Karte
+1 Aktion
+1 GeldLege pro leerem Vorratsstapel eine Handkarte ab.", "extra": "Du ziehst 1 Karte, erhältst + 1 Aktion und + 1 Geld.Dann schaust du, wie viele Vorratsstapel (Fluch-, Geld-, Punkte- und Aktionskarten, ggf. Ruinenkarten etc.) bereits leer sind.Ist kein Stapel leer, musst du keine Handkarten ablegen.Ist ein Stapel leer, legst du 1 Handkarte ab usw.Wenn du nicht so viele Karten auf der Hand hast, wie Vorratsstapel leer sind, legst du so viele Karten ab, wie du kannst.", - "name": "Wilddiebin" - + "name": "Wilddiebin" }, "Sentry": { "description": "+1 Karte
+1 AktionSieh dir die obersten 2 Karten deines Nachziehstapels an.Entsorge und/oder lege beliebig viele davon ab.Lege die übrigen Karten in beliebiger Reihenfolge auf deinen Nachziehstapel zurück.", "extra": "Du ziehst 1 Karte und erhältst +1 Aktion.Dann siehst du dir die obersten 2 Karten deines Nachziehstapels an.Du kannst beide Karten entsorgen, beide Karten ablegen oder sie in beliebiger Reihenfolge zurück auf den Nachziehstapel legen.Du kannst aber auch eine entsorgen und eine ablegen, oder eine entsorgen und die andere zurück auf den Nachziehstapel legen, oder eine ablegen und die andere zurücklegen.", - "name": "Torwächterin" - + "name": "Torwächterin" }, "Vassal": { "description": "+2 GeldLege die oberste Karte deines Nachziehstapels ab.Ist es eine Aktionskarte, darfst du sie ausspielen.", "extra": "Ist die aufgedeckte Karte eine Aktionskarte (auch ggf. kombinierte), darfst du sie sofort ausspielen.Wenn du sie ausspielst, legst du sie in deinen Spielbereich und führst sofort die Anweisungen darauf aus.Dafür benötigst du keine zusätzliche Aktion.Das Ausspielen der Aktionskarte verbraucht auch keine freie oder zusätzliche Aktion, die du durch das Ausspielen anderer Karten bereits gesammelt hast.", - "name": "Vasall" - + "name": "Vasall" }, "Advance": { "description": "You may trash an Action card from your hand. If you do, gain an Action card costing up to 6 Coins.", @@ -1671,44 +1670,37 @@ "Courtier": { "description": "Decke eine Handkarte auf.Für jeden Kartentyp (Aktion, Angriff ...), den sie hat, wähle eine andere Option:
+1 Aktion
+1 Kauf
+3 Geld oder
nimm ein Gold vom Vorrat.", "extra": "Decke eine Karte aus deiner Hand auf.Zähle dann die Typen, denen diese Karte angehört – also AKTION, GELD, REAKTION, ANGRIFF, PUNKTE, FLUCH etc.Pro Typ, dem die Karte angehört, entscheidest du dich für eine der vier angegebenen Optionen. Dabei darfst du keine der Optionen doppelt auswählen.Wenn du zum Beispiel eine PATROUILLE (AKTION) aufdeckst, darfst du eine Option auswählen, deckst du einen KARAWANENWÄCHTER aus Abenteuer (AKTION – DAUER – REAKTION) auf, darfst du 3 unterschiedliche Optionen wählen.Entscheidest du dich für das Gold, legst du dieses auf den Ablagestapel.Kannst du keine Handkarte aufdecken, erhältst du nichts.", - "name": "Höflinge" - + "name": "Höflinge" }, "Diplomat": { "description": "+2 Karten
Hast du nach dem Ziehen 5 oder weniger Handkarten: +2 Aktionen.Wenn ein Mitspieler eine Angriffskarte ausspielt und du mindestens 5 Handkarten hast, darfst du diese Karte aus deiner Hand aufdecken.Wenn du das tust: Ziehe 2 Karten und lege dann 3 Karten ab.", "extra": " Diese Karte ist eine Aktions- und Reaktionskarte.Wird sie als Aktion in der Aktionsphase ausgespielt, nimmst du 2 Karten.Hast du dann 5 oder weniger Karten auf der Hand, erhältst du außerdem + 2 Aktionen.Spielt ein Mitspieler eine Angriffskarte aus und du hast zu diesem Zeitpunkt 5 oder mehr Karten auf der Hand, darfst du diese Karte – bevor der ausgespielte Angriff ausgeführt wird – aus der Hand aufdecken.Wenn du das tust, nimmst du diese DIPLOMATIN wieder auf die Hand, ziehst 2 Karten und legst dann 3 Karten (auch möglich inklusive dieser DIPLOMATIN) ab.Hast du dann immer noch 5 oder mehr Karten sowie eine DIPLOMATIN auf der Hand, darfst du die DIPLOMATIN noch einmal aufdecken – und dies so oft wiederholen wie du möchtest und die Bedingung der 5 oder mehr Karten auf der Hand erfüllt ist.Erst dann wird der Angriff ausgeführt.Hast du mehrere Reaktionskarten auf der Hand, mit denen du auf das Ausspielen einer Angriffskarte reagieren kannst, darfst du diese nacheinander in beliebiger Reihenfolge aufdecken.", "name": "Diplomatin" - }, "Lurker": { "description": "+1 Aktion
Wähle eins:Entsorge eine Aktionskarte vom Vorratodernimm eine Aktionskarte vom Müll.", "extra": "Die Karte, die du entsorgst oder vom Müllstapel nimmst, muss den Typ AKTION beinhalten, d.h. sie kann auch eine kombinierte Aktionskarte (z.B. Mühle) sein.Genommene Karten werden auf den Ablagestapel gelegt - es sei denn, auf der Karte steht etwas anderes.Wird eine Karte entsorgt, die einen speziellen Effekt beim Entsorgen hat, tritt dieser ein.", - "name": "Herumtreiberin" - + "name": "Herumtreiberin" }, "Mill": { "description": "+1 Karte
+1 Aktion
Du darfst 2 Handkarten ablegen.Wenn du das tust: +2 Geld.1 <*VP*>", "extra": " Diese Karte ist eine kombinierte Aktions- und Punktekarte.Als Punktekarte bringt sie beim Zählen der Punkte 1 .Spielst du die MÜHLE als Aktionskarte aus, ziehst du 1 Karte und erhältst + 1 Aktion.Du darfst 2 Karten aus deiner Hand ablegen. Wenn du das tust, erhältst du + 2 Geld. Tust du das nicht (weil du zum Beispiel nicht genügend Karten auf der Hand hast), erhältst du nichts.Nur, wenn du nicht mehr als eine Karte auf der Hand hast, darfst du genau eine Karte ablegen, erhältst dafür aber kein Geld.", "name": "Mühle" - }, "Patrol": { "description": "+3 KartenDecke die obersten 4 Karten deines Nachziehstapels auf.Nimm alle aufgedeckten Punkte- und Fluchkarten auf die Hand.Lege die übrigen Karten in beliebiger Reihenfolge auf deinen Nachziehstapel zurück.", "extra": "Ziehe zuerst 3 Karten.Decke dann die obersten 4 Karten deines Nachziehstapels auf.So aufgedeckte Punktekarten (auch ggf. kombinierte) und Flüche nimmst du alle auf die Hand.Die restlichen Karten legst du in beliebiger Reihenfolge zurück auf den Nachziehstapel.", - "name": "Patrouille" - + "name": "Patrouille" }, "Replace": { "description": "Entsorge eine Handkarte.Nimm eine Karte vom Vorrat, die bis zu 2 Geld mehr kostet als die entsorgte Karte.Ist die genommene Karte eine Aktions- oder Geldkarte, lege sie auf deinen Nachziehstapel.Ist es eine Punktekarte, nimmt jeder Mitspieler einen Fluch vom Vorrat.", "extra": "Entsorge zuerst eine Karte aus deiner Hand.Dann nimmst du dir eine Karte vom Vorrat, die maximal 2 Geld mehr kostet als die entsorgte Karte.Eine Karte kostet nur dann maximal 2 Geld mehr, wenn die restlichen Kosten (z.B. Schulden aus Empires oder Trank aus Alchemie) gleich oder niedriger sind.Wenn die genommene Karte eine Aktions- und/oder Geldkarte ist, legst du die Karte oben auf deinen Nachziehstapel.Ansonsten legst du die Karte auf den Ablagestapel.Ist die genommene Karte eine Punktekarte, nimmt sich jeder Mitspieler – beginnend bei deinem linken Mitspieler – einen Fluch.Ist die genommene Karte eine Punktekarte sowie eine Aktions- oder Geldkarte (z.B. MÜHLE), legst du die Karte oben auf deinen Nachziehstapel und jeder Mitspieler muss sich einen Fluch nehmen.", - "name": "Austausch" - + "name": "Austausch" }, "Secret Passage": { "description": "+2 Karten
+1 AktionLege eine Handkarte an eine beliebige Stelle in deinen Nachziehstapel.", "extra": "Du ziehst 2 Karten und erhältst +1 Aktion.Dann nimmst du eine beliebige Karte aus deiner Hand (auch ggf. eine, die du gerade gezogen hast) und legst sie an eine beliebige Stelle in deinen Nachziehstapel.Du darfst sie oben drauf, unten drunter oder irgendwo in die Mitte legen.Du darfst dabei die Karten deines Nachziehstapels zählen, aber nicht ansehen.Befinden sich keine Karten in deinem Nachziehstapel, wird die zurückgelegte Karte zur einzigen Karte in deinem Nachziehstapel.", - "name": "Geheimgang" - + "name": "Geheimgang" }, "Bad Omens": { "description": "Put your deck into your discard pile. Look through it and put 2 Coppers from it onto your deck (or reveal you can't.)", diff --git a/domdiv/card_db/de/types_de.json b/domdiv/card_db/de/types_de.json index 4d47a5c..7d19226 100644 --- a/domdiv/card_db/de/types_de.json +++ b/domdiv/card_db/de/types_de.json @@ -26,6 +26,7 @@ "Shelter": "Unterschlupf", "Shelters": "Unterschlüpfe", "Spirit": "Spirit", + "Start Deck": "Start Deck", "State": "State", "Trash": "Müll", "Traveller": "Reisender", diff --git a/domdiv/card_db/en_us/cards_en_us.json b/domdiv/card_db/en_us/cards_en_us.json index 06350e1..cce92b1 100644 --- a/domdiv/card_db/en_us/cards_en_us.json +++ b/domdiv/card_db/en_us/cards_en_us.json @@ -404,6 +404,11 @@ "extra": "40 cards per game.", "name": "Silver" }, + "Start Deck": { + "description": "Player's starting deck of cards:7 Copper cards3 Estate cards", + "extra": "", + "name": "Player Start Deck" + }, "Trash": { "description": "Pile of trash.", "extra": "", diff --git a/domdiv/card_db/en_us/types_en_us.json b/domdiv/card_db/en_us/types_en_us.json index 076c840..7c8584d 100644 --- a/domdiv/card_db/en_us/types_en_us.json +++ b/domdiv/card_db/en_us/types_en_us.json @@ -26,6 +26,7 @@ "Shelter": "Shelter", "Shelters": "Shelters", "Spirit": "Spirit", + "Start Deck": "Start Deck", "State": "State", "Trash": "Trash", "Traveller": "Traveller", diff --git a/domdiv/card_db/fr/cards_fr.json b/domdiv/card_db/fr/cards_fr.json index a2fe845..36aa079 100644 --- a/domdiv/card_db/fr/cards_fr.json +++ b/domdiv/card_db/fr/cards_fr.json @@ -420,6 +420,12 @@ "extra": "40 cartes par partie.", "name": "Argent" }, + "Start Deck": { + "description": "Player's starting deck of cards:7 Copper cards3 Estate cards", + "extra": "", + "name": "Player Start Deck", + "untranslated": "description, extra, name" + }, "Trash": { "description": "Pile du rebut.", "extra": "", @@ -2736,4 +2742,3 @@ "untranslated": "description, extra, name" } } - diff --git a/domdiv/card_db/fr/types_fr.json b/domdiv/card_db/fr/types_fr.json index fd43e3e..00d25b0 100644 --- a/domdiv/card_db/fr/types_fr.json +++ b/domdiv/card_db/fr/types_fr.json @@ -26,6 +26,7 @@ "Shelter": "Refuge", "Shelters": "Refuges", "Spirit": "Spirit", + "Start Deck": "Start Deck", "State": "State", "Trash": "Rebut", "Traveller": "Itinérant", diff --git a/domdiv/card_db/it/cards_it.json b/domdiv/card_db/it/cards_it.json index 77031b8..9241686 100644 --- a/domdiv/card_db/it/cards_it.json +++ b/domdiv/card_db/it/cards_it.json @@ -465,6 +465,12 @@ "extra": " 40 carte per partita.", "name": "Argento" }, + "Start Deck": { + "description": "Player's starting deck of cards:7 Copper cards3 Estate cards", + "extra": "", + "name": "Player Start Deck", + "untranslated": "description, extra, name" + }, "Trash": { "description": "Pila delle carte eliminate.", "extra": "", diff --git a/domdiv/card_db/it/types_it.json b/domdiv/card_db/it/types_it.json index 076c840..7c8584d 100644 --- a/domdiv/card_db/it/types_it.json +++ b/domdiv/card_db/it/types_it.json @@ -26,6 +26,7 @@ "Shelter": "Shelter", "Shelters": "Shelters", "Spirit": "Spirit", + "Start Deck": "Start Deck", "State": "State", "Trash": "Trash", "Traveller": "Traveller", diff --git a/domdiv/card_db/nl_du/cards_nl_du.json b/domdiv/card_db/nl_du/cards_nl_du.json index 4cc5b07..6b1828b 100644 --- a/domdiv/card_db/nl_du/cards_nl_du.json +++ b/domdiv/card_db/nl_du/cards_nl_du.json @@ -410,6 +410,12 @@ "extra": " 40 kaarten per spel.", "name": "Zilver" }, + "Start Deck": { + "description": "Player's starting deck of cards:7 Copper cards3 Estate cards", + "extra": "", + "name": "Player Start Deck", + "untranslated": "description, extra, name" + }, "Trash": { "description": "stapel van vernietigde kaarten.", "extra": "", diff --git a/domdiv/card_db/nl_du/types_nl_du.json b/domdiv/card_db/nl_du/types_nl_du.json index e4e3acb..67029ca 100644 --- a/domdiv/card_db/nl_du/types_nl_du.json +++ b/domdiv/card_db/nl_du/types_nl_du.json @@ -26,6 +26,7 @@ "Shelter": "Onderdak", "Shelters": "Onderdakkaarten", "Spirit": "Spirit", + "Start Deck": "Start Deck", "State": "State", "Trash": "Vernietigde Kaarten", "Traveller": "Traveller", diff --git a/domdiv/card_db/sets_db.json b/domdiv/card_db/sets_db.json index 5ce8856..bebad80 100644 --- a/domdiv/card_db/sets_db.json +++ b/domdiv/card_db/sets_db.json @@ -48,6 +48,7 @@ "latest" ], "image": "", + "no_randomizer": true, "set_name": "*base*", "set_text": "", "text_icon": "*" diff --git a/domdiv/card_db/types_db.json b/domdiv/card_db/types_db.json index df15d08..9d0e135 100644 --- a/domdiv/card_db/types_db.json +++ b/domdiv/card_db/types_db.json @@ -391,6 +391,14 @@ "defaultCardCount": 0, "tabCostHeightOffset": -1, "tabTextHeightOffset": 0 +},{ + "card_type": [ + "Start Deck" + ], + "card_type_image": "action.png", + "defaultCardCount": 0, + "tabCostHeightOffset": -1, + "tabTextHeightOffset": 0 },{ "card_type": [ "State" diff --git a/domdiv/card_db/xx/cards_xx.json b/domdiv/card_db/xx/cards_xx.json index 2bbd9ed..2363f3f 100644 --- a/domdiv/card_db/xx/cards_xx.json +++ b/domdiv/card_db/xx/cards_xx.json @@ -485,6 +485,12 @@ "name": "Silver", "untranslated": "description, extra, name" }, + "Start Deck": { + "description": "Player's starting deck of cards:7 Copper cards3 Estate cards", + "extra": "", + "name": "Player Start Deck", + "untranslated": "description, extra, name" + }, "Trash": { "description": "Pile of trash.", "extra": "", diff --git a/domdiv/card_db/xx/types_xx.json b/domdiv/card_db/xx/types_xx.json index 076c840..7c8584d 100644 --- a/domdiv/card_db/xx/types_xx.json +++ b/domdiv/card_db/xx/types_xx.json @@ -26,6 +26,7 @@ "Shelter": "Shelter", "Shelters": "Shelters", "Spirit": "Spirit", + "Start Deck": "Start Deck", "State": "State", "Trash": "Trash", "Traveller": "Traveller", diff --git a/domdiv/cards.py b/domdiv/cards.py index 962e9d9..98ea671 100644 --- a/domdiv/cards.py +++ b/domdiv/cards.py @@ -50,19 +50,19 @@ class Card(object): self.image = image self.text_icon = text_icon self.cardset_tag = cardset_tag - if count < 0: - self.count = [self.getType().getTypeDefaultCardCount()] - elif count == 0: - self.count = [] - else: - self.count = [int(count)] + self.setCardCount(count) self.randomizer = randomizer def getCardCount(self): return sum(i for i in self.count) def setCardCount(self, value): - self.count = value + if value < 0: + self.count = [self.getType().getTypeDefaultCardCount()] + elif value == 0: + self.count = [] + else: + self.count = [int(value)] def addCardCount(self, value): self.count.extend(value) diff --git a/domdiv/main.py b/domdiv/main.py index 14c780e..ada68d5 100644 --- a/domdiv/main.py +++ b/domdiv/main.py @@ -293,6 +293,21 @@ def parse_opts(cmdline_args=None): action="store_true", help="Group cards that generally are used together " "(e.g., Shelters, Tournament and Prizes, Urchin/Mercenary, etc.).") + group_select.add_argument( + "--no-trash", + action="store_true", + dest="no_trash", + help="Exclude Trash from cards.") + group_select.add_argument( + "--curse10", + action="store_true", + dest="curse10", + 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( "--include-blanks", action="store_true", @@ -541,6 +556,32 @@ def get_resource_stream(path): return codecs.EncodedFile(pkg_resources.resource_stream('domdiv', path), "utf-8") +def find_index_of_object(lst=[], attributes={}): + # Returns the index of the first object in lst that matches the given attributes. Otherwise returns None. + # attributes is a dict of key: value pairs. Object attributes that are lists are checked to have value in them. + for i, d in enumerate(lst): + # Set match to false just in case there are no attributes. + match = False + for key, value in attributes.iteritems(): + # if anything does not match, then break out and start the next one. + match = hasattr(d, key) + if match: + test = getattr(d, key, None) + if type(test) is list: + match = value in test + else: + match = value == test + if not match: + break + + if match: + # If all the attributes are found, then we have a match + return i + + # nothing matched + return None + + def read_card_data(options): # Read in the card types @@ -576,6 +617,72 @@ def read_card_data(options): Card.sets[s]['no_randomizer'] = Card.sets[s].get('no_randomizer', False) Card.sets[s]['fan'] = Card.sets[s].get('fan', False) + # Remove the Trash card. Do early before propagating to various sets. + if options.no_trash: + i = find_index_of_object(cards, {'card_tag': 'Trash'}) + if i is not None: + del cards[i] + + # Repackage Curse cards into 10 per divider. Do early before propagating to various sets. + if options.curse10: + i = find_index_of_object(cards, {'card_tag': 'Curse'}) + if i is not None: + new_cards = [] + cards_remaining = cards[i].getCardCount() + while cards_remaining > 10: + # make a new copy of the card and set count to 10 + new_card = copy.deepcopy(cards[i]) + new_card.setCardCount(10) + new_cards.append(new_card) + cards_remaining -= 10 + + # Adjust original Curse card to the remaining cards (should be 10) + cards[i].setCardCount(cards_remaining) + # Add the new dividers + cards.extend(new_cards) + + # 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. + if options.start_decks: + # Find the index to the individual cards that need changed in the cards list + StartDeck_index = find_index_of_object(cards, {'card_tag': 'Start Deck'}) + Copper_index = find_index_of_object(cards, {'card_tag': 'Copper'}) + Estate_index = find_index_of_object(cards, {'card_tag': 'Estate'}) + if Copper_index is None or Estate_index is None or StartDeck_index is None: + # Something is wrong, can't find one or more of the cards that need to change + print "Error - cannot create Start Decks" + + # Remove the Start Deck prototype if we can + if StartDeck_index is not None: + del cards[StartDeck_index] + else: + # Start Deck Constants + STARTDECK_COPPERS = 7 + STARTDECK_ESTATES = 3 + STARTDECK_NUMBER = 4 + + # Add correct card counts to Start Deck prototype. This will be used to make copies. + cards[StartDeck_index].setCardCount(STARTDECK_COPPERS) + cards[StartDeck_index].addCardCount([int(STARTDECK_ESTATES)]) + + # Make new Start Deck Dividers and adjust the corresponding card counts + for x in range(0, STARTDECK_NUMBER): + # Add extra copies of the Start Deck prototype. + # But don't need to add the first one again, since the prototype is already there. + if x > 0: + cards.append(copy.deepcopy(cards[StartDeck_index])) + # Note: By appending, it should not change any of the index values being used + + # Remove Copper and Estate card counts from their dividers + cards[Copper_index].setCardCount(cards[Copper_index].getCardCount() - STARTDECK_COPPERS) + cards[Estate_index].setCardCount(cards[Estate_index].getCardCount() - STARTDECK_ESTATES) + else: + # Remove Start Deck prototype. It is not needed. + StartDeck_index = find_index_of_object(cards, {'card_tag': 'Start Deck'}) + if StartDeck_index is not None: + del cards[StartDeck_index] + # Set cardset_tag and expand cards that are used in multiple sets new_cards = [] for card in cards: @@ -613,7 +720,7 @@ class CardSorter(object): self.baseOrder = ['Copper', 'Silver', 'Gold', 'Platinum', 'Potion', 'Curse', 'Estate', 'Duchy', 'Province', 'Colony', - 'Trash'] + 'Trash', 'Start Deck'] self.baseCards = [] for tag in self.baseOrder: if tag in baseCards: diff --git a/domdiv/tests/carddb_tests.py b/domdiv/tests/carddb_tests.py index 25a02de..b5c3fc9 100644 --- a/domdiv/tests/carddb_tests.py +++ b/domdiv/tests/carddb_tests.py @@ -22,10 +22,12 @@ def rmtestcardb(request): def test_cardread(): + cardsExpected = 524 + options = main.parse_opts([]) options.data_path = '.' cards = main.read_card_data(options) - assert len(cards) == 524 + assert len(cards) == cardsExpected valid_cardsets = { u'base', u'dominion1stEdition', @@ -57,6 +59,13 @@ def test_cardread(): assert isinstance(c, domdiv_cards.Card) assert c.cardset_tag in valid_cardsets + # Option modified card count + options = main.parse_opts(['--no-trash', '--curse10', '--start-decks']) + options.data_path = '.' + cards = main.read_card_data(options) + # Total delta cards is +21 from Trash: -1 * 3 sets = -3; Curse: +2 * 4 sets =+8; Start Decks: +4 * 4 sets = +16 + assert len(cards) == cardsExpected + 21 + def test_languages(): languages = main.get_languages('card_db')