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
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()
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)
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 = []
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]