from __future__ import division
import pygame, math, sys, random, os, gc
from numpy import *

import pickle

import engine, ui, vect, physics, utils, simobject, constants
import grid, cell, resources, controls, datamanager, ai, nice_traces

#import cProfile

from pygame.locals import *

##try: 
##    import json
##except ImportError: 
##    try: import simplejson as json
##    except ImportError: print "JSON not imported"

try:
    import psyco
    psyco.full()
except ImportError:
    print "psyco not imported"

#os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (0,0)

class Game_Tactical(engine.Engine):
    
    def __init__(self):
        #gc.set_debug(gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS)
        engine.Engine.__init__(self)
        self.dm = datamanager.DataManager()
        
        self.set_clock_rate(constants.FPS)
        
        self.set_caption("Plague  --  Paused")
        
        #self.screen = pygame.display.set_mode((1440, 900), FULLSCREEN)
        os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (0,0)
        self.screen = pygame.display.set_mode(constants.SCREEN_PROP[0], constants.SCREEN_PROP[1])
        self.get_screen_dim()
        
        # sets up the screen within the world
        self.PPM = constants.PIXELS_PER_METER
        self.scale = 0.4*0.8
        self.screen_location = (15,20)
        self.zoom_position = self.screen_center
        ##self.screen_location = ui.world_loc(self, self.screen_center)
        self.zoom_factor = 1
        # find initial screen boundary for drawing
        ui.find_screen_bounds(self)
        self.mousemove = 0,0
        pygame.mouse.set_pos(self.screen_center)
        
        self.mouse_scroll = False
        
        self.draw_sprite_paths = False
        self.show_partitions = False
        
        """ sets up the world arena"""
        self.dimensions = constants.MAP_DIMENSIONS
        self.grid_size = constants.GRID_SIZE
        self.grid = grid.Grid(self.dimensions[0],self.dimensions[1], self.dimensions[0]/self.grid_size)
        
        """grid ,empty for now"""
        # grid size in meters
        self.linesy = []
        self.linesx = []
        
        """ load sounds and images """
        resources.load_resources(self)
        
        ''' adds the player avatar '''
        #self.player.location = 0,0
        self.player = None
        
        self.initialise_UI_text()

        self.file_loading = 0
        
        ui.scale_images(self)
        
        self.slow_precise_shadowing = True

        if self.grid_size == 5.0:
            ui.draw_grid_count(self)
  
        self.num_zom = 0
        self.num_hum = 0
        self.num_hives = 0
        
        
        self.Rocks = cell.Deposition(self, "concrete_block")
        self.Shrubs = cell.Deposition(self, "shrub")
        self.Atmosphere = cell.Atmosphere(self, "pressure")
        self.Shockwave = cell.Shockwave(self, "shockwave")
        self.Heat = cell.Heat(self, "heat")
        
        self.CA = set()
        self.CA.add(self.Atmosphere)
        self.CA.add(self.Shockwave)
        self.CA.add(self.Heat)
        self.CA_timer  = -0.01
        
        self.use_game_cursor()
        
        self.paused = False
        self.creating_map = False
        self.created_map = False
        
        self.temp_inputs = {}
        #self.timers = {}
        self.timers = set()
        
        self.TEST = False
    
    def use_game_cursor(self):
        pygame.mouse.set_visible(False)
        self.cursor = simobject.Image(self, ui.world_loc(self, pygame.mouse.get_pos()), "cursor_image")

    def update_timers(self):
        for timer in self.timers:
            timer.update()

    def initialise_UI_text(self):
        ''' adds HUD elements to provide game info to the player '''
        self.weapontext = {}
        for i in xrange(1,20):
            self.weapontext[i] = simobject.TextBox(self, (0, 20*i+20))
        
        self.grenadetext = {}
        for i in xrange(1,20):
            self.grenadetext[i] = simobject.TextBox(self, (self.screen_width-300, 20*i+20))
        
        self.avatartext = simobject.TextBox(self, (10, 0), color = (255,255,255))
        self.fpstext = simobject.TextBox(self, (10, self.screen_height-25), color = (255,255,255))

        self.winlosetext1 = simobject.TextBox(self, (self.screen_width/2, self.screen_height/2-50), "center", (255,255,255), 100)

        self.pausedtext = simobject.TextBox(self, (self.screen_width/2, self.screen_height/2), "center", (255,255,255), 30)
        self.buildleveltext = simobject.TextBox(self, (self.screen_width/2, self.screen_height/2+40), "center", (255,255,255), 20)
    
    def update_UI_text(self):
        self.update_game_text()
        self.update_avatar_text()
        self.update_grenade_text()
        self.update_weapon_text()
        self.update_winlose_text()
            
    def update_game_text(self):
        """ GAME TEXT (FPS, SCORE, ZOM, HUM) """
        if self.player:
            self.score = self.player.score           
            if self.player.health<self.player.max_health/4:
                self.avatartext.color = (255,0,0)
            else:
                self.avatartext.color = (255,255,255)
        else:
            self.score = 0
        self.fps = ui.showFPS(pygame.time.get_ticks(), self.clock.get_fps())
        self.fpstext.text = "FPS: %.1f       Score: %i       Humans: %i       Zombies: %i       Zombie Hives: %i" % \
        (self.fps, self.score, self.num_hum, self.num_zom, self.num_hives)

    def update_avatar_text(self):
        """ AVATAR TEXT (HEALTH, AMMO, ETC) """
        if self.player and self.player.health > -1:
            self.avatartext.text = "Health: %i %%       Grenades: %i     Speed (km/h) %.1f" % \
            (self.player.health/self.player.max_health*100, self.player.grenade_ammo, self.player.speed*3.6)
        else:
            self.avatartext.text = ""
            
    def update_grenade_text(self):
        """ GRENADE TEXT """
        if self.player and self.player.health > -1:
            for key in self.player.grenades.keys():
                if key == self.player.grenade:
                    color = (255,0,0)
                else:
                    color = (255,255,255)
                self.grenadetext[self.player.grenades[key][0]].color = color
                self.grenadetext[self.player.grenades[key][0]].text = " %i: %s %i " % \
                (self.player.grenades[key][0], key, self.player.grenades[key][1])
        else:
            for i in range(1,20):
                self.grenadetext[i].text = ""
            
    def update_weapon_text(self):
        """ WEAPON TEXT """
        """ yes, i should make this code event driven as opposed to polling"""
        if self.player and self.player.health > -1:
            """ we blank the weapon first, in case the player has dropped one"""
            for i in range(1,20):
                self.weapontext[i].text = ""   
            
            """ we then add in the weapons the player is still holding"""
            for type in self.player.inv.list_types():
                item = self.player.inv.list_items(type)[0]
                if item.sim_cat is "weapon":
                    # perhaps update the ammo elsewhere? this works, but isnt the obvious place to do it
                    item.update_ammo()
                    if self.player.weapon:
                        if self.player.weapon.sim_type is item.sim_type:
                            color = (255,0,0)
                            reload = int(self.player.weapon.timer_reload.get()/self.player.weapon.reload_time*100)
                            if reload > 0:
                                reload_pcent = "Reloading "+str(reload)+" %"
                            else:
                                reload_pcent = ""
                        else:
                            color = (255,255,255)
                            reload_pcent = ""
                    else:
                        color = (255,255,255)
                        reload_pcent = ""
                    self.weapontext[item.weapon_num].color = color
                    self.weapontext[item.weapon_num].text = " %s: %s %i / %i  Ammo %i   %s" % \
                    (item.weapon_num, item.sim_type, item.clip_ammo, item.clip_size, item.ammo, reload_pcent)
        else: 
            for i in range(1,20):
                self.weapontext[i].text = ""
            
    def update_winlose_text(self):
        """ WIN LOSE TEXT """
        if self.num_zom == 0 or self.num_hum == 0:
            self.buildleveltext.text = "Press Return to start a new level, or Esc to go to the title screen"
            if self.num_zom == 0 and self.num_hum == 0:
                self.winlosetext1.text = ""
            elif self.num_zom == 0:
                self.winlosetext1.text = "Survivors win!"
            else:
                self.winlosetext1.text = "Horde wins!"

        else:
            self.winlosetext1.text = ""
            self.buildleveltext.text = ""
        
        if (not self.created_map) or self.creating_map:
            self.buildleveltext.text = "Creating Map"
        
    
    def pause_game(self):
        if self.paused:
            self.dt = 0
            self.pausedtext.text = "Plague paused: Press Spacebar to resume"
            self.buildleveltext.text = "Pressing Esc will to go to the title screen and cancel your game"
        else:
            self.pausedtext.text = ""

    def update_partitions(self):
        if self.created_map:
            if self.Partitions.check_run():
                self.Partitions.find_new_values(lambda cell: cell.CA.new_cells[cell.grid_ref].value != cell.check_value)
                self.Partitions.find_max_partition()
                self.buildleveltext.text = "Finding Partitions"
        self.draw_partitions()

    def draw_partitions(self):
        if self.show_partitions:
            if self.created_map:
                self.Partitions.show_partitions()
                self.Partitions.show_active_cells()
                  
    def restart_level(self):
        if self.num_zom*self.num_hum == 0:
            created = False
            if self.creating_map and self.created_map:
                self.creating_map = False
                self.created_map = False
                
                if self.player and self.player.health >= 0:
                    score_continue = self.player.score
                else:
                    score_continue = 0

                self.buildleveltext.text = ""
                
                print "removing sims"
                for sprite in self.spriteGroups[-1]:
                    sprite.remove_sim()
                
                self.num_zom = 0
                self.num_hum = 0
                self.num_hives = 0
                    
                print "restarting CA"
                self.Atmosphere.initialise_cells()
                self.Heat.initialise_cells()
                self.Rocks.turn = 0
                self.Shrubs.turn = 0

                created = True

                if self.player:
                    self.player.score = score_continue
                
            if pygame.key.get_pressed()[pygame.K_RETURN] and (self.num_zom == 0 or self.num_hum == 0) and not created:
                self.creating_map = True
            
            if not self.created_map:
                self.creating_map = True
  
    def make_level(self):
        pass

    def add_item_to_partition(self, partition, sim_type):
        count = 0
        max_count = 1000
        while True:
            for ref in partition:
                sim = self.add_sim_partition_square(partition, ref, sim_type)
                count +=1
                if sim:
                    break
                if count > max_count:
                    break
                
            break

    def add_sim_partition_square(self, partition, ref, sim_type):
        if ref in partition:
            square = self.grid.squares[ref]
            if len(square.sims)==0:
                location = square.location
                sim = self.add_sim(sim_type, location)
                return sim
            
    def top_up_shrubs(self, num, set):
        shrubs = 0
        for item in self.spriteGroups[-1]:
            if item.sim_type == "shrub":
                shrubs +=1
        while shrubs < num:
            self.add_item_to_partition(set, "shrub")
            shrubs+=1     
             
    def top_up_pickups(self, num, set):
        ammo = 0
        medkits = 0
        for item in self.spriteGroups[-1]:
            if item.sim_type == "ammo":
                ammo +=1
            elif item.sim_type == "medkit":
                medkits +=1
        while ammo < num:
            self.add_item_to_partition(set, "ammo")
            ammo+=1
        while medkits < num:
            self.add_item_to_partition(set, "medkit")
            medkits+=1

    def top_up_zombie_hives(self, max_count, set):
        count = 0
        sim_type = "zombie_hive"
        while count < max_count:
            sim = self.add_item_to_partition(set, sim_type)
            count +=1
                          
    def top_up_survivors(self,max_count, set):
        count = 1
        sim_type = "survivor"
        while True:
            for ref in set:
                square = self.grid.squares[ref]
                if not square.blocked:
                    player = self.add_player(square.location)
                    location = square.location
                    if player:
                        break
            break
        count = 1
        length = 5
        stopcount = 0
        while count < max_count and stopcount < 1000:
            offset = random.uniform(-length,length),random.uniform(-length,length)
            new_location = location[0]+offset[0], location[1]+offset[1]
            sim = self.add_sim(sim_type, new_location)
            if sim:
                count  +=1
            stopcount  +=1
            #0 stopcount, sim_type             

    def add_pickup(self, location):
        if random.randint(0,1):
            sim_type = "ammo"
        else:
            sim_type = "medkit"
        self.add_sim(sim_type, location, sim_cat = "pickup")
    
    def add_weapon(self, location):
        weapon_dict = {}
        weapon_dict[30] = "Pistol"
        weapon_dict[50] = "SMG"
        weapon_dict[70] = "AssaultR"
        weapon_dict[90] = "Shotgun"
        weapon_dict[97] = "SniperR"
        weapon_dict[98] = "LaserR"
        weapon_dict[99] = "GaussR"
        weapon_dict[100] = "MiniGun"
        
        maxkey = max(weapon_dict.keys())
        listkeys = weapon_dict.keys()
        listkeys.sort()
        
        highest = maxkey
        num = random.randint(1,maxkey)
        for key in listkeys:
            if num < key and key <= highest:
                highest = key
        sim_type = weapon_dict[highest]
        self.add_sim(sim_type, location, sim_cat = "weapon")
    
    def top_up_weapons(self, number, set):
        ##we first set up a weapons dictionary with associated probabilities
        weapon_dict = {}
        weapon_dict[30] = "Pistol"
        weapon_dict[50] = "SMG"
        weapon_dict[70] = "AssaultR"
        weapon_dict[90] = "Shotgun"
        weapon_dict[97] = "SniperR"
        weapon_dict[98] = "LaserR"
        weapon_dict[99] = "GaussR"
        weapon_dict[100] = "MiniGun"
        
        maxkey = max(weapon_dict.keys())
        listkeys = weapon_dict.keys()
        listkeys.sort()

        ## we then add weapons until we have had enough
        print "started adding weapons"
        weapons = 0
        while weapons < number:
            highest = maxkey
            num = random.randint(1,maxkey)
            for key in listkeys:
                if num < key and key <= highest:
                    highest = key
            sim_type = weapon_dict[highest]
            self.add_item_to_partition(set, sim_type)
            weapons += 1
            #print sim_type, weapons

    def run_CA_sim(self):
        if self.CA_timer > 0: 
            self.make_level()
            self.update_partitions()
            for automata in self.CA:
                    automata.run_simulation()
            self.CA_timer = 0
        self.CA_timer += self.dt
        if self.paused:
            self.draw_partitions()
            for automata in self.CA:
                automata.force_update()

    def save_maplet(self):
##        try: json
##        except:print "json not imported"
##        else: 
            list = []
            for sprite in self.spriteGroups[-1]:
                """ we save immobile sprites first, as they should be loaded first (WHY? cannot remember)"""
                if not sprite.motive:
                    sprite_item = [sprite.sim_type, sprite.location, sprite.direction, sprite.speed, sprite.vel_dir, sprite.health, sprite.avatar]
                    list.append(sprite_item)

            for sprite in self.spriteGroups[-1]:
                if sprite.motive:
                    sprite_item = [sprite.sim_type, sprite.location, sprite.direction, sprite.speed, sprite.vel_dir, sprite.health, sprite.avatar]
                    list.append(sprite_item)

            file = open('./levels/maplet01.py','w')
            pickle.dump(list, file)
            #file.write(json.dumps(list))
            #file.close()       

    def load_maplet(self):
##        try: json
##        except:print "json not imported"
##        else: 
            """ loads maplet"""
            for sprite in self.spriteGroups[-1]:
                sprite.remove_sim()
            file = open('./levels/maplet01.py','r')
            #list = json.load(file)
            list = pickle.load(file)
            #file.close()
            self.file_loading = 1
            for spritedata in list:
                self.sprite_loader(spritedata)    

    def sprite_loader(self, spritedata):
        [Sim_type, Location, Direction, Speed, Vel_dir, Health, Avatar] = spritedata
        
        sim = self.dm.createInstance("sims", Sim_type, self, Sim_type, Location, Direction, Speed, Vel_dir, Health, Avatar)
        if sim:
            if sim.avatar:
                self.player = sim
                self.player.old_location = sim.location
        else:
            print "sprite_loader data:", Sim_type, self, Sim_type, Location, Direction, Speed, Vel_dir, Health, Avatar

    def events(self, event):
        """handle some player input - not really that good given how I accept input"""
        """ lets the mouse wheel control screen scrolling"""
        controls.check_player_commands(self, event)
        #ui.change_zoom(self, event)e

    def add_sim(self, sim_type, location, direction = 0, speed = 0, vel_dir = 0, health = None , avatar = False, sim_cat = None):
        if self.check_square_contents(location, sim_type, sim_cat):
            sim = self.dm.createInstance("sims", sim_type, self, sim_type, location, direction, speed, vel_dir, health, avatar)
        else: 
            sim = None
        return sim

    def check_square_contents(self, location, sim_type, sim_cat = None):
        x,y = location
        grid_location = ( int(x/self.grid.square_width), int(y/self.grid.square_height) )
        add = False
        if self.grid.check_grid_location_in_grid(grid_location):
            add = True
            square = self.grid.squares[grid_location]
            if square.blocked:
                add = False
            if square.opaque:
                if sim_cat == "block":
                    add = False
            if sim_cat == "biped":
                for sim in square.sims:
                    if sim.sim_cat == "biped":
                        add = False
            if sim_cat == "effect":
                add = True
        return add

    def delete_sprite(self, location, sim_type = None):
        x,y = location
        grid_location = ( int(x/self.grid.square_width), int(y/self.grid.square_height) )
        self.empty_square(grid_location, sim_type)

    def empty_square(self, grid_location, sim_type = None):
        for sim in self.grid.squares[grid_location].sims.copy():
            if sim.sim_type == sim_type or not sim_type:
                block = sim.block
                sim.remove_sim()
                if block:
                    try: self.Partitions
                    except: pass
                    else: self.Partitions.initialise_cell(grid_location)

    def add_player(self, location):
        
        if self.player == None or self.player.health < 0:
            sim = self.add_sim("survivor", location, avatar = True, sim_cat = "biped")
            self.player = sim
            if self.player:
                self.player.old_location = location
                ui.center_screen(self.player)
                return self.player
            else:
                return None

    def draw_overlay(self):
        """ it would be nice to place these on top of sim sprites, but under UI sprites... """
        pass

    def update(self):
        """ we fill the screen so that there is always an image """
        self.screen.fill((50,50,50))
        """ Game specific code here"""
        
        ui.screen_coord(self)
        self.update_UI_text()
        self.cursor.location = ui.world_loc(self, pygame.mouse.get_pos())
  
        """ this redraws the background image quickly in the new place"""
        self.background_position = ui.screen_pos(self, (0,self.dimensions[1]))
        self.screen.blit(self.images["background_image"].scaled_image, self.background_position)

        self.pause_game()
        self.update_timers()
        self.run_CA_sim()

        self.restart_level()

class Menu_Main(engine.Engine):
    def __init__(self):
        engine.Engine.__init__(self)
        self.setup_text()
        
    def setup_text(self):
                
        self.titletext1 = simobject.TextBox(self, (self.screen_width/2, 200), "center", (255,0,0), 220)
        self.titletext1.text = "Plague"
        self.titletext4 = simobject.TextBox(self, (self.screen_width/2, self.screen_height/2+40), "center", (255,255,255), 30)
        self.titletext4.text = "Press Enter to play, H for help, T for a tech demo, or Esc to quit"
        self.titletext2 = simobject.TextBox(self, (self.screen_width/2, self.screen_height/2+100), "center", (255,0,0), 30)
        self.titletext2.text = "http://plague-like.blogspot.com/"
        self.titletext3 = simobject.TextBox(self, (self.screen_width/2, self.screen_height/2+150), "center", (255,0,0), 30)
        self.titletext3.text = "Copyright Benedict Carter, 2008"

    def events(self, event):
        if event:
            if event.type == KEYDOWN:
                if event.key == K_RETURN:
                    self.continue_running = False
                    self.state = "play"
                if event.key == K_h:
                    self.continue_running = False
                    self.state = "instructions"
                if event.key == K_t:
                    self.continue_running = False
                    self.state = "tech" 
                if event.key == K_o:
                    self.continue_running = False
                    self.state = "test" 
        
class Menu_Instructions(engine.Engine):
    def __init__(self):
        engine.Engine.__init__(self)
        self.setup_text()

    def setup_text(self):

        instructions = [
        "PLAGUE BATTLE SCENARIO:",
        "",
        "You are a survivor in a Zombie Plague outbreak. In this scenario, you",
        "must survive by killing all the zombies and (purple) Zombie Hives.",
        "You can collect guns, ammo and health (pickups) by walking over them. You can", 
        "kill Zombies and Zombie Hives by shooting them, blowing them up or by setting ",
        "them on fire. You have some survivor allies with you who are also trying to ",
        "kill all the Zombies.",
        "",
        "Vision is based on (radius limited) line of sight, and is obscured by shrubs and rocks.",
        "This is why you cannot see much of the map when you start.",
        "All sims see in this way, although Survivors can see further than Zombies,",
        "Explosions are modelled so that they are channelled by rocks, making them much more",
        "deadly in confined spaces. Fire is modelled so that fire radiates heat, setting other",
        "objects alight. Everything in the map can be destroyed (apart from pickups), to allow you to",
        "make your own way in the world.",
        "",
        "Everything has inertia, so motion doesnt stop instantly.Use this to your advantage. ",
        "You cannot shoot while sprinting, and you run faster in the direction you are pointing",
        "",
        "CONTROLS:",
        "",
        "Movement: WSAD and left SHIFT to sprint",
        "Aiming: mouse movement OR IP",
        "Shoot gun: left mouse button OR left CTRL",
        "Throw grenade: right mouse button OR left ALT",
        "Zooming in and out: QE",
        "Free/lock camera: middle mouse ONLY",
        "Reload gun: R",
        "Change directly to weapon: 1-7",
        "Switch weapon up/down: OL or MOUSE WHEEL",
        "Change to grenade: 8-0",
        "",
        "This should be enough to get you started, read the Readme document for more info,",
        "there is a LOT more information in there.",
        "",
        "Press Esc to go back to the main menu"
        ]
        
        num_lines = len(instructions)
        for line_num in range(0,num_lines):
            temp_text = simobject.TextBox(self, (20, line_num*20+20), "topleft", (255,255,255), 20)
            temp_text.text = instructions[line_num]

class Game_Battle(Game_Tactical):
    def __init__(self):
        Game_Tactical.__init__(self)
        self.creating_map = False
        self.created_map = False
        #self.update_UI_text()
        self.scale = 1
        ui.scale_images(self)
        
    def update_UI_text(self):
        self.update_game_text()
        self.update_avatar_text()
        self.update_grenade_text()
        self.update_weapon_text()
        self.update_winlose_text()   

    def make_level(self):
        if self.creating_map:
            print "Making Map"
            while True:
                # Desposit Rocks
                a = 7
                b = 5
                prob = 0.32
                if self.Rocks.turn == 0:  
                    self.Rocks.initialise_cells()
                    self.Rocks.seed_map(prob)
                if self.Rocks.turn < a:
                    self.Rocks.find_new_values(lambda idx, val, check: check > 3)
                elif self.Rocks.turn < a+b: 
                    self.Rocks.find_new_values(lambda idx, val, check: check > 5 and val)
                elif self.Rocks.turn == a+b: 
                    self.Rocks.force_update()
                    self.Rocks.turn +=1
                    
                    print "Rocks done"
                    # create partitioned sets so we can place stuff
                    self.Partitions = cell.Partitions(self, "partitions")
                    while self.Partitions.check_run():
                        self.Partitions.find_new_values(lambda cell: cell.CA.new_cells[cell.grid_ref].value != cell.check_value)
                    self.Partitions.find_max_partition()
                    print "Sets done"
                    # Deposit shrubs
                    self.Shrubs.initialise_cells()
                    self.Shrubs.seed_map(0.05)
                    self.Shrubs.find_new_values(lambda idx, val, check: check > 1 and not self.grid.squares[idx].blocked)
                    self.Shrubs.find_new_values(lambda idx, val, check: check > 2 and not self.grid.squares[idx].blocked)
                    self.Shrubs.find_new_values(lambda idx, val, check: check > 3 and not self.grid.squares[idx].blocked)
                    self.Shrubs.force_update()
                    print "Shrubs done"
                    # Place stuff
                    self.top_up_zombie_hives(constants.NUM_HIVES, self.Partitions.max_partition)
                    print "zombies done"
                    self.top_up_survivors(constants.NUM_HUMANS, self.Partitions.max_partition)
                    print "survivors done"
                    self.top_up_weapons(constants.NUM_WEAPONS, self.Partitions.max_partition)
                    print "weapons done"
                    self.top_up_pickups(constants.NUM_PICKUPS, self.Partitions.max_partition)
                    print "pickups done"
                    print "Sims done"
                    self.created_map = True
                    self.creating_map = False
                    self.paused = True
                    break
                break

class Game_CA_Demo(Game_Tactical):
    def __init__(self):
        Game_Tactical.__init__(self)
        self.creating_map = False
        self.created_map = False
        self.show_partitions = True
  
    def make_level(self):
        if self.creating_map:
            while True:
                a = 4
                b = 1
                prob = 0.32
                if self.Rocks.turn == 0:
                    self.Rocks.initialise_cells()
                    self.Rocks.seed_map(prob)
                    self.Rocks.force_update()
                    self.buildleveltext.text = "Depositing Rocks"
                    break
                elif self.Rocks.turn < a:
                    self.Rocks.find_new_values(lambda idx, val, check: check > 3)
                    self.Rocks.force_update()
                    self.buildleveltext.text = "Depositing Rocks"
                    break
                elif self.Rocks.turn < a+b: 
                    self.Rocks.find_new_values(lambda idx, val, check: check > 4 and val)
                    self.Rocks.force_update()
                    self.buildleveltext.text = "Depositing Rocks"
                    break
                elif self.Rocks.turn == a+b: 
                    self.show_partitions = True
                    self.Partitions = cell.Partitions(self, "partitions")
                    self.buildleveltext.text = "Finding Partitions"
                    self.created_map = True
                    self.creating_map = False
                    self.Rocks.turn +=1
                    break
                break
        
        if self.created_map:
            if not self.Partitions.check_run():
                self.show_partitions = False
                
                if self.Shrubs.turn == 0:
                    self.Shrubs.initialise_cells()
                    self.Shrubs.seed_map(0.05) 
                    self.Shrubs.force_update()   
                    self.buildleveltext.text = "Growing Shrubs"
                elif self.Shrubs.turn == 1:
                    self.Shrubs.find_new_values(lambda idx, val, check: check > 0 and not self.grid.squares[idx].blocked)
                    self.Shrubs.force_update()
                    self.buildleveltext.text = "Growing Shrubs"
                elif self.Shrubs.turn == 2:
                    self.Shrubs.find_new_values(lambda idx, val, check: check > 2 and not self.grid.squares[idx].blocked)
                    self.Shrubs.force_update()
                    self.buildleveltext.text = "Growing Shrubs"
                elif self.Shrubs.turn == 3:
                    self.Shrubs.find_new_values(lambda idx, val, check: check > 4 and not self.grid.squares[idx].blocked)
                    self.Shrubs.force_update()   
                    self.buildleveltext.text = "Growing Shrubs" 
                elif self.Shrubs.turn == 4:
                    if len(self.Heat.cells)+len(self.Heat.new_cells)==0:
                        self.buildleveltext.text = "Try deleting some rocks with the delete key, or burn shrubs with right mouse"
                        self.show_partitions = True
                        self.TEST = True
                    else:
                        self.buildleveltext.text = "Burning Shrubs" 

class Game_Test(Game_Tactical):
    def __init__(self):
        Game_Tactical.__init__(self)
        self.creating_map = False
        self.created_map = False
        self.TEST = True

    def update_UI_text(self):
        self.update_game_text()
        self.update_avatar_text()
        self.update_grenade_text()
        self.update_weapon_text()
  
    def update(self):
        """ we fill the screen so that there is always an image """
        self.screen.fill((50,50,50))
        """ Game specific code here"""
        ui.screen_coord(self)
        self.update_UI_text()
        self.cursor.location = ui.world_loc(self, pygame.mouse.get_pos())
  
        """ this redraws the background image quickly in the new place"""
        self.background_position = ui.screen_pos(self, (0,self.dimensions[1]))
        self.screen.blit(self.images["background_image"].scaled_image, self.background_position)

        self.pause_game()
        self.update_timers()
        self.run_CA_sim()

        self.restart_level()

def load_instructions():
    instructions = Menu_Instructions()
    state = instructions.start()
    load_menu()

def load_battle():
    #if not self.game_battle:
    game_battle = Game_Battle()
        #state = self.game_battle.start()
    #else:
    state = game_battle.start()
    load_menu()

def load_tech():
    tech_demo = Game_CA_Demo()
    state = tech_demo.start()
    load_menu()
    
def load_test():
    test = Game_Test()
    state = test.start()
    load_menu()
    
def load_menu():
    #self.game_battle = None
    game_menu = Menu_Main()
    state = game_menu.start()  
    del game_menu 
    if state == "play":
        load_battle()
    elif state == "instructions":
        load_instructions()
    elif state == "tech":
        load_tech()
    elif state == "test":
        load_test()

if __name__ == "__main__":
    #cProfile.run('load_menu()', 'results')
    #states = ai.StateMachine()
    load_menu()
