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.
- pywargame/__init__.py +2 -0
- pywargame/common/__init__.py +3 -0
- pywargame/common/collector.py +87 -0
- pywargame/common/dicedraw.py +363 -0
- pywargame/common/drawdice.py +40 -0
- pywargame/common/singleton.py +22 -0
- pywargame/common/test.py +25 -0
- pywargame/common/verbose.py +59 -0
- pywargame/common/verboseguard.py +53 -0
- pywargame/cyberboard/__init__.py +18 -0
- pywargame/cyberboard/archive.py +283 -0
- pywargame/cyberboard/base.py +63 -0
- pywargame/cyberboard/board.py +462 -0
- pywargame/cyberboard/cell.py +200 -0
- pywargame/cyberboard/collect.py +49 -0
- pywargame/cyberboard/collectgbx0pwd.py +30 -0
- pywargame/cyberboard/collectgbxext.py +30 -0
- pywargame/cyberboard/collectgsnexp.py +32 -0
- pywargame/cyberboard/collectgsnext.py +30 -0
- pywargame/cyberboard/draw.py +396 -0
- pywargame/cyberboard/exporter.py +1132 -0
- pywargame/cyberboard/extractor.py +240 -0
- pywargame/cyberboard/features.py +17 -0
- pywargame/cyberboard/gamebox.py +81 -0
- pywargame/cyberboard/gbxexp.py +76 -0
- pywargame/cyberboard/gbxext.py +64 -0
- pywargame/cyberboard/gsnexp.py +147 -0
- pywargame/cyberboard/gsnext.py +59 -0
- pywargame/cyberboard/head.py +111 -0
- pywargame/cyberboard/image.py +76 -0
- pywargame/cyberboard/main.py +47 -0
- pywargame/cyberboard/mark.py +102 -0
- pywargame/cyberboard/palette.py +36 -0
- pywargame/cyberboard/piece.py +169 -0
- pywargame/cyberboard/player.py +36 -0
- pywargame/cyberboard/scenario.py +115 -0
- pywargame/cyberboard/testgrid.py +156 -0
- pywargame/cyberboard/tile.py +121 -0
- pywargame/cyberboard/tray.py +68 -0
- pywargame/cyberboard/windows.py +41 -0
- pywargame/cyberboard/zeropwd.py +45 -0
- pywargame/cyberboard.py +2728 -0
- pywargame/gbx0pwd.py +2776 -0
- pywargame/gbxextract.py +2795 -0
- pywargame/gsnexport.py +16499 -0
- pywargame/gsnextract.py +2790 -0
- pywargame/latex/__init__.py +2 -0
- pywargame/latex/collect.py +34 -0
- pywargame/latex/latexexporter.py +4010 -0
- pywargame/latex/main.py +184 -0
- pywargame/vassal/__init__.py +66 -0
- pywargame/vassal/base.py +139 -0
- pywargame/vassal/board.py +243 -0
- pywargame/vassal/buildfile.py +60 -0
- pywargame/vassal/chart.py +79 -0
- pywargame/vassal/chessclock.py +197 -0
- pywargame/vassal/collect.py +98 -0
- pywargame/vassal/collectpatch.py +28 -0
- pywargame/vassal/command.py +21 -0
- pywargame/vassal/documentation.py +322 -0
- pywargame/vassal/dumpcollect.py +28 -0
- pywargame/vassal/dumpvsav.py +28 -0
- pywargame/vassal/element.py +439 -0
- pywargame/vassal/exporter.py +89 -0
- pywargame/vassal/extension.py +101 -0
- pywargame/vassal/folder.py +103 -0
- pywargame/vassal/game.py +940 -0
- pywargame/vassal/gameelements.py +1091 -0
- pywargame/vassal/globalkey.py +127 -0
- pywargame/vassal/globalproperty.py +433 -0
- pywargame/vassal/grid.py +573 -0
- pywargame/vassal/map.py +1061 -0
- pywargame/vassal/mapelements.py +1020 -0
- pywargame/vassal/merge.py +57 -0
- pywargame/vassal/merger.py +460 -0
- pywargame/vassal/moduledata.py +275 -0
- pywargame/vassal/mrgcollect.py +31 -0
- pywargame/vassal/patch.py +44 -0
- pywargame/vassal/patchcollect.py +28 -0
- pywargame/vassal/player.py +83 -0
- pywargame/vassal/save.py +495 -0
- pywargame/vassal/skel.py +380 -0
- pywargame/vassal/trait.py +224 -0
- pywargame/vassal/traits/__init__.py +36 -0
- pywargame/vassal/traits/area.py +50 -0
- pywargame/vassal/traits/basic.py +35 -0
- pywargame/vassal/traits/calculatedproperty.py +22 -0
- pywargame/vassal/traits/cargo.py +29 -0
- pywargame/vassal/traits/click.py +41 -0
- pywargame/vassal/traits/clone.py +28 -0
- pywargame/vassal/traits/delete.py +24 -0
- pywargame/vassal/traits/deselect.py +32 -0
- pywargame/vassal/traits/dynamicproperty.py +112 -0
- pywargame/vassal/traits/globalcommand.py +55 -0
- pywargame/vassal/traits/globalhotkey.py +26 -0
- pywargame/vassal/traits/globalproperty.py +54 -0
- pywargame/vassal/traits/hide.py +67 -0
- pywargame/vassal/traits/label.py +76 -0
- pywargame/vassal/traits/layer.py +105 -0
- pywargame/vassal/traits/mark.py +20 -0
- pywargame/vassal/traits/mask.py +85 -0
- pywargame/vassal/traits/mat.py +26 -0
- pywargame/vassal/traits/moved.py +35 -0
- pywargame/vassal/traits/movefixed.py +51 -0
- pywargame/vassal/traits/nonrect.py +95 -0
- pywargame/vassal/traits/nostack.py +55 -0
- pywargame/vassal/traits/place.py +104 -0
- pywargame/vassal/traits/prototype.py +20 -0
- pywargame/vassal/traits/report.py +34 -0
- pywargame/vassal/traits/restrictaccess.py +28 -0
- pywargame/vassal/traits/restrictcommand.py +32 -0
- pywargame/vassal/traits/return.py +40 -0
- pywargame/vassal/traits/rotate.py +62 -0
- pywargame/vassal/traits/sendto.py +59 -0
- pywargame/vassal/traits/sheet.py +129 -0
- pywargame/vassal/traits/skel.py +9 -0
- pywargame/vassal/traits/stack.py +28 -0
- pywargame/vassal/traits/submenu.py +27 -0
- pywargame/vassal/traits/trail.py +61 -0
- pywargame/vassal/traits/trigger.py +72 -0
- pywargame/vassal/turn.py +272 -0
- pywargame/vassal/upgrade.py +191 -0
- pywargame/vassal/vmod.py +323 -0
- pywargame/vassal/vsav.py +100 -0
- pywargame/vassal/widget.py +358 -0
- pywargame/vassal/withtraits.py +634 -0
- pywargame/vassal/xml.py +4 -0
- pywargame/vassal/zone.py +399 -0
- pywargame/vassal.py +12500 -0
- pywargame/vmodpatch.py +12548 -0
- pywargame/vsavdump.py +12533 -0
- pywargame/vslmerge.py +13015 -0
- pywargame/wgexport.py +16689 -0
- pywargame/ztexport.py +14351 -0
- pywargame/zuntzu/__init__.py +5 -0
- pywargame/zuntzu/base.py +82 -0
- pywargame/zuntzu/collect.py +38 -0
- pywargame/zuntzu/countersheet.py +250 -0
- pywargame/zuntzu/dicehand.py +48 -0
- pywargame/zuntzu/exporter.py +936 -0
- pywargame/zuntzu/gamebox.py +154 -0
- pywargame/zuntzu/map.py +36 -0
- pywargame/zuntzu/piece.py +37 -0
- pywargame/zuntzu/scenario.py +208 -0
- pywargame/zuntzu/ztexp.py +115 -0
- pywargame-0.3.1.dist-info/METADATA +353 -0
- pywargame-0.3.1.dist-info/RECORD +150 -0
- pywargame-0.3.1.dist-info/WHEEL +5 -0
- pywargame-0.3.1.dist-info/licenses/LICENSE +5 -0
- pywargame-0.3.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,634 @@
|
|
1
|
+
## BEGIN_IMPORT
|
2
|
+
from common import VerboseGuard
|
3
|
+
from . base import *
|
4
|
+
from . element import Element
|
5
|
+
from . command import *
|
6
|
+
from . trait import Trait
|
7
|
+
from . traits import *
|
8
|
+
## END_IMPORT
|
9
|
+
|
10
|
+
# --------------------------------------------------------------------
|
11
|
+
#
|
12
|
+
# Traits of this kind of object are
|
13
|
+
#
|
14
|
+
# - Evaluated from the start of the list to the end of the list,
|
15
|
+
# skipping over report and trigger traits
|
16
|
+
# - Then evaluated from the end of the list to the start, only
|
17
|
+
# evaluating report and trigger traits
|
18
|
+
# - The list _must_ end in a BasicTrait
|
19
|
+
#
|
20
|
+
# Traits are copied when making a copy of objects of this class, and
|
21
|
+
# are done so using a full decoding and encoding. This means that
|
22
|
+
# copying is a bit susceptible to expansions of the strings of the traits,
|
23
|
+
# in particular if they contain special characters such as ',' or '/'.
|
24
|
+
#
|
25
|
+
class WithTraits(Element):
|
26
|
+
UNIQUE = ['entryName']
|
27
|
+
def __init__(self,parent,tag,node=None,traits=[],**kwargs):
|
28
|
+
'''Base class for things that have traits
|
29
|
+
|
30
|
+
Parameters
|
31
|
+
----------
|
32
|
+
parent : Element
|
33
|
+
Parent to add this to
|
34
|
+
node : xml.minidom.Element
|
35
|
+
If not None, XML element to read definition from.
|
36
|
+
Rest of the arguments are ignored if not None.
|
37
|
+
traits : list of Trait objects
|
38
|
+
The traits to set on this object
|
39
|
+
kwargs : dict
|
40
|
+
More attributes to set on element
|
41
|
+
'''
|
42
|
+
super(WithTraits,self).__init__(parent,tag,node=node,**kwargs)
|
43
|
+
if node is None: self.setTraits(*traits)
|
44
|
+
|
45
|
+
def addTrait(self,trait):
|
46
|
+
'''Add a `Trait` element to this. Note that this re-encodes
|
47
|
+
all traits.
|
48
|
+
|
49
|
+
Parameters
|
50
|
+
----------
|
51
|
+
trait : Trait
|
52
|
+
The trait to add
|
53
|
+
'''
|
54
|
+
traits = self.getTraits()
|
55
|
+
traits.append(trait)
|
56
|
+
self.setTraits(*traits)
|
57
|
+
|
58
|
+
|
59
|
+
def getTraits(self):
|
60
|
+
'''Get all element traits as objects. This decodes the trait
|
61
|
+
definitions. This is useful if we have read the element from
|
62
|
+
the XML file, or similar.
|
63
|
+
|
64
|
+
Note that the list of traits returned are _not_ tied to the
|
65
|
+
XML nodes content. Therefore, if one makes changes to the list,
|
66
|
+
or to elements of the list, and these changes should be
|
67
|
+
reflected in this object, then we _must_ call
|
68
|
+
|
69
|
+
setTraits(traits)
|
70
|
+
|
71
|
+
with the changed list of traits.
|
72
|
+
|
73
|
+
Returns
|
74
|
+
-------
|
75
|
+
traits : list of Trait objects
|
76
|
+
The decoded traits
|
77
|
+
|
78
|
+
'''
|
79
|
+
code = self._node.childNodes[0].nodeValue
|
80
|
+
return self.decodeAdd(code)
|
81
|
+
|
82
|
+
def encodedStates(self):
|
83
|
+
from re import split
|
84
|
+
|
85
|
+
code = self._node.childNodes[0].nodeValue
|
86
|
+
cmd, iden, typ, sta = split(fr'(?<!\\)/',code) #code.split('/')
|
87
|
+
|
88
|
+
return sta
|
89
|
+
|
90
|
+
def decodeStates(self,code,verbose=False):
|
91
|
+
from re import split
|
92
|
+
|
93
|
+
newstates, oldstates = split(fr'(?<!\\)/',code)#code.split('/')
|
94
|
+
|
95
|
+
splitit = lambda l : \
|
96
|
+
[s.strip('\\').split(';') for s in l.split(r' ')]
|
97
|
+
|
98
|
+
newstates = splitit(newstates)
|
99
|
+
oldstates = splitit(oldstates)
|
100
|
+
|
101
|
+
traits = self.getTraits()
|
102
|
+
|
103
|
+
if len(traits) != len(newstates):
|
104
|
+
print(f'Piece has {len(traits)} traits but got '
|
105
|
+
f'{len(newstates)} states')
|
106
|
+
|
107
|
+
for trait, state in zip(traits,newstates):
|
108
|
+
trait._state = state;
|
109
|
+
# print(trait.ID)
|
110
|
+
# for n,s in zip(trait._snames,trait._state):
|
111
|
+
# print(f' {n:30s}: {s}')
|
112
|
+
|
113
|
+
self.setTraits(*traits)
|
114
|
+
|
115
|
+
def copyStates(self,other,verbose=False):
|
116
|
+
straits = other.getTraits()
|
117
|
+
dtraits = self.getTraits()
|
118
|
+
|
119
|
+
matches = 0
|
120
|
+
for strait in straits:
|
121
|
+
if len(strait._state) < 1:
|
122
|
+
continue
|
123
|
+
|
124
|
+
cand = []
|
125
|
+
ttrait = None
|
126
|
+
for dtrait in dtraits:
|
127
|
+
if dtrait.ID == strait.ID:
|
128
|
+
cand.append(dtrait)
|
129
|
+
|
130
|
+
if verbose and len(cand) < 1:
|
131
|
+
print(f'Could not find candidate for {strait.ID}')
|
132
|
+
continue
|
133
|
+
|
134
|
+
if len(cand) == 1:
|
135
|
+
ttrait = cand[0]
|
136
|
+
|
137
|
+
else:
|
138
|
+
# print(f'Got {len(cand)} candidiate targets {strait.ID}')
|
139
|
+
|
140
|
+
best = None
|
141
|
+
count = 0
|
142
|
+
types = strait._type
|
143
|
+
for c in cand:
|
144
|
+
cnt = sum([ct == t for ct,t in zip(c._type, types)])
|
145
|
+
if cnt > count:
|
146
|
+
best = c
|
147
|
+
count = cnt
|
148
|
+
|
149
|
+
if verbose and best is None:
|
150
|
+
print(f'No candidate for {strait.ID} {len(again)}')
|
151
|
+
|
152
|
+
if verbose and count+2 < len(types):
|
153
|
+
print(f'Ambigious candidate for {strait.ID} '
|
154
|
+
f'({count} match out of {len(types)})')
|
155
|
+
#print(best._type)
|
156
|
+
#print(types)
|
157
|
+
|
158
|
+
ttrait = best
|
159
|
+
|
160
|
+
if ttrait is None:
|
161
|
+
continue
|
162
|
+
|
163
|
+
ttrait._state = strait._state
|
164
|
+
matches += 1
|
165
|
+
# print(ttrait.ID)
|
166
|
+
# for n,s in zip(ttrait._snames,ttrait._state):
|
167
|
+
# print(f' {n:30s}: {s}')
|
168
|
+
|
169
|
+
if verbose:
|
170
|
+
print(f'Got {matches} matches out of {len(dtraits)}')
|
171
|
+
|
172
|
+
self.setTraits(*dtraits)
|
173
|
+
|
174
|
+
|
175
|
+
def decodeAdd(self,code,verbose=False):
|
176
|
+
'''Try to decode make a piece from a piece of state code'''
|
177
|
+
from re import split
|
178
|
+
|
179
|
+
cmd, iden, typ, sta = split(fr'(?<!\\)/',code) #code.split('/')
|
180
|
+
# print(cmd,iden,typ,sta)
|
181
|
+
|
182
|
+
types = typ.split(r' ')
|
183
|
+
states = sta.split(r' ')
|
184
|
+
types = [t.strip('\\').split(';') for t in types]
|
185
|
+
states = [s.strip('\\').split(';') for s in states]
|
186
|
+
traits = []
|
187
|
+
|
188
|
+
for t, s in zip(types,states):
|
189
|
+
tid = t[0]
|
190
|
+
trem = t[1:]
|
191
|
+
known = False
|
192
|
+
|
193
|
+
for c in Trait.known_traits:
|
194
|
+
t = c.take(tid,trem,s) # See if we have it
|
195
|
+
if t is not None:
|
196
|
+
traits.append(t) # Got it
|
197
|
+
known = True
|
198
|
+
break
|
199
|
+
|
200
|
+
if not known:
|
201
|
+
print(f'Warning: Unknown trait {tid}')
|
202
|
+
|
203
|
+
return traits
|
204
|
+
|
205
|
+
def encodeAdd(self,*traits,iden='null',verbose=False):
|
206
|
+
'''Encodes type and states'''
|
207
|
+
if len(traits) < 1: return ''
|
208
|
+
|
209
|
+
last = traits[-1]
|
210
|
+
# A little hackish to use the name of the class, but needed
|
211
|
+
# because of imports into patch scripts.
|
212
|
+
lastBasic = isinstance(last,BasicTrait) or \
|
213
|
+
last.__class__.__name__.endswith('BasicTrait')
|
214
|
+
lastStack = isinstance(last,StackTrait) or \
|
215
|
+
last.__class__.__name__.endswith('StackTrait')
|
216
|
+
if not lastBasic and not lastStack:
|
217
|
+
from sys import stderr
|
218
|
+
print(f'Warning - last trait NOT a Basic(Stack)Trait, '
|
219
|
+
f'but a {type(last)}',
|
220
|
+
file=stderr)
|
221
|
+
|
222
|
+
types = []
|
223
|
+
states = []
|
224
|
+
for trait in traits:
|
225
|
+
if trait is None:
|
226
|
+
print(f'Trait is None (traits: {traits})')
|
227
|
+
continue
|
228
|
+
tpe, state = trait.encode()
|
229
|
+
types.append(tpe)
|
230
|
+
states.append(state)
|
231
|
+
|
232
|
+
tpe = WithTraits.encodeParts(*types)
|
233
|
+
state = WithTraits.encodeParts(*states)
|
234
|
+
add = AddCommand(str(iden),tpe,state)
|
235
|
+
return add.cmd
|
236
|
+
|
237
|
+
|
238
|
+
def setTraits(self,*traits,iden='null'):
|
239
|
+
'''Set traits on this element. This encodes the traits into
|
240
|
+
this object.
|
241
|
+
|
242
|
+
Parameters
|
243
|
+
----------
|
244
|
+
traits : tuple of Trait objects
|
245
|
+
The traits to set on this object.
|
246
|
+
iden : str
|
247
|
+
Identifier
|
248
|
+
|
249
|
+
'''
|
250
|
+
add = self.encodeAdd(*traits,iden=iden)
|
251
|
+
if self._node is None:
|
252
|
+
# from xml.dom.minidom import Element, Text
|
253
|
+
self._node = xmlns.Element(self.TAG)
|
254
|
+
self._node.appendChild(xmlns.Text())
|
255
|
+
|
256
|
+
if len(self._node.childNodes) < 1:
|
257
|
+
self.addText('')
|
258
|
+
self._node.childNodes[0].nodeValue = add
|
259
|
+
|
260
|
+
def removeTrait(self,ID,key=None,value=None,verbose=False):
|
261
|
+
'''Remove a trait from this object.
|
262
|
+
|
263
|
+
Parameters
|
264
|
+
----------
|
265
|
+
ID : str
|
266
|
+
The type of trait to remove. Must be a valid
|
267
|
+
ID of a class derived from Trait.
|
268
|
+
key : str
|
269
|
+
Optional key to inspect to select trait that has
|
270
|
+
this key and the traits key value is the argument value,
|
271
|
+
value :
|
272
|
+
If specified, then only traits which key has this value
|
273
|
+
are removed
|
274
|
+
verbose : bool
|
275
|
+
Be verbose if True
|
276
|
+
|
277
|
+
Returns
|
278
|
+
-------
|
279
|
+
trait : Trait
|
280
|
+
The removed trait or None
|
281
|
+
'''
|
282
|
+
traits = self.getTraits()
|
283
|
+
trait = Trait.findTrait(traits,ID,key,value,verbose)
|
284
|
+
if trait is not None:
|
285
|
+
traits.remove(trait)
|
286
|
+
self.setTraits(traits)
|
287
|
+
return trait
|
288
|
+
|
289
|
+
def addTraits(self,*toadd):
|
290
|
+
'''Add traits to this. Note that this will
|
291
|
+
decode and reencode the traits. Only use this when
|
292
|
+
adding traits on-mass. Repeated use of this is inefficient.
|
293
|
+
|
294
|
+
This member function takes care to push any basic trait to
|
295
|
+
the end of the list.
|
296
|
+
|
297
|
+
The added traits will not override existing triats.
|
298
|
+
|
299
|
+
Paramters
|
300
|
+
---------
|
301
|
+
toAdd : tuple of Trait objects
|
302
|
+
The traits to add
|
303
|
+
|
304
|
+
'''
|
305
|
+
traits = self.getTraits()
|
306
|
+
basic = Trait.findTrait(traits,BasicTrait.ID)
|
307
|
+
if basic:
|
308
|
+
traits.remove(basic)
|
309
|
+
traits.extend(toAdd)
|
310
|
+
if basic:
|
311
|
+
traits.append(basic)
|
312
|
+
self.setTraits(traits)
|
313
|
+
|
314
|
+
|
315
|
+
@classmethod
|
316
|
+
def encodeParts(cls,*parts):
|
317
|
+
'''Encode parts of a full piece definition
|
318
|
+
|
319
|
+
Each trait (VASSAL.counter.Decorator,
|
320
|
+
VASSAL.counter.BasicPiece) definition or state is separated by
|
321
|
+
a litteral TAB character. Beyond the first TAB separator,
|
322
|
+
additional escape characters (BACKSLAH) are added in front of
|
323
|
+
the separator. This is to that VASSAL.utils.SequenceDecoder
|
324
|
+
does not see consequitive TABs as a single TAB.
|
325
|
+
'''
|
326
|
+
ret = ''
|
327
|
+
sep = r' '
|
328
|
+
for i, p in enumerate(parts):
|
329
|
+
if i != 0:
|
330
|
+
ret += '\\'*(i-1) + sep
|
331
|
+
ret += str(p)
|
332
|
+
|
333
|
+
return ret
|
334
|
+
|
335
|
+
|
336
|
+
def cloneNode(self,parent):
|
337
|
+
'''This clones the underlying XML node.
|
338
|
+
|
339
|
+
Parameters
|
340
|
+
----------
|
341
|
+
parent : Element
|
342
|
+
The element to clone this element into
|
343
|
+
|
344
|
+
Returns
|
345
|
+
-------
|
346
|
+
copy : xml.minidom.Element
|
347
|
+
The newly created clone of this object's node
|
348
|
+
'''
|
349
|
+
copy = self._node.cloneNode(deep=True)
|
350
|
+
if parent is not None:
|
351
|
+
parent._node.appendChild(copy)
|
352
|
+
else:
|
353
|
+
print('WARNING: No parent to add copy to')
|
354
|
+
return copy
|
355
|
+
|
356
|
+
def print(self,file=None,recursive=1024,indent=''):
|
357
|
+
if file is None:
|
358
|
+
from sys import stdout
|
359
|
+
file = stdout
|
360
|
+
|
361
|
+
from textwrap import indent as i
|
362
|
+
|
363
|
+
if recursive <= 1:
|
364
|
+
n = len(self.getTraits())
|
365
|
+
if n > 1:
|
366
|
+
print(i(f' {n} traits',indent),file=file)
|
367
|
+
return
|
368
|
+
|
369
|
+
|
370
|
+
from io import StringIO
|
371
|
+
|
372
|
+
|
373
|
+
stream = StringIO()
|
374
|
+
traits = self.getTraits()
|
375
|
+
for trait in traits:
|
376
|
+
trait.print(stream)
|
377
|
+
|
378
|
+
s = i(stream.getvalue().rstrip(), ' ')
|
379
|
+
print(i(s,indent), file=file)
|
380
|
+
|
381
|
+
|
382
|
+
# --------------------------------------------------------------------
|
383
|
+
class DummyWithTraits(WithTraits):
|
384
|
+
TAG = 'dummy'
|
385
|
+
def __init__(self,parent,node=None,traits=[]):
|
386
|
+
'''An empty element. Used when making searching'''
|
387
|
+
super(DummyWithTraits,self).__init__(tag = self.TAG,
|
388
|
+
parent = parent,
|
389
|
+
node = node,
|
390
|
+
traits = traits)
|
391
|
+
if parent is not None:
|
392
|
+
parent.remove(self)
|
393
|
+
|
394
|
+
|
395
|
+
registerElement(DummyWithTraits)
|
396
|
+
|
397
|
+
# --------------------------------------------------------------------
|
398
|
+
class WithTraitsSlot(WithTraits):
|
399
|
+
def __init__(self,
|
400
|
+
parent,
|
401
|
+
tag,
|
402
|
+
node = None,
|
403
|
+
entryName = '',
|
404
|
+
traits = [],
|
405
|
+
gpid = 0,
|
406
|
+
height = 72,
|
407
|
+
width = 72,
|
408
|
+
icon = ''):
|
409
|
+
'''A piece slot. Used all the time.
|
410
|
+
|
411
|
+
Parameters
|
412
|
+
----------
|
413
|
+
parent : Element
|
414
|
+
Parent to add this to
|
415
|
+
node : xml.minidom.Element
|
416
|
+
If not None, XML element to read definition from.
|
417
|
+
Rest of the arguments are ignored if not None.
|
418
|
+
entryName : str
|
419
|
+
Name of this
|
420
|
+
traits : list of Trait objects
|
421
|
+
The traits to set on this object
|
422
|
+
gpid : int
|
423
|
+
Global Piece identifier. If 0, will be set by Game
|
424
|
+
height : int
|
425
|
+
Height size of the piece (in pixels)
|
426
|
+
width : int
|
427
|
+
Width size of the piece (in pixels)
|
428
|
+
icon : str
|
429
|
+
Piece image file name within 'image' sub-dir of archive
|
430
|
+
'''
|
431
|
+
super().\
|
432
|
+
__init__(parent,
|
433
|
+
tag,
|
434
|
+
node = node,
|
435
|
+
traits = traits,
|
436
|
+
entryName = entryName,
|
437
|
+
gpid = gpid,
|
438
|
+
height = height,
|
439
|
+
width = width,
|
440
|
+
icon = icon)
|
441
|
+
|
442
|
+
|
443
|
+
def _clone(self,cls,parent):
|
444
|
+
'''Adds copy of self to parent, possibly with new GPID'''
|
445
|
+
## BEGIN_IMPORT
|
446
|
+
from . game import Game
|
447
|
+
## END_IMPORT
|
448
|
+
game = self.getParentOfClass([Game])
|
449
|
+
gpid = game.nextPieceSlotId()
|
450
|
+
#opid = int(self.getAttribute('gpid'))
|
451
|
+
#print(f'Using GPID={gpid} for clone {opid}')
|
452
|
+
|
453
|
+
node = self.cloneNode(parent)
|
454
|
+
piece = cls(parent,node=node)
|
455
|
+
piece.setAttribute('gpid',gpid)
|
456
|
+
|
457
|
+
traits = piece.getTraits()
|
458
|
+
for trait in traits:
|
459
|
+
if isinstance(trait,BasicTrait):
|
460
|
+
trait['gpid'] = gpid
|
461
|
+
|
462
|
+
piece.setTraits(*traits)
|
463
|
+
return piece
|
464
|
+
|
465
|
+
def print(self,file=None,recursive=1024,indent=''):
|
466
|
+
if file is None:
|
467
|
+
from sys import stdout
|
468
|
+
file = stdout
|
469
|
+
from textwrap import indent as i
|
470
|
+
|
471
|
+
print(i(f'{type(self).__name__} {self["entryName"]}'+'\n'
|
472
|
+
f' gpid : {self["gpid"]}'+'\n'
|
473
|
+
f' height: {self["height"]}'+'\n'
|
474
|
+
f' width : {self["width"]}'+'\n'
|
475
|
+
f' icon : {self["icon"]}',indent),
|
476
|
+
file = file)
|
477
|
+
|
478
|
+
super().print(file=file,
|
479
|
+
recursive=recursive-1,
|
480
|
+
indent=indent)
|
481
|
+
|
482
|
+
# --------------------------------------------------------------------
|
483
|
+
class PieceSlot(WithTraitsSlot):
|
484
|
+
TAG = Element.WIDGET+'PieceSlot'
|
485
|
+
def __init__(self,
|
486
|
+
parent,
|
487
|
+
node = None,
|
488
|
+
entryName = '',
|
489
|
+
traits = [],
|
490
|
+
gpid = 0,
|
491
|
+
height = 72,
|
492
|
+
width = 72,
|
493
|
+
icon = ''):
|
494
|
+
'''A piece slot. Used all the time.
|
495
|
+
|
496
|
+
Parameters
|
497
|
+
----------
|
498
|
+
parent : Element
|
499
|
+
Parent to add this to
|
500
|
+
node : xml.minidom.Element
|
501
|
+
If not None, XML element to read definition from.
|
502
|
+
Rest of the arguments are ignored if not None.
|
503
|
+
entryName : str
|
504
|
+
Name of this
|
505
|
+
traits : list of Trait objects
|
506
|
+
The traits to set on this object
|
507
|
+
gpid : int
|
508
|
+
Global Piece identifier. If 0, will be set by Game
|
509
|
+
height : int
|
510
|
+
Height size of the piece (in pixels)
|
511
|
+
width : int
|
512
|
+
Width size of the piece (in pixels)
|
513
|
+
icon : str
|
514
|
+
Piece image file name within 'image' sub-dir of archive
|
515
|
+
'''
|
516
|
+
super().\
|
517
|
+
__init__(parent,
|
518
|
+
self.TAG,
|
519
|
+
node = node,
|
520
|
+
traits = traits,
|
521
|
+
entryName = entryName,
|
522
|
+
gpid = gpid,
|
523
|
+
height = height,
|
524
|
+
width = width,
|
525
|
+
icon = icon)
|
526
|
+
|
527
|
+
|
528
|
+
def clone(self,parent):
|
529
|
+
return self._clone(PieceSlot,parent)
|
530
|
+
|
531
|
+
|
532
|
+
registerElement(PieceSlot)
|
533
|
+
|
534
|
+
# --------------------------------------------------------------------
|
535
|
+
class CardSlot(WithTraitsSlot):
|
536
|
+
TAG = Element.WIDGET+'CardSlot'
|
537
|
+
def __init__(self,
|
538
|
+
parent,
|
539
|
+
node = None,
|
540
|
+
entryName = '',
|
541
|
+
traits = [],
|
542
|
+
gpid = 0,
|
543
|
+
height = 72,
|
544
|
+
width = 72,
|
545
|
+
icon = ''):
|
546
|
+
'''A card slot. Used all the time. It is essentially the
|
547
|
+
same as a PieceSlot, though a `MaskTrait` is added (with
|
548
|
+
default settings), if no such trait is present (to-be-done)
|
549
|
+
|
550
|
+
Parameters
|
551
|
+
----------
|
552
|
+
parent : Element
|
553
|
+
Parent to add this to
|
554
|
+
node : xml.minidom.Element
|
555
|
+
If not None, XML element to read definition from.
|
556
|
+
Rest of the arguments are ignored if not None.
|
557
|
+
entryName : str
|
558
|
+
Name of this
|
559
|
+
traits : list of Trait objects
|
560
|
+
The traits to set on this object
|
561
|
+
gpid : int
|
562
|
+
Global Piece identifier. If 0, will be set by Game
|
563
|
+
height : int
|
564
|
+
Height size of the card (in pixels)
|
565
|
+
width : int
|
566
|
+
Width size of the card (in pixels)
|
567
|
+
icon : str
|
568
|
+
Card image file name within 'image' sub-dir of archive
|
569
|
+
|
570
|
+
'''
|
571
|
+
super().\
|
572
|
+
__init__(parent,
|
573
|
+
self.TAG,
|
574
|
+
node = node,
|
575
|
+
traits = traits,
|
576
|
+
entryName = entryName,
|
577
|
+
gpid = gpid,
|
578
|
+
height = height,
|
579
|
+
width = width,
|
580
|
+
icon = icon)
|
581
|
+
|
582
|
+
def clone(self,parent):
|
583
|
+
return self._clone(CardSlot,parent)
|
584
|
+
|
585
|
+
registerElement(CardSlot)
|
586
|
+
|
587
|
+
# --------------------------------------------------------------------
|
588
|
+
class Prototype(WithTraits):
|
589
|
+
TAG = Element.MODULE+'PrototypeDefinition'
|
590
|
+
UNIQUE = ['name']
|
591
|
+
def __init__(self,cont,node=None,
|
592
|
+
name = '',
|
593
|
+
traits = [],
|
594
|
+
description = ''):
|
595
|
+
'''A prototype. Used all the time.
|
596
|
+
|
597
|
+
Parameters
|
598
|
+
----------
|
599
|
+
cont : Element
|
600
|
+
Parent to add this to
|
601
|
+
node : xml.minidom.Element
|
602
|
+
If not None, XML element to read definition from.
|
603
|
+
Rest of the arguments are ignored if not None.
|
604
|
+
name : str
|
605
|
+
Name of this
|
606
|
+
traits : list of Trait objects
|
607
|
+
The traits to set on this object
|
608
|
+
description : str
|
609
|
+
A free-form description of this prototype
|
610
|
+
'''
|
611
|
+
super(Prototype,self).__init__(cont,self.TAG,node=node,
|
612
|
+
traits = traits,
|
613
|
+
name = name,
|
614
|
+
description = description)
|
615
|
+
|
616
|
+
def print(self,file=None,recursive=1024,indent=''):
|
617
|
+
if file is None:
|
618
|
+
from sys import stdout
|
619
|
+
file = stdout
|
620
|
+
from textwrap import indent as i
|
621
|
+
|
622
|
+
print(i(f'Prototype {self["name"]}'+'\n'
|
623
|
+
f' description: {self["description"]}',indent),
|
624
|
+
file = file)
|
625
|
+
|
626
|
+
super(Prototype,self).print(file=file,
|
627
|
+
indent=indent,
|
628
|
+
recursive=recursive-1)
|
629
|
+
|
630
|
+
registerElement(Prototype)
|
631
|
+
|
632
|
+
#
|
633
|
+
# EOF
|
634
|
+
#
|
pywargame/vassal/xml.py
ADDED