import { Execution, Game } from "../game/Game"; import { PseudoRandom } from "../PseudoRandom"; import { ClientID, GameID, StampedIntent, Turn } from "../Schemas"; import { simpleHash } from "../Util"; import { AllianceExtensionExecution } from "./alliance/AllianceExtensionExecution"; import { AllianceRequestExecution } from "./alliance/AllianceRequestExecution"; import { AllianceRequestReplyExecution } from "./alliance/AllianceRequestReplyExecution"; import { BreakAllianceExecution } from "./alliance/BreakAllianceExecution"; import { AttackExecution } from "./AttackExecution"; import { BoatRetreatExecution } from "./BoatRetreatExecution"; import { BotSpawner } from "./BotSpawner"; import { ConstructionExecution } from "./ConstructionExecution"; import { DeleteUnitExecution } from "./DeleteUnitExecution"; import { DonateGoldExecution } from "./DonateGoldExecution"; import { DonateTroopsExecution } from "./DonateTroopExecution"; import { EmbargoAllExecution } from "./EmbargoAllExecution"; import { EmbargoExecution } from "./EmbargoExecution"; import { EmojiExecution } from "./EmojiExecution"; import { MarkDisconnectedExecution } from "./MarkDisconnectedExecution"; import { MoveWarshipExecution } from "./MoveWarshipExecution"; import { NationExecution } from "./NationExecution"; import { NoOpExecution } from "./NoOpExecution"; import { PauseExecution } from "./PauseExecution"; import { QuickChatExecution } from "./QuickChatExecution"; import { RetreatExecution } from "./RetreatExecution"; import { SpawnExecution } from "./SpawnExecution"; import { TargetPlayerExecution } from "./TargetPlayerExecution"; import { TransportShipExecution } from "./TransportShipExecution"; import { UpgradeStructureExecution } from "./UpgradeStructureExecution"; import { PlayerSpawner } from "./utils/PlayerSpawner"; export class Executor { // private random = new PseudoRandom(999) private random: PseudoRandom; constructor( private mg: Game, private gameID: GameID, private clientID: ClientID, ) { // Add one to avoid id collisions with bots. this.random = new PseudoRandom(simpleHash(gameID) + 1); } createExecs(turn: Turn): Execution[] { return turn.intents.map((i) => this.createExec(i)); } createExec(intent: StampedIntent): Execution { const player = this.mg.playerByClientID(intent.clientID); if (!player) { console.warn(`player with clientID ${intent.clientID} not found`); return new NoOpExecution(); } // create execution switch (intent.type) { case "attack": { return new AttackExecution( intent.troops, player, intent.targetID, intent.sourceTile ?? null, ); } case "cancel_attack": return new RetreatExecution(player, intent.attackID); case "cancel_boat": return new BoatRetreatExecution(player, intent.unitID); case "move_warship": return new MoveWarshipExecution(player, intent.unitId, intent.tile); case "spawn": return new SpawnExecution(this.gameID, player.info(), intent.tile); case "boat": return new TransportShipExecution(player, intent.dst, intent.troops); case "allianceRequest": return new AllianceRequestExecution(player, intent.recipient); case "allianceRequestReply": return new AllianceRequestReplyExecution( intent.requestor, player, intent.accept, ); case "breakAlliance": return new BreakAllianceExecution(player, intent.recipient); case "targetPlayer": return new TargetPlayerExecution(player, intent.target); case "emoji": return new EmojiExecution(player, intent.recipient, intent.emoji); case "donate_troops": return new DonateTroopsExecution( player, intent.recipient, intent.troops, ); case "donate_gold": return new DonateGoldExecution(player, intent.recipient, intent.gold); case "embargo": return new EmbargoExecution(player, intent.targetID, intent.action); case "embargo_all": return new EmbargoAllExecution(player, intent.action); case "build_unit": return new ConstructionExecution( player, intent.unit, intent.tile, intent.rocketDirectionUp, ); case "allianceExtension": { return new AllianceExtensionExecution(player, intent.recipient); } case "upgrade_structure": return new UpgradeStructureExecution(player, intent.unitId); case "delete_unit": return new DeleteUnitExecution(player, intent.unitId); case "quick_chat": return new QuickChatExecution( player, intent.recipient, intent.quickChatKey, intent.target, ); case "mark_disconnected": return new MarkDisconnectedExecution(player, intent.isDisconnected); case "toggle_pause": return new PauseExecution(player, intent.paused); default: throw new Error(`intent type ${intent} not found`); } } spawnBots(numBots: number): SpawnExecution[] { return new BotSpawner(this.mg, this.gameID).spawnBots(numBots); } spawnPlayers(): SpawnExecution[] { return new PlayerSpawner(this.mg, this.gameID).spawnPlayers(); } nationExecutions(): Execution[] { const execs: Execution[] = []; for (const nation of this.mg.nations()) { execs.push(new NationExecution(this.gameID, nation)); } return execs; } }