From 5c51655eca0f57a85053a7e0e5e397b69947eab5 Mon Sep 17 00:00:00 2001 From: evanpelle Date: Wed, 4 Dec 2024 13:21:35 -0800 Subject: [PATCH] add radiation --- TODO.txt | 2 +- src/client/graphics/layers/TerritoryLayer.ts | 4 + src/core/configuration/Config.ts | 2 + src/core/configuration/DefaultConfig.ts | 9 + src/core/configuration/PastelTheme.ts | 232 ++++++++++--------- src/core/execution/NukeExecution.ts | 3 + src/core/game/Game.ts | 2 + src/core/game/GameImpl.ts | 10 + src/core/game/TileImpl.ts | 6 + 9 files changed, 158 insertions(+), 112 deletions(-) diff --git a/TODO.txt b/TODO.txt index b4467f2d8..547d97b27 100644 --- a/TODO.txt +++ b/TODO.txt @@ -207,10 +207,10 @@ * use mini A* for all pathfinding DONE 12/3/2024 * bugfix: gameStop not found error DONE 12/3/2024 * log stack traces & display them on screen DONE 12/3/2024 +* add radiation from nuke * record and replay games for debugging purposes * bugfix: destroyers can't find path to dst and freeze * record single player game stats -* add radiation from nuke * add cities * create behavior tests * create perf test diff --git a/src/client/graphics/layers/TerritoryLayer.ts b/src/client/graphics/layers/TerritoryLayer.ts index 7a2edac37..dd8613c29 100644 --- a/src/client/graphics/layers/TerritoryLayer.ts +++ b/src/client/graphics/layers/TerritoryLayer.ts @@ -75,6 +75,10 @@ export class TerritoryLayer implements Layer { } paintTerritory(tile: Tile) { + if (tile.hasFallout()) { + this.paintCell(tile.cell(), this.theme.falloutColor(), 150) + return + } if (!tile.hasOwner()) { this.clearCell(tile.cell()) return diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 88cabcffd..277860ce5 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -62,6 +62,7 @@ export interface Config { tradeShipSpawnRate(): number defensePostRange(): number defensePostDefenseBonus(): number + falloutDefenseModifier(): number } export interface Theme { @@ -71,6 +72,7 @@ export interface Theme { defendedBorderColor(playerInfo: PlayerInfo): Colord; terrainColor(tile: Tile): Colord; backgroundColor(): Colord; + falloutColor(): Colord font(): string; } diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 24d81ac72..45fb05c14 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -7,6 +7,11 @@ import { pastelTheme } from "./PastelTheme"; export class DefaultConfig implements Config { + + falloutDefenseModifier(): number { + return 2 + } + defensePostRange(): number { return 30 } @@ -148,6 +153,10 @@ export class DefaultConfig implements Config { } mag *= tileToConquer.defenseBonus(attacker) speed *= tileToConquer.defenseBonus(attacker) + if (tileToConquer.hasFallout()) { + mag *= this.falloutDefenseModifier() + speed *= this.falloutDefenseModifier() + } if (attacker.isPlayer() && defender.isPlayer()) { if (attacker.type() == PlayerType.Human && defender.type() == PlayerType.Bot) { diff --git a/src/core/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts index 37420f38e..40cd994d8 100644 --- a/src/core/configuration/PastelTheme.ts +++ b/src/core/configuration/PastelTheme.ts @@ -1,123 +1,129 @@ -import {Colord, colord, random} from "colord"; -import {PlayerID, PlayerInfo, TerrainType, Tile} from "../game/Game"; -import {Theme} from "./Config"; -import {time} from "console"; -import {PseudoRandom} from "../PseudoRandom"; -import {simpleHash} from "../Util"; +import { Colord, colord, random } from "colord"; +import { PlayerID, PlayerInfo, TerrainType, Tile } from "../game/Game"; +import { Theme } from "./Config"; +import { time } from "console"; +import { PseudoRandom } from "../PseudoRandom"; +import { simpleHash } from "../Util"; export const pastelTheme = new class implements Theme { - + private rand = new PseudoRandom(123) - private background = colord({r: 60, g: 60, b: 60}); - private land = colord({r: 194, g: 193, b: 148}); - private shore = colord({r: 204, g: 203, b: 158}); - - private water = colord({r: 75, g: 142, b: 190}); - private shorelineWater = colord({r: 100, g: 143, b: 255}); + private background = colord({ r: 60, g: 60, b: 60 }); + private land = colord({ r: 194, g: 193, b: 148 }); + private shore = colord({ r: 204, g: 203, b: 158 }); + private falloutColors = [ + colord({ r: 120, g: 255, b: 71 }), // Original color + colord({ r: 130, g: 255, b: 85 }), // Slightly lighter + colord({ r: 110, g: 245, b: 65 }), // Slightly darker + colord({ r: 125, g: 255, b: 75 }), // Warmer tint + colord({ r: 115, g: 250, b: 68 }) // Cooler tint + ]; + private water = colord({ r: 75, g: 142, b: 190 }); + private shorelineWater = colord({ r: 100, g: 143, b: 255 }); private territoryColors: Colord[] = [ - colord({r: 230, g: 100, b: 100}), // Bright Red - colord({r: 100, g: 180, b: 230}), // Sky Blue - colord({r: 230, g: 180, b: 80}), // Golden Yellow - colord({r: 180, g: 100, b: 230}), // Purple - colord({r: 80, g: 200, b: 120}), // Emerald Green - colord({r: 230, g: 130, b: 180}), // Pink - colord({r: 100, g: 160, b: 80}), // Olive Green - colord({r: 230, g: 150, b: 100}), // Peach - colord({r: 80, g: 130, b: 190}), // Navy Blue - colord({r: 210, g: 210, b: 100}), // Lime Yellow - colord({r: 190, g: 100, b: 130}), // Maroon - colord({r: 100, g: 210, b: 210}), // Turquoise - colord({r: 210, g: 140, b: 80}), // Light Orange - colord({r: 150, g: 110, b: 190}), // Lavender - colord({r: 180, g: 210, b: 120}), // Light Green - colord({r: 210, g: 100, b: 160}), // Hot Pink - colord({r: 100, g: 140, b: 110}), // Sea Green - colord({r: 230, g: 180, b: 180}), // Light Pink - colord({r: 120, g: 120, b: 190}), // Periwinkle - colord({r: 190, g: 170, b: 100}), // Sand - colord({r: 100, g: 180, b: 160}), // Aquamarine - colord({r: 210, g: 160, b: 200}), // Orchid - colord({r: 170, g: 190, b: 100}), // Yellow Green - colord({r: 100, g: 130, b: 150}), // Steel Blue - colord({r: 230, g: 140, b: 140}), // Salmon - colord({r: 140, g: 180, b: 220}), // Light Blue - colord({r: 200, g: 160, b: 110}), // Tan - colord({r: 180, g: 130, b: 180}), // Plum - colord({r: 130, g: 200, b: 130}), // Light Sea Green - colord({r: 220, g: 120, b: 120}), // Coral - colord({r: 120, g: 160, b: 200}), // Cornflower Blue - colord({r: 200, g: 200, b: 140}), // Khaki - colord({r: 160, g: 120, b: 160}), // Purple Gray - colord({r: 140, g: 180, b: 140}), // Dark Sea Green - colord({r: 200, g: 130, b: 110}), // Dark Salmon - colord({r: 130, g: 170, b: 190}), // Cadet Blue - colord({r: 190, g: 180, b: 160}), // Tan Gray - colord({r: 170, g: 140, b: 190}), // Medium Purple - colord({r: 160, g: 190, b: 160}), // Pale Green - colord({r: 190, g: 150, b: 130}), // Rosy Brown - colord({r: 140, g: 150, b: 180}), // Light Slate Gray - colord({r: 180, g: 170, b: 140}), // Dark Khaki - colord({r: 150, g: 130, b: 150}), // Thistle - colord({r: 170, g: 190, b: 180}), // Pale Blue Green - colord({r: 190, g: 140, b: 150}), // Puce - colord({r: 130, g: 180, b: 170}), // Medium Aquamarine - colord({r: 180, g: 160, b: 180}), // Mauve - colord({r: 160, g: 180, b: 140}), // Dark Olive Green - colord({r: 170, g: 150, b: 170}), // Dusty Rose - colord({r: 100, g: 180, b: 230}), // Sky Blue - colord({r: 230, g: 180, b: 80}), // Golden Yellow - colord({r: 180, g: 100, b: 230}), // Purple - colord({r: 80, g: 200, b: 120}), // Emerald Green - colord({r: 230, g: 130, b: 180}), // Pink - colord({r: 100, g: 160, b: 80}), // Olive Green - colord({r: 230, g: 150, b: 100}), // Peach - colord({r: 80, g: 130, b: 190}), // Navy Blue - colord({r: 210, g: 210, b: 100}), // Lime Yellow - colord({r: 190, g: 100, b: 130}), // Maroon - colord({r: 100, g: 210, b: 210}), // Turquoise - colord({r: 210, g: 140, b: 80}), // Light Orange - colord({r: 150, g: 110, b: 190}), // Lavender - colord({r: 180, g: 210, b: 120}), // Light Green - colord({r: 210, g: 100, b: 160}), // Hot Pink - colord({r: 100, g: 140, b: 110}), // Sea Green - colord({r: 230, g: 180, b: 180}), // Light Pink - colord({r: 120, g: 120, b: 190}), // Periwinkle - colord({r: 190, g: 170, b: 100}), // Sand - colord({r: 100, g: 180, b: 160}), // Aquamarine - colord({r: 210, g: 160, b: 200}), // Orchid - colord({r: 170, g: 190, b: 100}), // Yellow Green - colord({r: 100, g: 130, b: 150}), // Steel Blue - colord({r: 230, g: 140, b: 140}), // Salmon - colord({r: 140, g: 180, b: 220}), // Light Blue - colord({r: 200, g: 160, b: 110}), // Tan - colord({r: 180, g: 130, b: 180}), // Plum - colord({r: 130, g: 200, b: 130}), // Light Sea Green - colord({r: 220, g: 120, b: 120}), // Coral - colord({r: 120, g: 160, b: 200}), // Cornflower Blue - colord({r: 200, g: 200, b: 140}), // Khaki - colord({r: 160, g: 120, b: 160}), // Purple Gray - colord({r: 140, g: 180, b: 140}), // Dark Sea Green - colord({r: 200, g: 130, b: 110}), // Dark Salmon - colord({r: 130, g: 170, b: 190}), // Cadet Blue - colord({r: 190, g: 180, b: 160}), // Tan Gray - colord({r: 170, g: 140, b: 190}), // Medium Purple - colord({r: 160, g: 190, b: 160}), // Pale Green - colord({r: 190, g: 150, b: 130}), // Rosy Brown - colord({r: 140, g: 150, b: 180}), // Light Slate Gray - colord({r: 180, g: 170, b: 140}), // Dark Khaki - colord({r: 150, g: 130, b: 150}), // Thistle - colord({r: 170, g: 190, b: 180}), // Pale Blue Green - colord({r: 190, g: 140, b: 150}), // Puce - colord({r: 130, g: 180, b: 170}), // Medium Aquamarine - colord({r: 180, g: 160, b: 180}), // Mauve - colord({r: 160, g: 180, b: 140}), // Dark Olive Green - colord({r: 170, g: 150, b: 170}) // Dusty Rose + colord({ r: 230, g: 100, b: 100 }), // Bright Red + colord({ r: 100, g: 180, b: 230 }), // Sky Blue + colord({ r: 230, g: 180, b: 80 }), // Golden Yellow + colord({ r: 180, g: 100, b: 230 }), // Purple + colord({ r: 80, g: 200, b: 120 }), // Emerald Green + colord({ r: 230, g: 130, b: 180 }), // Pink + colord({ r: 100, g: 160, b: 80 }), // Olive Green + colord({ r: 230, g: 150, b: 100 }), // Peach + colord({ r: 80, g: 130, b: 190 }), // Navy Blue + colord({ r: 210, g: 210, b: 100 }), // Lime Yellow + colord({ r: 190, g: 100, b: 130 }), // Maroon + colord({ r: 100, g: 210, b: 210 }), // Turquoise + colord({ r: 210, g: 140, b: 80 }), // Light Orange + colord({ r: 150, g: 110, b: 190 }), // Lavender + colord({ r: 180, g: 210, b: 120 }), // Light Green + colord({ r: 210, g: 100, b: 160 }), // Hot Pink + colord({ r: 100, g: 140, b: 110 }), // Sea Green + colord({ r: 230, g: 180, b: 180 }), // Light Pink + colord({ r: 120, g: 120, b: 190 }), // Periwinkle + colord({ r: 190, g: 170, b: 100 }), // Sand + colord({ r: 100, g: 180, b: 160 }), // Aquamarine + colord({ r: 210, g: 160, b: 200 }), // Orchid + colord({ r: 170, g: 190, b: 100 }), // Yellow Green + colord({ r: 100, g: 130, b: 150 }), // Steel Blue + colord({ r: 230, g: 140, b: 140 }), // Salmon + colord({ r: 140, g: 180, b: 220 }), // Light Blue + colord({ r: 200, g: 160, b: 110 }), // Tan + colord({ r: 180, g: 130, b: 180 }), // Plum + colord({ r: 130, g: 200, b: 130 }), // Light Sea Green + colord({ r: 220, g: 120, b: 120 }), // Coral + colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue + colord({ r: 200, g: 200, b: 140 }), // Khaki + colord({ r: 160, g: 120, b: 160 }), // Purple Gray + colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green + colord({ r: 200, g: 130, b: 110 }), // Dark Salmon + colord({ r: 130, g: 170, b: 190 }), // Cadet Blue + colord({ r: 190, g: 180, b: 160 }), // Tan Gray + colord({ r: 170, g: 140, b: 190 }), // Medium Purple + colord({ r: 160, g: 190, b: 160 }), // Pale Green + colord({ r: 190, g: 150, b: 130 }), // Rosy Brown + colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray + colord({ r: 180, g: 170, b: 140 }), // Dark Khaki + colord({ r: 150, g: 130, b: 150 }), // Thistle + colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green + colord({ r: 190, g: 140, b: 150 }), // Puce + colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine + colord({ r: 180, g: 160, b: 180 }), // Mauve + colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green + colord({ r: 170, g: 150, b: 170 }), // Dusty Rose + colord({ r: 100, g: 180, b: 230 }), // Sky Blue + colord({ r: 230, g: 180, b: 80 }), // Golden Yellow + colord({ r: 180, g: 100, b: 230 }), // Purple + colord({ r: 80, g: 200, b: 120 }), // Emerald Green + colord({ r: 230, g: 130, b: 180 }), // Pink + colord({ r: 100, g: 160, b: 80 }), // Olive Green + colord({ r: 230, g: 150, b: 100 }), // Peach + colord({ r: 80, g: 130, b: 190 }), // Navy Blue + colord({ r: 210, g: 210, b: 100 }), // Lime Yellow + colord({ r: 190, g: 100, b: 130 }), // Maroon + colord({ r: 100, g: 210, b: 210 }), // Turquoise + colord({ r: 210, g: 140, b: 80 }), // Light Orange + colord({ r: 150, g: 110, b: 190 }), // Lavender + colord({ r: 180, g: 210, b: 120 }), // Light Green + colord({ r: 210, g: 100, b: 160 }), // Hot Pink + colord({ r: 100, g: 140, b: 110 }), // Sea Green + colord({ r: 230, g: 180, b: 180 }), // Light Pink + colord({ r: 120, g: 120, b: 190 }), // Periwinkle + colord({ r: 190, g: 170, b: 100 }), // Sand + colord({ r: 100, g: 180, b: 160 }), // Aquamarine + colord({ r: 210, g: 160, b: 200 }), // Orchid + colord({ r: 170, g: 190, b: 100 }), // Yellow Green + colord({ r: 100, g: 130, b: 150 }), // Steel Blue + colord({ r: 230, g: 140, b: 140 }), // Salmon + colord({ r: 140, g: 180, b: 220 }), // Light Blue + colord({ r: 200, g: 160, b: 110 }), // Tan + colord({ r: 180, g: 130, b: 180 }), // Plum + colord({ r: 130, g: 200, b: 130 }), // Light Sea Green + colord({ r: 220, g: 120, b: 120 }), // Coral + colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue + colord({ r: 200, g: 200, b: 140 }), // Khaki + colord({ r: 160, g: 120, b: 160 }), // Purple Gray + colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green + colord({ r: 200, g: 130, b: 110 }), // Dark Salmon + colord({ r: 130, g: 170, b: 190 }), // Cadet Blue + colord({ r: 190, g: 180, b: 160 }), // Tan Gray + colord({ r: 170, g: 140, b: 190 }), // Medium Purple + colord({ r: 160, g: 190, b: 160 }), // Pale Green + colord({ r: 190, g: 150, b: 130 }), // Rosy Brown + colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray + colord({ r: 180, g: 170, b: 140 }), // Dark Khaki + colord({ r: 150, g: 130, b: 150 }), // Thistle + colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green + colord({ r: 190, g: 140, b: 150 }), // Puce + colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine + colord({ r: 180, g: 160, b: 180 }), // Mauve + colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green + colord({ r: 170, g: 150, b: 170 }) // Dusty Rose ]; playerInfoColor(id: PlayerID): Colord { - return colord({r: 50, g: 50, b: 50}) + return colord({ r: 50, g: 50, b: 50 }) } territoryColor(playerInfo: PlayerInfo): Colord { @@ -186,6 +192,10 @@ export const pastelTheme = new class implements Theme { return this.background; } + falloutColor(): Colord { + return this.rand.randElement(this.falloutColors) + } + font(): string { return "Overpass, sans-serif"; } diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts index 9e095ffaa..ce24c64ac 100644 --- a/src/core/execution/NukeExecution.ts +++ b/src/core/execution/NukeExecution.ts @@ -83,6 +83,9 @@ export class NukeExecution implements Execution { mp.removeTroops(2 * ratio[mp.id()]) others.add(mp) } + if (tile.isLand()) { + this.mg.addFallout(tile) + } } for (const other of others) { const alliance = this.player.allianceWith(other) diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index b46bf0dae..4f111a51f 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -174,6 +174,7 @@ export interface Tile extends SearchNode { defenseBonuses(): DefenseBonus[] // defense bonus against this player defenseBonus(player: Player): number + hasFallout(): boolean } export interface Unit { @@ -314,6 +315,7 @@ export interface MutableGame extends Game { units(...types: UnitType[]): MutableUnit[] addTileDefenseBonus(tile: Tile, unit: Unit, amount: number): DefenseBonus removeTileDefenseBonus(bonus: DefenseBonus): void + addFallout(tile: Tile) } export class TileEvent implements GameEvent { diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index fd80ca762..61f05631c 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -65,6 +65,15 @@ export class GameImpl implements MutableGame { }) } + addFallout(tile: Tile) { + const ti = tile as TileImpl + if (tile.hasOwner()) { + throw Error(`cannot set fallout, tile ${tile} has owner`) + } + ti._hasFallout = true + this.eventBus.emit(new TileEvent(tile)) + } + addTileDefenseBonus(tile: Tile, unit: Unit, amount: number): DefenseBonus { const df = { unit: unit, tile: tile, amount: amount }; (tile as TileImpl)._defenseBonuses.push(df) @@ -322,6 +331,7 @@ export class GameImpl implements MutableGame { tileImpl._owner = owner owner._tiles.set(tile.cell().toString(), tile) this.updateBorders(tile) + tileImpl._hasFallout = false this.eventBus.emit(new TileEvent(tile)) } diff --git a/src/core/game/TileImpl.ts b/src/core/game/TileImpl.ts index b88923b22..65b3ec26a 100644 --- a/src/core/game/TileImpl.ts +++ b/src/core/game/TileImpl.ts @@ -13,6 +13,8 @@ export class TileImpl implements Tile { public _defenseBonuses: DefenseBonus[] = [] + public _hasFallout = false + constructor( private readonly gs: GameImpl, public _owner: PlayerImpl | TerraNulliusImpl, @@ -20,6 +22,10 @@ export class TileImpl implements Tile { private readonly _terrain: TerrainTileImpl ) { } + hasFallout(): boolean { + return this._hasFallout + } + terrainType(): TerrainType { return this._terrain.type }