from server.game_state import GameState from server.models import BUILDING_CONFIGS, BuildingType import time from collections import defaultdict from server.logger import logger class EconomyEngine: """Handles all economy calculations and ticks""" def __init__(self, game_state: GameState): self.game_state = game_state def tick(self): """ Process one economy tick for all players using an efficient aggregate calculation. """ logger.debug("Processing economy tick...") start_time = time.perf_counter() player_money_deltas = defaultdict(int) player_total_population = defaultdict(int) # 1. Single pass over all buildings to aggregate their effects for building in self.game_state.buildings.values(): config = BUILDING_CONFIGS[building.building_type] owner_id = building.owner_id base_income = config.income if base_income > 0: zone_size = self.game_state.get_building_zone_size(building.x, building.y) connectivity_bonus = 1.0 + (zone_size * 0.05) base_income = int(base_income * connectivity_bonus) player_money_deltas[owner_id] += base_income player_total_population[owner_id] += config.population # 2. Apply the aggregated deltas to each player for player_id, player in self.game_state.players.items(): power_factor = 1.0 if player.is_online else 0.1 money_delta = player_money_deltas.get(player_id, 0) player.money += int(money_delta * power_factor) total_population = player_total_population.get(player_id, 0) player.population = max(0, total_population) if player.money < -100000: player.money = -100000 duration = time.perf_counter() - start_time logger.debug(f"Economy tick processed in {duration:.4f} seconds for {len(self.game_state.players)} players.") def calculate_building_stats(self, player_id: str, building_type: BuildingType) -> dict: """Calculate what a building would produce for a player""" config = BUILDING_CONFIGS[building_type] return { "cost": config.cost, "income": config.income, "population": config.population, "power_required": config.power_required, "requires_population": config.requires_population, "description": config.description }