From 0881d947383ba4307268dfaca9fa4fecb45c59fa Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 13:40:07 -0800 Subject: [PATCH 01/22] fix for custom papersize --- dominion_tabs.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 199c8df..0444186 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -516,6 +516,10 @@ class DominionTabs: fname = args[0] return self.generate(options,fname) + def parseDimensions(self, dimensionsStr): + x, y = dimensionsStr.upper().split('X', 1) + return (float (x) * cm, float (y) * cm) + def generate(self,options,f): self.options = options size = self.options.size.upper() @@ -526,24 +530,27 @@ class DominionTabs: dominionCardWidth, dominionCardHeight = (9.1*cm, 5.9*cm) print 'Using normal card size, %.2fcm x%.2fcm' % (dominionCardWidth/cm,dominionCardHeight/cm) else: - x, y = size.split ("X", 1) - dominionCardWidth, dominionCardHeight = (float (x) * cm, float (y) * cm) + dominionCardWidth, dominionCardHeight = self.parseDimensions(size) print 'Using custom card size, %.2fcm x %.2fcm' % (dominionCardWidth/cm,dominionCardHeight/cm) papersize = None if not self.options.papersize: if os.path.exists("/etc/papersize"): papersize = open ("/etc/papersize").readline().upper() + else: + papersize = 'LETTER' else: papersize = self.options.papersize.upper() if papersize == 'A4': print "Using A4 sized paper." self.paperwidth, self.paperheight = A4 - else: + elif papersize == 'LETTER': print "Using letter sized paper." self.paperwidth, self.paperheight = LETTER - + else: + self.paperwidth, self.paperheight = self.parseDimensions(papersize) + print 'Using custom paper size, %.2fcm x %.2fcm' % (self.paperwidth/cm,self.paperheight/cm) if self.options.orientation == "vertical": self.tabWidth, self.tabBaseHeight = dominionCardHeight, dominionCardWidth @@ -563,8 +570,7 @@ class DominionTabs: self.verticalBorderSpace = 0.01*cm fixedMargins = True else: - minmarginwidth, minmarginheight = self.options.minmargin.split ("x", 1) - minmarginwidth, minmarginheight = float (minmarginwidth) * cm, float (minmarginheight) * cm + minmarginwidth, minmarginheight = self.parseDimensions(self.options.minmargin) self.tabLabelHeight = 0.9*cm self.tabLabelWidth = 4*cm From d9430674710ef0340f8899feb102939a51c86a73 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:29:48 -0800 Subject: [PATCH 02/22] support for custom tab width --- dominion_tabs.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 0444186..bf3628d 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -170,7 +170,7 @@ class DominionTabs: else: self.canvas.translate(0,self.tabHeight-self.tabLabelHeight) - textWidth = 85 + textWidth = self.tabLabelWidth - 6 # allow for 3 pt border on each side textHeight = self.tabLabelHeight/2-7+card.getType().getTabTextHeightOffset() self.canvas.drawImage(os.path.join(self.filedir,'images',card.getType().getNoCoinTabImageFile()),1,0, @@ -180,7 +180,6 @@ class DominionTabs: if card.getType().getTypeNames() != ('Expansion',): textInset = 22 - costHeight = textHeight + card.getType().getTabCostHeightOffset() potHeight = 3 + card.getType().getTabTextHeightOffset() potSize = 11 @@ -190,7 +189,6 @@ class DominionTabs: if card.potcost: self.canvas.drawImage(os.path.join(self.filedir,'images','potion.png'),21,potHeight,potSize,potSize,preserveAspectRatio=True,mask=[255,255,255,255,255,255]) textInset += potSize - textWidth -= potSize setImageHeight = potHeight self.canvas.setFont('MinionPro-Bold',12) @@ -204,6 +202,8 @@ class DominionTabs: textInset = 13 setImageHeight = 3 + card.getType().getTabTextHeightOffset() + textWidth -= textInset + #set image setImage = DominionTabs.setImages.get(card.cardset, None) if not setImage: @@ -488,6 +488,8 @@ class DominionTabs: help="'<%f>x<%f>' (size in cm, left/right, top/bottom), default: 1x1") parser.add_option("--papersize",type="string",dest="papersize",default=None, help="'<%f>x<%f>' (size in cm), or 'A4', or 'LETTER'") + parser.add_option("--tabwidth",type="float",default=4, + help="width in cm of stick-up tab (ignored if tabs-only used)") parser.add_option("--samesidelabels",action="store_true",dest="sameside", help="force all label tabs to be on the same side") parser.add_option("--expansions",action="append",type="string", @@ -571,9 +573,8 @@ class DominionTabs: fixedMargins = True else: minmarginwidth, minmarginheight = self.parseDimensions(self.options.minmargin) - - self.tabLabelHeight = 0.9*cm - self.tabLabelWidth = 4*cm + self.tabLabelWidth = self.options.tabwidth * cm + self.tabLabelHeight = .9*cm self.horizontalBorderSpace = 0*cm self.verticalBorderSpace = 0*cm From 34a81d53a769ac1243bc34c6115347ac956f655b Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:30:40 -0800 Subject: [PATCH 03/22] fix missing spaces in card extras (wasn't inserting space in place of line break) --- dominion_tabs.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index bf3628d..357f078 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -320,7 +320,7 @@ class DominionTabs: if not self.options.expansions and currentCard and (currentCard not in (c.name for c in cards)): print currentCard + ' has extra description, but is not in cards' else: - extra += line.strip() + extra += ' ' + line.strip() if currentCard and extra: extras[currentCard] = extra.strip() for c in cards: @@ -659,10 +659,10 @@ class DominionTabs: open('cards.yaml','w').write(out) if options.order == "global": - sf = lambda x,y: cmp(x.name,y.name) + sortKey = lambda x: x.name else: - sf = lambda x,y: cmp((x.cardset,x.name),(y.cardset,y.name)) - cards.sort(cmp=sf) + sortKey = lambda x: (x.cardset,x.name) + cards.sort(key=sortKey) if not f: f = "dominion_tabs.pdf" From 013b094e76435891e949fdbfa84900ac85b873af Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:31:41 -0800 Subject: [PATCH 04/22] fix for 2-line names with more than 2 parts --- dominion_tabs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 357f078..a4fb930 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -250,7 +250,7 @@ class DominionTabs: self.canvas.drawString(textInset+w,h,n[1:]) w += pdfmetrics.stringWidth(n[1:],'MinionPro-Regular',fontSize-2) w += pdfmetrics.stringWidth(' ','MinionPro-Regular',fontSize) - if tooLong: + if tooLong and i == 0: w = 0 self.canvas.restoreState() From 569afbcc54ed22f7992735419f452e695cba9b0d Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:32:47 -0800 Subject: [PATCH 05/22] add edge-align-name option to make names more visible --- dominion_tabs.py | 105 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 30 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index a4fb930..7d3bc53 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -19,8 +19,8 @@ def split(l,n): class Card: def __init__(self,name,cardset,types,cost,description,potcost=0): - self.name = name - self.cardset = cardset + self.name = name.strip() + self.cardset = cardset.strip() self.types = types self.cost = cost self.potcost = potcost @@ -161,6 +161,17 @@ class DominionTabs: self.canvas.restoreState() + @classmethod + def nameWidth(self, name, fontSize): + w = 0 + name_parts = name.split() + for i, part in enumerate(name_parts): + if i != 0: + w += pdfmetrics.stringWidth(' ','MinionPro-Regular',fontSize) + w += pdfmetrics.stringWidth(part[0],'MinionPro-Regular',fontSize) + w += pdfmetrics.stringWidth(part[1:],'MinionPro-Regular',fontSize-2) + return w + def drawTab(self, card, rightSide): #draw tab flap self.canvas.saveState() @@ -202,15 +213,17 @@ class DominionTabs: textInset = 13 setImageHeight = 3 + card.getType().getTabTextHeightOffset() - textWidth -= textInset - #set image setImage = DominionTabs.setImages.get(card.cardset, None) if not setImage: setImage = DominionTabs.promoImages.get(card.name.lower(), None) + # always need to offset from right edge, to make sure it stays on + # banner + textInsetRight = 6 if setImage: self.canvas.drawImage(os.path.join(self.filedir,'images',setImage), self.tabLabelWidth-20, setImageHeight, 14, 12, mask='auto') + textInsetRight = 20 elif setImage == None and card.cardset != 'base' and card.getType().getTypeNames() != ('Expansion',): print 'warning, no set image for set "%s" card "%s"' % (card.cardset, card.name) DominionTabs.setImages[card.cardset] = 0 @@ -218,40 +231,61 @@ class DominionTabs: fontSize = 12 name = card.name.upper() - name_parts = name.partition(' / ') - if name_parts[1]: - name_parts = (name_parts[0] + ' /', name_parts[2]) - else: - name_parts = name.split() - width = pdfmetrics.stringWidth(name,'MinionPro-Regular',fontSize) + textWidth -= textInset + textWidth -= textInsetRight + + width = self.nameWidth(name, fontSize) while width > textWidth and fontSize > 8: fontSize -= 1 #print 'decreasing font size for tab of',name,'now',fontSize - width = pdfmetrics.stringWidth(name,'MinionPro-Regular',fontSize) + width = self.nameWidth(name, fontSize) tooLong = width > textWidth + if tooLong: + name_lines = name.partition(' / ') + if name_lines[1]: + name_lines = (name_lines[0] + ' /', name_lines[2]) + else: + name_lines = name.split(None, 1) + else: + name_lines = [name] #if tooLong: # print name - #self.canvas.drawString(tabLabelWidth/2+8,tabLabelHeight/2-7,name[0]) - w = 0 - for i,n in enumerate(name_parts): - self.canvas.setFont('MinionPro-Regular',fontSize) + for linenum, line in enumerate(name_lines): h = textHeight - if tooLong: - if i == 0: + if tooLong and len(name_lines) > 1: + if linenum == 0: h += h/2 else: h -= h/2 - self.canvas.drawString(textInset+w,h,n[0]) - w += pdfmetrics.stringWidth(n[0],'MinionPro-Regular',fontSize) - #self.canvas.drawString(tabLabelWidth/2+8+w,tabLabelHeight/2-7,name[1:]) - self.canvas.setFont('MinionPro-Regular',fontSize-2) - self.canvas.drawString(textInset+w,h,n[1:]) - w += pdfmetrics.stringWidth(n[1:],'MinionPro-Regular',fontSize-2) - w += pdfmetrics.stringWidth(' ','MinionPro-Regular',fontSize) - if tooLong and i == 0: - w = 0 + + if rightSide or not self.options.edge_align_name: + w = textInset + name_parts = line.split() + def drawWordPiece(text, fontSize): + self.canvas.setFont('MinionPro-Regular',fontSize) + if text != ' ': + self.canvas.drawString(w,h,text) + return pdfmetrics.stringWidth(text,'MinionPro-Regular',fontSize) + for word in name_parts: + w += drawWordPiece(word[0], fontSize) + w += drawWordPiece(word[1:], fontSize-2) + else: + # align text to the right if tab is on right side, to make + # tabs easier to read when grouped together extra 3pt is for + # space between text + set symbol + + w = self.tabLabelWidth - textInsetRight - 3 + name_parts = reversed(line.split()) + def drawWordPiece(text, fontSize): + self.canvas.setFont('MinionPro-Regular',fontSize) + if text != ' ': + self.canvas.drawRightString(w,h,text) + return -pdfmetrics.stringWidth(text,'MinionPro-Regular',fontSize) + for word in name_parts: + w += drawWordPiece(word[1:], fontSize-2) + w += drawWordPiece(word[0], fontSize) self.canvas.restoreState() def drawText(self, card, useExtra=False): @@ -283,7 +317,7 @@ class DominionTabs: def drawDivider(self,card,x,y,useExtra=False): #figure out whether the tab should go on the right side or not - if self.numTabsHorizontal % 2 == 0: + if not self.options.sameside: rightSide = x%2 == 1 else: rightSide = useExtra @@ -380,8 +414,8 @@ class DominionTabs: potcost = int(m.groupdict()["potioncost"]) else: potcost = 0 - currentCard = Card(m.groupdict()["name"], - m.groupdict()["set"].lower(), + currentCard = Card(m.groupdict()["name"].strip(), + m.groupdict()["set"].lower().strip(), tuple([t.strip() for t in m.groupdict()["type"].split("-")]), int(m.groupdict()["cost"]), '', @@ -491,7 +525,14 @@ class DominionTabs: parser.add_option("--tabwidth",type="float",default=4, help="width in cm of stick-up tab (ignored if tabs-only used)") parser.add_option("--samesidelabels",action="store_true",dest="sameside", - help="force all label tabs to be on the same side") + help="force all label tabs to be on the same side" + " (this will be forced on if there is an uneven" + " number of cards horizontally across the page)") + parser.add_option("--edge-align-name",action="store_true", + help="align the card name to the outside edge of the" + " tab, so that when using tabs on alternating sides," + " the name is less likely to be hidden by the tab" + " in front; ignored if samesidelabels is on") parser.add_option("--expansions",action="append",type="string", help="subset of dominion expansions to produce tabs for") parser.add_option("--cropmarks",action="store_true",dest="cropmarks", @@ -603,6 +644,10 @@ class DominionTabs: self.minHorizontalMargin = minmarginwidth self.minVerticalMargin = minmarginheight + if self.numTabsHorizontal % 2 != 0: + # force on sameside if an uneven # of tabs horizontally + self.options.sameside = True + if not fixedMargins: #dynamically max margins self.horizontalMargin = (self.paperwidth-self.numTabsHorizontal*self.totalTabWidth)/2 From 676e082b3b45743982ca50255202798066d6f94b Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:33:22 -0800 Subject: [PATCH 06/22] fix alignment of tabs on back of cards when using sameside option --- dominion_tabs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 7d3bc53..4af1522 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -125,7 +125,7 @@ class DominionTabs: self.canvas.setLineWidth(self.options.linewidth) cropmarksright = (x == self.numTabsHorizontal-1) cropmarksleft = (x == 0) - if rightSide and not self.options.sameside: + if rightSide: self.canvas.translate(self.tabWidth,0) self.canvas.scale(-1,1) if not self.options.cropmarks and not isBack: @@ -175,7 +175,7 @@ class DominionTabs: def drawTab(self, card, rightSide): #draw tab flap self.canvas.saveState() - if not rightSide or self.options.sameside: + if not rightSide: self.canvas.translate(self.tabWidth-self.tabLabelWidth, self.tabHeight-self.tabLabelHeight) else: From 2c4fe05fd9189fa12f3a7f4ae57f0863935c4de8 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:34:17 -0800 Subject: [PATCH 07/22] fix some missing vertical-line cropmarks --- dominion_tabs.py | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 4af1522..f68af6c 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -133,6 +133,8 @@ class DominionTabs: self.canvas.lines(self.tabOutline) elif self.options.cropmarks: cmw = 0.5*cm + + # Horizontal-line cropmarks mirror = cropmarksright and not rightSide or cropmarksleft and rightSide if mirror: self.canvas.saveState() @@ -145,19 +147,35 @@ class DominionTabs: self.canvas.line(-2*cmw,self.tabHeight,-cmw,self.tabHeight) if mirror: self.canvas.restoreState() + + # Vertical-line cropmarks + + # want to always draw the right-edge and middle-label-edge lines.. + # ...and draw the left-edge if this is the first card on the left + + # ...but we need to take mirroring into account, to know "where" + # to draw the left / right lines... + if rightSide: + leftLine = self.tabWidth + rightLine = 0 + else: + leftLine = 0 + rightLine = self.tabWidth + middleLine = self.tabWidth-self.tabLabelWidth + if y == 0: - self.canvas.line(self.tabWidth,-2*cmw,self.tabWidth,-cmw) - self.canvas.line(self.tabWidth-self.tabLabelWidth,-2*cmw,self.tabWidth-self.tabLabelWidth,-cmw) - if x == 0: - self.canvas.line(0,-2*cmw,0,-cmw) - elif y == self.numTabsVertical-1: - self.canvas.line(self.tabWidth,self.tabHeight+cmw,self.tabWidth,self.tabHeight+2*cmw) - self.canvas.line(self.tabWidth-self.tabLabelWidth, - self.tabHeight+cmw, - self.tabWidth-self.tabLabelWidth, - self.tabHeight+2*cmw) - if x == 0: - self.canvas.line(0,self.tabHeight+cmw,0,self.tabHeight+2*cmw) + self.canvas.line(rightLine,-2*cmw,rightLine,-cmw) + self.canvas.line(middleLine,-2*cmw,middleLine,-cmw) + if cropmarksleft: + self.canvas.line(leftLine,-2*cmw,leftLine,-cmw) + if y == self.numTabsVertical-1: + self.canvas.line(rightLine,self.tabHeight+cmw, + rightLine,self.tabHeight+2*cmw) + self.canvas.line(middleLine, self.tabHeight+cmw, + middleLine, self.tabHeight+2*cmw) + if cropmarksleft: + self.canvas.line(leftLine,self.tabHeight+cmw, + leftLine,self.tabHeight+2*cmw) self.canvas.restoreState() From 34aead2485a48f63b1731f92c892c859e68c5225 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:35:00 -0800 Subject: [PATCH 08/22] error if unknown extension given --- dominion_tabs.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index f68af6c..df0835e 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -706,7 +706,18 @@ class DominionTabs: if self.options.expansions: self.options.expansions = [o.lower() for o in self.options.expansions] - cards=[c for c in cards if c.cardset in self.options.expansions] + filteredCards = [] + knownExpansions = set() + for c in cards: + knownExpansions.add(c.cardset) + if c.cardset in self.options.expansions: + filteredCards.append(c) + unknownExpansions = set(self.options.expansions) - knownExpansions + if unknownExpansions: + print "Error - unknown expansion(s): %s" % ", ".join(unknownExpansions) + return + + cards = filteredCards if options.expansion_dividers: cardnamesByExpansion = {} From 896c86f349cdd809351663fb18a9e53448adf97a Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:35:37 -0800 Subject: [PATCH 09/22] fix for spaces in names --- dominion_tabs.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index df0835e..3091c97 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -278,15 +278,17 @@ class DominionTabs: else: h -= h/2 + words = line.split() if rightSide or not self.options.edge_align_name: w = textInset - name_parts = line.split() def drawWordPiece(text, fontSize): self.canvas.setFont('MinionPro-Regular',fontSize) if text != ' ': self.canvas.drawString(w,h,text) return pdfmetrics.stringWidth(text,'MinionPro-Regular',fontSize) - for word in name_parts: + for i, word in enumerate(words): + if i != 0: + w += drawWordPiece(' ', fontSize) w += drawWordPiece(word[0], fontSize) w += drawWordPiece(word[1:], fontSize-2) else: @@ -295,15 +297,17 @@ class DominionTabs: # space between text + set symbol w = self.tabLabelWidth - textInsetRight - 3 - name_parts = reversed(line.split()) + words.reverse() def drawWordPiece(text, fontSize): self.canvas.setFont('MinionPro-Regular',fontSize) if text != ' ': self.canvas.drawRightString(w,h,text) return -pdfmetrics.stringWidth(text,'MinionPro-Regular',fontSize) - for word in name_parts: + for i, word in enumerate(words): w += drawWordPiece(word[1:], fontSize-2) w += drawWordPiece(word[0], fontSize) + if i != len(words) - 1: + w += drawWordPiece(' ', fontSize) self.canvas.restoreState() def drawText(self, card, useExtra=False): From c06d2563b023beddbe386a83ea46429f9bcaad5e Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:36:08 -0800 Subject: [PATCH 10/22] make text-size decrease use increments of .1 (makes for larger / more readable text) --- dominion_tabs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 3091c97..5de3073 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -255,7 +255,7 @@ class DominionTabs: width = self.nameWidth(name, fontSize) while width > textWidth and fontSize > 8: - fontSize -= 1 + fontSize -= .01 #print 'decreasing font size for tab of',name,'now',fontSize width = self.nameWidth(name, fontSize) tooLong = width > textWidth From 8a08e180277a8121f303297467b8b3756c55acd7 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:36:54 -0800 Subject: [PATCH 11/22] add python hash-bang (for easier execution on POSIX oses) --- dominion_tabs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dominion_tabs.py b/dominion_tabs.py index 5de3073..4955d80 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -1,3 +1,4 @@ +#!python import re from optparse import OptionParser import os.path From 0f835c81b51ef64025e80541b60e678172992458 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:37:50 -0800 Subject: [PATCH 12/22] add option to hide / move cost --- dominion_tabs.py | 75 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 4955d80..10f720e 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -37,6 +37,9 @@ class Card: def toString(self): return self.name + ' ' + self.cardset + ' ' + '-'.join(self.types) + ' ' + `self.cost` + ' ' + self.description + ' ' + self.extra + def isExpansion(self): + return self.getType().getTypeNames() == ('Expansion',) + class CardType: def __init__(self, typeNames, tabImageFile, tabTextHeightOffset=0, tabCostHeightOffset=-1): self.typeNames = typeNames @@ -180,6 +183,27 @@ class DominionTabs: self.canvas.restoreState() + def drawCost(self, card, x, y, costOffset=-1): + # base width is 16 (for image) + 2 (1 pt border on each side) + width = 18 + + costHeight = y + costOffset + coinHeight = costHeight - 5 + potHeight = y - 3 + potSize = 11 + + self.canvas.drawImage(os.path.join(self.filedir,'images','coin_small.png'),x,coinHeight,16,16,preserveAspectRatio=True,mask='auto') + if card.potcost: + self.canvas.drawImage(os.path.join(self.filedir,'images','potion.png'),x+17,potHeight,potSize,potSize,preserveAspectRatio=True,mask=[255,255,255,255,255,255]) + width += potSize + + self.canvas.setFont('MinionPro-Bold',12) + cost = str(card.cost) + if 'Prize' in card.types: + cost += '*' + self.canvas.drawCentredString(x+8,costHeight,cost) + return width + @classmethod def nameWidth(self, name, fontSize): w = 0 @@ -207,30 +231,17 @@ class DominionTabs: self.tabLabelWidth-2,self.tabLabelHeight-1, preserveAspectRatio=False,anchor='n',mask='auto') - if card.getType().getTypeNames() != ('Expansion',): - textInset = 22 - - costHeight = textHeight + card.getType().getTabCostHeightOffset() - potHeight = 3 + card.getType().getTabTextHeightOffset() - potSize = 11 - - self.canvas.drawImage(os.path.join(self.filedir,'images','coin_small.png'),4,costHeight-5,16,16,preserveAspectRatio=True,mask='auto') - - if card.potcost: - self.canvas.drawImage(os.path.join(self.filedir,'images','potion.png'),21,potHeight,potSize,potSize,preserveAspectRatio=True,mask=[255,255,255,255,255,255]) - textInset += potSize - setImageHeight = potHeight - - self.canvas.setFont('MinionPro-Bold',12) - cost = str(card.cost) - if 'Prize' in card.types: - cost += '*' - costWidthOffset = 12 - self.canvas.drawCentredString(costWidthOffset,costHeight,cost) + setImageHeight = 3 + card.getType().getTabTextHeightOffset() + if not card.isExpansion(): + if 'tab' in self.options.cost: + textInset = 4 + textInset += self.drawCost(card, textInset, textHeight, + card.getType().getTabCostHeightOffset()) + else: + textInset = 6 else: textInset = 13 - setImageHeight = 3 + card.getType().getTabTextHeightOffset() #set image setImage = DominionTabs.setImages.get(card.cardset, None) @@ -243,7 +254,7 @@ class DominionTabs: if setImage: self.canvas.drawImage(os.path.join(self.filedir,'images',setImage), self.tabLabelWidth-20, setImageHeight, 14, 12, mask='auto') textInsetRight = 20 - elif setImage == None and card.cardset != 'base' and card.getType().getTypeNames() != ('Expansion',): + elif setImage == None and card.cardset != 'base' and not card.isExpansion(): print 'warning, no set image for set "%s" card "%s"' % (card.cardset, card.name) DominionTabs.setImages[card.cardset] = 0 DominionTabs.promoImages[card.name.lower()] = 0 @@ -312,19 +323,24 @@ class DominionTabs: self.canvas.restoreState() def drawText(self, card, useExtra=False): + height = 0 + textHeight = self.tabHeight - self.tabLabelHeight + 0.2*cm + + if 'body-top' in self.options.cost and not card.isExpansion(): + self.drawCost(card, cm/4.0, textHeight-0.7*cm) + height += 15 + #draw text if useExtra and card.extra: descriptions = (card.extra,) else: descriptions = re.split("\n",card.description) - height = 0 for d in descriptions: s = getSampleStyleSheet()['BodyText'] s.fontName = "Times-Roman" dmod = self.add_inline_images(d,s.fontSize) p = Paragraph(dmod,s) - textHeight = self.tabHeight - self.tabLabelHeight + 0.2*cm textWidth = self.tabWidth - cm w,h = p.wrap(textWidth,textHeight) @@ -556,6 +572,12 @@ class DominionTabs: " tab, so that when using tabs on alternating sides," " the name is less likely to be hidden by the tab" " in front; ignored if samesidelabels is on") + parser.add_option("--cost",action="append",type="choice", + choices=["tab", "body-top", "hide"], + help="where to display the card cost; may be set to" + " 'hide' to indicate it should not be displayed, or" + " given multiple times to show it in multiple" + " places - defaults to 'tab'", default=[]) parser.add_option("--expansions",action="append",type="string", help="subset of dominion expansions to produce tabs for") parser.add_option("--cropmarks",action="store_true",dest="cropmarks", @@ -573,7 +595,10 @@ class DominionTabs: parser.add_option("--expansion_dividers", action="store_true", dest="expansion_dividers", help="add dividers describing each expansion set") - return parser.parse_args(argstring) + options, args = parser.parse_args(argstring) + if not options.cost: + options.cost = ['tab'] + return options, args def main(self,argstring): options,args = DominionTabs.parse_opts(argstring) From 18fb56673e7c6aea7fd4a5d2e94b4a490142a1bc Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:39:39 -0800 Subject: [PATCH 13/22] add option to hide / move set icon --- dominion_tabs.py | 62 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 10f720e..039b64c 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -40,6 +40,17 @@ class Card: def isExpansion(self): return self.getType().getTypeNames() == ('Expansion',) + def setImage(self): + setImage = DominionTabs.setImages.get(self.cardset, None) + if not setImage: + setImage = DominionTabs.promoImages.get(self.name.lower(), None) + if setImage == None and self.cardset != 'base' and not self.isExpansion(): + print 'warning, no set image for set "%s" card "%s"' % (self.cardset, self.name) + DominionTabs.setImages[self.cardset] = 0 + DominionTabs.promoImages[self.name.lower()] = 0 + return setImage + + class CardType: def __init__(self, typeNames, tabImageFile, tabTextHeightOffset=0, tabCostHeightOffset=-1): self.typeNames = typeNames @@ -204,6 +215,10 @@ class DominionTabs: self.canvas.drawCentredString(x+8,costHeight,cost) return width + def drawSetIcon(self, setImage, x, y): + # set image + self.canvas.drawImage(os.path.join(self.filedir,'images',setImage), x, y, 14, 12, mask='auto') + @classmethod def nameWidth(self, name, fontSize): w = 0 @@ -227,12 +242,12 @@ class DominionTabs: textWidth = self.tabLabelWidth - 6 # allow for 3 pt border on each side textHeight = self.tabLabelHeight/2-7+card.getType().getTabTextHeightOffset() + # draw banner self.canvas.drawImage(os.path.join(self.filedir,'images',card.getType().getNoCoinTabImageFile()),1,0, self.tabLabelWidth-2,self.tabLabelHeight-1, preserveAspectRatio=False,anchor='n',mask='auto') - setImageHeight = 3 + card.getType().getTabTextHeightOffset() - + # draw cost if not card.isExpansion(): if 'tab' in self.options.cost: textInset = 4 @@ -243,22 +258,19 @@ class DominionTabs: else: textInset = 13 - #set image - setImage = DominionTabs.setImages.get(card.cardset, None) - if not setImage: - setImage = DominionTabs.promoImages.get(card.name.lower(), None) - - # always need to offset from right edge, to make sure it stays on - # banner - textInsetRight = 6 - if setImage: - self.canvas.drawImage(os.path.join(self.filedir,'images',setImage), self.tabLabelWidth-20, setImageHeight, 14, 12, mask='auto') + # draw set image + setImage = card.setImage() + if setImage and 'tab' in self.options.set_icon: + setImageHeight = 3 + card.getType().getTabTextHeightOffset() + self.drawSetIcon(setImage, self.tabLabelWidth-20, + setImageHeight) textInsetRight = 20 - elif setImage == None and card.cardset != 'base' and not card.isExpansion(): - print 'warning, no set image for set "%s" card "%s"' % (card.cardset, card.name) - DominionTabs.setImages[card.cardset] = 0 - DominionTabs.promoImages[card.name.lower()] = 0 + else: + # always need to offset from right edge, to make sure it stays on + # banner + textInsetRight = 6 + # draw name fontSize = 12 name = card.name.upper() @@ -326,8 +338,18 @@ class DominionTabs: height = 0 textHeight = self.tabHeight - self.tabLabelHeight + 0.2*cm + drewTopIcon = False if 'body-top' in self.options.cost and not card.isExpansion(): self.drawCost(card, cm/4.0, textHeight-0.7*cm) + drewTopIcon = True + + if 'body-top' in self.options.set_icon and not card.isExpansion(): + setImage = card.setImage() + if setImage: + self.drawSetIcon(setImage, self.tabWidth-16, + textHeight-0.7*cm-3) + drewTopIcon = True + if drewTopIcon: height += 15 #draw text @@ -578,6 +600,12 @@ class DominionTabs: " 'hide' to indicate it should not be displayed, or" " given multiple times to show it in multiple" " places - defaults to 'tab'", default=[]) + parser.add_option("--set-icon",action="append",type="choice", + choices=["tab", "body-top", "hide"], + help="where to display the set icon; may be set to" + " 'hide' to indicate it should not be displayed, or" + " given multiple times to show it in multiple" + " places - defaults to 'tab'", default=[]) parser.add_option("--expansions",action="append",type="string", help="subset of dominion expansions to produce tabs for") parser.add_option("--cropmarks",action="store_true",dest="cropmarks", @@ -598,6 +626,8 @@ class DominionTabs: options, args = parser.parse_args(argstring) if not options.cost: options.cost = ['tab'] + if not options.set_icon: + options.set_icon = ['tab'] return options, args def main(self,argstring): From eac2727407fd10e468f0bddeb1ea58cf611e8cb9 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:40:43 -0800 Subject: [PATCH 14/22] fix for fitting some long card descriptions into textbox (ie, Guilds - Herald) --- dominion_tabs.py | 53 +++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 039b64c..b7613d1 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -335,22 +335,22 @@ class DominionTabs: self.canvas.restoreState() def drawText(self, card, useExtra=False): - height = 0 - textHeight = self.tabHeight - self.tabLabelHeight + 0.2*cm + usedHeight = 0 + totalHeight = self.tabHeight - self.tabLabelHeight drewTopIcon = False if 'body-top' in self.options.cost and not card.isExpansion(): - self.drawCost(card, cm/4.0, textHeight-0.7*cm) + self.drawCost(card, cm/4.0, totalHeight - 0.5*cm) drewTopIcon = True if 'body-top' in self.options.set_icon and not card.isExpansion(): setImage = card.setImage() if setImage: self.drawSetIcon(setImage, self.tabWidth-16, - textHeight-0.7*cm-3) + totalHeight-0.5*cm-3) drewTopIcon = True if drewTopIcon: - height += 15 + usedHeight += 15 #draw text if useExtra and card.extra: @@ -358,23 +358,38 @@ class DominionTabs: else: descriptions = re.split("\n",card.description) - for d in descriptions: - s = getSampleStyleSheet()['BodyText'] - s.fontName = "Times-Roman" - dmod = self.add_inline_images(d,s.fontSize) - p = Paragraph(dmod,s) - textWidth = self.tabWidth - cm + s = getSampleStyleSheet()['BodyText'] + s.fontName = "Times-Roman" - w,h = p.wrap(textWidth,textHeight) - while h > textHeight: - s.fontSize -= 1 - s.leading -= 1 - #print 'decreasing fontsize on description for',card.name,'now',s.fontSize + textHorizontalMargin = .5*cm + textVerticalMargin = .3*cm + textBoxWidth = self.tabWidth - 2*textHorizontalMargin + textBoxHeight = totalHeight - usedHeight - 2*textVerticalMargin + spacerHeight = 0.2*cm + minSpacerHeight = 0.05*cm + + while True: + paragraphs = [] + # this accounts for the spacers we insert between paragraphs + h = (len(descriptions) - 1) * spacerHeight + for d in descriptions: dmod = self.add_inline_images(d,s.fontSize) p = Paragraph(dmod,s) - w,h = p.wrap(textWidth,textHeight) - p.drawOn(self.canvas,cm/2.0,textHeight-height-h-0.5*cm) - height += h + 0.2*cm + h += p.wrap(textBoxWidth, textBoxHeight)[1] + paragraphs.append(p) + + if h <= textBoxHeight or s.fontSize <= 1 or s.leading <= 1: + break + else: + s.fontSize -= 1 + s.leading -= 1 + spacerHeight = max(spacerHeight - 1, minSpacerHeight) + + h = totalHeight - usedHeight - textVerticalMargin + for p in paragraphs: + h -= p.height + p.drawOn(self.canvas, textHorizontalMargin, h) + h -= spacerHeight def drawDivider(self,card,x,y,useExtra=False): #figure out whether the tab should go on the right side or not From 7d63c0584bab503e75c5dc828f96deec3ae02084 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Mon, 23 Dec 2013 14:44:14 -0800 Subject: [PATCH 15/22] justify descriptions to make it all purty --- dominion_tabs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dominion_tabs.py b/dominion_tabs.py index b7613d1..87d3014 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -10,6 +10,7 @@ from reportlab.platypus import Paragraph from reportlab.lib.styles import getSampleStyleSheet from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase import pdfmetrics +from reportlab.lib.enums import TA_JUSTIFY def split(l,n): i = 0 @@ -360,6 +361,7 @@ class DominionTabs: s = getSampleStyleSheet()['BodyText'] s.fontName = "Times-Roman" + s.alignment = TA_JUSTIFY textHorizontalMargin = .5*cm textVerticalMargin = .3*cm From c0b7a0eb3fd0a0eec7ff60a1be367f2f1e129e6a Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Sun, 29 Dec 2013 08:13:51 -0800 Subject: [PATCH 16/22] marked "Hermit/Madman" card as belonging to Darg Ages Extras --- dominion_cards.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dominion_cards.txt b/dominion_cards.txt index 3910566..f44bf9d 100644 --- a/dominion_cards.txt +++ b/dominion_cards.txt @@ -460,7 +460,7 @@ If it’s the named card, put it into your hand. Necropolis: +2 Actions Overgrown Estate: 0 ; when you trash this, +1 Card. 43 Urchin / Mercenary Dark Ages Extras Action $3 Urchin: When you play this, you draw a card and get +1 Action, then each other player discards down to 4 cards in hand. Players who already have 4 or fewer cards in hand do not do anything. While Urchin is in play, when you play another Attack card, before resolving it, you may trash the Urchin. If you do, you gain a Mercenary. If there are no Mercenaries left you do not gain one. If you play the same Urchin twice in one turn, such as via Procession, that does not let you trash it for a Mercenary. If you play two different Urchins however, playing the second one will let you trash the first one. -44 Hermit / Madman Dark Ages Action $3 Hermit: When you play this, look through your discard pile, and then you may choose to trash a card that is not a Treasure, from either your hand or your discard pile. You do not have to trash a card and cannot trash Treasures. A card with multiple types, one of which is Treasure (such as Harem from Intrigue), is a Treasure. After trashing or not, you gain a card costing up to 3 Coins. The card you gain comes from the Supply and is put into your discard pile. Gaining a card is mandatory if it is possible. Then, when you discard Hermit from play - normally, in Clean-up, after playing it in your Action phase - if you did not buy any cards this turn, you trash Hermit and gain a Madman. It does not matter whether or not you gained cards other ways, only whether or not you bought a card. If there are no Madman cards left, you do not gain one. If Hermit is not discarded from play during Clean-up - for example, if you put it on your deck with Scheme (from Hinterlands) - then the ability that trashes it will not trigger. +44 Hermit / Madman Dark Ages Extras Action $3 Hermit: When you play this, look through your discard pile, and then you may choose to trash a card that is not a Treasure, from either your hand or your discard pile. You do not have to trash a card and cannot trash Treasures. A card with multiple types, one of which is Treasure (such as Harem from Intrigue), is a Treasure. After trashing or not, you gain a card costing up to 3 Coins. The card you gain comes from the Supply and is put into your discard pile. Gaining a card is mandatory if it is possible. Then, when you discard Hermit from play - normally, in Clean-up, after playing it in your Action phase - if you did not buy any cards this turn, you trash Hermit and gain a Madman. It does not matter whether or not you gained cards other ways, only whether or not you bought a card. If there are no Madman cards left, you do not gain one. If Hermit is not discarded from play during Clean-up - for example, if you put it on your deck with Scheme (from Hinterlands) - then the ability that trashes it will not trigger. 1 Advisor Guilds Action $4 +1 Action Reveal the top 3 cards of your deck. The player to your left chooses one of them. Discard that card. Put the other cards into your hand. 2 Baker Guilds Action $5 +1 Card From 062a6c0f5dfbd2698423c0b1a1d4d9b7e48137ec Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Sun, 29 Dec 2013 08:33:08 -0800 Subject: [PATCH 17/22] insert newlines between expansions in dominion_cards.txt better visual spacing, and will be stripped out from descriptions anyway --- dominion_cards.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dominion_cards.txt b/dominion_cards.txt index f44bf9d..1023de9 100644 --- a/dominion_cards.txt +++ b/dominion_cards.txt @@ -23,6 +23,7 @@ 23 Mine Dominion Action $5 Trash a Treasure card from your hand. Gain a Treasure card costing up to 3 Coins more; put it into your hand. 24 Witch Dominion Action - Attack $5 +2 Cards, Each other player gains a Curse card. 25 Adventurer Dominion Action $6 Reveal cards from your deck until you reveal 2 Treasure cards. Put those Treasure cards in your hand and discard the other revealed cards. + 1 Courtyard Intrigue Action $2 +3 Card, Put a card from your hand on top of your deck. 2 Pawn Intrigue Action $2 Choose two: +1 Card, +1 Action, +1 Buy, +1 Coin. (The choices must be different.). 3 Secret Chamber Intrigue Action - Reaction $2 Discard any number of cards. +1 Coin per card discarded. - When another player plays an Attack card, you may reveal this from your hand. If you do, +2 cards, then put 2 cards from your hand on top of your deck. @@ -49,6 +50,7 @@ 24 Harem Intrigue Treasure - Victory $6 Worth 2 Coins, 2 25 Nobles Intrigue Action - Victory $6 2 Choose one: +3 Cards, or +2 Actions. + 1 Embargo Seaside Action $2 +2 Coins, Trash this card. Put an Embargo token on top of a Supply pile. - When a player buys a card, he gains a Curse card per Embargo token on that pile. 2 Haven Seaside Action - Duration $2 +1 Card, +1 Action, Set aside a card from your hand face down. At the start of your next turn, put it into your hand. 3 Lighthouse Seaside Action - Duration $2 +1 Action, Now and at the start of your next turn: +1 Coin. - While this is in play, when another player plays an Attack card, it doesn't affect you. @@ -76,6 +78,7 @@ At the start of your next turn, +1 Card. 24 Tactician Seaside Action - Duration $5 Discard your hand. If you discarded any cards this way, then at the start of your next turn, +5 Cards, +1 Buy, and +1 Action. 25 Treasury Seaside Action $5 +1 Card, +1 Action, +1 Coin, When you discard this from play, if you didn't buy a Victory card this turn, you may put this on top of your deck. 26 Wharf Seaside Action - Duration $5 Now and at the start of your next turn: +2 Cards, +1 Buy. + 1 Transmute Alchemy Action $0 1P Trash a card from your hand. If it is an... Action card, gain a Duchy Treasure card, gain a Transmute @@ -179,6 +182,7 @@ When you play this, it`s worth 1 Coin per Treasure card you have in play (counti During your Buy phase, this costs 2 Coins less per Action card you have in play, but not less than 0 Coins. 26 Platinum Prosperity Treasure $9 Worth 5 Coins. 27 Colony Prosperity Victory $11 10 . + 1 Black Market Promo Action $3 +2 Coins, Reveal the top 3 cards of the Black Market deck. You may buy one of them immediately. Put the unbought cards on the bottom of the Black Market deck in any order. (Before the game, make a Black Market deck out of one copy of each Kingdom card not in the supply.). 2 Envoy Promo Action $4 Reveal the top 5 cards of your deck. The player to your left chooses one for you to discard. Draw the rest. @@ -187,8 +191,8 @@ During your Buy phase, this costs 2 Coins less per Action card you have in play, +2 Actions At the start of Clean-up, if you have this and no more than one other Action card in play, you may put this on top of your deck. 5 Governor Promo Action $5 +1 Action - Choose one; you get the version in parentheses: Each player gets +1 (+3) Cards; or each player gains a Silver (Gold); or each player may trash a card from his hand and gain a card costing exactly 1 Coin (2 Coins) more. + 1 Copper Base Treasure $0 Worth 1 Coin. 2 Curse Base Curse $0 -1 3 Estate Base Victory $2 1 @@ -201,7 +205,6 @@ Choose one; you get the version in parentheses: Each player gets +1 (+3) Cards; 10 Colony Base Victory $11 10 11 Trash Base Action $0 Pile of trash. - 1 Bag of Gold Cornucopia Action - Prize $0 +1 Action Gain a Gold, putting it on top of your deck. (This is not in the Supply.) @@ -248,6 +251,7 @@ Reveal your hand. Reveal cards from your deck until you reveal a card that isn 17 Jester Cornucopia Action - Attack $5 +2 Coins Each other player discards the top card of his deck. If it’s a Victory card he gains a Curse. Otherwise he gains a copy of the discarded card or you do, your choice. 18 Fairgrounds Cornucopia Victory $6 Worth 2 for every 5 differently named cards in your deck (rounded down) + 1 Crossroads Hinterlands Action $2 Reveal your hand. +1 Card per Victory card revealed. If this is the first time you played a Crossroads this turn, +3 Actions. 2 Duchess Hinterlands Action $2 +2 Coins @@ -328,6 +332,7 @@ When you gain this, gain a card costing less than this. 26 Farmland Hinterlands Victory $6 2 ---------- When you buy this, trash a card from your hand. Gain a card costing exactly 2 Coins more than the trashed card. + 1 Ruins Dark Ages Action - Ruins $0 Abandoned Mine: +1 Coin Ruined Library: +1 Card Ruined Marked: :1 Buy @@ -461,6 +466,7 @@ Necropolis: +2 Actions Overgrown Estate: 0 ; when you trash this, +1 Card. 43 Urchin / Mercenary Dark Ages Extras Action $3 Urchin: When you play this, you draw a card and get +1 Action, then each other player discards down to 4 cards in hand. Players who already have 4 or fewer cards in hand do not do anything. While Urchin is in play, when you play another Attack card, before resolving it, you may trash the Urchin. If you do, you gain a Mercenary. If there are no Mercenaries left you do not gain one. If you play the same Urchin twice in one turn, such as via Procession, that does not let you trash it for a Mercenary. If you play two different Urchins however, playing the second one will let you trash the first one. 44 Hermit / Madman Dark Ages Extras Action $3 Hermit: When you play this, look through your discard pile, and then you may choose to trash a card that is not a Treasure, from either your hand or your discard pile. You do not have to trash a card and cannot trash Treasures. A card with multiple types, one of which is Treasure (such as Harem from Intrigue), is a Treasure. After trashing or not, you gain a card costing up to 3 Coins. The card you gain comes from the Supply and is put into your discard pile. Gaining a card is mandatory if it is possible. Then, when you discard Hermit from play - normally, in Clean-up, after playing it in your Action phase - if you did not buy any cards this turn, you trash Hermit and gain a Madman. It does not matter whether or not you gained cards other ways, only whether or not you bought a card. If there are no Madman cards left, you do not gain one. If Hermit is not discarded from play during Clean-up - for example, if you put it on your deck with Scheme (from Hinterlands) - then the ability that trashes it will not trigger. + 1 Advisor Guilds Action $4 +1 Action Reveal the top 3 cards of your deck. The player to your left chooses one of them. Discard that card. Put the other cards into your hand. 2 Baker Guilds Action $5 +1 Card From 1c1b2d5025670832c636d1bec03afd4b4b75612b Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Sun, 29 Dec 2013 08:46:30 -0800 Subject: [PATCH 18/22] dominion_card_extras.txt: add rules for copper/silver/gold, saying how many cards to use --- dominion_card_extras.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dominion_card_extras.txt b/dominion_card_extras.txt index 387875a..80b8626 100644 --- a/dominion_card_extras.txt +++ b/dominion_card_extras.txt @@ -1,6 +1,9 @@ :::Copper +60 cards per game. :::Silver +40 cards per game. :::Gold +30 cards per game. :::Estate Put 8 in the Supply in a game with two players. @@ -2066,4 +2069,4 @@ cards in your deck, it becomes the only card in your deck. You do not have to gain a more expensive Treasure; you may gain a Treasure with the same cost, or a cheaper Treasure. You have to gain a card if you trashed one though, if possible. The gained -Treasure comes from the Supply. \ No newline at end of file +Treasure comes from the Supply. From 90c863a409d45f9c9085a763b896f6d85c93a5c8 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Sun, 29 Dec 2013 08:52:54 -0800 Subject: [PATCH 19/22] allow float for back_offset option --- dominion_tabs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 87d3014..4e3964d 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -589,7 +589,7 @@ class DominionTabs: @staticmethod def parse_opts(argstring): parser = OptionParser() - parser.add_option("--back_offset",type="int",dest="back_offset",default=0, + parser.add_option("--back_offset",type="float",dest="back_offset",default=0, help="Points to offset the back page to the right; needed for some printers") parser.add_option("--orientation",type="choice",choices=["horizontal","vertical"],dest="orientation",default="horizontal", help="horizontal or vertical, default:horizontal") From 4d1fee18acaebf122d49da40a9ab20607d16ab34 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Sun, 29 Dec 2013 08:56:26 -0800 Subject: [PATCH 20/22] print valid choices for cost/set-icon in help --- dominion_tabs.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 4e3964d..a383d92 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -586,8 +586,12 @@ class DominionTabs: self.canvas.restoreState() self.canvas.showPage() - @staticmethod - def parse_opts(argstring): + + + LOCATION_CHOICES = ["tab", "body-top", "hide"] + + @classmethod + def parse_opts(cls, argstring): parser = OptionParser() parser.add_option("--back_offset",type="float",dest="back_offset",default=0, help="Points to offset the back page to the right; needed for some printers") @@ -612,17 +616,19 @@ class DominionTabs: " the name is less likely to be hidden by the tab" " in front; ignored if samesidelabels is on") parser.add_option("--cost",action="append",type="choice", - choices=["tab", "body-top", "hide"], + choices=cls.LOCATION_CHOICES, default=[], help="where to display the card cost; may be set to" " 'hide' to indicate it should not be displayed, or" " given multiple times to show it in multiple" - " places - defaults to 'tab'", default=[]) + " places; valid values are: %s; defaults to 'tab'" + % ", ".join("'%s'" % x for x in cls.LOCATION_CHOICES)) parser.add_option("--set-icon",action="append",type="choice", - choices=["tab", "body-top", "hide"], + choices=cls.LOCATION_CHOICES, default=[], help="where to display the set icon; may be set to" " 'hide' to indicate it should not be displayed, or" " given multiple times to show it in multiple" - " places - defaults to 'tab'", default=[]) + " places; valid values are: %s; defaults to 'tab'" + % ", ".join("'%s'" % x for x in cls.LOCATION_CHOICES)) parser.add_option("--expansions",action="append",type="string", help="subset of dominion expansions to produce tabs for") parser.add_option("--cropmarks",action="store_true",dest="cropmarks", From 1fc85dc1a2b4cb4282a5ded796e1c09952975717 Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Sun, 29 Dec 2013 09:11:22 -0800 Subject: [PATCH 21/22] add base_cards_with_expansion option --- dominion_cards.txt | 32 ++++++++++++++++++++++++-------- dominion_tabs.py | 30 ++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/dominion_cards.txt b/dominion_cards.txt index 1023de9..33570dc 100644 --- a/dominion_cards.txt +++ b/dominion_cards.txt @@ -23,6 +23,14 @@ 23 Mine Dominion Action $5 Trash a Treasure card from your hand. Gain a Treasure card costing up to 3 Coins more; put it into your hand. 24 Witch Dominion Action - Attack $5 +2 Cards, Each other player gains a Curse card. 25 Adventurer Dominion Action $6 Reveal cards from your deck until you reveal 2 Treasure cards. Put those Treasure cards in your hand and discard the other revealed cards. +26 Copper Dominion Treasure $0 Worth 1 Coin. +27 Silver Dominion Treasure $3 Worth 2 Coins. +28 Gold Dominion Treasure $6 Worth 3 Coins. +29 Curse Dominion Curse $0 -1 +30 Estate Dominion Victory $2 1 +31 Duchy Dominion Victory $5 3 +32 Province Dominion Victory $8 6 +33 Trash Dominion Action $0 Pile of trash. 1 Courtyard Intrigue Action $2 +3 Card, Put a card from your hand on top of your deck. 2 Pawn Intrigue Action $2 Choose two: +1 Card, +1 Action, +1 Buy, +1 Coin. (The choices must be different.). @@ -50,6 +58,14 @@ 24 Harem Intrigue Treasure - Victory $6 Worth 2 Coins, 2 25 Nobles Intrigue Action - Victory $6 2 Choose one: +3 Cards, or +2 Actions. +26 Copper Intrigue Treasure $0 Worth 1 Coin. +27 Silver Intrigue Treasure $3 Worth 2 Coins. +28 Gold Intrigue Treasure $6 Worth 3 Coins. +29 Curse Intrigue Curse $0 -1 +30 Estate Intrigue Victory $2 1 +31 Duchy Intrigue Victory $5 3 +32 Province Intrigue Victory $8 6 +33 Trash Intrigue Action $0 Pile of trash. 1 Embargo Seaside Action $2 +2 Coins, Trash this card. Put an Embargo token on top of a Supply pile. - When a player buys a card, he gains a Curse card per Embargo token on that pile. 2 Haven Seaside Action - Duration $2 +1 Card, +1 Action, Set aside a card from your hand face down. At the start of your next turn, put it into your hand. @@ -194,14 +210,14 @@ At the start of Clean-up, if you have this and no more than one other Action car Choose one; you get the version in parentheses: Each player gets +1 (+3) Cards; or each player gains a Silver (Gold); or each player may trash a card from his hand and gain a card costing exactly 1 Coin (2 Coins) more. 1 Copper Base Treasure $0 Worth 1 Coin. -2 Curse Base Curse $0 -1 -3 Estate Base Victory $2 1 -4 Silver Base Treasure $3 Worth 2 Coins. -5 Duchy Base Victory $5 3 -6 Gold Base Treasure $6 Worth 3 Coins. -7 Province Base Victory $8 6 -8 Potion Base Treasure $4 Worth 1 Potion. -9 Platinum Base Treasure $9 Worth 5 Coins. +2 Silver Base Treasure $3 Worth 2 Coins. +3 Gold Base Treasure $6 Worth 3 Coins. +4 Platinum Base Treasure $9 Worth 5 Coins. +5 Potion Base Treasure $4 Worth 1 Potion. +6 Curse Base Curse $0 -1 +7 Estate Base Victory $2 1 +8 Duchy Base Victory $5 3 +9 Province Base Victory $8 6 10 Colony Base Victory $11 10 11 Trash Base Action $0 Pile of trash. diff --git a/dominion_tabs.py b/dominion_tabs.py index a383d92..688ed23 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -645,6 +645,10 @@ class DominionTabs: help="sort order for the cards, whether by expansion or globally alphabetical") parser.add_option("--expansion_dividers", action="store_true", dest="expansion_dividers", help="add dividers describing each expansion set") + parser.add_option("--base_cards_with_expansion", action="store_true", + help='print the base cards as part of the expansion; ie, a divider for "Silver"' + 'will be printed as both a "Dominion" card and as an "Intrigue" card; if this' + 'option is not given, all base cards are placed in their own "Base" expansion') options, args = parser.parse_args(argstring) if not options.cost: @@ -787,6 +791,15 @@ class DominionTabs: cards = self.read_card_defs(os.path.join(self.filedir,"dominion_cards.txt")) self.read_card_extras(os.path.join(self.filedir,"dominion_card_extras.txt"),cards) + + baseCards = [card.name for card in cards if card.cardset.lower() == 'base'] + def isBaseExpansionCard(card): + return card.cardset.lower() != base and card.name in baseCards + if self.options.base_cards_with_expansion: + cards = [card for card in cards if card.cardset.lower() != 'base'] + else: + cards = [card for card in cards if not isBaseExpansionCard(card)] + if self.options.expansions: self.options.expansions = [o.lower() for o in self.options.expansions] filteredCards = [] @@ -805,6 +818,8 @@ class DominionTabs: if options.expansion_dividers: cardnamesByExpansion = {} for c in cards: + if isBaseExpansionCard(c): + continue cardnamesByExpansion.setdefault(c.cardset,[]).append(c.name.strip()) for exp,names in cardnamesByExpansion.iteritems(): c = Card(exp, exp, ("Expansion",), None, ' | '.join(sorted(names))) @@ -815,10 +830,21 @@ class DominionTabs: out = yaml.dump(cards) open('cards.yaml','w').write(out) + # When sorting cards, want to always put "base" cards after all + # kingdom cards, and order the base cards in a set order - the + # order they are listed in the database (ie, all normal treasures + # by worth, then potion, then all normal VP cards by worth, then + # trash) + def baseIndex(name): + try: + return baseCards.index(name) + except Exception: + return -1 + if options.order == "global": - sortKey = lambda x: x.name + sortKey = lambda x: (int(x.isExpansion()), baseIndex(x.name),x.name) else: - sortKey = lambda x: (x.cardset,x.name) + sortKey = lambda x: (x.cardset,int(x.isExpansion()),baseIndex(x.name),x.name) cards.sort(key=sortKey) if not f: From 105581602abfb986c21b6900bdc3790e110de57c Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Sun, 29 Dec 2013 09:17:11 -0800 Subject: [PATCH 22/22] standardize my new options to use underscores, not dashes --- dominion_tabs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dominion_tabs.py b/dominion_tabs.py index 688ed23..159d043 100644 --- a/dominion_tabs.py +++ b/dominion_tabs.py @@ -610,7 +610,7 @@ class DominionTabs: help="force all label tabs to be on the same side" " (this will be forced on if there is an uneven" " number of cards horizontally across the page)") - parser.add_option("--edge-align-name",action="store_true", + parser.add_option("--edge_align_name",action="store_true", help="align the card name to the outside edge of the" " tab, so that when using tabs on alternating sides," " the name is less likely to be hidden by the tab" @@ -622,7 +622,7 @@ class DominionTabs: " given multiple times to show it in multiple" " places; valid values are: %s; defaults to 'tab'" % ", ".join("'%s'" % x for x in cls.LOCATION_CHOICES)) - parser.add_option("--set-icon",action="append",type="choice", + parser.add_option("--set_icon",action="append",type="choice", choices=cls.LOCATION_CHOICES, default=[], help="where to display the set icon; may be set to" " 'hide' to indicate it should not be displayed, or"