#!/usr/bin/python

# Copyright (C) 2010 Jonathan Ciesla

# 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, either version 3 of the License, or
# (at your option) any later version.

# 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.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import sys, pygame, random, os.path, getpass, time, math
from optparse import OptionParser

usage = "%prog [-w | --windowed] [-n | --nosound] | --version";
parser = OptionParser(usage, version="%prog 1.1")
parser.add_option("-w", "--windowed", action="store", nargs=0, dest="windowed", help="Play in windowed mode", default="0")
parser.add_option("-n", "--nosound", action="store", nargs=0, dest="nosound", help="Disable sound", default="0")

(options, args) = parser.parse_args()

pygame.init()
if options.nosound: pygame.mixer.init(22050, -16, 16, 1024)

pygame.display.set_caption("Iapetal")

clock = pygame.time.Clock()

size = width, height = 1024, 768
black = 0, 0, 0

screen = pygame.display.set_mode(size)
if options.windowed:
    pygame.display.toggle_fullscreen()

pygame.mouse.set_visible(0)

floor = height - 25

level = 1

landers = 3
score = 0
endlevel = 0
endgame = 0

people_in_habitat = 16
people_in_lander = 0
people_in_lander_limit = 4
people_in_rescue = 0
load_delay = 0
load_delay_max = 8

rock_delay = 0
rock_delay_max = 120

def stars_init(stars, width, floor):
    stars = []
    for star_count in range(0, 25):
        stars.append((random.randrange(25, width-25), random.randrange(25, floor-25)))
    return stars

stars = []
stars = stars_init(stars, width, floor)

font = pygame.font.SysFont("DejaVu Sans", 12)
big_font = pygame.font.SysFont("DejaVu Sans", 48)
color = (0, 255, 255)
infobar_h = height-20

if os.path.lexists("/usr/share/iapetal"):
    file_path = "/usr/share/iapetal/"
else:
    file_path = "./"

lander = pygame.image.load(file_path + "lander.png")
lander_thrust = pygame.image.load(file_path + "lander_thrust.png")
boom = pygame.image.load(file_path + "boom.png")
landerrect = lander.get_rect()
lander_burn = pygame.image.load(file_path + "burn_medium.png")
lander_burnrect = lander_burn.get_rect()

class rocks:
    h = 0 
    v = 0 
    speed_h = 0
    speed_v = 0
    dir = 0
    spin = 0
    image = 0
    image_boom = 0
    rect = 0
    centerhold = 0, 0
    new = 0
    mass = 0
    burning = 0
    burn_image = 0
    burnrect = 0
    burnnew = 0

rocklist = []

base = pygame.image.load(file_path + "base.png")
base_boom = pygame.image.load(file_path + "base_boom.png")
baserect = base.get_rect()
base_out = 0

habitat = pygame.image.load(file_path + "habitat.png")
habitat_boom = pygame.image.load(file_path + "habitat_boom.png")
habitatrect = habitat.get_rect()
habitat_out = 0
habitat_out_count = 5

class rescues:
    h = 0 
    v = 0 
    speed_h = 0
    speed_v = 0
    orig_speed_h = 0
    image_left = 0
    image_left_boom = 0
    image_right = 0
    image_right_boom = 0
    center = 0
    rect = 0
    new = 0
    orient_mult = 0
    out = 0
    entering = 0

def rescue_init(width, height):

    rescue = rescues()
    
    rescue.entering = 1
    orient = random.randrange(-1, 1)
    if orient >=0:
        rescue.orient_mult = 1
    else:
        rescue.orient_mult = -1
    rescue.h = random.randrange(50, width-50)
    rescue.v = random.randrange(-25, 0)
    rescue.speed_h = random.randrange(1, 2) * rescue.orient_mult
    rescue.speed_v = 0
    rescue.orig_speed_h = rescue.speed_h

    rescue.image_right = pygame.image.load(file_path + "rescue_right.png")
    rescue.image_right_boom = pygame.image.load(file_path + "rescue_boom_right.png")
    rescue.image_left = pygame.image.load(file_path + "rescue_left.png")
    rescue.image_left_boom = pygame.image.load(file_path + "rescue_boom_left.png")
    rescue.out = 0

    if rescue.orient_mult == 1:
        rescue.rect = rescue.image_right.get_rect()
    else:
        rescue.rect = rescue.image_left.get_rect()
    rescue.rect = rescue.rect.move([rescue.h, rescue.v])    
    
    return rescue    


thrust_sound = pygame.mixer.Sound(file_path + "thrust.ogg")
crash_sound = pygame.mixer.Sound(file_path + "crash.ogg")
shield_sound = pygame.mixer.Sound(file_path + "shield.ogg")
pickup_sound = pygame.mixer.Sound(file_path + "pickup.ogg")
dropoff_sound = pygame.mixer.Sound(file_path + "dropoff.ogg")
burn_sound = pygame.mixer.Sound(file_path + "burn.ogg")
channel = pygame.mixer.find_channel()
thrust_channel = pygame.mixer.find_channel()
shield_channel = pygame.mixer.find_channel()
burn_channel = pygame.mixer.find_channel()

def kabam(new, rect):
    screen.blit(new, rect)   
    pygame.display.flip()


def rock_load_images(thisrock, size):
    if size == 4: filestring = ""
    if size == 3: filestring = "_medium"
    if size == 2: filestring = "_small"
    if size == 1: filestring = "_tiny"

    thisrock.image = pygame.image.load(file_path + "rock" + filestring + ".png")
    thisrock.image_boom = pygame.image.load(file_path + "rock" + filestring + "_boom.png")
    thisrock.burn_image = pygame.image.load(file_path + "burn" + filestring + ".png")

    return thisrock

def rock_init(rocklist, width, height):

    newrock = rocks()

    newrock.h = random.randrange(50, width-50)
    newrock.v = -random.randrange(0, height-200)
    newrock.spin = random.randrange(-5, 5)
    newrock.speed_h = 0
    while newrock.speed_h == 0:
        newrock.speed_h = random.randrange(-15, 15)
    newrock.speed_v = random.randrange(0, 2)

    size = random.randrange(0,100)
    
    if size >= 90:
        newrock = rock_load_images(newrock, 4)
        newrock.burnrect = newrock.burn_image.get_rect()
        newrock.mass = 4
    elif size >= 70:
        newrock = rock_load_images(newrock, 3)
        newrock.burnrect = newrock.burn_image.get_rect()
        newrock.mass = 3
    elif size >=50:
        newrock = rock_load_images(newrock, 2)
        newrock.burnrect = newrock.burn_image.get_rect()
        newrock.mass = 2
    else:
        newrock = rock_load_images(newrock, 1)
        newrock.burnrect = newrock.burn_image.get_rect()
        newrock.mass = 1

    
    newrock.rect = newrock.image.get_rect()
    newrock.rect = newrock.rect.move([newrock.h, newrock.v])

    rocklist.append(newrock)
    
    return rocklist        

def wrap(x, width):
    if x < 0:
        x = width - 12
    else:
        if x > width:
            x = 12
    return x

def gravitize(speed, floor, y):
    speed += (1/math.pow((floor-y)+1000,2))*100000
    return speed

def rockburst(rocklist, width, height):
    burst_count = 5
    while burst_count>=0:
        rocklist = rock_init(rocklist, width, height)
        burst_count -= 1

    return rocklist

def level_init(baserect, base_out, base_out_count, habitatrect, width):

    base_h = random.randrange(50, width-50)

    if base_out >= 0:
        base_out = 0
        base_out_count = 5
        base_v = floor - 14
        baserect = base.get_rect()
        baserect = baserect.move([base_h, base_v])

    habitat_h = base_h
    while abs(habitat_h-base_h)<= 60:
        habitat_h = random.randrange(50, width-50)
    habitat_v = floor - 31
    habitatrect = habitat.get_rect()
    habitatrect = habitatrect.move([habitat_h, habitat_v])

        
    return baserect, base_out, base_out_count, habitatrect

def game_init(landerrect, rocklist, baserect, habitatrect, base_out, new_level):

    dir = 0
    fuel = 200
    dead = 0
    lost = 0
    destroyed = 0
    deflector = 500

    lander_start_h = random.randrange(50, width-50)
    lander_start_v = random.randrange(25, 300)
    lander_start_speed_h = random.randrange(-10, 10)
    lander_start_speed_v = random.randrange(0, 5)
    speed = [lander_start_speed_h, lander_start_speed_v]
    landerrect = lander.get_rect()
    landerrect = landerrect.move([lander_start_h, lander_start_v])

    rocklist = rock_init(rocklist, width, height)

    on_rescue = 0
    rescue = rescue_init(width, height)

    on_base = 0    

    base_out_count = 0

    if new_level:
        baserect, base_out, base_out_count, habitatrect = level_init(baserect, base_out, base_out_count, habitatrect, width)
    else:
        if not base_out: base_out_count = 5
        rescue.out = 1
        
    return dir, fuel, dead, lost, destroyed, deflector, landerrect, speed, rocklist, on_base, base_out, base_out_count, baserect, habitatrect, rescue, on_rescue

dir, fuel, dead, lost, destroyed, deflector, landerrect, speed, rocklist, on_base, base_out, base_out_count, baserect, habitatrect, rescue, on_rescue = game_init(landerrect, rocklist, baserect, habitatrect, base_out, 1)


while 1:
    thrust = 0
    deflect = 0
    deflector_range = deflector/5
    deflect_rate = deflector_range/10

    on_floor = 0
    lander_burning = 0

    for thisrock in rocklist:
        thisrock.burning = 0
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_p:
                pause_text = big_font.render("Paused. . .", 1, color)
                screen.blit(pause_text, ((width/2)-100, (height/2)-100))
                pygame.display.flip()
                pauseloop = 0
                while pauseloop == 0:
                    for pevent in pygame.event.get():
                        if pevent.type == pygame.KEYDOWN and pevent.key == pygame.K_p:
                            pauseloop = 1
            if event.key == pygame.K_s:
                if options.nosound == 1:
                    sound_text = big_font.render("Sound off!", 1, color)
                    options.nosound = 0
                else:
                    sound_text = big_font.render("Sound on!", 1, color)
                    options.nosound = 1
                screen.blit(sound_text, ((width/2)-100, (height/2)-100))
                pygame.display.flip()


    key = pygame.key.get_pressed()

    center = landerrect.center 
    lander_burn_center = lander_burnrect.center

    if key[pygame.K_q]:
        pygame.mouse.set_visible(1)
        sys.exit()

    if key[pygame.K_r]:
        rocklist = rockburst(rocklist, width, height)
        score += 50

    if key[pygame.K_LEFT]:
        if fuel >= 0.5 and landerrect.bottom < floor and not on_base and not on_rescue:
            dir +=6
            fuel -= 0.5
    
    if key[pygame.K_RIGHT]:
        if fuel >= 0.5 and landerrect.bottom < floor and not on_base and not on_rescue:
            dir -=6
            fuel -= 0.5
    
    if key[pygame.K_SPACE] and deflector > 0 and not on_base and not on_rescue:
        if options.nosound: shield_channel.play(shield_sound, -1)
        deflector -=1
        deflect = 1
    else:
        if options.nosound: shield_channel.stop()
        
    on_base = 0    
    on_rescue = 0
    
    landernew = pygame.transform.rotate(lander, dir)
    landerrect = landernew.get_rect(center=landerrect.center)
    lander_thrustnew = pygame.transform.rotate(lander_thrust, dir)

    #lander burn
    total_speed = math.sqrt( math.pow(speed[0],2) + math.pow(speed[1],2) )
    atmo_quot = 1200-floor-landerrect.centery
    if(total_speed > atmo_quot and total_speed > 8):  #vary by altitute, i.e. atmospheric viscosity
        if options.nosound: burn_channel.play(burn_sound, -1)
        lander_burning = 1
        if deflector >= 0:
            deflector -= int(total_speed)
        else:
            if options.nosound: channel = crash_sound.play()
            landernew = pygame.transform.rotate(boom, dir)
            landerrect = landernew.get_rect(center=center)
            dead_text = big_font.render("FOOF!!!", 1, color)
            dead = 1

        lander_travel_dir = math.degrees(math.atan2(speed[0], speed[1]))
        lander_burnnew = pygame.transform.rotate(lander_burn, lander_travel_dir) #get dir from movement
        lander_burnrect.centerx = landerrect.centerx-(landerrect.width/2) #center burning on lander
        lander_burnrect.centery = landerrect.centery-(landerrect.height/2)

    #rock burn
    rock_count = 0
    for thisrock in rocklist:
        total_speed = math.sqrt( math.pow(thisrock.speed_h,2) + math.pow(thisrock.speed_v,2) )
        atmo_quot = 1200-floor-thisrock.rect.centery
        if(total_speed > atmo_quot and total_speed > 8):
            thisrock.burning = 1
            thisrock.mass -= total_speed / (thisrock.mass * 100 )
            if thisrock.mass <= 3:
                thisrock = rock_load_images(thisrock, 3)
            if thisrock.mass <= 2:
                thisrock = rock_load_images(thisrock, 2)
            if thisrock.mass <= 1:
                thisrock = rock_load_images(thisrock, 1)
            if thisrock.mass <= 0:
                del rocklist[rock_count]
                break

        rock_burn_center = thisrock.burnrect.center
        rock_travel_dir = math.degrees(math.atan2(thisrock.speed_h, thisrock.speed_v))
        thisrock.burnnew = pygame.transform.rotate(thisrock.burn_image, rock_travel_dir) #get dir from movement
        #thisrock.burnrect = thisrock.burnnew.get_rect(center=thisrock.burnrect.center)
        #thisrock.burnrect.centerx = thisrock.rect.centerx-(thisrock.rect.width/2) #center burning on rock
        #thisrock.burnrect.centery = thisrock.rect.centery-(thisrock.rect.height/2)
        rock_count += 1

    if not base_out: basenew = pygame.transform.rotate(base, 0)
    habitatnew = pygame.transform.rotate(habitat, 0)
    if rescue.orient_mult == 1:
        rescue.new = pygame.transform.rotate(rescue.image_right, 0)
    else:
        rescue.new = pygame.transform.rotate(rescue.image_left, 0)

    if dir >= 360: dir -= 360
    if dir < 0: dir += 360
    
    for thisrock in rocklist:
        if thisrock.dir >= 360: thisrock.dir -= 360
        if thisrock.dir < 0: thisrock.dir += 360
        
    if key[pygame.K_UP]:
        if fuel >= 1:
            if options.nosound: thrust_channel.play(thrust_sound, -1)
            thrust = 1
            fuel -= 1
            dirscratch = abs(dir)
            rem = 0
            rem_result = 0
            dir_result = 0
            if dirscratch == 0:
                speed[1] -= 1
            
            if dirscratch > 0 and dirscratch < 90:
                rem = 90 - dirscratch
                rem_result = float(rem)/90
                dir_result = float(dir)/90
                speed[0] -= dir_result
                speed[1] -= rem_result

            if dirscratch == 90:
                speed[0] -= 1
            
            if dirscratch > 90 and dirscratch < 180:
                dir_calc = dirscratch - 90
                rem = 90 - dir_calc
                rem_result = float(rem)/90
                dir_result = float(dir_calc)/90
                speed[0] -= rem_result
                speed[1] += dir_result
                
            if dirscratch == 180:
                speed[1] += 1
            
            if dirscratch > 180 and dirscratch < 270:
                dir_calc = dirscratch - 180
                rem = 90 - dir_calc
                rem_result = float(rem)/90
                dir_result = float(dir_calc)/90
                speed[0] += dir_result
                speed[1] += rem_result    
            
            if dirscratch == 270:
                speed[0] += 1
            
            if dirscratch > 270:
                dir_calc = dirscratch - 270
                rem = 90 - dir_calc
                rem_result = float(rem)/90
                dir_result = float(dir_calc)/90
                speed[0] += rem_result
                speed[1] -= dir_result    
        else:
            if options.nosound: thrust_channel.stop()

    if key[pygame.K_DOWN]:
        if fuel >= 1:
            if options.nosound: thrust_channel.play(thrust_sound, -1)
            fuel -= 0.25
            dirscratch = abs(dir)
            rem = 0
            rem_result = 0
            dir_result = 0
            if dirscratch == 0:
                speed[1] += 0.25
            
            if dirscratch > 0 and dirscratch < 90:
                rem = 90 - dirscratch
                rem_result = float(rem)/90
                dir_result = float(dir)/90
                speed[0] += dir_result/4
                speed[1] += rem_result/4

            if dirscratch == 90:
                speed[0] += 0.25
            
            if dirscratch > 90 and dirscratch < 180:
                dir_calc = dirscratch - 90
                rem = 90 - dir_calc
                rem_result = float(rem)/90
                dir_result = float(dir_calc)/90
                speed[0] += rem_result/4
                speed[1] -= dir_result/4
                
            if dirscratch == 180:
                speed[1] -= 0.25
            
            if dirscratch > 180 and dirscratch < 270:
                dir_calc = dirscratch - 180
                rem = 90 - dir_calc
                rem_result = float(rem)/90
                dir_result = float(dir_calc)/90
                speed[0] -= dir_result/4
                speed[1] -= rem_result/4
            
            if dirscratch == 270:
                speed[0] -= 0.25
            
            if dirscratch > 270:
                dir_calc = dirscratch - 270
                rem = 90 - dir_calc
                rem_result = float(rem)/90
                dir_result = float(dir_calc)/90
                speed[0] -= rem_result/4
                speed[1] += dir_result/4
        else:
            if options.nosound: thrust_channel.stop()

    if landerrect.bottom > floor:
        impactspeed_v = speed[1]
        impactspeed_h = speed[0]
        speed[1] = 0
        speed[0] = 0
        landerrect.bottom = floor
        if (dir > 350 or dir < 10) and abs(impactspeed_h) < 2 and abs(impactspeed_v) < 5:            
            dir = 0                            
        else:
            if options.nosound: channel = crash_sound.play()
            landernew = pygame.transform.rotate(boom, dir)
            landerrect = landernew.get_rect(center=center)
            dead_text = big_font.render("CRASH!!!", 1, color)
            dead = 1

    if landerrect.bottom == floor and speed[0] == 0 and speed[1] == 0:
        on_floor = 1
        if abs(landerrect.centerx-habitatrect.centerx) <= 75:
            load_delay += 1
            if people_in_habitat > 0 and load_delay >= load_delay_max and people_in_lander < people_in_lander_limit:
                if options.nosound: channel = pickup_sound.play()
                people_in_habitat -= 1
                people_in_lander += 1
                load_delay = 0
                

    if landerrect.bottom > baserect.top and abs(landerrect.centerx-baserect.centerx) <= 16 and not on_base and not base_out:
        impactspeed_v = speed[1]
        impactspeed_h = speed[0]
        speed[1] = 0
        speed[0] = 0
        landerrect.bottom = baserect.top
        if (dir > 350 or dir < 10) and abs(impactspeed_h) < 2 and abs(impactspeed_v) < 5:            
            dir = 0 
        else:
            if options.nosound: channel = crash_sound.play()
            landernew = pygame.transform.rotate(boom, dir)
            landerrect = landernew.get_rect(center=center)
            dead_text = big_font.render("CRASH!!!", 1, color)
            dead = 1          

    if landerrect.bottom == baserect.top and speed[0] == 0 and speed[1] == 0 and not base_out:
        on_base = 1
        if fuel < 200: fuel += 1    
        if deflector < 500: deflector += 0.5

    if landerrect.bottom > rescue.rect.top and landerrect.top < rescue.rect.bottom and abs(landerrect.centerx-rescue.rect.centerx) <= 20 and rescue.out == 0:
        impactspeed_v = speed[1]
        impactspeed_h = speed[0]
        speed[1] = rescue.speed_v
        speed[0] = rescue.speed_h
        landerrect.bottom = rescue.rect.top
        if (dir > 350 or dir < 10) and abs(impactspeed_h) < 3 and abs(impactspeed_v) < 6:            
            dir = 0
        else:
            if options.nosound: channel = crash_sound.play()
            landernew = pygame.transform.rotate(boom, dir)
            landerrect = landernew.get_rect(center=center)
            dead_text = big_font.render("CRASH!!!", 1, color)
            dead = 1

    if landerrect.bottom == rescue.rect.top and speed[0] == rescue.speed_h and speed[1] == rescue.speed_v and rescue.out == 0:
        on_rescue = 1
        load_delay += 1
        if fuel < 200: fuel += 0.5    
        if deflector < 500: deflector += 0.25
        if people_in_lander > 0 and load_delay >= load_delay_max:
            if options.nosound: channel = dropoff_sound.play()
            people_in_lander -= 1
            people_in_rescue += 1
            score += 50
            load_delay = 0
    
    rock_count = 0
    for thisrock in rocklist:
        if thisrock.rect.centery > floor:
            if options.nosound: channel = crash_sound.play()
            thisrock.speed_h, thisrock.speed_v = (0, 0)
            thisrock.rect.centery = floor
            thisrock.spin = 0
            thisrock.centerhold = thisrock.rect.center
            thisrock.new = pygame.transform.rotate(thisrock.image_boom, thisrock.dir)
            thisrock.rect = thisrock.new.get_rect(center=thisrock.centerhold)
            kabam(thisrock.new, thisrock.rect)
            score += abs(thisrock.rect.centerx-habitatrect.centerx)
            del rocklist[rock_count]
        rock_count += 1
        
    if landerrect.bottom < floor - 5000:
        if rescue.out == 0:
            lost_text = big_font.render("LOST IN SPACE!!!", 1, color)
            lost = 1
        else:
            score += people_in_lander*100
            endlevel = 1


    for thisrock in rocklist:
        distance = math.sqrt(math.pow(abs(landerrect.centerx-thisrock.rect.centerx),2) + math.pow(abs(landerrect.centery-thisrock.rect.centery),2))
        if distance < deflector_range and deflect == 1:
            deflector -= deflect_rate * 10
            if deflector < 0: deflector = 0        
            kick = deflect_rate-(distance/50)
            rock_kick = kick/thisrock.mass
            lander_kick = kick*thisrock.mass/3
            if landerrect.centerx > thisrock.rect.centerx:
                if thisrock.speed_h > 0: thisrock.speed_h -= rock_kick
                speed[0] += abs(lander_kick-1)
            else:
                if thisrock.speed_h > 0: thisrock.speed_h += rock_kick
                speed[0] -= abs(lander_kick-1)
            if landerrect.centery > thisrock.rect.centery:
                if thisrock.speed_v > 0: thisrock.speed_v -= rock_kick
                speed[1] += abs(lander_kick-1)
            else:
                if thisrock.speed_v > 0: thisrock.speed_v += rock_kick
                speed[1] -= abs(lander_kick-1)

    if floor-landerrect.centery < deflector_range and deflect == 1:
        deflector -= deflect_rate * 10
        if deflector < 0: deflector = 0
        speed[1] -= abs(deflect_rate-1)

    for thisrock in rocklist:
        if landerrect.colliderect(thisrock.rect):
            if options.nosound: channel = crash_sound.play()
            landernew = pygame.transform.rotate(boom, dir)
            landerrect = landernew.get_rect(center=center)
            dead_text = big_font.render("CRASH!!!", 1, color)
            dead = 1

    rock_count = 0
    for thisrock in rocklist:
        if thisrock.rect.colliderect(habitatrect) and not habitat_out:
            if options.nosound: channel = crash_sound.play()
            thisrock.speed_h, thisrock.speed_v = (0, 0)
            thisrock.spin = 0
            thisrock.centerhold = thisrock.rect.center
            thisrock.new = pygame.transform.rotate(thisrock.image_boom, thisrock.dir)
            thisrock.rect = thisrock.new.get_rect(center=thisrock.centerhold) 
            kabam(thisrock.new, thisrock.rect)
            del rocklist[rock_count]
            habitatnew = pygame.transform.rotate(habitat_boom, 0)
            habitatrect = habitatnew.get_rect(center=habitatrect.center)
            habitatrect.bottom = floor
            if people_in_rescue+people_in_lander == 0:
                destroyed = 1
            else:
                people_in_habitat = 0
                habitat_out = 1
        rock_count += 1

    if landerrect.colliderect(habitatrect) and not habitat_out:
        if options.nosound: channel = crash_sound.play()
        landernew = pygame.transform.rotate(boom, dir)
        landerrect = landernew.get_rect(center=center)
        dead_text = big_font.render("CRASH!!!", 1, color)
        dead = 1
        habitatnew = pygame.transform.rotate(habitat_boom, 0)
        habitatrect = habitatnew.get_rect(center=habitatrect.center)
        habitatrect.bottom = floor
        if people_in_rescue+people_in_lander == 0:
            destroyed = 1
        people_in_habitat = 0
        habitat_out = 1

    if landerrect.colliderect(rescue.rect) and not rescue.out:
        if options.nosound: channel = crash_sound.play()
        landernew = pygame.transform.rotate(boom, dir)
        landerrect = landernew.get_rect(center=center)
        dead_text = big_font.render("CRASH!!!", 1, color)
        dead = 1
        if rescue.orient_mult == 1:
            rescue.new = pygame.transform.rotate(rescue.image_right_boom, 0)
        else:
            rescue.new = pygame.transform.rotate(rescue.image_left_boom, 0)
        rescue.rect = rescue.new.get_rect(center=rescue.rect.center)
        rescue.out = 1

    rock_count = 0
    for thisrock in rocklist:
        if thisrock.rect.colliderect(baserect) and not base_out:
            if options.nosound: channel = crash_sound.play()
            thisrock.speed_h, thisrock.speed_v = (0, 0)
            thisrock.spin = 0
            thisrock.centerhold = thisrock.rect.center
            thisrock.new = pygame.transform.rotate(thisrock.image_boom, thisrock.dir)
            thisrock.rect = thisrock.new.get_rect(center=thisrock.centerhold) 
            kabam(thisrock.new, thisrock.rect)
            time.sleep(0.25)
            del rocklist[rock_count]
            basenew = pygame.transform.rotate(base_boom, 0)
            baserect = basenew.get_rect(center=baserect.center)
            base_out = 1
            baserect.bottom = floor
            if on_base:
                if options.nosound: channel = crash_sound.play()
                landernew = pygame.transform.rotate(boom, dir)
                landerrect = landernew.get_rect(center=center)
                dead_text = big_font.render("CRASH!!!", 1, color)
                dead = 1
        rock_count += 1

    rock_count = 0
    for thisrock in rocklist:
        if thisrock.rect.colliderect(rescue.rect) and not rescue.out:
            if options.nosound: channel = crash_sound.play()
            thisrock.speed_h, thisrock.speed_v = (0, 0)
            thisrock.spin = 0
            thisrock.centerhold = thisrock.rect.center
            thisrock.new = pygame.transform.rotate(thisrock.image_boom, thisrock.dir)
            thisrock.rect = thisrock.new.get_rect(center=thisrock.centerhold) 
            kabam(thisrock.new, thisrock.rect)
            time.sleep(0.25)
            del rocklist[rock_count]
            if rescue.orient_mult == 1:
                rescue.new = pygame.transform.rotate(rescue.image_right_boom, 0)
            else:
                rescue.new = pygame.transform.rotate(rescue.image_left_boom, 0)
            rescue.rect = rescue.new.get_rect(center=rescue.rect.center)
            rescue.out = 1
            if on_rescue:
                if options.nosound: channel = crash_sound.play()
                landernew = pygame.transform.rotate(boom, dir)
                landerrect = landernew.get_rect(center=center)
                dead_text = big_font.render("CRASH!!!", 1, color)
                dead = 1
        rock_count += 1

    rock_a_counter = 0
    for thisrock in rocklist:
        rock_b_counter = 0
        for thatrock in rocklist:
            if thisrock.rect.colliderect(thatrock.rect) and not rock_a_counter==rock_b_counter:
                if options.nosound: channel = crash_sound.play()
                if thisrock.mass >= thatrock.mass:
                    thisrock.mass += thatrock.mass
                    del rocklist[rock_b_counter]
                    if thisrock.mass <= 3:
                        thisrock = rock_load_images(thisrock, 3)
                    if thisrock.mass <= 2:
                        thisrock = rock_load_images(thisrock, 2)
                    if thisrock.mass <= 1:
                        thisrock = rock_load_images(thisrock, 1)
                    thisrock.speed_h = thatrock.speed_h/5
                    thisrock.speed_v = thatrock.speed_v/5
                else:
                    thatrock.mass += thisrock.mass
                    del rocklist[rock_a_counter]
                    if thatrock.mass <= 3:
                        thatrock = rock_load_images(thatrock, 3)
                    if thatrock.mass <= 2:
                        thatrock = rock_load_images(thatrock, 2)
                    if thatrock.mass <= 1:
                        thatrock = rock_load_images(thatrock, 1)
                    thatrock.speed_h = thisrock.speed_h/5
                    thatrock.speed_v = thisrock.speed_v/5
            rock_b_counter += 1
        rock_a_counter += 1

    for thisrock in rocklist:
        thisrock.dir += thisrock.spin
        thisrock.centerhold = thisrock.rect.center
        thisrock.new = pygame.transform.rotate(thisrock.image, thisrock.dir)
        thisrock.rect = thisrock.new.get_rect(center=thisrock.centerhold)
        
    for thisrock in rocklist:        
        thisrock.rect.centerx = wrap(thisrock.rect.centerx, width)

    for thisrock in rocklist:
        if thisrock.rect.centery < floor:
            thisrock.speed_v = gravitize(thisrock.speed_v, floor, thisrock.rect.centery)

    #rescue evasive action
    if not rescue.out and rescue.rect.centery < 500 and rescue.entering:
        rescue.speed_v = 2
        if on_rescue: speed[1] = 2
    else:
        if len(rocklist) > 0:
            for thisrock in rocklist:
                if thisrock.rect.centery < rescue.rect.centery and abs(thisrock.rect.centerx-rescue.rect.centerx) < 400 and (floor-rescue.rect.centery) > 200 and abs(thisrock.rect.centery-rescue.rect.centery) < 400:
                    rescue.speed_v = 1
                    if thisrock.rect.centerx < rescue.rect.centerx:
                        rescue.speed_h = 2 * rescue.orient_mult
                        if on_rescue: speed[0] = 2 * rescue.orient_mult
                    else:
                        rescue_speed_v = 1 * rescue.orient_mult       
                        if on_rescue: speed[0] = 1 * rescue.orient_mult       
        else:
            rescue.speed_h = rescue.orig_speed_h
            if on_rescue: speed[0] = rescue.orig_speed_h
        if floor-rescue.rect.centery < 400:
            rescue.speed_v = -1
            if on_rescue: speed[1] = -1
        else:
            rescue.speed_v = 0
            if on_rescue: speed[1] = 0


    #wrap
    landerrect.centerx = wrap(landerrect.centerx, width)
    rescue.rect.centerx = wrap(rescue.rect.centerx, width)
    

    if landerrect.bottom < floor and not on_base and not on_rescue:
        speed[1] = gravitize(speed[1], floor, landerrect.centery)
            
      
    landerrect = landerrect.move(speed)
    for thisrock in rocklist: 
        thisrock.rect = thisrock.rect.move([thisrock.speed_h, thisrock.speed_v])
    if not rescue.out: rescue.rect = rescue.rect.move([rescue.speed_h, rescue.speed_v])

    if rescue.entering and rescue.rect.centery >= 500:
        rescue.entering = 0

    if rescue.out == 1: people_in_rescue = 0

    fuel_text = font.render("Fuel: " + str(fuel), 1, color) 
    vspeed_text = font.render("V: " + str(int(speed[1])), 1, color)
    hspeed_text = font.render("H: " + str(int(speed[0])), 1, color)
    altitude_text = font.render("Alt: " + str(floor-landerrect.bottom), 1, color)
    attitude_text = font.render("Att: " + str(abs(dir)), 1, color)
    deflector_text = font.render("Deflector: " + str(deflector), 1, color)    
    score_text = font.render("Score: " + str(score), 1, color)
    landers_text = font.render("Landers: " + str(landers), 1, color)
    people_text = font.render("People: Habitat: " + str(people_in_habitat) + " Lander: " + str(people_in_lander) + " Rescued: " + str(people_in_rescue), 1, color)
    level_text = font.render("Level: " + str(level), 1, color)
    screen.fill(black)
    floor_line = pygame.draw.line(screen, color, (0, floor), (width, floor), 1)
    for star in stars:
        star_circle = pygame.draw.circle(screen, color, star, 2, 2)
    for thisrock in rocklist: 
        screen.blit(thisrock.new, thisrock.rect)   
        if thisrock.burning:
            screen.blit(thisrock.burnnew, thisrock.rect)
    if base_out_count > 0 and base_out:
        base_out_count -= 1
    if base_out_count > 0: screen.blit(basenew, baserect)
    if rescue.out == 0: screen.blit(rescue.new, rescue.rect)
    if habitat_out_count > 0 and habitat_out:
        habitat_out_count -= 1
    if habitat_out_count > 0: screen.blit(habitatnew, habitatrect)
    if thrust:
        screen.blit(lander_thrustnew, landerrect)
    else:
        screen.blit(landernew, landerrect)
    if lander_burning: screen.blit(lander_burnnew, lander_burnrect)
    if deflect and deflector_range >= 1:
        deflector_line = pygame.draw.circle(screen, color, landerrect.center, int(deflector_range), 1)
    screen.blit(fuel_text, (10, infobar_h))
    screen.blit(vspeed_text, (90, infobar_h))
    screen.blit(hspeed_text, (140, infobar_h))
    screen.blit(altitude_text, (195, infobar_h))
    screen.blit(attitude_text, (270, infobar_h))
    screen.blit(deflector_text, (325, infobar_h))
    screen.blit(score_text, (450, infobar_h))
    screen.blit(landers_text, (550, infobar_h))
    screen.blit(people_text, (650, infobar_h))
    screen.blit(level_text, (925, infobar_h))
    if dead: screen.blit(dead_text, ((width/2)-125, (height/2)-150))
    if lost: screen.blit(lost_text, ((width/2)-200, (height/2)-150))
    pygame.display.flip()
    
    clock.tick(20)
    
    #regen rocks
    if rock_delay >= rock_delay_max:
        if len(rocklist) < level:
            if random.randrange(0, 100) > 42: rocklist = rock_init(rocklist, width, height)
            rock_delay = 0
    else: rock_delay += 1

    if random.randrange(0, 100) > 99: rocklist = rockburst(rocklist, width, height)

    # check if we lost a lander
    if dead:
        people_in_lander = 0
        if landers > 0:
            landers -= 1;
        else:
            endgame = 1
    
    # check if we ended the level
    if rescue.out == 0 and people_in_lander == 0 and ( people_in_habitat == 0 or habitat_out == 1 ) and people_in_rescue > 0:
        endlevel = 1

    if people_in_habitat + people_in_lander + people_in_rescue == 0:
        endgame = 1

    # check if we ended the game
    if landers <= 0 or lost or destroyed: endgame = 1

    if endgame == 1:
        #end the game
        if options.nosound: pygame.mixer.stop()
        scorefilename = os.path.join(os.path.expanduser('~' +  getpass.getuser()), '.iapetal_score')
        if not os.path.isfile(scorefilename):
            open(scorefilename, 'a').close()
        scorefile = open(scorefilename, 'r')
        oldscore = scorefile.readline()
        scorefile.close()
        if not oldscore: oldscore = 0
        if score > int(oldscore):
            scorefile = open(scorefilename, 'w')
            scorefile.write(str(score) + '\n') 
        destroyed_text = big_font.render("GAME OVER", 1, color)
        screen.blit(destroyed_text, ((width/2)-150, (height/2)-100))
        endscore_text = big_font.render(str(score), 1, color)
        screen.blit(endscore_text, ((width/2)-75, (height/2)-50))
        pygame.display.flip()
        time.sleep(1)
        #. . .and start a new game after a short break
        newgame_text = big_font.render("Play again (y/n)?", 1, color)
        screen.blit(newgame_text, ((width/2)-200, (height/2)))
        pygame.display.flip()
        time.sleep(2)
        quitloop = 0
        while quitloop == 0:
            for qevent in pygame.event.get():
                if qevent.type == pygame.KEYDOWN and qevent.key == pygame.K_n:
                    sys.exit()
                if qevent.type == pygame.KEYDOWN and qevent.key == pygame.K_y:
                    quitloop = 1
        score = 0
        landers = 3
        endgame = 0
        people_in_habitat = 16
        people_in_lander = 0
        people_in_rescue = 0
        level = 1
        rocklist = []
        habitat_out = 0
        base_out = 0
        habitat_out_count = 5
        stars = stars_init(stars, width, floor)
        dir, fuel, dead, lost, destroyed, deflector, landerrect, speed, rocklist, on_base, base_out, base_out_count, baserect, habitatrect, rescue, on_rescue = game_init(landerrect, rocklist, baserect, habitatrect, base_out, 1)
    else:
        # if not, move on
        if endlevel == 1:
            #new level block
            if options.nosound: pygame.mixer.stop()
            score += people_in_rescue * 100
            if not base_out:
                score += 500
            people_in_habitat = 16
            people_in_rescue = 0
            people_in_lander = 0
            habitat_out = 0
            habitat_out_count = 5
            rescue.out = 0
            base_out = 0
            level += 1
            rocklist = []
            time.sleep(1)
            dir, fuel, dead, lost, destroyed, deflector, landerrect, speed, rocklist, on_base, base_out, base_out_count, baserect, habitatrect, rescue, on_rescue = game_init(landerrect, rocklist, baserect, habitatrect, base_out, endlevel)        
            stars = stars_init(stars, width, floor)
            endlevel = 0
        if dead == 1:
            #spawn player, and level if appropriate
            time.sleep(1)
            dir, fuel, dead, lost, destroyed, deflector, landerrect, speed, rocklist, on_base, base_out, base_out_count, baserect, habitatrect, rescue, on_rescue = game_init(landerrect, rocklist, baserect, habitatrect, base_out, endlevel)        
        
