summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2024-10-30 00:45:54 +0100
committerTor Andersson <tor@ccxvii.net>2024-10-30 00:53:56 +0100
commitb9aced407fd405cdc46df7d5dde9968909724b3d (patch)
tree5af03727f193510b3f02cc0bbfe5821670b3ff0f /rules.js
parentb81278195d8184e77fe778c325a74aa865562792 (diff)
downloadmaria-b9aced407fd405cdc46df7d5dde9968909724b3d.tar.gz
Introductory game.
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js160
1 files changed, 149 insertions, 11 deletions
diff --git a/rules.js b/rules.js
index 1d57af3..9a1395b 100644
--- a/rules.js
+++ b/rules.js
@@ -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