From 2082b229b4d66cefba4f7add6b27773eea213001 Mon Sep 17 00:00:00 2001 From: evanpelle Date: Wed, 4 Sep 2024 19:33:49 -0700 Subject: [PATCH] send boat even if borders with enemy --- TODO.txt | 8 ++- src/client/ClientGame.ts | 66 +++++++++++++---------- src/core/Util.ts | 3 +- src/core/configuration/DevConfig.ts | 17 +++--- src/core/execution/BoatAttackExecution.ts | 6 +-- 5 files changed, 57 insertions(+), 43 deletions(-) diff --git a/TODO.txt b/TODO.txt index c0c05247f..c748989cc 100644 --- a/TODO.txt +++ b/TODO.txt @@ -91,7 +91,8 @@ * names don't appear when zoomed out DONE 9/3/2024 * make names bigger DONE 9/3/2024 * boats leave trails DONE 9/3/2024 -* send boat even if touching +* send boat even if touching DONE 9/4/2024 +* when attacking by boat, attack execution only starts from boat pixel * directed expansion * more random names for game id & client id * Make fake humans @@ -99,7 +100,12 @@ * UI: boats * UI: current attacks * UI: leader board +* UI: event box +* make random waves on ocean, dark spots * Load terrain dataImage in background + +--- v3 Release + * BUG: when sending boat to TerraNullius, only takes one tile * REFACTOR: give terranullius an ID, game.player() returns terranullius * REFACTOR: ocean is considered TerraNullius ? diff --git a/src/client/ClientGame.ts b/src/client/ClientGame.ts index 29659271c..56434269c 100644 --- a/src/client/ClientGame.ts +++ b/src/client/ClientGame.ts @@ -206,38 +206,48 @@ export class ClientGame { return } - if (tile.hasOwner()) { - // Attack Player - if (tile.isLand()) { - if (this.myPlayer.sharesBorderWith(tile.owner())) { - this.sendAttackIntent(targetID, cell, this.gs.config().attackAmount(this.myPlayer, owner)) - } else if (owner.isPlayer()) { - console.log('going to send boat') - this.sendBoatAttackIntent(targetID, cell, this.gs.config().boatAttackAmount(this.myPlayer, owner)) - } - } - return - } - - - - // Attack Terra Nullius if (tile.isLand()) { - - const neighbors = Array.from(bfs(tile, and((t) => t.isLand(), dist(tile, 100)))); - for (const n of neighbors) { - if (this.myPlayer.borderTiles().has(n)) { - this.sendAttackIntent(targetID, cell, this.gs.config().attackAmount(this.myPlayer, owner)) - return + const bordersWithDists: Tile[] = [] + for (const border of this.myPlayer.borderTiles()) { + for (const n of border.neighbors()) { + if (n.owner() == tile.owner()) { + bordersWithDists.push(n) + } } } - const tn = Array.from(bfs(tile, dist(tile, 30))) - .filter(t => t.isOceanShore()) - .filter(t => !t.hasOwner()) - .sort((a, b) => manhattanDist(tile.cell(), a.cell()) - manhattanDist(tile.cell(), b.cell())) - if (tn.length > 0) { - this.sendBoatAttackIntent(targetID, tn[0].cell(), this.gs.config().boatAttackAmount(this.myPlayer, owner)) + // Border with enemy sorted by distance to click tile. + const borderWithDists = bordersWithDists.map(t => ({ + dist: manhattanDist(t.cell(), tile.cell()), + tile: t + })).sort((a, b) => a.dist - b.dist); + + + const enemyShoreDists = Array.from(bfs( + tile, + and((t) => t.isLand() && t.owner() == tile.owner(), dist(tile, 400)) + )).filter(t => t.isOceanShore()).map(t => ({ + dist: manhattanDist(t.cell(), tile.cell()), + tile: t + })).sort((a, b) => a.dist - b.dist); + + + + if (bordersWithDists.length == 0 && enemyShoreDists.length == 0) { + return + } + + + let borderTileClosest = 10000000 + let enemyShoreClosest = 10000 + if (bordersWithDists.length > 0) { + borderTileClosest = borderWithDists[0].dist + } + if (enemyShoreDists.length > 0) { + enemyShoreClosest = enemyShoreDists[0].dist + } + if (enemyShoreClosest < borderTileClosest) { + this.sendBoatAttackIntent(targetID, enemyShoreDists[0].tile.cell(), this.gs.config().boatAttackAmount(this.myPlayer, owner)) } else { this.sendAttackIntent(targetID, cell, this.gs.config().attackAmount(this.myPlayer, owner)) } diff --git a/src/core/Util.ts b/src/core/Util.ts index 409e262e7..17e30f53f 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -1,4 +1,3 @@ -import {functional} from "typia"; import {Cell, Player, Tile} from "./Game"; export function manhattanDist(c1: Cell, c2: Cell): number { @@ -70,7 +69,7 @@ export function calculateBoundingBox(borderTiles: ReadonlySet): {min: Cell return {min: new Cell(minX, minY), max: new Cell(maxX, maxY)} } -export function inscribed(outer: { min: Cell; max: Cell }, inner: { min: Cell; max: Cell }): boolean { +export function inscribed(outer: {min: Cell; max: Cell}, inner: {min: Cell; max: Cell}): boolean { return ( outer.min.x <= inner.min.x && outer.min.y <= inner.min.y && diff --git a/src/core/configuration/DevConfig.ts b/src/core/configuration/DevConfig.ts index 7e952596c..8bf624c26 100644 --- a/src/core/configuration/DevConfig.ts +++ b/src/core/configuration/DevConfig.ts @@ -16,7 +16,7 @@ export const devConfig = new class extends DefaultConfig { } numBots(): number { - return 350 + return 50 } startTroops(playerInfo: PlayerInfo): number { @@ -26,12 +26,11 @@ export const devConfig = new class extends DefaultConfig { return 5000 } - // troopAdditionRate(player: Player): number { - // let max = Math.sqrt(player.numTilesOwned()) * 2000 + 10000 + 10000 - // max = Math.min(max, 1_000_000) - - // let toAdd = 10 + (player.troops() + Math.sqrt(player.troops() * player.numTilesOwned())) / 200 * 100 - - // return Math.min(player.troops() + toAdd, max) - // } + troopAdditionRate(player: Player): number { + if (player.isBot()) { + return 10000 + } else { + return 100000 + } + } } \ No newline at end of file diff --git a/src/core/execution/BoatAttackExecution.ts b/src/core/execution/BoatAttackExecution.ts index 4b3a552b9..70f88eff4 100644 --- a/src/core/execution/BoatAttackExecution.ts +++ b/src/core/execution/BoatAttackExecution.ts @@ -63,9 +63,9 @@ export class BoatAttackExecution implements Execution { this.troops = Math.min(this.troops, this.attacker.troops()) this.attacker.removeTroops(this.troops) - this.src = this.closestShoreTileToTarget(this.attacker, this.cell) + this.src = this.closestShoreTile(this.attacker, this.cell) if (this.target.isPlayer()) { - this.dst = this.closestShoreTileToTarget(this.target, this.cell) + this.dst = this.closestShoreTile(this.target, this.cell) } else { this.dst = this.mg.tile(this.cell) } @@ -137,7 +137,7 @@ export class BoatAttackExecution implements Execution { return this.active } - private closestShoreTileToTarget(player: Player, target: Cell): Tile | null { + private closestShoreTile(player: Player, target: Cell): Tile | null { const shoreTiles = Array.from(player.borderTiles()).filter(t => t.isOceanShore()) if (shoreTiles.length == 0) { return null