def __init__(self,
              type_name,
              editor,
              sprites,
              name=None,
              factor=1.,
              relpos=(0, 0),
              build=True,
              new_type=True):
     self.stop_animation = float("inf")
     self.stop_animation_func = None
     self.set_animation_type("loop")
     self.animation_step = 0
     self.grayed = []
     self.highlights = {}
     self.sprites_ref = {}
     if sprites:
         imgs = []
         isprite = 0
         for key in SPRITES_KEYS:
             sprites_for_this_key, frame_type = sprites[key]
             imgs.extend(sprites_for_this_key)
             n = len(sprites_for_this_key)
             self.sprites_ref[key] = (isprite, n, frame_type)
             isprite += n
     else:
         imgs = [""]
     MapObject.__init__(self, editor, imgs, type_name, factor, relpos,
                        build, new_type)
     self.can_interact = True
     #
     self.max_dist = None
     self.attack_range = None
     self.shot_frequency = None
     self.help_range = None
     self.cost = None
     self.base_number = None
     self.material_cost = {}
     self.terrain_attack = {}
     self.object_defense = {}
     self.strength = None
     self.defense = None
     self.help_repair = None
     #
     self.race = None
     self.game = None
     #
     self.walk_img = {}
     self.set_frame_refresh_type(2)  #type fast
     self.vel = 0.07
     self.current_isprite = 0
     self.team = None
     self.footprint = None
     self.projectile1 = None  #projectile used in close battle
     self.is_grayed = False
     self.is_building = None
     self.id = Unit.unit_id
     Unit.unit_id += 1
Exemple #2
0
 def initialize_rivers(self):
     lm = self.lm
     img_fullsize = self.get_material_image("Shallow water")
     imgs = {}
     for dx in [-1,0,1]:
         for dy in[-1,0,1]:
             imgs = tm.build_tiles(img_fullsize, lm.cell_sizes,
                                             lm.nframes,
                                             dx*lm.nframes, dy*lm.nframes, #dx, dy
                                             sin=False)
             river_obj = MapObject(self, imgs[0], "river", 1.)
             river_obj.is_ground = True
             self.register_object_type(river_obj)
 def __init__(self, name, baserace, racetype, me, color="blue", team=None):
     self.name = name
     self.baserace = baserace
     self.racetype = racetype
     self.team = team
     #
     self.base_material_cost = std_material_cost.copy()
     self.dist_factor = std_distance_factor
     self.base_terrain_attack = {}
     self.base_object_defense = std_object_defense.copy()
     self.strength_factor = 1.
     self.defense_factor = 1.
     #
     self.unit_types = {}
     self.me = me
     self.color = color
     for unit_type in units_type_to_load:
         self.add_type(unit_type, "sprites/" + baserace + "_" + unit_type)
     imgs_flag = unit.get_unit_sprites("sprites/flag_idle.png", self.color)
     self.flag = MapObject(self.me,
                           imgs_flag,
                           self.name + " flag",
                           str_type="flag")
     self.flag.can_interact = True
     self.flag.max_relpos = [0.7, -0.1]
     self.flag.min_relpos = [0.7, -0.1]
     ##        self.flag.always_drawn_last = True
     self.unit_descr = std_unit_descr.copy()
Exemple #4
0
def from_file_units(f, me):
    """Load units and their logical content (names, properties, etc.)"""
    print("Loading units")
    n = pickle.load(f) #len(dynamic_objects)
    for i in range(n):
        coord = pickle.load(f) #coord
        a = {}
        for attr_name in MapObject.get_saved_attributes():
            a[attr_name] = pickle.load(f)
        #
        print("*** Loading unit", a["name"])
        print(a)
        obj = MapObject(me, fns=a["fns"], name=a["name"], factor=a["factor"],
                        relpos=a["relpos"], build=a["build"], new_type=a["new_type"])
        obj.set_frame_refresh_type(obj._refresh_frame_type)
        obj_added = me.add_unit(coord, obj, a["quantity"])
 def make_grayed(self):
     if not self.is_grayed:
         self.is_grayed = True
         self.hide = True
         imgs = self.get_race_unit().grayed
         obj = MapObject(self.game.me, imgs[self.game.me.zoom_level])
         obj.imgs_z_t = imgs
         obj = self.game.add_object(self.cell.coord, obj, 1)
         obj.set_frame_refresh_type(self._refresh_frame_type)
         obj.get_map_time = self.get_map_time
         obj.get_current_frame = obj._get_current_frame3
         obj.name = "*" + self.str_type
         obj.is_grayed = True
         self.game.gui.last_move = None
 def get_saved_attributes():
     return MapObject.get_saved_attributes() + ["team"]
 def build_imgs(self):
     MapObject.build_imgs(self)
     self.build_highlighted_idles()
     self.build_grayed_idles()
 def refresh_translation_animation(self):
     if self.animation_type == ANIM_LOOP:
         delta = MapObject.refresh_translation_animation(self)
         key = DELTA_TO_KEY[delta]
         self.set_sprite_type(key)
def add_random_river(me, layer, material_dict,
                    imgs,
                    costs_materials, costs_objects,
                    possible_materials, possible_objects,
                    min_length, max_length):
    """Computes and draw a random river."""
    print("     Building random river...")
    lm = me.lm
    md = material_dict
    #1) pick one random end
    if "shallow water" in md:
        cell_end = random.choice(md["shallow water"])
    elif "grass" in md:
        cell_end = random.choice(md["grass"])
    elif "snow" in md:
        cell_end = random.choice(md["snow"])
    else:
        return
    #2) pick one random source
    if "snow" in md:
        cell_source = random.choice(md["snow"])
    elif "thin snow" in md:
        cell_source = random.choice(md["thin snow"])
    elif "rock" in md:
        cell_source = random.choice(md["rock"])
    else:
        return
    #3) verify distance
    cell_source = lm.cells[cell_source[0]][cell_source[1]]
    cell_end = lm.cells[cell_end[0]][cell_end[1]]
    if min_length <=  cell_source.distance_to(cell_end) <= max_length:
        pass
    else:
        return
    sp = BranchAndBoundForMap(lm, cell_source, cell_end,
                            costs_materials, costs_objects,
                            possible_materials, possible_objects)
    path = sp.solve()
    #4) change the end to first shallow shore cell
    actual_path = []
    for cell in path:
        if cell.name == "river":
            break
        actual_path.append(cell)
        if "water" in cell.material.name.lower():
            break
        else:
            next_to_water = False
            for neigh in cell.get_neighbors_von_neuman():
                if neigh:
                    if "water" in neigh.material.name.lower():
                        next_to_water = True
                        break
            if next_to_water:
                break
    #
    objs = {}
    for delta in imgs: #imgs[(dx,dy)][zoom]
        river_obj = MapObject(me, imgs[delta][0], "river", 1.)
        river_obj.is_ground = True
        objs[delta] = river_obj
    #5) add river cells to map and layer
    for i,cell in enumerate(actual_path):
        dx,dy = get_path_orientation(i, cell, actual_path)
        c = objs.get((dx,dy))
        if not c:
            raise Exception("No river object for delta", dx, dy)
        assert cell.name != "river"
        c = c.add_copy_on_cell(cell)
        cell.name = "river"
        layer.static_objects.append(c)
    if path:
        print("RIVER BUILT:", [cell.coord for cell in path])
    return objs
    def add_static_objects(self, me):
        #1) We use another hmap to decide where we want trees (or any other object)
        S = len(me.hmap)
        self._forest_map = ng.generate_terrain(S, n_octaves=self.static_objects_n_octaves,
                                            persistance=self.static_objects_persistance,
                                            chunk=self.static_objects_chunk)
        ng.normalize(self._forest_map)
        #me.lm is a superimposed map on which we decide to blit some static objects:
        #3) We build the objects that we want.
        # its up to you to decide what should be the size of the object (3rd arg)
        tree = MapObject(me,self.tree,self.forest_text,self.tree_size)
        tree.max_relpos = [0., 0.]
        fir1 = MapObject(me,self.fir1,self.forest_text,self.fir1_size)
        fir1.max_relpos = [0., 0.]
        fir2 = MapObject(me,self.fir2,self.forest_text,self.fir2_size)
        fir2.max_relpos = [0., 0.]
        firsnow = MapObject(me,self.firsnow, self.forest_snow_text, self.firsnow_size)
        firsnow.max_relpos = [0., 0.]
        fir1.set_same_type([fir2, firsnow])
        palm = MapObject(me,self.palm,self.palm_text,self.palm_size)
        palm.max_relpos[0] = 0.1 #restrict because they are near to water
        palm.min_relpos[0] = -0.1
        bush = MapObject(me,self.bush,"bush",self.bush_size)
        village1 = MapObject(me,self.village1, "village",self.village1_size)
##        village2 = MapObject(me,self.village2, "village",self.village2_size)
##        village3 = MapObject(me,self.village3, "village",self.village3_size)
##        all_villages = [village1,village2,village3]
        all_villages = [village1]
        for v in all_villages:
            v.max_relpos = [0, 0.15]
            v.min_relpos = [0, 0.1]
        #
        cobble = MapObject(me,self.cobble,"cobblestone",self.cobble_size)
        cobble.is_ground = True
        self.cobblestone = cobble
        bridge_h = MapObject(me,self.bridge_h,"bridge",self.bridge_h_size,
                                str_type="bridge_h")
        bridge_h.is_ground = True
        bridge_h.max_relpos = [0., 0.]
        bridge_h.min_relpos = [0., 0.]
        bridge_v = MapObject(me,self.bridge_v,"bridge",self.bridge_v_size,
                                str_type="bridge_v")
        bridge_v.is_ground = True
        bridge_v.max_relpos = [0.,0.]
        bridge_v.min_relpos = [0., 0.]
        self.bridge_h_mapobject = bridge_h
        self.bridge_v_mapobject = bridge_v
        self._objects = {"oak":tree, "fir1":fir1, "fir2":fir2, "firsnow":firsnow,
                        "palm":palm, "bush":bush, "village":village1,
                        "cobble":cobble, "bridge_h":bridge_h, "bridge_v":bridge_v,
                        "road":cobble}
        #4) we add the objects via distributors, to add them randomly in a nice way
        #normal forest
##        print("LALA 1", tree.relpos, tree.max_relpos, tree.min_relpos)
        all_forest = [fir1, fir2, tree]
        distributor = objs.get_distributor(me, all_forest,
                                            self._forest_map, ["Grass","Rock"])
##        print("LALA 2", tree.relpos, tree.max_relpos, tree.min_relpos)
        for obj in distributor.objs:
            obj.max_relpos[1] *= self.forest_relposy_multiplier
##        print("LALA 3", tree.relpos, tree.max_relpos, tree.min_relpos)
##        tree.max_relpos = [0., -0.25] #!!!!!!!!!!!!!!!!!
##        tree.max_relpos = list(tree.min_relpos)
##        tree.randomize_relpos()
        distributor.max_density = self.forest_max_density
        distributor.homogeneity = self.forest_homogeneity
        distributor.zones_spread = self.forest_zones_spread
        distributor.distribute_objects(me.lm, exclusive=True) #here, relpos is randomized for each object distributed
        #more trees in plains
        distributor = objs.get_distributor(me, [tree], self._forest_map, ["Grass"])
        for obj in distributor.objs:
            obj.max_relpos[1] *= self.forest_relposy_multiplier
        distributor.max_density = self.forest_max_density
        distributor.homogeneity = self.forest_homogeneity
        distributor.zones_spread = self.forest_zones_spread
        distributor.distribute_objects(me.lm, exclusive=True)
        #snow forest
        distributor = objs.get_distributor(me, [firsnow, firsnow.flip()],
                                        self._forest_map, ["Thin snow","Snow"])
        for obj in distributor.objs:
            obj.max_relpos[1] *= self.forest_relposy_multiplier
        distributor.max_density = self.forest_snow_max_density
        distributor.homogeneity = self.forest_snow_homogeneity
        distributor.zones_spread = self.forest_snow_zones_spread
        distributor.distribute_objects(me.lm, exclusive=True)
        #palm forest
        distributor = objs.get_distributor(me, [palm, palm.flip()], self._forest_map, ["Sand"])
        for obj in distributor.objs:
            obj.max_relpos[1] *= self.forest_relposy_multiplier
        distributor.max_density = self.palm_max_density
        distributor.homogeneity = self.palm_homogeneity
        distributor.zones_spread = self.palm_zones_spread
        distributor.distribute_objects(me.lm, exclusive=True)
        #bushes
        distributor = objs.get_distributor(me, [bush], self._forest_map, ["Grass"])
        distributor.max_density = 2
        distributor.homogeneity = 0.2
        distributor.zones_spread = [(0., 0.05), (0.3,0.05), (0.6,0.05)]
        distributor.distribute_objects(me.lm)
        #villages
        distributor = objs.get_distributor(me, [village1, village1.flip()],
                            self._forest_map, ["Grass"], limit_relpos_y=False)
        distributor.max_density = 1
        distributor.homogeneity = self.village_homogeneity
        distributor.zones_spread = [(0.1, 0.02), (0.2,0.02), (0.4,0.02), (0.5,0.02)]
##        distributor.distribute_objects(me.lm, exclusive=True)
        village_mat = list(me.materials.keys())
        village_mat = [n for n in village_mat if not("water" in n.lower())]
        village_mat.remove("outside")
        objs.simple_distribution(me, [village1, village1.flip()], village_mat, 6)
        cobbles = [cobble, cobble.flip(True,False),
                    cobble.flip(False,True), cobble.flip(True,True)]
        ############################################################################
        #Here we show how to use the path finder for a given unit of the game
        #Actually, we use it here in order to build cobblestone roads on the map
        me.initialize_rivers()
        costs_materials_road = {name:1. for name in me.materials}
        costs_materials_road["Snow"] = 10. #unit is 10 times slower in snow
        costs_materials_road["Thin snow"] = 2. #twice slower on thin snow...
        costs_materials_road["Sand"] = 2.
##        for name in me.materials:
##            if "water" in name.lower():
##                costs_materials_road[name] = 10
        print("     COST SHALLOW WATER", costs_materials_road)
        river_type = me.object_types["river"]
        costs_objects_road = {bush.int_type: 2., #unit is 2 times slower in bushes
                                cobble.int_type: 0.9,
                                river_type:2.}
        #Materials allowed (here we allow water because we add bridges)
        possible_materials_road=list(me.materials)
        for name in me.materials:
            if "water" in name.lower():
                possible_materials_road.remove(name)
        possible_objects_road=[cobble.int_type, bush.int_type,
                                village1.int_type, river_type]
        ########################################################################
        #now we build a path for rivers, just like we did with roads.
        costs_materials_river = {name:1. for name in me.materials}
        #Materials allowed (here we allow water because we add bridges)
        possible_materials_river=list(me.materials)
        possible_objects_river=[]
        river_img = me.get_material_image("Shallow water")
        random.seed(self.seed_static_objects)
        n_roads = 0
        n_rivers = 0
        imgs_river = {}
        lm = me.lm
        for dx in [-1,0,1]:
            for dy in[-1,0,1]:
                imgs_river[(dx,dy)] = tm.build_tiles(river_img, lm.cell_sizes,
                                            lm.nframes,
                                            dx*lm.nframes, dy*lm.nframes, #dx, dy
                                            sin=False)
        self.imgs_river = imgs_river
        material_dict = get_materials_dict(lm)
        self.update_loading_bar("Finding paths for rivers and roads...",0.6)
        while n_roads < self.max_number_of_roads or n_rivers < self.max_number_of_rivers:
            if n_rivers < self.max_number_of_rivers:
                n_rivers += 1
                self.rivers = add_random_river(me, me.lm, material_dict, imgs_river,
                                    costs_materials_river,
                                    costs_objects_road,
                                    possible_materials_river,
                                    possible_objects_river,
                                    min_length=self.min_river_length,
                                    max_length=self.max_river_length)
            if n_roads < self.max_number_of_roads:
                n_roads += 1
                add_random_road(me.lm, me.lm, cobbles,
                                    (bridge_h,bridge_v),
                                    costs_materials_road,
                                    costs_objects_road,
                                    possible_materials_road,
                                    possible_objects_road,
                                    min_length=self.min_road_length,
                                    max_length=self.max_road_length)
Exemple #11
0
    def __init__(self, me):
        self.me = me
        me.game = self
        self.gui = None
        self.units = []
        self.t = 0
        self.days_left = -1  #set -1 for an infinite number of days
        self.days_elapsed = 1
        self.current_player = None
        self.players = None
        self.current_player_i = None
        self.need_refresh_ui_box = True
        #
        self.sounds = thorpy.SoundCollection()
        self.battle_ambiant_sounds = get_sounds("sounds/battle_ambiant",
                                                self.sounds)
        self.turn_page_sound = self.sounds.add("sounds/ui/turn_page.wav")[0]
        self.construction_sound = self.sounds.add(
            "sounds/ui/metal-clash.wav")[0]
        self.village_sound = self.sounds.add(
            "sounds/ui/leather_inventory.wav")[0]
        ##        self.coin_sound = self.sounds.add("sounds/ui/coin2.wav")[0]
        self.coin_sound = self.sounds.add("sounds/ui/sell_buy_item.wav")[0]
        self.flag_sound = self.sounds.add("sounds/hits/new_hits_5.wav")[0]
        self.start_battle_sound = self.sounds.add("sounds/start_battle.wav")[0]
        self.fire_extinguish_sound = self.sounds.add("sounds/psht.wav")[0]
        self.fire_sound = self.sounds.add("sounds/fire.wav")[0]
        self.deny_sound = self.sounds.add("sounds/ui/deny2.wav")[0]
        self.death_sounds = get_sounds("sounds/death/", self.sounds)
        self.hit_sounds = get_sounds("sounds/hits/", self.sounds)
        self.walk_sounds = get_sounds("sounds/footsteps/", self.sounds)
        self.outdoor_sound = self.sounds.add("sounds/atmosphere/nature.wav")[0]
        self.magic_attack_sounds = get_sounds("sounds/magic/attacks/",
                                              self.sounds)
        self.magic_explosion_sounds = get_sounds("sounds/magic/explosions/",
                                                 self.sounds)
        for s in self.death_sounds:
            s.set_volume(0.5)
        self.can_build = ["grass", "rock", "sand", "snow", "thin snow"]
        self.is_burnable = [
            "grass", "bridge_v", "bridge_h", "oak", "fir1", "fir2", "firsnow",
            "palm", "bush", "village", "flag", "forest", "flag", "windmill",
            "construction"
        ]
        self.burning = {
        }  #e.g. burning[(4,12):2] means 2 remaining turns to burn
        fire_imgs = get_sprite_frames("sprites/fire_idle.png")
        self.fire = MapObject(self.me, fire_imgs, "fire")
        self.fire.can_interact = True
        self.fire.min_relpos = [0, -0.4]
        self.fire_max_relpos = [0, -0.4]
        self.fire.relpos = [0, -0.4]
        self.bridge_v, self.bridge_h = None, None
        self.bridges = []
        #
        self.smokes_log = {}
        effects.initialize_smokegens()
        windmill_imgs = get_sprite_frames("sprites/windmill_idle.png")
        self.windmill = MapObject(me, windmill_imgs, "windmill")
        self.windmill.set_animation_speed("midslow")
        self.windmill.min_relpos = [0, -0.15]
        self.windmill.max_relpos = [0, -0.15]
        self.windmill.randomize_relpos()
        self.cobblestone = None
        self.road = None
        self.bridge_h = None
        self.bridge_v = None
        self.bridge = None

        #
        self.construction = MapObject(
            me, get_sprite_frames("sprites/construction.png"), "construction")
        self.construction.is_ground = True
        self.village = MapObject(
            me, get_sprite_frames("sprites/house.png", s="auto"), "village")
        self.buildable_objs = {
            "windmill": self.windmill,
            "village": self.village,
            "bridge_v": None,
            "bridge_h": None,
            "road": None
        }
        self.allowed_build_on = ["cobblestone"]
        self.constructions = {}
        self.construction_time = {
            "village": 4,
            "windmill": 6,
            "bridge": 6,
            "road": 2
        }
        self.construction_price = {
            "village": INCOME_PER_VILLAGE * 5,
            "windmill": INCOME_PER_WINDMILL * 5,
            "bridge": INCOME_PER_WINDMILL * 2,
            "road": INCOME_PER_VILLAGE // 4
        }
        self.construction_ground = {
            "village": True,
            "windmill": True,
            "bridge": False,
            "road": True
        }
        self.construction_flag = {
            "village": True,
            "windmill": True,
            "bridge": False,
            "road": False
        }
        self.capturing = []
Exemple #12
0
class Game:
    def __init__(self, me):
        self.me = me
        me.game = self
        self.gui = None
        self.units = []
        self.t = 0
        self.days_left = -1  #set -1 for an infinite number of days
        self.days_elapsed = 1
        self.current_player = None
        self.players = None
        self.current_player_i = None
        self.need_refresh_ui_box = True
        #
        self.sounds = thorpy.SoundCollection()
        self.battle_ambiant_sounds = get_sounds("sounds/battle_ambiant",
                                                self.sounds)
        self.turn_page_sound = self.sounds.add("sounds/ui/turn_page.wav")[0]
        self.construction_sound = self.sounds.add(
            "sounds/ui/metal-clash.wav")[0]
        self.village_sound = self.sounds.add(
            "sounds/ui/leather_inventory.wav")[0]
        ##        self.coin_sound = self.sounds.add("sounds/ui/coin2.wav")[0]
        self.coin_sound = self.sounds.add("sounds/ui/sell_buy_item.wav")[0]
        self.flag_sound = self.sounds.add("sounds/hits/new_hits_5.wav")[0]
        self.start_battle_sound = self.sounds.add("sounds/start_battle.wav")[0]
        self.fire_extinguish_sound = self.sounds.add("sounds/psht.wav")[0]
        self.fire_sound = self.sounds.add("sounds/fire.wav")[0]
        self.deny_sound = self.sounds.add("sounds/ui/deny2.wav")[0]
        self.death_sounds = get_sounds("sounds/death/", self.sounds)
        self.hit_sounds = get_sounds("sounds/hits/", self.sounds)
        self.walk_sounds = get_sounds("sounds/footsteps/", self.sounds)
        self.outdoor_sound = self.sounds.add("sounds/atmosphere/nature.wav")[0]
        self.magic_attack_sounds = get_sounds("sounds/magic/attacks/",
                                              self.sounds)
        self.magic_explosion_sounds = get_sounds("sounds/magic/explosions/",
                                                 self.sounds)
        for s in self.death_sounds:
            s.set_volume(0.5)
        self.can_build = ["grass", "rock", "sand", "snow", "thin snow"]
        self.is_burnable = [
            "grass", "bridge_v", "bridge_h", "oak", "fir1", "fir2", "firsnow",
            "palm", "bush", "village", "flag", "forest", "flag", "windmill",
            "construction"
        ]
        self.burning = {
        }  #e.g. burning[(4,12):2] means 2 remaining turns to burn
        fire_imgs = get_sprite_frames("sprites/fire_idle.png")
        self.fire = MapObject(self.me, fire_imgs, "fire")
        self.fire.can_interact = True
        self.fire.min_relpos = [0, -0.4]
        self.fire_max_relpos = [0, -0.4]
        self.fire.relpos = [0, -0.4]
        self.bridge_v, self.bridge_h = None, None
        self.bridges = []
        #
        self.smokes_log = {}
        effects.initialize_smokegens()
        windmill_imgs = get_sprite_frames("sprites/windmill_idle.png")
        self.windmill = MapObject(me, windmill_imgs, "windmill")
        self.windmill.set_animation_speed("midslow")
        self.windmill.min_relpos = [0, -0.15]
        self.windmill.max_relpos = [0, -0.15]
        self.windmill.randomize_relpos()
        self.cobblestone = None
        self.road = None
        self.bridge_h = None
        self.bridge_v = None
        self.bridge = None

        #
        self.construction = MapObject(
            me, get_sprite_frames("sprites/construction.png"), "construction")
        self.construction.is_ground = True
        self.village = MapObject(
            me, get_sprite_frames("sprites/house.png", s="auto"), "village")
        self.buildable_objs = {
            "windmill": self.windmill,
            "village": self.village,
            "bridge_v": None,
            "bridge_h": None,
            "road": None
        }
        self.allowed_build_on = ["cobblestone"]
        self.constructions = {}
        self.construction_time = {
            "village": 4,
            "windmill": 6,
            "bridge": 6,
            "road": 2
        }
        self.construction_price = {
            "village": INCOME_PER_VILLAGE * 5,
            "windmill": INCOME_PER_WINDMILL * 5,
            "bridge": INCOME_PER_WINDMILL * 2,
            "road": INCOME_PER_VILLAGE // 4
        }
        self.construction_ground = {
            "village": True,
            "windmill": True,
            "bridge": False,
            "road": True
        }
        self.construction_flag = {
            "village": True,
            "windmill": True,
            "bridge": False,
            "road": False
        }
        self.capturing = []

    def set_ambiant_sounds(self, val):
        if val:
            self.outdoor_sound.play(-1)
            if self.burning:
                self.fire_sound.play(-1)
        else:
            self.outdoor_sound.stop()
            if self.burning:
                self.fire_sound.stop()

    def add_construction(self, coord, str_type, unit):
        #for the moment, all races and units take the same construction time
        self.constructions[coord] = (str_type,
                                     self.construction_time[str_type], unit)
        self.construction_sound.play()
        obj = self.add_object(coord, self.construction)
        obj.name = str_type

    def add_bridge(self, coord):
        assert not coord in self.bridges
        ##        bridge = self.find_right_bridge(coord)
        ##        bridge = self.bridge_h
        left = self.get_object("river", (coord[0] - 1, coord[1]))
        right = self.get_object("river", (coord[0] - 1, coord[1]))
        if left and right:
            bridge = self.bridge_v
        else:
            bridge = self.bridge_h
        self.add_object(coord, bridge)
        self.bridges.append(coord)

##    def refresh_captures(self):
##        to_remove = []
##        for i in range(len(self.capturing)):
##            u, what, time_left = self.capturing[i]
##            u.make_grayed()
##            self.gui.has_moved.append(u)
##            time_left -= 1
##            self.capturing[i] = u, what, time_left
##            if time_left == 0:
##                to_remove.append(i)
##                self.set_flag(u.cell.coord,
##                              u.race.flag,
##                              u.team,
##                              sound=True)
##                self.refresh_village_gui()
##        for i in to_remove[::-1]:
##            self.capturing.pop(i)

    def refresh_constructions(self):
        to_remove = []
        for coord in self.constructions:
            str_type, time_left, unit = self.constructions[coord]
            ##            unit.make_grayed()
            ##            self.gui.has_moved.append(unit)
            if unit:
                time_left -= 1
            self.constructions[coord] = str_type, time_left, unit
            if time_left <= 0:
                self.construction_sound.play_next_channel()
                self.get_object("construction", coord).remove_from_map(self.me)
                if str_type == "bridge":
                    self.add_bridge(coord)
                else:
                    self.add_object(coord, self.buildable_objs[str_type])
                    if self.construction_flag[str_type]:
                        self.set_flag(coord, self.current_player.race.flag,
                                      self.current_player.team)
                to_remove.append(coord)
                unit.is_building = False
        for coord in to_remove:
            self.constructions.pop(coord)
        self.refresh_village_gui()

    def add_smoke(self, type_, coord, delta=None, what=""):
        if type_ == "small":
            sg = effects.smokegen_small
        else:
            sg = effects.smokegen_large
        smoke = effects.GameSmoke(self.me.cam, sg, coord, delta)
        self.smokes_log[coord] = smoke

    def remove_smoke(self, coord):
        return self.smokes_log.pop(coord, None)

    def refresh_smokes(self):
        effects.refresh_smokes(self)

    def recompute_smokes_position(self):
        for s in self.smokes_log.values():
            s.refresh_pos()

    def extinguish(self, coord, natural_end=False):
        self.remove_fire(coord)
        if not self.burning:
            self.fire_sound.stop()
        if natural_end:  #then the burnable objects are removed
            objs = self.get_cell_at(coord[0], coord[1]).objects  #ok
            to_burn = [o for o in objs if o.str_type in self.is_burnable]
            for o in to_burn:
                self.fire_extinguish_sound.play_next_channel()
                o.remove_from_map(self.me)
                effects.draw_ashes(self, o)
                if o.str_type == "construction":
                    u = self.constructions[o.cell.coord][2]
                    if u:
                        u.is_building = None
                    self.constructions.pop(o.cell.coord)
                if o.name == "bridge":
                    self.bridges.remove(o.cell.coord)

    def set_players(self, players, current=0):
        self.players = players
        self.current_player = self.players[current]
        self.current_player_i = current
        for p in players:
            for u in p.race.unit_types.values():
                p.team = p.race.team

    def get_players_from_team(self, team):
        return [p for p in self.players if p.team == team]

    def update_fire_logic(self):
        to_extinguish = []
        for coord in self.burning:
            self.burning[coord] -= 1
            if self.burning[coord] == 0:
                to_extinguish.append(coord)
            elif self.burning[coord] == 2:
                self.add_smoke("small", coord, (0, -0.3), "fire")
            elif self.burning[coord] == 1:
                self.remove_smoke(coord)
                self.add_smoke("large", coord, (0, -0.3), "fire")
        for coord in to_extinguish:
            self.extinguish(coord, natural_end=True)

    def refresh_village_gui(self):
        nvillages = len(
            self.get_objects_of_team(self.current_player.team, "village"))
        nwindmills = len(
            self.get_objects_of_team(self.current_player.team, "windmill"))
        self.gui.e_pop_txt.set_text(str(nvillages))
        self.gui.e_windmill_txt.set_text(str(nwindmills))

    def remove_all_grayed(self):
        to_remove = []
        for o in self.me.dynamic_objects:
            print(o, o.str_type)
            if o.name[0] == "*":
                to_remove.append(o)
        for o in to_remove:
            o.remove_from_map(self.me)

    def end_turn(self):
        self.gui.clear()
        self.remove_all_grayed()
        self.need_refresh_ui_box = True
        self.update_fire_logic()
        self.current_player_i += 1
        self.current_player_i %= len(self.players)
        self.current_player = self.players[self.current_player_i]
        self.refresh_village_gui()
        for u in self.units:
            u.is_grayed = False
            u.hide = False
        if self.current_player_i == 0:
            self.days_elapsed += 1
            self.current_player_i = 0
            #process other things to reinitialize each turn:
            ...
            if self.days_left == 1:
                #end game
                ...
            elif self.days_left > 1:
                self.days_left -= 1
        self.gui.has_moved = []
        #
        from_ = self.current_player.money
        self.refresh_village_gui()
        self.update_player_income(self.current_player)
        self.gui.show_animation_income(from_, self.current_player.money)
        self.gui.e_gold_txt.set_text(str(self.current_player.money))
        self.refresh_constructions()
##        self.refresh_captures()

    def func_reac_time(self):
        self.gui.refresh()
        self.me.func_reac_time()
        self.t += 1
        pygame.display.flip()
##        if self.t%100 == 0:
##            self.check_integrity()

    def update_loading_bar(self, text, progress):
        self.map_initializer.update_loading_bar(text, progress)

    def build_map(self, map_initializer, fast, use_beach_tiler, load_tilers):
        map_initializer.build_map(self.me, fast, use_beach_tiler, load_tilers)
        self.map_initializer = map_initializer
        self.me.build_objects_dict()
        self.collect_path_objects(map_initializer)
        self.add_structures()
        thorpy.add_time_reaction(self.me.e_box, self.func_reac_time)

    def add_structures(self):
        windmill_probability = 0.05
        can_windmill = [
            n.lower() for n in self.me.materials if not ("water") in n.lower()
        ]
        neighs = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0),
                  (1, 1)]
        gnx, gny = self.get_map_size()
        race1 = self.players[0].race
        race2 = self.players[1].race
        for obj in self.get_all_objects_by_name("bridge"):
            self.bridges.append(obj.cell.coord)
        villages = list(self.get_all_objects_by_str_type("village"))
        idx = random.randint(0, 1)
        villages.sort(key=lambda x: x.cell.coord[idx])
        villages_1 = villages[0:len(villages) // 3]
        villages_2 = villages[(2 * len(villages)) // 3:]
        for obj in villages:  #add flag to villages and add windmills
            cx, cy = obj.cell.coord
            race = None
            if obj in villages_1:
                race = race1
            elif obj in villages_2:
                race = race2
            if race:
                self.set_flag(obj.cell.coord, race.flag, race.team)
            for x, y in neighs:
                coord = cx + x, cy + y
                cell = self.get_cell_at(coord[0], coord[1])
                if cell:
                    if not cell.objects:
                        if cell.material.name.lower() in can_windmill:
                            if random.random() < windmill_probability:
                                self.add_object(coord, self.windmill, 1)
                                if race:
                                    self.set_flag(coord, race.flag, race.team)

    def collect_path_objects(self, map_initializer):
        self.cobblestone = map_initializer.cobblestone
        self.bridge_h = map_initializer.bridge_h_mapobject
        self.bridge_v = map_initializer.bridge_v_mapobject
        assert self.cobblestone
        assert self.bridge_h
        assert self.bridge_v
        self.bridge = self.bridge_h
        self.road = self.cobblestone
        self.buildable_objs["road"] = self.cobblestone
        self.buildable_objs["bridge_v"] = self.bridge_v
        self.buildable_objs["bridge_h"] = self.bridge_h

    def add_unit(self, coord, unit, quantity):
        u = self.me.add_unit(coord, unit, quantity)
        u.team = u.race.team
        u.game = self
        self.units.append(u)
        return u

    def add_object(self, coord, obj, quantity=1, rand_relpos=False):
        o = self.me.add_dynamic_object(coord, obj, quantity)
        o.game = self
        if rand_relpos:
            o.randomize_relpos()
        return o

    def get_cell_at(self, x, y):
        return self.me.lm.get_cell_at(x, y)

    def get_unit_at(self, x, y):
        cell = self.get_cell_at(x, y)
        if cell:
            return cell.unit

    def remove_flag(self, coord, sound=False):
        flag = self.get_object("flag", coord)
        if flag:
            flag.remove_from_map(self.me)
            if sound:
                self.flag_sound.play()
            return flag

    def set_flag(self, coord, flag_template, team, sound=False):
        self.remove_flag(coord, sound=False)
        if sound:
            self.flag_sound.play()
        cell = self.get_cell_at(coord[0], coord[1])
        ##        o = self.add_obj_before_other_if_needed(flag_template,
        ##                                                 1, ["village"], cell)
        o = self.add_object(cell.coord, flag_template, 1, True)
        o.team = team

    def remove_fire(self, coord):
        if coord in self.burning:
            self.burning.pop(coord)
            fire = self.get_object("fire", coord)
            fire.remove_from_map(self.me)
        self.remove_smoke(coord)

    def set_fire(self, coord, n):
        #1. remove old fire if necessary
        self.remove_fire(coord)
        #2. add new fire
        if n > 0:
            self.fire_sound.play(-1)
            cell = self.get_cell_at(coord[0], coord[1])
            self.burning[coord] = n
            names = ("village", "forest", "windmill")
            self.add_obj_before_other_if_needed(self.fire, 1, names, cell)

    def add_obj_before_other_if_needed(self, obj, qty, other_names, cell):
        has_other = False
        for o in cell.objects:  #ok
            for n in other_names:
                if o.name == n:
                    has_other = True
                    s = self.me.lm.get_current_cell_size()
                    im2, r2 = o.get_current_img_and_rect(s)
                    cell_rect = o.get_current_cell_rect(s)
                    obj.cell = cell
                    obj_rect = obj.get_current_img().get_rect()
                    obj_rect.bottom = r2.bottom + 1
                    obj.cell = None
                    #pos = centercell + relpos*s
                    #<==> relpos = (pos - centercell)/s
                    relpos = (obj_rect.centery - cell_rect.centery) / s
                    obj.min_relpos = [0, relpos]
                    obj.max_relpos = [0, relpos]
                    break
        o = self.add_object(cell.coord, obj, qty, has_other)
        return o

    def get_interactive_objects(self, x, y):
        return [o for o in self.get_cell_at(x, y).objects if o.can_interact]

    def get_all_objects_by_name(self, name):
        objs = []
        for x in range(self.me.lm.nx):
            for y in range(self.me.lm.ny):
                cell = self.get_cell_at(x, y)
                for o in cell.objects:  #ok
                    if o.name == name:
                        objs.append(o)
        return objs

    def get_all_objects_by_str_type(self, str_type):
        d = self.me.objects_dict.get(str_type)
        if d:
            return d.values()
        return []

    def get_map_size(self):
        return self.me.lm.nx, self.me.lm.ny

    def center_cam_on_cell(self, coord):
        """To actually see the result, first draw the map, then display()"""
        self.me.cam.center_on_cell(coord)
        self.recompute_smokes_position()

    def get_objects_of_team(self, team, str_type):
        objs = []
        if "flag" in self.me.objects_dict:
            for o in self.me.objects_dict["flag"].values():
                if o.team == team:
                    obj = self.get_object(str_type, o.cell.coord)
                    if obj:
                        objs.append(obj)
        return objs

    def update_player_income(self, p):
        p.money += self.compute_player_income(p)

    def compute_player_income(self, p):
        #1. villages
        v = len(self.get_objects_of_team(p.team, "village"))
        income = int(v * INCOME_PER_VILLAGE * p.tax)
        #2. windmills
        w = len(self.get_objects_of_team(p.team, "windmill"))
        income += int(w * INCOME_PER_WINDMILL)
        return income

    def get_units_of_player(self, p):
        for u in self.units:
            if u.team == p.team:
                yield u

    def get_object(self, str_type, coord):
        return self.me.get_object(str_type, coord)

    def check_integrity(self):
        o1 = self.me.lm.static_objects + self.me.dynamic_objects
        o2 = []
        for x in range(self.get_map_size()[0]):
            for y in range(self.get_map_size()[1]):
                o2 += self.get_cell_at(x, y).objects
        for o in o1:
            o.game = self
            assert o in o2
        for o in o2:
            assert o in o1
        #o1 contains the same objects as o2
        od = []
        for entry in self.me.objects_dict.keys():
            for o in self.me.objects_dict[entry].values():
                od.append(o)
                if not (o in o1):
                    print(o, o.name, o.str_type, o.cell.coord)
                    assert o in o1
##        for o in o1:
##            print(o, o.name, o.str_type, o.cell.coord)
##            assert o in od
        print("The", len(o1), "objects are consistent in memory.")

    def get_all_races(self):
        races = set()
        for u in self.units:
            races.add(u.race)
        return races

    def initialize_last_parameters(self):
        self.gui.footstep = get_sprite_frames("sprites/footstep.png",
                                              s=12,
                                              resize_factor=0.6)
        self.gui.sword = get_sprite_frames("sprites/sword_shine.png")
        self.gui.medic = get_sprite_frames("sprites/medic.png", s=16)
        self.gui.under_construct = get_sprite_frames(
            "sprites/under_construction.png", s=16)
        self.gui.under_capture = get_sprite_frames("sprites/under_capture.png",
                                                   s=16)
        ##        self.update_player_income(self.current_player)
        self.gui.e_gold_txt.set_text(str(self.current_player.money))
        self.gui.empty_star = get_sprite_frames("sprites/star_empty.png",
                                                s=13)[0]
        self.gui.plain_star = get_sprite_frames("sprites/star_plain.png",
                                                s=13)[0]
        self.hourglass = get_sprite_frames("sprites/hourglass.png")
##        p1,p2 = self.players
##        villages1 = self.get_objects_of_team(p1.team, "village")
##        villages2 = self.get_objects_of_team(p2.team, "village")
##        L1 = len(villages1)
##        L2 = len(villages2)
##        if L1 == L2: #including 0
##            return
##        if L1 > 0:
##            if L2 / L1 < 0.5:
##                v = random.choice(villages1)
##                self.set_flag(v.cell.coord, p2.race.flag, p2.team)
##        elif L2 > 0:
##            if L1 / L2 < 0.5:
##                v = random.choice(villages2)
##                self.set_flag(v.cell.coord, p1.race.flag, p1.team)

    def initialize_money(self, amount, compensation):
        for p in self.players:
            p.money += amount
        income1 = self.compute_player_income(self.players[0])
        income2 = self.compute_player_income(self.players[1])
        if income1 > income2:
            self.players[1].money += compensation * (income1 - income2)
        elif income2 > income1:
            self.players[0].money += compensation * (income2 - income1)
        self.refresh_village_gui()
        self.gui.refresh()
        self.update_player_income(self.current_player)
        self.gui.e_gold_txt.set_text(str(self.current_player.money))

    def get_other_player(self, player):
        if player is self.players[0]:
            return self.players[1]
        return self.players[0]