diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 293 |
1 files changed, 158 insertions, 135 deletions
@@ -46,64 +46,26 @@ const R_LOUIS_XV = "Louis XV" const R_FREDERICK = "Frederick" const R_MARIA_THERESA = "Maria Theresa" -exports.roles = [ R_LOUIS_XV, R_FREDERICK, R_MARIA_THERESA ] +exports.roles = [ + R_MARIA_THERESA, + R_FREDERICK, + R_LOUIS_XV +] exports.scenarios = [ "Advanced" ] -/* DATA */ +const data = require("./data") var game var view var states = {} -const data = require("./data") - -function is_bohemia_space(s) { - return s >= 0 && s <= 401 -} - -function is_flanders_space(s) { - return s >= 402 && s <= 618 -} - -function is_map_space(s) { - return s >= 0 && s <= 618 -} - -function is_piece_on_map(p) { - return is_map_space(game.pos[p]) -} - -function is_piece_on_map_or_eliminated(p) { - let s = game.pos[p] - return is_map_space(s) || s === ELIMINATED -} - -function find_city(city) { - let n = data.cities.name.length - let x = -1 - for (let c = 0; c < n; ++c) { - if (data.cities.name[c] === city) { - if (x < 0) - x = c - else - throw "TWO CITIES: " + city - } - } - if (x < 0) - throw "CITY NOT FOUND: " + city - return x -} - -function find_city_list(names) { - let list = [] - for (let n of names) - set_add(list, find_city(n)) - return list -} +/* DATA (SHARED) */ const deck_name = [ "red", "green", "blue", "yellow" ] const suit_name = [ "\u2660", "\u2663", "\u2665", "\u2666", "R" ] +const suit_class = [ "spades", "clubs", "hearts", "diamonds", "reserve" ] +const suit_letter = [ "S", "C", "H", "D", "R" ] const P_FRANCE = 0 const P_BAVARIA = 1 @@ -112,7 +74,8 @@ const P_SAXONY = 3 const P_PRAGMATIC = 4 const P_AUSTRIA = 5 -const POWER_NAME = [ "France", "Bavaria", "Prussia", "Saxony", "Pragmatic Army", "Austria" ] +const power_name = [ "France", "Bavaria", "Prussia", "Saxony", "Pragmatic Army", "Austria" ] +const power_class = [ "france", "bavaria", "prussia", "saxony", "pragmatic", "austria" ] const is_major_power = [ 1, 0, 1, 0, 1, 1 ] const is_minor_power = [ 0, 1, 0, 1, 0, 0 ] @@ -127,24 +90,6 @@ const IMPERIAL_ELECTION = 25 const ELIMINATED = data.cities.name.length -const TRIER = find_city("Trier") -const MAINZ = find_city("Mainz") -const KOLN = find_city("Köln") -const MANNHEIM = find_city("Mannheim") - -const LIEGNITZ = find_city("Liegnitz") -const GLOGAU = find_city("Glogau") -const BRESLAU = find_city("Breslau") -const BRIEG = find_city("Brieg") -const GLATZ = find_city("Glatz") -const NEISSE = find_city("Neisse") -const COSEL = find_city("Cosel") - -const MUNCHEN = find_city("München") -const DRESDEN = find_city("Dresden") - -const ENGLAND = find_city("England") - const all_powers = [ 0, 1, 2, 3, 4, 5 ] const all_power_generals = [ @@ -194,6 +139,15 @@ const piece_rank = [ 1, 2, 3, 4, 5, 6, ] +const piece_abbr = [ + "F1", "F2", "F3", "F4", "F5", + "B1", + "P1", "P2", "P3", "P4", + "S1", + "PA1", "PA2", "PA3", + "A1", "A2", "A3", "A4", "A5", "A6", +] + const piece_name = [ "Moritz", "Belle-Isle", @@ -224,11 +178,117 @@ const piece_name = [ "hussar", "hussar", ] +const piece_log_name = [ + "Moritz", + "Belle-Isle", + "Broglie", + "Maillebois", + "Noailles", + "Törring", + "Friedrich", + "Schwerin", + "Leopold", + "Dessauer", + "Rutowski", + "George II", + "Cumberland", + "Earl of Stair", + "Karl", + "Traun", + "Khevenhüller", + "Batthyány", + "Neipperg", + "Arenberg", + "French ST", "French ST", + "Bavarian ST", + "Prussian ST", "Prussian ST", + "Saxon ST", + "Pragmatic Army ST", + "Austrian ST", "Austrian ST", "Austrian ST", + "Hussars", "Hussars", +] + + const all_pieces = [ ...all_power_generals.flat(), ...all_power_trains.flat() ] const all_trains = [ ...all_power_trains.flat() ] const all_generals = [ ...all_power_generals.flat() ] const all_generals_by_rank = all_generals.slice().sort((a,b)=>piece_rank[a]-piece_rank[b]) +function to_deck(c) { + return c >> 7 +} + +function to_suit(c) { + return (c >> 4) & 7 +} + +function to_value(c) { + if (to_suit(c) === RESERVE) + return 8 + return c & 15 +} + +/* DATA */ + +function is_bohemia_space(s) { + return s >= 0 && s <= 401 +} + +function is_flanders_space(s) { + return s >= 402 && s <= 618 +} + +function is_map_space(s) { + return s >= 0 && s <= 618 +} + +function is_piece_on_map(p) { + return is_map_space(game.pos[p]) +} + +function is_piece_eliminated(p) { + return game.pos[p] === ELIMINATED +} + +function is_piece_on_map_or_eliminated(p) { + let s = game.pos[p] + return is_map_space(s) || s === ELIMINATED +} + +function find_city(city) { + let n = data.cities.name.length + let x = -1 + for (let c = 0; c < n; ++c) { + if (data.cities.name[c] === city) { + if (x < 0) + x = c + else + throw "TWO CITIES: " + city + } + } + if (x < 0) + throw "CITY NOT FOUND: " + city + return x +} + +const TRIER = find_city("Trier") +const MAINZ = find_city("Mainz") +const KOLN = find_city("Köln") +const MANNHEIM = find_city("Mannheim") + +const LIEGNITZ = find_city("Liegnitz") +const GLOGAU = find_city("Glogau") +const BRESLAU = find_city("Breslau") +const BRIEG = find_city("Brieg") +const GLATZ = find_city("Glatz") +const NEISSE = find_city("Neisse") +const COSEL = find_city("Cosel") + +const MUNCHEN = find_city("München") +const DRESDEN = find_city("Dresden") + +const ENGLAND = find_city("England") + const all_france_bavaria_generals = [ ...all_power_generals[P_FRANCE], ...all_power_generals[P_BAVARIA], @@ -490,20 +550,6 @@ function is_hussar(p) { return p >= 30 && p < 32 } -function to_deck(c) { - return c >> 7 -} - -function to_suit(c) { - return (c >> 4) & 7 -} - -function to_value(c) { - if (to_suit(c) === RESERVE) - return 8 - return c & 15 -} - function format_card_prompt(c) { if (is_reserve(c)) return "8R" @@ -583,10 +629,6 @@ function make_protect_range(result, start, here, range) { } } -function is_fortress(s) { - return set_has(all_fortresses, s) -} - function is_home_country(s) { // TODO: Silesia switch (game.power) { @@ -690,18 +732,20 @@ function tc_per_turn() { return n } -const player_from_power_table = [ - R_LOUIS_XV, - R_LOUIS_XV, - R_FREDERICK, - R_FREDERICK, - R_FREDERICK, - R_MARIA_THERESA, -] - function player_from_power(pow) { - // TOOD: saxony allies with austria - return player_from_power_table[pow] + switch (pow) { + case P_FRANCE: + case P_BAVARIA: + return R_LOUIS_XV + case P_PRUSSIA: + return R_FREDERICK + case P_SAXONY: + return R_FREDERICK + case P_PRAGMATIC: + return R_FREDERICK + case P_AUSTRIA: + return R_MARIA_THERESA + } } function set_active_to_power(power) { @@ -783,20 +827,6 @@ function has_friendly_supply_train(to) { return false } -function has_enemy_supply_train(to) { - for (let p of all_enemy_trains(game.power)) - if (game.pos[p] === to) - return true - return false -} - -function has_enemy_general(to) { - for (let p of all_enemy_generals(game.power)) - if (game.pos[p] === to) - return true - return false -} - function has_enemy_piece(to) { for (let p of all_enemy_generals(game.power)) if (game.pos[p] === to) @@ -815,13 +845,6 @@ function has_non_cooperative_general(to) { return false } -function has_own_general(to) { - for (let p of all_power_generals[game.power]) - if (game.pos[p] === to) - return true - return false -} - function count_generals(to) { let n = 0 for (let p of all_generals) @@ -877,8 +900,8 @@ const TURN_NAME = [ const POWER_FROM_ACTION_STAGE = [ P_FRANCE, // and bavaria P_PRUSSIA, // and saxony - P_AUSTRIA, // and pragmatic army -- interleave with pragmatic moves on flanders map P_PRAGMATIC, // interleave with austria moves on flanders map + P_AUSTRIA, // and pragmatic army -- interleave with pragmatic moves on flanders map ] const title_from_action_stage = [ @@ -1122,7 +1145,7 @@ function draw_tc(n) { while (n > 0) { if (game.deck.length === 0) { if (k > 0) - log(POWER_NAME[game.power] + " " + k + " TC.") + log(power_name[game.power] + " " + k + " TC.") k = 0 next_tactics_deck() if (game.deck.length === 0) { @@ -1136,7 +1159,7 @@ function draw_tc(n) { } if (k > 0) - log(POWER_NAME[game.power] + " " + k + " TC.") + log(power_name[game.power] + " " + k + " TC.") } function goto_tactical_cards() { @@ -1358,7 +1381,7 @@ function resume_supply() { goto_supply_suffer() else end_supply() - // TODO: pause + // TODO: pause // game.state = "supply_done" } @@ -2102,7 +2125,7 @@ function goto_re_enter_train() { function can_train_re_enter(p) { return ( - (is_piece_on_map(p) || game.pos[p] === ELIMINATED) && + (is_piece_on_map_or_eliminated(p)) && !set_has(game.moved, p) && has_re_entry_space_for_supply_train(piece_power[p]) ) @@ -2238,7 +2261,7 @@ states.re_enter_train_where = { function end_re_enter_train() { if (game.recruit.used.length > 0) { log_br() - log(POWER_NAME[game.power] + " spent " + game.recruit.used.map(format_card).join(", ") + ".") + log(power_name[game.power] + " spent " + game.recruit.used.map(format_card).join(", ") + ".") map_for_each(game.recruit.pieces, (p, s) => { if (s !== ELIMINATED) log("Re-entered P" + p + " from S" + s + " at S" + game.pos[p] + ".") @@ -2311,7 +2334,7 @@ function has_re_entry_space_for_general() { return false } -function can_re_enter_general_at_city(from, to) { +function can_re_enter_general_at_city(to) { if (is_enemy_controlled_fortress(to)) return false if (has_friendly_supply_train(to)) @@ -2326,7 +2349,7 @@ function can_re_enter_general_at_city(from, to) { function can_recruit_anything() { for (let p of all_power_generals[game.power]) { // can re-enter generals - if (game.pos[p] === ELIMINATED && has_re_entry_space_for_general()) + if (is_piece_eliminated(p) && has_re_entry_space_for_general()) return true // can recruit troops? if (is_piece_on_map(p) && game.troops[p] < 8) @@ -2343,7 +2366,7 @@ states.recruit = { for (let p of all_power_generals[game.power]) { if (is_piece_on_map(p)) av_troops += 8 - game.troops[p] - else if (game.pos[p] === ELIMINATED && has_re_entry_space_for_general()) { + else if (is_piece_eliminated(p) && has_re_entry_space_for_general()) { av_general += 1 av_troops += 8 } @@ -2379,7 +2402,7 @@ states.recruit = { for (let p of all_power_generals[game.power]) { if (game.troops[p] > 0 && game.troops[p] < 8) gen_action_piece(p) - else if (game.pos[p] === ELIMINATED && has_re_entry_space_for_general()) + else if (is_piece_eliminated(p) && has_re_entry_space_for_general()) gen_action_piece(p) } } @@ -2398,7 +2421,7 @@ states.recruit = { spend_card_value(game.recruit.pool, game.recruit.used, 4) - if (game.pos[p] === ELIMINATED) { + if (is_piece_eliminated(p)) { game.selected = p game.state = "re_enter_general_where" } else { @@ -2627,7 +2650,7 @@ function format_combat(value) { let a = format_combat_stack(game.attacker) let d = format_combat_stack(game.defender) let s = signed_number(value) - let p = POWER_NAME[game.power] + let p = power_name[game.power] return `${a} vs ${d}. ${p} is at ${s}.` } @@ -2699,7 +2722,7 @@ function gen_play_reserve() { } function play_card(c, sign) { - let prefix = (sign < 0 ? ">>" : ">") + POWER_NAME[game.power] + let prefix = (sign < 0 ? ">>" : ">") + power_name[game.power] if (sign < 0) game.count -= to_value(c) else @@ -2711,7 +2734,7 @@ 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] + let prefix = (sign < 0 ? ">>" : ">") + power_name[game.power] if (sign < 0) game.count -= v else @@ -2867,7 +2890,7 @@ function goto_retreat() { for (let pow of all_powers) if (lost[pow] > 0) - log(POWER_NAME[pow] + " lost " + (lost[pow]) + " troops.") + log(power_name[pow] + " lost " + (lost[pow]) + " troops.") resume_retreat() } @@ -3100,7 +3123,7 @@ const setup_max_troops = [ 8, 8, 8, 8, 8, 5, 8, 8, 8, 6, - 8, + 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, ] @@ -3270,7 +3293,7 @@ states.setup = { } else { let n_stacks = 0 for (let p of all_power_generals[game.power]) { - if (game.pos[p] !== ELIMINATED && !set_has(game.moved, p)) { + if (!set_has(game.moved, p)) { gen_action_piece(p) n_stacks ++ } @@ -3432,7 +3455,7 @@ exports.view = function (state, player) { if (typeof inactive === "function") view.prompt = inactive() else - view.prompt = `Waiting for ${POWER_NAME[game.power]} to ${inactive}.` + view.prompt = `Waiting for ${power_name[game.power]} to ${inactive}.` } else { view.actions = {} if (states[game.state]) @@ -3463,7 +3486,7 @@ function goto_game_over(result, victory) { } function prompt(str) { - view.prompt = POWER_NAME[game.power] + ": " + str + view.prompt = power_name[game.power] + ": " + str } exports.action = function (state, _player, action, arg) { |