<s> from __future__ import division <EOL> from __future__ import absolute_import <EOL> from __future__ import print_function <EOL> from abc import ABCMeta , abstractmethod <EOL> from builtins import object <EOL> from builtins import range <EOL> from copy import copy <EOL> from math import pi , sin , cos , sqrt <EOL> from random import uniform , randint <EOL> from future . utils import with_metaclass <EOL> from asciimatics . effects import Effect <EOL> from asciimatics . screen import Screen <EOL> class Particle ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , chars , x , y , dx , dy , colours , life_time , move , <EOL> next_colour = None , next_char = None , parm = None , <EOL> on_create = None , on_each = None , on_destroy = None ) : <EOL> """<STR_LIT>""" <EOL> self . chars = chars <EOL> self . x = x <EOL> self . y = y <EOL> self . dx = dx <EOL> self . dy = dy <EOL> self . colours = colours <EOL> self . time = <NUM_LIT:0> <EOL> self . life_time = life_time <EOL> self . _move = move <EOL> self . _next_colour = ( <EOL> self . _default_next_colour if next_colour is None else next_colour ) <EOL> self . _next_char = ( <EOL> self . _default_next_char if next_char is None else next_char ) <EOL> self . _last = None <EOL> self . _parm = parm <EOL> self . _on_create = on_create <EOL> self . _on_each = on_each <EOL> self . _on_destroy = on_destroy <EOL> @ staticmethod <EOL> def _default_next_char ( particle ) : <EOL> """<STR_LIT>""" <EOL> return particle . chars [ <EOL> ( len ( particle . chars ) - <NUM_LIT:1> ) * particle . time // particle . life_time ] <EOL> @ staticmethod <EOL> def _default_next_colour ( particle ) : <EOL> """<STR_LIT>""" <EOL> return particle . colours [ <EOL> ( len ( particle . colours ) - <NUM_LIT:1> ) * particle . time // particle . life_time ] <EOL> def last ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _last <EOL> def next ( self ) : <EOL> """<STR_LIT>""" <EOL> x , y = self . _move ( self ) <EOL> colour = self . _next_colour ( self ) <EOL> char = self . _next_char ( self ) <EOL> self . _last = char , x , y , colour [ <NUM_LIT:0> ] , colour [ <NUM_LIT:1> ] , colour [ <NUM_LIT:2> ] <EOL> self . time += <NUM_LIT:1> <EOL> if self . time == <NUM_LIT:1> and self . _on_create is not None : <EOL> self . _on_create ( self ) <EOL> elif self . life_time == self . time and self . _on_destroy is not None : <EOL> self . _on_destroy ( self ) <EOL> elif self . _on_each is not None : <EOL> self . _on_each ( self ) <EOL> return self . _last <EOL> class ParticleEmitter ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , count , new_particle , spawn , life_time , <EOL> blend = False ) : <EOL> """<STR_LIT>""" <EOL> super ( ParticleEmitter , self ) . __init__ ( ) <EOL> self . _screen = screen <EOL> self . _x = x <EOL> self . _y = y <EOL> self . _count = count <EOL> self . _new_particle = new_particle <EOL> self . _life_time = life_time <EOL> self . particles = [ ] <EOL> self . time_left = spawn <EOL> self . _blend = blend <EOL> def update ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . time_left > <NUM_LIT:0> : <EOL> self . time_left -= <NUM_LIT:1> <EOL> for _ in range ( self . _count ) : <EOL> new_particle = self . _new_particle ( ) <EOL> if new_particle is not None : <EOL> self . particles . append ( new_particle ) <EOL> for particle in self . particles : <EOL> last = particle . last ( ) <EOL> if last is not None : <EOL> char , x , y , fg , attr , bg = last <EOL> screen_data = self . _screen . get_from ( x , y ) <EOL> if self . _blend and screen_data : <EOL> char2 , fg2 , attr2 , bg2 = screen_data <EOL> index = <NUM_LIT:0> <EOL> for i , colours in enumerate ( particle . colours ) : <EOL> if ( fg2 , attr2 , bg2 ) == colours : <EOL> index = i <EOL> break <EOL> index -= <NUM_LIT:1> <EOL> fg , attr , bg = particle . colours [ max ( index , <NUM_LIT:0> ) ] <EOL> self . _screen . print_at ( "<STR_LIT:U+0020>" , x , y , fg , attr , bg ) <EOL> if particle . time < particle . life_time : <EOL> char , x , y , fg , attr , bg = particle . next ( ) <EOL> screen_data = self . _screen . get_from ( x , y ) <EOL> if self . _blend and screen_data : <EOL> char2 , fg2 , attr2 , bg2 = screen_data <EOL> index = - <NUM_LIT:1> <EOL> for i , colours in enumerate ( particle . colours ) : <EOL> if ( fg2 , attr2 , bg2 ) == colours : <EOL> index = i <EOL> break <EOL> index += <NUM_LIT:1> <EOL> fg , attr , bg = particle . colours [ min ( index , len ( particle . colours ) - <NUM_LIT:1> ) ] <EOL> self . _screen . print_at ( char , x , y , fg , attr , bg ) <EOL> else : <EOL> self . particles . remove ( particle ) <EOL> class ParticleEffect ( with_metaclass ( ABCMeta , Effect ) ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( ParticleEffect , self ) . __init__ ( ** kwargs ) <EOL> self . _screen = screen <EOL> self . _x = x <EOL> self . _y = y <EOL> self . _life_time = life_time <EOL> self . _active_systems = [ ] <EOL> self . reset ( ) <EOL> @ abstractmethod <EOL> def reset ( self ) : <EOL> """<STR_LIT>""" <EOL> def _update ( self , frame_no ) : <EOL> for system in copy ( self . _active_systems ) : <EOL> if len ( system . particles ) > <NUM_LIT:0> or system . time_left > <NUM_LIT:0> : <EOL> system . update ( ) <EOL> else : <EOL> self . _active_systems . remove ( system ) <EOL> @ property <EOL> def stop_frame ( self ) : <EOL> return self . _stop_frame <EOL> class Rocket ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , on_destroy = None ) : <EOL> """<STR_LIT>""" <EOL> super ( Rocket , self ) . __init__ ( <EOL> screen , x , screen . height - <NUM_LIT:1> , <NUM_LIT:1> , self . _new_particle , <NUM_LIT:1> , life_time ) <EOL> self . _end_y = y <EOL> self . _acceleration = ( self . _end_y - self . _y ) // life_time <EOL> self . _on_destroy = on_destroy <EOL> def _new_particle ( self ) : <EOL> return Particle ( "<STR_LIT:|>" , <EOL> self . _x , <EOL> self . _y , <EOL> <NUM_LIT:0> , <EOL> self . _acceleration , <EOL> [ ( Screen . COLOUR_YELLOW , Screen . A_BOLD , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _move , <EOL> on_destroy = self . _on_destroy ) <EOL> def _move ( self , particle ) : <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> if particle . y <= self . _end_y : <EOL> particle . y = self . _end_y <EOL> particle . time = self . _life_time - <NUM_LIT:1> <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class RingExplosion ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time ) : <EOL> """<STR_LIT>""" <EOL> super ( RingExplosion , self ) . __init__ ( <EOL> screen , x , y , <NUM_LIT:30> , self . _new_particle , <NUM_LIT:1> , life_time ) <EOL> self . _colour = randint ( <NUM_LIT:1> , <NUM_LIT:7> ) <EOL> self . _acceleration = <NUM_LIT:1.0> - ( <NUM_LIT:1.0> / life_time ) <EOL> def _new_particle ( self ) : <EOL> direction = uniform ( <NUM_LIT:0> , <NUM_LIT:2> * pi ) <EOL> return Particle ( "<STR_LIT>" , <EOL> self . _x , <EOL> self . _y , <EOL> sin ( direction ) * <NUM_LIT:3> * <NUM_LIT:8> / self . _life_time , <EOL> cos ( direction ) * <NUM_LIT> * <NUM_LIT:8> / self . _life_time , <EOL> [ ( self . _colour , Screen . A_BOLD , <NUM_LIT:0> ) , <EOL> ( self . _colour , <NUM_LIT:0> , <NUM_LIT:0> ) , <EOL> ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _explode ) <EOL> def _explode ( self , particle ) : <EOL> particle . dy = particle . dy * self . _acceleration + <NUM_LIT> <EOL> particle . dx *= self . _acceleration <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class SerpentExplosion ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time ) : <EOL> """<STR_LIT>""" <EOL> super ( SerpentExplosion , self ) . __init__ ( <EOL> screen , x , y , <NUM_LIT:8> , self . _new_particle , <NUM_LIT:2> , life_time ) <EOL> self . _colour = randint ( <NUM_LIT:1> , <NUM_LIT:7> ) <EOL> def _new_particle ( self ) : <EOL> direction = uniform ( <NUM_LIT:0> , <NUM_LIT:2> * pi ) <EOL> acceleration = uniform ( <NUM_LIT:0> , <NUM_LIT:2> * pi ) <EOL> return Particle ( "<STR_LIT>" , <EOL> self . _x , <EOL> self . _y , <EOL> cos ( direction ) , <EOL> sin ( direction ) / <NUM_LIT:2> , <EOL> [ ( self . _colour , Screen . A_BOLD , <NUM_LIT:0> ) , ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _explode , <EOL> parm = acceleration ) <EOL> @ staticmethod <EOL> def _explode ( particle ) : <EOL> if particle . time % <NUM_LIT:3> == <NUM_LIT:0> : <EOL> particle . _parm = uniform ( <NUM_LIT:0> , <NUM_LIT:2> * pi ) <EOL> particle . dx = ( particle . dx + cos ( particle . _parm ) / <NUM_LIT:2> ) * <NUM_LIT> <EOL> particle . dy = ( particle . dy + sin ( particle . _parm ) / <NUM_LIT:4> ) * <NUM_LIT> <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class StarExplosion ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , points , on_each ) : <EOL> """<STR_LIT>""" <EOL> super ( StarExplosion , self ) . __init__ ( <EOL> screen , x , y , points , self . _new_particle , <NUM_LIT:1> , life_time ) <EOL> self . _colour = randint ( <NUM_LIT:1> , <NUM_LIT:7> ) <EOL> self . _acceleration = <NUM_LIT:1.0> - ( <NUM_LIT:1.0> / life_time ) <EOL> self . _on_each = on_each <EOL> self . _points = points <EOL> self . _point_count = <NUM_LIT:0> <EOL> def _new_particle ( self ) : <EOL> direction = self . _point_count * <NUM_LIT:2> * pi / self . _points <EOL> self . _point_count += <NUM_LIT:1> <EOL> return Particle ( "<STR_LIT:+>" , <EOL> self . _x , <EOL> self . _y , <EOL> sin ( direction ) * <NUM_LIT:3> * <NUM_LIT:8> / self . _life_time , <EOL> cos ( direction ) * <NUM_LIT> * <NUM_LIT:8> / self . _life_time , <EOL> [ ( self . _colour , Screen . A_BOLD , <NUM_LIT:0> ) , ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _explode , <EOL> on_each = self . _on_each ) <EOL> def _explode ( self , particle ) : <EOL> particle . dy = particle . dy * self . _acceleration + <NUM_LIT> <EOL> particle . dx *= self . _acceleration <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class StarTrail ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , colour ) : <EOL> """<STR_LIT>""" <EOL> super ( StarTrail , self ) . __init__ ( <EOL> screen , x , y , <NUM_LIT:1> , self . _new_particle , <NUM_LIT:1> , life_time ) <EOL> self . _colour = colour <EOL> def _new_particle ( self ) : <EOL> return Particle ( "<STR_LIT>" , <EOL> self . _x , <EOL> self . _y , <EOL> <NUM_LIT:0> , <EOL> <NUM_LIT:0> , <EOL> [ ( self . _colour , Screen . A_BOLD , <NUM_LIT:0> ) , <EOL> ( self . _colour , <NUM_LIT:0> , <NUM_LIT:0> ) , <EOL> ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _twinkle ) <EOL> @ staticmethod <EOL> def _twinkle ( particle ) : <EOL> particle . dy += <NUM_LIT> <EOL> particle . y += particle . dy <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class PalmExplosion ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , on_each = None ) : <EOL> """<STR_LIT>""" <EOL> super ( PalmExplosion , self ) . __init__ ( <EOL> screen , x , y , <NUM_LIT:6> , self . _new_particle , <NUM_LIT:2> , life_time ) <EOL> self . _colour = randint ( <NUM_LIT:1> , <NUM_LIT:7> ) <EOL> self . _on_each = on_each <EOL> self . _arc_start = uniform ( pi / <NUM_LIT:6> , pi / <NUM_LIT:3> ) <EOL> self . _arc_end = self . _arc_start + uniform ( pi / <NUM_LIT:6> , pi / <NUM_LIT:2> ) <EOL> def _new_particle ( self ) : <EOL> direction = uniform ( self . _arc_start , self . _arc_end ) <EOL> return Particle ( "<STR_LIT>" , <EOL> self . _x , <EOL> self . _y , <EOL> cos ( direction ) * <NUM_LIT> , <EOL> - sin ( direction ) , <EOL> [ ( self . _colour , Screen . A_BOLD , <NUM_LIT:0> ) , <EOL> ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _explode , <EOL> on_each = self . _on_each ) <EOL> @ staticmethod <EOL> def _explode ( particle ) : <EOL> particle . dy += <NUM_LIT> <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class ExplosionFlames ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time ) : <EOL> """<STR_LIT>""" <EOL> super ( ExplosionFlames , self ) . __init__ ( <EOL> screen , x , y , <NUM_LIT:30> , self . _new_particle , life_time - <NUM_LIT:10> , life_time , <EOL> blend = True ) <EOL> def _new_particle ( self ) : <EOL> direction = uniform ( <NUM_LIT:0> , <NUM_LIT:2> * pi ) <EOL> d = self . _life_time - <NUM_LIT:10> <EOL> r = uniform ( <NUM_LIT:0> , sin ( pi * ( d - self . time_left ) / ( d * <NUM_LIT:2> ) ) ) * <NUM_LIT> <EOL> return Particle ( "<STR_LIT:#>" , <EOL> self . _x + sin ( direction ) * r * <NUM_LIT> , <EOL> self . _y + cos ( direction ) * r , <EOL> sin ( direction ) / <NUM_LIT> , <EOL> cos ( direction ) / <NUM_LIT> , <EOL> [ <EOL> ( Screen . COLOUR_BLACK , <NUM_LIT:0> , <NUM_LIT:0> ) , <EOL> ( Screen . COLOUR_RED , <NUM_LIT:0> , <NUM_LIT:0> ) , <EOL> ( Screen . COLOUR_RED , Screen . A_BOLD , <NUM_LIT:0> ) , <EOL> ( Screen . COLOUR_YELLOW , Screen . A_BOLD , <NUM_LIT:0> ) , <EOL> ( Screen . COLOUR_WHITE , Screen . A_BOLD , <NUM_LIT:0> ) , <EOL> ] , <EOL> <NUM_LIT:10> , <EOL> self . _burn , <EOL> next_colour = self . _colour ) <EOL> @ staticmethod <EOL> def _burn ( particle ) : <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> @ staticmethod <EOL> def _colour ( particle ) : <EOL> return particle . colours [ <NUM_LIT:0> ] <EOL> class DropEmitter ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , life_time ) : <EOL> """<STR_LIT>""" <EOL> super ( DropEmitter , self ) . __init__ ( <EOL> screen , <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:20> , self . _new_particle , life_time , life_time ) <EOL> self . _particles = None <EOL> def _new_particle ( self ) : <EOL> if self . _particles is None : <EOL> self . _particles = [ ] <EOL> for x in range ( self . _screen . width ) : <EOL> for y in range ( self . _screen . height ) : <EOL> ch , fg , attr , bg = self . _screen . get_from ( x , y ) <EOL> if ch != <NUM_LIT:32> : <EOL> self . _particles . insert ( <EOL> randint ( <NUM_LIT:0> , len ( self . _particles ) ) , <EOL> ( x , y , ch , fg , attr , bg ) ) <EOL> if len ( self . _particles ) == <NUM_LIT:0> : <EOL> return None <EOL> x , y , ch , fg , attr , bg = self . _particles . pop ( ) <EOL> return Particle ( chr ( ch ) , x , y , <EOL> <NUM_LIT:0.0> , <EOL> <NUM_LIT:0.0> , <EOL> [ ( fg , attr , bg ) ] , <EOL> self . _life_time , <EOL> self . _move ) <EOL> @ staticmethod <EOL> def _move ( particle ) : <EOL> result = int ( particle . x ) , int ( particle . y ) <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> particle . dy += <NUM_LIT> <EOL> return result <EOL> class ShotEmitter ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time ) : <EOL> """<STR_LIT>""" <EOL> super ( ShotEmitter , self ) . __init__ ( <EOL> screen , x , y , <NUM_LIT:50> , self . _new_particle , life_time , life_time ) <EOL> self . _particles = None <EOL> def _new_particle ( self ) : <EOL> if self . _particles is None : <EOL> self . _particles = [ ] <EOL> for x in range ( self . _screen . width ) : <EOL> for y in range ( self . _screen . height ) : <EOL> ch , fg , attr , bg = self . _screen . get_from ( x , y ) <EOL> if ch != <NUM_LIT:32> : <EOL> self . _particles . append ( ( x , y , ch , fg , attr , bg ) ) <EOL> self . _particles = sorted ( <EOL> self . _particles , key = self . _sort , reverse = True ) <EOL> if len ( self . _particles ) == <NUM_LIT:0> : <EOL> return None <EOL> x , y , ch , fg , attr , bg = self . _particles . pop ( ) <EOL> r = min ( <NUM_LIT:10> , <EOL> max ( <NUM_LIT> , <EOL> sqrt ( ( ( x - self . _x ) ** <NUM_LIT:2> ) + ( ( y - self . _y ) ** <NUM_LIT:2> ) ) ) ) <EOL> return Particle ( chr ( ch ) , x , y , <EOL> ( x - self . _x ) * <NUM_LIT> / r ** <NUM_LIT:2> , <EOL> ( y - self . _y ) * <NUM_LIT> / r ** <NUM_LIT:2> , <EOL> [ ( fg , attr , bg ) ] , <EOL> self . _life_time , <EOL> self . _move ) <EOL> def _sort ( self , data ) : <EOL> dx = data [ <NUM_LIT:0> ] - self . _x <EOL> dy = data [ <NUM_LIT:1> ] - self . _y <EOL> return ( dx * dx / <NUM_LIT> ) + ( dy * dy ) <EOL> @ staticmethod <EOL> def _move ( particle ) : <EOL> result = int ( particle . x ) , int ( particle . y ) <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> return result <EOL> class RainSource ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , life_time , on_each ) : <EOL> """<STR_LIT>""" <EOL> super ( RainSource , self ) . __init__ ( <EOL> screen , <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:4> , self . _new_particle , life_time , life_time ) <EOL> self . _particles = None <EOL> self . _on_each = on_each <EOL> def _new_particle ( self ) : <EOL> speed = randint ( <NUM_LIT:1> , <NUM_LIT:3> ) <EOL> return Particle ( "<STR_LIT>" [ speed ] , <EOL> randint ( - self . _screen . height , self . _screen . width ) , <NUM_LIT:0> , <EOL> ( speed + <NUM_LIT:1> ) / <NUM_LIT> , <EOL> ( speed + <NUM_LIT:1> ) / <NUM_LIT> , <EOL> [ ( Screen . COLOUR_CYAN , <NUM_LIT:0> , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _move , <EOL> on_each = self . _on_each ) <EOL> @ staticmethod <EOL> def _move ( particle ) : <EOL> particle . x += particle . dx <EOL> particle . y += particle . dy <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class Splash ( ParticleEmitter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y ) : <EOL> """<STR_LIT>""" <EOL> super ( Splash , self ) . __init__ ( <EOL> screen , x , y , <NUM_LIT:1> , self . _new_particle , <NUM_LIT:1> , <NUM_LIT:3> ) <EOL> def _new_particle ( self ) : <EOL> return Particle ( "<STR_LIT:v>" , <EOL> self . _x , self . _y , <EOL> <NUM_LIT:0> , <NUM_LIT:0> , <EOL> [ ( Screen . COLOUR_CYAN , <NUM_LIT:0> , <NUM_LIT:0> ) ] , <EOL> self . _life_time , <EOL> self . _splash ) <EOL> @ staticmethod <EOL> def _splash ( particle ) : <EOL> return int ( particle . x ) , int ( particle . y ) <EOL> class StarFirework ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( StarFirework , self ) . __init__ ( screen , x , y , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> Rocket ( self . _screen , self . _x , self . _y , <NUM_LIT:10> , on_destroy = self . _next ) ) <EOL> def _next ( self , parent ) : <EOL> self . _active_systems . append ( <EOL> StarExplosion ( <EOL> self . _screen , parent . x , parent . y , self . _life_time - <NUM_LIT:10> , <EOL> randint ( <NUM_LIT:6> , <NUM_LIT:20> ) , on_each = self . _trail ) ) <EOL> def _trail ( self , parent ) : <EOL> if len ( self . _active_systems ) < <NUM_LIT> and randint ( <NUM_LIT:0> , <NUM_LIT:100> ) < <NUM_LIT:50> : <EOL> self . _active_systems . insert ( <EOL> <NUM_LIT:0> , StarTrail ( self . _screen , <EOL> parent . x , <EOL> parent . y , <EOL> <NUM_LIT:10> , <EOL> parent . colours [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] ) ) <EOL> class RingFirework ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( RingFirework , self ) . __init__ ( screen , x , y , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> Rocket ( self . _screen , self . _x , self . _y , <NUM_LIT:10> , on_destroy = self . _next ) ) <EOL> def _next ( self , parent ) : <EOL> self . _active_systems . append ( RingExplosion ( <EOL> self . _screen , parent . x , parent . y , self . _life_time - <NUM_LIT:10> ) ) <EOL> class SerpentFirework ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( SerpentFirework , self ) . __init__ ( screen , x , y , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> Rocket ( self . _screen , self . _x , self . _y , <NUM_LIT:10> , on_destroy = self . _next ) ) <EOL> def _next ( self , parent ) : <EOL> self . _active_systems . append ( SerpentExplosion ( <EOL> self . _screen , parent . x , parent . y , self . _life_time - <NUM_LIT:10> ) ) <EOL> class PalmFirework ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( PalmFirework , self ) . __init__ ( screen , x , y , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> Rocket ( self . _screen , self . _x , self . _y , <NUM_LIT:10> , on_destroy = self . _next ) ) <EOL> def _next ( self , parent ) : <EOL> self . _active_systems . append ( PalmExplosion ( <EOL> self . _screen , parent . x , parent . y , self . _life_time - <NUM_LIT:10> , <EOL> on_each = self . _trail ) ) <EOL> def _trail ( self , parent ) : <EOL> if len ( self . _active_systems ) < <NUM_LIT:100> and randint ( <NUM_LIT:0> , <NUM_LIT:100> ) < <NUM_LIT> : <EOL> self . _active_systems . insert ( <EOL> <NUM_LIT:0> , StarTrail ( self . _screen , <EOL> parent . x , <EOL> parent . y , <EOL> <NUM_LIT:10> , <EOL> parent . colours [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] ) ) <EOL> class Explosion ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( Explosion , self ) . __init__ ( screen , x , y , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> ExplosionFlames ( self . _screen , self . _x , self . _y , self . _life_time ) ) <EOL> class DropScreen ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( DropScreen , self ) . __init__ ( screen , <NUM_LIT:0> , <NUM_LIT:0> , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> DropEmitter ( self . _screen , self . _life_time ) ) <EOL> class ShootScreen ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , x , y , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( ShootScreen , self ) . __init__ ( screen , x , y , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> ShotEmitter ( self . _screen , self . _x , self . _y , self . _life_time ) ) <EOL> class Rain ( ParticleEffect ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , screen , life_time , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( Rain , self ) . __init__ ( screen , <NUM_LIT:0> , <NUM_LIT:0> , life_time , ** kwargs ) <EOL> def reset ( self ) : <EOL> self . _active_systems = [ ] <EOL> self . _active_systems . append ( <EOL> RainSource ( self . _screen , self . _life_time , self . _collision ) ) <EOL> def _collision ( self , particle ) : <EOL> _ , x , y , _ , _ , _ = particle . last ( ) <EOL> current_char = None <EOL> dx = <NUM_LIT:0> <EOL> for dx in range ( min ( <NUM_LIT:1> , int ( particle . dx ) ) ) : <EOL> next_point = self . _screen . get_from ( int ( x + dx ) , int ( y + dx ) ) <EOL> if next_point is None : <EOL> current_char = None <EOL> break <EOL> current_char = next_point [ <NUM_LIT:0> ] <EOL> if current_char != <NUM_LIT:32> : <EOL> break <EOL> if ( current_char not in [ <NUM_LIT:32> , None , ord ( "<STR_LIT>" ) , ord ( "<STR_LIT:\\>" ) , ord ( "<STR_LIT:v>" ) ] or <EOL> particle . y + dx >= self . _screen . height ) : <EOL> particle . time = particle . life_time <EOL> self . _active_systems . append ( <EOL> Splash ( self . _screen , x + dx - <NUM_LIT:1> , y + dx - <NUM_LIT:1> ) ) </s>
