comparison pytouhou/vm/eclrunner.py @ 151:5cf927cbd9c5

Merge GameState into Game. TODO: Merge PlayerState into Player
author Thibaut Girka <thib@sitedethib.com>
date Tue, 04 Oct 2011 23:32:02 +0200
parents 4f46717390aa
children 86807b8a63bd
comparison
equal deleted inserted replaced
150:4f46717390aa 151:5cf927cbd9c5
23 23
24 24
25 25
26 class ECLMainRunner(object): 26 class ECLMainRunner(object):
27 __metaclass__ = MetaRegistry 27 __metaclass__ = MetaRegistry
28 __slots__ = ('_ecl', '_new_enemy_func', '_game_state', 'processes', 28 __slots__ = ('_ecl', '_new_enemy_func', '_game', 'processes',
29 'instruction_pointer') 29 'instruction_pointer')
30 30
31 def __init__(self, ecl, new_enemy_func, game_state): 31 def __init__(self, ecl, new_enemy_func, game):
32 self._ecl = ecl 32 self._ecl = ecl
33 self._new_enemy_func = new_enemy_func 33 self._new_enemy_func = new_enemy_func
34 self._game_state = game_state 34 self._game = game
35 35
36 self.processes = [] 36 self.processes = []
37 37
38 self.instruction_pointer = 0 38 self.instruction_pointer = 0
39 39
43 try: 43 try:
44 frame, sub, instr_type, args = self._ecl.main[self.instruction_pointer] 44 frame, sub, instr_type, args = self._ecl.main[self.instruction_pointer]
45 except IndexError: 45 except IndexError:
46 break 46 break
47 47
48 if frame > self._game_state.frame: 48 if frame > self._game.frame:
49 break 49 break
50 else: 50 else:
51 self.instruction_pointer += 1 51 self.instruction_pointer += 1
52 52
53 if frame == self._game_state.frame: 53 if frame == self._game.frame:
54 try: 54 try:
55 callback = self._handlers[instr_type] 55 callback = self._handlers[instr_type]
56 except KeyError: 56 except KeyError:
57 logger.warn('unhandled main opcode %d (args: %r)', instr_type, args) 57 logger.warn('unhandled main opcode %d (args: %r)', instr_type, args)
58 else: 58 else:
63 63
64 64
65 def _pop_enemy(self, sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3): 65 def _pop_enemy(self, sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3):
66 if instr_type & 4: 66 if instr_type & 4:
67 if x < -990: #102h.exe@0x411820 67 if x < -990: #102h.exe@0x411820
68 x = self._game_state.prng.rand_double() * 368 68 x = self._game.prng.rand_double() * 368
69 if y < -990: #102h.exe@0x41184b 69 if y < -990: #102h.exe@0x41184b
70 y = self._game_state.prng.rand_double() * 416 70 y = self._game.prng.rand_double() * 416
71 if z < -990: #102h.exe@0x411881 71 if z < -990: #102h.exe@0x411881
72 y = self._game_state.prng.rand_double() * 800 72 y = self._game.prng.rand_double() * 800
73 enemy = self._new_enemy_func((x, y), life, instr_type, self._pop_enemy) 73 enemy = self._new_enemy_func((x, y), life, instr_type, self._pop_enemy)
74 process = ECLRunner(self._ecl, sub, enemy, self._game_state) 74 process = ECLRunner(self._ecl, sub, enemy, self._game)
75 self.processes.append(process) 75 self.processes.append(process)
76 process.run_iteration() 76 process.run_iteration()
77 77
78 78
79 @instruction(0) 79 @instruction(0)
80 @instruction(2) 80 @instruction(2)
81 @instruction(4) 81 @instruction(4)
82 @instruction(6) 82 @instruction(6)
83 def pop_enemy(self, sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3): 83 def pop_enemy(self, sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3):
84 if self._game_state.boss: 84 if self._game.boss:
85 return 85 return
86 self._pop_enemy(sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3) 86 self._pop_enemy(sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3)
87 87
88 88
89 89
90 90
91 class ECLRunner(object): 91 class ECLRunner(object):
92 __metaclass__ = MetaRegistry 92 __metaclass__ = MetaRegistry
93 __slots__ = ('_ecl', '_enemy', '_game_state', 'variables', 'sub', 'frame', 93 __slots__ = ('_ecl', '_enemy', '_game', 'variables', 'sub', 'frame',
94 'instruction_pointer', 'comparison_reg', 'stack') 94 'instruction_pointer', 'comparison_reg', 'stack')
95 95
96 def __init__(self, ecl, sub, enemy, game_state): 96 def __init__(self, ecl, sub, enemy, game):
97 # Things not supposed to change 97 # Things not supposed to change
98 self._ecl = ecl 98 self._ecl = ecl
99 self._enemy = enemy 99 self._enemy = enemy
100 self._game_state = game_state 100 self._game = game
101 101
102 # Things supposed to change (and be put in the stack) 102 # Things supposed to change (and be put in the stack)
103 self.variables = [0, 0, 0, 0, 103 self.variables = [0, 0, 0, 0,
104 0., 0., 0., 0., 104 0., 0., 0., 0.,
105 0, 0, 0, 0] 105 0, 0, 0, 0]
157 else: 157 else:
158 self.instruction_pointer += 1 158 self.instruction_pointer += 1
159 159
160 160
161 #TODO: skip bad ranks 161 #TODO: skip bad ranks
162 if not rank_mask & (0x100 << self._game_state.rank): 162 if not rank_mask & (0x100 << self._game.rank):
163 continue 163 continue
164 164
165 165
166 if frame == self.frame: 166 if frame == self.frame:
167 try: 167 try:
179 def _getval(self, value): 179 def _getval(self, value):
180 if -10012 <= value <= -10001: 180 if -10012 <= value <= -10001:
181 return self.variables[int(-10001-value)] 181 return self.variables[int(-10001-value)]
182 elif -10025 <= value <= -10013: 182 elif -10025 <= value <= -10013:
183 if value == -10013: 183 if value == -10013:
184 return self._game_state.rank 184 return self._game.rank
185 elif value == -10014: 185 elif value == -10014:
186 return self._game_state.difficulty 186 return self._game.difficulty
187 elif value == -10015: 187 elif value == -10015:
188 return self._enemy.x 188 return self._enemy.x
189 elif value == -10016: 189 elif value == -10016:
190 return self._enemy.y 190 return self._enemy.y
191 elif value == -10017: 191 elif value == -10017:
201 elif value == -10022: 201 elif value == -10022:
202 return self._enemy.frame 202 return self._enemy.frame
203 elif value == -10024: 203 elif value == -10024:
204 return self._enemy.life 204 return self._enemy.life
205 elif value == -10025: 205 elif value == -10025:
206 return self._enemy.select_player().character 206 return self._enemy.select_player().state.character #TODO
207 raise NotImplementedError(value) #TODO 207 raise NotImplementedError(value) #TODO
208 else: 208 else:
209 return value 209 return value
210 210
211 211
272 272
273 @instruction(6) 273 @instruction(6)
274 def set_random_int(self, variable_id, maxval): 274 def set_random_int(self, variable_id, maxval):
275 """Set the specified variable to a random int in the [0, maxval) range. 275 """Set the specified variable to a random int in the [0, maxval) range.
276 """ 276 """
277 self._setval(variable_id, int(self._getval(maxval) * self._game_state.prng.rand_double())) 277 self._setval(variable_id, int(self._getval(maxval) * self._game.prng.rand_double()))
278 278
279 279
280 @instruction(8) 280 @instruction(8)
281 def set_random_float(self, variable_id, maxval): 281 def set_random_float(self, variable_id, maxval):
282 """Set the specified variable to a random float in [0, maxval) range. 282 """Set the specified variable to a random float in [0, maxval) range.
283 """ 283 """
284 self._setval(variable_id, self._getval(maxval) * self._game_state.prng.rand_double()) 284 self._setval(variable_id, self._getval(maxval) * self._game.prng.rand_double())
285 285
286 286
287 @instruction(9) 287 @instruction(9)
288 def set_random_float2(self, variable_id, amp, minval): 288 def set_random_float2(self, variable_id, amp, minval):
289 self._setval(variable_id, self._getval(minval) + self._getval(amp) * self._game_state.prng.rand_double()) 289 self._setval(variable_id, self._getval(minval) + self._getval(amp) * self._game.prng.rand_double())
290 290
291 291
292 @instruction(10) 292 @instruction(10)
293 def store_x(self, variable_id): 293 def store_x(self, variable_id):
294 self._setval(variable_id, self._enemy.x) 294 self._setval(variable_id, self._enemy.x)
441 self._enemy.acceleration = acceleration 441 self._enemy.acceleration = acceleration
442 442
443 443
444 @instruction(49) 444 @instruction(49)
445 def set_random_angle(self, min_angle, max_angle): 445 def set_random_angle(self, min_angle, max_angle):
446 angle = self._game_state.prng.rand_double() * (max_angle - min_angle) + min_angle 446 angle = self._game.prng.rand_double() * (max_angle - min_angle) + min_angle
447 self._enemy.angle = angle 447 self._enemy.angle = angle
448 448
449 449
450 @instruction(50) 450 @instruction(50)
451 def set_random_angle_ex(self, min_angle, max_angle): 451 def set_random_angle_ex(self, min_angle, max_angle):
452 if self._enemy.screen_box: 452 if self._enemy.screen_box:
453 minx, miny, maxx, maxy = self._enemy.screen_box 453 minx, miny, maxx, maxy = self._enemy.screen_box
454 else: 454 else:
455 minx, miny, maxx, maxy = (0., 0., 0., 0.) 455 minx, miny, maxx, maxy = (0., 0., 0., 0.)
456 456
457 angle = self._game_state.prng.rand_double() * (max_angle - min_angle) + min_angle 457 angle = self._game.prng.rand_double() * (max_angle - min_angle) + min_angle
458 sa, ca = sin(angle), cos(angle) 458 sa, ca = sin(angle), cos(angle)
459 459
460 distx = min(96.0, (maxx - minx) / 2.) 460 distx = min(96.0, (maxx - minx) / 2.)
461 disty = min(96.0, (maxy - miny) / 2.) 461 disty = min(96.0, (maxy - miny) / 2.)
462 462
633 633
634 634
635 @instruction(77) 635 @instruction(77)
636 def set_bullet_interval_ex(self, value): 636 def set_bullet_interval_ex(self, value):
637 self._enemy.bullet_launch_interval = value 637 self._enemy.bullet_launch_interval = value
638 self._enemy.bullet_launch_timer = int(self._game_state.prng.rand_double() * value) #TODO: check 638 self._enemy.bullet_launch_timer = int(self._game.prng.rand_double() * value) #TODO: check
639 639
640 640
641 @instruction(78) 641 @instruction(78)
642 def set_delay_attack(self): 642 def set_delay_attack(self):
643 self._enemy.delay_attack = True 643 self._enemy.delay_attack = True
658 self._enemy.extended_bullet_attributes = tuple(self._getval(attr) for attr in attributes) 658 self._enemy.extended_bullet_attributes = tuple(self._getval(attr) for attr in attributes)
659 659
660 660
661 @instruction(83) 661 @instruction(83)
662 def change_bullets_into_star_items(self): 662 def change_bullets_into_star_items(self):
663 self._game_state.change_bullets_into_star_items() 663 self._game.change_bullets_into_star_items()
664 664
665 665
666 @instruction(93) 666 @instruction(93)
667 def set_spellcard(self, unknown, number, name): 667 def set_spellcard(self, unknown, number, name):
668 #TODO: display it on the game. 668 #TODO: display it on the game.
691 691
692 692
693 @instruction(101) 693 @instruction(101)
694 def set_boss_mode(self, unknown): 694 def set_boss_mode(self, unknown):
695 #TODO: unknown 695 #TODO: unknown
696 self._game_state.boss = self._enemy 696 self._game.boss = self._enemy
697 697
698 698
699 @instruction(103) 699 @instruction(103)
700 def set_hitbox(self, width, height, depth): 700 def set_hitbox(self, width, height, depth):
701 self._enemy.hitbox = (width, height) 701 self._enemy.hitbox = (width, height)
785 785
786 @instruction(121) 786 @instruction(121)
787 def call_special_function(self, function, arg): 787 def call_special_function(self, function, arg):
788 if function == 0: # Cirno 788 if function == 0: # Cirno
789 if arg == 0: 789 if arg == 0:
790 for bullet in self._game_state.bullets: 790 for bullet in self._game.bullets:
791 bullet.speed = bullet.angle = 0. 791 bullet.speed = bullet.angle = 0.
792 bullet.delta = (0., 0.) 792 bullet.delta = (0., 0.)
793 bullet.set_anim(sprite_idx_offset=15) #TODO: check 793 bullet.set_anim(sprite_idx_offset=15) #TODO: check
794 else: 794 else:
795 for bullet in self._game_state.bullets: 795 for bullet in self._game.bullets:
796 bullet.speed = 2.0 #TODO 796 bullet.speed = 2.0 #TODO
797 bullet.angle = self._game_state.prng.rand_double() * pi #TODO 797 bullet.angle = self._game.prng.rand_double() * pi #TODO
798 bullet.delta = (cos(bullet.angle) * bullet.speed, sin(bullet.angle) * bullet.speed) 798 bullet.delta = (cos(bullet.angle) * bullet.speed, sin(bullet.angle) * bullet.speed)
799 else: 799 else:
800 logger.warn("Unimplemented special function %d!", function) 800 logger.warn("Unimplemented special function %d!", function)
801 801
802 802