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,240 @@
1
+ ## BEGIN_IMPORT
2
+ from common import VerboseGuard
3
+ ## END_IMPORT
4
+
5
+ # ====================================================================
6
+ class CbExtractor:
7
+ def __init__(self):
8
+ pass
9
+
10
+ def save(self,filename):
11
+ from zipfile import ZipFile
12
+ from copy import deepcopy
13
+
14
+ with VerboseGuard(f'Saving to {filename}') as g:
15
+ with ZipFile(filename,'w') as zfile:
16
+ self._save(zfile)
17
+
18
+ def saveImages(self,d,zfile):
19
+ with VerboseGuard(f'Saving images') as g:
20
+ for serial, board in d['boards'].items():
21
+ g(f'Saving board: {board}')
22
+ self.saveSVG(board,zfile)
23
+
24
+ for piece in d['pieces']['map'].values():
25
+ g(f'Saving piece: {piece}')
26
+ for which in ['front','back']:
27
+ if which not in piece:
28
+ continue
29
+
30
+ side = piece[which]
31
+ self.savePNG(side,zfile)
32
+ piece[which] = side['filename']
33
+
34
+ for mark in d['marks']['map'].values():
35
+ g(f'Saving marks: {mark}')
36
+ self.savePNG(mark,zfile)
37
+
38
+ for tile in d['tiles'].values():
39
+ g(f'Saving tile: {tile}')
40
+ self.savePNG(tile,zfile)
41
+
42
+ del d['tiles']
43
+
44
+
45
+ def saveSVG(self,d,zfile,removeImage=True):
46
+ from io import StringIO
47
+
48
+ with VerboseGuard(f'Saving SVG') as g:
49
+ filename = d['filename']
50
+ image = d['image']
51
+
52
+ # stream = StringIO()
53
+ # image.write(stream,pretty=True)
54
+ g(f'Saving SVG: {image}')
55
+ zfile.writestr(filename,image)#stream.getvalue())
56
+
57
+ if removeImage:
58
+ del d['image']
59
+
60
+ def savePNG(self,d,zfile,removeImage=True):
61
+ with VerboseGuard(f'Saving PNG') as g:
62
+ filename = d['filename']
63
+ img = d['image']
64
+
65
+ with zfile.open(filename,'w') as file:
66
+ g(f'Save {img}')
67
+ img.save(file,format='PNG')
68
+
69
+ if removeImage:
70
+ del d['image']
71
+
72
+ def _save(self,zfile):
73
+ pass
74
+
75
+
76
+ # ====================================================================
77
+ class GBXExtractor(CbExtractor):
78
+ def __init__(self,gbx):
79
+ '''Turns gambox into a more sensible structure'''
80
+ super(GBXExtractor,self).__init__()
81
+
82
+ with VerboseGuard(f'Extract gamebox {gbx._info._title}') as g:
83
+ self._d = {
84
+ 'title': gbx._info._title,
85
+ 'author': gbx._info._author,
86
+ 'description': gbx._info._description.replace('\r',''),
87
+ 'major': gbx._info._majorRevs,
88
+ 'minor': gbx._info._minorRevs,
89
+ 'version': f'{gbx._info._majorRevs}.{gbx._info._minorRevs}'
90
+ }
91
+
92
+ self._d['pieces'] = gbx._pieceManager.toDict(gbx._tileManager,
93
+ gbx._strings)
94
+ self._d['marks'] = gbx._markManager.toDict(gbx._tileManager,
95
+ gbx._strings)
96
+ self._d['boards'] = gbx._boardManager.toDict(gbx._tileManager,
97
+ gbx._markManager,
98
+ gbx._strings)
99
+ self._d['tiles'] = gbx._tileManager._toStore
100
+
101
+ g(f'Done rationalizing {gbx._info._title}')
102
+
103
+
104
+ def _save(self,zfile):
105
+ from pprint import pprint
106
+ from io import StringIO
107
+ from json import dumps
108
+ from copy import deepcopy
109
+
110
+ with VerboseGuard(f'Saving {self._d["title"]} to {zfile.filename}')as g:
111
+ d = deepcopy(self._d)
112
+
113
+ self.saveImages(d,zfile)
114
+
115
+ zfile.writestr('info.json',dumps(d,indent=2))
116
+
117
+ g(f'Done saving')
118
+
119
+ def fromZipfile(self,zipfile,d):
120
+ pass
121
+
122
+ def __str__(self):
123
+ from pprint import pformat
124
+
125
+ return pformat(self._d,depth=2)
126
+
127
+ # ====================================================================
128
+ class GSNExtractor(CbExtractor):
129
+ def __init__(self,gsn,zipfile=None):
130
+ '''Turns gambox into a more sensible structure'''
131
+ super(GSNExtractor,self).__init__()
132
+
133
+ if zipfile is not None:
134
+ self.fromZipfile(zipfile)
135
+ return
136
+
137
+ with VerboseGuard(f'Extract scenario {gsn._info._title}') as g:
138
+ gbxextractor = GBXExtractor(gsn._gbx)
139
+ self._d = {
140
+ 'title': gsn._info._title,
141
+ 'author': gsn._info._author,
142
+ 'description': gsn._info._description.replace('\r',''),
143
+ 'major': gsn._info._majorRevs,
144
+ 'minor': gsn._info._minorRevs,
145
+ 'version': f'{gsn._info._majorRevs}.{gsn._info._minorRevs}',
146
+ 'gamebox': gbxextractor._d}
147
+ self._d['players'] = gsn._playerManager.toDict()
148
+ self._d['trays'] = gsn._trayManager.toDict()
149
+ self._d['boards'] = gsn._boards.toDict(gsn._gbx._boardManager)
150
+
151
+
152
+ def _save(self,zfile):
153
+ from pprint import pprint
154
+ from io import StringIO
155
+ from json import dumps
156
+ from copy import deepcopy
157
+
158
+ with VerboseGuard(f'Saving {self._d["title"]} to {zfile.filename}')as g:
159
+ d = deepcopy(self._d)
160
+
161
+ self.saveImages(d['gamebox'],zfile)
162
+
163
+ zfile.writestr('info.json',dumps(d,indent=2))
164
+
165
+ g(f'Done saving')
166
+
167
+ def fromZipfile(self,zipfile):
168
+ from json import loads
169
+ from PIL import Image as PILImage
170
+ from io import BytesIO
171
+ from wand.image import Image as WandImage
172
+ with VerboseGuard(f'Reading module from zip file') as v:
173
+ self._d = loads(zipfile.read('info.json').decode())
174
+
175
+ newMap = {}
176
+ for pieceSID,piece in self._d['gamebox']['pieces']['map'].items():
177
+ pieceID = int(pieceSID)
178
+ if pieceID in newMap:
179
+ continue
180
+ for which in ['front', 'back']:
181
+ if which not in piece:
182
+ continue
183
+
184
+
185
+ fn = piece[which]
186
+ v(f'Read image {fn}')
187
+ bts = BytesIO(zipfile.read(fn))
188
+ img = PILImage.open(bts)
189
+ piece[which] = {'filename': fn,
190
+ 'image': img,
191
+ 'size': img.size}
192
+
193
+ newMap[pieceID] = piece
194
+
195
+ del self._d['gamebox']['pieces']['map']
196
+ self._d['gamebox']['pieces']['map'] = newMap
197
+
198
+ newMap = {}
199
+ for markSID,mark in self._d['gamebox']['marks']['map'].items():
200
+ markID = int(markSID)
201
+ if markID in newMap:
202
+ continue
203
+ fn = mark['filename']
204
+ v(f'Read image {fn}')
205
+ bts = BytesIO(zipfile.read(fn))
206
+ img = PILImage.open(bts)
207
+ dsc = mark.get('description',None)
208
+ mark['image'] = img
209
+ mark['size'] = img.size
210
+ newMap[markID] = mark
211
+
212
+ del self._d['gamebox']['marks']['map']
213
+ self._d['gamebox']['marks']['map'] = newMap
214
+
215
+ newMap = {}
216
+ for boardSID,board in self._d['gamebox']['boards'].items():
217
+ boardID = int(boardSID)
218
+ if boardID in newMap:
219
+ continue
220
+ filename = board['filename']
221
+ v(f'Read file {filename}')
222
+ content = zipfile.read(filename)
223
+ img = WandImage(blob=content)
224
+ board['image'] = content.decode()
225
+ board['size'] = img.size
226
+ newMap[boardID] = board
227
+
228
+ # del self._d['gamebox']['boards']
229
+ # self._d['gamebox']['boards'] = newMap
230
+
231
+ # print(self)
232
+
233
+ def __str__(self):
234
+ from pprint import pformat
235
+
236
+ return pformat(self._d)#,depth=5)
237
+
238
+ #
239
+ # EOF
240
+ #
@@ -0,0 +1,17 @@
1
+ # --------------------------------------------------------------------
2
+ ## BEGIN_IMPORT
3
+ from common.singleton import Singleton
4
+ ## END_IMPORT
5
+
6
+ class Features(metaclass=Singleton):
7
+ def __init__(self):
8
+ self.bmp_zlib = False # wxBMPHandler + Zlib
9
+ self.id_size = 2 # Size of IDs in bytes (1, 2 or 4)
10
+ self.size_size = 4 # Size of sizes in bytes (4 or 8)
11
+ self.sub_size = 2 # Size of sub-sizes in bytes (4 or 8)
12
+ self.square_cells = False # Geomorphic boards, square cells
13
+ self.rotate_unit = False # Geomorphic boards, rotated unit board
14
+ self.piece_100 = False # Pieces w/<= 100 sides
15
+ self.private_board = False #
16
+ self.roll_state = False # serialize roll state
17
+ self.little_endian = True
@@ -0,0 +1,81 @@
1
+ ## BEGIN_IMPORT
2
+ from common import VerboseGuard
3
+ from . head import *
4
+ from . tile import GBXTileManager
5
+ from . piece import GBXPieceManager
6
+ from . mark import GBXMarkManager
7
+ from . board import GBXBoardManager
8
+ from . archive import Archive
9
+ from . features import Features
10
+ ## END_IMPORT
11
+
12
+ # --------------------------------------------------------------------
13
+ class GBXInfo:
14
+ def __init__(self,ar):
15
+ '''GameBox information'''
16
+ with VerboseGuard('Reading information') as g:
17
+ self._bitsPerPixel = ar.word() # 2 -> 2
18
+ self._majorRevs = ar.dword() # 4 -> 6
19
+ self._minorRevs = ar.dword() # 4 -> 10
20
+ self._gameID = ar.dword() # 4 -> 14
21
+ self._boxID = ar.read(16) # 16 -> 30
22
+ self._author = ar.str() # X -> 30+X
23
+ self._title = ar.str() # Y -> 30+X+Y
24
+ self._description = ar.str() # Z -> 30+X+Y+Z
25
+ self._password = ar.read(16) # 16 -> 46+X+Y+Z
26
+ self._stickyDraw = ar.word() # 2 -> 48+X+Y+Z
27
+ self._compression = ar.word() # 2 -> 50+X+Y+Z
28
+ self._reserved = [ar.word() for _ in range(4)] # 4x2 -> 58+X+Y+Z
29
+ g(f'GameBox is {self._title} by {self._author} (password: {self._password})')
30
+
31
+ def __str__(self):
32
+ return ('Information:\n'
33
+ f' Bits/pixel: {self._bitsPerPixel}\n'
34
+ f' Major revision: {self._majorRevs}\n'
35
+ f' Minor revision: {self._minorRevs}\n'
36
+ f' Game ID: {self._gameID}\n'
37
+ f' Box ID: {self._boxID}\n'
38
+ f' Author: {self._author}\n'
39
+ f' Title: {self._title}\n'
40
+ f' Description: {self._description}\n'
41
+ f' Password: {self._password}\n'
42
+ f' Sticky Draw tools: {self._stickyDraw}\n'
43
+ f' Compression level: {self._compression}\n'
44
+ f' Reserved: {self._reserved}')
45
+
46
+
47
+ # ====================================================================
48
+ class GameBox:
49
+ def __init__(self,ar):
50
+ '''Container of game'''
51
+ with VerboseGuard(f'Reading gamebox'):
52
+ self._header = GBXHeader(ar,GBXHeader.BOX)
53
+ self._info = GBXInfo(ar)
54
+ self._strings = GBXStrings(ar)
55
+ self._tileManager = GBXTileManager(ar)
56
+ self._boardManager = GBXBoardManager(ar)
57
+ self._pieceManager = GBXPieceManager(ar)
58
+ self._markManager = GBXMarkManager(ar)
59
+
60
+ # print(self._strings)
61
+ # print(self._markManager)
62
+
63
+ def __str__(self):
64
+ return (str(self._header)+
65
+ str(self._info)+
66
+ str(self._strings)+
67
+ str(self._tileManager)+
68
+ str(self._boardManager)+
69
+ str(self._pieceManager)+
70
+ str(self._markManager))
71
+
72
+
73
+ @classmethod
74
+ def fromFile(cls,filename):
75
+ with VerboseGuard(f'Read gamebox from {filename}'):
76
+ with Archive(filename,'rb') as ar:
77
+ return GameBox(ar)
78
+
79
+ #
80
+ # EOF
81
+ #
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env python
2
+ ## BEGIN_IMPORTS
3
+ from exporter import GBXExporter
4
+ from common import Verbose
5
+ from gamebox import GameBox
6
+ from extractor import GBXExtractor
7
+ ## END_IMPORTS
8
+
9
+ # ====================================================================
10
+ if __name__ == '__main__':
11
+ from argparse import ArgumentParser, FileType
12
+
13
+ ap = ArgumentParser(description='Create draft VASSAL module')
14
+ ap.add_argument('gbxfile',
15
+ help='The GBX file to data from',
16
+ type=FileType('r'))
17
+ ap.add_argument('-p','--patch',
18
+ help='A python script to patch generated module',
19
+ type=FileType('r'))
20
+ ap.add_argument('-o','--output',
21
+ help='Output file to write module to',
22
+ type=FileType('w'),
23
+ default='Draft.vmod')
24
+ ap.add_argument('-r','--rules',
25
+ help='Rules PDF file',
26
+ type=FileType('r'))
27
+ ap.add_argument('-T','--tutorial',
28
+ help='Tutorial (v)log file',
29
+ type=FileType('r'))
30
+ ap.add_argument('-W','--vassal-version',
31
+ help='Vassal version number',
32
+ type=str,
33
+ default='3.6.7')
34
+ ap.add_argument('-V','--verbose',
35
+ help='Be verbose',
36
+ action='store_true')
37
+ ap.add_argument('-G','--visible-grids',
38
+ action='store_true',
39
+ help='Make grids visible in the module')
40
+
41
+
42
+ args = ap.parse_args()
43
+
44
+ gbxname = args.gbxfile.name
45
+ vmodname = args.output.name
46
+ rulesname = args.rules.name if args.rules is not None else None
47
+ tutname = args.tutorial.name if args.tutorial is not None else None
48
+ args.output.close()
49
+ args.gbxfile.close()
50
+
51
+ patchname = args.patch.name if args.patch is not None else None
52
+ if args.patch is not None:
53
+ args.patch.close()
54
+
55
+ Verbose().setVerbose(args.verbose)
56
+
57
+ try:
58
+ gamebox = GameBox.fromFile(gbxname)
59
+ extractor = GBXExtractor(gamebox)
60
+ exporter = GBXExporter(extractor._d,
61
+ rules = rulesname,
62
+ tutorial = tutname,
63
+ visible = args.visible_grids,
64
+ vassalVersion = args.vassal_version)
65
+ exporter.run(vmodname,patchname)
66
+ except Exception as e:
67
+ from sys import stderr
68
+ print(f'Failed to build {vmodname}: {e}',file=stderr)
69
+ from os import unlink
70
+ try:
71
+ unlink(vmodname)
72
+ except:
73
+ pass
74
+
75
+ raise e
76
+
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env python
2
+ #
3
+ # CyberBoard GitHub page:
4
+ #
5
+ # https://github.com/CyberBoardPBEM/cbwindows
6
+ #
7
+ #
8
+
9
+
10
+ # ====================================================================
11
+ if __name__ == '__main__':
12
+ from argparse import ArgumentParser, FileType
13
+ from pathlib import Path
14
+ ## BEGIN_IMPORT
15
+ from gamebox import GameBox
16
+ from extractor import GBXExtractor
17
+ from common import Verbose
18
+ ## END_IMPORT
19
+
20
+ ap = ArgumentParser(description='Extract information from a '
21
+ 'CyberBoard GameBox file and store in ZIP archive',
22
+ epilog='Default output file name is input file name '
23
+ 'with .gbx replaced by .zip')
24
+ ap.add_argument('input', type=str, help='The file')
25
+ ap.add_argument('output',type=str, nargs='?',help='Output',default='')
26
+ ap.add_argument('-V','--verbose',
27
+ help='Be verbose',
28
+ action='store_true')
29
+ ap.add_argument('-D','--dump',type=str,nargs='*',default='',
30
+ help='Dump content')
31
+ ap.add_argument('-S','--size-bytes',type=int,choices=[4,8],
32
+ default=4, help='The size of size counts')
33
+ ap.add_argument('-I','--id-bytes',type=int,choices=[2,4],
34
+ default=2, help='The size of identifiers')
35
+ ap.add_argument('-P','--password',action='store_true',
36
+ help='Show password')
37
+
38
+ args = ap.parse_args()
39
+ Verbose().setVerbose(args.verbose)
40
+
41
+ Features().size_size = args.size_bytes
42
+ Features().id_size = args.id_bytes
43
+
44
+ gbx = GameBox.fromFile(args.input)
45
+ if args.password:
46
+ print(f'Password is "{gbx._info._password.decode()}"')
47
+
48
+ rat = GBXExtractor(gbx)
49
+
50
+ out = args.output
51
+ if out == '':
52
+ p = Path(args.input)
53
+ out = p.stem+'.zip'
54
+
55
+ rat.save(out)
56
+
57
+ if 'save' in args.dump:
58
+ print(rat)
59
+ if 'gbx' in args.dump:
60
+ print(gbx)
61
+
62
+
63
+
64
+
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env python
2
+ ## BEGIN_IMPORTS
3
+ from sys import path
4
+ path.append('..')
5
+ from exporter import GSNExporter
6
+ from common import Verbose
7
+ from scenario import Scenario
8
+ from extractor import GSNExtractor
9
+ from head import GBXHeader
10
+ ## END_IMPORTS
11
+
12
+ # ====================================================================
13
+ if __name__ == '__main__':
14
+ from argparse import ArgumentParser, FileType, \
15
+ RawDescriptionHelpFormatter
16
+ from textwrap import wrap, dedent
17
+ from pathlib import Path
18
+
19
+ w = lambda s : '\n\n'.join(['\n'.join(wrap(p))
20
+ for p in dedent(s).split('\n\n')])
21
+ e = '''
22
+ The script can only handle CyberBoard game boxes and scenarios
23
+ from version 3 and up. Use CBDesign.exe and CBPlay.exe to
24
+ upgrade any pre-version 3 '.gbx' and '.gsn' files, respectively.
25
+
26
+ You can override the game box files searched for by passing
27
+ that game box file name to the option '--gamebox'.
28
+
29
+ If the script finds the wrong main map, try passing the name
30
+ of the main board as argument to the option '--main-board'.
31
+
32
+ If the script adds boards (maps) to the 'Charts' menu,
33
+ rather than as maps, pass a regular expression to match
34
+ these board names, as argument to the option '--map-regex'.
35
+
36
+ Pass a Python script with the option -p to do
37
+ user post-processing with that script. Use the
38
+ pywargame VASSAL API to do all sorts of manipulations.
39
+ '''
40
+
41
+ ap = ArgumentParser(description='Create draft VASSAL module',
42
+ formatter_class= RawDescriptionHelpFormatter,
43
+ epilog=w(e))
44
+ ap.add_argument('gsnfile',
45
+ help='The GSN file to data from',
46
+ type=FileType('rb'))
47
+ ap.add_argument('-p','--patch',
48
+ help='A python script to patch generated module',
49
+ type=FileType('r'))
50
+ ap.add_argument('-o','--output',
51
+ help='Output file to write module to',
52
+ type=str,
53
+ default='')
54
+ ap.add_argument('-t','--title',
55
+ help='Override title',
56
+ type=str,
57
+ default=None)
58
+ ap.add_argument('-v','--version',
59
+ help='Override version',
60
+ type=str,
61
+ default=None)
62
+ ap.add_argument('-r','--rules',
63
+ help='Rules PDF file',
64
+ type=FileType('r'))
65
+ ap.add_argument('-T','--tutorial',
66
+ help='Tutorial (v)log file',
67
+ type=FileType('r'))
68
+ ap.add_argument('-W','--vassal-version',
69
+ help='Vassal version number',
70
+ type=str,
71
+ default='3.7.0')
72
+ ap.add_argument('-V','--verbose',
73
+ help='Be verbose',
74
+ action='store_true')
75
+ ap.add_argument('-G','--visible-grids',
76
+ action='store_true',
77
+ help='Make grids visible in the module')
78
+ ap.add_argument('-X','--gamebox',
79
+ type=str,
80
+ default=None,
81
+ help='Override gamebox (.gbx) file')
82
+ ap.add_argument('-M','--main-board',
83
+ type=str,
84
+ default=None,
85
+ help='Set the main board')
86
+ ap.add_argument('-R','--map-regex',
87
+ type=str,
88
+ default=None,
89
+ help='Regular expression to match additional maps')
90
+ ap.add_argument('-S','--scenario',
91
+ action='store_true',
92
+ help='Make scenario rather than at-start placements')
93
+
94
+
95
+ args = ap.parse_args()
96
+
97
+ gsnname = args.gsnfile.name
98
+ zipfile = None
99
+ vmodname = args.output
100
+ rulesname = args.rules.name if args.rules is not None else None
101
+ tutname = args.tutorial.name if args.tutorial is not None else None
102
+ # Read first 4 bytes from input to see if we're dealing with a GSN file
103
+ magic = args.gsnfile.read(4)
104
+ args.gsnfile.close()
105
+ if magic != GBXHeader.SCENARIO.encode():
106
+ if magic[:2] == 'PK'.encode():
107
+ from zipfile import ZipFile
108
+ zipfile = ZipFile(gsnname,'r')
109
+ # args.output.close()
110
+
111
+ if vmodname == '':
112
+ p = Path(gsnname)
113
+ vmodname = p.stem+'.vmod'
114
+
115
+ patchname = args.patch.name if args.patch is not None else None
116
+ if args.patch is not None:
117
+ args.patch.close()
118
+
119
+ Verbose().setVerbose(args.verbose)
120
+
121
+ try:
122
+ scenario = None
123
+ if zipfile is None:
124
+ scenario = Scenario.fromFile(gsnname,args.gamebox)
125
+ extractor = GSNExtractor(scenario,zipfile)
126
+ exporter = GSNExporter(extractor._d,
127
+ title = args.title,
128
+ version = args.version,
129
+ rules = rulesname,
130
+ tutorial = tutname,
131
+ visible = args.visible_grids,
132
+ main_board = args.main_board,
133
+ map_regex = args.map_regex,
134
+ vassalVersion = args.vassal_version,
135
+ do_scenario = args.scenario)
136
+ exporter.run(vmodname,patchname)
137
+ except Exception as e:
138
+ from sys import stderr
139
+ print(f'Failed to build {vmodname}: {e}',file=stderr)
140
+ from os import unlink
141
+ try:
142
+ unlink(vmodname)
143
+ except:
144
+ pass
145
+
146
+ raise e
147
+
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env python
2
+ #
3
+ # CyberBoard GitHub page:
4
+ #
5
+ # https://github.com/CyberBoardPBEM/cbwindows
6
+ #
7
+ #
8
+
9
+
10
+ # ====================================================================
11
+ if __name__ == '__main__':
12
+ from argparse import ArgumentParser, FileType
13
+ from pathlib import Path
14
+ ## BEGIN_IMPORT
15
+ from scenario import Scenario
16
+ from extractor import GSNExtractor
17
+ from common import Verbose
18
+ ## END_IMPORT
19
+
20
+ ap = ArgumentParser(description='Extract information from a '
21
+ 'CyberBoard Scenario file and store in ZIP archive',
22
+ epilog='Default output file name is input file name '
23
+ 'with .gsn replaced by .zip')
24
+ ap.add_argument('input', type=str, help='The file')
25
+ ap.add_argument('output',type=str, nargs='?',help='Output',default='')
26
+ ap.add_argument('-V','--verbose',
27
+ help='Be verbose',
28
+ action='store_true')
29
+ ap.add_argument('-D','--dump',type=str,nargs='*',default='',
30
+ help='Dump content')
31
+ ap.add_argument('-X','--gamebox',
32
+ type=str,
33
+ default=None,
34
+ help='Override gamebox (.gbx) file')
35
+
36
+ args = ap.parse_args()
37
+ Verbose().setVerbose(args.verbose)
38
+
39
+ gsn = Scenario.fromFile(args.input,args.gamebox)
40
+ rat = GSNExtractor(gsn)
41
+
42
+ out = args.output
43
+ if out == '':
44
+ p = Path(args.input)
45
+ out = p.stem+'.zip'
46
+ rat.save(out)
47
+
48
+ if 'save' in args.dump:
49
+ print(rat)
50
+ if 'gsn' in args.dump:
51
+ print(gsn)
52
+
53
+ #
54
+ # EOF
55
+ #
56
+
57
+
58
+
59
+