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 8 files changed, 72 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- 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 * <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
+++ 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 *
--- 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 += <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 @@ 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 * (<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 @@ 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
--- 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 *
--- 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:
--- 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
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)
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(<unsigned short>(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() / <double>0x100000000