# Path: game/enemy.py
# class Enemy(GameObject):
#     STATES       = config.Enum(*ENEMY_STATES)
#     anim         = 0.0
#     base_speed   = 0.5
#     GROUP        = None
#     shoot_odds   = 0.002
#     should_flip  = False
#     start_time   = None
#     velocity     = [0.5, 0.0]
# 
#     def __init__(self, form_position):
#         super().__init__()
#         ### Local variables ####################################################
#         the_color = choice(color.LIST)
#         the_id    = id(the_color)
#         ########################################################################
#         
#         ### Object Attributes ##################################################
#         self.amount_lowered     = 0
#         self._anim              = 0.0
#         self.color              = the_color
#         self.column             = None
#         self._form_position     = form_position
#         self.current_frame_list = ENEMY_FRAMES_COLOR_BLIND if settings.SETTINGS['color_blind'] else ENEMY_FRAMES
#         self.image              = self.current_frame_list[the_id][0]
#         self.position           = list(START_POS)
#         self.rect               = Rect(START_POS, self.image.get_size())
#         self.state              = Enemy.STATES.IDLE
#         self.emitter            = ParticleEmitter(color.color_particles[the_id], self.rect, 1)
#         ########################################################################
#         
#         ### Preparation ########################################################
#         del self.acceleration, self.velocity
#         ########################################################################
# 
#     def appear(self):
#         self.add(Enemy.GROUP)
#         self.position     = [
#                              START_POS[0] * (self._form_position[0] + 1) * 1.5,
#                              START_POS[1] * (self._form_position[1] + 1) * 1.5,
#                             ]
#         self.rect.topleft = (self.position[0] + .5, self.position[1] + .5)
#         self.color        = choice(color.LIST)
#         self.__animate()
#         self.emitter.pool = color.color_particles[id(self.color)]
#         self.change_state(Enemy.STATES.ACTIVE)
# 
#     def move(self):
#         self.__animate()
#         self.position[0] += Enemy.velocity[0]
#         self.rect.topleft = (self.position[0] + .5, self.position[1] + .5)
#         
#         if uniform(0, 1) < Enemy.shoot_odds and not enemybullet.EnemyBullet.halt:
#         #With Enemy.shoot_odds% of firing...
#         #TODO: Use another probability distribution
#             b             = enemybullet.get_enemy_bullet()
#             b.rect.midtop = self.rect.midbottom
#             b.position    = list(b.rect.topleft)
#             b.add(enemybullet.EnemyBullet.GROUP)
# 
#         if not Enemy.should_flip:
#         #If the squadron of enemies is not marked to reverse direction...
#             if self.rect.left < 0 or self.rect.right > config.SCREEN_WIDTH:
#             #If this enemy touches either end of the screen...
#                 Enemy.should_flip = True
# 
#     def die(self):
#         balloflight.get_ball(self.rect.topleft, self.column, self.color).add(Enemy.GROUP)
#         _hurt.play()
#         self.emitter.burst(20)
#         self.kill()
#         
#         self.position      = [-300.0, -300.0]
#         self.rect.topleft  = self.position
#         self.change_state(Enemy.STATES.IDLE)
#         Enemy.velocity[0] += copysign(0.1, Enemy.velocity[0])
#         #^ Increase the enemy squadron's speed (copysign() considers direction)
# 
#     def lower(self):
#         self.__animate()
#         self.amount_lowered += 1
#         self.position[1]    += 1
#         self.rect.top        = self.position[1]
#         if self.amount_lowered == LOWER_INCREMENT:
#             self.amount_lowered = 0
#             self.change_state(Enemy.STATES.ACTIVE)
# 
#     def cheer(self):
#         self.__animate()
#         self.position[1] -= 2 * sin((Enemy.anim/2) - (pi/4) * self._form_position[0])
#         self.rect.top = self.position[1] + .5
#     
#     def __animate(self):
#         self._anim = int(3 - abs(Enemy.anim - 3)) % 4
#         self.image = self.current_frame_list[id(self.color)][self._anim]
# 
#     actions = {
#                 STATES.APPEARING: 'appear',
#                 STATES.LOWERING : 'lower' ,
#                 STATES.ACTIVE   : 'move'  ,
#                 STATES.DYING    : 'die'   ,
#                 STATES.IDLE     : None    ,
#                 STATES.CHEERING : 'cheer' ,
#               }
# 
# Path: game/gamedata.py
# DEFAULT_LIVES = 3
# MAX_COMBO_TIME = 60  #In frames
# def clean_up():


from math   import log1p
from random import randint
from game.enemy import Enemy
from game       import gamedata
import pygame.time
    _enemies         = None
    Enemy.velocity   = [.5, 0.0]
    Enemy.start_time = None
    Enemy.shoot_odds = .002

def celebrate():
    '''
    Plays the Enemy celebration animation upon game over.
    '''
    Enemy.velocity = [0.0, 0.0]
    for e in (j for j in ENEMY_GROUP if isinstance(j, Enemy)):
    #For all enemies...
        e.change_state(Enemy.STATES.CHEERING)

def move_down():
    '''
    Moves the entire squadron down.
    '''
    for e in ENEMY_GROUP:
    #For all enemies on-screen...
        e.change_state(Enemy.STATES.LOWERING)
    Enemy.should_flip  = False

def reset():
    '''
    Brings out the next wave of Enemys (and recycles all the Enemy objects).
    '''
    global _enemies
    ENEMY_GROUP.empty()
    _enemies       = tuple([Enemy((i, j)) for i in range(ROW_SIZE)] for j in range(COL_SIZE))

# Path: game/enemy.py
# class Enemy(GameObject):
#     STATES       = config.Enum(*ENEMY_STATES)
#     anim         = 0.0
#     base_speed   = 0.5
#     GROUP        = None
#     shoot_odds   = 0.002
#     should_flip  = False
#     start_time   = None
#     velocity     = [0.5, 0.0]
# 
#     def __init__(self, form_position):
#         super().__init__()
#         ### Local variables ####################################################
#         the_color = choice(color.LIST)
#         the_id    = id(the_color)
#         ########################################################################
#         
#         ### Object Attributes ##################################################
#         self.amount_lowered     = 0
#         self._anim              = 0.0
#         self.color              = the_color
#         self.column             = None
#         self._form_position     = form_position
#         self.current_frame_list = ENEMY_FRAMES_COLOR_BLIND if settings.SETTINGS['color_blind'] else ENEMY_FRAMES
#         self.image              = self.current_frame_list[the_id][0]
#         self.position           = list(START_POS)
#         self.rect               = Rect(START_POS, self.image.get_size())
#         self.state              = Enemy.STATES.IDLE
#         self.emitter            = ParticleEmitter(color.color_particles[the_id], self.rect, 1)
#         ########################################################################
#         
#         ### Preparation ########################################################
#         del self.acceleration, self.velocity
#         ########################################################################
# 
#     def appear(self):
#         self.add(Enemy.GROUP)
#         self.position     = [
#                              START_POS[0] * (self._form_position[0] + 1) * 1.5,
#                              START_POS[1] * (self._form_position[1] + 1) * 1.5,
#                             ]
#         self.rect.topleft = (self.position[0] + .5, self.position[1] + .5)
#         self.color        = choice(color.LIST)
#         self.__animate()
#         self.emitter.pool = color.color_particles[id(self.color)]
#         self.change_state(Enemy.STATES.ACTIVE)
# 
#     def move(self):
#         self.__animate()
#         self.position[0] += Enemy.velocity[0]
#         self.rect.topleft = (self.position[0] + .5, self.position[1] + .5)
#         
#         if uniform(0, 1) < Enemy.shoot_odds and not enemybullet.EnemyBullet.halt:
#         #With Enemy.shoot_odds% of firing...
#         #TODO: Use another probability distribution
#             b             = enemybullet.get_enemy_bullet()
#             b.rect.midtop = self.rect.midbottom
#             b.position    = list(b.rect.topleft)
#             b.add(enemybullet.EnemyBullet.GROUP)
# 
#         if not Enemy.should_flip:
#         #If the squadron of enemies is not marked to reverse direction...
#             if self.rect.left < 0 or self.rect.right > config.SCREEN_WIDTH:
#             #If this enemy touches either end of the screen...
#                 Enemy.should_flip = True
# 
#     def die(self):
#         balloflight.get_ball(self.rect.topleft, self.column, self.color).add(Enemy.GROUP)
#         _hurt.play()
#         self.emitter.burst(20)
#         self.kill()
#         
#         self.position      = [-300.0, -300.0]
#         self.rect.topleft  = self.position
#         self.change_state(Enemy.STATES.IDLE)
#         Enemy.velocity[0] += copysign(0.1, Enemy.velocity[0])
#         #^ Increase the enemy squadron's speed (copysign() considers direction)
# 
#     def lower(self):
#         self.__animate()
#         self.amount_lowered += 1
#         self.position[1]    += 1
#         self.rect.top        = self.position[1]
#         if self.amount_lowered == LOWER_INCREMENT:
#             self.amount_lowered = 0
#             self.change_state(Enemy.STATES.ACTIVE)
# 
#     def cheer(self):
#         self.__animate()
#         self.position[1] -= 2 * sin((Enemy.anim/2) - (pi/4) * self._form_position[0])
#         self.rect.top = self.position[1] + .5
#     
#     def __animate(self):
#         self._anim = int(3 - abs(Enemy.anim - 3)) % 4
#         self.image = self.current_frame_list[id(self.color)][self._anim]
# 
#     actions = {
#                 STATES.APPEARING: 'appear',
#                 STATES.LOWERING : 'lower' ,
#                 STATES.ACTIVE   : 'move'  ,
#                 STATES.DYING    : 'die'   ,
#                 STATES.IDLE     : None    ,
#                 STATES.CHEERING : 'cheer' ,
#               }
# 
# Path: game/gamedata.py
# DEFAULT_LIVES = 3
# MAX_COMBO_TIME = 60  #In frames
# def clean_up():


# Path: game/enemysquadron.py
from math   import log1p
from random import randint
from game.enemy import Enemy
from game       import gamedata
import pygame.time

    _enemies         = None
    Enemy.velocity   = [.5, 0.0]
    Enemy.start_time = None
    Enemy.shoot_odds = .002

def celebrate():
    '''
    Plays the Enemy celebration animation upon game over.
    '''
    Enemy.velocity = [0.0, 0.0]
    for e in (j for j in ENEMY_GROUP if isinstance(j, Enemy)):
    #For all enemies...
        e.change_state(Enemy.STATES.CHEERING)

def move_down():
    '''
    Moves the entire squadron down.
    '''
    for e in ENEMY_GROUP:
    #For all enemies on-screen...
        e.change_state(Enemy.STATES.LOWERING)
    Enemy.should_flip  = False

def reset():
    '''
    Brings out the next wave of Enemys (and recycles all the Enemy objects).
    '''
    global _enemies
    ENEMY_GROUP.empty()
    _enemies       = tuple([Enemy((i, j)) for i in range(ROW_SIZE)] for j in range(COL_SIZE))

    gamedata.wave += 1