-
Notifications
You must be signed in to change notification settings - Fork 4
/
pybw.py
319 lines (254 loc) · 8.96 KB
/
pybw.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
import inspect
print "Importing swig module (python file)"
import pybw_swig
keep_as_methods = set([
'next',
'resumeGame',
'startGame',
'leaveGame',
'restartGame',
'pauseGame',
'fromWalkable',
'toWalkable',
'makeValid',
'onFrame',
'onStart',
'returnCargo',
'siege',
'cancelAddon',
'cancelConstruction',
'cancelUpgrade',
'lift',
'holdPosition',
'haltConstruction',
'burrow',
'stop',
'unburrow',
'cancelMorph',
'cancelResearch',
'decloak',
'unsiege',
'reset',
'init',
'draw',
])
print "Converting all 'getSomething' into 'something'..."
def deget_class(c):
for name in c.__dict__.keys():
obj = getattr(c, name)
if not inspect.ismethod(obj):
continue
argspec = inspect.getargspec(obj)
if len(argspec.args) != 1: # not really get?
continue
if argspec.varargs != None or argspec.keywords != None: # not really get?
continue
if name.startswith('_'): # kinda hackish..
continue
if name == 'getID':
prop_name = 'id'
elif name.startswith('get'):
prop_name = name[3].lower() + name[4:]
elif name in keep_as_methods:
continue
else:
#print '&', name
prop_name = name
if prop_name!=name and hasattr(c, prop_name):
print "Cannot deget property %s->%s of class %s: Already exists" % (name, prop_name, c)
continue # don't overwrite existing... In the future combine somehow?
setattr(c, prop_name, property(obj) )
def get_all_classes(m):
for name in m.__dict__.keys():
obj = getattr(m, name)
if inspect.isclass(obj) and not name.startswith('_'):
yield obj
print "Adding __repr__ and __str__ method to classes"
def Position_repr(self):
return "Position(%s, %s)" % (self.x, self.y)
pybw_swig.Position.__repr__ = Position_repr
def TilePosition_repr(self):
return "TilePosition(%s, %s)" % (self.x, self.y)
pybw_swig.TilePosition.__repr__ = TilePosition_repr
def Force_repr(self):
return "<Force: %s, players=%s>" % (self.name, list(self.players))
pybw_swig.Force.__repr__ = Force_repr
def Player_repr(self):
return "<Player: %s, race=%s>" % (self.name, self.race.name)
def Player_str(self):
return "P:%s(%s)" % (self.name, self.race.name)
pybw_swig.Player.__repr__ = Player_repr
pybw_swig.Player.__str__ = Player_str
def repr_by_class_and_name(self):
return "<%s: %s>" % (self.__class__.__name__, self.name)
pybw_swig.UnitType.__repr__ = repr_by_class_and_name
pybw_swig.PlayerType.__repr__ = repr_by_class_and_name
pybw_swig.TechType.__repr__ = repr_by_class_and_name
pybw_swig.UpgradeType.__repr__ = repr_by_class_and_name
pybw_swig.WeaponType.__repr__ = repr_by_class_and_name
pybw_swig.DamageType.__repr__ = repr_by_class_and_name
pybw_swig.ExplosionType.__repr__ = repr_by_class_and_name
pybw_swig.Race.__repr__ = repr_by_class_and_name
pybw_swig.Order.__repr__ = repr_by_class_and_name
pybw_swig.UnitSizeType.__repr__ = repr_by_class_and_name
def Unit_repr(self):
return "<Unit: %s, player=%s>" % (self.type.name, self.player.name)
pybw_swig.Unit.__repr__ = Unit_repr
def Error_repr(self):
return "<Error: %s>" % self.toString()
pybw_swig.Error.__repr__ = Error_repr
# ToDo ?
# * BaseLocation
# * Chokepoint
# * Region
# * Polygon
print "Fixing __eq__ and __hash__ methods in classes"
def eq_by_id(self, other):
if self is None or other is None:
return self is other
return self.id == other.id
def ne_by_id(self, other):
if self is None or other is None:
return self is not other
return self.id != other.id
def hash_by_id(self):
assert self is not None
return hash(self.id)
pybw_swig.Player.__hash__ = hash_by_id
pybw_swig.Player.__eq__ = eq_by_id
pybw_swig.Player.__ne__ = ne_by_id
pybw_swig.PlayerType.__hash__ = hash_by_id
pybw_swig.PlayerType.__eq__ = eq_by_id
pybw_swig.PlayerType.__ne__ = ne_by_id
pybw_swig.Unit.__hash__ = hash_by_id
pybw_swig.Unit.__eq__ = eq_by_id
pybw_swig.Unit.__ne__ = ne_by_id
pybw_swig.UnitType.__hash__ = hash_by_id
pybw_swig.UnitType.__eq__ = eq_by_id
pybw_swig.UnitType.__ne__ = ne_by_id
pybw_swig.TechType.__hash__ = hash_by_id
pybw_swig.TechType.__eq__ = eq_by_id
pybw_swig.TechType.__ne__ = ne_by_id
pybw_swig.UpgradeType.__hash__ = hash_by_id
pybw_swig.UpgradeType.__eq__ = eq_by_id
pybw_swig.UpgradeType.__ne__ = ne_by_id
pybw_swig.WeaponType.__hash__ = hash_by_id
pybw_swig.WeaponType.__eq__ = eq_by_id
pybw_swig.WeaponType.__ne__ = ne_by_id
pybw_swig.DamageType.__hash__ = hash_by_id
pybw_swig.DamageType.__eq__ = eq_by_id
pybw_swig.DamageType.__ne__ = ne_by_id
pybw_swig.ExplosionType.__hash__ = hash_by_id
pybw_swig.ExplosionType.__eq__ = eq_by_id
pybw_swig.ExplosionType.__ne__ = ne_by_id
pybw_swig.Race.__hash__ = hash_by_id
pybw_swig.Race.__eq__ = eq_by_id
pybw_swig.Race.__ne__ = ne_by_id
pybw_swig.Order.__hash__ = hash_by_id
pybw_swig.Order.__eq__ = eq_by_id
pybw_swig.Order.__ne__ = ne_by_id
pybw_swig.UnitSizeType.__hash__ = hash_by_id
pybw_swig.UnitSizeType.__eq__ = eq_by_id
pybw_swig.UnitSizeType.__ne__ = ne_by_id
pybw_swig.Error.__hash__ = hash_by_id
pybw_swig.Error.__eq__ = eq_by_id
pybw_swig.Error.__ne__ = ne_by_id
def Force_eq(self, other):
raise NotImplementedError("Cannot compare forces. Compare force.name instead")
def Force_hash(self):
raise NotImplementedError("Cannot calculate hash for force")
pybw_swig.Force.__hash__ = Force_hash
pybw_swig.Force.__eq__ = Force_eq
pybw_swig.Force.__ne__ = Force_eq
def Position_hash(self):
return hash((self.x, self.y))
pybw_swig.Position.__hash__ = Position_hash
def TilePosition_hash(self):
return hash((self.x, self.y))
pybw_swig.TilePosition.__hash__ = TilePosition_hash
def BaseLocation_eq(self, other):
return self.tilePosition == other.tilePosition
def BaseLocation_ne(self, other):
return self.tilePosition != other.tilePosition
def BaseLocation_hash(self):
return hash(self.tilePosition)
pybw_swig.BaseLocation.__eq__ = BaseLocation_eq
pybw_swig.BaseLocation.__ne__ = BaseLocation_ne
pybw_swig.BaseLocation.__hash__ = BaseLocation_hash
# ToDo ?
# * BaseLocation
# * Chokepoint
# * Region
# * Polygon
print "Adding some utility methods"
def Pos_iter(self):
yield self.x
yield self.y
pybw_swig.Position.__iter__ = Pos_iter
pybw_swig.TilePosition.__iter__ = Pos_iter
def TilePosition_toWalkable(self):
return self.__class__( self.x*4, self.y*4 )
def TilePosition_fromWalkable(self):
return self.__class__( self.x/4, self.y/4 )
def Position_toWalkable(self):
return self.__class__( self.x/8, self.y/8 )
def Position_fromWalkable(self):
return self.__class__( self.x*8, self.y*8 )
pybw_swig.TilePosition.toWalkable = TilePosition_toWalkable
pybw_swig.TilePosition.fromWalkable = TilePosition_fromWalkable
pybw_swig.Position.toWalkable = Position_toWalkable
pybw_swig.Position.fromWalkable = Position_fromWalkable
for c in set(get_all_classes(pybw_swig)):
deget_class(c)
print "Creating event handler"
import pybw_event_handler
event_handler = pybw_event_handler.PyBW_EventHandler(0)
event_handler.listeners.append( pybw_event_handler.VerboseEventHandler() )
def reload_event_handler():
global event_handler
try:
event_handler = None
import pybw_event_handler
reload(pybw_event_handler)
pybw_event_handler._reload()
event_handler = pybw_event_handler.PyBW_EventHandler(0)
except Exception, e:
print "error", e
print "Creating console"
import threading
import code
import pybw_repl
class ConsoleManagerXMLRPC(object):
def onConnect(self):
game = pybw_swig.getGame()
self.consoleClient = pybw_repl.ConsoleClient()
self.consoleClient.start_repl(dict(game=game, swig=pybw_swig))
def onMatchFrame(self):
self.consoleClient.on_frame()
class ConsoleManagerThreaded(object):
locals={}
def onConnect(self):
t = threading.Thread( target=self.thread, args=(self.locals,) )
t.start()
def thread(self, *args):
print "Started interp thread"
locals = args[0]
game = pybw_swig.getGame()
locals.update(dict(game=game, swig=pybw_swig))
i = code.InteractiveConsole(locals=locals)
i.interact()
#~ consoleManager = ConsoleManagerXMLRPC()
consoleManager = ConsoleManagerThreaded()
event_handler.listeners.append( consoleManager )
try:
import exampleai
event_handler.listeners.append( exampleai.ExampleAI() )
#import erezai.main
#event_handler.listeners.append( erezai.main.ErezAI() )
#import cannonai
#event_handler.listeners.append( cannonai.CannonAI() )
except ImportError, e:
print "Error importing AI:", e
except Exception, e:
print "Error running AI:", e
print "PyBW module Initialization complete"