Skip to main content
Glama
turn-processor.ts4.84 kB
import { NationRepository } from '../../storage/repos/nation.repo.js'; import { RegionRepository } from '../../storage/repos/region.repo.js'; import { DiplomacyRepository } from '../../storage/repos/diplomacy.repo.js'; import { ConflictResolver } from './conflict-resolver.js'; import { Nation } from '../../schema/nation.js'; export class TurnProcessor { constructor( private nationRepo: NationRepository, private regionRepo: RegionRepository, private diplomacyRepo: DiplomacyRepository, private conflictResolver: ConflictResolver ) { } processTurn(worldId: string, turnNumber: number): void { const nations = this.nationRepo.findByWorldId(worldId); // 1. Economic Growth this.processEconomy(nations); // 2. Resolve Conflicts this.processConflicts(worldId, turnNumber); // 3. Resource Drift (Consumption) this.processConsumption(nations); } private processEconomy(nations: Nation[]): void { for (const nation of nations) { // Simple GDP growth: 1% per turn base + resources // const growthRate = 1.01; // const newGdp = nation.gdp * growthRate; // TODO: Persist GDP update // Resource production based on owned regions (simplified for now) const newResources = { food: nation.resources.food + 10, metal: nation.resources.metal + 5, oil: nation.resources.oil + 2 }; this.nationRepo.updateResources(nation.id, newResources); nation.resources = newResources; // Update local state } } private processConflicts(worldId: string, turnNumber: number): void { const regions = this.regionRepo.findByWorldId(worldId); for (const region of regions) { const claims = this.diplomacyRepo.getClaimsByRegion(region.id); if (claims.length === 0) continue; const claimantNations = claims.map(c => this.nationRepo.findById(c.nationId)).filter((n): n is Nation => !!n); if (claimantNations.length === 0) continue; // Case 1: Uncontested claim on unowned region -> Auto-win if (claimantNations.length === 1 && !region.ownerNationId) { const winner = claimantNations[0]; this.regionRepo.updateOwnership(region.id, winner.id, 10); // Initial control this.diplomacyRepo.logEvent({ worldId, turnNumber, eventType: 'REGION_CLAIMED', involvedNations: [winner.id], details: { log: `${winner.name} established control over ${region.name}`, regionId: region.id }, timestamp: new Date().toISOString() }); continue; } // Case 2: Contested claim OR Claim on owned region if (claimantNations.length > 1 || (region.ownerNationId && claimantNations[0].id !== region.ownerNationId)) { const participants = [...claimantNations]; if (region.ownerNationId && !participants.find(n => n.id === region.ownerNationId)) { const owner = this.nationRepo.findById(region.ownerNationId); if (owner) participants.push(owner); } if (participants.length < 2) continue; // Should not happen if logic is correct, but safety check const result = this.conflictResolver.resolveRegionConflict( region, participants, `${worldId}-${turnNumber}-${region.id}` ); this.regionRepo.updateOwnership( region.id, result.newControlLevel <= 0 ? null : (result.log.includes('conquered') ? result.winnerId : region.ownerNationId || null), result.newControlLevel ); this.diplomacyRepo.logEvent({ worldId, turnNumber, eventType: result.log.includes('conquered') ? 'REGION_CONQUERED' : 'REGION_CLAIMED', involvedNations: [result.winnerId, result.loserId], details: { log: result.log, regionId: region.id }, timestamp: new Date().toISOString() }); } } } private processConsumption(nations: Nation[]): void { for (const nation of nations) { const consumed = { food: Math.max(0, nation.resources.food - 5), metal: nation.resources.metal, oil: nation.resources.oil }; this.nationRepo.updateResources(nation.id, consumed); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mnehmos/rpg-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server