118 lines
4.0 KiB
JavaScript
118 lines
4.0 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const vm = require('node:vm');
|
|
|
|
const ROOT = path.resolve(__dirname, '..');
|
|
|
|
function loadStrategy() {
|
|
const dataSrc = fs.readFileSync(path.join(ROOT, 'js/data.js'), 'utf8');
|
|
const utilsSrc = fs.readFileSync(path.join(ROOT, 'js/utils.js'), 'utf8');
|
|
const renderSrc = fs.readFileSync(path.join(ROOT, 'js/render.js'), 'utf8');
|
|
const strategySrc = fs.readFileSync(path.join(ROOT, 'js/strategy.js'), 'utf8');
|
|
const context = {
|
|
console,
|
|
Math,
|
|
Date,
|
|
window: {},
|
|
document: {
|
|
getElementById() { return null; },
|
|
body: { appendChild() {} },
|
|
createElement() { return { style: {}, appendChild() {}, remove() {}, setAttribute() {}, innerHTML: '', textContent: '' }; },
|
|
querySelector() { return null; },
|
|
querySelectorAll() { return []; },
|
|
},
|
|
showToast() {},
|
|
log() {},
|
|
canAffordBuilding() { return false; },
|
|
localStorage: {
|
|
_raw: null,
|
|
getItem() { return this._raw; },
|
|
setItem(_k, v) { this._raw = v; },
|
|
removeItem() { this._raw = null; },
|
|
},
|
|
EVENTS: [],
|
|
updateRates() {},
|
|
showOfflinePopup() {},
|
|
Combat: { renderCombatPanel() {} },
|
|
};
|
|
vm.createContext(context);
|
|
vm.runInContext(`${dataSrc}\n${utilsSrc}\n${renderSrc}\n${strategySrc}\nthis.__exports = { G, StrategyEngine, STRATEGY_LIBRARY, saveGame: typeof saveGame === 'function' ? saveGame : null, loadGame: typeof loadGame === 'function' ? loadGame : null };`, context);
|
|
return context.__exports;
|
|
}
|
|
|
|
test('strategy engine exposes eight game theory strategies', () => {
|
|
const { STRATEGY_LIBRARY } = loadStrategy();
|
|
assert.deepEqual(Object.keys(STRATEGY_LIBRARY).sort(), [
|
|
'cooperate', 'defect', 'generous', 'greedy', 'grim', 'minimax', 'random', 'tit_for_tat'
|
|
]);
|
|
});
|
|
|
|
test('strategy engine unlocks strategies progressively by knowledge', () => {
|
|
const { G, StrategyEngine } = loadStrategy();
|
|
G.strategicFlag = 1;
|
|
G.totalKnowledge = 16000;
|
|
const sse = new StrategyEngine();
|
|
assert.equal(sse.getUnlockedStrategies().length, 4);
|
|
G.totalKnowledge = 25000;
|
|
assert.equal(sse.getUnlockedStrategies().length, 6);
|
|
G.totalKnowledge = 60000;
|
|
assert.equal(sse.getUnlockedStrategies().length, 8);
|
|
});
|
|
|
|
test('round-robin tournament produces a sorted leaderboard', () => {
|
|
const { G, StrategyEngine } = loadStrategy();
|
|
G.strategicFlag = 1;
|
|
G.totalKnowledge = 60000;
|
|
const sse = new StrategyEngine();
|
|
const board = sse.runTournament(6);
|
|
assert.ok(board.length >= 8);
|
|
for (let i = 1; i < board.length; i++) {
|
|
assert.ok(board[i - 1].score >= board[i].score);
|
|
}
|
|
});
|
|
|
|
test('auto-tournament mode awards Yomi as knowledge over time', () => {
|
|
const { G, StrategyEngine } = loadStrategy();
|
|
G.strategicFlag = 1;
|
|
G.totalKnowledge = 60000;
|
|
G.autoTournamentUnlocked = true;
|
|
G.autoTournamentEnabled = true;
|
|
G.strategyPoints = 0;
|
|
const sse = new StrategyEngine();
|
|
sse.tick(31);
|
|
assert.ok(G.strategyPoints > 0);
|
|
assert.ok(G.totalKnowledge > 60000);
|
|
assert.ok(Array.isArray(G.strategyLeaderboard));
|
|
assert.ok(G.strategyLeaderboard.length > 0);
|
|
});
|
|
|
|
test('strategy state persists through save/load payload fields', () => {
|
|
const { G, saveGame, loadGame } = loadStrategy();
|
|
assert.equal(typeof saveGame, 'function');
|
|
assert.equal(typeof loadGame, 'function');
|
|
|
|
G.startedAt = Date.now();
|
|
G.strategyPoints = 42;
|
|
G.autoTournamentUnlocked = true;
|
|
G.autoTournamentEnabled = true;
|
|
G.strategyLastRunAt = 123456;
|
|
G.strategyLeaderboard = [{ id: 'tit_for_tat', score: 99 }];
|
|
|
|
saveGame();
|
|
|
|
G.strategyPoints = 0;
|
|
G.autoTournamentUnlocked = false;
|
|
G.autoTournamentEnabled = false;
|
|
G.strategyLastRunAt = 0;
|
|
G.strategyLeaderboard = [];
|
|
|
|
assert.equal(loadGame(), true);
|
|
assert.equal(G.strategyPoints, 42);
|
|
assert.equal(G.autoTournamentUnlocked, true);
|
|
assert.equal(G.autoTournamentEnabled, true);
|
|
assert.equal(G.strategyLastRunAt, 123456);
|
|
assert.equal(G.strategyLeaderboard[0].id, 'tit_for_tat');
|
|
});
|