From aca5c93a8bb86fd0b8e4d063b614d1e807aff564 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 30 Oct 2024 00:54:01 +0100 Subject: Two-player, and shift saxony after oos elimination. --- rules.js | 411 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 303 insertions(+), 108 deletions(-) (limited to 'rules.js') diff --git a/rules.js b/rules.js index 9a1395b..8b4303e 100644 --- a/rules.js +++ b/rules.js @@ -20,22 +20,27 @@ const R_MARIA_THERESA = "Maria Theresa" const R_PLAYER_A = "Player A" const R_PLAYER_B = "Player B" -exports.roles = [ - R_MARIA_THERESA, - R_FREDERICK, - R_LOUIS_XV -] - -const SCENARIO_INDEX = { - "Advanced": 0, - "Introductory": 1, -} +const ROLES_3P = [ R_MARIA_THERESA, R_FREDERICK, R_LOUIS_XV ] +const ROLES_2P = [ R_PLAYER_A, R_PLAYER_B ] exports.scenarios = [ "Advanced", + "Advanced 2P", "Introductory", + "Introductory 2P", ] +exports.roles = function (scenario, _options) { + switch (scenario) { + case "Advanced": + case "Introductory": + return ROLES_3P + case "Advanced 2P": + case "Introductory 2P": + return ROLES_2P + } +} + const data = require("./data.js") const political_cards = require("./cards.js") @@ -61,7 +66,13 @@ const SET_ASIDE_FRANCE = 4 const SET_ASIDE_PRUSSIA = 5 const power_name = [ "France", "Prussia", "Pragmatic Army", "Austria", "Bavaria", "Saxony" ] -const power_class = [ "france", "prussia", "pragmatic", "austria", "bavaria", "saxony" ] +const power_class = [ + "france", "prussia", "pragmatic", "austria", "bavaria", "saxony", + "france bavaria", + "prussia saxony", + "austria pragmatic", + "austria pragmatic saxony", +] const F_EMPEROR_FRANCE = 1 const F_EMPEROR_AUSTRIA = 2 @@ -74,6 +85,10 @@ const F_SAXONY_TC_ONCE = 128 // only draw TCs once per turn const F_FRANCE_REDUCED = 256 const F_PRUSSIA_NEUTRAL = 512 const F_MOVE_FLANDERS = 1024 +const F_INTRODUCTORY = 2048 +const F_TWO_PLAYER = 4096 +const F_PLAYER_A_PICK = 8192 // picked PC card +const F_PLAYER_B_PICK = 16384 const SPADES = 0 const CLUBS = 1 @@ -87,11 +102,11 @@ const ELIMINATED = data.cities.name.length const ARENBERG = 17 const SAXONY_GENERAL = 19 -const SAXONY_TRAIN = 29 const PRUSSIAN_TRAIN_2 = 23 const all_powers = [ 0, 1, 2, 3, 4, 5 ] const all_major_powers = [ 0, 1, 2, 3 ] +const all_minor_powers = [ 4, 5 ] const all_power_generals = [ [ 0, 1, 2, 3, 4 ], @@ -462,6 +477,11 @@ function all_controlled_powers(pow) { case P_PRAGMATIC: return all_powers_pragmatic case P_AUSTRIA: + if (is_two_player() && !is_intro()) { + if (is_saxony_austrian()) + return all_powers_pragmatic_austria_saxony + return all_powers_pragmatic_austria + } if (is_saxony_austrian()) return all_powers_austria_saxony return all_powers_austria @@ -479,6 +499,11 @@ function all_controlled_generals(pow) { case P_PRAGMATIC: return all_power_generals[P_PRAGMATIC] case P_AUSTRIA: + if (is_two_player() && !is_intro()) { + if (is_saxony_austrian()) + return all_austria_pragmatic_saxony_generals + return all_austria_pragmatic_generals + } if (is_saxony_austrian()) return all_austria_saxony_generals return all_power_generals[P_AUSTRIA] @@ -496,6 +521,11 @@ function all_controlled_trains(pow) { case P_PRAGMATIC: return all_power_trains[P_PRAGMATIC] case P_AUSTRIA: + if (is_two_player() && !is_intro()) { + if (is_saxony_austrian()) + return all_austria_pragmatic_saxony_trains + return all_austria_pragmatic_trains + } if (is_saxony_austrian()) return all_austria_saxony_trains return all_power_trains[P_AUSTRIA] @@ -726,6 +756,10 @@ const all_silesian_major_fortresses = set_intersect(data.type.major_fortress, da const all_core_austria_cities = data.country.Austria.filter(is_bohemia_space) const all_core_austria_fortresses = all_home_country_fortresses[P_AUSTRIA].filter(is_bohemia_space) +const all_core_austria_and_silesia_fortresses = set_union( + all_core_austria_fortresses, + all_silesian_fortresses +) const all_prussian_and_silesian_fortresses = set_union( all_home_country_fortresses[P_PRUSSIA], @@ -847,7 +881,6 @@ function set_control_of_fortress(s, pow) { map_delete(game.victory, s) } - function is_space_protected_by_piece(s, p) { return set_has(protect_range[s], game.pos[p]) } @@ -867,11 +900,11 @@ function is_protected_from_conquest(s) { /* STATE */ function is_intro() { - return game.scenario & 1 + return game.flags & F_INTRODUCTORY } function is_two_player() { - return game.scenario & 2 + return game.flags & F_TWO_PLAYER } const tc_per_turn_table = [ 5, 3, 3, 5, 1, 1 ] @@ -925,6 +958,26 @@ function tc_per_turn() { } function player_from_power(pow) { + if (is_two_player()) { + switch (pow) { + case P_FRANCE: + return R_PLAYER_A + case P_PRUSSIA: + return R_PLAYER_A + case P_PRAGMATIC: + return R_PLAYER_B + case P_AUSTRIA: + return R_PLAYER_B + case P_SAXONY: + if (is_saxony_prussian()) + return R_PLAYER_A + else + return R_PLAYER_B + case P_BAVARIA: + return R_PLAYER_A + } + } + switch (pow) { case P_FRANCE: return R_LOUIS_XV @@ -1045,7 +1098,7 @@ function has_enemy_piece(to) { function has_non_cooperative_general(to) { for (let other of all_non_coop_powers(game.power)) - for (let p of all_controlled_generals(other)) + for (let p of all_power_generals[other]) if (game.pos[p] === to) return true return false @@ -1139,6 +1192,7 @@ const advanced_sequence_of_play = [ { power: P_FRANCE, action: goto_tactical_cards }, { power: P_BAVARIA, action: goto_tactical_cards }, { power: P_FRANCE, action: goto_supply }, + { power: P_BAVARIA, action: goto_supply }, { power: P_FRANCE, action: init_movement }, { power: P_FRANCE, action: goto_movement_global }, { power: P_FRANCE, action: end_movement }, @@ -1148,16 +1202,9 @@ const advanced_sequence_of_play = [ { power: P_PRUSSIA, action: start_action_stage }, { power: P_PRUSSIA, action: goto_tactical_cards }, - { - power: P_SAXONY, - action() { - if (is_saxony_prussian()) - goto_tactical_cards() - else - next_sequence_of_play() - }, - }, + { power: P_SAXONY, action: goto_tactical_cards, condition: is_saxony_prussian }, { power: P_PRUSSIA, action: goto_supply }, + { power: P_SAXONY, action: goto_supply, condition: is_saxony_prussian }, { power: P_PRUSSIA, action: init_movement }, { power: P_PRUSSIA, action: goto_movement_global }, { power: P_PRUSSIA, action: end_movement }, @@ -1167,18 +1214,10 @@ const advanced_sequence_of_play = [ { power: P_PRUSSIA, action: goto_prussia_annexes_silesia }, { power: P_AUSTRIA, action: start_action_stage }, - { power: P_AUSTRIA, action: goto_tactical_cards }, - { - power: P_SAXONY, - action() { - if (is_saxony_prussian()) - next_sequence_of_play() - else - goto_tactical_cards() - }, - }, + { power: P_SAXONY, action: goto_tactical_cards, condition: is_saxony_austrian }, { power: P_AUSTRIA, action: goto_supply }, + { power: P_SAXONY, action: goto_supply, condition: is_saxony_austrian }, { power: P_PRAGMATIC, action: goto_tactical_cards }, { power: P_PRAGMATIC, action: goto_supply }, @@ -1202,6 +1241,55 @@ const advanced_sequence_of_play = [ { power: P_FRANCE, action: goto_end_turn }, ] +const two_player_sequence_of_play = [ + { power: P_AUSTRIA, action: goto_place_hussars }, + + { power: P_FRANCE, action: start_action_stage }, + { power: P_FRANCE, action: goto_tactical_cards }, + { power: P_BAVARIA, action: goto_tactical_cards }, + { power: P_FRANCE, action: goto_supply }, + { power: P_BAVARIA, action: goto_supply }, + { power: P_FRANCE, action: init_movement }, + { power: P_FRANCE, action: goto_movement_global }, + { power: P_FRANCE, action: end_movement }, + { power: P_FRANCE, action: goto_combat }, + { power: P_FRANCE, action: end_action_stage }, + { power: P_FRANCE, action: goto_france_reduces_military_objectives }, + + { power: P_PRUSSIA, action: start_action_stage }, + { power: P_PRUSSIA, action: goto_tactical_cards }, + { power: P_SAXONY, action: goto_tactical_cards, condition: is_saxony_prussian }, + { power: P_PRUSSIA, action: goto_supply }, + { power: P_SAXONY, action: goto_supply, condition: is_saxony_prussian }, + { power: P_PRUSSIA, action: init_movement }, + { power: P_PRUSSIA, action: goto_movement_global }, + { power: P_PRUSSIA, action: end_movement }, + { power: P_PRUSSIA, action: goto_combat }, + { power: P_PRUSSIA, action: end_action_stage }, + { power: P_PRUSSIA, action: goto_prussia_ends_neutrality }, + { power: P_PRUSSIA, action: goto_prussia_annexes_silesia }, + + { power: P_AUSTRIA, action: start_action_stage }, + { power: P_AUSTRIA, action: goto_tactical_cards }, + { power: P_SAXONY, action: goto_tactical_cards, condition: is_saxony_austrian }, + { power: P_PRAGMATIC, action: goto_tactical_cards }, + { power: P_AUSTRIA, action: goto_supply }, + { power: P_SAXONY, action: goto_supply, condition: is_saxony_austrian }, + { power: P_PRAGMATIC, action: goto_supply }, + + // austria and pragmatic share movement (like with minor power) + { power: P_AUSTRIA, action: init_movement }, + { power: P_AUSTRIA, action: goto_movement_global }, + { power: P_AUSTRIA, action: end_movement }, + + // austria and pragmatic share combat (like with minor power) + { power: P_AUSTRIA, action: goto_combat }, + + { power: P_AUSTRIA, action: end_action_stage }, + + { power: P_FRANCE, action: goto_end_turn }, +] + const intro_sequence_of_play = [ { power: P_AUSTRIA, action: goto_place_hussars }, @@ -1209,6 +1297,7 @@ const intro_sequence_of_play = [ { power: P_FRANCE, action: goto_tactical_cards }, { power: P_BAVARIA, action: goto_tactical_cards }, { power: P_FRANCE, action: goto_supply }, + { power: P_BAVARIA, action: goto_supply }, { power: P_FRANCE, action: init_movement }, { power: P_FRANCE, action: goto_movement_global }, { power: P_FRANCE, action: end_movement }, @@ -1217,16 +1306,9 @@ const intro_sequence_of_play = [ { power: P_PRUSSIA, action: start_action_stage }, { power: P_PRUSSIA, action: goto_tactical_cards }, - { - power: P_SAXONY, - action() { - if (is_saxony_prussian()) - goto_tactical_cards() - else - next_sequence_of_play() - }, - }, + { power: P_SAXONY, action: goto_tactical_cards }, { power: P_PRUSSIA, action: goto_supply }, + { power: P_SAXONY, action: goto_supply }, { power: P_PRUSSIA, action: init_movement }, { power: P_PRUSSIA, action: goto_movement_global }, { power: P_PRUSSIA, action: end_movement }, @@ -1235,15 +1317,6 @@ const intro_sequence_of_play = [ { power: P_AUSTRIA, action: start_action_stage }, { power: P_AUSTRIA, action: goto_tactical_cards }, - { - power: P_SAXONY, - action() { - if (is_saxony_prussian()) - next_sequence_of_play() - else - goto_tactical_cards() - }, - }, { power: P_AUSTRIA, action: goto_supply }, { power: P_AUSTRIA, action: init_movement }, { power: P_AUSTRIA, action: goto_movement_global }, @@ -1262,7 +1335,9 @@ function start_sequence_of_play() { function current_sequence_of_play() { if (is_intro()) return intro_sequence_of_play[game.stage] - return sequence_of_play[game.stage] + if (is_two_player()) + return two_player_sequence_of_play[game.stage] + return advanced_sequence_of_play[game.stage] } function set_active_to_current_sequence_of_play() { @@ -1273,7 +1348,10 @@ function next_sequence_of_play() { ++game.stage let row = current_sequence_of_play() set_active_to_power(row.power) - row.action() + if (row.condition && !row.condition()) + next_sequence_of_play() + else + row.action() } function start_action_stage() { @@ -1725,13 +1803,15 @@ function search_supply_path(who) { } function goto_supply() { + game.count = 0 // to track saxony shift to oos + game.supply = { hussars: [], restore: [], suffer: [], } - for (let p of all_controlled_generals(game.power)) { + for (let p of all_power_generals[game.power]) { if (!is_piece_on_map(p)) continue @@ -1796,6 +1876,7 @@ function goto_supply_suffer() { log_br() log("Out of supply") game.state = "supply_suffer" + game.count = 0 // number of lost VP } states.supply_hussars = { @@ -1910,19 +1991,22 @@ states.supply_suffer = { gen_action_piece(p) }, piece(p) { - log(`>P${p} at S${game.pos[p]}`) + let s = game.pos[p] + log(`>P${p} at S${s}`) set_delete(game.supply.suffer, p) if (is_out_of_supply(p)) { - //log(`>P${p} at S${game.pos[p]} -2 troops`) + //log(`>P${p} at S${s} -2 troops`) game.troops[p] -= 2 } else { - //log(`>P${p} at S${game.pos[p]} -1 troop`) + //log(`>P${p} at S${s} -1 troop`) set_out_of_supply(p) game.troops[p] -= 1 } if (game.troops[p] <= 0) { eliminate_general(p, true) lose_vp(coop_major_power(game.power), 1) + if (is_bohemia_space(s)) + game.count += 1 // for saxony shift } if (game.supply.suffer.length === 0) resume_supply() @@ -1941,7 +2025,13 @@ states.supply_done = { } function end_supply() { + if (game.count > 0 && should_saxony_shift_after_supply(coop_major_power(game.power))) { + game.state = "saxony_shift_supply" + return + } + delete game.supply + next_sequence_of_play() } @@ -2039,15 +2129,13 @@ function goto_movement_bohemia() { next_sequence_of_play() } -function goto_movement() { - game.state = "movement" -} - function resume_movement() { + if (is_two_player() && game.power === P_PRAGMATIC) + game.power = P_AUSTRIA set_active_to_power(coop_major_power(game.power)) game.selected = -1 if (game.flags & F_MOVE_FLANDERS) { - let row = sequence_of_play[game.stage+1] + let row = advanced_sequence_of_play[game.stage+1] if (row.action === goto_movement_flanders) { let next = game.power === P_PRAGMATIC ? P_AUSTRIA : P_PRAGMATIC if (!has_unmoved_piece_on_flanders_map(next)) { @@ -2067,7 +2155,7 @@ function resume_movement() { function resume_movement_after_flanders_stacking() { set_active_to_power(coop_major_power(game.power)) game.selected = -1 - let row = sequence_of_play[game.stage+1] + let row = advanced_sequence_of_play[game.stage+1] if (row.action === goto_movement_flanders) { next_sequence_of_play() } else { @@ -2810,13 +2898,13 @@ states.confirm_flanders_stack_3 = { //view.selected = game.selected //view.actions.next = 1 }, - piece(p) { + piece(_) { this.next() }, next() { push_undo() - let s = game.forbidden /* + let s = game.forbidden if (game.power === P_AUSTRIA) log("Pragmatic Army refused to stack at S" + s + ".") else @@ -3021,6 +3109,13 @@ function goto_winter_turn() { for (let pow of all_major_powers) game.score[pow].push(count_vp_markers_in_pool(pow)) + if (is_intro()) { + if (game.turn === 10) { + goto_game_over(player_from_power(P_AUSTRIA), "Austria survived 9 turns!") + return + } + } + if (game.turn === 16) { log("Winter Scores") let best_score = 1000 @@ -3035,7 +3130,7 @@ function goto_winter_turn() { best_power = pow } } - goto_game_over(player_from_power(best_power), power_name[best] + " won!") + goto_game_over(player_from_power(best_power), power_name[best_power] + " won!") return } @@ -3230,7 +3325,7 @@ function enter_general_at(p, s) { // return set-aside prussian victory markers when leaving prussia if (piece_power[p] === P_PRUSSIA && game.vp[SET_ASIDE_PRUSSIA] > 0) - if (!set_has(all_prussian_and_silesian_cities, to)) + if (!set_has(all_prussian_and_silesian_cities, s)) return_set_aside_markers(P_PRUSSIA, SET_ASIDE_PRUSSIA) } @@ -3359,7 +3454,6 @@ function next_combat() { goto_retroactive_conquest() } - states.combat = { inactive: "attack", prompt() { @@ -3926,10 +4020,10 @@ function finish_combat() { delete game.lost_generals delete game.lost_troops - if (game.loser_power === P_PRUSSIA && n > 0 && game.saxony < 5) { + if (should_shift_saxony_after_battle(n)) { game.count = n set_active_to_power(P_AUSTRIA) - game.state = "saxony_shift" + game.state = "saxony_shift_battle" return } @@ -4033,7 +4127,43 @@ function count_vp_markers_in_pool(pow) { return Math.max(0, power_victory_target[pow] - count_vp_markers(pow)) } +function count_victory_markers_in_country(pow, country) { + let n = 0 + map_for_each(game.victory, (vspace, vpow) => { + if (vpow === pow && set_has(country, vspace)) + ++n + }) + return n +} + +function check_instant_victory_intro() { + let win_france = count_victory_markers_in_country(P_FRANCE, all_core_austria_fortresses) >= 9 + let win_prussia = count_victory_markers_in_country(P_PRUSSIA, all_core_austria_and_silesia_fortresses) >= 12 + + if (is_two_player()) { + if (win_france && win_prussia) { + goto_game_over(R_PLAYER_A, "France controls 9 fortresses and Prussia controls 12!") + return true + } + } else { + if (win_france) { + goto_game_over(player_from_power(P_FRANCE), "France controls 9 fortresses in Austria!") + return true + } + if (win_prussia) { + goto_game_over(player_from_power(P_PRUSSIA), "Prussia controls 12 fortresses in Austria and Silesia!") + return true + } + } + + return false +} + function check_instant_victory() { + + if (is_intro()) + return check_instant_victory_intro() + let margin = [ count_vp_markers(P_FRANCE) - 11, count_vp_markers(P_PRUSSIA) - 13, @@ -4245,13 +4375,32 @@ function goto_select_political_card() { game.stage |= 1 << pow set_active_to_power(pow) log("=" + game.power) + game.state = "select_political_card" + if (is_two_player()) { + if ((game.flags & F_PLAYER_A_PICK) && (game.power === P_FRANCE || game.power === P_PRUSSIA)) + game.state = "must_save_tc" + if ((game.flags & F_PLAYER_B_PICK) && (game.power === P_PRAGMATIC || game.power === P_AUSTRIA)) + game.state = "must_save_tc" + } } } else { end_politics() } } +states.must_save_tc = { + inactive: "select a political card", + prompt() { + prompt(`Save your TC.`) + view.actions.save = 1 + }, + save() { + log(power_name[game.power] + " saved her TC.") + goto_select_political_card() + }, +} + states.select_political_card = { inactive: "select a political card", prompt() { @@ -4268,12 +4417,19 @@ states.select_political_card = { // face-up TCs to discard game.face_up[game.power] = [] + if (is_two_player()) { + if (game.power === P_FRANCE || game.power === P_PRUSSIA) + game.flags |= F_PLAYER_A_PICK + if (game.power === P_PRAGMATIC || game.power === P_AUSTRIA) + game.flags |= F_PLAYER_B_PICK + } + game.pc = pc game.pcx = -1 game.state = "political_card_discard_or_execute" }, save() { - log(power_name[game.power] + " saved its TC.") + log(power_name[game.power] + " saved her TC.") goto_select_political_card() }, } @@ -4303,6 +4459,11 @@ function end_politics() { game.trump = -1 + if (is_two_player()) { + game.flags &= ~F_PLAYER_A_PICK + game.flags &= ~F_PLAYER_B_PICK + } + // did not take a political turn; flip all cards face-down for (let pow of all_major_powers) { if (!(game.stage & (1 << pow))) { @@ -4462,6 +4623,7 @@ states.political_troop_power = { game.count = info.troops }, pass() { + let info = event_troops[current_political_effect()] if (info.tcs > 0) log("Did not receive TC and troops.") else @@ -4574,7 +4736,23 @@ function is_saxony_austrian_ally() { return game.saxony === 5 } -states.saxony_shift = { +function should_shift_saxony_after_battle(n) { + if (n > 0 && game.saxony < 5) { + if (game.loser_power === P_PRUSSIA) + return true + if (is_two_player() && game.loser_power === P_FRANCE && is_bohemia_space(game.attacker)) + return true + } +} + +function should_saxony_shift_after_supply(pow) { + if (pow === P_PRUSSIA) + return true + if (is_two_player() && pow === P_FRANCE) + return true +} + +states.saxony_shift_battle = { inactive: "shift Saxony marker", prompt() { prompt(`Shift Saxony marker ${game.count} to the right.`) @@ -4602,6 +4780,36 @@ states.saxony_shift = { }, } +states.saxony_shift_supply = { + inactive: "shift Saxony marker", + prompt() { + prompt(`Shift Saxony marker up to ${game.count} to the right.`) + view.actions.shift = [] + for (let i = 1; i <= game.count; ++i) + view.actions.shift.push(i) + view.actions.pass = 1 + }, + shift(n) { + log("Saxony marker " + n + " right.") + let save_saxony = game.saxony + game.saxony = Math.max(1, Math.min(5, game.saxony + n)) + game.count = 0 + + // Saxony defection + if (save_saxony < 3 && is_saxony_neutral()) + goto_saxony_becomes_neutral() + else if (save_saxony < 5 && is_saxony_austrian_ally()) + goto_saxony_becomes_austrian_ally() + else + resume_supply() + }, + pass() { + log("Did not shift Saxony marker.") + game.count = 0 + resume_supply() + }, +} + function goto_adjust_political_tracks() { // clamp final values to track game.saxony = Math.max(1, Math.min(5, game.saxony)) @@ -4898,7 +5106,6 @@ function goto_saxony_becomes_austrian_ally() { if (game.pos[SAXONY_GENERAL] === ELIMINATED) { game.special_saxony_recruit = 1 goto_recruit() - throw "STOP TEST" return } @@ -4940,6 +5147,12 @@ function end_saxony_neutral() { return } + // Out of Supply shift + if (game.supply) { + end_supply() + return + } + // Battle Victory shift next_combat() } @@ -5205,18 +5418,6 @@ function count_french_vp_markers_in_core_austria() { return n } -function remove_french_vp_markers_in_core_austria() { - // TODO: map_filter - for (let i = 0; i < game.victory.length; i += 2) { - if (game.victory[i+1] === P_FRANCE) { - if (set_has(all_core_austria_fortresses, game.victory[i])) { - array_remove_pair(game.victory, i) - i -= 2 - } - } - } -} - function france_has_no_generals_in_core_austria() { for (let p of all_power_generals[P_FRANCE]) { let s = game.pos[p] @@ -5388,7 +5589,7 @@ states.propose_subsidy_to = { let player = game.power let from = game.proposal.from prompt(`Subsidy contract between ${power_name[from]} and who?`) - for (let to of all_powers) { + for (let to of (is_two_player() ? all_minor_powers : all_powers)) { if (from !== to && is_allied_power(from, to)) { if (is_controlled_power(player, from) || is_controlled_power(player, to)) gen_action_power(to) @@ -5455,7 +5656,7 @@ function may_cancel_subsidy() { let player = game.power let result = false for (let from of all_major_powers) { - map_for_each(game.contracts[from], (to, n) => { + map_for_each(game.contracts[from], (to, _n) => { // cannot cancel initial contract! if (from === P_FRANCE && to === P_BAVARIA && game.turn < 3) return @@ -5477,7 +5678,7 @@ states.cancel_subsidy_from = { let player = game.power prompt("Cancel which subsidy contract?") for (let from of all_major_powers) { - map_for_each(game.contracts[from], (to, n) => { + map_for_each(game.contracts[from], (to, _n) => { // cannot cancel initial contract! if (from === P_FRANCE && to === P_BAVARIA && game.turn < 3) return @@ -5498,7 +5699,7 @@ states.cancel_subsidy_to = { let player = game.power let from = game.proposal.from prompt(`Cancel subsidy contract between ${power_name[from]} and who?`) - map_for_each(game.contracts[from], (to, n) => { + map_for_each(game.contracts[from], (to, _n) => { // cannot cancel initial contract! if (from === P_FRANCE && to === P_BAVARIA && game.turn < 3) return @@ -5534,9 +5735,8 @@ states.cancel_subsidy_approve = { map_delete(game.contracts[from], to) end_cancel_subsidy() }, - refuse(n) { + refuse() { let from = game.proposal.from - let to = game.proposal.to log(power_name[game.power] + ` refused to cancel subsidy contract from ${power_name[from]}.`) end_cancel_subsidy() }, @@ -5709,7 +5909,6 @@ function make_tactics_discard(n) { exports.setup = function (seed, scenario, _options) { game = { seed: seed, - scenario: SCENARIO_INDEX[scenario], undo: [], log: [], @@ -5762,8 +5961,10 @@ exports.setup = function (seed, scenario, _options) { count: 0, } - if (is_intro()) { - log("Introductory") + if (scenario.startsWith("Introductory")) { + log("# Introductory") + + game.flags |= F_INTRODUCTORY game.troops[ARENBERG] = 4 game.troops[0] = 3 @@ -5771,6 +5972,12 @@ exports.setup = function (seed, scenario, _options) { game.troops[2] = 8 game.troops[3] = 3 game.troops[4] = 4 + } else { + log("# Advanced") + } + + if (scenario.endsWith("2P")) { + game.flags |= F_TWO_PLAYER } if (!is_intro()) @@ -5964,17 +6171,6 @@ function is_trump_card(c) { return (game.trump >= 0) && (is_reserve(c) || to_suit(c) === game.trump) } -function total_troops_list() { - let list = [] - for (let pow of all_powers) { - let n = 0 - for (let p of all_power_generals[pow]) - n += game.troops[p] - list[pow] = n - } - return list -} - exports.view = function (state, player) { game = state view = { @@ -5997,7 +6193,6 @@ exports.view = function (state, player) { troops: mask_troops(player), hand1: mask_hand1(player), hand2: mask_hand2(player), - // pt: total_troops_list(), discard: total_discard_list(), contracts: game.contracts, -- cgit v1.2.3