diff --git a/src/main.ts b/src/main.ts
index 7d032d3..d9febc0 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -2,7 +2,7 @@
///
const versionMajor = 2;
-const versionMinor = 0;
+const versionMinor = 1;
let globalStartTime = 0;
let globalTimeout: number | null = null;
@@ -45,18 +45,17 @@ The game's source code on Github
const config = new GameConfig(versionMajor, versionMinor);
// debug values to make the game play faster while testing
- config.cfgTitheAmount = 1000;
- config.cfgTimeBetweenTithes = 5000;
- config.cfgCryptoReturnAmount = 100;
config.cfgCredibilityRestoreRate = 5;
config.cfgPastorRecruitRate = 0.5;
+ config.cfgTimeBetweenTithes = 5000;
+ config.cfgTitheAmount = 1000;
const renderer = new DebugRenderer();
renderer.onInitialRender = initialRender;
const state = config.generateState();
// re-run main loop immediately on user clicks
- state.onResourceClick.push((): void => {
+ state.onAction.push((): void => {
if (globalTimeout !== null) {
clearTimeout(globalTimeout);
gameLoop(state, renderer);
diff --git a/src/model/GameConfig.ts b/src/model/GameConfig.ts
index 7b43d0c..9c04cf8 100644
--- a/src/model/GameConfig.ts
+++ b/src/model/GameConfig.ts
@@ -4,6 +4,7 @@
///
///
///
+///
///
///
///
@@ -29,7 +30,8 @@ class GameConfig {
// general configs
public cfgInitialMax: ResourceNumber = {
- cryptoCurrency: 1000,
+ cryptoCurrency: 10000,
+ cryptoMarket: 100000000,
megaChurches: 2,
money: 500000,
followers: 5,
@@ -70,7 +72,10 @@ class GameConfig {
public cfgCredibilityFollowerLossRatio = 0.04;
public cfgCredibilityFollowerLossTime = 10000;
public cfgCredibilityRestoreRate = 0.25;
- public cfgCryptoReturnAmount = 1;
+ public cfgCryptoCurrencyMinimumValue = 1;
+ public cfgCryptoMarketAdjustAmount = 0.1;
+ public cfgCryptoMarketAdjustPeriod = 30000;
+ public cfgCryptoMarketGrowthBias = 0.1;
public cfgDefaultSellMultiplier = 0.5;
public cfgFollowerGainLossLogTimer = 10000;
public cfgPassiveMax = 100;
@@ -194,6 +199,7 @@ class GameConfig {
// add passive resources
state.addResource(ResourceKey.credibility, new Credibility(this));
+ state.addResource(ResourceKey.cryptoMarket, new CryptoMarket(this));
return state;
}
diff --git a/src/model/GameState.ts b/src/model/GameState.ts
index 1118ae3..2f063f5 100644
--- a/src/model/GameState.ts
+++ b/src/model/GameState.ts
@@ -3,7 +3,7 @@
class GameState {
public readonly config: GameConfig;
- public onResourceClick: Array<() => void> = [];
+ public onAction: Array<() => void> = [];
public logger: ILogger | null = null;
public now = 0;
@@ -70,6 +70,12 @@ class GameState {
}
}
+ public autoAction(): void {
+ for (const callback of this.onAction) {
+ callback();
+ }
+ }
+
public performAction(resourceKey: ResourceKey, actionIndex: number): void {
const resource = this._resources[resourceKey];
if (
@@ -83,7 +89,7 @@ class GameState {
const action = resource.userActions[actionIndex];
action.performAction(this);
- for (const callback of this.onResourceClick) {
+ for (const callback of this.onAction) {
callback();
}
}
diff --git a/src/model/resource/CryptoCurrency.ts b/src/model/resource/CryptoCurrency.ts
index 4a799a1..f5f6b4d 100644
--- a/src/model/resource/CryptoCurrency.ts
+++ b/src/model/resource/CryptoCurrency.ts
@@ -14,6 +14,8 @@ class CryptoCurrency extends Purchasable {
this.valueInWholeNumbers = false;
}
- public max: (state: GameState) => number = (state) =>
+ public isUnlocked = (_state: GameState): boolean => true;
+
+ public max = (state: GameState): number =>
state.config.cfgInitialMax.cryptoCurrency ?? 0;
}
diff --git a/src/model/resource/CryptoMarket.ts b/src/model/resource/CryptoMarket.ts
new file mode 100644
index 0000000..cfa8c7b
--- /dev/null
+++ b/src/model/resource/CryptoMarket.ts
@@ -0,0 +1,55 @@
+///
+
+class CryptoMarket extends Hidden {
+ private _adjustmentTime = 0;
+
+ constructor(config: GameConfig) {
+ super(
+ 'crypto market',
+ 'crypto markets',
+ 'How much money a single FaithCoin is worth'
+ );
+ this.value = config.cfgInitialCost.cryptoCurrency ?? 0;
+ }
+
+ public max = (state: GameState): number =>
+ state.config.cfgInitialMax.cryptoMarket ?? 0;
+
+ public advanceAction = (time: number, state: GameState): void => {
+ const crypto = state.resource.cryptoCurrency;
+ if (crypto === undefined) return;
+ this._adjustmentTime += time;
+ if (this._adjustmentTime >= state.config.cfgCryptoMarketAdjustPeriod) {
+ this._adjustmentTime = 0;
+ let adjustment =
+ this.value *
+ state.config.cfgCryptoMarketAdjustAmount *
+ 2 *
+ Math.random() -
+ this.value * state.config.cfgCryptoMarketAdjustAmount;
+ adjustment +=
+ this.value *
+ state.config.cfgCryptoMarketAdjustAmount *
+ Math.random() *
+ state.config.cfgCryptoMarketGrowthBias;
+ if (
+ this.value + adjustment <
+ state.config.cfgCryptoCurrencyMinimumValue
+ ) {
+ adjustment = state.config.cfgCryptoCurrencyMinimumValue - this.value;
+ }
+ //if (Math.abs(adjustment) > 0) {
+ this.addValue(adjustment, state);
+ state.log(
+ `FaithCoin just ${
+ adjustment > 0 ? 'increased' : 'decreased'
+ } in value by $${formatNumber(Math.abs(adjustment))}.`
+ );
+ //}
+ if (crypto?.cost !== undefined) {
+ crypto.cost.money = this.value;
+ state.autoAction(); // cause redraw
+ }
+ }
+ };
+}
diff --git a/src/model/resource/Hidden.ts b/src/model/resource/Hidden.ts
new file mode 100644
index 0000000..1c7249d
--- /dev/null
+++ b/src/model/resource/Hidden.ts
@@ -0,0 +1,21 @@
+///
+
+abstract class Hidden implements IResource {
+ public readonly resourceType = ResourceType.passive;
+ public readonly valueInWholeNumbers = false;
+ public value = 0;
+
+ constructor(
+ public readonly singularName: string,
+ public readonly pluralName: string,
+ public readonly description: string
+ ) {}
+
+ public addValue(amount: number, _state: GameState): void {
+ this.value += amount;
+ }
+
+ public isUnlocked(_state: GameState): boolean {
+ return true;
+ }
+}
diff --git a/src/model/resource/Money.ts b/src/model/resource/Money.ts
index 88fbe5c..abe21c8 100644
--- a/src/model/resource/Money.ts
+++ b/src/model/resource/Money.ts
@@ -42,11 +42,6 @@ class Money implements IResource {
public inc: (state: GameState) => number = (state) => {
let inc = 0;
- // crypto currency
- inc +=
- (state.resource.cryptoCurrency?.value ?? 0) *
- state.config.cfgCryptoReturnAmount;
-
// salaries
inc -=
(state.resource.pastors?.value ?? 0) *
diff --git a/src/model/resource/Passive.ts b/src/model/resource/Passive.ts
index 60391e5..c537b6a 100644
--- a/src/model/resource/Passive.ts
+++ b/src/model/resource/Passive.ts
@@ -5,8 +5,6 @@ abstract class Passive implements IResource {
public readonly valueInWholeNumbers = false;
public value = 0;
- public advanceAction?: (time: number, state: GameState) => void = undefined;
-
constructor(
public readonly label: string,
public readonly singularName: string,
diff --git a/src/model/resource/SharedTypes.ts b/src/model/resource/SharedTypes.ts
index 0484f80..63a2c87 100644
--- a/src/model/resource/SharedTypes.ts
+++ b/src/model/resource/SharedTypes.ts
@@ -22,6 +22,7 @@ enum ResourceKey {
pastors = 'pastors',
money = 'money',
cryptoCurrency = 'cryptoCurrency',
+ cryptoMarket = 'cryptoMarket',
tents = 'tents',
houses = 'houses',
churches = 'churches',
diff --git a/src/render/DebugRenderer.ts b/src/render/DebugRenderer.ts
index fd406ca..6c68479 100644
--- a/src/render/DebugRenderer.ts
+++ b/src/render/DebugRenderer.ts
@@ -14,7 +14,7 @@ class DebugRenderer implements IRenderer {
console.error('could not find game container');
return;
}
- state.onResourceClick.push((): void => {
+ state.onAction.push((): void => {
this._handleClick = true;
});
const style = document.createElement('link');