pywargame 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. pywargame/__init__.py +2 -0
  2. pywargame/common/__init__.py +3 -0
  3. pywargame/common/collector.py +87 -0
  4. pywargame/common/dicedraw.py +363 -0
  5. pywargame/common/drawdice.py +40 -0
  6. pywargame/common/singleton.py +22 -0
  7. pywargame/common/test.py +25 -0
  8. pywargame/common/verbose.py +59 -0
  9. pywargame/common/verboseguard.py +53 -0
  10. pywargame/cyberboard/__init__.py +18 -0
  11. pywargame/cyberboard/archive.py +283 -0
  12. pywargame/cyberboard/base.py +63 -0
  13. pywargame/cyberboard/board.py +462 -0
  14. pywargame/cyberboard/cell.py +200 -0
  15. pywargame/cyberboard/collect.py +49 -0
  16. pywargame/cyberboard/collectgbx0pwd.py +30 -0
  17. pywargame/cyberboard/collectgbxext.py +30 -0
  18. pywargame/cyberboard/collectgsnexp.py +32 -0
  19. pywargame/cyberboard/collectgsnext.py +30 -0
  20. pywargame/cyberboard/draw.py +396 -0
  21. pywargame/cyberboard/exporter.py +1132 -0
  22. pywargame/cyberboard/extractor.py +240 -0
  23. pywargame/cyberboard/features.py +17 -0
  24. pywargame/cyberboard/gamebox.py +81 -0
  25. pywargame/cyberboard/gbxexp.py +76 -0
  26. pywargame/cyberboard/gbxext.py +64 -0
  27. pywargame/cyberboard/gsnexp.py +147 -0
  28. pywargame/cyberboard/gsnext.py +59 -0
  29. pywargame/cyberboard/head.py +111 -0
  30. pywargame/cyberboard/image.py +76 -0
  31. pywargame/cyberboard/main.py +47 -0
  32. pywargame/cyberboard/mark.py +102 -0
  33. pywargame/cyberboard/palette.py +36 -0
  34. pywargame/cyberboard/piece.py +169 -0
  35. pywargame/cyberboard/player.py +36 -0
  36. pywargame/cyberboard/scenario.py +115 -0
  37. pywargame/cyberboard/testgrid.py +156 -0
  38. pywargame/cyberboard/tile.py +121 -0
  39. pywargame/cyberboard/tray.py +68 -0
  40. pywargame/cyberboard/windows.py +41 -0
  41. pywargame/cyberboard/zeropwd.py +45 -0
  42. pywargame/cyberboard.py +2728 -0
  43. pywargame/gbx0pwd.py +2776 -0
  44. pywargame/gbxextract.py +2795 -0
  45. pywargame/gsnexport.py +16499 -0
  46. pywargame/gsnextract.py +2790 -0
  47. pywargame/latex/__init__.py +2 -0
  48. pywargame/latex/collect.py +34 -0
  49. pywargame/latex/latexexporter.py +4010 -0
  50. pywargame/latex/main.py +184 -0
  51. pywargame/vassal/__init__.py +66 -0
  52. pywargame/vassal/base.py +139 -0
  53. pywargame/vassal/board.py +243 -0
  54. pywargame/vassal/buildfile.py +60 -0
  55. pywargame/vassal/chart.py +79 -0
  56. pywargame/vassal/chessclock.py +197 -0
  57. pywargame/vassal/collect.py +98 -0
  58. pywargame/vassal/collectpatch.py +28 -0
  59. pywargame/vassal/command.py +21 -0
  60. pywargame/vassal/documentation.py +322 -0
  61. pywargame/vassal/dumpcollect.py +28 -0
  62. pywargame/vassal/dumpvsav.py +28 -0
  63. pywargame/vassal/element.py +439 -0
  64. pywargame/vassal/exporter.py +89 -0
  65. pywargame/vassal/extension.py +101 -0
  66. pywargame/vassal/folder.py +103 -0
  67. pywargame/vassal/game.py +940 -0
  68. pywargame/vassal/gameelements.py +1091 -0
  69. pywargame/vassal/globalkey.py +127 -0
  70. pywargame/vassal/globalproperty.py +433 -0
  71. pywargame/vassal/grid.py +573 -0
  72. pywargame/vassal/map.py +1061 -0
  73. pywargame/vassal/mapelements.py +1020 -0
  74. pywargame/vassal/merge.py +57 -0
  75. pywargame/vassal/merger.py +460 -0
  76. pywargame/vassal/moduledata.py +275 -0
  77. pywargame/vassal/mrgcollect.py +31 -0
  78. pywargame/vassal/patch.py +44 -0
  79. pywargame/vassal/patchcollect.py +28 -0
  80. pywargame/vassal/player.py +83 -0
  81. pywargame/vassal/save.py +495 -0
  82. pywargame/vassal/skel.py +380 -0
  83. pywargame/vassal/trait.py +224 -0
  84. pywargame/vassal/traits/__init__.py +36 -0
  85. pywargame/vassal/traits/area.py +50 -0
  86. pywargame/vassal/traits/basic.py +35 -0
  87. pywargame/vassal/traits/calculatedproperty.py +22 -0
  88. pywargame/vassal/traits/cargo.py +29 -0
  89. pywargame/vassal/traits/click.py +41 -0
  90. pywargame/vassal/traits/clone.py +28 -0
  91. pywargame/vassal/traits/delete.py +24 -0
  92. pywargame/vassal/traits/deselect.py +32 -0
  93. pywargame/vassal/traits/dynamicproperty.py +112 -0
  94. pywargame/vassal/traits/globalcommand.py +55 -0
  95. pywargame/vassal/traits/globalhotkey.py +26 -0
  96. pywargame/vassal/traits/globalproperty.py +54 -0
  97. pywargame/vassal/traits/hide.py +67 -0
  98. pywargame/vassal/traits/label.py +76 -0
  99. pywargame/vassal/traits/layer.py +105 -0
  100. pywargame/vassal/traits/mark.py +20 -0
  101. pywargame/vassal/traits/mask.py +85 -0
  102. pywargame/vassal/traits/mat.py +26 -0
  103. pywargame/vassal/traits/moved.py +35 -0
  104. pywargame/vassal/traits/movefixed.py +51 -0
  105. pywargame/vassal/traits/nonrect.py +95 -0
  106. pywargame/vassal/traits/nostack.py +55 -0
  107. pywargame/vassal/traits/place.py +104 -0
  108. pywargame/vassal/traits/prototype.py +20 -0
  109. pywargame/vassal/traits/report.py +34 -0
  110. pywargame/vassal/traits/restrictaccess.py +28 -0
  111. pywargame/vassal/traits/restrictcommand.py +32 -0
  112. pywargame/vassal/traits/return.py +40 -0
  113. pywargame/vassal/traits/rotate.py +62 -0
  114. pywargame/vassal/traits/sendto.py +59 -0
  115. pywargame/vassal/traits/sheet.py +129 -0
  116. pywargame/vassal/traits/skel.py +9 -0
  117. pywargame/vassal/traits/stack.py +28 -0
  118. pywargame/vassal/traits/submenu.py +27 -0
  119. pywargame/vassal/traits/trail.py +61 -0
  120. pywargame/vassal/traits/trigger.py +72 -0
  121. pywargame/vassal/turn.py +272 -0
  122. pywargame/vassal/upgrade.py +191 -0
  123. pywargame/vassal/vmod.py +323 -0
  124. pywargame/vassal/vsav.py +100 -0
  125. pywargame/vassal/widget.py +358 -0
  126. pywargame/vassal/withtraits.py +634 -0
  127. pywargame/vassal/xml.py +4 -0
  128. pywargame/vassal/zone.py +399 -0
  129. pywargame/vassal.py +12500 -0
  130. pywargame/vmodpatch.py +12548 -0
  131. pywargame/vsavdump.py +12533 -0
  132. pywargame/vslmerge.py +13015 -0
  133. pywargame/wgexport.py +16689 -0
  134. pywargame/ztexport.py +14351 -0
  135. pywargame/zuntzu/__init__.py +5 -0
  136. pywargame/zuntzu/base.py +82 -0
  137. pywargame/zuntzu/collect.py +38 -0
  138. pywargame/zuntzu/countersheet.py +250 -0
  139. pywargame/zuntzu/dicehand.py +48 -0
  140. pywargame/zuntzu/exporter.py +936 -0
  141. pywargame/zuntzu/gamebox.py +154 -0
  142. pywargame/zuntzu/map.py +36 -0
  143. pywargame/zuntzu/piece.py +37 -0
  144. pywargame/zuntzu/scenario.py +208 -0
  145. pywargame/zuntzu/ztexp.py +115 -0
  146. pywargame-0.3.1.dist-info/METADATA +353 -0
  147. pywargame-0.3.1.dist-info/RECORD +150 -0
  148. pywargame-0.3.1.dist-info/WHEEL +5 -0
  149. pywargame-0.3.1.dist-info/licenses/LICENSE +5 -0
  150. pywargame-0.3.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env python
2
+ ## BEGIN_IMPORTS
3
+ from latexexporter import LaTeXExporter
4
+ from vassal.vmod import VMod
5
+ from common import Verbose
6
+ ## END_IMPORTS
7
+
8
+ from argparse import ArgumentParser
9
+
10
+ class DefaultSubcommandArgParse(ArgumentParser):
11
+ _default_subparser = None
12
+
13
+ def set_default_subparser(self, name):
14
+ self._default_subparser = name
15
+
16
+ def _parse_known_args(self, arg_strings, *args, **kwargs):
17
+ from argparse import _SubParsersAction
18
+ in_args = set(arg_strings)
19
+ d_sp = self._default_subparser
20
+ if d_sp is not None and not {'-h', '--help'}.intersection(in_args):
21
+ for x in self._subparsers._actions:
22
+ subparser_found = (
23
+ isinstance(x, _SubParsersAction) and
24
+ in_args.intersection(x._name_parser_map.keys())
25
+ )
26
+ if subparser_found:
27
+ break
28
+ else:
29
+ # insert default in first position, this implies no
30
+ # global options without a sub_parsers specified
31
+ arg_strings = [d_sp] + arg_strings
32
+ return super(DefaultSubcommandArgParse, self)._parse_known_args(
33
+ arg_strings, *args, **kwargs
34
+ )
35
+ # ====================================================================
36
+ def patchIt(args):
37
+ vmodname = args.output.name
38
+ patchname = args.patch.name
39
+ args.output.close()
40
+ args.patch .close()
41
+
42
+ VMod.patch(vmodname, patchname, args.verbose)
43
+
44
+ # ====================================================================
45
+ def exportIt(args):
46
+
47
+ vmodname = args.output.name
48
+ patchname = args.patch.name if args.patch is not None else None
49
+
50
+ args.output.close()
51
+ if args.patch is not None:
52
+ args.patch.close()
53
+
54
+ Verbose().setVerbose(args.verbose)
55
+
56
+ try:
57
+ if args.version.lower() == 'draft':
58
+ args.visible_grids = True
59
+
60
+ rulesname = args.rules.name if args.rules is not None else None
61
+ tutname = args.tutorial.name if args.tutorial is not None else None
62
+
63
+ exporter = LaTeXExporter(vmodname = vmodname,
64
+ pdfname = args.pdffile.name,
65
+ infoname = args.infofile.name,
66
+ title = args.title,
67
+ version = args.version,
68
+ description = args.description,
69
+ rules = rulesname,
70
+ tutorial = tutname,
71
+ patch = patchname,
72
+ visible = args.visible_grids,
73
+ vassalVersion = args.vassal_version,
74
+ nonato = args.no_nato_prototypes,
75
+ nochit = args.no_chit_information,
76
+ resolution = args.resolution,
77
+ counterScale = args.counter_scale,
78
+ imageFormat = args.image_format)
79
+ exporter.run()
80
+ except Exception as e:
81
+ from sys import stderr
82
+ print(f'Failed to build {vmodname}: {e}',file=stderr)
83
+ from os import unlink
84
+ try:
85
+ unlink(vmodname)
86
+ except:
87
+ pass
88
+
89
+ raise e
90
+
91
+
92
+ # ====================================================================
93
+ if __name__ == '__main__':
94
+ from argparse import ArgumentParser, FileType
95
+
96
+ ap = DefaultSubcommandArgParse(description='Create draft VASSAL module')
97
+ ap.set_default_subparser('export')
98
+ sp = ap.add_subparsers(dest='mode')
99
+
100
+ pp = sp.add_parser('patch',help='Patch VMod')
101
+ pp.add_argument('output',
102
+ help='Module to patch',
103
+ type=FileType('r'),
104
+ default='Draft.vmod')
105
+ pp.add_argument('patch',
106
+ help='A python script to patch generated module',
107
+ type=FileType('r'),
108
+ default='patch.py')
109
+ pp.add_argument('-V','--verbose',
110
+ help='Be verbose',
111
+ action='store_true')
112
+
113
+
114
+ ep = sp.add_parser('export',help='Export from PDF and JSON to VMod')
115
+ ep.add_argument('pdffile',
116
+ help='The PDF file to read images from',
117
+ type=FileType('r'),
118
+ default='export.pdf',
119
+ nargs='?')
120
+ ep.add_argument('infofile',
121
+ help='The JSON file to read image information from',
122
+ type=FileType('r'),
123
+ default='export.json',
124
+ nargs='?')
125
+ ep.add_argument('-o','--output',
126
+ help='Output file to write module to',
127
+ type=FileType('w'),
128
+ default='Draft.vmod')
129
+ ep.add_argument('-p','--patch',
130
+ help='A python script to patch generated module',
131
+ type=FileType('r'))
132
+ ep.add_argument('-V','--verbose',
133
+ help='Be verbose',
134
+ action='store_true')
135
+ ep.add_argument('-t','--title',
136
+ help='Module title', default='Draft',
137
+ type=str)
138
+ ep.add_argument('-v','--version',
139
+ help='Module version',
140
+ type=str,
141
+ default='draft')
142
+ ep.add_argument('-r','--rules',
143
+ help='Rules PDF file',
144
+ type=FileType('r'))
145
+ ep.add_argument('-T','--tutorial',
146
+ help='Tutorial (v)log file',
147
+ type=FileType('r'))
148
+ ep.add_argument('-d','--description',
149
+ help='Short description of module',
150
+ type=str,
151
+ default='draft of module')
152
+ ep.add_argument('-W','--vassal-version',
153
+ help='Vassal version number',
154
+ type=str,
155
+ default='3.7.12')
156
+ ep.add_argument('-G','--visible-grids',
157
+ action='store_true',
158
+ help='Make grids visible in the module')
159
+ ep.add_argument('-N','--no-nato-prototypes',
160
+ action='store_true',
161
+ help='Do not make prototypes for types,echelons,commands')
162
+ ep.add_argument('-C','--no-chit-information',
163
+ action='store_true',
164
+ help='Do not make properties from chit information')
165
+ ep.add_argument('-S','--counter-scale',
166
+ type=float, default=1,
167
+ help='Scale counters by factor')
168
+ ep.add_argument('-R','--resolution',
169
+ type=int, default=150,
170
+ help='Resolution of images')
171
+ ep.add_argument('-I','--image-format',
172
+ choices = ['png','svg'], default='png',
173
+ help='Image format to use')
174
+
175
+ args = ap.parse_args()
176
+
177
+ if args.mode == 'patch':
178
+ patchIt(args)
179
+ else:
180
+ exportIt(args)
181
+
182
+ #
183
+ # EOF
184
+ #
@@ -0,0 +1,66 @@
1
+ '''
2
+ Module to manipulate a VASSAL module (VMOD)
3
+ '''
4
+ from . base import *
5
+ from . element import *
6
+ from . folder import *
7
+ from . globalkey import *
8
+ from . gameelements import *
9
+ from . mapelements import *
10
+ from . globalproperty import *
11
+ from . turn import *
12
+ from . documentation import *
13
+ from . player import *
14
+ from . widget import *
15
+ from . grid import *
16
+ from . zone import *
17
+ from . board import *
18
+ from . map import *
19
+ from . chart import *
20
+ from . command import *
21
+ from . trait import *
22
+ from . withtraits import *
23
+ from . extension import *
24
+ from . traits.area import *
25
+ from . traits.clone import *
26
+ from . traits.dynamicproperty import *
27
+ from . traits.globalproperty import *
28
+ from . traits.prototype import *
29
+ from . traits.place import *
30
+ from . traits.report import *
31
+ from . traits.calculatedproperty import *
32
+ from . traits.restrictcommand import *
33
+ from . traits.label import *
34
+ from . traits.layer import *
35
+ from . traits.globalcommand import *
36
+ from . traits.globalhotkey import *
37
+ from . traits.nostack import *
38
+ from . traits.deselect import *
39
+ from . traits.restrictaccess import *
40
+ from . traits.rotate import *
41
+ from . traits.stack import *
42
+ from . traits.mark import *
43
+ from . traits.mask import *
44
+ from . traits.trail import *
45
+ from . traits.delete import *
46
+ from . traits.sendto import *
47
+ from . traits.moved import *
48
+ from . traits.skel import *
49
+ from . traits.submenu import *
50
+ from . traits.basic import *
51
+ from . traits.trigger import *
52
+ from . traits.nonrect import *
53
+ from . traits.click import *
54
+ from . traits.mat import MatTrait
55
+ from . traits.cargo import CargoTrait
56
+ from . traits.movefixed import MoveFixedTrait
57
+ from . traits.sheet import SheeTrait
58
+ from . traits.hide import HideTrait
59
+ from . traits.return import ReturnTrait
60
+ from . game import *
61
+ from . buildfile import *
62
+ from . moduledata import *
63
+ from . save import *
64
+ from . vsav import *
65
+ from . vmod import *
66
+ from . exporter import *
@@ -0,0 +1,139 @@
1
+ # ====================================================================
2
+ # Key encoding
3
+ SHIFT = 65
4
+ CTRL = 130
5
+ ALT = 520
6
+ CTRL_SHIFT = CTRL+SHIFT
7
+ ALT_SHIFT = ALT+SHIFT
8
+ NONE = '\ue004'
9
+ NONE_MOD = 0
10
+
11
+ # --------------------------------------------------------------------
12
+ def key(let,mod=CTRL):
13
+
14
+ '''Encode a key sequence
15
+
16
+ down = 40,0
17
+ up = 38,0
18
+ left = 37,0
19
+ right = 39,0
20
+
21
+ Parameters
22
+ ----------
23
+ let : str
24
+ Key code (Letter)
25
+ mod : int
26
+ Modifier mask
27
+ '''
28
+ if let is None:
29
+ return f'{ord(NONE)},{NONE_MOD}'
30
+ return f'{ord(let)},{mod}'
31
+
32
+ # --------------------------------------------------------------------
33
+ #
34
+ def hexcolor(s):
35
+ if isinstance(s,str):
36
+ s = s.replace('0x','')
37
+ if len(s) == 3:
38
+ r, g, b = [int(si,16)/16 for si in s]
39
+ elif len(s) == 6:
40
+ r = int(s[0:2],16) / 256
41
+ g = int(s[2:4],16) / 256
42
+ b = int(s[4:6],16) / 256
43
+ else:
44
+ raise RuntimeError('3 or 6 hexadecimal digits for color string')
45
+ elif isinstance(s,int):
46
+ r = ((s >> 16) & 0xFF) / 256
47
+ g = ((s >> 8) & 0xFF) / 256
48
+ b = ((s >> 0) & 0xFF) / 256
49
+ else:
50
+ raise RuntimeError('Hex colour must be string or integer')
51
+
52
+ return rgb(int(r*256),int(g*256),int(b*256))
53
+
54
+ # --------------------------------------------------------------------
55
+ # Colour encoding
56
+ def rgb(r,g,b):
57
+ '''Encode RGB colour
58
+
59
+ Parameters
60
+ ----------
61
+ r : int
62
+ Red channel
63
+ g : int
64
+ Green channel
65
+ b : int
66
+ Blue channel
67
+
68
+ Returns
69
+ -------
70
+ colour : str
71
+ RGB colour as a string
72
+ '''
73
+ return ','.join([str(r),str(g),str(b)])
74
+
75
+ # --------------------------------------------------------------------
76
+ def rgba(r,g,b,a):
77
+ '''Encode RGBA colour
78
+
79
+ Parameters
80
+ ----------
81
+ r : int
82
+ Red channel
83
+ g : int
84
+ Green channel
85
+ b : int
86
+ Blue channel
87
+ a : int
88
+ Alpha channel
89
+
90
+ Returns
91
+ -------
92
+ colour : str
93
+ RGBA colour as a string
94
+ '''
95
+ return ','.join([str(r),str(g),str(b),str(a)])
96
+
97
+ # --------------------------------------------------------------------
98
+ def dumpTree(node,ind=''):
99
+ '''Dump the tree of nodes
100
+
101
+ Parameters
102
+ ----------
103
+ node : xml.dom.Node
104
+ Node to dump
105
+ ind : str
106
+ Current indent
107
+ '''
108
+ print(f'{ind}{node}')
109
+ for c in node.childNodes:
110
+ dumpTree(c,ind+' ')
111
+
112
+ # --------------------------------------------------------------------
113
+ def registerElement(cls,uniqueAttr=[],tag=None):
114
+ '''Register a TAG to element class, as well as unique attributes
115
+ to compare when comparing objects of that element class.
116
+
117
+ '''
118
+ ## BEGIN_IMPORT
119
+ from . element import Element
120
+ ## END_IMPORT
121
+
122
+ # Get class-level definitions of UNIQUE
123
+ uniqueCls = getattr(cls,'UNIQUE',None)
124
+ if uniqueCls:
125
+ try:
126
+ iter(uniqueCls)
127
+ except:
128
+ uniqueCls = list(uniqueCls)
129
+ else:
130
+ uniqueCls = []
131
+
132
+ tagName = cls.TAG if tag is None else tag
133
+ Element.known_tags [tagName] = cls
134
+ Element.unique_attrs[tagName] = uniqueAttr+uniqueCls
135
+
136
+
137
+ #
138
+ # EOF
139
+ #
@@ -0,0 +1,243 @@
1
+ ## BEGIN_IMPORT
2
+ from common import VerboseGuard
3
+ from . base import *
4
+ from . element import Element
5
+ from . gameelements import GameElement
6
+ from . mapelements import MapElement
7
+ from . zone import *
8
+ from . grid import *
9
+ ## END_IMPORT
10
+
11
+ # --------------------------------------------------------------------
12
+ class BoardPicker(MapElement):
13
+ TAG = Element.MAP+'BoardPicker'
14
+ def __init__(self,doc,node=None,
15
+ addColumnText = 'Add column',
16
+ addRowText = 'Add row',
17
+ boardPrompt = 'Select board',
18
+ slotHeight = 125,
19
+ slotScale = 0.2,
20
+ slotWidth = 350,
21
+ title = 'Choose Boards'):
22
+ super(BoardPicker,self).__init__(doc,self.TAG,node=node,
23
+ addColumnText = addColumnText,
24
+ addRowText = addRowText,
25
+ boardPrompt = boardPrompt,
26
+ slotHeight = slotHeight,
27
+ slotScale = slotScale,
28
+ slotWidth = slotWidth,
29
+ title = title,
30
+ selected = '')
31
+
32
+ def addSetup(self,**kwargs):
33
+ '''Add a `Setup` element to this
34
+
35
+ Parameters
36
+ ----------
37
+ kwargs : dict
38
+ Dictionary of attribute key-value pairs
39
+
40
+ Returns
41
+ -------
42
+ element : Setup
43
+ The added element
44
+ '''
45
+ if 'mapName' not in kwargs:
46
+ m = self.getMap()
47
+ kwargs['mapName'] = m.getAttribute('mapName')
48
+
49
+ return self.add(Setup,**kwargs)
50
+ def getSetups(self,single=False):
51
+ '''Get all or a sole `Setup` element(s) from this
52
+
53
+ Parameters
54
+ ----------
55
+ single : bool
56
+ If `True`, there can be only one `Setup` child, otherwise fail.
57
+ If `False` return all `Setup` children in this element
58
+
59
+ Returns
60
+ -------
61
+ children : list
62
+ List of `Setup` children (even if `single=True`)
63
+ '''
64
+ return self.getAllElements(Setup,single=single)
65
+ def addBoard(self,**kwargs):
66
+ '''Add a `Board` element to this
67
+
68
+ Parameters
69
+ ----------
70
+ kwargs : dict
71
+ Dictionary of attribute key-value pairs
72
+
73
+ Returns
74
+ -------
75
+ element : Board
76
+ The added element
77
+ '''
78
+ return self.add(Board,**kwargs)
79
+ def getBoards(self,asdict=True):
80
+ '''Get all Board element(s) from this
81
+
82
+ Parameters
83
+ ----------
84
+ asdict : bool
85
+ If `True`, return a dictonary that maps key to `Board` elements. If `False`, return a list of all Board` children.
86
+
87
+ Returns
88
+ -------
89
+ children : dict or list
90
+ Dictionary or list of `Board` children
91
+ '''
92
+ return self.getElementsByKey(Board,'name',asdict=asdict)
93
+
94
+ def selectBoard(self,name):
95
+ if name is None:
96
+ self.setAttribute('selected','')
97
+ return
98
+
99
+ if name not in self.getBoards():
100
+ print(f'Board "{name}" not in "{self.getMap()["mapName"]}" picker')
101
+ return
102
+
103
+ escname = name.replace('|',' ')
104
+ self.setAttribute('selected',f'{self["selected"]}|{name}|')
105
+ #print(f'Added "{name}" to selected boards: {self["selected"]}')
106
+
107
+ def encode(self):
108
+ setups = self.getSetups()
109
+ if setups is not None and len(setups)>0:
110
+ return [setups[0]._node.childNodes[0].nodeValue]
111
+
112
+ ret = []
113
+ selected = self['selected']
114
+ #print(f'Selected boards: {selected}')
115
+ for bn in self.getBoards().keys():
116
+ escname = '|'+bn.replace('|',' ')+'|'
117
+ # if selected != '':
118
+ # print(f'Ignore board "{bn}" in map '
119
+ # f'{self.getMap()["mapName"]} '
120
+ # f'"{selected}" -> '
121
+ # f'{escname not in selected}')
122
+ if escname not in selected:
123
+ continue
124
+ ret.append(self.getMap()['mapName']+'BoardPicker\t'+bn+'\t0\t0')
125
+
126
+ return ret
127
+
128
+ registerElement(BoardPicker)
129
+
130
+ # --------------------------------------------------------------------
131
+ class Setup(Element):
132
+ TAG = 'setup'
133
+ def __init__(self,picker,node=None,
134
+ mapName = '',
135
+ maxColumns = 1,
136
+ boardNames = []):
137
+ super(Setup,self).__init__(picker,self.TAG,node=node)
138
+ col = 0
139
+ row = 0
140
+ lst = [f'{mapName}BoardPicker']
141
+ for bn in boardNames:
142
+ lst.extend([bn,str(col),str(row)])
143
+ col += 1
144
+ if col >= maxColumns:
145
+ col = 0
146
+ row += 1
147
+
148
+ txt = r' '.join(lst)
149
+ self.addText(txt)
150
+
151
+ def getPicker(self): return self.getParent(BoardPicker)
152
+
153
+ registerElement(Setup)
154
+
155
+ # --------------------------------------------------------------------
156
+ class Board(Element):
157
+ TAG = Element.PICKER+'Board'
158
+ UNIQUE = ['name']
159
+ def __init__(self,picker,node=None,
160
+ name = '',
161
+ image = '',
162
+ reversible = False,
163
+ color = rgb(255,255,255),
164
+ width = 0,
165
+ height = 0):
166
+ super(Board,self).__init__(picker,self.TAG,node=node,
167
+ image = image,
168
+ name = name,
169
+ reversible = reversible,
170
+ color = color,
171
+ width = width,
172
+ height = height)
173
+
174
+ def getPicker(self): return self.getParent(BoardPicker)
175
+ def getMap(self):
176
+ z = self.getPicker()
177
+ if z is not None:
178
+ return z.getMap()
179
+ return None
180
+ def addZonedGrid(self,**kwargs):
181
+ '''Add a `ZonedGrid` element to this
182
+
183
+ Parameters
184
+ ----------
185
+ kwargs : dict
186
+ Dictionary of attribute key-value pairs
187
+
188
+ Returns
189
+ -------
190
+ element : ZonedGrid
191
+ The added element
192
+ '''
193
+ return self.add(ZonedGrid,**kwargs)
194
+ def getZonedGrids(self,single=True):
195
+ '''Get all or a sole `ZonedGrid` element(s) from this
196
+
197
+ Parameters
198
+ ----------
199
+ single : bool
200
+ If `True`, there can be only one `ZonedGrid` child, otherwise fail.
201
+ If `False` return all `ZonedGrid` children in this element
202
+
203
+ Returns
204
+ -------
205
+ children : list
206
+ List of `ZonedGrid` children (even if `single=True`)
207
+ '''
208
+ return self.getAllElements(ZonedGrid,single=single)
209
+ def getZones(self,asdict=True):
210
+ '''Get all Zone element(s) from this
211
+
212
+ Parameters
213
+ ----------
214
+ asdict : bool
215
+ If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children.
216
+
217
+ Returns
218
+ -------
219
+ children : dict or list
220
+ Dictionary or list of `Zone` children
221
+ '''
222
+ zoned = self.getZonedGrids(single=True)
223
+ if zoned is None: return None
224
+
225
+ return zoned[0].getZones(asdict=asdict)
226
+
227
+ def getWidth(self):
228
+ # print(f'Getting width of {self}: {self["width"]}')
229
+ if 'width' in self and int(self['width']) != 0:
230
+ return int(self['width'])
231
+ return 0
232
+
233
+ def getHeight(self):
234
+ # print(f'Getting height of {self}: {self["height"]}')
235
+ if 'height' in self and int(self['height']) != 0:
236
+ return int(self['height'])
237
+ return 0
238
+
239
+ registerElement(Board)
240
+
241
+ #
242
+ # EOF
243
+ #
@@ -0,0 +1,60 @@
1
+ ## BEGIN_IMPORT
2
+ from common import VerboseGuard
3
+ from . base import *
4
+ from . element import Element
5
+ from . game import Game
6
+ ## END_IMPORT
7
+
8
+ # --------------------------------------------------------------------
9
+ class BuildFile(Element):
10
+ def __init__(self,root=None):
11
+ '''Construct from a DOM object, if given, otherwise make new'''
12
+ # from xml.dom.minidom import Document
13
+ super(BuildFile,self).__init__(None,'',None)
14
+
15
+ self._root = root
16
+ self._tag = 'buildFile'
17
+ if self._root is None:
18
+ self._root = xmlns.Document()
19
+
20
+ self._node = self._root
21
+
22
+ def addGame(self,**kwargs):
23
+ '''Add a `Game` element to this
24
+
25
+ Parameters
26
+ ----------
27
+ kwargs : dict
28
+ Dictionary of attribute key-value pairs
29
+
30
+ Returns
31
+ -------
32
+ element : Game
33
+ The added element
34
+ '''
35
+ return Game(self,**kwargs)
36
+
37
+ def getGame(self):
38
+ '''Get the `Game`'''
39
+ try:
40
+ return Game(self,
41
+ node=self._root.\
42
+ getElementsByTagName('VASSAL.build.GameModule')[0])
43
+ except:
44
+ pass
45
+
46
+ return Game(self,
47
+ node=self._root.\
48
+ getElementsByTagName('VASSAL.launch.BasicModule')[0])
49
+
50
+
51
+ def encode(self):
52
+ '''Encode into XML'''
53
+ return self._root.toprettyxml(indent=' ',
54
+ encoding="UTF-8",
55
+ standalone=False)
56
+
57
+
58
+ #
59
+ # EOF
60
+ #