def execute_research(self, asset_name, target_type): uc = UPGRADE_CLASSES[asset_name] if uc.alien_min_level > self.difficulty: return False if uc.resource_type in self.civ.upgrades_stocked: self.civ.upgrades_stocked.remove(uc.resource_type) #if uc.cursor is None: # TODO: add cursor to every tech?? if uc.category == "tech": self.research_with_target(asset_name, self.civ) else: target = None available_planets = [ p for p in self.scene.get_civ_planets(self.civ) if p.is_buildable() ] if not available_planets: return False # Random planet if target_type == buildorder.BOResearch.TARGET_TYPE_RANDOM: target = random.choice(available_planets) # Planet which lacks the building elif target_type == buildorder.BOResearch.TARGET_TYPE_LACKING_ASSET: def key(p): return asset_name in [ b['building'].upgrade.name for b in p.buildings ] available_planets.sort(key=key) print([(p, key(p)) for p in available_planets]) target = available_planets[0] # Homeworld, or random if dead elif target_type == buildorder.BOResearch.TARGET_TYPE_HOMEWORLD: if self.civ.homeworld in available_planets: target = self.civ.homeworld else: target = random.choice(available_planets) # Undefended elif target_type == buildorder.BOResearch.TARGET_TYPE_UNDEFENDED: available_planets.sort(key=lambda p: sum(p.ships.values())) target = available_planets[0] if target is None: return False self.research_with_target(asset_name, target) return True else: return False
def grant_achievement(self, name): if name not in ACHIEVEMENT_INFO: return was_new = self.save.set_achievement(name) self.save.save() if USE_STEAMWORKS: print("SET ACHIEVEMENT", name) steamworks_sdk.UserStats.SetAchievement(name.encode("ascii")) steamworks_sdk.UserStats.StoreStats() #steamworks_sdk.run_callbacks() else: if was_new: game.Game.inst.show_achievement( ACHIEVEMENT_INFO[name]['name'], ACHIEVEMENT_INFO[name]['description'])
def pause(self, key_pressed): #pause menu if (key_pressed != -1): debug.print(key_pressed) if key_pressed == 27: if self.paused: self.scrn.unrender_pause() else: self.scrn.render_pause() self.paused = not self.paused key_pressed = -1 elif self.paused: self.scrn.scr.addstr(0, 0, "PAUSE") self.scrn.render_pause() if key_pressed == 27: self.paused = not self.paused elif key_pressed == ord('q'): self.should_keep_going = False
def update_post_build_order(self, dt): # Expand or attack if we are behind the expanding curve neutral_planets = self.scene.get_civ_planets(None) my_planets = self.scene.get_civ_planets(self.civ) num = len(my_planets) orders = self.get_ordered_ships(self.get_colonist()) if orders: num += len(set([o[1] for o in orders])) target_num = self.get_target_num_planets(self.time * self.build_order_acceleration) if num < target_num: if self.time_behind_expand_curve < 20: self.time_behind_expand_curve += dt else: if neutral_planets: self.execute_expand( buildorder.BOExpand.TARGET_TYPE_NEAR_HOME) self.time_behind_expand_curve = 0 else: self.attack_behind_expansion_curve_countdown -= dt if self.attack_behind_expansion_curve_countdown < 0: self.time_behind_expand_curve = 0 print("attack because expand curve") self.execute_attack( buildorder.BOAttack.ATTACK_TYPE_OUTLYING) self.attack_behind_expansion_curve_countdown = 120 / self.build_order_acceleration # Attack if we're close to winning if self.count_attacking_ships() < max(self.get_max_attackers() - 2, 3): winning_acceleration = 1 if self.near_winning: winning_acceleration = 2 # only count down when there's no attackers self.attack_countdown -= dt * winning_acceleration if self.attack_countdown < 0: print("attack because attack countdown") self.execute_attack(buildorder.BOAttack.ATTACK_TYPE_CENTRAL) self.attack_countdown = self.get_next_attack_countdown() # Research randomly self.research_randomly()
def load_level(self, levelfile): print("load level") data = json.load(open(resource_path("levels/%s.json" % levelfile))) for obj in data: t = None owner = None if obj['type'].endswith("planet"): t = "planet" if obj['type'] == "my_planet": owner = self.player_civ elif obj['type'] == "enemy_planet": owner = self.enemy.civ if t == "planet": r = [v * 10 for v in obj['data']['resources']] pos = V2(*obj['pos']) o = Planet(self, pos + self.game.game_offset, obj['size'], Resources(*r)) if owner and not owner.homeworld: owner.homeworld = o if owner: o.change_owner(owner) o.population = 1 elif obj['type'] == "hazard": pos = V2(*obj['pos']) o = Hazard(self, pos + self.game.game_offset, obj['size']) elif obj['type'] == "crystal": pos = V2(*obj['pos']) r = [v * 10 for v in obj['data']['resources']] o = bosstimecrystal.TimeCrystal(self, pos + self.game.game_offset, 2, Resources(*r)) o.change_owner(self.enemy.civ) o.generate_stranded_ships() o.add_ship("bosslaser") o.add_ship("bossfighter") else: print(obj) self.game_group.add(o) self.objgrid.generate_grid(self.get_objects_initial())
def send_attacking_party(self, source, target, max_num=999, possible_colonist=True): ships = self.get_planet_ship_instances(source) ships = [s for s in ships if s in self.get_attacking_ships()] num_to_send = random.randint(1, max(len(ships), 1)) num_to_send = min(num_to_send, max_num) num_attackers = len(self.get_ordered_ships(target_filter=target)) num_to_send = min(num_to_send, self.get_max_attackers() - num_attackers) print("attacking with %d" % num_to_send) if num_to_send <= 0: return for s in ships[0:num_to_send]: source.emit_ship(s, {'to': target}) num_planets = self.count_expansions_plus_pending() if ships and possible_colonist and num_planets < self.get_max_planets( ): if source.population > 1 and random.random() < 0.8: source.emit_ship(self.get_colonist(), {'to': target, 'num': 1})
def update(self, alien, dt): self.time += dt if self.is_over(): return pending_step = self.steps[0] if self.time > pending_step.time: if not pending_step.triggered: print("trigger", str(pending_step)) pending_step.trigger(alien) else: pending_step.update(alien, dt) if pending_step.done: print("done with", str(pending_step)) self.steps.pop(0) elif pending_step.abandoned: print("abandoning", str(pending_step)) self.steps.pop(0)
def open(self) -> "API": device_id = None try: if not os.path.isfile(SETTING_FILE): debug.print(f"API Unable to find Auth file: {SETTING_FILE}") self.api = Client(USERNAME, PASSWORD, on_login=self.__onlogin_callback) else: with open(SETTING_FILE) as file_data: cached_settings = json.load(file_data, object_hook=self.__from_json) debug.print(f"API Reusing Auth Settings: {SETTING_FILE}") device_id = cached_settings.get("device_id") self.api = Client(USERNAME, PASSWORD, settings=cached_settings) except (ClientError) as err: debug.print(f"API Client Expired: {err}") self.api = Client(USERNAME, PASSWORD, device_id=device_id, on_login=self.__onlogin_callback) return self
def init_steam(): if not STEAM_ENABLED: return global USE_STEAMWORKS global steamworks_sdk try: import steamworks steamworks_sdk = steamworks.STEAMWORKS() steamworks_sdk.initialize() print("USING STEAM") print("Steam ID", steamworks_sdk.Users.GetSteamID()) print("Logged on:", steamworks_sdk.Users.LoggedOn()) print("RequestCurrentStats:", steamworks_sdk.UserStats.RequestCurrentStats() == True) steamworks_sdk.run_callbacks() USE_STEAMWORKS = True except Exception as e: print(e) print("NOT USING STEAM")
def render(self): t = time.time() #self.game.screen.fill(PICO_BLACK) self.update_layers() if game.DEV: for spr in self.background_group.sprites( ) + self.game_group.sprites() + self.ui_group.sprites(): if spr.image is None and spr.visible: print(spr, "bad image") self.background_group.draw(self.game.screen) self.particle_group.draw(self.game.screen) self.game_group.draw(self.game.screen) if self.shake_sprite: self.shake_sprite.render(self.game.screen) if self.debug: for k, v in self.fleet_managers.items(): for fleet in v.current_fleets: fleet.debug_render(self.game.screen) gi = pygame.Surface(self.game.screen.get_size(), pygame.SRCALPHA) gi.fill((0, 0, 0, 0)) ff = list(self.flowfield.fields.values())[self.flowfielddebug] if self.flowfielddebugstage > 0: for col in range(1, len(ff.base_grid[0])): x = col * flowfield.GRIDSIZE + ff.offset.x pygame.draw.line(gi, (255, 255, 255, 50), (x, ff.offset.y), (x, ff.offset.y + game.RES[1]), 1) for row in range(1, len(ff.base_grid)): y = row * flowfield.GRIDSIZE + ff.offset.y pygame.draw.line(gi, (255, 255, 255, 50), (ff.offset.x, y), (ff.offset.x + game.RES[0], y), 1) if self.flowfielddebugstage == 1: for y, gr in enumerate(ff.base_grid): for x, gc in enumerate(gr): pt = V2(x * flowfield.GRIDSIZE, y * flowfield.GRIDSIZE) + ff.offset s = "-" if gc: s = "O" FONTS['tiny'].render_to(gi, (pt.x + 2, pt.y + 2), s, (128, 255, 128, 180)) if self.flowfielddebugstage == 2: for y, gr in enumerate(ff.dgrid): for x, gc in enumerate(gr): pt = V2(x * flowfield.GRIDSIZE, y * flowfield.GRIDSIZE) + ff.offset if isinstance(gc, tuple): s = "-" elif gc is None: s = "??" else: s = str(gc % 10) FONTS['tiny'].render_to(gi, (pt.x + 2, pt.y + 2), s, (128, 255, 128, 180)) elif self.flowfielddebugstage == 3: for y, gr in enumerate(ff.grid): for x, gc in enumerate(gr): p1 = V2((x + 0.5) * flowfield.GRIDSIZE, (y + 0.5) * flowfield.GRIDSIZE) + ff.offset if gc is not None: p2 = p1 + gc * flowfield.GRIDSIZE * 0.75 pygame.draw.line(gi, (0, 0, 255), p1, p2) pygame.draw.circle(gi, (0, 0, 255), p1, 1) else: pygame.draw.circle(gi, (255, 0, 255), p1, 3, 1) if False: for y in range(len(self.objgrid.grid)): for x in range(len(self.objgrid.grid[0])): x1 = x * self.objgrid.grid_size y1 = y * self.objgrid.grid_size pygame.draw.rect(gi, (0, 255, 0, 150), (x1, y1, self.objgrid.grid_size + 1, self.objgrid.grid_size + 1), 1) FONTS['tiny'].render_to( gi, (x1 + 2, y1 + 2), "%d" % len(self.objgrid.grid[y][x]), (128, 255, 128, 180)) self.game.screen.blit(gi, (0, 0)) self.pause_sprite.visible = self.paused if self.stage_name.time < 2 and self.stage_name.alive(): self.pause_sprite.visible = False if not self.cinematic: self.ui_group.draw(self.game.screen) self.tutorial_group.draw(self.game.screen) if self.debug: self.enemy.render(self.game.screen) debug_render(self.game.screen, self) self.update_times['render'] = time.time() - t #FONTS['small'].render_to(self.game.screen, (5,game.RES[1] - 25), "%d" % self.time, (255,255,255,255)) if self.debug: for i, s in enumerate([ "%s:%.1f" % (a, b * 1000) for a, b in self.update_times.items() ]): FONTS['tiny'].render_to(self.game.screen, (30, 100 + i * 8), s, (128, 255, 128, 180)) FONTS['tiny'].render_to( self.game.screen, (30, 50), "diagram: %.1f MAX, %.1f MEAN" % (self.fleet_diagram.max_debug_time * 1000, self.fleet_diagram.mean_debug_time * 1000), (128, 255, 255, 180)) if game.DEV: FONTS['tiny'].render_to(self.game.screen, (game.RES[0] - 120, 4), "%d" % self.time, (128, 255, 128, 180)) res = self.game.game_resolution if self.cinematic: surf = pygame.Surface(res, pygame.SRCALPHA) pygame.draw.rect(surf, PICO_DARKBLUE, (0, 0, res.x, 40), 0) pygame.draw.rect(surf, PICO_DARKBLUE, (0, res.y - 40, res.x, 40), 0) #surf.set_alpha(160) self.game.screen.blit(surf, (0, 0)) tri = [V2(0, 0), V2(4, 4), V2(0, 8)] if self.game_speed > 1: color = PICO_BLUE if ((self.time % 2) > 1) else PICO_WHITE pygame.draw.rect(self.game.screen, PICO_BLUE, (0, 0, res.x, res.y), 1) pygame.draw.polygon(self.game.screen, color, [(z + V2(res.x - 12, res.y - 12)) for z in tri], 0) pygame.draw.polygon(self.game.screen, color, [(z + V2(res.x - 7, res.y - 12)) for z in tri], 0) elif not self.cinematic: ctl = "Space" if self.game.input_mode == "joystick": ctl = "L1" t = text.render_multiline(ctl, "small", PICO_LIGHTGRAY, wrap_width=130) self.game.screen.blit(t, (res.x - t.get_width() - 16, res.y - 12)) pygame.draw.polygon(self.game.screen, PICO_LIGHTGRAY, [(z + V2(res.x - 12, res.y - 12)) for z in tri], 0) pygame.draw.polygon(self.game.screen, PICO_LIGHTGRAY, [(z + V2(res.x - 7, res.y - 12)) for z in tri], 0) #FONTS['small'].render_to(self.game.screen, PICO_BLUE, "") return None
def load(self): print("load") self.create_layers() civ_name = self.game.run_info.get_current_level_galaxy()['alien'] if self.alienrace: civ_name = self.alienrace AlienClass = aliens.alien.ALIENS[civ_name] self.enemies = [AlienClass(self, Civ(self))] self.enemy = self.enemies[0] self.enemy.bonus_supply = 999 if self.levelfile: self.load_level(self.levelfile) else: self.load_level("choke") if self.difficulty == 9: self.level_controller = bosslevelcontroller.BossLevelController( self) else: self.level_controller = levelcontroller.LevelController(self) self.setup_players() self.add_extra_spaceobjects() self.objgrid.generate_grid( [s for s in self.game_group.sprites() if s.collidable]) print("generate image") self.background.generate_image(self.objgrid) print("done generate image") self.add_ui_elements() self.fleet_managers = { 'my': fleet.FleetManager(self, self.player_civ), 'enemy': fleet.FleetManager(self, self.enemy.civ) } print("generate flowfield") self.flowfield = flowfield.FlowFieldMap() self.flowfield.generate(self) self.flowfielddebug = 0 self.flowfielddebugstage = 0 self.fleet_diagram.generate_image(self) self.enemy.set_difficulty(self.difficulty) self.setup_mods() # Add the time loops if self.difficulty >= 6 and self.difficulty < 9: planets = [ s for s in self.get_objects_initial() if isinstance(s, Planet) and s.owning_civ == None and s.time_loop == False ] if planets: planets.sort(key=lambda x: x.pos.x) for i in range(1): p = planets.pop(int(len(planets) / 2)) #p.set_time_loop() if self.options == "surround": for planet in self.get_civ_planets(None): planet.change_owner(self.enemy.civ) self.enemy.civ.resources.set_resource("gas", 220) if self.options == "performance": from aliens.alien1fighter import Alien1Fighter for i in range(60): #civ = self.player_civ if i % 2 == 0 else self.enemy.civ civ = self.enemy.civ p = V2(random.randint(50, self.game.game_resolution.x - 50), random.randint(50, self.game.game_resolution.y - 50)) s = Alien1Fighter(self, p, civ) self.game_group.add(s) random_planet = random.choice(self.get_planets()) s.set_target(random_planet) if self.options == "rich": self.player_civ.resources.set_resource("iron", 1150) self.player_civ.resources.set_resource("ice", 1150) self.player_civ.resources.set_resource("gas", 1150) if self.options == "gas": self.player_civ.resources.set_resource("gas", 1150) if self.options == "fighters": for i in range(20): self.homeworld.add_ship("fighter")
def execute_attack(self, attack_type, attack_strength=1): all_potential_targets = self.scene.get_civ_planets( self.scene.player_civ) all_potential_targets = [ t for t in all_potential_targets if len(self.get_ordered_ships( target_filter=t)) <= self.get_max_attackers() * attack_strength ] if not all_potential_targets: return False sorted_targets = all_potential_targets[::] all_potential_sources = self.scene.get_civ_planets(self.civ) all_potential_sources = [ s for s in all_potential_sources if sum({ k: v for k, v in s.ships.items() if k in self.get_attacking_ships() }.values()) > 0 ] all_potential_ships = sum([ sum({ k: v for k, v in s.ships.items() if k in self.get_attacking_ships() }.values()) for s in all_potential_sources ]) num_to_send = math.ceil(all_potential_ships * attack_strength) possible_colonist = True if attack_strength < 0.25: possible_colonist = False print("num to send", num_to_send) if not all_potential_sources: return False sorted_sources = all_potential_sources[::] if attack_type == buildorder.BOAttack.ATTACK_TYPE_CENTRAL: sorted_targets.sort(key=lambda p: p.population, reverse=True) target = sorted_targets[0] sorted_sources.sort( key=lambda p: (p.pos - target.pos).length_squared()) num_sources = random.randint(2, 4) sources = sorted_sources[0:num_sources] for source in sources: self.send_attacking_party(source, target, num_to_send, possible_colonist) elif attack_type == buildorder.BOAttack.ATTACK_TYPE_OUTLYING: def key(p): # Middle = smallest delta between near me and near enemy distances. d1 = (p.pos - self.scene.player_civ.homeworld.pos).length_squared() d2 = (p.pos - self.civ.homeworld.pos).length_squared() return abs(d1 - d2) sorted_targets.sort(key=key) target = sorted_targets[0] sorted_sources.sort( key=lambda p: (p.pos - target.pos).length_squared()) self.send_attacking_party(sorted_sources[0], target, num_to_send, possible_colonist) elif attack_type == buildorder.BOAttack.ATTACK_TYPE_RANDOM: target = random.choice(sorted_targets) sorted_sources.sort( key=lambda p: (p.pos - target.pos).length_squared()) self.send_attacking_party(sorted_sources[0], target, num_to_send, possible_colonist) return True
def research_with_target(self, asset_name, target): print("Researching %s" % asset_name) up = UPGRADE_CLASSES[asset_name] up().apply(target) self.civ.register_research(up.name) self.civ.upgrades.append(up)
def __onlogin_callback(self, api): cache_settings = api.settings with open(SETTING_FILE, 'w') as outfile: json.dump(cache_settings, outfile, default=self.__to_json) debug.print(f"API Saving Auth Settings: {SETTING_FILE}")