* deleted old maps

* fixed bug where NPC and Bots had same id
* NPCs spawn near IRL location
* NPCs have different strength (starting troops)
* game has more NPCs than before
* Needs more balancing
This commit is contained in:
evanpelle
2024-10-08 20:42:35 -07:00
parent 4059b53904
commit 7235b73b6c
13 changed files with 87 additions and 31 deletions
+3 -3
View File
@@ -18,9 +18,9 @@ export const devConfig = new class extends DefaultConfig {
return 100
}
// numBots(): number {
// return 0
// }
numBots(): number {
return 400
}
// allianceDuration(): Tick {
// return 10 * 10
+10 -7
View File
@@ -26,7 +26,8 @@ export class Executor {
private random: PseudoRandom = null
constructor(private gs: Game, private gameID: GameID) {
this.random = new PseudoRandom(simpleHash(gameID))
// Add one to avoid id collisions with bots.
this.random = new PseudoRandom(simpleHash(gameID) + 1)
}
createExecs(turn: Turn): Execution[] {
@@ -86,15 +87,17 @@ export class Executor {
fakeHumanExecutions(numFakes: number): Execution[] {
const execs = []
for (let i = 0; i < numFakes; i++) {
execs.push(
new FakeHumanExecution(new PlayerInfo(
this.usernames[this.random.nextInt(0, this.usernames.length)],
for (const nation of this.gs.nations()) {
execs.push(new FakeHumanExecution(
new PlayerInfo(
nation.name,
PlayerType.FakeHuman,
null,
this.random.nextID()
))
)
),
nation.cell,
nation.strength
))
}
return execs
}
+12 -3
View File
@@ -21,7 +21,7 @@ export class FakeHumanExecution implements Execution {
private isTraitor = false
constructor(private playerInfo: PlayerInfo) {
constructor(private playerInfo: PlayerInfo, private cell: Cell, private strength: number) {
this.random = new PseudoRandom(simpleHash(playerInfo.id))
}
@@ -41,12 +41,14 @@ export class FakeHumanExecution implements Execution {
this.randomLand().cell()
))
}
return
}
if (this.player == null) {
this.player = this.mg.players().find(p => p.id() == this.playerInfo.id)
if (this.player == null) {
//console.log(`player with id ${this.playerInfo.id} not found in FakeHumanExecution`)
return
} else {
this.player.setTroops(this.player.troops() * this.strength)
}
}
@@ -194,8 +196,15 @@ export class FakeHumanExecution implements Execution {
}
randomLand(): Tile {
const delta = 25
while (true) {
const cell = new Cell(this.random.nextInt(0, this.mg.width()), this.random.nextInt(0, this.mg.height()))
const cell = new Cell(
this.random.nextInt(this.cell.x - delta, this.cell.x + delta),
this.random.nextInt(this.cell.y - delta, this.cell.y + delta)
)
if (!this.mg.isOnMap(cell)) {
continue
}
const tile = this.mg.tile(cell)
if (tile.isLand() && !tile.hasOwner()) {
if (tile.terrain() == TerrainType.Mountain && this.random.chance(2)) {
+9
View File
@@ -11,6 +11,14 @@ export type Tick = number
export const AllPlayers = "AllPlayers" as const;
export class Nation {
constructor(
public readonly name: string,
public readonly cell: Cell,
public readonly strength: number,
) { }
}
export class EmojiMessage {
constructor(
public readonly sender: Player,
@@ -217,6 +225,7 @@ export interface Game {
ticks(): Tick
inSpawnPhase(): boolean
addExecution(...exec: Execution[]): void
nations(): Nation[]
config(): Config
displayMessage(message: string, type: MessageType, playerID: PlayerID | null): void
}
+13 -1
View File
@@ -1,7 +1,7 @@
import {info} from "console";
import {Config} from "../configuration/Config";
import {EventBus} from "../EventBus";
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Boat, BoatEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent} from "./Game";
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Boat, BoatEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation} from "./Game";
import {TerrainMap} from "./TerrainMapLoader";
import {PlayerImpl} from "./PlayerImpl";
import {TerraNulliusImpl} from "./TerraNulliusImpl";
@@ -24,6 +24,9 @@ export class GameImpl implements MutableGame {
// idCounter: PlayerID = 1; // Zero reserved for TerraNullius
map: TileImpl[][]
private nations_: Nation[] = []
_players: Map<PlayerID, PlayerImpl> = new Map<PlayerID, PlayerImpl>
private execs: Execution[] = []
private _width: number
@@ -47,6 +50,15 @@ export class GameImpl implements MutableGame {
this.map[x][y] = new TileImpl(this, this._terraNullius, cell, terrainMap.terrain(cell));
}
}
this.nations_ = terrainMap.nationMap.nations
.map(n => new Nation(
n.name,
new Cell(n.coordinates[0], n.coordinates[1]),
n.strength
))
}
nations(): Nation[] {
return this.nations_
}
createAllianceRequest(requestor: MutablePlayer, recipient: Player): MutableAllianceRequest {
+21 -2
View File
@@ -1,8 +1,27 @@
import {Cell, TerrainType} from './Game';
import binAsString from "!!binary-loader!../../../resources/maps/WorldMap.bin";
import worldMapInfo from "../../../resources/maps/WorldMap.json"
export interface NationMap {
name: string;
width: number;
height: number;
nations: Nation[];
}
export interface Nation {
coordinates: [number, number];
name: string;
strength: number;
}
export class TerrainMap {
constructor(public readonly tiles: Terrain[][], public readonly numLandTiles: number) { }
constructor(
public readonly tiles: Terrain[][],
public readonly numLandTiles: number,
public readonly nationMap: NationMap
) { }
terrain(cell: Cell): Terrain {
return this.tiles[cell.x][cell.y]
@@ -84,7 +103,7 @@ export async function loadTerrainMap(): Promise<TerrainMap> {
}
}
return new TerrainMap(terrain, numLand);
return new TerrainMap(terrain, numLand, worldMapInfo);
}
function logBinaryAsAscii(data: string, length: number = 8) {
+4
View File
@@ -26,4 +26,8 @@ declare module '*.txt' {
declare module '*.html' {
const content: string;
export default content;
}
declare module '*.json' {
const value: any;
export default value;
}
+3 -3
View File
@@ -1,7 +1,7 @@
import PImage from 'pureimage';
import path from 'path';
import fs from 'fs/promises';
import {createReadStream, createWriteStream} from 'fs';
import {createReadStream} from 'fs';
import {fileURLToPath} from 'url';
@@ -44,7 +44,7 @@ export class Terrain {
}
export async function loadTerrainMap(): Promise<void> {
const imagePath = path.resolve(__dirname, '..', '..', 'resources', 'maps', 'TopoWorldMap.png');
const imagePath = path.resolve(__dirname, '..', '..', 'resources', 'maps', 'WorldMap.png');
const readStream = createReadStream(imagePath);
const img = await PImage.decodePNGFromStream(readStream);
@@ -92,7 +92,7 @@ export async function loadTerrainMap(): Promise<void> {
processDistToLand(shorelineWaters, terrain)
processOcean(terrain)
const packed = packTerrain(terrain)
const outputPath = path.join(__dirname, '..', '..', 'resources', 'TopoWorldMap.bin');
const outputPath = path.join(__dirname, '..', '..', 'resources', 'maps', 'WorldMap.bin');
fs.writeFile(outputPath, packed);
}