fix bugs from using tilerefs

This commit is contained in:
Evan
2025-01-18 20:45:06 -08:00
parent f0f5bae79f
commit b91d9d4148
14 changed files with 41 additions and 62 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ export function createGrid(game: Game, player: Player, boundingBox: { min: Point
const cell = new Cell(x * scalingFactor, y * scalingFactor);
if (game.isOnMap(cell)) {
const tile = game.ref(cell.x, cell.y);
grid[x - scaledBoundingBox.min.x][y - scaledBoundingBox.min.y] = this.game.isLake(tile) || this.game.owner(tile) === player; // TODO: okay if lake
grid[x - scaledBoundingBox.min.x][y - scaledBoundingBox.min.y] = game.isLake(tile) || game.owner(tile) === player; // TODO: okay if lake
}
}
}
+12 -12
View File
@@ -18,7 +18,7 @@ import { Layer } from "./Layer";
import { SendAllianceReplyIntentEvent } from "../../Transport";
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { onlyImages, sanitize } from '../../../core/Util';
import { GameView } from '../../../core/GameView';
import { GameView, PlayerView } from '../../../core/GameView';
interface Event {
description: string;
@@ -222,8 +222,8 @@ export class EventsDisplay extends LitElement implements Layer {
return;
}
const requestor = this.game.playerBySmallID(update.requestorID)
const recipient = this.game.playerBySmallID(update.recipientID)
const requestor = this.game.playerBySmallID(update.requestorID) as PlayerView
const recipient = this.game.playerBySmallID(update.recipientID) as PlayerView
this.addEvent({
description: `${requestor.name()} requests an alliance!`,
@@ -258,7 +258,7 @@ export class EventsDisplay extends LitElement implements Layer {
return;
}
const recipient = this.game.playerBySmallID(update.request.recipientID)
const recipient = this.game.playerBySmallID(update.request.recipientID) as PlayerView
this.addEvent({
description: `${recipient.name()} ${update.accepted ? "accepted" : "rejected"} your alliance request`,
@@ -272,8 +272,8 @@ export class EventsDisplay extends LitElement implements Layer {
const myPlayer = this.game.playerByClientID(this.clientID);
if (!myPlayer) return;
const betrayed = this.game.playerBySmallID(update.betrayedID)
const traitor = this.game.playerBySmallID(update.traitorID)
const betrayed = this.game.playerBySmallID(update.betrayedID) as PlayerView
const traitor = this.game.playerBySmallID(update.traitorID) as PlayerView
if (!betrayed.isTraitor() && traitor === myPlayer) {
this.addEvent({
@@ -297,7 +297,7 @@ export class EventsDisplay extends LitElement implements Layer {
if (!myPlayer) return;
const otherID = update.player1ID === myPlayer.smallID() ? update.player2ID : update.player2ID === myPlayer.smallID() ? update.player1ID : null;
const other = this.game.playerBySmallID(otherID)
const other = this.game.playerBySmallID(otherID) as PlayerView
if (!other || !myPlayer.isAlive() || !other.isAlive()) return;
this.addEvent({
@@ -309,11 +309,11 @@ export class EventsDisplay extends LitElement implements Layer {
}
onTargetPlayerEvent(event: TargetPlayerUpdate) {
const other = this.game.playerBySmallID(event.playerID)
const myPlayer = this.game.playerByClientID(this.clientID);
const other = this.game.playerBySmallID(event.playerID) as PlayerView
const myPlayer = this.game.playerByClientID(this.clientID) as PlayerView
if (!myPlayer || !myPlayer.isAlliedWith(other)) return;
const target = this.game.playerBySmallID(event.targetID)
const target = this.game.playerBySmallID(event.targetID) as PlayerView
this.addEvent({
description: `${other.name()} requests you attack ${target.name()}`,
@@ -328,7 +328,7 @@ export class EventsDisplay extends LitElement implements Layer {
if (!myPlayer) return;
const recipient = update.recipientID == AllPlayers ? AllPlayers : this.game.playerBySmallID(update.recipientID)
const sender = this.game.playerBySmallID(update.senderID)
const sender = this.game.playerBySmallID(update.senderID) as PlayerView
if (recipient == myPlayer) {
this.addEvent({
@@ -340,7 +340,7 @@ export class EventsDisplay extends LitElement implements Layer {
});
} else if (sender === myPlayer && recipient !== AllPlayers) {
this.addEvent({
description: `Sent ${recipient.displayName()}: ${update.message}`,
description: `Sent ${(recipient as PlayerView).displayName()}: ${update.message}`,
unsafeDescription: true,
type: MessageType.INFO,
highlight: true,
+6 -5
View File
@@ -161,7 +161,8 @@ export class TerritoryLayer implements Layer {
if (!this.game.hasOwner(tile)) {
if (this.game.hasFallout(tile)) {
this.paintCell(
new Cell(this.game.x(tile), this.game.y(tile)),
this.game.x(tile),
this.game.y(tile),
this.theme.falloutColor(),
150
);
@@ -173,21 +174,21 @@ export class TerritoryLayer implements Layer {
const owner = this.game.owner(tile) as Player;
if (this.game.isBorder(tile)) {
this.paintCell(
new Cell(this.game.x(tile), this.game.y(tile)),
this.game.x(tile), this.game.y(tile),
this.theme.borderColor(owner.info()),
255
);
} else {
this.paintCell(
new Cell(this.game.x(tile), this.game.y(tile)),
this.game.x(tile), this.game.y(tile),
this.theme.territoryColor(owner.info()),
150
);
}
}
paintCell(cell: Cell, color: Colord, alpha: number) {
const index = (cell.y * this.game.width()) + cell.x;
paintCell(x: number, y: number, color: Colord, alpha: number) {
const index = (y * this.game.width()) + x;
const offset = index * 4;
this.imageData.data[offset] = color.rgba.r;
this.imageData.data[offset + 1] = color.rgba.g;
+8 -5
View File
@@ -49,7 +49,7 @@ export class UnitView implements Unit {
return this.gameView.ref(this.data.pos.x, this.data.pos.y)
}
owner(): PlayerView {
return this.gameView.playerBySmallID(this.data.ownerID)
return this.gameView.playerBySmallID(this.data.ownerID) as PlayerView
}
isActive(): boolean {
return this.data.isActive
@@ -222,6 +222,7 @@ export class GameView implements GameMap {
public update(gu: GameUpdateViewData) {
this.lastUpdate = gu
this.updatedTiles = []
this.lastUpdate.packedTileUpdates.forEach(tu => {
this.updatedTiles.push(this.updateTile(tu))
})
@@ -259,7 +260,10 @@ export class GameView implements GameMap {
throw Error(`player id ${id} not found`)
}
playerBySmallID(id: number): PlayerView {
playerBySmallID(id: number): PlayerView | TerraNullius {
if (id == 0) {
return new TerraNulliusImpl()
}
if (!this.smallIDToID.has(id)) {
throw new Error(`small id ${id} not found`)
}
@@ -284,7 +288,7 @@ export class GameView implements GameMap {
return []
}
owner(tile: TileRef): PlayerView {
owner(tile: TileRef): PlayerView | TerraNullius {
return this.playerBySmallID(this.ownerID(tile))
}
@@ -312,7 +316,7 @@ export class GameView implements GameMap {
height(): number { return this._map.height() }
numLandTiles(): number { return this._map.numLandTiles() }
isValidCoord(x: number, y: number): boolean { return this._map.isValidCoord(x, y) }
isLand(ref: TileRef): boolean { return this._map.isLake(ref) }
isLand(ref: TileRef): boolean { return this._map.isLand(ref) }
isOceanShore(ref: TileRef): boolean { return this._map.isOceanShore(ref) }
isOcean(ref: TileRef): boolean { return this._map.isOcean(ref) }
isShoreline(ref: TileRef): boolean { return this._map.isShoreline(ref) }
@@ -323,7 +327,6 @@ export class GameView implements GameMap {
hasFallout(ref: TileRef): boolean { return this._map.hasFallout(ref) }
setFallout(ref: TileRef, value: boolean): void { return this._map.setFallout(ref, value) }
isBorder(ref: TileRef): boolean { return this._map.isBorder(ref) }
setBorder(ref: TileRef, value: boolean): void { return this._map.setBorder(ref, value) }
neighbors(ref: TileRef): TileRef[] { return this._map.neighbors(ref) }
isWater(ref: TileRef): boolean { return this._map.isWater(ref) }
isLake(ref: TileRef): boolean { return this._map.isLake(ref) }
-1
View File
@@ -175,7 +175,6 @@ export class AttackExecution implements Execution {
}
this.border.add(neighbor)
let numOwnedByMe = this.mg.neighbors(neighbor)
.filter(t => this.mg.isLake(t))
.filter(t => this.mg.owner(t) == this._owner)
.length
let dist = 0
+1 -1
View File
@@ -56,7 +56,7 @@ export class BotExecution implements Execution {
if (this.neighborsTerraNullius) {
for (const b of this.bot.borderTiles()) {
for (const n of this.mg.neighbors(b)) {
if (!this.mg.hasOwner(n) && this.mg.isLake(n)) {
if (!this.mg.hasOwner(n) && this.mg.isLand(n)) {
this.sendAttack(this.mg.terraNullius())
return
}
+1 -1
View File
@@ -20,7 +20,7 @@ export class CityExecution implements Execution {
if (this.city == null) {
const spawnTile = this.player.canBuild(UnitType.City, this.tile)
if (spawnTile == false) {
consolex.warn('cannot build Defense Post')
consolex.warn('cannot build city')
this.active = false
return
}
+1 -1
View File
@@ -92,7 +92,7 @@ export class FakeHumanExecution implements Execution {
const enemyborder = Array.from(this.player.borderTiles())
.flatMap(t => this.mg.neighbors(t))
.filter(t => this.mg.isLake(t) && this.mg.ownerID(t) != this.player.smallID())
.filter(t => this.mg.isLand(t) && this.mg.ownerID(t) != this.player.smallID())
if (enemyborder.length == 0) {
if (this.random.chance(5)) {
+3 -3
View File
@@ -150,9 +150,9 @@ export class PlayerExecution implements Execution {
private removeCluster(cluster: Set<TileRef>) {
const arr = Array.from(cluster)
const mode = getMode(
arr.
flatMap(t => this.mg.neighbors(t))
.filter(t => this.mg.ownerID(t) != this.player.smallID())
arr
.flatMap(t => this.mg.neighbors(t))
.filter(t => this.mg.hasOwner(t) && this.mg.ownerID(t) != this.player.smallID())
.map(t => this.mg.ownerID(t))
)
if (!this.mg.playerBySmallID(mode).isPlayer()) {
-1
View File
@@ -337,7 +337,6 @@ export interface MutableGame extends Game {
units(...types: UnitType[]): MutableUnit[]
addTileDefenseBonus(tile: TileRef, unit: Unit, amount: number): DefenseBonus
removeTileDefenseBonus(bonus: DefenseBonus): void
addFallout(tile: TileRef): void
setWinner(winner: Player): void
}
+4 -17
View File
@@ -84,11 +84,11 @@ export class GameImpl implements MutableGame {
return old
}
addFallout(tile: TileRef) {
if (this.hasOwner(tile)) {
setFallout(tile: TileRef, value: boolean) {
if (value && this.hasOwner(tile)) {
throw Error(`cannot set fallout, tile ${tile} has owner`)
}
this._map.setFallout(tile, true)
this._map.setFallout(tile, value)
this.addUpdate({
type: GameUpdateType.Tile,
update: this.toTileUpdate(tile)
@@ -315,12 +315,6 @@ export class GameImpl implements MutableGame {
return ns
}
private assertIsOnMap(cell: Cell) {
if (!this.isOnMap(cell)) {
throw new Error(`cell ${cell.toString()} is not on map`)
}
}
conquer(owner: PlayerImpl, tile: TileRef): void {
if (!this.isLand(tile)) {
throw Error(`cannot conquer water`)
@@ -330,7 +324,6 @@ export class GameImpl implements MutableGame {
previousOwner._lastTileChange = this._ticks
previousOwner._tiles.delete(tile)
previousOwner._borderTiles.delete(tile)
this._map.setBorder(tile, false)
}
this._map.setOwnerID(tile, owner.smallID())
owner._tiles.add(tile)
@@ -355,7 +348,6 @@ export class GameImpl implements MutableGame {
previousOwner._lastTileChange = this._ticks
previousOwner._tiles.delete(tile)
previousOwner._borderTiles.delete(tile)
this._map.setBorder(tile, false)
this._map.setOwnerID(tile, 0)
this.updateBorders(tile)
@@ -373,15 +365,12 @@ export class GameImpl implements MutableGame {
for (const t of tiles) {
if (!this.hasOwner(t)) {
this._map.setBorder(t, false)
continue
}
if (this.calcIsBorder(t)) {
(this.owner(t) as PlayerImpl)._borderTiles.add(t);
this._map.setBorder(t, true)
} else {
(this.owner(t) as PlayerImpl)._borderTiles.delete(t);
this._map.setBorder(t, false)
}
// this.updates.push(t.toUpdate())
}
@@ -494,7 +483,7 @@ export class GameImpl implements MutableGame {
height(): number { return this._map.height() }
numLandTiles(): number { return this._map.numLandTiles() }
isValidCoord(x: number, y: number): boolean { return this._map.isValidCoord(x, y) }
isLand(ref: TileRef): boolean { return this._map.isLake(ref) }
isLand(ref: TileRef): boolean { return this._map.isLand(ref) }
isOceanShore(ref: TileRef): boolean { return this._map.isOceanShore(ref) }
isOcean(ref: TileRef): boolean { return this._map.isOcean(ref) }
isShoreline(ref: TileRef): boolean { return this._map.isShoreline(ref) }
@@ -503,9 +492,7 @@ export class GameImpl implements MutableGame {
hasOwner(ref: TileRef): boolean { return this._map.hasOwner(ref) }
setOwnerID(ref: TileRef, playerId: number): void { return this._map.setOwnerID(ref, playerId) }
hasFallout(ref: TileRef): boolean { return this._map.hasFallout(ref) }
setFallout(ref: TileRef, value: boolean): void { return this._map.setFallout(ref, value) }
isBorder(ref: TileRef): boolean { return this._map.isBorder(ref) }
setBorder(ref: TileRef, value: boolean): void { return this._map.setBorder(ref, value) }
neighbors(ref: TileRef): TileRef[] { return this._map.neighbors(ref) }
isWater(ref: TileRef): boolean { return this._map.isWater(ref) }
isLake(ref: TileRef): boolean { return this._map.isLake(ref) }
+2 -12
View File
@@ -28,7 +28,6 @@ export interface GameMap {
hasFallout(ref: TileRef): boolean
setFallout(ref: TileRef, value: boolean): void
isBorder(ref: TileRef): boolean
setBorder(ref: TileRef, value: boolean): void
neighbors(ref: TileRef): TileRef[]
isWater(ref: TileRef): boolean
isLake(ref: TileRef): boolean
@@ -62,8 +61,7 @@ export class GameMapImpl implements GameMap {
// State bits (Uint16Array)
private static readonly PLAYER_ID_OFFSET = 0; // Uses bits 0-11 (12 bits)
private static readonly PLAYER_ID_MASK = 0xFFF;
private static readonly FALLOUT_BIT = 12;
private static readonly BORDER_BIT = 13;
private static readonly FALLOUT_BIT = 13;
private static readonly DEFENSE_BONUS_BIT = 14;
// Bit 15 still reserved
@@ -155,15 +153,7 @@ export class GameMapImpl implements GameMap {
}
isBorder(ref: TileRef): boolean {
return Boolean(this.state[ref] & (1 << GameMapImpl.BORDER_BIT));
}
setBorder(ref: TileRef, value: boolean): void {
if (value) {
this.state[ref] |= 1 << GameMapImpl.BORDER_BIT;
} else {
this.state[ref] &= ~(1 << GameMapImpl.BORDER_BIT);
}
return this.neighbors(ref).some(tr => this.ownerID(tr) != this.ownerID(ref))
}
hasDefenseBonus(ref: TileRef): boolean {
+1 -1
View File
@@ -31,7 +31,7 @@ export class PlayerImpl implements MutablePlayer {
public _borderTiles: Set<TileRef> = new Set();
public _units: UnitImpl[] = [];
public _tiles: Set<TileRef>
public _tiles: Set<TileRef> = new Set()
private _name: string;
private _displayName: string;
+1 -1
View File
@@ -40,7 +40,7 @@ export class MiniAStar implements AStar {
}
reconstructPath(): TileRef[] {
const upscaled = upscalePath(this.aStar.reconstructPath().map(tr => new Cell(this.gameMap.x(tr), this.gameMap.y(tr))))
const upscaled = upscalePath(this.aStar.reconstructPath().map(tr => new Cell(this.miniMap.x(tr), this.miniMap.y(tr))))
upscaled.push(new Cell(this.gameMap.x(this.dst), this.gameMap.y(this.dst)))
return upscaled.map(c => this.gameMap.ref(c.x, c.y))
}