diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 160 |
1 files changed, 149 insertions, 11 deletions
@@ -17,13 +17,24 @@ const R_LOUIS_XV = "Louis XV" const R_FREDERICK = "Frederick" 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 ] -exports.scenarios = [ "Advanced" ] +const SCENARIO_INDEX = { + "Advanced": 0, + "Introductory": 1, +} + +exports.scenarios = [ + "Advanced", + "Introductory", +] const data = require("./data.js") const political_cards = require("./cards.js") @@ -855,11 +866,22 @@ function is_protected_from_conquest(s) { /* STATE */ +function is_intro() { + return game.scenario & 1 +} + +function is_two_player() { + return game.scenario & 2 +} + const tc_per_turn_table = [ 5, 3, 3, 5, 1, 1 ] function tc_per_turn() { let n = tc_per_turn_table[game.power] + if (game.power === P_FRANCE && is_intro()) + n = 3 + // Saxony track if (game.power === P_SAXONY) { if (game.saxony > 4) @@ -1095,7 +1117,10 @@ function goto_start_turn() { if (game.turn % 4 === 0) { goto_winter_turn() } else { - goto_politics() + if (is_intro()) + start_sequence_of_play() + else + goto_politics() } } @@ -1107,7 +1132,7 @@ function goto_end_turn() { goto_start_turn() } -const sequence_of_play = [ +const advanced_sequence_of_play = [ { power: P_AUSTRIA, action: goto_place_hussars }, { power: P_FRANCE, action: start_action_stage }, @@ -1177,12 +1202,66 @@ const sequence_of_play = [ { power: P_FRANCE, action: goto_end_turn }, ] +const intro_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_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_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_PRUSSIA, action: goto_supply }, + { 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_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 }, + { power: P_AUSTRIA, action: end_movement }, + { power: P_AUSTRIA, action: goto_combat }, + { power: P_AUSTRIA, action: end_action_stage }, + + { power: P_FRANCE, action: goto_end_turn }, +] + function start_sequence_of_play() { game.stage = -1 next_sequence_of_play() } function current_sequence_of_play() { + if (is_intro()) + return intro_sequence_of_play[game.stage] return sequence_of_play[game.stage] } @@ -1913,6 +1992,12 @@ function give_troops(total) { function init_movement() { set_clear(game.moved) + if (is_intro()) { + for (let p of all_pieces) + if (is_flanders_space(game.pos[p])) + set_add(game.moved, p) + } + log_br() game.move_re_entered = 0 @@ -2207,6 +2292,8 @@ function can_move_train_to(p, from, to) { } function is_illegal_cross_map_move(from, to) { + if (is_intro() && is_flanders_space(to)) + return true return ( game.power !== P_FRANCE && game.power !== P_AUSTRIA && ( (is_flanders_space(from) && is_bohemia_space(to)) || @@ -2959,6 +3046,11 @@ function goto_winter_turn() { function goto_winter_stage() { set_active_to_current_winter_stage() + if (is_intro() && game.power === P_PRAGMATIC) { + end_winter_stage() + return + } + log(title_from_winter_stage[game.stage]) goto_recruit() @@ -3032,6 +3124,8 @@ states.recruit = { let av_general = 0 let av_troops = 0 for (let p of all_power_generals[game.power]) { + if (is_intro() && is_flanders_space(game.pos[p])) + continue if (is_piece_on_map(p)) av_troops += 8 - game.troops[p] else if (is_piece_eliminated(p) && has_re_entry_space_for_general(p)) { @@ -3066,6 +3160,8 @@ states.recruit = { if (paid >= 4) { for (let p of all_power_generals[game.power]) { + if (is_intro() && is_flanders_space(game.pos[p])) + continue if (game.troops[p] > 0 && game.troops[p] < 8) gen_action_piece(p) else if (is_piece_eliminated(p) && has_re_entry_space_for_general(p)) @@ -3811,6 +3907,13 @@ function lose_vp(pow, n) { } function finish_combat() { + if (is_intro()) { + delete game.lost_generals + delete game.lost_troops + next_combat() + return + } + let n = game.lost_troops / 3 | 0 if (n === 0 && game.lost_generals > 0) n = 1 @@ -5454,8 +5557,16 @@ const POWER_FROM_SETUP_STAGE = [ P_AUSTRIA, ] +const INTRO_POWER_FROM_SETUP_STAGE = [ + P_PRUSSIA, + P_AUSTRIA, +] + function set_active_setup_power() { - set_active_to_power(POWER_FROM_SETUP_STAGE[game.stage]) + if (is_intro()) + set_active_to_power(INTRO_POWER_FROM_SETUP_STAGE[game.stage]) + else + set_active_to_power(POWER_FROM_SETUP_STAGE[game.stage]) } const setup_initial_tcs = [ 2, 9, 3, 5, 5, 3 ] @@ -5595,9 +5706,10 @@ function make_tactics_discard(n) { }) } -exports.setup = function (seed, _scenario, _options) { +exports.setup = function (seed, scenario, _options) { game = { seed: seed, + scenario: SCENARIO_INDEX[scenario], undo: [], log: [], @@ -5620,7 +5732,6 @@ exports.setup = function (seed, _scenario, _options) { loser_power: -1, trump: SPADES, - pol_deck: null, deck: null, hand1: [ [], [], [], [], [], [] ], hand2: [ [], [], [], [], [], [] ], @@ -5651,7 +5762,20 @@ exports.setup = function (seed, _scenario, _options) { count: 0, } - game.pol_deck = make_political_deck() + if (is_intro()) { + log("Introductory") + + game.troops[ARENBERG] = 4 + game.troops[0] = 3 + game.troops[1] = 8 + game.troops[2] = 8 + game.troops[3] = 3 + game.troops[4] = 4 + } + + if (!is_intro()) + game.pol_deck = make_political_deck() + game.deck = make_tactics_deck(0) shuffle_bigint(game.deck) @@ -5670,12 +5794,17 @@ exports.setup = function (seed, _scenario, _options) { map_set(game.victory, COSEL, P_AUSTRIA) // Deal initial cards - for (let pow of all_powers) + for (let pow of all_powers) { + if (is_intro() && pow === P_PRAGMATIC) + continue for (let i = 0; i < setup_initial_tcs[pow]; ++i) set_add(game.hand1[pow], game.deck.pop()) + } log("# 1741") + goto_setup() + return game } @@ -5759,8 +5888,15 @@ states.setup_general = { }, } +function goto_setup() { + game.stage = 0 + set_active_setup_power() + game.state = "setup" +} + function end_setup() { - if (++game.stage === 4) { + let end = is_intro() ? 2 : 4 + if (++game.stage === end) { goto_start_turn() } else { set_active_setup_power() @@ -5865,7 +6001,6 @@ exports.view = function (state, player) { discard: total_discard_list(), contracts: game.contracts, - pol_deck: mask_pol_deck(), face_up: game.face_up, face_down: mask_face_down(), @@ -5878,6 +6013,9 @@ exports.view = function (state, player) { view.defender = game.defender } + if (!is_intro()) + view.pol_deck = mask_pol_deck() + if (game.political) view.political = game.political @@ -5906,7 +6044,7 @@ exports.view = function (state, player) { } // subsidy contracts actions for active player - if (!game.proposal) { + if (!game.proposal && !is_intro()) { if (may_cancel_subsidy()) view.actions.cancel_subsidy = 1 view.actions.propose_subsidy = 1 |