diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 243 |
1 files changed, 219 insertions, 24 deletions
@@ -47,6 +47,7 @@ const last_space = S_PUNJAB const last_province = S_TAMILAKAM const faction_name = [ "Delhi Sultanate", "Bahmani Kingdom", "Vijayanagara Empire", "Mongol Invaders" ] +const faction_acronyms = [ "ds", "bk", "ve", "mi" ] exports.scenarios = [ "Standard", "Solo" ] @@ -89,14 +90,14 @@ exports.view = function (state, role) { let deck_size = Math.max(0, game.deck.length - 1) view = { + state: game.state, prompt: null, actions: null, log: game.log, current: game.current, vp: game.vp, resources: game.resources, - bk_inf: 0, - ve_inf: 0, + inf: game.inf, deck: [ this_card, deck_size, game.of_gods_and_kings ], cavalry: game.cavalry, cylinder: game.cylinder, @@ -104,6 +105,7 @@ exports.view = function (state, role) { tributary: game.tributary, control: game.control, rebel: game.rebel, + order: game.order, } if (game.result) { @@ -189,14 +191,14 @@ exports.setup = function (seed, scenario, _options) { resources: [ 12, 6, 7 ], vp: [ 18, 0, 0 ], prosperity: [ 0, 0, 0 ], - bk_inf: 0, - ve_inf: 0, + inf: [null, 1, 2], tributary: 8191, // all 13 provinces control: [0, 0, 0], rebel: [null, 0, 0], // amir/raja rebel status pieces: Array(104).fill(AVAILABLE), // piece locations cavalry: Array(10).fill(AVAILABLE), deck: [], + order: [], cmd: { type: null, limited: null, @@ -204,6 +206,7 @@ exports.setup = function (seed, scenario, _options) { spaces: [], pieces: [], where: null, + who: null, }, decree: 0 } @@ -230,7 +233,7 @@ exports.setup = function (seed, scenario, _options) { } function setup_deck() { - game.deck = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ] + game.deck = [ 1, 37, 2, 41, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ] } function setup_standard() { @@ -285,11 +288,19 @@ function this_card() { } function goto_card() { - log_h1("C" + this_card()) - if (this_card() === "todo") - console.log("todo") - else + if (this_card() >= 37 && this_card() <= 39) { + log_h1("Mongol Invaders C" + this_card()) + goto_mongol_invaders(BK) + } else if (this_card() >= 40 && this_card() <= 42) { + log_h1("Mongol Invaders C" + this_card()) + goto_mongol_invaders(VE) + } else { + log_h1("C" + this_card()) + adjust_eligibility(DS) + adjust_eligibility(BK) + adjust_eligibility(VE) resume_event_card() + } } function resume_event_card() { @@ -304,10 +315,6 @@ function resume_event_card() { function end_card() { clear_undo() - adjust_eligibility(DS) - adjust_eligibility(BK) - adjust_eligibility(VE) - array_remove(game.deck, 0) goto_card() } @@ -341,8 +348,8 @@ function did_option(e) { } function next_eligible_faction() { - let order = data.card_order[this_card()] - for (let faction of order) + game.order = data.card_order[this_card()] + for (let faction of game.order) if (is_eligible(faction)) return faction return -1 @@ -373,6 +380,16 @@ function goto_pass() { resume_event_card() } +function goto_advance() { + init_command("Advance") + game.state = "advance" +} + +function goto_amass() { + init_command("Amass") + game.state = "amass" +} + function goto_build() { init_command("Build") game.state = "build" @@ -388,6 +405,13 @@ function goto_collect() { game.state = "collect" } +function goto_compromising_gifts() { + if (game.inf[game.cmd.who] === 0) + end_card() + else + game.state = "compromising_gifts" +} + function goto_conscript() { init_command("Conscript") game.state = "conscript" @@ -462,6 +486,29 @@ function end_march_space() { game.state = "march" } +function goto_mi_attack() { + init_command("Attack & Plunder") + game.state = "mi_attack" +} + +function goto_mongol_invaders(faction) { + game.cmd = {} + game.current = faction + game.cmd.free = 2 + goto_strategic_assistance() +} + +function goto_strategic_assistance() { + if (game.cmd.free > 0) { + game.state = "strategic_assistance" + } + else { + game.cmd.free = 1 + goto_compromising_gifts() + } + +} + function goto_rally() { init_command("Rally") game.state = "rally" @@ -589,6 +636,55 @@ states.lim_command = { rebel: goto_rebel, } +states.advance = { + prompt() { + view.prompt = "Advance: Select the Advance destination" + + if (has_piece(S_MOUNTAIN_PASSES, MI, TROOPS)) + gen_action_space(S_PUNJAB) + + if (has_piece(S_PUNJAB, MI, TROOPS)) + gen_action_space(S_DELHI) + }, + space(s) { + game.cmd.where = s + game.state = "advance_space" + } +} + +states.advance_space = { + prompt() { + view.prompt = "Advance: Move any number of Mongol Invaders into destination" + + let origin = game.cmd.where === S_DELHI ? S_PUNJAB : S_MOUNTAIN_PASSES + for (let p = first_piece[MI][TROOPS]; p <= last_piece[MI][TROOPS]; ++p) + if (piece_space(p) === origin) + gen_action_piece(p) + + view.actions.end_advance = true + }, + piece(p) { + place_piece(p, game.cmd.where) + }, + end_advance() { + game.cmd.free -= 1 + goto_strategic_assistance() + } +} + +states.amass = { + prompt() { + view.prompt = "Amass: Place three invaders into the Mountain Passes" + + gen_action_space(S_MONGOL_INVADERS) + }, + space(s) { + amass() + game.cmd.free -= 1 + goto_strategic_assistance() + } +} + states.build = { prompt() { if (game.current === BK) @@ -619,15 +715,15 @@ states.build = { states.cavalry = { prompt() { view.prompt = `Gain Cavalry: Take ${game.cmd.n_count} calvary tokens` - gen_take_cavalry(game.current) + }, token(c) { game.cmd.n_count -= 1 set_cavalry_faction(c, game.current) - if (!game.cmd.n_count) - game.state = "command_decree" - + if (!game.cmd.n_count) { + game.state = game.cmd.save + } } } @@ -646,6 +742,32 @@ states.collect = { } } +states.compromising_gifts = { + prompt() { + + if (game.cmd.free === 1) { + view.prompt = "Compromising gifts: Reduce your influence by one to gain two Resources and two Cavalry tokens" + gen_action_influence(game.current) + } else { + view.prompt = "Compromising gifts: End gift exchange" + } + + view.actions.end_gifts = true + }, + inf() { + game.cmd.free = 0 + game.inf[game.current] -= 1 + log_h2(faction_acronyms[game.current] + "Compromising Gifts") + logi_resources(game.current, 2) + add_resources(game.current, 2) + game.cmd.save = "compromising_gifts" + goto_cavalry(2) + }, + end_gifts() { + end_card() + } +} + states.conscript = { prompt() { @@ -894,6 +1016,18 @@ states.rebel = { end_rebel: end_command, } +states.strategic_assistance = { + prompt() { + let n_command = (game.cmd.free === 2) ? "two" : "one" + view.prompt = `Strategic Assistance: ${faction_name[game.cmd.who]} must execute ${n_command} Mongol Invaders Commands` + + gen_mi_command() + }, + amass: goto_amass, + advance: goto_advance, + mi_attack: goto_mi_attack, +} + states.tax = { prompt() { view.prompt = `Tax: Collect ${tax_count()} from Controlled Prosperity and Temples` @@ -910,7 +1044,6 @@ states.tax = { } states.trade = { - // TODO : Add horses logic to trade prompt() { view.prompt = `Trade: Collect ${trade_count()} from Provinces with your presence` @@ -1141,6 +1274,64 @@ function trade_count() { return count } +/* MONGOL INVADERS COMMANDS */ + +function gen_mi_command() { + view.actions.amass = can_amass() ? 1 : 0 + view.actions.advance = can_advance() ? 1 : 0 + view.actions.mi_attack = can_mi_attack() ? 1 : 0 +} + +function can_advance() { + return (has_piece(S_MOUNTAIN_PASSES, MI, TROOPS) || has_piece(S_PUNJAB, MI, TROOPS)) +} + +function can_amass() { + return has_piece(AVAILABLE, MI, TROOPS) +} + +function can_mi_attack() { + let first = first_piece[MI][TROOPS] + let last = last_piece[MI][TROOPS] + for (let p = first; p <= last; ++p) + if (piece_space(p) >= 0) + return true + return false +} + +function amass() { + let n_available = Math.min(count_faction_pieces(AVAILABLE, MI), 3) + + // Add three to mountain pass + log_space(S_MOUNTAIN_PASSES, "Amass") + push_summary() + for (let i = 0; i < n_available; ++i) { + let p = find_piece(AVAILABLE, MI, TROOPS) + log_summary_place(p) + place_piece(p, S_MOUNTAIN_PASSES) + } + pop_summary() + + amass_trinkle_down(S_MOUNTAIN_PASSES, S_PUNJAB) + amass_trinkle_down(S_PUNJAB, S_DELHI) + +} + +function amass_trinkle_down(s_source, s_dest) { + let n = count_faction_pieces(s_source, MI) - 4 + if (n > 0) { + log_space(s_dest, "Amass") + push_summary() + for (let i = n; i > 0; --i) { + let p = find_piece(s_source, MI, TROOPS) + log_summary_place(p) + place_piece(p, s_dest) + } + pop_summary() + } +} + + /* TRIBUTARY AND REBELS */ function add_tributary(s) { @@ -1376,8 +1567,8 @@ function set_cavalry_faction(c, f) { } function trade_cavalry_count() { - if (game.bk_inf === 0) return 1; - if (game.bk_inf <= 2) return 2; + if (game.inf[BK] === 0) return 1; + if (game.inf[BK] <= 2) return 2; return 3; } @@ -1407,8 +1598,8 @@ function update_control() { function update_vp() { game.vp[DS] = game.prosperity[DS] - game.vp[BK] = game.prosperity[BK] + count_pieces_on_map(BK, DISC) + game.bk_inf - game.vp[VE] = game.prosperity[VE] + count_pieces_on_map(VE, DISC) + game.ve_inf + game.vp[BK] = game.prosperity[BK] + count_pieces_on_map(BK, DISC) + game.inf[BK] + game.vp[VE] = game.prosperity[VE] + count_pieces_on_map(VE, DISC) + game.inf[VE] } /* ACTIONS */ @@ -1419,6 +1610,10 @@ function gen_action(action, argument) { set_add(view.actions[action], argument) } +function gen_action_influence(faction) { + gen_action("inf", faction) +} + function gen_action_piece(p) { gen_action("piece", p) } |