diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 221 |
1 files changed, 73 insertions, 148 deletions
@@ -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) { |