diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index 139addcaa..a64b44c25 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -14,6 +14,7 @@ export type Intent = SpawnIntent | TargetPlayerIntent | EmojiIntent | DonateIntent + | NukeIntent export type AttackIntent = z.infer export type SpawnIntent = z.infer @@ -25,6 +26,7 @@ export type BreakAllianceIntent = z.infer export type TargetPlayerIntent = z.infer export type EmojiIntent = z.infer export type DonateIntent = z.infer +export type NukeIntent = z.infer export type Turn = z.infer export type GameConfig = z.infer @@ -142,6 +144,14 @@ export const DonateIntentSchema = BaseIntentSchema.extend({ troops: z.number().nullable(), }) +export const NukeIntentSchema = BaseIntentSchema.extend({ + type: z.literal('nuke'), + sender: z.string(), + x: z.number(), + y: z.number(), + magnitude: z.number().nullable(), +}) + const IntentSchema = z.union([ AttackIntentSchema, SpawnIntentSchema, @@ -153,6 +163,7 @@ const IntentSchema = z.union([ TargetPlayerIntentSchema, EmojiIntentSchema, DonateIntentSchema, + NukeIntentSchema, ]); const TurnSchema = z.object({ diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index 8e52b3168..0149fc812 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -15,6 +15,7 @@ import {BreakAllianceExecution} from "./alliance/BreakAllianceExecution"; import {TargetPlayerExecution} from "./TargetPlayerExecution"; import {EmojiExecution} from "./EmojiExecution"; import {DonateExecution} from "./DonateExecution"; +import {NukeExecution} from "./NukeExecution"; @@ -74,8 +75,9 @@ export class Executor { return new EmojiExecution(intent.sender, intent.recipient, intent.emoji) } else if (intent.type == "donate") { return new DonateExecution(intent.sender, intent.recipient, intent.troops) - } - else { + } else if (intent.type == "nuke") { + return new NukeExecution(intent.sender, new Cell(intent.x, intent.y), intent.magnitude) + } else { throw new Error(`intent type ${intent} not found`) } } diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts new file mode 100644 index 000000000..424e095ad --- /dev/null +++ b/src/core/execution/NukeExecution.ts @@ -0,0 +1,53 @@ +import {Cell, Execution, MutableGame, MutablePlayer, PlayerID, Tile} from "../game/Game"; +import {bfs, dist} from "../Util"; + +export class NukeExecution implements Execution { + + private sender: MutablePlayer + + private active = true + + private toDestroy: Set = new Set() + + private mg: MutableGame + + constructor( + private senderID: PlayerID, + private cell: Cell, + private magnitude: number | null + ) { } + + + init(mg: MutableGame, ticks: number): void { + this.mg = mg + this.sender = mg.player(this.senderID) + if (this.magnitude == null) { + this.magnitude = 50 + } + const tile = mg.tile(this.cell) + this.toDestroy = bfs(tile, dist(tile, this.magnitude)) + } + + tick(ticks: number): void { + for (const tile of this.toDestroy) { + const owner = tile.owner() + if (owner.isPlayer()) { + this.mg.player(owner.id()).relinquish(tile) + } + } + this.active = false + } + + owner(): MutablePlayer { + return null + } + + isActive(): boolean { + return this.active + } + + activeDuringSpawnPhase(): boolean { + return false + } + +} \ No newline at end of file