mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 06:20:44 +00:00
* 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:
@@ -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.
@@ -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": [
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Vendored
+4
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user