rebalance unit cost

This commit is contained in:
evanpelle
2024-12-09 13:05:32 -08:00
committed by Evan
parent d290054e5c
commit 63b0e89d8b
7 changed files with 183 additions and 72 deletions
+7 -2
View File
@@ -216,15 +216,20 @@
* bufix: mini map doesn't load in time DONE 12/7/2023
* bugfix: private game host game doesn't start DONE 12/8/2023
* add NA map DONE 12/8/2023
* add Oceania map 12/8/2023
* add Oceania map DONE 12/8/2023
* max price for units DONE 12/9/2024
* better unit scaling DONE 12/9/2024
* store in BigQuery
* make hard & impossible harder
* clicking on a player's name in the rank UI should teleport you to him (pretty useful to know who's who and to locate small nations)
* record commit hash of game
* record game winner
* add panama canal NA
* make boats work on lakes (& oceania)
* replay stored games
* max price for units
* when player dies, don't remove atom bombs
* remove alliance when player dies
* only check islands/clusters when being attacked
* alert on attack
* alert on unit captured or destroyed
* nuking an enemy and accidentally destroying a trade ship shouldn't break the alliance and make you a traitor
+105
View File
@@ -7,6 +7,7 @@
"name": "openfront-client",
"dependencies": {
"@datastructures-js/priority-queue": "^6.3.1",
"@google-cloud/bigquery": "^7.9.1",
"@google-cloud/storage": "^7.14.0",
"@types/dompurify": "^3.0.5",
"@types/express": "^4.17.21",
@@ -2351,6 +2352,92 @@
"node": ">=18"
}
},
"node_modules/@google-cloud/bigquery": {
"version": "7.9.1",
"resolved": "https://registry.npmjs.org/@google-cloud/bigquery/-/bigquery-7.9.1.tgz",
"integrity": "sha512-ZkcRMpBoFLxIh6TiQBywA22yT3c2j0f07AHWEMjtYqMQzZQbFrpxuJU2COp3tyjZ91ZIGHe4gY7/dGZL88cltg==",
"license": "Apache-2.0",
"dependencies": {
"@google-cloud/common": "^5.0.0",
"@google-cloud/paginator": "^5.0.2",
"@google-cloud/precise-date": "^4.0.0",
"@google-cloud/promisify": "^4.0.0",
"arrify": "^2.0.1",
"big.js": "^6.0.0",
"duplexify": "^4.0.0",
"extend": "^3.0.2",
"is": "^3.3.0",
"stream-events": "^1.0.5",
"uuid": "^9.0.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@google-cloud/bigquery/node_modules/arrify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/@google-cloud/bigquery/node_modules/big.js": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz",
"integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==",
"license": "MIT",
"engines": {
"node": "*"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/bigjs"
}
},
"node_modules/@google-cloud/bigquery/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@google-cloud/common": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-5.0.2.tgz",
"integrity": "sha512-V7bmBKYQyu0eVG2BFejuUjlBt+zrya6vtsKdY+JxMM/dNntPF41vZ9+LhOshEUH01zOHEqBSvI7Dad7ZS6aUeA==",
"license": "Apache-2.0",
"dependencies": {
"@google-cloud/projectify": "^4.0.0",
"@google-cloud/promisify": "^4.0.0",
"arrify": "^2.0.1",
"duplexify": "^4.1.1",
"extend": "^3.0.2",
"google-auth-library": "^9.0.0",
"html-entities": "^2.5.2",
"retry-request": "^7.0.0",
"teeny-request": "^9.0.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@google-cloud/common/node_modules/arrify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/@google-cloud/paginator": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz",
@@ -2373,6 +2460,15 @@
"node": ">=8"
}
},
"node_modules/@google-cloud/precise-date": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-4.0.0.tgz",
"integrity": "sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==",
"license": "Apache-2.0",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@google-cloud/projectify": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz",
@@ -8767,6 +8863,15 @@
"node": ">= 0.10"
}
},
"node_modules/is": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz",
"integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+1
View File
@@ -55,6 +55,7 @@
},
"dependencies": {
"@datastructures-js/priority-queue": "^6.3.1",
"@google-cloud/bigquery": "^7.9.1",
"@google-cloud/storage": "^7.14.0",
"@types/dompurify": "^3.0.5",
"@types/express": "^4.17.21",
-1
View File
@@ -64,7 +64,6 @@ export interface Config {
defensePostRange(): number
defensePostDefenseBonus(): number
falloutDefenseModifier(): number
maxUnitCost(): number
}
export interface Theme {
+66 -68
View File
@@ -8,10 +8,6 @@ import { pastelTheme } from "./PastelTheme";
export class DefaultConfig implements Config {
maxUnitCost(): number {
return 99_999_999
}
cityPopulationIncrease(): number {
return 250_000
}
@@ -38,71 +34,73 @@ export class DefaultConfig implements Config {
}
unitInfo(type: UnitType): UnitInfo {
const fn = () => {
switch (type) {
case UnitType.TransportShip:
return {
cost: () => 0,
territoryBound: false
}
case UnitType.Destroyer:
return {
cost: (p: Player) => (p.units(UnitType.Destroyer).length + 1) * 250_000,
territoryBound: false
}
case UnitType.Battleship:
return {
cost: (p: Player) => (p.units(UnitType.Battleship).length + 1) * 500_000,
territoryBound: false
}
case UnitType.Shell:
return {
cost: (p: Player) => 0,
territoryBound: false
}
case UnitType.Port:
return {
cost: (p: Player) => Math.pow(2, p.units(UnitType.Port).length) * 250_000,
territoryBound: true
}
case UnitType.AtomBomb:
return {
cost: () => 1_000_000,
territoryBound: false
}
case UnitType.HydrogenBomb:
return {
cost: () => 5_000_000,
territoryBound: false
}
case UnitType.TradeShip:
return {
cost: () => 0,
territoryBound: false
}
case UnitType.MissileSilo:
return {
cost: () => 1_000_000,
territoryBound: true
}
case UnitType.DefensePost:
return {
cost: (p: Player) => Math.pow(2, p.units(UnitType.DefensePost).length) * 100_000,
territoryBound: true
}
case UnitType.City:
return {
cost: (p: Player) => Math.pow(2, p.units(UnitType.City).length) * 250_000,
territoryBound: true
}
default:
assertNever(type)
}
switch (type) {
case UnitType.TransportShip:
return {
cost: () => 0,
territoryBound: false
}
case UnitType.Destroyer:
return {
cost: (p: Player) => (p.units(UnitType.Destroyer).length + 1) * 250_000,
territoryBound: false
}
case UnitType.Battleship:
return {
cost: (p: Player) => (p.units(UnitType.Battleship).length + 1) * 500_000,
territoryBound: false
}
case UnitType.Shell:
return {
cost: () => 0,
territoryBound: false
}
case UnitType.Port:
return {
cost: (p: Player) =>
Math.min(
10_000_000,
Math.pow(2, p.units(UnitType.Port).length) * 250_000
),
territoryBound: true
}
case UnitType.AtomBomb:
return {
cost: () => 1_000_000,
territoryBound: false
}
case UnitType.HydrogenBomb:
return {
cost: () => 5_000_000,
territoryBound: false
}
case UnitType.TradeShip:
return {
cost: () => 0,
territoryBound: false
}
case UnitType.MissileSilo:
return {
cost: () => 1_000_000,
territoryBound: true
}
case UnitType.DefensePost:
return {
cost: (p: Player) =>
Math.min(
500_000,
(p.units(UnitType.DefensePost).length + 1) * 100_000
),
territoryBound: true
}
case UnitType.City:
return {
cost: (p: Player) => Math.pow(2, p.units(UnitType.City).length) * 125_000,
territoryBound: true
}
default:
assertNever(type)
}
const ui = fn()
const oldCost = ui.cost
ui.cost = (p: Player) => Math.min(this.maxUnitCost(), oldCost(p))
return ui
}
defaultDonationAmount(sender: Player): number {
return Math.floor(sender.troops() / 3)
+1 -1
View File
@@ -5,7 +5,7 @@ export const devConfig = new class extends DefaultConfig {
unitInfo(type: UnitType): UnitInfo {
const info = super.unitInfo(type)
const oldCost = info.cost
info.cost = (p: Player) => oldCost(p) / 1000
// info.cost = (p: Player) => oldCost(p) / 1000
return info
}
maxUnitCost(): number {
+3
View File
@@ -1,7 +1,10 @@
import { GameConfig, GameID, GameRecord, GameRecordSchema, Turn } from "../core/Schemas";
import { Storage } from '@google-cloud/storage';
import { BigQuery } from '@google-cloud/bigquery';
const storage = new Storage();
const bigquery = new BigQuery();
export async function archive(gameRecord: GameRecord) {
try {