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,380 @@
1
+ ## BEGIN_IMPORT
2
+ from common import VerboseGuard
3
+ from . base import *
4
+ from . element import Element
5
+ ## END_IMPORT
6
+
7
+ # --------------------------------------------------------------------
8
+ class GameElement(Element):
9
+ def __init__(self,game,tag,node=None,**kwargs):
10
+ super(GameElement,self).__init__(game,tag,node=node,**kwargs)
11
+
12
+ def getGame(self):
13
+ return self.getParent(Game)
14
+
15
+
16
+ # --------------------------------------------------------------------
17
+ class Notes(GameElement):
18
+ TAG = Element.MODULE+'NotesWindow'
19
+ def __init__(self,elem,node=None,
20
+ name = 'Notes',
21
+ buttonText = '',
22
+ hotkey = key('N',ALT),
23
+ icon = '/images/notes.gif',
24
+ tooltip = 'Show notes window'):
25
+ super(Notes,self).__init__(elem,self.TAG,node=node,
26
+ name = name,
27
+ buttonText = buttonText,
28
+ hotkey = hotkey,
29
+ icon = icon,
30
+ tooltip = tooltip)
31
+ def encode(self):
32
+ return ['NOTES\t\\','PNOTES']
33
+
34
+ registerElement(Notes)
35
+
36
+ # --------------------------------------------------------------------
37
+ class PredefinedSetup(GameElement):
38
+ TAG = Element.MODULE+'PredefinedSetup'
39
+ def __init__(self,elem,node=None,
40
+ name = '',
41
+ file = '',
42
+ useFile = False,
43
+ isMenu = False,
44
+ description = ''):
45
+ useFile = ((useFile or not isMenu) and
46
+ (file is not None and len(file) > 0))
47
+ if file is None: file = ''
48
+ super(PredefinedSetup,self).__init__(elem,self.TAG,node=node,
49
+ name = name,
50
+ file = file,
51
+ useFile = useFile,
52
+ isMenu = isMenu,
53
+ description = description)
54
+ def addPredefinedSetup(self,**kwargs):
55
+ '''Add a `PredefinedSetup` element to this
56
+
57
+ Parameters
58
+ ----------
59
+ kwargs : dict
60
+ Dictionary of attribute key-value pairs
61
+ Returns
62
+ -------
63
+ element : PredefinedSetup
64
+ The added element
65
+ '''
66
+ return self.add(PredefinedSetup,**kwargs)
67
+ def getPredefinedSetups(self,asdict=True):
68
+ '''Get all PredefinedSetup element(s) from this
69
+
70
+ Parameters
71
+ ----------
72
+ asdict : bool
73
+ If `True`, return a dictonary that maps key to `PredefinedSetup` elements. If `False`, return a list of all PredefinedSetup` children.
74
+ Returns
75
+ -------
76
+ children : dict or list
77
+ Dictionary or list of `PredefinedSetup` children
78
+ '''
79
+ return self.getElementsByKey(PredefinedSetup,'name',asdict)
80
+
81
+
82
+
83
+
84
+ registerElement(PredefinedSetup)
85
+
86
+ # --------------------------------------------------------------------
87
+ class GlobalTranslatableMessages(GameElement):
88
+ TAG=Element.MODULE+'properties.GlobalTranslatableMessages'
89
+ def __init__(self,elem,node=None):
90
+ '''Translations
91
+
92
+ Parameters
93
+ ----------
94
+ doc : Element
95
+ Parent
96
+ node : xml.dom.Element
97
+ Node to read state from
98
+ '''
99
+ super(GlobalTranslatableMessages,self).\
100
+ __init__(elem,self.TAG,node=node)
101
+
102
+ registerElement(GlobalTranslatableMessages)
103
+
104
+ # --------------------------------------------------------------------
105
+ class Language(GameElement):
106
+ TAG = 'VASSAL.i18n.Language'
107
+ def __init__(self,elem,node=None,**kwargs):
108
+ super(Languate,self).__init__(sele,self.TAG,node=none,**kwargs)
109
+
110
+ registerElement(Language)
111
+
112
+ # --------------------------------------------------------------------
113
+ class Chatter(GameElement):
114
+ TAG=Element.MODULE+'Chatter'
115
+ def __init__(self,elem,node=None,**kwargs):
116
+ '''Chat
117
+
118
+ Parameters
119
+ ----------
120
+ doc : Element
121
+ Parent
122
+ node : xml.dom.Element
123
+ Node to read state from
124
+ kwargs : dict
125
+ Attributes
126
+ '''
127
+ super(Chatter,self).__init__(elem,self.TAG,node=node,**kwargs)
128
+
129
+ registerElement(Chatter)
130
+
131
+ # --------------------------------------------------------------------
132
+ class KeyNamer(GameElement):
133
+ TAG=Element.MODULE+'KeyNamer'
134
+ def __init__(self,elem,node=None,**kwargs):
135
+ '''Key namer (or help menu)
136
+
137
+ Parameters
138
+ ----------
139
+ doc : Element
140
+ Parent
141
+ node : xml.dom.Element
142
+ Node to read state from
143
+ kwargs : dict
144
+ Attributes
145
+ '''
146
+ super(KeyNamer,self).__init__(elem,self.TAG,node=node,**kwargs)
147
+
148
+ registerElement(KeyNamer)
149
+
150
+ # --------------------------------------------------------------------
151
+ class GlobalOptions(GameElement):
152
+ TAG = Element.MODULE+'GlobalOptions'
153
+ def __init__(self,doc,node=None,
154
+ autoReport = "Use Preferences Setting",
155
+ centerOnMove = "Use Preferences Setting",
156
+ chatterHTMLSupport = "Always",
157
+ hotKeysOnClosedWindows = "Never",
158
+ inventoryForAll = "Always",
159
+ nonOwnerUnmaskable = "Use Preferences Setting",
160
+ playerIdFormat = "$playerName$",
161
+ promptString = "Opponents can unmask pieces",
162
+ sendToLocationMoveTrails = "Never"):
163
+ '''Set global options on the module
164
+
165
+ Parameters
166
+ ----------
167
+ doc : Element
168
+ Parent
169
+ node : xml.dom.Element
170
+ Node to read state from
171
+ autoReport : str Option
172
+ centerOnMove : str Option
173
+ chatterHTMLSupport : str Option
174
+ hotKeysOnClosedWindows : str Option
175
+ inventoryForAll : str Option
176
+ nonOwnerUnmaskable : str Option
177
+ playerIdFormat : str Option
178
+ promptString : str Option
179
+ sendToLocationMoveTrails : str Option
180
+ '''
181
+ super(GlobalOptions,self).\
182
+ __init__(doc,self.TAG,node=node,
183
+ autoReport = autoReport,
184
+ centerOnMove = centerOnMove,
185
+ chatterHTMLSupport = chatterHTMLSupport,
186
+ hotKeysOnClosedWindows = hotKeysOnClosedWindows,
187
+ inventoryForAll = inventoryForAll,
188
+ nonOwnerUnmaskable = nonOwnerUnmaskable,
189
+ playerIdFormat = playerIdFormat,
190
+ promptString = promptString,
191
+ sendToLocationMoveTrails = sendToLocationMoveTrails)
192
+
193
+ def addOption(self,**kwargs):
194
+ '''Add a `Option` element to this
195
+
196
+ Parameters
197
+ ----------
198
+ kwargs : dict
199
+ Dictionary of attribute key-value pairs
200
+ Returns
201
+ -------
202
+ element : Option
203
+ The added element
204
+ '''
205
+ return self.add(Option,**kwargs)
206
+ def getOptions(self):
207
+ return self.getElementsByKey(Option,'name')
208
+
209
+ registerElement(GlobalOptions)
210
+
211
+
212
+ # --------------------------------------------------------------------
213
+ class Option(Element):
214
+ TAG = 'option'
215
+ def __init__(self,doc,node=None,name='',value=''):
216
+ super(Option,self).__init__(doc,node=node,name=name)
217
+ self._root.addText(self._node,value)
218
+
219
+ def getGlobalOptions(self):
220
+ return self.getParent(GlobalOptions)
221
+
222
+ registerElement(Option)
223
+
224
+ # --------------------------------------------------------------------
225
+ # CurrentMap == "Board"
226
+ class Inventory(GameElement):
227
+ TAG = Element.MODULE+'Inventory'
228
+ def __init__(self,doc,node=None,
229
+ canDisable = False,
230
+ centerOnPiece = True,
231
+ disabledIcon = '',
232
+ drawPieces = True,
233
+ foldersOnly = False,
234
+ forwardKeystroke = True,
235
+ groupBy = '',
236
+ hotkey = key('I',ALT),
237
+ icon = '/images/inventory.gif',
238
+ include = '{}',
239
+ launchFunction = 'functionHide',
240
+ leafFormat = '$PieceName$',
241
+ name = '',
242
+ nonLeafFormat = '$PropertyValue$',
243
+ pieceZoom = '0.33',
244
+ pieceZoom2 = '0.5',
245
+ pieceZoom3 = '0.6',
246
+ propertyGate = '',
247
+ refreshHotkey = key('I',ALT_SHIFT),
248
+ showMenu = True,
249
+ sides = '',
250
+ sortFormat = '$PieceName$',
251
+ sortPieces = True,
252
+ sorting = 'alpha',
253
+ text = '',
254
+ tooltip = 'Show inventory of all pieces',
255
+ zoomOn = False):
256
+ super(Inventory,self).__init__(doc,self.TAG,node=node,
257
+ canDisable = canDisable,
258
+ centerOnPiece = centerOnPiece,
259
+ disabledIcon = disabledIcon,
260
+ drawPieces = drawPieces,
261
+ foldersOnly = foldersOnly,
262
+ forwardKeystroke = forwardKeystroke,
263
+ groupBy = groupBy,
264
+ hotkey = hotkey,
265
+ icon = icon,
266
+ include = include,
267
+ launchFunction = launchFunction,
268
+ leafFormat = leafFormat,
269
+ name = name,
270
+ nonLeafFormat = nonLeafFormat,
271
+ pieceZoom = pieceZoom,
272
+ pieceZoom2 = pieceZoom2,
273
+ pieceZoom3 = pieceZoom3,
274
+ propertyGate = propertyGate,
275
+ refreshHotkey = refreshHotkey,
276
+ showMenu = showMenu,
277
+ sides = sides,
278
+ sortFormat = sortFormat,
279
+ sortPieces = sortPieces,
280
+ sorting = sorting,
281
+ text = text,
282
+ tooltip = tooltip,
283
+ zoomOn = zoomOn)
284
+
285
+ registerElement(Inventory)
286
+
287
+ # --------------------------------------------------------------------
288
+ class Prototypes(GameElement):
289
+ TAG = Element.MODULE+'PrototypesContainer'
290
+ def __init__(self,game,node=None,**kwargs):
291
+ super(Prototypes,self).\
292
+ __init__(game,self.TAG,node=node,**kwargs)
293
+
294
+ def addPrototype(self,**kwargs):
295
+ '''Add a `Prototype` element to this
296
+
297
+ Parameters
298
+ ----------
299
+ kwargs : dict
300
+ Dictionary of attribute key-value pairs
301
+ Returns
302
+ -------
303
+ element : Prototype
304
+ The added element
305
+ '''
306
+ return self.add(Prototype,**kwargs)
307
+ def getPrototypes(self,asdict=True):
308
+ '''Get all Prototype element(s) from this
309
+
310
+ Parameters
311
+ ----------
312
+ asdict : bool
313
+ If `True`, return a dictonary that maps key to `Prototype` elements. If `False`, return a list of all Prototype` children.
314
+ Returns
315
+ -------
316
+ children : dict or list
317
+ Dictionary or list of `Prototype` children
318
+ '''
319
+ return self.getElementsByKey(Prototype,'name',asdict=asdict)
320
+
321
+
322
+
323
+ registerElement(Prototypes)
324
+
325
+ # --------------------------------------------------------------------
326
+ class DiceButton(GameElement):
327
+ TAG=Element.MODULE+'DiceButton'
328
+ def __init__(self,elem,node=None,
329
+ addToTotal = 0,
330
+ canDisable = False,
331
+ hotkey = key('6',ALT),
332
+ icon = '/images/die.gif',
333
+ keepCount = 1,
334
+ keepDice = False,
335
+ keepOption = '>',
336
+ lockAdd = False,
337
+ lockDice = False,
338
+ lockPlus = False,
339
+ lockSides = False,
340
+ nDice = 1,
341
+ nSides = 6,
342
+ name = '1d6',
343
+ plus = 0,
344
+ prompt = False,
345
+ propertyGate = '',
346
+ reportFormat = '** $name$ = $result$ *** <$PlayerName$>;',
347
+ reportTotal = False,
348
+ sortDice = False,
349
+ text = '1d6',
350
+ tooltip = 'Roll a 1d6'):
351
+ super(DiceButton,self).\
352
+ __init__(elem,self.TAG,node=node,
353
+ addToTotal = addToTotal,
354
+ canDisable = canDisable,
355
+ hotkey = hotkey,
356
+ icon = icon,
357
+ keepCount = keepCount,
358
+ keepDice = keepDice,
359
+ keepOption = keepOption,
360
+ lockAdd = lockAdd,
361
+ lockDice = lockDice,
362
+ lockPlus = lockPlus,
363
+ lockSides = lockSides,
364
+ nDice = nDice,
365
+ nSides = nSides,
366
+ name = name,
367
+ plus = plus,
368
+ prompt = prompt,
369
+ propertyGate = propertyGate,
370
+ reportFormat = reportFormat,
371
+ reportTotal = reportTotal,
372
+ sortDice = sortDice,
373
+ text = text,
374
+ tooltip = tooltip)
375
+
376
+ registerElement(DiceButton)
377
+
378
+ #
379
+ # EOF
380
+ #
@@ -0,0 +1,224 @@
1
+ # ====================================================================
2
+ class Trait:
3
+ known_traits = []
4
+ def __init__(self):
5
+ '''Base class for trait capture.
6
+
7
+ Unlike the Element classes, this actually holds state that
8
+ isn't reflected elsewhere in the DOM. This means that the
9
+ data here is local to the object. So when we do
10
+
11
+ piece = foo.getPieceSlots()[0]
12
+ traits = p.getTraits()
13
+ for trait in traits:
14
+ if trait.ID == 'piece':
15
+ trait["gpid"] = newPid
16
+ trait["lpid"] = newPid
17
+
18
+ we do not actually change anything in the DOM. To do that, we
19
+ must add back _all_ the traits as
20
+
21
+ piece.setTraits(traits)
22
+
23
+ We can add traits to a piece, like
24
+
25
+ piece.addTrait(MarkTrait('Hello','World'))
26
+
27
+ But it is not particularly efficient. Better to do
28
+ (continuing from above)
29
+
30
+ traits.append(MarkTrait('Hello','World;)
31
+ piece.setTraits(traits)
32
+
33
+ .. include:: ../../vassal/traits/README.md
34
+ :parser: myst_parser.sphinx_
35
+
36
+ '''
37
+ self._type = None
38
+ self._state = None
39
+
40
+ def setType(self,**kwargs):
41
+ '''Set types. Dictionary of names and values. Dictonary keys
42
+ defines how we access the fields, which is internal here.
43
+ What matters is the order of the values.
44
+
45
+ '''
46
+ self._type = list(kwargs.values())
47
+ self._tnames = list(kwargs.keys())
48
+
49
+ def setState(self,**kwargs):
50
+ '''Set states. Dictionary of names and values. Dictonary keys
51
+ defines how we access the fields, which is internal here.
52
+ What matters is the order of the values.
53
+ '''
54
+ self._state = list(kwargs.values())
55
+ self._snames = list(kwargs.keys())
56
+
57
+ def __getitem__(self,key):
58
+ '''Look up item in either type or state'''
59
+ try:
60
+ return self._type[self._tnames.index(key)]
61
+ except:
62
+ pass
63
+ return self._state[self._snames.index(key)]
64
+
65
+ def __setitem__(self,key,value):
66
+ '''Set item in either type or state'''
67
+ try:
68
+ self._type[self._tnames.index(key)] = value
69
+ return
70
+ except:
71
+ pass
72
+ self._state[self._snames.index(key)] = value
73
+
74
+ def encode(self,term=False):
75
+ '''
76
+ returns type and state encoded'''
77
+ t = self.encodeFields(self.ID,*self._type,term=term)
78
+ s = self.encodeFields(*self._state,term=term)
79
+ return t,s
80
+
81
+ @classmethod
82
+ def findTrait(cls,traits,ID,key=None,value=None,verbose=False):
83
+ for trait in traits:
84
+ if trait.ID != ID:
85
+ continue
86
+ if verbose:
87
+ print(f' {trait.ID}')
88
+ if key is None or value is None:
89
+ if verbose:
90
+ print(f' Return {trait.ID}')
91
+ return trait
92
+ if verbose:
93
+ print(f' Check {key}={value}: {trait[key]}')
94
+ if trait[key] == value:
95
+ return trait
96
+ if verbose:
97
+ print(f' Trait of type {ID} with {key}={value} not found')
98
+ return None
99
+
100
+ @classmethod
101
+ def take(cls,iden,t,s):
102
+ '''If the first part of the string t matches the ID, then take it.
103
+
104
+ t and s are lists of strings.
105
+ '''
106
+ if iden != cls.ID: return None
107
+
108
+ ret = cls()
109
+ ret._type = t
110
+ ret._state = s
111
+ ret.check() # Check if we're reasonable, or raise
112
+ #print(f'Took {iden} {cls}\n'
113
+ # f' {ret._tnames}\n'
114
+ # f' {ret._snames}')
115
+ return ret
116
+
117
+ def check(self):
118
+ '''Implement if trait should check that all is OK when cloning'''
119
+ pass
120
+
121
+ @classmethod
122
+ def encodeFields(cls,*args,term=False):
123
+ return ';'.join([str(e).lower() if isinstance(e,bool) else str(e)
124
+ for e in args])+(';' if term else '')
125
+
126
+ @classmethod
127
+ def decodeFields(cls,s):
128
+ from re import split
129
+ return split(r'(?<!\\);',s)
130
+ # return s.split(';') # Probably too simple-minded
131
+
132
+ @classmethod
133
+ def encodeKeys(cls,keys,sep=','):
134
+ return sep.join([k.replace(',','\\'+f'{sep}') for k in keys])
135
+
136
+ @classmethod
137
+ def decodeKeys(cls,keys,sep=','):
138
+ from re import split
139
+ ks = split(r'(?<!\\)'+f'{sep}',keys)
140
+ return [k.replace('\\'+f'{sep}',f'{sep}') for k in ks]
141
+
142
+ @classmethod
143
+ def flatten(cls,traits,game=None,prototypes=None,verbose=False):
144
+ ## BEGIN_IMPORT
145
+ from . traits import BasicTrait
146
+ ## END_IMPORT
147
+ if prototypes is None:
148
+ if game is None:
149
+ print(f'Warning: Game or prototypes not passed')
150
+ return None
151
+ prototypes = game.getPrototypes()[0].getPrototypes()
152
+
153
+ if len(traits) < 1: return None
154
+
155
+ basic = None
156
+ if traits[-1].ID == 'piece': # BasicTrait.ID:
157
+ basic = traits.pop()
158
+
159
+ if verbose:
160
+ print(f'Piece {basic["name"]}')
161
+
162
+ ret = cls._flatten(traits,prototypes,' ',verbose)
163
+ ret.append(basic)
164
+
165
+ return ret
166
+
167
+ @classmethod
168
+ def _flatten(cls,traits,prototypes,ind,verbose):
169
+ ## BEGIN_IMPORT
170
+ from . traits import BasicTrait
171
+ from . traits import PrototypeTrait
172
+ ## END_IMPORT
173
+ '''Expand all prototype traits in traits'''
174
+ ret = []
175
+ for trait in traits:
176
+ # Ignore recursive basic traits
177
+ if trait.ID == BasicTrait.ID:
178
+ continue
179
+ # Add normal traits
180
+ if trait.ID != PrototypeTrait.ID:
181
+ if verbose:
182
+ print(f'{ind}Adding trait "{trait.ID}"')
183
+
184
+ ret.append(trait)
185
+ continue
186
+
187
+ # Find prototype
188
+ name = trait['name']
189
+ proto = prototypes.get(name,None)
190
+ if proto is None:
191
+ if name != ' prototype':
192
+ print(f'{ind}Warning, prototype {name} not found')
193
+ continue
194
+
195
+ if verbose:
196
+ print(f'{ind}Expanding prototype "{name}"')
197
+
198
+ # Recursive call to add prototype traits (and possibly
199
+ # more recursive calls
200
+ ret.extend(cls._flatten(proto.getTraits(), prototypes,
201
+ ind+' ',verbose))
202
+
203
+ return ret
204
+
205
+ def print(self,file=None):
206
+ if file is None:
207
+ from sys import stdout
208
+ file = stdout
209
+
210
+ nt = max([len(i) for i in self._tnames]) if self._tnames else 0
211
+ ns = max([len(i) for i in self._snames]) if self._snames else 0
212
+ nw = max(nt,ns)
213
+
214
+ print(f'Trait ID={self.ID}',file=file)
215
+ print(f' Type:', file=file)
216
+ for n,v in zip(self._tnames,self._type):
217
+ print(f' {n:<{nw}s}: {v}',file=file)
218
+ print(f' State:', file=file)
219
+ for n,v in zip(self._snames,self._state):
220
+ print(f' {n:<{nw}s}: {v}',file=file)
221
+
222
+ #
223
+ # EOF
224
+ #
@@ -0,0 +1,36 @@
1
+ #
2
+ from . area import AreaTrait
3
+ from . basic import BasicTrait
4
+ from . calculatedproperty import CalculatedTrait
5
+ from . clone import CloneTrait
6
+ from . delete import DeleteTrait
7
+ from . globalcommand import GlobalCommandTrait
8
+ from . globalhotkey import GlobalHotkeyTrait
9
+ from . dynamicproperty import *
10
+ from . nostack import *
11
+ from . deselect import *
12
+ from . globalproperty import GlobalPropertyTrait
13
+ from . label import LabelTraitCodes, LabelTrait
14
+ from . layer import LayerTrait
15
+ from . mark import MarkTrait
16
+ from . mask import MaskTrait
17
+ from . moved import MovedTrait
18
+ from . place import PlaceTrait
19
+ from . prototype import PrototypeTrait
20
+ from . report import ReportTrait
21
+ from . restrictaccess import RestrictAccessTrait
22
+ from . restrictcommand import RestrictCommandsTrait
23
+ from . rotate import RotateTrait
24
+ from . sendto import SendtoTrait
25
+ from . stack import StackTrait
26
+ from . submenu import SubMenuTrait
27
+ from . trail import TrailTrait
28
+ from . trigger import TriggerTrait
29
+ from . nonrect import NonRectangleTrait
30
+ from . click import ClickTrait
31
+ from . mat import MatTrait
32
+ from . cargo import CargoTrait
33
+ from . movefixed import MoveFixedTrait
34
+ from . sheet import SheetTrait
35
+ from . hide import HideTrait
36
+ from . return import ReturnTrait
@@ -0,0 +1,50 @@
1
+ ## BEGIN_IMPORT
2
+ from common import VerboseGuard
3
+ from .. trait import Trait
4
+ from .. base import rgb, key
5
+ ## END_IMPORT
6
+
7
+ class AreaTrait(Trait):
8
+ ID = 'AreaOfEffect'
9
+ def __init__(self,
10
+ transparancyColor = rgb(0x77,0x77,0x77),
11
+ transparancyLevel = 30,
12
+ radius = 1,
13
+ alwaysActive = False,
14
+ activateCommand = 'Toggle area of effect',
15
+ activateKey = key('A'), # Ctrl-A
16
+ mapShaderName = '',
17
+ fixedRadius = True,
18
+ radiusMarker = '', # Property
19
+ description = 'Show area of effect',
20
+ name = 'EffectArea',
21
+ onMenuText = '', # Show area of effect
22
+ onKey = '', # key('A')
23
+ offMenuText = '', # Hide area of effect
24
+ offKey = '', # key(A,SHIFT)
25
+ globallyVisible = True):
26
+ super(AreaTrait,self).__init__()
27
+ self.setType(
28
+ transparancyColor = transparancyColor,
29
+ transparancyLevel = int(transparancyLevel),
30
+ radius = radius,
31
+ alwaysActive = alwaysActive,
32
+ activateCommand = activateCommand,
33
+ activateKey = activateKey,
34
+ mapShaderName = mapShaderName,
35
+ fixedRadius = fixedRadius,
36
+ radiusMarker = radiusMarker,
37
+ description = description,
38
+ name = name,
39
+ onMenuText = onMenuText,
40
+ onKey = onKey,
41
+ offMenuText = offMenuText,
42
+ offKey = offKey,
43
+ globallyVisible = globallyVisible
44
+ )
45
+ self.setState(active = alwaysActive or not globallyVisible)
46
+
47
+ Trait.known_traits.append(AreaTrait)
48
+ #
49
+ # EOF
50
+ #