diff options
-rw-r--r-- | play.js | 13 | ||||
-rw-r--r-- | rules.js | 309 |
2 files changed, 231 insertions, 91 deletions
@@ -1045,21 +1045,30 @@ function on_update() { // Decree buttons action_button("build", "Build") + action_button("end_build", "End Build") action_button("demand", "Demand Obedience") action_button("end_demand", "End Demand Obedience") - action_button("collect", "Collect") + action_button("collect", "Collect Tribute") + action_button("end_collect", "End Collect Tribute") action_button("tax", "Tax") + action_button("end_tax", "End Tax") action_button("trade", "Trade") + action_button("end_trade", "End Trade") // MI buttons action_button("advance", "Advance") action_button("end_advance", "End Advance") action_button("amass", "Amass") action_button("mi_attack", "Attack & Plunder") - action_button("end_gifts", "End Compromising Gifts") + action_button("end_gifts", "Refuse Compromising Gifts") + + // Other buttons + action_button("end_cavalry", "End Cavalry Selection") action_button("next", "Next") action_button("undo", "Undo") + action_button("end_of_turn", "End your turn") + action_button("end_return", "End Influence Shift") return @@ -191,7 +191,7 @@ exports.setup = function (seed, scenario, _options) { resources: [ 12, 6, 7 ], vp: [ 18, 0, 0 ], prosperity: [ 0, 0, 0 ], - inf: [null, 1, 2], + inf: [null, 0, 0], tributary: 8191, // all 13 provinces control: [0, 0, 0], rebel: [null, 0, 0], // amir/raja rebel status @@ -207,8 +207,12 @@ exports.setup = function (seed, scenario, _options) { pieces: [], where: null, who: null, + event: 0 }, - decree: 0 + cav: null, + inf_shift: null, + decree: null, + vm: null, } if (scenario === "Solo") @@ -391,17 +395,20 @@ function goto_amass() { } function goto_build() { - init_command("Build") + init_decree("Build") game.state = "build" } -function goto_cavalry(n_cavalry) { - game.cmd.n_count = n_cavalry +function goto_cavalry(n, next) { + game.cav = { + "n": n, + "next": next + } game.state = "cavalry" } function goto_collect() { - init_command("Collect") + init_decree("Collect") game.state = "collect" } @@ -438,7 +445,7 @@ function end_conscript_space() { } function goto_demand() { - init_command("Demand Obedience") + init_decree("Demand Obedience") game.state = "demand" } @@ -540,12 +547,12 @@ function goto_rebel() { } function goto_tax() { - init_command("Tax") + init_decree("Tax") game.state = "tax" } function goto_trade() { - init_command("Trade") + init_decree("Trade") game.state = "trade" } @@ -575,28 +582,48 @@ states.eligible = { push_undo() game.cylinder[game.current] = SOP_COMMAND_DECREE game.decree = 1 - game.state = "command_decree" + game.state = "main_phase" }, event_command() { push_undo() game.cylinder[game.current] = SOP_EVENT_OR_COMMAND - game.state = "event_command" + game.cmd.event = 1 + game.state = "main_phase" }, lim_command() { push_undo() game.cylinder[game.current] = SOP_LIMITED_COMMAND game.cmd.limited = 1 - game.state = "lim_command" + game.state = "main_phase" }, } -states.command_decree = { - inactive: "Command & Decree", +states.main_phase = { + inactive: "Eligible Faction", prompt() { - view.prompt = "Select a Command and a Decree!" - gen_any_command() - if (game.decree === 1) + + if (game.cmd && game.cmd.limited === 1) { + view.prompt = "Select a limited Command." + gen_any_command() + } else if (game.cmd && game.decree === 1) { + view.prompt = "Select a Command and a Decree." + gen_any_command() + gen_any_decree() + } else if (game.cmd && game.cmd.event === 1) { + view.prompt = "Select a Command or the Event." + gen_any_command() + // gen_event() + } else if (game.cmd) { + view.prompt = "Select a Command." + gen_any_command() + } else if (game.decree === 1) { + view.prompt = "Select a Decree." gen_any_decree() + } else { + view.prompt = "End of turn." + view.actions.end_of_turn = 1 + } + }, build: goto_build, collect: goto_collect, @@ -608,32 +635,7 @@ states.command_decree = { rebel: goto_rebel, tax: goto_tax, trade: goto_trade, -} - -states.event_command = { - inactive: "Event or Command", - prompt() { - view.prompt = "Select the card Event or a Command!" - gen_any_command() - }, - conscript: goto_conscript, - govern: goto_govern, - march: goto_march, - rally: goto_rally, - rebel: goto_rebel, -} - -states.lim_command = { - inactive: "Limited command", - prompt() { - view.prompt = "Select a limited Command!" - gen_any_command() - }, - conscript: goto_conscript, - govern: goto_govern, - march: goto_march, - rally: goto_rally, - rebel: goto_rebel, + end_of_turn: resume_event_card, } states.advance = { @@ -647,6 +649,7 @@ states.advance = { gen_action_space(S_DELHI) }, space(s) { + push_summary() game.cmd.where = s game.state = "advance_space" } @@ -661,20 +664,23 @@ states.advance_space = { if (piece_space(p) === origin) gen_action_piece(p) - view.actions.end_advance = true + view.actions.end_advance = 1 }, piece(p) { + log_summary_move_from(p) place_piece(p, game.cmd.where) }, end_advance() { game.cmd.free -= 1 + log_space(game.cmd.where, "Advance") + pop_summary() goto_strategic_assistance() } } states.amass = { prompt() { - view.prompt = "Amass: Place three invaders into the Mountain Passes" + view.prompt = "Amass: Place up to three invaders into the Mountain Passes" gen_action_space(S_MONGOL_INVADERS) }, @@ -688,15 +694,18 @@ states.amass = { states.build = { prompt() { if (game.current === BK) - view.prompt = "Build: Select a Province with an Amir" + view.prompt = "Build: Select a Province with an Amir." else if (game.current === VE) - view.prompt = "Build: Select a Province with a Raja" + view.prompt = "Build: Select a Province with a Raja." - if (can_build()) { + if (game.decree === 1) { for (let s = first_space; s <= last_space; ++s) { if (can_build_in_space(s)) gen_action_space(s) } + } else { + view.prompt = "Build: Done." + view.actions.end_build = 1 } }, space(s) { @@ -708,60 +717,72 @@ states.build = { log_space(s, "Build") pop_summary() game.decree = 0 - game.state = "command_decree" - } + }, + end_build: end_decree, } states.cavalry = { prompt() { - view.prompt = `Gain Cavalry: Take ${game.cmd.n_count} calvary tokens` - gen_take_cavalry(game.current) - + if (game.cav.n > 0) { + view.prompt = `Gain Cavalry: Take ${game.cav.n} calvary tokens.` + gen_take_cavalry(game.current) + } else { + view.prompt = "Gain Cavalry: Done." + view.actions.end_cavalry = 1 + } }, token(c) { - game.cmd.n_count -= 1 + game.cav.n -= 1 set_cavalry_faction(c, game.current) - if (!game.cmd.n_count) { - game.state = game.cmd.save - } + // TODO: cavalry log + }, + end_cavalry() { + if (game.cav.next) + game.state = game.cav.next + else + end_card() } } states.collect = { prompt() { - view.prompt = `Collect Tribute: Collect ${collect_count()} from half the Tributaries prosperity` - - gen_action_resources(DS) + if (game.decree > 0) { + view.prompt = `Collect Tribute: Collect ${collect_count()} from half the Tributaries prosperity` + gen_action_resources(DS) + } else { + view.prompt = "Collect Tribute: Done." + view.actions.end_collect = 1 + } }, resources(f) { let c = collect_count() add_resources(DS, c) logi_resources(DS, c) game.decree = 0 - goto_cavalry(2) - } + goto_cavalry(2, "collect") + }, + end_collect: end_decree, } states.compromising_gifts = { prompt() { + view.prompt = "Compromising gifts: Reduce your influence by one to gain two Resources and two Cavalry tokens" + gen_action_influence(game.current) - 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 + view.actions.end_gifts = 1 }, 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) + game.inf_shift = { + "next": "cavalry", + } + game.cav = { + "n": 2, + "next": null + } + remove_influence(game.current) }, end_gifts() { end_card() @@ -828,10 +849,7 @@ states.demand = { to_obedient_space(s) log_space(s, "Demand Obedience") }, - end_demand() { - game.decree = 0 - game.state = "command_decree" - } + end_demand: end_decree, } states.govern = { @@ -1019,7 +1037,7 @@ states.rebel = { 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` + view.prompt = `Strategic Assistance: ${faction_name[game.current]} must execute ${n_command} Mongol Invaders Commands` gen_mi_command() }, @@ -1030,32 +1048,42 @@ states.strategic_assistance = { states.tax = { prompt() { - view.prompt = `Tax: Collect ${tax_count()} from Controlled Prosperity and Temples` + if (game.decree === 1) { + view.prompt = `Tax: Collect ${tax_count()} from Controlled Prosperity and Temples.` + gen_action_resources(VE) + } else { + view.prompt = "Tax: Done." + view.actions.end_tax = 1 + } - gen_action_resources(VE) }, resources(f) { let t = tax_count() add_resources(game.current, t) logi_resources(VE, t) game.decree = 0 - game.state = "command_decree" - } + }, + end_tax: end_decree } states.trade = { prompt() { - view.prompt = `Trade: Collect ${trade_count()} from Provinces with your presence` - - gen_action_resources(BK) + if (game.decree === 1) { + view.prompt = `Trade: Collect ${trade_count()} from Provinces with your presence.` + gen_action_resources(BK) + } else { + view.prompt = "Trade: Done." + view.actions.end_trade = 1 + } }, resources(f) { let t = trade_count() add_resources(game.current, t) logi_resources(BK, t) game.decree = 0 - goto_cavalry(trade_cavalry_count()) - } + goto_cavalry(trade_cavalry_count(), "trade") + }, + end_trade: end_decree, } @@ -1215,11 +1243,22 @@ function prompt_end_cmd(cost) { function end_command() { log_br() game.cmd = null - resume_event_card() + game.state = "main_phase" +} + +function end_decree() { + log_br() + game.decree = 0 + game.state = "main_phase" } /* DECREES */ +function init_decree(type) { + push_undo() + log_h2(faction_name[game.current] + " - " + type) +} + function gen_any_decree() { if (game.current === DS) { view.actions.collect = can_collect() ? 1 : 0 @@ -1473,6 +1512,14 @@ function gen_place_piece(faction, type) { return can_place } +function move_all_faction_piece_from(faction, type, from, to) { + let first = first_piece[faction][type] + let last = last_piece[faction][type] + for (let p = first; p <= last; ++p) + if (piece_space(p) === from) + set_piece_space(p, to) +} + function is_selected_cmd_space(s) { return game.cmd.spaces && set_has(game.cmd.spaces, s) } @@ -1572,6 +1619,90 @@ function trade_cavalry_count() { return 3; } +/* INFLUENCE */ + +function add_influence(faction) { + if (game.inf[faction] === 4) + return + + game.inf[faction]++ + + if (faction === BK && game.inf[faction] === 2) + move_all_faction_piece_from(BK, ELITE, S_BK_INF_2, AVAILABLE) + else if (faction === BK && game.inf[faction] === 4) + move_all_faction_piece_from(BK, ELITE, S_BK_INF_4, AVAILABLE) + else if (faction === VE) + move_all_faction_piece_from(VE, ELITE, S_VE_INF_1 + game.inf[faction] - 1, AVAILABLE) +} + +function remove_influence(faction) { + if (game.inf[faction] === 0) + return + + game.inf[faction]-- + + if (faction === BK && game.inf[faction] === 3) + troops_to_inf_track(BK, S_BK_INF_4) + else if (faction === BK && game.inf[faction] === 1) + troops_to_inf_track(BK, S_BK_INF_2) + else if (faction === VE) + troops_to_inf_track(VE, S_VE_INF_1 + game.inf[faction]) +} + +function troops_to_inf_track(faction, s) { + let n_available = Math.min(count_pieces(AVAILABLE, faction, ELITE), 2) + let moved = 0 + + let p = null + while (n_available > moved) { + p = find_piece(AVAILABLE, faction, ELITE) + place_piece(p, s) + moved++ + } + + if (moved < 2) { + goto_return_troops(faction, 2-moved, s) + } else { + game.state = game.inf_shift.next + } +} + +function goto_return_troops(faction, n_troops, s) { + push_summary() + game.inf_shift.n = n_troops + game.inf_shift.s = s + game.inf_shift.save_current = game.current + game.current = faction + game.state = "return_troops" +} + +states.return_troops = { + prompt() { + + if (game.inf_shift.n > 0) { + view.prompt = "Deccan Influence dwindles: Return troops to the influence track." + for (let p of iter_faction_pieces(game.current, ELITE)) + if (piece_space(p) >= 0 && piece_space(p) <= S_PUNJAB) + gen_action_piece(p) + } + else { + view.prompt = "Deccan Influence dwindles: Done." + view.actions.end_return = 1 + } + + }, + piece(p) { + log_summary_move_from(p) + place_piece(p, game.inf_shift.s) + game.inf_shift.n -= 1 + }, + end_return() { + pop_summary() + game.current = game.inf_shift.save_current + game.state = game.inf_shift.next + } +} + /* UTILS */ function add_resources(faction, n) { |