summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js283
1 files changed, 185 insertions, 98 deletions
diff --git a/rules.js b/rules.js
index bdac983..8c7b846 100644
--- a/rules.js
+++ b/rules.js
@@ -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,