summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Paul <n@nc0.fr>2024-03-18 08:55:45 +0100
committerNicolas Paul <n@nc0.fr>2024-03-18 08:55:45 +0100
commit5b7be9c3b28701e3f62d56547345c226b5d64390 (patch)
tree5340bc71be3331067776f86272bf79b4f0484f30
parent86928ce3d140e0772f46ca5ca70339c7571586a6 (diff)
Add stats calculation within the game loop
This patch changes the behavior of the calculation loop of a board (nextState) to keep track of the changes that happened during the round (number of cells that died or were born in a given team). These stats may be accessed by called the getStats() method on a World instance, which returns a !Stats object: const world = Life2.World(...); // ... const stats = world.getStats(); displayStats(stats); Close: https://github.com/nc0fr/life2/issues/8 Signed-off-by: Nicolas Paul <n@nc0.fr>
-rw-r--r--life2/game/index.js2
-rw-r--r--life2/game/world.js60
2 files changed, 60 insertions, 2 deletions
diff --git a/life2/game/index.js b/life2/game/index.js
index b8e8f9c..5d9277e 100644
--- a/life2/game/index.js
+++ b/life2/game/index.js
@@ -25,4 +25,4 @@ export {Board, Grid} from './board';
export {Cell} from './cell';
export {Rule, RuleFunction} from './rule';
export {RulesManager} from './rules_manager';
-export {World} from './world';
+export {Stats, World} from './world';
diff --git a/life2/game/world.js b/life2/game/world.js
index b9c52e0..d6981dc 100644
--- a/life2/game/world.js
+++ b/life2/game/world.js
@@ -30,6 +30,17 @@ import {Rule} from './rule';
import {RulesManager} from './rules_manager';
/**
+ * Stats about a board in general, and a state in particular.
+ * @typedef {Object} Stats
+ * @property {number} birthACount The number of cells that became TEAM_A.
+ * @property {number} deathACount The number of cells from TEAM_A that died.
+ * @property {number} birthBCount The number of cells that became TEAM_B.
+ * @property {number} deathBCount The number of cells from TEAM_B that died.
+ * @const
+ */
+export let Stats;
+
+/**
* The World class is the main interface to interact with the game state in
* real-time without coupling the game's internal state to external
* applications. The World is also the main manager of the game loop and
@@ -52,6 +63,28 @@ export class World {
* @type {!RulesManager}
*/
this.rules = new RulesManager(rules);
+
+ // Stats
+ /**
+ * The amount of cells from TEAM_A that died in the last game iteration.
+ * @type {number}
+ */
+ this.deathACount_ = 0;
+ /**
+ * The amount of cells from TEAM_B that died in the last game iteration.
+ * @type {number}
+ */
+ this.deathBCount_ = 0;
+ /**
+ * The amount of cells that became from TEAM_A in the last game iteration.
+ * @type {number}
+ */
+ this.birthACount_ = 0;
+ /**
+ * The amount of cells that became TEAM_A in the last game iteration.
+ * @type {number}
+ */
+ this.birthBCount_ = 0;
}
/**
@@ -99,10 +132,35 @@ export class World {
const states = rules.map((rule) => rule.execute(cell, neighbors))
.filter((state) => state != null);
- newGrid[x][y] = this.reduceStates_(states);
+ const newCell = this.reduceStates_(states);
+
+ if (newCell === Cell.EMPTY && cell === Cell.TEAM_A) {
+ this.deathACount_ += 1;
+ } else if (newCell === Cell.EMPTY && cell === Cell.TEAM_B) {
+ this.deathBCount_ += 1;
+ } else if (newCell === Cell.TEAM_A && cell !== Cell.TEAM_A) {
+ this.birthACount_ += 1;
+ } else if (newCell === Cell.TEAM_B && cell !== Cell.TEAM_B) {
+ this.birthBCount_ += 1;
+ }
+
+ newGrid[x][y] = newCell;
}
}
this.board.setGrid(newGrid);
}
+
+ /**
+ * Returns the stats of the world and of the last nextState().
+ * @return {!Stats}
+ */
+ getStats() {
+ return {
+ birthACount: this.birthACount_,
+ deathACount: this.deathACount_,
+ birthBCount: this.birthBCount_,
+ deathBCount: this.deathBCount_,
+ };
+ }
}