summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js250
1 files changed, 232 insertions, 18 deletions
diff --git a/rules.js b/rules.js
index 8ebf3cc..18ed12c 100644
--- a/rules.js
+++ b/rules.js
@@ -543,6 +543,14 @@ function all_enemy_powers(pow) {
}
}
+function is_allied_power(a, b) {
+ return !all_enemy_powers(a).includes(b)
+}
+
+function is_controlled_power(major, other) {
+ return player_from_power(major) === player_from_power(other)
+}
+
function all_non_coop_powers(pow) {
switch (pow) {
case P_FRANCE:
@@ -2485,13 +2493,12 @@ states.re_enter_train_power = {
inactive: "move",
prompt() {
prompt("Re-enter supply train from which power?")
- view.actions.power = []
for (let pow of all_controlled_powers(game.power)) {
if (game.move_re_entered & (1 << pow))
continue
for (let p of all_power_trains[pow]) {
if (can_train_re_enter(p)) {
- view.actions.power.push(pow)
+ gen_action_power(pow)
break
}
}
@@ -4530,12 +4537,12 @@ states.accept_peace = {
prompt() {
prompt("Accept Prussia's offer of temporary peace to annex Silesia?")
view.actions.accept = 1
- view.actions.deny = 1
+ view.actions.refuse = 1
},
accept() {
goto_annex_silesia()
},
- deny() {
+ refuse() {
end_action_stage_2()
},
}
@@ -4874,6 +4881,195 @@ function end_imperial_election() {
goto_start_turn()
}
+/* SUBSIDY CONTRACTS - CREATE */
+
+function goto_propose_subsidy() {
+ game.proposal = { save_power: game.power, save_state: game.state, from: -1, to: -1, n: 0 }
+ game.state = "propose_subsidy_from"
+}
+
+states.propose_subsidy_from = {
+ inactive: "create subsidy contract",
+ prompt() {
+ prompt("Subsidy contract from which major power?")
+ for (let from of all_major_powers)
+ if (is_allied_power(game.power, from))
+ gen_action_power(from)
+ },
+ power(from) {
+ game.proposal.from = from
+ game.state = "propose_subsidy_to"
+ }
+}
+
+states.propose_subsidy_to = {
+ inactive: "create subsidy contract",
+ prompt() {
+ let player = game.power
+ let from = game.proposal.from
+ prompt(`Subsidy contract between ${power_name[from]} and who?`)
+ for (let to of 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)
+ }
+ }
+ },
+ power(to) {
+ game.proposal.to = to
+ game.state = "propose_subsidy_length"
+ }
+}
+
+states.propose_subsidy_length = {
+ inactive: "create subsidy contract",
+ prompt() {
+ let from = game.proposal.from
+ let to = game.proposal.to
+ prompt(`Subsidy contract between ${power_name[from]} and ${power_name[to]} for how many turns?`)
+ view.actions.value = [ 1, 2, 3, 4, 5, 6 ]
+ },
+ value(n) {
+ clear_undo()
+ game.proposal.n = n
+ set_active_to_power(game.proposal.from)
+ game.state = "propose_subsidy_approve"
+ },
+}
+
+states.propose_subsidy_approve = {
+ inactive: "approve subsidy contract",
+ prompt() {
+ let from = game.proposal.from
+ let to = game.proposal.to
+ let n = game.proposal.n
+ prompt(`Subsidy contract between ${power_name[from]} and ${power_name[to]} for ${n} turns?`)
+ view.actions.accept = 1
+ view.actions.refuse = 1
+ },
+ accept() {
+ let from = game.proposal.from
+ let to = game.proposal.to
+ let n = game.proposal.n
+ log(`Subsidy contract between ${power_name[from]} and ${power_name[to]} for ${n} turns.`)
+ map_set(game.contracts[from], to, map_get(game.contracts[from], to, 0) + n)
+ end_propose_subsidy()
+ },
+ refuse() {
+ let from = game.proposal.from
+ let to = game.proposal.to
+ let n = game.proposal.n
+ log(`${power_name[from]} refused to create subsidy contract to ${power_name[to]} for ${n} turns.`)
+ end_propose_subsidy()
+ },
+}
+
+function end_propose_subsidy() {
+ set_active_to_power(game.proposal.save_power)
+ game.state = game.proposal.save_state
+ delete game.proposal
+}
+
+/* SUBSIDY CONTRACTS - CANCEL */
+
+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) => {
+ // cannot cancel initial contract!
+ if (from === P_FRANCE && to === P_BAVARIA && game.turn < 3)
+ return
+ if (is_controlled_power(player, from) || is_controlled_power(player, to))
+ result = true
+ })
+ }
+ return result
+}
+
+function goto_cancel_subsidy() {
+ game.proposal = { save_power: game.power, save_state: game.state, from: -1, to: -1 }
+ game.state = "cancel_subsidy_from"
+}
+
+states.cancel_subsidy_from = {
+ inactive: "cancel subsidy contract",
+ prompt() {
+ let player = game.power
+ prompt("Cancel which subsidy contract?")
+ for (let from of all_major_powers) {
+ map_for_each(game.contracts[from], (to, n) => {
+ // cannot cancel initial contract!
+ if (from === P_FRANCE && to === P_BAVARIA && game.turn < 3)
+ return
+ if (is_controlled_power(player, from) || is_controlled_power(player, to))
+ gen_action_power(from)
+ })
+ }
+ },
+ power(from) {
+ game.proposal.from = from
+ game.state = "cancel_subsidy_to"
+ }
+}
+
+states.cancel_subsidy_to = {
+ inactive: "cancel subsidy contract",
+ prompt() {
+ 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) => {
+ // cannot cancel initial contract!
+ if (from === P_FRANCE && to === P_BAVARIA && game.turn < 3)
+ return
+ if (is_controlled_power(player, from) || is_controlled_power(player, to))
+ gen_action_power(to)
+ })
+ },
+ power(to) {
+ let player = game.power
+ let from = game.proposal.from
+ clear_undo()
+ game.proposal.to = to
+ if (is_controlled_power(player, from))
+ set_active_to_power(to)
+ else
+ set_active_to_power(from)
+ game.state = "cancel_subsidy_approve"
+ }
+}
+
+states.cancel_subsidy_approve = {
+ inactive: "cancel subsidy contract",
+ prompt() {
+ let from = game.proposal.from
+ let to = game.proposal.to
+ prompt(`Cancel subsidy contract between ${power_name[from]} and ${power_name[to]}?`)
+ view.actions.accept = 1
+ view.actions.refuse = 1
+ },
+ accept() {
+ let from = game.proposal.from
+ let to = game.proposal.to
+ log(`Canceled subsidy contract between ${power_name[from]} and ${power_name[to]}.`)
+ map_delete(game.contracts[from], to)
+ end_cancel_subsidy()
+ },
+ refuse(n) {
+ 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()
+ },
+}
+
+function end_cancel_subsidy() {
+ set_active_to_power(game.proposal.save_power)
+ game.state = game.proposal.save_state
+ delete game.proposal
+}
+
/* SETUP */
const POWER_FROM_SETUP_STAGE = [
@@ -5334,11 +5530,39 @@ exports.view = function (state, player) {
else
view.actions.undo = 0
}
+
+ // subsidy contracts actions for active player
+ if (!game.proposal) {
+ if (may_cancel_subsidy())
+ view.actions.cancel_subsidy = 1
+ view.actions.propose_subsidy = 1
+ }
+
}
return view
}
+exports.action = function (state, _player, action, arg) {
+ game = state
+ let S = states[game.state]
+ if (S && action in S) {
+ S[action](arg)
+ } else {
+ if (action === "undo" && game.undo && game.undo.length > 0) {
+ pop_undo()
+ } else if (action === "propose_subsidy") {
+ push_undo()
+ goto_propose_subsidy()
+ } else if (action === "cancel_subsidy") {
+ push_undo()
+ goto_cancel_subsidy()
+ } else
+ throw new Error("Invalid action: " + action)
+ }
+ return game
+}
+
/* COMMON FRAMEWORK */
function goto_game_over(result, victory) {
@@ -5355,20 +5579,6 @@ function prompt(str) {
view.prompt = power_name[game.power] + ": " + str
}
-exports.action = function (state, _player, action, arg) {
- game = state
- let S = states[game.state]
- if (S && action in S) {
- S[action](arg)
- } else {
- if (action === "undo" && game.undo && game.undo.length > 0)
- pop_undo()
- else
- throw new Error("Invalid action: " + action)
- }
- return game
-}
-
function gen_action(action, argument) {
if (view.actions[action] === undefined)
view.actions[action] = [ argument ]
@@ -5376,6 +5586,10 @@ function gen_action(action, argument) {
set_add(view.actions[action], argument)
}
+function gen_action_power(p) {
+ gen_action("power", p)
+}
+
function gen_action_piece(p) {
gen_action("piece", p)
}