summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js369
1 files changed, 269 insertions, 100 deletions
diff --git a/rules.js b/rules.js
index 08edea8..2952679 100644
--- a/rules.js
+++ b/rules.js
@@ -1,108 +1,277 @@
-"use strict"
-
-var states = {}
-var game = null
-var view = null
-
-exports.scenarios = [ "Standard" ]
-
-exports.roles = [ "Anarchist", "Moderate", "Fascist" ]
-
+'use strict';
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.roles = exports.scenarios = void 0;
+exports.action = action;
+exports.view = game_view;
+exports.setup = setup;
+const data_1 = require("./data");
+const states = {};
+let game = {}; // = null
+var view = {}; // = null
+const ANARCHIST = 'Anarchist';
+const COMMUNIST = 'Communist';
+const MODERATE = 'Moderate';
+const ANARCHISTS_ID = 'a';
+const COMMUNISTS_ID = 'c';
+const MODERATES_ID = 'm';
+const { cards,
+// fronts
+ } = data_1.default;
+const faction_cards = {
+ [ANARCHIST]: make_list(37, 54),
+ [COMMUNIST]: make_list(19, 36),
+ [MODERATE]: make_list(1, 18),
+};
+const fascist_decks = {
+ 1: make_list(55, 62),
+};
+exports.scenarios = ['Standard'];
+exports.roles = [ANARCHIST, COMMUNIST, MODERATE];
function gen_action(action, argument) {
- if (!(action in view.actions))
- view.actions[action] = []
- view.actions[action].push(argument)
+ if (!(action in view.actions))
+ view.actions[action] = [];
+ view.actions[action].push(argument);
}
-
function gen_action_space(space) {
- gen_action("space", space)
+ gen_action('space', space);
}
-
function gen_action_piece(piece) {
- gen_action("piece", piece)
-}
-
-function gen_action_card(card) {
- gen_action("card", card)
-}
-
-exports.action = function (state, player, action, arg) {
- game = state
- let S = states[game.state]
- if (action in S)
- S[action](arg, player)
- else if (action === "undo" && game.undo && game.undo.length > 0)
- pop_undo()
- else
- throw new Error("Invalid action: " + action)
- return game
-}
-
-exports.view = function (state, player) {
- game = state
-
- view = {
- log: game.log,
- prompt: null,
- location: game.location,
- selected: game.selected,
- }
-
- if (player !== game.active) {
- let inactive = states[game.state].inactive || game.state
- view.prompt = `Waiting for ${game.active} to ${inactive}.`
- } else {
- view.actions = {}
- states[game.state].prompt()
- if (game.undo && game.undo.length > 0)
- view.actions.undo = 1
- else
- view.actions.undo = 0
- }
-
- return view
-}
-
-exports.setup = function (seed, scenario, options) {
- game = {
- seed: seed,
- state: null,
- active: "Anarchist",
- log: [],
- undo: [],
- }
-
- game.state = "move"
-
- return game
-}
-
+ gen_action('piece', piece);
+}
+// function gen_action_card(card) {
+// gen_action('card', card);
+// }
+function action(state, player, action, arg) {
+ game = state;
+ let S = states[game.state];
+ if (action in S)
+ S[action](arg, player);
+ else if (action === 'undo' && game.undo && game.undo.length > 0)
+ pop_undo();
+ else
+ throw new Error('Invalid action: ' + action);
+ return game;
+}
+function game_view(state, player) {
+ console.log('game_view', state);
+ console.log('player', player);
+ game = state;
+ const faction_id = get_faction_id(player);
+ view = {
+ log: game.log,
+ prompt: null,
+ location: game.location,
+ selected: game.selected,
+ current_events: game.current_events,
+ hand: game.hands[faction_id],
+ };
+ if (player !== game.active) {
+ let inactive = states[game.state].inactive || game.state;
+ view.prompt = `Waiting for ${game.active} to ${inactive}.`;
+ }
+ else {
+ view.actions = {};
+ states[game.state].prompt();
+ if (game.undo && game.undo.length > 0)
+ view.actions.undo = 1;
+ else
+ view.actions.undo = 0;
+ }
+ return view;
+}
+// #endregion
+// #region setup
+function setup(seed, _scenario, _options) {
+ game = {
+ seed: seed,
+ state: null,
+ active: ANARCHIST,
+ bag_of_glory: {
+ [ANARCHISTS_ID]: 1,
+ [COMMUNISTS_ID]: 1,
+ [MODERATES_ID]: 1,
+ },
+ bonuses: [data_1.ON, data_1.ON],
+ current_events: [],
+ fronts: {
+ a: 2,
+ m: 2,
+ n: 2,
+ s: 2,
+ },
+ hands: {
+ [ANARCHISTS_ID]: [
+ draw_card(faction_cards[ANARCHIST]),
+ draw_card(faction_cards[ANARCHIST]),
+ draw_card(faction_cards[ANARCHIST]),
+ draw_card(faction_cards[ANARCHIST]),
+ draw_card(faction_cards[ANARCHIST]),
+ ],
+ [COMMUNISTS_ID]: [
+ draw_card(faction_cards[COMMUNIST]),
+ draw_card(faction_cards[COMMUNIST]),
+ draw_card(faction_cards[COMMUNIST]),
+ draw_card(faction_cards[COMMUNIST]),
+ draw_card(faction_cards[COMMUNIST]),
+ ],
+ [MODERATES_ID]: [
+ draw_card(faction_cards[MODERATE]),
+ draw_card(faction_cards[MODERATE]),
+ draw_card(faction_cards[MODERATE]),
+ draw_card(faction_cards[MODERATE]),
+ draw_card(faction_cards[MODERATE]),
+ ],
+ },
+ hero_points: {
+ [ANARCHISTS_ID]: 2,
+ [COMMUNISTS_ID]: 2,
+ [MODERATES_ID]: 0,
+ },
+ initiative: MODERATES_ID,
+ tracks: [5, 5, 6, 3, 3],
+ log: [],
+ undo: [],
+ turn: 1,
+ year: 1,
+ };
+ fascist_event();
+ game.state = 'move';
+ return game;
+}
+// #endregion
states.move = {
- inactive: "move",
- prompt() {
- view.prompt = "Move a piece."
- for (let p = 0; p < 32; ++p)
- gen_action_piece(p)
- },
- piece(p) {
- game.selected = p
- game.state = "move_to"
- },
-}
-
+ inactive: 'move',
+ prompt() {
+ view.prompt = 'Move a piece.';
+ for (let p = 0; p < 32; ++p)
+ gen_action_piece(p);
+ },
+ // piece(p) {
+ // game.selected = p
+ // game.state = "move_to"
+ // },
+};
states.move_to = {
- inactive: "move",
- prompt() {
- view.prompt = "Move the piece to a space."
- for (let s = 0; s < 64; ++s)
- gen_action_space(s)
- },
- space(to) {
- game.location[game.selected] = to
- game.state = "move"
- if (game.active === PLAYER1)
- game.active = PLAYER2
- else
- game.active = PLAYER1
- },
+ inactive: 'move',
+ prompt() {
+ view.prompt = 'Move the piece to a space.';
+ for (let s = 0; s < 64; ++s)
+ gen_action_space(s);
+ },
+ // space(to) {
+ // game.location[game.selected] = to
+ // game.state = "move"
+ // if (game.active === PLAYER1)
+ // game.active = PLAYER2
+ // else
+ // game.active = PLAYER1
+ // },
+};
+function pop_undo() {
+ const save_log = game.log;
+ const save_undo = game.undo;
+ game = save_undo.pop();
+ save_log.length = game.log;
+ game.log = save_log;
+ game.undo = save_undo;
+}
+// #region CARDS
+// function draw_faction_card(faction: Player): CardId {
+// return draw_faction_cards(faction, 1)[0];
+// }
+// function draw_faction_cards(faction: Player, count: number = 1): CardId[] {
+// const drawnCards = [];
+// }
+function draw_card(deck) {
+ clear_undo();
+ let i = random(deck.length);
+ let c = deck[i];
+ set_delete(deck, c);
+ return c;
+}
+// #endregion
+// #region EVENTS
+function resolve_event_attack(target, value) {
+ switch (target) {
+ case 'v':
+ break;
+ case 'd':
+ break;
+ default:
+ game.fronts[target] += value;
+ }
+}
+function fascist_event() {
+ const deck = fascist_decks[game.year];
+ const cardId = draw_card(deck);
+ game.current_events.push(cardId);
+ const card = cards[cardId];
+ card.effects.forEach((effect) => {
+ switch (effect.type) {
+ case 'attack':
+ resolve_event_attack(effect.target, effect.value);
+ break;
+ case 'bonus':
+ break;
+ case 'hero_points':
+ break;
+ case 'track':
+ game.tracks[effect.target] += effect.value;
+ break;
+ }
+ });
+}
+// #endregion
+// #region UTILITY
+function clear_undo() {
+ if (game.undo.length > 0)
+ game.undo = [];
+}
+function get_faction_id(player) {
+ switch (player) {
+ case ANARCHIST:
+ return ANARCHISTS_ID;
+ case COMMUNIST:
+ return COMMUNISTS_ID;
+ case MODERATE:
+ return MODERATES_ID;
+ default:
+ throw new Error('Unknown player');
+ }
+}
+function make_list(first, last) {
+ let list = [];
+ for (let i = first; i <= last; i++)
+ list.push(i);
+ return list;
+}
+function random(range) {
+ // An MLCG using integer arithmetic with doubles.
+ // https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
+ // m = 2**35 − 31
+ return (game.seed = (game.seed * 200105) % 34359738337) % range;
+}
+function set_delete(set, item) {
+ let a = 0;
+ let b = set.length - 1;
+ while (a <= b) {
+ let m = (a + b) >> 1;
+ let x = set[m];
+ if (item < x)
+ b = m - 1;
+ else if (item > x)
+ a = m + 1;
+ else {
+ array_remove(set, m);
+ return;
+ }
+ }
+}
+// #endregion
+// #region ARRAY
+function array_remove(array, index) {
+ let n = array.length;
+ for (let i = index + 1; i < n; ++i)
+ array[i - 1] = array[i];
+ array.length = n - 1;
}