Mercurial > touhou
changeset 509:292fea5c584e
Some more type optimisations.
| author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
|---|---|
| date | Mon, 25 Nov 2013 19:12:56 +0100 |
| parents | 1bc014f9d572 |
| children | 64a72df88de5 |
| files | pytouhou/game/effect.pyx pytouhou/game/enemy.pxd pytouhou/game/enemy.pyx pytouhou/game/game.pxd pytouhou/game/game.pyx pytouhou/game/player.pyx pytouhou/utils/random.pxd pytouhou/utils/random.py pytouhou/utils/random.pyx |
| diffstat | 9 files changed, 130 insertions(+), 109 deletions(-) [+] |
line wrap: on
line diff
--- a/pytouhou/game/effect.pyx Tue Nov 19 14:19:14 2013 +0100 +++ b/pytouhou/game/effect.pyx Mon Nov 25 19:12:56 2013 +0100 @@ -43,8 +43,8 @@ self.frame = 0 self.duration = duration - random_pos = (self.x + amp * <double>game.prng.rand_double() - amp / 2, - self.y + amp * <double>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,
--- a/pytouhou/game/enemy.pxd Tue Nov 19 14:19:14 2013 +0100 +++ b/pytouhou/game/enemy.pxd Mon Nov 25 19:12:56 2013 +0100 @@ -28,24 +28,25 @@ 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 *
--- a/pytouhou/game/enemy.pyx Tue Nov 19 14:19:14 2013 +0100 +++ b/pytouhou/game/enemy.pyx Mon Nov 25 19:12:56 2013 +0100 @@ -133,8 +133,11 @@ 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 @@ 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 += <long>(nb_a * (1. - diff_coeff) + nb_b * diff_coeff) + number_of_shots += <long>(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 @@ 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 * (<long>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 @@ 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 @@ 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 @@ 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
--- a/pytouhou/game/game.pxd Tue Nov 19 14:19:14 2013 +0100 +++ b/pytouhou/game/game.pxd Mon Nov 25 19:12:56 2013 +0100 @@ -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 *
--- a/pytouhou/game/game.pyx Tue Nov 19 14:19:14 2013 +0100 +++ b/pytouhou/game/game.pyx Mon Nov 25 19:12:56 2013 +0100 @@ -26,8 +26,8 @@ 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 @@ 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 @@ cpdef run_iter(self, list keystates): cdef Laser laser + cdef long i # 1. VMs. for runner in self.ecl_runners:
--- a/pytouhou/game/player.pyx Tue Nov 19 14:19:14 2013 +0100 +++ b/pytouhou/game/player.pyx Mon Nov 25 19:12:56 2013 +0100 @@ -29,7 +29,7 @@ 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 @@ self.graze = 0 self.points = 0 - self.x = 192.0 - self.y = 384.0 - self.invulnerable_time = 240 self.touchable = True self.focused = False
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pytouhou/utils/random.pxd Mon Nov 25 19:12:56 2013 +0100 @@ -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)
--- a/pytouhou/utils/random.py Tue Nov 19 14:19:14 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -# -*- encoding: utf-8 -*- -## -## Copyright (C) 2011 Thibaut Girka <thib@sitedethib.com> -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 3 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - - -""" -This file provides a pseudo-random number generator identical to the one used in -Touhou 6: The Embodiment of Scarlet Devil. -It is the only truly reverse-engineered piece of code of this project, -as it is needed in order to retain compatibility with replay files produced by -the offical game code. - -It has been reverse engineered from 102h.exe.""" - - -#TODO: maybe some post-processing is missing - - -from time import time - -class Random(object): - def __init__(self, seed=None): - if seed is None: - seed = int(time() % 65536) - self.seed = seed - self.counter = 0 - - - def set_seed(self, seed): - self.seed = seed - self.counter = 0 - - - def rewind(self): - """Rewind the PRNG by 1 step. This is the reverse of rand_uint16. - Might be useful for debugging purposes. - """ - x = self.seed - x = (x >> 2) | ((x & 3) << 14) - self.seed = ((x + 0x6553) & 0xffff) ^ 0x9630 - self.counter -= 1 - return self.seed - - - def rand_uint16(self): - # 102h.exe@0x41e780 - x = ((self.seed ^ 0x9630) - 0x6553) & 0xffff - self.seed = (((x & 0xc000) >> 14) | (x << 2)) & 0xffff - self.counter += 1 - return self.seed - - - def rand_uint32(self): - # 102h.exe@0x41e7f0 - a = self.rand_uint16() << 16 - a |= self.rand_uint16() - return a - - - def rand_double(self): - # 102h.exe@0x41e820 - return float(self.rand_uint32()) / 0x100000000 -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pytouhou/utils/random.pyx Mon Nov 25 19:12:56 2013 +0100 @@ -0,0 +1,71 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2011 Thibaut Girka <thib@sitedethib.com> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + + +""" +This file provides a pseudo-random number generator identical to the one used in +Touhou 6: The Embodiment of Scarlet Devil. +It is the only truly reverse-engineered piece of code of this project, +as it is needed in order to retain compatibility with replay files produced by +the offical game code. + +It has been reverse engineered from 102h.exe.""" + + +#TODO: maybe some post-processing is missing + + +from time import time + +cdef class Random: + def __init__(self, long seed=-1): + if seed < 0: + seed = time() + self.set_seed(<unsigned short>(seed & 65535)) + + + cdef void set_seed(self, unsigned short seed) nogil: + self.seed = seed + self.counter = 0 + + + 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. + """ + x = self.seed + x = (x >> 2) | ((x & 3) << 14) + self.seed = ((x + 0x6553) & 0xffff) ^ 0x9630 + self.counter -= 1 + return self.seed + + + cpdef unsigned short rand_uint16(self): + # 102h.exe@0x41e780 + x = ((self.seed ^ 0x9630) - 0x6553) & 0xffff + self.seed = (((x & 0xc000) >> 14) | (x << 2)) & 0xffff + self.counter += 1 + return self.seed + + + cpdef unsigned int rand_uint32(self): + # 102h.exe@0x41e7f0 + a = self.rand_uint16() << 16 + a |= self.rand_uint16() + return a + + + cpdef double rand_double(self): + # 102h.exe@0x41e820 + return self.rand_uint32() / <double>0x100000000
