parametric game fules. minor simulator refactoring
This commit is contained in:
@@ -14,7 +14,10 @@ export class Game {
|
||||
rules: GameRules,
|
||||
) {
|
||||
this.rules = rules;
|
||||
this.reset();
|
||||
}
|
||||
|
||||
public reset() {
|
||||
this.initResources();
|
||||
this.initGenerators();
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ export class ResourceGenerator {
|
||||
// }
|
||||
|
||||
public getGain(level?: number): ResourceSet {
|
||||
return this.rule.generationGain(level ?? this.level, this.game);
|
||||
return this.rule.generationGain(level ?? this.level, this.game).mul(this.getPeriod(level));
|
||||
}
|
||||
|
||||
public snapshot(): ResourceGeneratorSnapshot {
|
||||
|
||||
@@ -79,8 +79,14 @@ export class ResourceSet {
|
||||
return inst;
|
||||
}
|
||||
|
||||
public div(factor: number): ResourceSet {
|
||||
const inst = new ResourceSet();
|
||||
ResourceSet.transform(this.keys(), inst, (res) => this.get(res).divide(factor));
|
||||
return inst;
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return Array.from(this.items).map(([k, v]) => `${v} ${k}`).join(', ');
|
||||
return Array.from(this.items).map(([k, v]) => `${formatNumber(v)} ${k}`).join(', ');
|
||||
}
|
||||
|
||||
public toObject(): PartialResources {
|
||||
|
||||
+3
-3
@@ -5,8 +5,8 @@ export * from './rules';
|
||||
export * from './game';
|
||||
export * from './actions';
|
||||
|
||||
import { rules } from './rulesets/rules';
|
||||
import { rules, type GameRulesOptions } from './rulesets/rules';
|
||||
|
||||
export function makeGame(): Game {
|
||||
return new Game(rules)
|
||||
export function makeGame(options: GameRulesOptions): Game {
|
||||
return new Game(rules(options))
|
||||
};
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import Decimal from "break_eternity.js";
|
||||
import type { GameRules } from "../rules/GameRules";
|
||||
import { simpleResGen, resourceGen } from './utils';
|
||||
import { ResourceSet } from "../game";
|
||||
|
||||
export const rules: GameRules = {
|
||||
startResources: { prestigeMul: new Decimal(1) },
|
||||
generators: [
|
||||
{
|
||||
name: 'white',
|
||||
startingLevel: 1,
|
||||
resetProgressOnUpgrade: true,
|
||||
manualGeneration: true,
|
||||
period: (level) => level ? 3 : 0,
|
||||
isVisible: () => true,
|
||||
upgradePrice: () => ResourceSet.zero,
|
||||
isUpgradable: () => false,
|
||||
generationGain: (level, game) => resourceGen({ RED: { offset: 14, power: 2, factor: 1 } }, level),
|
||||
onGenerate: (level, game, gain) => game.resources.add(gain),
|
||||
},
|
||||
// simpleResGen({
|
||||
// name: 'red',
|
||||
// startingLevel: 1,
|
||||
// period: (level) => level === 0 ? 0 : Math.pow(0.95, level - 1),
|
||||
// upgradePrice: { RED: { offset: 3, power: 2.1, factor: 10 } },
|
||||
// generatesResources: { RED: { offset: 3, power: 1.5, factor: 1 } },
|
||||
// }),
|
||||
// ...['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet']
|
||||
...['red', 'orange', 'yellow']
|
||||
.map((color, idx) => simpleResGen({
|
||||
name: color,
|
||||
startingLevel: idx === 0 ? 1 : 0,
|
||||
period: (level) => level === 0 ? 0 : Math.pow(0.95, level) + 0.05,
|
||||
generatesResources: { RED: { offset: 2 * 15 ** idx, power: 1, factor: 1 * 15 ** idx } },
|
||||
// visibilityPrice: { RED: { offset: 5 * 10 ** (idx + 1) } },
|
||||
upgradePrice: { RED: { offset: 2 * 20 ** idx, power: 2.6, factor: 3 * 15 ** idx } }
|
||||
})),
|
||||
// {
|
||||
// name: 'prestige',
|
||||
// startingLevel: 0,
|
||||
// period: () => 0,
|
||||
// // generation: resourceGen({ prestigeMul: { offset: 0, power: 0.2, factor: 1 } }),
|
||||
// openPrice: (level) => ({ RED: new Decimal(50) }),
|
||||
// upgradePrice: () => ({}),
|
||||
// visibilityPrice: () => ({}),
|
||||
// manualProgressReset: true,
|
||||
// resetProgressOnUpgrade: true,
|
||||
// generation: (level, game, dryRun) => {
|
||||
// if (!dryRun) {
|
||||
// console.log('prestige ' + level);
|
||||
// game.generators.filter((gen) => gen.rule.name !== 'prestige').forEach((gen) => gen.reset());
|
||||
// ResourceSet.transform(
|
||||
// game.resources.keys().filter((res) => res != 'prestigeMul'),
|
||||
// game.resources,
|
||||
// () => Decimal.dZero,
|
||||
// );
|
||||
// }
|
||||
|
||||
// return resourceGen({ prestigeMul: { offset: 0, power: 1, factor: 1 } })(level, game);
|
||||
|
||||
// // game.resources.clear();
|
||||
// }
|
||||
// }
|
||||
],
|
||||
}
|
||||
@@ -1,37 +1,52 @@
|
||||
import Decimal from "break_eternity.js";
|
||||
import type { GameRules } from "../rules/GameRules";
|
||||
import { simpleResGen, resourceGen } from './utils';
|
||||
import { resourceGen, classicResGen } from './utils';
|
||||
import { ResourceSet } from "../game";
|
||||
|
||||
export const rules: GameRules = {
|
||||
startResources: { prestigeMul: new Decimal(1) },
|
||||
export type GameRulesOptions = {
|
||||
startingResources: number,
|
||||
upgradeBasePrice: number,
|
||||
generationBasePrice: number,
|
||||
upgradeFactor: number,
|
||||
generationPower: number,
|
||||
}
|
||||
|
||||
export const defaultGameRulesOptions: GameRulesOptions = {
|
||||
startingResources: 100,
|
||||
generationBasePrice: 0.2,
|
||||
generationPower: 0.3,
|
||||
upgradeBasePrice: 100,
|
||||
upgradeFactor: 1.01,
|
||||
}
|
||||
|
||||
export const rules: (options: GameRulesOptions) => GameRules = (options) => ({
|
||||
startResources: { RED: new Decimal(options.startingResources), prestigeMul: new Decimal(1) },
|
||||
generators: [
|
||||
{
|
||||
name: 'white',
|
||||
startingLevel: 1,
|
||||
resetProgressOnUpgrade: true,
|
||||
manualGeneration: true,
|
||||
period: (level) => level ? 3 : 0,
|
||||
isVisible: () => true,
|
||||
upgradePrice: () => ResourceSet.zero,
|
||||
isUpgradable: () => false,
|
||||
generationGain: (level, game) => resourceGen({ RED: { offset: 14, power: 2, factor: 1 } }, level),
|
||||
onGenerate: (level, game, gain) => game.resources.add(gain),
|
||||
},
|
||||
simpleResGen({
|
||||
name: 'red',
|
||||
startingLevel: 1,
|
||||
period: 1,
|
||||
upgradePrice: { RED: { offset: 3, power: 2.1, factor: 10 } },
|
||||
generatesResources: { RED: { offset: 3, power: 1.5, factor: 1 } },
|
||||
}),
|
||||
...['orange', 'yellow', 'green', 'cyan', 'blue', 'violet']
|
||||
.map((color, idx) => simpleResGen({
|
||||
// {
|
||||
// name: 'white',
|
||||
// startingLevel: 1,
|
||||
// resetProgressOnUpgrade: true,
|
||||
// manualGeneration: true,
|
||||
// period: (level) => level ? 3 : 0,
|
||||
// isVisible: () => true,
|
||||
// upgradePrice: () => ResourceSet.zero,
|
||||
// isUpgradable: () => false,
|
||||
// generationGain: (level, game) => resourceGen({ RED: { offset: 14, power: 2, factor: 1 } }, level),
|
||||
// onGenerate: (level, game, gain) => game.resources.add(gain),
|
||||
// },
|
||||
|
||||
// simpleResGen({
|
||||
// name: 'red',
|
||||
// startingLevel: 1,
|
||||
// period: (level) => level === 0 ? 0 : Math.pow(0.95, level - 1),
|
||||
// upgradePrice: { RED: { offset: 3, power: 2.1, factor: 10 } },
|
||||
// generatesResources: { RED: { offset: 3, power: 1.5, factor: 1 } },
|
||||
// }),
|
||||
// ...['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet']
|
||||
...['red']
|
||||
.map((color, idx) => classicResGen(options, {
|
||||
name: color,
|
||||
period: idx + 2,
|
||||
generatesResources: { RED: { power: 1.5, factor: (idx + 2) ** 2 } },
|
||||
// visibilityPrice: { RED: { offset: 5 * 10 ** (idx + 1) } },
|
||||
upgradePrice: { RED: { offset: 10 ** (idx + 2), power: 2.1, factor: 10 * 5 ** (idx + 1) } }
|
||||
startingLevel: 1,
|
||||
})),
|
||||
// {
|
||||
// name: 'prestige',
|
||||
@@ -60,4 +75,4 @@ export const rules: GameRules = {
|
||||
// }
|
||||
// }
|
||||
],
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Decimal from "break_eternity.js";
|
||||
import type { PartialResources, Resources } from "../types";
|
||||
import type { ResourceGeneratorRule } from "../rules/ResourceGeneratorRule";
|
||||
import { ResourceSet, type Game } from "../game";
|
||||
import type { GameRulesOptions } from "./rules";
|
||||
|
||||
type ResourceGenParams = {
|
||||
offset?: number,
|
||||
@@ -12,7 +12,7 @@ type ResourceGenParams = {
|
||||
type SimpleResGenParams = {
|
||||
name: string,
|
||||
startingLevel?: number,
|
||||
period: number,
|
||||
period: (level: number, game: Game) => number,
|
||||
visibilityPrice?: Partial<Record<string, ResourceGenParams>>,
|
||||
// openPrice: Partial<Record<string, ResourceGenParams>>,
|
||||
upgradePrice: Partial<Record<string, ResourceGenParams>>,
|
||||
@@ -65,11 +65,31 @@ export function simpleResGen(params: SimpleResGenParams): ResourceGeneratorRule
|
||||
startingLevel: params.startingLevel ?? 0,
|
||||
resetProgressOnUpgrade: true,
|
||||
manualGeneration: false,
|
||||
period: (level) => level ? params.period : 0,
|
||||
period: params.period,
|
||||
isVisible: (level, game) => game.resources.gte(resourceGen(params.visibilityPrice, level)),
|
||||
upgradePrice: (level, game) => resourceGen(params.upgradePrice, level),
|
||||
isUpgradable: (level, game, upgradePrice) => game.resources.gte(upgradePrice),
|
||||
generationGain: (level, game) => resourceGen(params.generatesResources, level),
|
||||
onGenerate: (level, game, gain) => game.resources.add(gain),
|
||||
}
|
||||
}
|
||||
|
||||
type ClassicResGenParams = {
|
||||
name: string,
|
||||
startingLevel: number,
|
||||
}
|
||||
|
||||
export function classicResGen(options: GameRulesOptions, params: ClassicResGenParams): ResourceGeneratorRule {
|
||||
return {
|
||||
name: params.name,
|
||||
startingLevel: params.startingLevel ?? 0,
|
||||
resetProgressOnUpgrade: true,
|
||||
manualGeneration: false,
|
||||
period: () => 1,
|
||||
isVisible: (level, game) => true,
|
||||
upgradePrice: (level, game) => ResourceSet.from({ RED: new Decimal(options.upgradeBasePrice * options.upgradeFactor ** level) }),
|
||||
isUpgradable: (level, game, upgradePrice) => game.resources.gte(upgradePrice),
|
||||
generationGain: (level, game) => ResourceSet.from({ RED: new Decimal(options.generationBasePrice * level ** options.generationPower) }),
|
||||
onGenerate: (level, game, gain) => game.resources.add(gain),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user