* 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
+1 -1
View File
@@ -162,9 +162,9 @@
* disable double tap on mobile DONE 10/6/2024
* donate troops button DONE 10/7/2024
* Make fake humans spawn by their country
* Test on android
* Increase disk size
* NPC more likely to accept alliance fewer alliance player has
* rewrite mobile input handling
* fake humans target enemies
* create private lobby menu
* block user inputs if too far behind server
Binary file not shown.
Binary file not shown.
Binary file not shown.
+11 -11
View File
@@ -2,14 +2,14 @@
"name": "World",
"width": 2000,
"height": 1000,
"countries": [
"nations": [
{
"coordinates": [
375,
272
],
"name": "USA",
"strength": 1
"strength": 3
},
{
"coordinates": [
@@ -17,7 +17,7 @@
136
],
"name": "Canada",
"strength": 1
"strength": 2
},
{
"coordinates": [
@@ -73,7 +73,7 @@
975
],
"name": "Antartica",
"strength": 1
"strength": 3
},
{
"coordinates": [
@@ -81,7 +81,7 @@
57
],
"name": "Greenland",
"strength": 1
"strength": 2
},
{
"coordinates": [
@@ -209,7 +209,7 @@
136
],
"name": "Russia",
"strength": 1
"strength": 3
},
{
"coordinates": [
@@ -225,7 +225,7 @@
328
],
"name": "China",
"strength": 1
"strength": 3
},
{
"coordinates": [
@@ -233,7 +233,7 @@
373
],
"name": "India",
"strength": 1
"strength": 2
},
{
"coordinates": [
@@ -265,7 +265,7 @@
657
],
"name": "Australia",
"strength": 1
"strength": 2
},
{
"coordinates": [
@@ -273,7 +273,7 @@
775
],
"name": "New Zealand",
"strength": 1
"strength": 0.5
},
{
"coordinates": [
@@ -353,7 +353,7 @@
627
],
"name": "Madagascar",
"strength": 1
"strength": 0.5
},
{
"coordinates": [
+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);
}