"use strict" const P1 = "Red" const P2 = "Blue" const P3 = "Yellow" const P4 = "Green" const player_names = [ P1, P2, P3, P4 ] const player_names_by_scenario = { "4P": [ P1, P2, P3, P4 ], "3P": [ P1, P2, P3 ], "2P": [ P1, P2 ], } const scenario_player_count = { "4P": 4, "3P": 3, "2P": 2, } const player_index = { [P1]: 0, [P2]: 1, [P3]: 2, [P4]: 3, "Observer": -1, } var game var view const states = {} exports.scenarios = [ "Standard" ] exports.roles = function (scenario, options) { if (options.players == 2) return [ P1, P2 ] if (options.players == 3) return [ P1, P2, P3 ] return [ P1, P2, P3, P4 ] } exports.setup = function (seed, scenario, options) { let players = options.players || 4 game = { seed: seed, log: [], undo: [], players: players, active: 0, state: "none", } return save_game() } function load_game(state) { game = state game.active = player_index[game.active] } function save_game() { game.active = player_names[game.active] return game } exports.action = function (state, player, action, arg) { load_game(state) let S = states[game.state] if (action in S) { S[action](arg) } else { if (action === "undo" && game.undo && game.undo.length > 0) pop_undo() else throw new Error("Invalid action: " + action) } return save_game() } exports.view = function (state, player_name) { let player = player_index[player_name] load_game(state) view = { log: game.log, active: player_names[game.active], prompt: null, } if (game.state === "game_over") { view.prompt = game.victory } else if (game.active !== player) { let inactive = states[game.state].inactive || game.state view.prompt = `Waiting for ${player_names[game.active]} \u2014 ${inactive}...` } else { view.actions = {} states[game.state].prompt() view.prompt = player_names[game.active] + ": " + view.prompt if (game.undo && game.undo.length > 0) view.actions.undo = 1 else view.actions.undo = 0 } save_game() return view } // STATES states.none = { prompt() {} }