added logging
This commit is contained in:
parent
8cab5cdb29
commit
00f228b331
|
@ -1,9 +1,10 @@
|
||||||
.resource-type-container {
|
.resource-type-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.resource {
|
.resource {
|
||||||
|
min-width: 8em;
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
padding: 5px 10px;
|
padding: 0.25em 0.5em;
|
||||||
margin: 0 5px 5px 0;
|
margin: 0 0.5em 0.5em 0;
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/// <reference path="./GameState.ts" />
|
/// <reference path="./GameState.ts" />
|
||||||
/// <reference path="./resource/Money.ts" />
|
/// <reference path="./resource/Money.ts" />
|
||||||
/// <reference path="./resource/Religion.ts" />
|
/// <reference path="./resource/Religion.ts" />
|
||||||
/// <reference path="./resource/Savings.ts" />
|
|
||||||
|
|
||||||
class GameConfig {
|
class GameConfig {
|
||||||
public worldPopulation: number = 790000000;
|
public worldPopulation: number = 790000000;
|
||||||
|
@ -57,8 +56,7 @@ class GameConfig {
|
||||||
this.relNoneShare * this.worldPopulation));
|
this.relNoneShare * this.worldPopulation));
|
||||||
|
|
||||||
// add purchasable resources
|
// add purchasable resources
|
||||||
state.addResource('money', new Money(0));
|
state.addResource('money', new Money(100));
|
||||||
state.addResource('bonds', new Savings(0));
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/// <reference path="./logging/ILogger.ts" />
|
||||||
/// <reference path="./resource/IResource.ts" />
|
/// <reference path="./resource/IResource.ts" />
|
||||||
|
|
||||||
class GameState {
|
class GameState {
|
||||||
|
@ -5,6 +6,8 @@ class GameState {
|
||||||
private _resourceKeys: string[] = [];
|
private _resourceKeys: string[] = [];
|
||||||
|
|
||||||
public onResourceClick: (() => void)[] = [];
|
public onResourceClick: (() => void)[] = [];
|
||||||
|
public logger: ILogger = null;
|
||||||
|
public numberFormatDigits: number = 1;
|
||||||
|
|
||||||
public addResource (key: string, resource: IResource): void {
|
public addResource (key: string, resource: IResource): void {
|
||||||
this._resourceKeys.push(key);
|
this._resourceKeys.push(key);
|
||||||
|
@ -12,15 +15,24 @@ class GameState {
|
||||||
}
|
}
|
||||||
|
|
||||||
public advance (time: number): void {
|
public advance (time: number): void {
|
||||||
|
// advance each resource
|
||||||
for (const rkey of this._resourceKeys) {
|
for (const rkey of this._resourceKeys) {
|
||||||
if (this._resources[rkey].advanceAction !== null) {
|
if (this._resources[rkey].advanceAction !== null) {
|
||||||
this._resources[rkey].advanceAction(time, this);
|
this._resources[rkey].advanceAction(time, this);
|
||||||
}
|
}
|
||||||
const max: number | null = this._resources[rkey].max(this);
|
}
|
||||||
if (this._resources[rkey].inc(this) > 0
|
|
||||||
&& (max === null || this._resources[rkey].value < max)) {
|
// perform auto increments
|
||||||
this._resources[rkey].value +=
|
for (const rkey of this._resourceKeys) {
|
||||||
this._resources[rkey].inc(this) * time / 1000;
|
const max: number = this._resources[rkey].max
|
||||||
|
? this._resources[rkey].max(this)
|
||||||
|
: null;
|
||||||
|
const inc: number = this._resources[rkey].inc
|
||||||
|
? this._resources[rkey].inc(this)
|
||||||
|
: 0;
|
||||||
|
if (inc > 0 && (max === null
|
||||||
|
|| this._resources[rkey].value < max)) {
|
||||||
|
this._resources[rkey].value += inc * time / 1000;
|
||||||
}
|
}
|
||||||
if (max !== null && this._resources[rkey].value > max) {
|
if (max !== null && this._resources[rkey].value > max) {
|
||||||
this._resources[rkey].value = max;
|
this._resources[rkey].value = max;
|
||||||
|
@ -63,4 +75,31 @@ class GameState {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public formatNumber (num: number): string {
|
||||||
|
type vlookup = { value: number, symbol: string };
|
||||||
|
const lookup: vlookup[] = [
|
||||||
|
{ value: 1, symbol: "" },
|
||||||
|
{ value: 1e3, symbol: "K" },
|
||||||
|
{ value: 1e6, symbol: "M" },
|
||||||
|
{ value: 1e9, symbol: "G" },
|
||||||
|
{ value: 1e12, symbol: "T" },
|
||||||
|
{ value: 1e15, symbol: "P" },
|
||||||
|
{ value: 1e18, symbol: "E" }
|
||||||
|
];
|
||||||
|
const rx: RegExp = /\.0+$|(\.[0-9]*[1-9])0+$/;
|
||||||
|
const item: vlookup =
|
||||||
|
lookup.slice().reverse()
|
||||||
|
.find((i: vlookup): boolean => num >= i.value);
|
||||||
|
return item
|
||||||
|
? (num / item.value).toFixed(this.numberFormatDigits)
|
||||||
|
.replace(rx, "$1") + item.symbol
|
||||||
|
: num.toFixed(this.numberFormatDigits).replace(rx, "$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public log (text: string): void {
|
||||||
|
if (this.logger !== null) {
|
||||||
|
this.logger.msg(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
/// <reference path="./ILogger.ts" />
|
||||||
|
|
||||||
|
class ConsoleLogger implements ILogger {
|
||||||
|
public msg (text: string): void {
|
||||||
|
console.log(text); // tslint:disable-line
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
interface ILogger {
|
||||||
|
msg (text: string): void;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
/// <reference path="./Hidden.ts" />
|
||||||
|
|
||||||
|
class Credibility extends Hidden {
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/// <reference path="./IResource.ts" />
|
||||||
|
|
||||||
|
abstract class Hidden implements IResource {
|
||||||
|
public readonly resourceType: ResourceType = ResourceType.Hidden;
|
||||||
|
public readonly clickText: null = null;
|
||||||
|
public readonly clickDescription: null = null;
|
||||||
|
public readonly advanceAction: null = null;
|
||||||
|
public readonly cost: null = null;
|
||||||
|
public readonly clickAction: null = null;
|
||||||
|
public readonly name: null = null;
|
||||||
|
public readonly description: null = null;
|
||||||
|
|
||||||
|
protected _baseMax: number | null = null;
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
public value: number
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public inc (state: GameState): number | null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public max (state: GameState): number | null {
|
||||||
|
return this._baseMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isUnlocked (state: GameState): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +1,28 @@
|
||||||
enum ResourceType {
|
enum ResourceType {
|
||||||
Religion = 'religion',
|
Religion = 'religion',
|
||||||
Consumable = 'consumable',
|
Consumable = 'consumable',
|
||||||
Infrastructure = 'infrastructure'
|
Infrastructure = 'infrastructure',
|
||||||
|
Hidden = 'hidden'
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IResource {
|
interface IResource {
|
||||||
name: string;
|
name: string | null;
|
||||||
description: string;
|
description: string | null;
|
||||||
|
|
||||||
resourceType: ResourceType;
|
resourceType: ResourceType;
|
||||||
value: number;
|
value: number;
|
||||||
max: (state: GameState) => number | null;
|
|
||||||
inc: (state: GameState) => number | null;
|
|
||||||
cost: { [key: string]: number };
|
|
||||||
|
|
||||||
isUnlocked: (state: GameState) => boolean;
|
|
||||||
|
|
||||||
clickText: string;
|
clickText: string;
|
||||||
clickDescription: string;
|
clickDescription: string;
|
||||||
clickAction: (state: GameState) => void;
|
|
||||||
|
|
||||||
advanceAction: (time: number, state: GameState) => void;
|
clickAction (state: GameState): void;
|
||||||
|
|
||||||
|
cost: { [key: string]: number };
|
||||||
|
|
||||||
|
max (state: GameState): number | null;
|
||||||
|
inc (state: GameState): number | null;
|
||||||
|
|
||||||
|
isUnlocked (state: GameState): boolean;
|
||||||
|
|
||||||
|
advanceAction (time: number, state: GameState): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,19 +5,23 @@ class Money extends Purchasable {
|
||||||
public value: number,
|
public value: number,
|
||||||
) {
|
) {
|
||||||
super('Money', 'Used to purchase goods and services.');
|
super('Money', 'Used to purchase goods and services.');
|
||||||
this.clickText = 'Beg';
|
this.clickText = 'Collect Tithes';
|
||||||
this.clickDescription = 'Alms for the poor.';
|
this.clickDescription = 'Voluntary contributions from followers.';
|
||||||
this._baseMax = 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public isUnlocked (state: GameState): boolean {
|
public isUnlocked (state: GameState): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public inc (state: GameState): number {
|
protected _incrementAmount (state: GameState): number {
|
||||||
let baseInc: number = 0;
|
const plorg: IResource = state.getResource('plorg');
|
||||||
// bonds give $1/s
|
if (plorg.value === 0) {
|
||||||
baseInc += state.getResource('bonds').value;
|
state.log('You have no followers to collect from!');
|
||||||
return baseInc;
|
return 0;
|
||||||
|
}
|
||||||
|
// each follower gives you $10
|
||||||
|
const tithings: number = plorg.value * 10;
|
||||||
|
state.log(`You collected $${state.formatNumber(tithings)} from ${state.formatNumber(plorg.value)} followers.`);
|
||||||
|
return tithings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ abstract class Purchasable implements IResource {
|
||||||
public clickText: string = 'Purchase';
|
public clickText: string = 'Purchase';
|
||||||
public clickDescription: string = 'Purchase';
|
public clickDescription: string = 'Purchase';
|
||||||
|
|
||||||
public cost: { [key: string]: number } = null;
|
public cost: { [key: string]: number } | null = null;
|
||||||
|
|
||||||
protected _costMultiplier: { [key: string]: number } = null;
|
protected _costMultiplier: { [key: string]: number } | null = null;
|
||||||
protected _baseMax: number | null = null;
|
protected _baseMax: number | null = null;
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
@ -20,7 +20,7 @@ abstract class Purchasable implements IResource {
|
||||||
public clickAction (state: GameState): void {
|
public clickAction (state: GameState): void {
|
||||||
if (this.max(state) !== null && this.value >= this.max(state)) return;
|
if (this.max(state) !== null && this.value >= this.max(state)) return;
|
||||||
if (state.deductCost(this.cost)) {
|
if (state.deductCost(this.cost)) {
|
||||||
this.value += 1;
|
this.value += this._incrementAmount(state);
|
||||||
if (this._costMultiplier !== null
|
if (this._costMultiplier !== null
|
||||||
&& Object.keys(this._costMultiplier !== null)) {
|
&& Object.keys(this._costMultiplier !== null)) {
|
||||||
for (const rkey of Object.keys(this._costMultiplier)) {
|
for (const rkey of Object.keys(this._costMultiplier)) {
|
||||||
|
@ -45,4 +45,8 @@ abstract class Purchasable implements IResource {
|
||||||
public isUnlocked (state: GameState): boolean {
|
public isUnlocked (state: GameState): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected _incrementAmount (state: GameState): number {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class Religion implements IResource {
|
class Religion implements IResource {
|
||||||
public readonly resourceType: ResourceType = ResourceType.Religion;
|
public readonly resourceType: ResourceType = ResourceType.Religion;
|
||||||
public readonly clickText: string = null;
|
public readonly clickText: null = null;
|
||||||
public readonly clickDescription: string = null;
|
public readonly clickDescription: null = null;
|
||||||
public readonly advanceAction: (time: number) => void = null;
|
public readonly advanceAction: null = null;
|
||||||
public readonly cost: { [key: string]: number } = null;
|
public readonly cost: null = null;
|
||||||
|
|
||||||
public readonly max: () => null = (): null => null;
|
public readonly max: null = null;
|
||||||
public readonly inc: () => null = (): null => null;
|
public readonly inc: null = null;
|
||||||
public readonly clickAction: () => void = null;
|
public readonly clickAction: null = null;
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
public readonly name: string,
|
public readonly name: string,
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/// <reference path="./Purchasable.ts" />
|
|
||||||
|
|
||||||
class Savings extends Purchasable {
|
|
||||||
private _isUnlocked: boolean = false;
|
|
||||||
|
|
||||||
constructor (
|
|
||||||
public value: number,
|
|
||||||
) {
|
|
||||||
super('Savings', "Can't be spent, but grows money over time.");
|
|
||||||
this.cost = { 'money': 10 };
|
|
||||||
this._costMultiplier = { 'money': 1.1 };
|
|
||||||
}
|
|
||||||
|
|
||||||
public isUnlocked (state: GameState): boolean {
|
|
||||||
if (this._isUnlocked) return true;
|
|
||||||
if (state.getResource('money').value >= this.cost.money) {
|
|
||||||
this._isUnlocked = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected purchaseEffect (state: GameState): void {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
/// <reference path="../model/GameState.ts" />
|
/// <reference path="../model/GameState.ts" />
|
||||||
|
/// <reference path="../model/logging/ConsoleLogger.ts" />
|
||||||
/// <reference path="./IRenderer.ts" />
|
/// <reference path="./IRenderer.ts" />
|
||||||
|
|
||||||
class DebugRenderer implements IRenderer {
|
class DebugRenderer implements IRenderer {
|
||||||
|
@ -7,6 +8,7 @@ class DebugRenderer implements IRenderer {
|
||||||
|
|
||||||
public render (state: GameState): void {
|
public render (state: GameState): void {
|
||||||
if (!this._initialized) {
|
if (!this._initialized) {
|
||||||
|
state.logger = new ConsoleLogger();
|
||||||
const container: HTMLElement =
|
const container: HTMLElement =
|
||||||
document.getElementById('irreligious-game');
|
document.getElementById('irreligious-game');
|
||||||
this._initialized = true;
|
this._initialized = true;
|
||||||
|
@ -70,16 +72,17 @@ class DebugRenderer implements IRenderer {
|
||||||
el.getElementsByClassName('resource-value')[0];
|
el.getElementsByClassName('resource-value')[0];
|
||||||
const elT: Element =
|
const elT: Element =
|
||||||
el.getElementsByClassName('resource-max')[0];
|
el.getElementsByClassName('resource-max')[0];
|
||||||
elV.innerHTML = this.formatNumber(resource.value, 1);
|
elV.innerHTML = state.formatNumber(resource.value);
|
||||||
elT.innerHTML = resource.max(state) !== null
|
elT.innerHTML = resource.max !== null
|
||||||
? ` / ${this.formatNumber(resource.max(state), 1)}`
|
&& resource.max(state) !== null
|
||||||
|
? ` / ${state.formatNumber(resource.max(state))}`
|
||||||
: '';
|
: '';
|
||||||
if (this._handleClick) {
|
if (this._handleClick) {
|
||||||
if (resource.inc(state) > 0) {
|
if (resource.inc !== null && resource.inc(state) > 0) {
|
||||||
const elI: Element =
|
const elI: Element =
|
||||||
el.getElementsByClassName('resource-inc')[0];
|
el.getElementsByClassName('resource-inc')[0];
|
||||||
elI.innerHTML =
|
elI.innerHTML =
|
||||||
` +${this.formatNumber(resource.inc(state), 1)}/s`;
|
` +${state.formatNumber(resource.inc(state))}/s`;
|
||||||
}
|
}
|
||||||
const elC: HTMLCollectionOf<Element> =
|
const elC: HTMLCollectionOf<Element> =
|
||||||
el.getElementsByClassName('resource-cost');
|
el.getElementsByClassName('resource-cost');
|
||||||
|
@ -98,33 +101,13 @@ class DebugRenderer implements IRenderer {
|
||||||
if (resource.cost[rkey] !== undefined) {
|
if (resource.cost[rkey] !== undefined) {
|
||||||
if (cost !== '') cost += ', ';
|
if (cost !== '') cost += ', ';
|
||||||
if (rkey === 'money') {
|
if (rkey === 'money') {
|
||||||
cost += `$${this.formatNumber(resource.cost[rkey], 1)}`;
|
cost += `$${state.formatNumber(resource.cost[rkey])}`;
|
||||||
} else {
|
} else {
|
||||||
cost += `${this.formatNumber(resource.cost[rkey], 1)}
|
cost += `${state.formatNumber(resource.cost[rkey])}
|
||||||
${state.getResource(rkey).name}`;
|
${state.getResource(rkey).name}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private formatNumber (num: number, digits: number): string {
|
|
||||||
type vlookup = { value: number, symbol: string };
|
|
||||||
const lookup: vlookup[] = [
|
|
||||||
{ value: 1, symbol: "" },
|
|
||||||
{ value: 1e3, symbol: "K" },
|
|
||||||
{ value: 1e6, symbol: "M" },
|
|
||||||
{ value: 1e9, symbol: "G" },
|
|
||||||
{ value: 1e12, symbol: "T" },
|
|
||||||
{ value: 1e15, symbol: "P" },
|
|
||||||
{ value: 1e18, symbol: "E" }
|
|
||||||
];
|
|
||||||
const rx: RegExp = /\.0+$|(\.[0-9]*[1-9])0+$/;
|
|
||||||
const item: vlookup =
|
|
||||||
lookup.slice().reverse()
|
|
||||||
.find((i: vlookup): boolean => num >= i.value);
|
|
||||||
return item
|
|
||||||
? (num / item.value).toFixed(digits).replace(rx, "$1") + item.symbol
|
|
||||||
: num.toFixed(digits).replace(rx, "$1");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
"max-line-length": [
|
"max-line-length": [
|
||||||
true, {
|
true, {
|
||||||
"limit": 75,
|
"limit": 75,
|
||||||
"check-strings": true
|
"check-strings": true,
|
||||||
|
"ignore-pattern": "\\s+state\\.log\\("
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"whitespace": [
|
"whitespace": [
|
||||||
|
|
Reference in New Issue