From 2368a22c888fd3916fd2f2c32330d328a0ddafa8 Mon Sep 17 00:00:00 2001 From: Phoscur Date: Mon, 6 May 2024 00:10:19 +0200 Subject: [PATCH] Add EngineService fromJSON, adapt a copy of resource & building examples --- src/app/engine/buildings.ts | 212 ++++++++++++++++++++++++++++++++++++ src/app/engine/economy.ts | 9 ++ src/app/engine/resources.ts | 107 ++++++++++++++++++ src/app/engine/service.ts | 36 ++++++ 4 files changed, 364 insertions(+) create mode 100644 src/app/engine/buildings.ts create mode 100644 src/app/engine/economy.ts create mode 100644 src/app/engine/resources.ts create mode 100644 src/app/engine/service.ts diff --git a/src/app/engine/buildings.ts b/src/app/engine/buildings.ts new file mode 100644 index 0000000..18925b6 --- /dev/null +++ b/src/app/engine/buildings.ts @@ -0,0 +1,212 @@ +import { + ResourceTypes, + EnergyTypes, + MetallicResource, + CrystallineResource, + LiquidResource, + zeroResources, + zeroEnergy, +} from './resources'; +export type Resources = ResourceTypes | EnergyTypes; +import { Stock, ResourceCollection } from '@phlame/engine'; +import { + Building, + BuildingIdentifier as BuildingID, + ProsumptionLookup, + RequirementLookup, +} from '@phlame/engine'; +import { BuildingRequirement } from '@phlame/engine'; + +export type BuildingIdentifier = BuildingID; + +export const requirements: RequirementLookup = { + // Metallic mine + 1: new BuildingRequirement( + 1, + ResourceCollection.fromArray([ + new MetallicResource(60), + new CrystallineResource(15), + ]), + 1.5, + [], + ), + // Crystalline mine + 2: new BuildingRequirement( + 2, + ResourceCollection.fromArray([ + new MetallicResource(48), + new CrystallineResource(24), + ]), + 1.6, + [], + ), + // Liquid mine + 3: new BuildingRequirement( + 3, + ResourceCollection.fromArray([ + new MetallicResource(225), + new CrystallineResource(75), + ]), + 1.5, + [], + ), + // power + 4: new BuildingRequirement( + 4, + ResourceCollection.fromArray([ + new MetallicResource(75), + new CrystallineResource(30), + ]), + 1.5, + [], + ), + // power based on Liquid + 12: new BuildingRequirement( + 12, + ResourceCollection.fromArray([ + new MetallicResource(48), + new CrystallineResource(24), + ]), + 1.8, + [ + { + type: 3, + level: 5, + }, + { + type: 113, + level: 3, + }, + ], + ), + // build buildings faster! TODO we need to add the time reducing factors + 14: new BuildingRequirement( + 14, // robots factor=1/(1+level) + ResourceCollection.fromArray([ + new MetallicResource(400), + new CrystallineResource(120), + new LiquidResource(200), + ]), + 2, + [], + ), // FASTER + 15: new BuildingRequirement( + 15, // nanites factor=1/2^level + ResourceCollection.fromArray([ + new MetallicResource(1000000), + new CrystallineResource(500000), + new LiquidResource(100000), + ]), + 2, + [ + { + type: 14, + level: 10, + }, + { + type: 108, + level: 10, + }, + ], + ), + // lab + 31: new BuildingRequirement( + 31, + ResourceCollection.fromArray([ + new MetallicResource(200), + new CrystallineResource(400), + new LiquidResource(200), + ]), + 2, + [], + ), + // tech (above 100) + 109: new BuildingRequirement( + 113, // computer + ResourceCollection.fromArray([ + new CrystallineResource(800), + new LiquidResource(400), + ]), + 2, + [ + { + type: 31, + level: 4, + }, + ], + ), + 113: new BuildingRequirement( + 113, // energy + ResourceCollection.fromArray([ + new CrystallineResource(800), + new LiquidResource(400), + ]), + 2, + [ + { + type: 31, + level: 1, + }, + ], + ), + // TODO add the remaining buildings and tech aswell as fleet (with ids above 200) +}; + +export const prosumption: ProsumptionLookup = { + 0: { + [ResourceTypes.Metallic]: (): number => { + return 0; + }, + [ResourceTypes.Crystalline]: (): number => { + return 0; + }, + [ResourceTypes.Liquid]: (): number => { + return 0; + }, + [EnergyTypes.Electricity]: (): number => { + return 0; + }, + [EnergyTypes.Heat]: (): number => { + return 0; + }, + }, + 1: { + [ResourceTypes.Metallic]: (lvl: number) => 30 * lvl * lvl ** 1.1, + [EnergyTypes.Electricity]: (lvl: number) => -10 * lvl * lvl ** 1.1, + }, + 2: { + [ResourceTypes.Crystalline]: (lvl: number) => 20 * lvl * lvl ** 1.1, + [EnergyTypes.Electricity]: (lvl: number) => -10 * lvl * lvl ** 1.1, + }, + 3: { + // TODO actually [ResourceTypes.Liquid]: (lvl, planet) => 10 * lvl * lvl ** 1.1 * (-0.002 * planet.maxTemperature + 1.28), + [ResourceTypes.Liquid]: (lvl: number): number => { + return 10 * lvl * lvl ** 1.1; + }, + [EnergyTypes.Electricity]: (lvl: number): number => { + return -10 * lvl * lvl ** 1.1; + }, + }, + 4: { + [EnergyTypes.Electricity]: (lvl: number): number => 20 * lvl * lvl ** 1.1, + }, + 12: { + [ResourceTypes.Liquid]: (lvl: number): number => { + return -10 * lvl * lvl ** 1.1; + }, + [EnergyTypes.Electricity]: (lvl: number): number => { + return 50 * lvl * lvl ** 1.1; + }, + }, +}; + +const b = new Building(12, requirements, prosumption, 1, 100); +const bUpgraded = new Building(12, requirements, prosumption, 2, 100); +const b0 = new Building(0, requirements, prosumption, 1, 50); // 0 times 0,5 is still 0 +const b3 = new Building(3, requirements, prosumption, 1, 100); +const b1 = new Building(1, requirements, prosumption, 2, 100); +const b2 = new Building(2, requirements, prosumption, 1, 100); +const b4 = new Building(4, requirements, prosumption, 1, 100); + +export const defaultBuildings: Building[] = []; +export const emptyStock = new Stock(zeroResources); diff --git a/src/app/engine/economy.ts b/src/app/engine/economy.ts new file mode 100644 index 0000000..597895a --- /dev/null +++ b/src/app/engine/economy.ts @@ -0,0 +1,9 @@ +import { Economy } from '@phlame/engine'; +import { Empire } from '@phlame/engine'; +import type { Zeitgeber } from '../signals/zeitgeber'; +import { defaultBuildings, emptyStock } from './buildings'; + +export function economyFactory(zeit: Zeitgeber) {} + +export const economy = new Economy('Phlameplanet', emptyStock, defaultBuildings); +export const empire = new Empire('Phlameland', []); diff --git a/src/app/engine/resources.ts b/src/app/engine/resources.ts new file mode 100644 index 0000000..1cc334f --- /dev/null +++ b/src/app/engine/resources.ts @@ -0,0 +1,107 @@ +import { BaseResources, Energy, Resource, ResourceCollection } from '@phlame/engine'; + +export enum ResourceTypes { + // (partially) liquid - reactive non-metals + Liquid = 'liquid', + // Hydrogen = 'H', // P1-1 + // Deuterium = 'D', // P1-1 (2H) + // Tritium = 'T', // P1-1 (3H) + // Helium = 'He', // P2-18 + // Lithium = 'Li', // P3-1-2 + // Biomass = 'biomass', + // Carbon = 'C', // P6-14-2 + // Nitrogen = 'N', // P7-15-3 + // Oxygen = 'O', // P8-16-2 + // Phosphorus = 'P', // P15-15-3 + // crystalline - metalloids + Crystalline = 'crystalline', + // Boron = 'B', // P5-13-2 + // Silicon = 'Si', // P14-14-3 + // metallic metals + Metallic = 'metallic', + // Cobalt = 'Co', // P27-9-4 + // Titanium = 'Ti', // P22-4-4 + // Iron = 'Fe', // P26-8-4 + // Copper = 'Cu', // P29-11-4 + // [...] need more Elements from the periodic table? https://ptable.com + // Uranium = 'U', // P92-3-7 + // TODO what do we have all those special resource types for! + // The current basic types should become placeholders or titles for resource summaries... +} +// TODO? refactor use "as const" (instead of enum) + +export enum EnergyTypes { + Electricity = 'energy', + Heat = 'heat', +} + +export type Types = ResourceTypes | EnergyTypes | BaseResources; + +// Add new resources to known resource types - only categories for now +const newResourceTypes: Types[] = [ + ResourceTypes.Metallic, + ResourceTypes.Crystalline, + ResourceTypes.Liquid, +]; +const newEnergyTypes: Types[] = [EnergyTypes.Electricity]; // TODO? , EnergyTypes.Heat]; +Resource.types.push(...newResourceTypes); +Energy.types.push(...newEnergyTypes); + +export class MetallicResource extends Resource { + constructor(amount: number) { + super(ResourceTypes.Metallic, amount); + } +} + +export class CrystallineResource extends Resource { + constructor(amount: number) { + super(ResourceTypes.Crystalline, amount); + } +} + +export class LiquidResource extends Resource { + constructor(amount: number) { + super(ResourceTypes.Liquid, amount); + } +} + +export class EnergyResource extends Energy { + constructor(amount: number) { + super(EnergyTypes.Electricity, amount); + } +} +/* * + * Heat as another energy example type, yes! + * Geoengineering allows to change a planets temperature for example, which has a huge impact on the ecology + * The game physics of temperature could be similar to energy level + * / +export class HeatResource extends Energy { + constructor(amount: number) { + super(EnergyTypes.Heat, amount); + } +}*/ + +export type ResourceType = MetallicResource | CrystallineResource | BaseResources; +export type EnergyType = EnergyResource; + +export const zeroResources = ResourceCollection.fromArray([ + new MetallicResource(0), + new CrystallineResource(0), + new LiquidResource(0), +]); +export const zeroEnergy: Energy = new EnergyResource(0); + +export class ResourceFactory { + fromJSON({ type, amount }: { type: Types; amount: number }): Resource { + switch (type) { + case ResourceTypes.Metallic: + return new MetallicResource(amount); + case ResourceTypes.Crystalline: + return new CrystallineResource(amount); + case ResourceTypes.Liquid: + return new LiquidResource(amount); + default: + return Resource.Null; + } + } +} diff --git a/src/app/engine/service.ts b/src/app/engine/service.ts new file mode 100644 index 0000000..0be1ad7 --- /dev/null +++ b/src/app/engine/service.ts @@ -0,0 +1,36 @@ +import { inject, injectable } from '@joist/di'; +import { + ComparableResource, + Economy, + ID, + Phlame, + ResourceCollection, + ResourceJSON, + Stock, +} from '@phlame/engine'; +import { Zeitgeber } from '../signals/zeitgeber'; +import { ResourceFactory, type Types } from './resources'; +import type { BuildingIdentifier } from './buildings'; + +@injectable +export class EngineService { + #zeit = inject(Zeitgeber); + #resource = inject(ResourceFactory); + + createPhlame(id: ID): Phlame { + return new Phlame(id, this.createEconomy([])); + } + createEconomy(resources: ResourceJSON[]): Economy { + return new Economy('Eco', this.createStock(resources)); + } + createStock(json: ResourceJSON[]): Stock { + return new Stock(this.createResources(json)); + } + createResources(json: ResourceJSON[]): ResourceCollection { + return ResourceCollection.fromArray(json.map((j) => this.createResource(j))); + } + createResource(json: ResourceJSON): ComparableResource { + const factory = this.#resource(); + return factory.fromJSON(json); + } +}