summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js221
1 files changed, 73 insertions, 148 deletions
diff --git a/rules.js b/rules.js
index bdb4a00..e1659f2 100644
--- a/rules.js
+++ b/rules.js
@@ -1,117 +1,5 @@
"use strict"
-/*
-var game, view
-
-// piece list:
-// generals, trains, and hussars - have location (loc)
-// generals - have strength (str)
-
-// space list:
-// objective/fortress have control (0 or power)
-
-const data = require("./data")
-let objectives = {}
-let anti_objectives = { Austria: [], "Pragmatic Army": [], France: [], Prussia: [] }
-let prot_objectives = { Austria: [], "Pragmatic Army": [], France: [], Prussia: [] }
-
-let whose_objective = {
- Austria: [ "France", "Prussia" ],
- Bavaria: [ "Austria" ],
- France: [ "Austria", "Pragmatic Army" ],
- Netherlands: [ "France" ],
- Prussia: [ "Austria" ],
- Saxony: [ "Austria" ],
- Silesia: [ "Austria", "Prussia" ],
- HRE: [ "Austria", "Pragmatic Army", "France" ],
-}
-
-let protect_objective = {
- Austria: [ "Austria" ],
- Bavaria: [ "France" ],
- France: [ "France" ],
- Netherlands: [ "Pragmatic Army" ],
- Prussia: [ "Prussia" ],
- Saxony: [ "Prussia" ],
- Silesia: [ "Austria", "Prussia" ],
- HRE: [ "Austria", "Pragmatic Army", "France" ],
-}
-
-for (let type of [ "major_fortress", "minor_fortress" ]) {
- let group = object_group_by(data.type[type], s => data.cities.country[s])
- for (let region in group) {
- if (objectives[region] === undefined)
- objectives[region] = []
- for (let s of group[region]) {
- set_add(objectives[region], s)
- console.log(region)
- for (let list of whose_objective[region])
- set_add(anti_objectives[list], s)
- for (let list of protect_objective[region])
- set_add(prot_objectives[list], s)
- }
-
- }
-}
-for (let x in anti_objectives)
- console.log(x, anti_objectives[x].length)
-console.log(objectives)
-console.log("TAKE", anti_objectives)
-console.log("PROT", prot_objectives)
-
-exports.roles = [
- "Louis XV",
- "Frederick",
- "Maria Theresa",
-]
-
-exports.scenarios = [ "Standard", "Introductory" ]
-
-const P_AUSTRIA = 0
-const P_PRUSSIA = 1
-const P_SAXONY = 2
-const P_PRAGMATIC = 3
-const P_FRANCE = 4
-const P_BAVARIA = 5
-
-const PLAYERS = {
- "Maria Theresa": [ P_AUSTRIA ],
- "Frederick": [ P_PRUSSIA, P_SAXONY, P_PRAGMATIC ],
- "Louis XV": [ P_FRANCE, P_BAVARIA ],
-}
-
-const MAJOR_POWERS = [ P_AUSTRIA, P_PRUSSIA, P_FRANCE, P_PRAGMATIC ]
-
-const MINOR_POWERS = [ P_BAVARIA, P_SAXONY ]
-
-const ALLIED = [
- [ P_FRANCE, P_BAVARIA, P_PRUSSIA, P_SAXONY ],
- [ P_AUSTRIA, P_PRAGMATIC ],
-]
-
-const COOPERATE = [
- [ P_FRANCE, P_BAVARIA ],
- [ P_PRUSSIA, P_SAXONY ],
- [ P_AUSTRIA, P_PRAGMATIC ],
-]
-
-*/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"use strict"
-
const R_LOUIS_XV = "Louis XV"
const R_FREDERICK = "Frederick"
const R_MARIA_THERESA = "Maria Theresa"
@@ -314,22 +202,36 @@ function to_value(c) {
return c & 15
}
-function format_card(c) {
+function format_card_prompt(c) {
if (is_reserve(c))
return "8R"
return to_value(c) + suit_name[to_suit(c)]
}
+function format_card(c) {
+ return (to_deck(c)+1) + "^" + format_card_prompt(c)
+}
+
+function format_reserve(c, v) {
+ return (to_deck(c)+1) + "^" + v + "R"
+}
+
function is_reserve(c) {
return to_suit(c) === RESERVE
}
-function format_cards(list) {
+function format_card_list(list) {
if (list.length > 0)
return list.map(format_card).join(", ")
return "nothing"
}
+function format_card_list_prompt(list) {
+ if (list.length > 0)
+ return list.map(format_card_prompt).join(", ")
+ return "nothing"
+}
+
function format_selected() {
if (game.selected.length === 0)
return "nobody"
@@ -682,19 +584,29 @@ function find_largest_discard(u) {
throw "OUT OF CARDS"
}
-function next_tactics_deck() {
- let held = [ 0, 0, 0, 0, 0 ]
+function count_used_cards() {
+ let held = [ 0, 0, 0, 0 ]
// count cards in hands
for (let pow of all_powers) {
for (let c of game.hand[pow])
held[to_deck(c)]++
}
+
+ // count cards currently being held
if (game.draw)
for (let c of game.draw)
held[to_deck(c)]++
- if (game.oo > 0)
- held[to_deck(game.oo)]++
+
+ // count cards remaining in deck
+ for (let c of game.deck)
+ held[to_deck(c)]++
+
+ return held
+}
+
+function next_tactics_deck() {
+ let held = count_used_cards()
// find next unused deck
for (let i = 1; i < 5; ++i) {
@@ -726,6 +638,13 @@ function next_tactics_deck() {
shuffle_bigint(game.deck)
}
+function total_discard_list() {
+ let discard = count_used_cards()
+ for (let i = 0; i < 4; ++i)
+ discard[i] = Math.ceil((38 - discard[i]) / 5)
+ return discard
+}
+
function draw_tc(n) {
game.draw = []
@@ -763,7 +682,7 @@ states.tactical_cards_show = {
inactive: "draw tactical cards",
prompt() {
view.draw = game.draw
- prompt("Draw " + format_cards(game.draw) + ".")
+ prompt("Draw " + format_card_list_prompt(game.draw) + ".")
view.actions.end_cards = 1
},
end_cards() {
@@ -942,10 +861,10 @@ states.movement = {
game.count = 0
- if (data.cities.major_roads[here].length > 0)
- game.major = 1
+ if (data.cities.main_roads[here].length > 0)
+ game.main = 1
else
- game.major = 0
+ game.main = 0
if (is_supply_train(p))
game.state = "move_supply_train"
@@ -973,7 +892,7 @@ states.movement = {
function format_move(max) {
let n = max - game.count
- if (game.major)
+ if (game.main)
return ` up to ${n} cities (${n+1} on main roads).`
return ` up to ${n} cities.`
}
@@ -1075,8 +994,8 @@ states.move_supply_train = {
let who = game.selected[0]
let here = game.pos[who]
- if (game.count < 2 + game.major)
- for (let next of data.cities.major_roads[here])
+ if (game.count < 2 + game.main)
+ for (let next of data.cities.main_roads[here])
if (!has_any_piece(next))
gen_action_space(next)
if (game.count < 2)
@@ -1107,13 +1026,13 @@ states.move_supply_train = {
log(">to S" + to)
- if (!set_has(data.cities.major_roads[from], to))
- game.major = 0
+ if (!set_has(data.cities.main_roads[from], to))
+ game.main = 0
set_add(game.moved, who)
game.pos[who] = to
- if (++game.count === 2 + game.major)
+ if (++game.count === 2 + game.main)
end_move_piece()
},
}
@@ -1131,7 +1050,7 @@ states.move_general = {
if (game.selected.length > 1) {
for (let p of game.selected) {
gen_action_piece(p)
- gen_action_detach(p)
+ gen_action_unstack(p)
}
}
@@ -1151,8 +1070,8 @@ states.move_general = {
view.actions.stop = 1
}
- if (game.count < movement_range() + game.major)
- for (let next of data.cities.major_roads[here])
+ if (game.count < movement_range() + game.main)
+ for (let next of data.cities.main_roads[here])
if (can_move_general_to(next))
gen_action_space_or_piece(next)
@@ -1167,7 +1086,7 @@ states.move_general = {
give() {
game.state = "move_give"
},
- detach(p) {
+ unstack(p) {
set_delete(game.selected, p)
},
piece(p) {
@@ -1199,10 +1118,10 @@ states.move_general = {
log(">to S" + to)
- if (!set_has(data.cities.major_roads[from], to))
- game.major = 0
+ if (!set_has(data.cities.main_roads[from], to))
+ game.main = 0
- if (move_general_to(to) || ++game.count === movement_range() + game.major)
+ if (move_general_to(to) || ++game.count === movement_range() + game.main)
end_move_piece()
},
}
@@ -1698,22 +1617,22 @@ function format_combat(value) {
let d = format_combat_stack(game.defender)
let s = signed_number(value)
let p = POWER_NAME[game.power]
- return `${a} vs ${d}. ${p} is at ${s}`
+ return `${a} vs ${d}. ${p} is at ${s}.`
}
function inactive_attack() {
- return "combat " + format_combat(game.count)
+ return "Waiting for " + format_combat(game.count)
}
function inactive_defend() {
- return "combat " + format_combat(-game.count)
+ return "Waiting for " + format_combat(-game.count)
}
function prompt_combat(value, extra = null) {
- let text = "Combat " + format_combat(value) + "."
+ let text = format_combat(value)
if (extra)
text += " " + extra
- prompt(text)
+ view.prompt = text
}
function set_active_attacker() {
@@ -1764,6 +1683,7 @@ function gen_play_card(suit) {
}
function gen_play_reserve() {
+ view.draw = [ game.reserve ]
view.actions.value = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
}
@@ -1778,13 +1698,15 @@ function play_card(c, sign) {
}
function play_reserve(v, sign) {
+ let c = game.reserve
+ delete game.reserve
let prefix = (sign < 0 ? ">>" : ">") + POWER_NAME[game.power]
if (sign < 0)
game.count -= v
else
game.count += v
let score = signed_number(sign * game.count)
- log(`${prefix} ${v}R = ${score}`)
+ log(`${prefix} ${format_reserve(c, v)} = ${score}`)
}
function play_combat_card(c, sign, resume, next_state) {
@@ -1792,6 +1714,7 @@ function play_combat_card(c, sign, resume, next_state) {
array_remove_item(game.hand[game.power], c)
if (is_reserve(c)) {
game.state = next_state
+ game.reserve = c
} else {
play_card(c, sign)
resume()
@@ -2486,8 +2409,6 @@ function make_tactics_deck(n) {
function make_tactics_discard(n) {
return make_tactics_deck(n).filter(c => {
- if (c === game.oo)
- return false
if (game.draw && set_has(game.draw, c))
return false
for (let pow of all_powers)
@@ -2693,6 +2614,7 @@ exports.view = function (state, player) {
troops: mask_troops(player),
hand: mask_hand(player),
pt: total_troops_list(),
+ discard: total_discard_list(),
power: game.power,
retro: game.retro,
@@ -2705,11 +2627,14 @@ exports.view = function (state, player) {
if (game.state === "game_over") {
view.prompt = game.victory
+ view.troops = game.troops
+ view.hand = game.hand
} else if (game.active !== player) {
let inactive = states[game.state].inactive || game.state
if (typeof inactive === "function")
- inactive = inactive()
- view.prompt = `Waiting for ${POWER_NAME[game.power]} to ${inactive}.`
+ view.prompt = inactive()
+ else
+ view.prompt = `Waiting for ${POWER_NAME[game.power]} to ${inactive}.`
} else {
view.actions = {}
if (states[game.state])
@@ -2730,11 +2655,11 @@ exports.view = function (state, player) {
/* COMMON FRAMEWORK */
function goto_game_over(result, victory) {
+ log("# The End")
game.active = "None"
game.state = "game_over"
game.result = result
game.victory = victory
- log("# Game Over")
log(game.victory)
return true
}
@@ -2790,8 +2715,8 @@ function gen_action_card(c) {
gen_action("card", c)
}
-function gen_action_detach(p) {
- gen_action("detach", p)
+function gen_action_unstack(p) {
+ gen_action("unstack", p)
}
function log(msg) {