# HG changeset patch # User Emmanuel Gil Peyrot # Date 1385403176 -3600 # Node ID 292fea5c584e279854d03f06130aac007a7f1f14 # Parent 1bc014f9d572123f90532c240fc39527aa5326c7 Some more type optimisations. diff --git a/pytouhou/game/effect.pyx b/pytouhou/game/effect.pyx --- a/pytouhou/game/effect.pyx +++ b/pytouhou/game/effect.pyx @@ -43,8 +43,8 @@ cdef class Particle(Effect): self.frame = 0 self.duration = duration - random_pos = (self.x + amp * game.prng.rand_double() - amp / 2, - self.y + amp * game.prng.rand_double() - amp / 2) + random_pos = (self.x + amp * game.prng.rand_double() - amp / 2, + self.y + amp * game.prng.rand_double() - amp / 2) if not reverse: self.pos_interpolator = Interpolator((self.x, self.y), 0, diff --git a/pytouhou/game/enemy.pxd b/pytouhou/game/enemy.pxd --- a/pytouhou/game/enemy.pxd +++ b/pytouhou/game/enemy.pxd @@ -28,24 +28,25 @@ cdef class Enemy(Element): cpdef play_sound(self, index) cpdef set_hitbox(self, double width, double height) cpdef set_bullet_attributes(self, type_, anim, sprite_idx_offset, - bullets_per_shot, number_of_shots, speed, speed2, - launch_angle, angle, flags) + unsigned long bullets_per_shot, + unsigned long number_of_shots, double speed, + double speed2, launch_angle, angle, flags) cpdef set_bullet_launch_interval(self, long value, unsigned long start=*) - cpdef fire(self, offset=*, bullet_attributes=*, launch_pos=*) - cpdef new_laser(self, variant, laser_type, sprite_idx_offset, angle, speed, - start_offset, end_offset, max_length, width, - start_duration, duration, end_duration, + cpdef fire(self, offset=*, bullet_attributes=*, tuple launch_pos=*) + cpdef new_laser(self, unsigned long variant, laser_type, sprite_idx_offset, + double angle, speed, start_offset, end_offset, max_length, + width, start_duration, duration, end_duration, grazing_delay, grazing_extra_duration, unknown, - offset=*) + tuple offset=*) cpdef Player select_player(self, list players=*) cpdef double get_player_angle(self, tuple pos=*, Player player=*) except 42 cpdef set_anim(self, index) cdef void die_anim(self) except * cdef void drop_particles(self, long number, long color) except * cpdef set_aux_anm(self, long number, long index) - cpdef set_pos(self, x, y, z) - cpdef move_to(self, duration, x, y, z, formula) - cpdef stop_in(self, duration, formula) + cpdef set_pos(self, double x, double y, double z) + cpdef move_to(self, unsigned long duration, double x, double y, double z, formula) + cpdef stop_in(self, unsigned long duration, formula) cdef bint is_visible(self, long screen_width, long screen_height) except? False cdef void check_collisions(self) except * cdef void handle_callbacks(self) except * diff --git a/pytouhou/game/enemy.pyx b/pytouhou/game/enemy.pyx --- a/pytouhou/game/enemy.pyx +++ b/pytouhou/game/enemy.pyx @@ -133,8 +133,11 @@ cdef class Enemy(Element): cpdef set_bullet_attributes(self, type_, anim, sprite_idx_offset, - bullets_per_shot, number_of_shots, speed, speed2, - launch_angle, angle, flags): + unsigned long bullets_per_shot, + unsigned long number_of_shots, double speed, + double speed2, launch_angle, angle, flags): + cdef double speed_a, speed_b + cdef long nb_a, nb_b, shots_a, shots_b # Apply difficulty-specific modifiers speed_a, speed_b, nb_a, nb_b, shots_a, shots_b = self.difficulty_coeffs @@ -142,8 +145,8 @@ cdef class Enemy(Element): speed += speed_a * (1. - diff_coeff) + speed_b * diff_coeff speed2 += (speed_a * (1. - diff_coeff) + speed_b * diff_coeff) / 2. - bullets_per_shot += int(nb_a * (1. - diff_coeff) + nb_b * diff_coeff) - number_of_shots += int(shots_a * (1. - diff_coeff) + shots_b * diff_coeff) + bullets_per_shot += (nb_a * (1. - diff_coeff) + nb_b * diff_coeff) + number_of_shots += (shots_a * (1. - diff_coeff) + shots_b * diff_coeff) self.bullet_attributes = (type_, anim, sprite_idx_offset, bullets_per_shot, number_of_shots, speed, speed2, launch_angle, @@ -155,13 +158,16 @@ cdef class Enemy(Element): cpdef set_bullet_launch_interval(self, long value, unsigned long start=0): # Apply difficulty-specific modifiers: #TODO: check every value possible! Look around 102h.exe@0x408720 - value -= value * (self._game.difficulty - 16) // 80 + value -= value * (self._game.difficulty - 16) // 80 self.bullet_launch_interval = value self.bullet_launch_timer = start % value if value > 0 else 0 - cpdef fire(self, offset=None, bullet_attributes=None, launch_pos=None): + cpdef fire(self, offset=None, bullet_attributes=None, tuple launch_pos=None): + cdef unsigned long type_, bullets_per_shot, number_of_shots + cdef double speed, speed2, launch_angle, angle + (type_, type_idx, sprite_idx_offset, bullets_per_shot, number_of_shots, speed, speed2, launch_angle, angle, flags) = bullet_attributes or self.bullet_attributes @@ -214,12 +220,16 @@ cdef class Enemy(Element): bullet_angle += angle - cpdef new_laser(self, variant, laser_type, sprite_idx_offset, angle, speed, - start_offset, end_offset, max_length, width, - start_duration, duration, end_duration, + cpdef new_laser(self, unsigned long variant, laser_type, sprite_idx_offset, + double angle, speed, start_offset, end_offset, max_length, + width, start_duration, duration, end_duration, grazing_delay, grazing_extra_duration, unknown, - offset=None): - ox, oy = offset or self.bullet_launch_offset + tuple offset=None): + cdef double ox, oy + + if offset is None: + offset = self.bullet_launch_offset + ox, oy = offset launch_pos = self.x + ox, self.y + oy if variant == 86: angle += self.get_player_angle(launch_pos) @@ -272,13 +282,14 @@ cdef class Enemy(Element): self.aux_anm[number] = Effect((self.x, self.y), index, self._anms[entry]) - cpdef set_pos(self, x, y, z): + cpdef set_pos(self, double x, double y, double z): self.x, self.y = x, y self.update_mode = 1 self.interpolator = Interpolator((x, y), self._game.frame) - cpdef move_to(self, duration, x, y, z, formula): + cpdef move_to(self, unsigned long duration, double x, double y, double z, + formula): frame = self._game.frame self.speed_interpolator = None self.update_mode = 1 @@ -289,7 +300,7 @@ cdef class Enemy(Element): self.angle = atan2(y - self.y, x - self.x) - cpdef stop_in(self, duration, formula): + cpdef stop_in(self, unsigned long duration, formula): frame = self._game.frame self.interpolator = None self.update_mode = 1 diff --git a/pytouhou/game/game.pxd b/pytouhou/game/game.pxd --- a/pytouhou/game/game.pxd +++ b/pytouhou/game/game.pxd @@ -1,22 +1,25 @@ from pytouhou.game.effect cimport Effect from pytouhou.game.player cimport Player from pytouhou.game.text cimport Text, NativeText +from pytouhou.utils.random cimport Random cdef class Game: - cdef public long width, height, nb_bullets_max, stage, rank, difficulty, difficulty_counter, difficulty_min, difficulty_max, frame, last_keystate + cdef public long width, height, nb_bullets_max, stage, rank, difficulty, difficulty_min, difficulty_max, frame cdef public list bullet_types, laser_types, item_types, players, enemies, effects, bullets, lasers, cancelled_bullets, players_bullets, players_lasers, items, labels, faces, texts, hints, bonus_list - cdef public object interface, boss, msg_runner, prng, sfx_player + cdef public object interface, boss, msg_runner, sfx_player + cdef public Random prng cdef public double continues cdef public Effect spellcard_effect cdef public tuple spellcard cdef public bint time_stop, msg_wait cdef public unsigned short deaths_count, next_bonus + cdef long difficulty_counter, last_keystate cdef bint friendly_fire cdef list msg_sprites(self) cdef list lasers_sprites(self) - cdef void modify_difficulty(self, long diff) except * + cdef void modify_difficulty(self, long diff) nogil cpdef enable_spellcard_effect(self) cpdef disable_spellcard_effect(self) cdef void set_player_bomb(self) except * diff --git a/pytouhou/game/game.pyx b/pytouhou/game/game.pyx --- a/pytouhou/game/game.pyx +++ b/pytouhou/game/game.pyx @@ -26,8 +26,8 @@ from pytouhou.game.face import Face cdef class Game: def __init__(self, players, long stage, long rank, long difficulty, bullet_types, laser_types, item_types, long nb_bullets_max=0, long width=384, - long height=448, prng=None, interface=None, hints=None, - friendly_fire=True): + long height=448, Random prng=None, interface=None, hints=None, + bint friendly_fire=True): self.width, self.height = width, height self.nb_bullets_max = nb_bullets_max @@ -85,7 +85,7 @@ cdef class Game: return [laser for laser in self.players_lasers if laser is not None] - cdef void modify_difficulty(self, long diff): + cdef void modify_difficulty(self, long diff) nogil: self.difficulty_counter += diff while self.difficulty_counter < 0: self.difficulty -= 1 @@ -269,6 +269,7 @@ cdef class Game: cpdef run_iter(self, list keystates): cdef Laser laser + cdef long i # 1. VMs. for runner in self.ecl_runners: diff --git a/pytouhou/game/player.pyx b/pytouhou/game/player.pyx --- a/pytouhou/game/player.pyx +++ b/pytouhou/game/player.pyx @@ -29,7 +29,7 @@ class GameOver(Exception): cdef class Player(Element): def __init__(self, long number, anm, long character=0, long power=0, long continues=0, long lives=2, long bombs=3, long score=0): - Element.__init__(self) + Element.__init__(self, (192, 384)) self.number = number self.character = character # ReimuA/ReimuB/MarisaA/MarisaB/... @@ -48,9 +48,6 @@ cdef class Player(Element): self.graze = 0 self.points = 0 - self.x = 192.0 - self.y = 384.0 - self.invulnerable_time = 240 self.touchable = True self.focused = False diff --git a/pytouhou/utils/random.pxd b/pytouhou/utils/random.pxd new file mode 100644 --- /dev/null +++ b/pytouhou/utils/random.pxd @@ -0,0 +1,10 @@ +cdef class Random: + cdef unsigned short seed + cdef unsigned long counter + + cdef void set_seed(self, unsigned short seed) nogil + cdef unsigned short rewind(self) nogil + + cpdef unsigned short rand_uint16(self) + cpdef unsigned int rand_uint32(self) + cpdef double rand_double(self) diff --git a/pytouhou/utils/random.py b/pytouhou/utils/random.pyx rename from pytouhou/utils/random.py rename to pytouhou/utils/random.pyx --- a/pytouhou/utils/random.py +++ b/pytouhou/utils/random.pyx @@ -28,20 +28,19 @@ It has been reverse engineered from 102h from time import time -class Random(object): - def __init__(self, seed=None): - if seed is None: - seed = int(time() % 65536) +cdef class Random: + def __init__(self, long seed=-1): + if seed < 0: + seed = time() + self.set_seed((seed & 65535)) + + + cdef void set_seed(self, unsigned short seed) nogil: self.seed = seed self.counter = 0 - def set_seed(self, seed): - self.seed = seed - self.counter = 0 - - - def rewind(self): + cdef unsigned short rewind(self) nogil: """Rewind the PRNG by 1 step. This is the reverse of rand_uint16. Might be useful for debugging purposes. """ @@ -52,7 +51,7 @@ class Random(object): return self.seed - def rand_uint16(self): + cpdef unsigned short rand_uint16(self): # 102h.exe@0x41e780 x = ((self.seed ^ 0x9630) - 0x6553) & 0xffff self.seed = (((x & 0xc000) >> 14) | (x << 2)) & 0xffff @@ -60,14 +59,13 @@ class Random(object): return self.seed - def rand_uint32(self): + cpdef unsigned int rand_uint32(self): # 102h.exe@0x41e7f0 a = self.rand_uint16() << 16 a |= self.rand_uint16() return a - def rand_double(self): + cpdef double rand_double(self): # 102h.exe@0x41e820 - return float(self.rand_uint32()) / 0x100000000 - + return self.rand_uint32() / 0x100000000