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
}