diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 283 |
1 files changed, 185 insertions, 98 deletions
@@ -316,115 +316,118 @@ const EVENT_INFLATION = 13 const EVENT_GOOD_AUGURIES = 14 const EVENT_DIOCLETIAN = 15 -// 12x -const CARD_M1 = [ 1, 12 ] -const CARD_S1 = [ 13, 24 ] -const CARD_P1 = [ 25, 36 ] - -// 9x -const CARD_M2 = [ 37, 45 ] -const CARD_S2 = [ 46, 54 ] -const CARD_P2 = [ 55, 63 ] - -// 8x -const CARD_M3 = [ 64, 71 ] -const CARD_S3 = [ 72, 79 ] -const CARD_P3 = [ 80, 87 ] - -// 6x -const CARD_M4 = [ 88, 93 ] -const CARD_S4 = [ 94, 99 ] -const CARD_P4 = [ 100, 105 ] +const CARD_M1 = [ 0, 11 ] +const CARD_S1 = [ 12, 23 ] +const CARD_P1 = [ 24, 35 ] +const CARD_M2 = [ 36, 44 ] +const CARD_S2 = [ 45, 53 ] +const CARD_P2 = [ 54, 62 ] +const CARD_M2X = [ 63, 71 ] +const CARD_S2X = [ 72, 80 ] +const CARD_P2X = [ 81, 89 ] +const CARD_M3 = [ 90, 97 ] +const CARD_S3 = [ 98, 105 ] +const CARD_P3 = [ 106, 113 ] +const CARD_M3X = [ 114, 121 ] +const CARD_S3X = [ 122, 129 ] +const CARD_P3X = [ 130, 137 ] +const CARD_M4 = [ 138, 143 ] +const CARD_S4 = [ 144, 149 ] +const CARD_S4B = [ 150, 155 ] +const CARD_P4 = [ 156, 161 ] +const CARD_M4X = [ 162, 167 ] +const CARD_S4X = [ 168, 173 ] +const CARD_P4X = [ 174, 179 ] + +const CARD_INDEX = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20, + 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, +] + +const CARD_INFO = [ + { name: "M1", type: 0, cost: 1, event: "None" }, + { name: "S1", type: 1, cost: 1, event: "None" }, + { name: "P1", type: 2, cost: 1, event: "None" }, + { name: "M2", type: 0, cost: 2, event: "Castra" }, + { name: "S2", type: 1, cost: 2, event: "Tribute" }, + { name: "P2", type: 2, cost: 2, event: "Quaestor" }, + { name: "M2X", type: 0, cost: 2, event: "Cavalry" }, + { name: "S2X", type: 1, cost: 2, event: "Princeps Senatus" }, + { name: "P2X", type: 2, cost: 2, event: "Ambitus" }, + { name: "M3", type: 0, cost: 3, event: "Flanking Maneuver" }, + { name: "S3", type: 1, cost: 3, event: "Foederati" }, + { name: "P3", type: 2, cost: 3, event: "Mob" }, + { name: "M3X", type: 0, cost: 3, event: "Force March" }, + { name: "S3X", type: 1, cost: 3, event: "Frumentarii" }, + { name: "P3X", type: 2, cost: 3, event: "Mobile Vulgus" }, + { name: "M4", type: 0, cost: 4, event: "Praetorian Guard" }, + { name: "S4", type: 1, cost: 4, event: "Damnatio Memoriae" }, + { name: "S4B", type: 1, cost: 4, event: "Damnatio Memoriae (exp)" }, + { name: "P4", type: 2, cost: 4, event: "Pretender" }, + { name: "M4X", type: 0, cost: 4, event: "Spiculum" }, + { name: "S4X", type: 1, cost: 4, event: "Triumph" }, + { name: "P4X", type: 2, cost: 4, event: "Demagogue" }, +] function card_name(c) { - if (c >= CARD_M1[0] && c <= CARD_M1[1]) return "M1" - if (c >= CARD_M2[0] && c <= CARD_M2[1]) return "M2" - if (c >= CARD_M3[0] && c <= CARD_M3[1]) return "M3" - if (c >= CARD_M4[0] && c <= CARD_M4[1]) return "M4" - if (c >= CARD_S1[0] && c <= CARD_S1[1]) return "S1" - if (c >= CARD_S2[0] && c <= CARD_S2[1]) return "S2" - if (c >= CARD_S3[0] && c <= CARD_S3[1]) return "S3" - if (c >= CARD_S4[0] && c <= CARD_S4[1]) return "S4" - if (c >= CARD_P1[0] && c <= CARD_P1[1]) return "P1" - if (c >= CARD_P2[0] && c <= CARD_P2[1]) return "P2" - if (c >= CARD_P3[0] && c <= CARD_P3[1]) return "P3" - if (c >= CARD_P4[0] && c <= CARD_P4[1]) return "P4" - return "??" + return CARD_INFO[CARD_INDEX[c]].name } function card_cost(c) { - if (c >= CARD_M1[0] && c <= CARD_M1[1]) return 1 - if (c >= CARD_M2[0] && c <= CARD_M2[1]) return 2 - if (c >= CARD_M3[0] && c <= CARD_M3[1]) return 3 - if (c >= CARD_M4[0] && c <= CARD_M4[1]) return 4 - if (c >= CARD_S1[0] && c <= CARD_S1[1]) return 1 - if (c >= CARD_S2[0] && c <= CARD_S2[1]) return 2 - if (c >= CARD_S3[0] && c <= CARD_S3[1]) return 3 - if (c >= CARD_S4[0] && c <= CARD_S4[1]) return 4 - if (c >= CARD_P1[0] && c <= CARD_P1[1]) return 1 - if (c >= CARD_P2[0] && c <= CARD_P2[1]) return 2 - if (c >= CARD_P3[0] && c <= CARD_P3[1]) return 3 - if (c >= CARD_P4[0] && c <= CARD_P4[1]) return 4 - return "??" + return CARD_INFO[CARD_INDEX[c]].cost +} + +function card_influence(c) { + return CARD_INFO[CARD_INDEX[c]].type } function card_event_name(c) { - if (c >= CARD_M1[0] && c <= CARD_M1[1]) return "None" - if (c >= CARD_M2[0] && c <= CARD_M2[1]) return "Castra" - if (c >= CARD_M3[0] && c <= CARD_M3[1]) return "Flanking Maneuver" - if (c >= CARD_M4[0] && c <= CARD_M4[1]) return "Praetorian Guard" - if (c >= CARD_S1[0] && c <= CARD_S1[1]) return "None" - if (c >= CARD_S2[0] && c <= CARD_S2[1]) return "Tribute" - if (c >= CARD_S3[0] && c <= CARD_S3[1]) return "Foederati" - if (c >= CARD_S4[0] && c <= CARD_S4[1]) return "Damnatio Memoriae" - if (c >= CARD_P1[0] && c <= CARD_P1[1]) return "None" - if (c >= CARD_P2[0] && c <= CARD_P2[1]) return "Quaestor" - if (c >= CARD_P3[0] && c <= CARD_P3[1]) return "Mob" - if (c >= CARD_P4[0] && c <= CARD_P4[1]) return "Pretender" - return "None" + return CARD_INFO[CARD_INDEX[c]].event +} + +const PLAY_CARD_EVENT = { + "Castra": play_castra, + // "Flanking Maneuver": play_flanking_maneuver, + "Praetorian Guard": play_praetorian_guard, + "Tribute": play_tribute, + "Foederati": play_foederati, + // "Damnatio Memoriae": play_damnatio_memoriae, + // "Damnatio Memoriae (exp)": play_damnatio_memoriae_exp, + "Quaestor": play_quaestor, + "Mob": play_mob, + "Pretender": play_pretender, +} + +const CAN_PLAY_CARD_EVENT = { + "Castra": can_play_castra, + // "Flanking Maneuver": can_play_flanking_maneuver, + "Praetorian Guard": can_play_praetorian_guard, + "Tribute": can_play_tribute, + "Foederati": can_play_foederati, + // "Damnatio Memoriae": can_play_damnatio_memoriae, + // "Damnatio Memoriae (exp)": can_play_damnatio_memoriae_exp, + "Quaestor": can_play_quaestor, + "Mob": can_play_mob, + "Pretender": can_play_pretender, } function can_play_card_event(c) { - if (c >= CARD_M1[0] && c <= CARD_M1[1]) return false - if (c >= CARD_M2[0] && c <= CARD_M2[1]) return can_play_castra() - if (c >= CARD_M3[0] && c <= CARD_M3[1]) return false // "Flanking Maneuver" - if (c >= CARD_M4[0] && c <= CARD_M4[1]) return can_play_praetorian_guard() - if (c >= CARD_S1[0] && c <= CARD_S1[1]) return false - if (c >= CARD_S2[0] && c <= CARD_S2[1]) return can_play_tribute() - if (c >= CARD_S3[0] && c <= CARD_S3[1]) return can_play_foederati() - if (c >= CARD_S4[0] && c <= CARD_S4[1]) return false // "Damnatio Memoriae" - if (c >= CARD_P1[0] && c <= CARD_P1[1]) return false - if (c >= CARD_P2[0] && c <= CARD_P2[1]) return can_play_quaestor() - if (c >= CARD_P3[0] && c <= CARD_P3[1]) return can_play_mob() - if (c >= CARD_P4[0] && c <= CARD_P4[1]) return false // "Pretender" - return false + let f = CAN_PLAY_CARD_EVENT[card_event_name(c)] + return f ? f() : false } function play_card_event(c) { - if (c >= CARD_M2[0] && c <= CARD_M2[1]) play_castra() - if (c >= CARD_M3[0] && c <= CARD_M3[1]) play_flanking_maneuver() - if (c >= CARD_M4[0] && c <= CARD_M4[1]) play_praetorian_guard() - if (c >= CARD_S2[0] && c <= CARD_S2[1]) play_tribute() - if (c >= CARD_S3[0] && c <= CARD_S3[1]) play_foederati() - if (c >= CARD_S4[0] && c <= CARD_S4[1]) play_damnatio_memoriae() - if (c >= CARD_P2[0] && c <= CARD_P2[1]) play_quaestor() - if (c >= CARD_P3[0] && c <= CARD_P3[1]) play_mob() - if (c >= CARD_P4[0] && c <= CARD_P4[1]) play_pretender() + PLAY_CARD_EVENT[card_event_name(c)]() } function add_card_ip(c) { - if (c >= CARD_M1[0] && c <= CARD_M1[1]) return game.ip[MILITARY] += 1 - if (c >= CARD_M2[0] && c <= CARD_M2[1]) return game.ip[MILITARY] += 2 - if (c >= CARD_M3[0] && c <= CARD_M3[1]) return game.ip[MILITARY] += 3 - if (c >= CARD_M4[0] && c <= CARD_M4[1]) return game.ip[MILITARY] += 4 - if (c >= CARD_S1[0] && c <= CARD_S1[1]) return game.ip[SENATE] += 1 - if (c >= CARD_S2[0] && c <= CARD_S2[1]) return game.ip[SENATE] += 2 - if (c >= CARD_S3[0] && c <= CARD_S3[1]) return game.ip[SENATE] += 3 - if (c >= CARD_S4[0] && c <= CARD_S4[1]) return game.ip[SENATE] += 4 - if (c >= CARD_P1[0] && c <= CARD_P1[1]) return game.ip[POPULACE] += 1 - if (c >= CARD_P2[0] && c <= CARD_P2[1]) return game.ip[POPULACE] += 2 - if (c >= CARD_P3[0] && c <= CARD_P3[1]) return game.ip[POPULACE] += 3 - if (c >= CARD_P4[0] && c <= CARD_P4[1]) return game.ip[POPULACE] += 4 + let cost = CARD_INFO[CARD_INDEX[c]].cost + let type = CARD_INFO[CARD_INDEX[c]].type + game.ip[type] += cost } function is_region(where) { @@ -1955,7 +1958,7 @@ function play_castra() { function can_play_quaestor() { let where = get_selected_region() if (game.selected_governor >= 0 && is_province(where)) - return !has_quaestor(where) + return !has_quaestor(where) && !is_breakaway(where) && !is_seat_of_power(where) return false } @@ -2100,6 +2103,85 @@ states.mob = { }, } +// CARD: PRETENDER + +function find_seat_of_power() { + for (let where = 1; where < 12; ++where) + if (is_seat_of_power(where) && is_own_province(where)) + return where + return -1 +} + +function is_possible_seat_of_power(from) { + if (is_own_province(from) && get_support(from) >= 3) + for (let to of ADJACENT[from]) + if (is_own_province(to) && get_support(to) >= 3) + return true + return false +} + +function can_play_pretender() { + if (is_emperor_player()) + return false + if (is_pretender_player()) + return false + for (let where = 1; where < 12; ++where) + if (is_possible_seat_of_power(where)) + return true + return false +} + +function play_pretender() { + game.state = "pretender_seat_of_power" +} + +states.pretender_seat_of_power = { + prompt() { + prompt("Pretender: Place a Seat of Power.") + view.color = POPULACE + for (let where = 0; where < 12; ++where) + for (let where = 1; where < 12; ++where) + if (is_possible_seat_of_power(where)) + gen_action_region(where) + }, + region(where) { + push_undo() + log("Seat of Power in S" + where) + add_seat_of_power(where) + remove_quaestor(where) // no effect anymore + goto_pretender_breakaway() + }, +} + +function goto_pretender_breakaway() { + let seat = find_seat_of_power() + for (let where of ADJACENT[seat]) { + if (get_support(where) >= 3 && !is_breakaway(where) && is_own_province(where)) { + game.state = "pretender_breakaway" + return + } + } + game.state = "take_actions" +} + +states.pretender_breakaway = { + prompt() { + prompt("Pretender: Place Breakaway markers.") + view.color = POPULACE + let seat = find_seat_of_power() + for (let where of ADJACENT[seat]) + if (get_support(where) >= 3 && !is_breakaway(where) && is_own_province(where)) + gen_action_region(where) + }, + region(where) { + push_undo() + log("Breakaway in S" + where) + add_breakaway(where) + remove_quaestor(where) // no effect anymore + goto_pretender_breakaway() + }, +} + // === COMBAT === function goto_battle_vs_general(where, attacker, target) { @@ -2505,7 +2587,10 @@ function goto_combat_victory() { } function award_legacy(p, reason, n) { - log(PLAYER_NAMES[p] + " gained " + n + " Legacy for " + reason + ".") + if (n > 0) + log(PLAYER_NAMES[p] + " gained " + n + " Legacy for " + reason + ".") + if (n < 0) + log(PLAYER_NAMES[p] + " lost " + n + " Legacy for " + reason + ".") game.legacy[p] += n } @@ -2680,7 +2765,7 @@ function goto_expand_pretender_empire() { function goto_gain_legacy() { log_h3("Gain Legacy") - if (is_only_pretender()) + if (is_only_pretender_player()) award_legacy(game.current, "Pretender", count_own_breakaway_provinces()) if (is_emperor_player()) @@ -2699,8 +2784,8 @@ function goto_legitimize_claim() { states.legitimize_claim = { prompt() { prompt("Gain Legacy: Remove Seat of Power and Breakaway markers in your provinces.") - for (let where = 1; where < 12; ++where) { - if (is_own_province(where) && is_seat_of_power(where) || is_breakaway(where)) { + for (let where = 1; where < 12; ++where) + if (is_own_province(where) && is_seat_of_power(where) || is_breakaway(where)) gen_action_region(where) }, region(where) { @@ -3151,7 +3236,7 @@ exports.setup = function (seed, scenario, options) { game.hand[player] = [] game.draw[player] = setup_player_deck(player) game.discard[player] = [] - game.draw[player].push(game.market[2].pop()) + for (let i = 0; i < 9; ++i) set_add(game.draw[player], game.market[i].pop()) } update_neutral_italia() @@ -3216,6 +3301,8 @@ exports.view = function (state, player_name) { amphitheater: game.amphitheater, basilica: game.basilica, limes: game.limes, + seat_of_power: game.seat_of_power, + breakaway: game.breakaway, governors: game.governors, generals: game.generals, |