Created hydrogen bomb

This commit is contained in:
Evan
2024-11-20 19:55:42 -08:00
parent 8531b47144
commit 18ac34ae45
11 changed files with 37 additions and 55 deletions
+2 -1
View File
@@ -186,8 +186,9 @@
* nuke spawns from missile silo DONE 11/16/2024
* REFACTOR: move canbuild to player DONE 11/17/2024
* BUG: can build destroyer on land DONE 11/17/2024
* fix pathfinding bug
* fix pathfinding bug DONE 11/20/2024
* make two nukes: atom & hydrogen
* NPC builds ports
* destroyer can capture trade ships
* add battleship
* add defense post
+2 -22
View File
@@ -75,14 +75,6 @@ export class SendDonateIntentEvent implements GameEvent {
) { }
}
export class SendNukeIntentEvent implements GameEvent {
constructor(
public readonly sender: Player,
public readonly cell: Cell,
public readonly magnitude: number | null,
) { }
}
export class SendSetTargetTroopRatioEvent implements GameEvent {
constructor(
public readonly ratio: number,
@@ -120,9 +112,8 @@ export class Transport {
this.eventBus.on(SendTargetPlayerIntentEvent, (e) => this.onSendTargetPlayerIntent(e))
this.eventBus.on(SendEmojiIntentEvent, (e) => this.onSendEmojiIntent(e))
this.eventBus.on(SendDonateIntentEvent, (e) => this.onSendDonateIntent(e))
this.eventBus.on(SendNukeIntentEvent, (e) => this.onSendNukeIntent(e))
this.eventBus.on(SendSetTargetTroopRatioEvent, (e) => this.onSendSetTargetTroopRatioEvent(e))
this.eventBus.on(BuildUnitIntentEvent, (e) => this.onCreateDestroyerIntent(e))
this.eventBus.on(BuildUnitIntentEvent, (e) => this.onBuildUnitIntent(e))
}
connect(onconnect: () => void, onmessage: (message: ServerMessage) => void) {
@@ -302,17 +293,6 @@ export class Transport {
})
}
private onSendNukeIntent(event: SendNukeIntentEvent) {
this.sendIntent({
type: "nuke",
clientID: this.clientID,
sender: event.sender.id(),
x: event.cell.x,
y: event.cell.y,
magnitude: event.magnitude,
})
}
private onSendSetTargetTroopRatioEvent(event: SendSetTargetTroopRatioEvent) {
this.sendIntent({
type: "troop_ratio",
@@ -322,7 +302,7 @@ export class Transport {
})
}
private onCreateDestroyerIntent(event: BuildUnitIntentEvent) {
private onBuildUnitIntent(event: BuildUnitIntentEvent) {
this.sendIntent({
type: "build_unit",
clientID: this.clientID,
+1 -1
View File
@@ -80,7 +80,7 @@ export class UnitLayer implements Layer {
break;
case UnitType.TradeShip:
this.handleTradeShipEvent(event)
case UnitType.Nuke:
case UnitType.AtomBomb:
this.handleNuke(event)
}
}
@@ -2,8 +2,9 @@ import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { EventBus } from '../../../../core/EventBus';
import { Cell, Game, Player, UnitType } from '../../../../core/game/Game';
import { BuildUnitIntentEvent, SendNukeIntentEvent } from '../../../Transport';
import nukeIcon from '../../../../../resources/images/NukeIconWhite.svg';
import { BuildUnitIntentEvent } from '../../../Transport';
import atomBombIcon from '../../../../../resources/images/NukeIconWhite.svg';
import hydrogenBombIcon from '../../../../../resources/images/MushroomCloudIconWhite.svg';
import destroyerIcon from '../../../../../resources/images/DestroyerIconWhite.svg';
import missileSiloIcon from '../../../../../resources/images/MissileSiloIconWhite.svg';
import goldCoinIcon from '../../../../../resources/images/GoldCoinIcon.svg';
@@ -18,7 +19,8 @@ interface BuildItemDisplay {
const buildTable: BuildItemDisplay[][] = [
[
{ unitType: UnitType.Nuke, icon: nukeIcon },
{ unitType: UnitType.AtomBomb, icon: atomBombIcon },
{ unitType: UnitType.HydrogenBomb, icon: hydrogenBombIcon },
{ unitType: UnitType.Destroyer, icon: destroyerIcon },
{ unitType: UnitType.Port, icon: portIcon },
{ unitType: UnitType.MissileSilo, icon: missileSiloIcon }
@@ -155,9 +157,11 @@ export class BuildMenu extends LitElement {
public onBuildSelected = (item: BuildItemDisplay) => {
switch (item.unitType) {
case UnitType.Nuke:
this.eventBus.emit(new SendNukeIntentEvent(this.myPlayer, this.clickedCell, null))
case UnitType.AtomBomb:
this.eventBus.emit(new BuildUnitIntentEvent(UnitType.AtomBomb, this.clickedCell))
break
case UnitType.HydrogenBomb:
this.eventBus.emit(new BuildUnitIntentEvent(UnitType.HydrogenBomb, this.clickedCell))
case UnitType.Destroyer:
this.eventBus.emit(new BuildUnitIntentEvent(UnitType.Destroyer, this.clickedCell))
break
@@ -3,7 +3,7 @@ import { AllPlayers, Cell, Game, Player, UnitType } from "../../../../core/game/
import { ClientID } from "../../../../core/Schemas";
import { and, bfs, dist, manhattanDist, manhattanDistWrapped, sourceDstOceanShore, targetTransportTile } from "../../../../core/Util";
import { ContextMenuEvent, MouseUpEvent } from "../../../InputHandler";
import { SendAllianceRequestIntentEvent, SendAttackIntentEvent, SendBoatAttackIntentEvent, SendBreakAllianceIntentEvent, SendDonateIntentEvent, SendEmojiIntentEvent, SendNukeIntentEvent, SendSpawnIntentEvent, SendTargetPlayerIntentEvent } from "../../../Transport";
import { SendAllianceRequestIntentEvent, SendAttackIntentEvent, SendBoatAttackIntentEvent, SendBreakAllianceIntentEvent, SendDonateIntentEvent, SendEmojiIntentEvent, SendSpawnIntentEvent, SendTargetPlayerIntentEvent } from "../../../Transport";
import { TransformHandler } from "../../TransformHandler";
import { Layer } from "../Layer";
import * as d3 from 'd3';
+1 -12
View File
@@ -13,7 +13,6 @@ export type Intent = SpawnIntent
| TargetPlayerIntent
| EmojiIntent
| DonateIntent
| NukeIntent
| TargetTroopRatioIntent
| BuildUnitIntent
@@ -26,7 +25,6 @@ export type BreakAllianceIntent = z.infer<typeof BreakAllianceIntentSchema>
export type TargetPlayerIntent = z.infer<typeof TargetPlayerIntentSchema>
export type EmojiIntent = z.infer<typeof EmojiIntentSchema>
export type DonateIntent = z.infer<typeof DonateIntentSchema>
export type NukeIntent = z.infer<typeof NukeIntentSchema>
export type TargetTroopRatioIntent = z.infer<typeof TargetTroopRatioIntentSchema>
export type BuildUnitIntent = z.infer<typeof BuildUnitIntentSchema>
@@ -69,7 +67,7 @@ const EmojiSchema = z.string().refine(
);
// Zod schemas
const BaseIntentSchema = z.object({
type: z.enum(['attack', 'spawn', 'boat', 'name', 'targetPlayer', 'emoji', 'nuke', 'troop_ratio', 'build_unit']),
type: z.enum(['attack', 'spawn', 'boat', 'name', 'targetPlayer', 'emoji', 'troop_ratio', 'build_unit']),
clientID: z.string(),
});
@@ -147,14 +145,6 @@ 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(),
})
export const TargetTroopRatioIntentSchema = BaseIntentSchema.extend({
type: z.literal('troop_ratio'),
player: z.string(),
@@ -179,7 +169,6 @@ const IntentSchema = z.union([
TargetPlayerIntentSchema,
EmojiIntentSchema,
DonateIntentSchema,
NukeIntentSchema,
TargetTroopRatioIntentSchema,
BuildUnitIntentSchema,
]);
+6 -1
View File
@@ -24,11 +24,16 @@ export class DefaultConfig implements Config {
cost: 300_000,
territoryBound: true
}
case UnitType.Nuke:
case UnitType.AtomBomb:
return {
cost: 1_000_000,
territoryBound: false
}
case UnitType.HydrogenBomb:
return {
cost: 5_000_000,
territoryBound: false
}
case UnitType.TradeShip:
return {
cost: 0,
+3 -2
View File
@@ -79,12 +79,13 @@ export class Executor {
return new EmojiExecution(intent.sender, intent.recipient, intent.emoji);
case "donate":
return new DonateExecution(intent.sender, intent.recipient, intent.troops);
case "nuke":
return new NukeExecution(intent.sender, new Cell(intent.x, intent.y), intent.magnitude);
case "troop_ratio":
return new SetTargetTroopRatioExecution(intent.player, intent.ratio);
case "build_unit":
switch (intent.unit) {
case UnitType.AtomBomb:
case UnitType.HydrogenBomb:
return new NukeExecution(intent.unit, intent.player, new Cell(intent.x, intent.y))
case UnitType.Destroyer:
return new DestroyerExecution(intent.player, new Cell(intent.x, intent.y))
case UnitType.Port:
+8 -8
View File
@@ -17,30 +17,27 @@ export class NukeExecution implements Execution {
private pathFinder: PathFinder = new PathFinder(10_000, () => true)
constructor(
private type: UnitType.AtomBomb | UnitType.HydrogenBomb,
private senderID: PlayerID,
private cell: Cell,
private magnitude: number | null
) { }
init(mg: MutableGame, ticks: number): void {
this.mg = mg
this.player = mg.player(this.senderID)
if (this.magnitude == null) {
this.magnitude = 50
}
this.dst = this.mg.tile(this.cell)
}
tick(ticks: number): void {
if (this.nuke == null) {
const spawn = this.player.canBuild(UnitType.Nuke, this.dst)
const spawn = this.player.canBuild(UnitType.AtomBomb, this.dst)
if (spawn == false) {
console.warn(`cannot build Nuke`)
this.active = false
return
}
this.nuke = this.player.buildUnit(UnitType.Nuke, 0, spawn)
this.nuke = this.player.buildUnit(UnitType.AtomBomb, 0, spawn)
}
for (let i = 0; i < 4; i++) {
@@ -64,11 +61,14 @@ export class NukeExecution implements Execution {
}
private detonate() {
const magnitude = this.type == UnitType.AtomBomb ? 25 : 100
const rand = new PseudoRandom(this.mg.ticks())
const tile = this.mg.tile(this.cell)
const toDestroy = bfs(tile, (n: Tile) => {
const d = euclideanDist(tile.cell(), n.cell())
return (d <= this.magnitude || rand.chance(2)) && d <= this.magnitude + 40
return (d <= magnitude || rand.chance(2)) && d <= magnitude * 2
})
const ratio = Object.fromEntries(
@@ -85,7 +85,7 @@ export class NukeExecution implements Execution {
}
}
for (const unit of this.mg.units()) {
if (euclideanDist(this.cell, unit.tile().cell()) < this.magnitude + 50) {
if (euclideanDist(this.cell, unit.tile().cell()) < magnitude * 2) {
unit.delete()
}
}
+2 -1
View File
@@ -32,7 +32,8 @@ export enum UnitType {
TransportShip = "Transport",
Destroyer = "Destroyer",
Port = "Port",
Nuke = "Nuke",
AtomBomb = "Atom Bomb",
HydrogenBomb = "Hydrogen Bomb",
TradeShip = "Trade Ship",
MissileSilo = "Missile Silo",
}
+2 -1
View File
@@ -346,7 +346,8 @@ export class PlayerImpl implements MutablePlayer {
return false
}
switch (unitType) {
case UnitType.Nuke:
case UnitType.AtomBomb:
case UnitType.HydrogenBomb:
return this.nukeSpawn(targetTile)
case UnitType.Port:
return this.portSpawn(targetTile)