summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js225
1 files changed, 210 insertions, 15 deletions
diff --git a/rules.js b/rules.js
index 8a123f6..357fe73 100644
--- a/rules.js
+++ b/rules.js
@@ -6,23 +6,20 @@
show who controls which power in player list
+set-aside victory marker areas
+
austria/pragmatic move order on flanders (start with pragmatic)
only stack if agree (undo/move to previous space)
winter scoring
-tc draw
- no TCs for minor power if major fortress enemy controlled
+when are subsidies given?
+ example france subsidy to prussia
+ at france's stage?
+ at prussia's stage?
-- advanced --
-VICTORY BOXES
- vp for winning (tracks)
- electors (check victory markers)
- emperor (bit)
- italy (bit)
- silesia (bit)
-
silesia home country for prussia
tc subsidies
@@ -49,7 +46,6 @@ neutrality
// PLAN: move all austria on bohemia first, then alternate pragmatic and austria activations on flanders map
// TODO: confirm mixed stack creation on flanders map (force "undo" to previous location if denied?)
-// TODO: supreme commander in mixed stacks
// TODO: TC subsidies
// TODO: subsidy markers?
@@ -93,6 +89,7 @@ const F_EMPEROR_AUSTRIA = 2
const F_ITALY_FRANCE = 4
const F_ITALY_AUSTRIA = 8
const F_SILESIA_ANNEXED = 16
+const F_IMPERIAL_ELECTION = 32 // imperial election card revealed!
const SPADES = 0
const CLUBS = 1
@@ -105,6 +102,7 @@ const IMPERIAL_ELECTION = 25
const ELIMINATED = data.cities.name.length
const all_powers = [ 0, 1, 2, 3, 4, 5 ]
+const all_major_powers = [ 0, 1, 2, 3 ]
const all_power_generals = [
[ 0, 1, 2, 3, 4 ],
@@ -1093,6 +1091,12 @@ function count_used_cards() {
held[to_deck(c)]++
}
+ // count cards in saved political display
+ for (let pow of all_major_powers) {
+ for (let c of game.saved[pow])
+ held[to_deck(c)]++
+ }
+
// count cards currently being held
if (game.draw)
for (let c of game.draw)
@@ -3112,8 +3116,6 @@ function finish_combat() {
lose_vp(game.loser_power, n)
}
- delete game.loser_power
- delete game.winner_power
delete game.lost_generals
delete game.lost_troops
@@ -3218,11 +3220,151 @@ function check_instant_victory() {
/* POLITICS */
+const POWER_FROM_POLITICAL_STAGE = [
+ P_PRUSSIA,
+ P_FRANCE,
+ P_PRAGMATIC,
+ P_AUSTRIA,
+]
+
+function set_active_political_power() {
+ set_active_to_power(POWER_FROM_POLITICAL_STAGE[game.stage])
+}
+
function goto_politics() {
- end_politics()
+ game.political = []
+ game.display = [ 0, 0, 0, 0 ]
+ game.stage = 0
+
+ while (game.political.length < 2) {
+ let pc = game.pol_deck.pop()
+ if (pc === IMPERIAL_ELECTION)
+ game.flags |= F_IMPERIAL_ELECTION
+ else
+ game.political.push(pc)
+ }
+
+ if (game.winner_power >= 0) {
+ set_active_to_power(game.winner_power)
+ game.state = "determine_trump_suit"
+ } else {
+ for (;;) {
+ draw_tc(1)
+ log("Trump " + format_card(game.draw[0]) + ".")
+ if (!is_reserve(game.draw[0])) {
+ game.trump = to_suit(game.draw[0])
+ break
+ }
+ delete game.draw
+ }
+ goto_place_tc_on_display()
+ }
+}
+
+states.determine_trump_suit = {
+ inactive: "determine the political trump suit",
+ prompt() {
+ prompt("Determine the political trump suit.")
+ view.actions.suit = [ 0, 1, 2, 3 ]
+ },
+ suit(s) {
+ game.trump = s
+ goto_place_tc_on_display()
+ }
+}
+
+function goto_place_tc_on_display() {
+ set_active_political_power()
+ game.state = "place_tc_on_display"
+}
+
+states.place_tc_on_display = {
+ inactive: "place TC on political display",
+ prompt() {
+ prompt(`Place TC on political display (${suit_name[game.trump]} is trump).`)
+ for (let c of game.hand[game.power])
+ gen_action_card(c)
+ view.actions.pass = 1
+ },
+ card(c) {
+ push_undo()
+ log(power_name[game.power] + " placed a TC.")
+ set_delete(game.hand[game.power], c)
+ game.display[game.power] = c
+ game.state = "place_tc_on_display_done"
+ },
+ pass() {
+ log(power_name[game.power] + " passed.")
+ end_place_tc_on_display()
+ },
+}
+
+states.place_tc_on_display_done = {
+ inactive: "place TC on political display",
+ prompt() {
+ prompt(`Place TC on political display (${suit_name[game.trump]} is trump) done.`)
+ view.actions.next = 1
+ },
+ next() {
+ end_place_tc_on_display()
+ },
+}
+
+function end_place_tc_on_display() {
+ if (++game.stage === 4)
+ goto_determine_order_of_influence()
+ else
+ goto_place_tc_on_display()
+}
+
+function goto_determine_order_of_influence() {
+ // Turn cards face-up and return bluff cards
+ for (let pow of all_major_powers) {
+ let c = game.display[pow]
+ if (c > 0) {
+ if (to_suit(c) === game.trump) {
+ log(power_name[pow] + " played " + format_card(c) + ".")
+ set_add(game.saved[pow], c)
+ } else {
+ log(power_name[pow] + " bluffed " + format_card(c) + ".")
+ set_add(game.hand[pow], c)
+ }
+ }
+ }
+ delete game.display
+
+ game.stage = 4
+ goto_select_political_cards()
+}
+
+function goto_select_political_cards() {
+ if (--game.stage < 0)
+ end_politics()
+ set_active_to_power(most_influence())
+ game.state = "select_political_card"
+}
+
+states.select_political_card = {
+ inactive: "select a political card",
+ prompt() {
+ prompt(`Select a political card or save your TC.`)
+ for (let pc of game.political)
+ gen_action_political(pc)
+ view.actions.pass = 1
+ },
+ political(pc) {
+ push_undo()
+ log(power_name[game.power] + " chose C" + pc + ".")
+ throw "TODO"
+ },
+ pass() {
+ log(power_name[game.power] + " saved its TC.")
+ goto_select_political_cards()
+ },
}
function end_politics() {
+ delete game.political
if (check_instant_victory())
return
goto_place_hussars()
@@ -3238,8 +3380,7 @@ const POWER_FROM_SETUP_STAGE = [
]
function set_active_setup_power() {
- game.power = POWER_FROM_SETUP_STAGE[game.stage]
- game.active = current_player()
+ set_active_to_power(POWER_FROM_SETUP_STAGE[game.stage])
}
const setup_initial_tcs = [ 2, 9, 3, 5, 5, 3 ]
@@ -3366,6 +3507,9 @@ function make_tactics_discard(n) {
for (let pow of all_powers)
if (set_has(game.hand[pow], c))
return false
+ for (let pow of all_major_powers)
+ if (set_has(game.saved[pow], c))
+ return false
return true
})
}
@@ -3389,9 +3533,16 @@ exports.setup = function (seed, _scenario, _options) {
italy: 5, // political track
flags: 0, // emperor vp, italy vp, silesia annexed, etc
+ // for tracking VP gains/losses and political trump suit
+ winner_power: -1,
+ loser_power: -1,
+ trump: SPADES,
+
pol_deck: null,
deck: null,
hand: [ [], [], [], [], [], [] ],
+ saved: [ [], [], [], [] ],
+ display: [ [], [], [], [] ],
pos: setup_piece_position.slice(),
oos: 0,
@@ -3526,6 +3677,16 @@ function end_setup() {
/* VIEW */
+function mask_pol_deck() {
+ if (game.pol_deck.length > 0) {
+ let top = game.pol_deck[game.pol_deck.length - 1]
+ if (top === IMPERIAL_ELECTION)
+ return 2
+ return 1 + ((top-1) / 6 | 0)
+ }
+ return 0
+}
+
function mask_troops(player) {
let view_troops = []
for (let pow of all_powers) {
@@ -3559,6 +3720,30 @@ function mask_hand(player) {
return view_hand
}
+function mask_display(player) {
+ let view_display = []
+ for (let pow of all_major_powers) {
+ if (game.display[pow] === 0)
+ view_display[pow] = -1
+ else if (player_from_power(pow) === player)
+ view_display[pow] = game.display[pow]
+ else
+ view_display[pow] = game.display[pow] & ~127
+ }
+ return view_display
+}
+
+function mask_saved(player) {
+ let view_saved = []
+ for (let pow of all_major_powers) {
+ if (player_from_power(pow) === player)
+ view_saved[pow] = game.saved[pow]
+ else
+ view_saved[pow] = game.saved[pow].map(c => c & ~127)
+ }
+ return view_saved
+}
+
function total_troops_list() {
let list = []
for (let pow of all_powers) {
@@ -3594,6 +3779,9 @@ exports.view = function (state, player) {
pt: total_troops_list(),
discard: total_discard_list(),
+ pol_deck: mask_pol_deck(),
+ saved: mask_saved(player),
+
power: game.power,
retro: game.retro,
}
@@ -3603,6 +3791,9 @@ exports.view = function (state, player) {
view.defender = game.defender
}
+ if (game.display)
+ view.display = mask_display(player)
+
if (game.state === "game_over") {
view.prompt = game.victory
view.troops = game.troops
@@ -3693,6 +3884,10 @@ function gen_action_card(c) {
gen_action("card", c)
}
+function gen_action_political(c) {
+ gen_action("political", c)
+}
+
function log(msg) {
game.log.push(msg)
}