From 285606d4c3fec57d501c66b46a48e730e71d0f6a Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sat, 1 Jul 2023 16:36:11 +0200 Subject: Expansion cards. TODO: Frumentarii, Spiculum, Demagogue. --- info/cards.html | 42 +++-- info/readme.html | 5 +- play.css | 4 - play.js | 2 +- rules.js | 531 +++++++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 496 insertions(+), 88 deletions(-) diff --git a/info/cards.html b/info/cards.html index 4fc8758..3c3bd5a 100644 --- a/info/cards.html +++ b/info/cards.html @@ -66,6 +66,16 @@ h2 { .card.influence_s2{background-image:url(../cards.1x/influence_s2.jpg)} .card.influence_s3{background-image:url(../cards.1x/influence_s3.jpg)} .card.influence_s4{background-image:url(../cards.1x/influence_s4.jpg)} +.card.influence_s4b{background-image:url(../cards.1x/influence_s4b.jpg)} +.card.influence_m2x{background-image:url(../cards.1x/influence_m2x.jpg)} +.card.influence_m3x{background-image:url(../cards.1x/influence_m3x.jpg)} +.card.influence_m4x{background-image:url(../cards.1x/influence_m4x.jpg)} +.card.influence_p2x{background-image:url(../cards.1x/influence_p2x.jpg)} +.card.influence_p3x{background-image:url(../cards.1x/influence_p3x.jpg)} +.card.influence_p4x{background-image:url(../cards.1x/influence_p4x.jpg)} +.card.influence_s2x{background-image:url(../cards.1x/influence_s2x.jpg)} +.card.influence_s3x{background-image:url(../cards.1x/influence_s3x.jpg)} +.card.influence_s4x{background-image:url(../cards.1x/influence_s4x.jpg)} @media (min-resolution:97dpi) { .card.event_back{background-image:url(../cards.2x/event_back.jpg)} @@ -101,6 +111,16 @@ h2 { .card.influence_s2{background-image:url(../cards.2x/influence_s2.jpg)} .card.influence_s3{background-image:url(../cards.2x/influence_s3.jpg)} .card.influence_s4{background-image:url(../cards.2x/influence_s4.jpg)} +.card.influence_s4b{background-image:url(../cards.2x/influence_s4b.jpg)} +.card.influence_m2x{background-image:url(../cards.2x/influence_m2x.jpg)} +.card.influence_m3x{background-image:url(../cards.2x/influence_m3x.jpg)} +.card.influence_m4x{background-image:url(../cards.2x/influence_m4x.jpg)} +.card.influence_p2x{background-image:url(../cards.2x/influence_p2x.jpg)} +.card.influence_p3x{background-image:url(../cards.2x/influence_p3x.jpg)} +.card.influence_p4x{background-image:url(../cards.2x/influence_p4x.jpg)} +.card.influence_s2x{background-image:url(../cards.2x/influence_s2x.jpg)} +.card.influence_s3x{background-image:url(../cards.2x/influence_s3x.jpg)} +.card.influence_s4x{background-image:url(../cards.2x/influence_s4x.jpg)} } @@ -116,17 +136,17 @@ h2 {
-
-
-
-
-
-
+
+
+
+
+
+

Expansion Influence Cards

@@ -136,16 +156,16 @@ h2 {
-
-
-
-
-
+
+
+
+
+

Event Cards

diff --git a/info/readme.html b/info/readme.html index d43559d..ef978f0 100644 --- a/info/readme.html +++ b/info/readme.html @@ -49,7 +49,10 @@ How do I use the event on a card?

Once the card is in your "Played" area you can click it again to use the event. The card will turn dark once its effect has been used. -"Flanking Maneuver" and "Damnatio Memoriae" can only be played when prompted at the appropriate time. +

+"Cavalry", "Flanking Maneuver", "Spiculum", and "Triumph" can only be played in combat. +

+"Ambitus" and "Damnatio Memoriae" can only be played during the Place Governor action.


diff --git a/play.css b/play.css index ac6c457..f8d8536 100644 --- a/play.css +++ b/play.css @@ -192,10 +192,6 @@ body svg .sea.action { display: block; } -.support.s0.action { - background-color: hsla(206, 100%, 35%, 0.4); -} - .dice { width: 36px; height: 36px; diff --git a/play.js b/play.js index 0e6618c..88db339 100644 --- a/play.js +++ b/play.js @@ -826,7 +826,7 @@ function create_support_buttons(region) { for (let i = 0; i <= 4; ++i) { let x = Math.floor(-1 + x0 + i * 51.6666) let y = (-1 + y0) - let e = create_thing({ className: "support s" + i, my_action: i > 0 ? "support" : "recall", my_id: i > 0 ? (region << 3) + i : region }) + let e = create_thing({ className: "support s" + i, my_action: "support", my_id: (region << 3) + i }) e.style.top = y + "px" e.style.left = x + "px" } diff --git a/rules.js b/rules.js index 880dff1..ed56611 100644 --- a/rules.js +++ b/rules.js @@ -4,13 +4,16 @@ TODO [ ] killed leader stash for buy/trash phase -[ ] killed ardashur+shapur: two support bumps -[ ] killed gives credits for military + senate [ ] display of general+castra stacked with militia+castra +[ ] todo: battle twice with militia (remove mbattled?) [ ] emperor [ ] expansion cards +Frumentarii +Demagogue +Spiculum + */ var game @@ -401,6 +404,16 @@ const PLAY_CARD_EVENT = { "Damnatio Memoriae": play_damnatio_memoriae, "Damnatio Memoriae (exp)": play_damnatio_memoriae_exp, "Pretender": play_pretender, + + "Cavalry": play_cavalry, + "Princeps Senatus": play_princeps_senatus, + "Ambitus": play_ambitus, + "Force March": play_force_march, + "Frumentarii": play_frumentarii, + "Mobile Vulgus": play_mobile_vulgus, + "Spiculum": play_spiculum, + "Triumph": play_triumph, + "Demagogue": play_demagogue, } const CAN_PLAY_CARD_EVENT = { @@ -414,6 +427,16 @@ const CAN_PLAY_CARD_EVENT = { "Damnatio Memoriae": null, "Damnatio Memoriae (exp)": null, "Pretender": can_play_pretender, + + "Cavalry": null, + "Princeps Senatus": can_play_princeps_senatus, + "Ambitus": null, + "Force March": can_play_force_march, + "Frumentarii": can_play_frumentarii, + "Mobile Vulgus": can_play_mobile_vulgus, + "Spiculum": null, + "Triumph": null, + "Demagogue": can_play_demagogue, } function can_play_card_event(c) { @@ -561,6 +584,9 @@ function has_general_battled(id) { return game.battled & (1 << id) } function set_general_battled(id) { game.battled |= (1 << id) } function clear_general_battled(id) { game.battled &= ~(1 << id) } +function has_general_force_marched(id) { return game.force_march & (1 << id) } +function set_general_force_marched(id) { game.force_march |= (1 << id) } + function has_militia_battled(province) { return game.mbattled & (1 << province) } function set_militia_battled(province) { game.mbattled |= (1 << province) } function clear_militia_battled(province) { game.mbattled &= ~(1 << province) } @@ -1116,6 +1142,13 @@ function has_card_event(event) { return false } +function used_card_event(event) { + for (let c = event[0]; c <= event[1]; ++c) + if (set_has(game.used, c)) + return true + return false +} + // === SETUP === states.setup_province = { @@ -1179,6 +1212,7 @@ function goto_start_turn() { game.killed = 0 game.battled = 0 + game.force_march = 0 game.mbattled = 0 game.placed = 0 @@ -1993,6 +2027,7 @@ states.take_actions = { push_undo() if (game.selected_governor >= 0) { spend_senate(1) + game.ambitus = 0 game.count = 1 game.where = where game.state = "place_governor" @@ -2148,6 +2183,16 @@ function place_governor(where, new_governor) { update_neutral_italia() } +function count_units_in_capital(where) { + let n = 0 + let army = get_capital_general(where) + if (army >= 0) + n += count_units_in_army(army) + if (has_militia(where)) + n += 1 + return n +} + function calc_needed_votes(where, pg) { let n = get_support(where) * 2 // base number of votes let old_governor = get_province_governor(where) @@ -2166,6 +2211,8 @@ function calc_needed_votes(where, pg) { if (has_militia(where)) n += 1 } + // Ambitus adds guaranteed votes. + n -= game.ambitus return Math.max(1, n) } @@ -2173,19 +2220,28 @@ states.place_governor = { inactive: "Place Governor", prompt() { let need = calc_needed_votes(game.where, false) - let votes = game.count + let dice = game.count if (game.where === ITALIA) - votes += count_own_basilicas() + dice += count_own_basilicas() view.color = SENATE view.selected_region = game.where view.selected_governor = game.selected_governor - prompt(`Place Governor: ${game.sip} senate. Rolling ${votes} dice. ${need} votes needed.`) + prompt(`Place Governor: ${game.sip} senate. Rolling ${dice} dice. ${need} votes needed.`) + if (game.ambitus < game.count && has_card_event(CARD_P2X)) { + view.prompt += " Ambitus?" + gen_card_event(CARD_P2X) + } if (game.sip >= 1) view.actions.spend_senate = 1 else view.actions.spend_senate = 0 view.actions.roll = 1 }, + card(c) { + push_undo() + set_add(game.used, c) + play_card_event(c) + }, spend_senate() { push_undo() spend_senate(1) @@ -2201,19 +2257,28 @@ states.praetorian_guard = { inactive: "Praetorian Guard", prompt() { let need = calc_needed_votes(game.where, true) - let votes = game.count + let dice = game.count if (game.where === ITALIA) - votes += count_own_basilicas() + dice += count_own_basilicas() view.color = MILITARY view.selected_region = game.where view.selected_governor = game.selected_governor - prompt(`Praetorian Guard: ${game.mip} Military. Rolling ${votes} dice. ${need} votes needed.`) + prompt(`Praetorian Guard: ${game.mip} military. Rolling ${dice} dice. ${need} votes needed.`) + if (game.ambitus < game.count && has_card_event(CARD_P2X)) { + view.prompt += " Ambitus?" + gen_card_event(CARD_P2X) + } if (game.mip >= 1) view.actions.spend_military = 1 else view.actions.spend_military = 0 view.actions.roll = 1 }, + card(c) { + push_undo() + set_add(game.used, c) + play_card_event(c) + }, spend_military() { push_undo() spend_military(1) @@ -2296,6 +2361,7 @@ function play_praetorian_guard_auto() { } } spend_military(1) + game.ambitus = 0 game.count = 1 game.where = ITALIA game.state = "praetorian_guard" @@ -2737,6 +2803,7 @@ function can_play_foederati() { } function play_foederati() { + // TODO: auto-select general on map? game.state = "foederati" } @@ -2917,12 +2984,253 @@ states.pretender_breakaway = { }, } + +// CARD: Princeps Senatus + +function can_play_princeps_senatus() { + return !used_card_event(CARD_S2X) +} + +function play_princeps_senatus() { + log("Princeps Senatus.") +} + +// CARD: Ambitus + +function play_ambitus() { + log("Ambitus.") + game.ambitus += 1 +} + +// CARD: Force March + +function can_play_force_march() { + if (game.mip >= 1) { + for (let i = 0; i < 6; ++i) { + let id = game.current * 6 + i + if (is_region(get_general_location(id))) + if (has_general_battled(id) && !has_general_force_marched(id)) + return true + } + } + return false +} + +function play_force_march() { + // TODO: auto-select general on map? + game.state = "force_march_who" +} + +states.force_march_who = { + prompt() { + prompt("Force March: Choose an army you command...") + for (let i = 0; i < 6; ++i) { + let id = game.current * 6 + i + let where = get_general_location(id) + if (is_region(where) && has_general_battled(id) && !has_general_force_marched(id)) + gen_action_general(id) + } + // TODO: Militia + Force March ? + }, + general(id) { + log("Force March.") + set_general_force_marched(id) + game.selected_governor = -1 + game.selected_general = id + game.selected_militia = -1 + game.state = "force_march" + }, +} + +states.force_march = { + prompt() { + prompt("Force March: Move Army or Initiate Battle.") + + let where = UNAVAILABLE + view.color = MILITARY + if (game.selected_general > 0) { + view.selected_general = game.selected_general + where = get_general_location(game.selected_general) + } else { + view.selected_militia = game.selected_militia + where = game.selected_militia + } + + // Initiate Battle + gen_initiate_battle(where) + + // Move Army + if (game.selected_general > 0) { + for (let to of ADJACENT[where]) { + if (!is_sea(to)) { + gen_action_region(to) + if (can_enter_capital(to)) + gen_action_capital(to) + } + } + + // Free Action: Enter/Leave Capital + if (is_province(where)) { + if (is_general_inside_capital(game.selected_general)) { + view.actions.leave = 1 + } else if (can_enter_capital(where)) { + view.actions.enter = 1 + gen_action_capital(where) + } + } + } + }, + + general(id) { + push_undo() + goto_battle_vs_general(get_general_location(game.selected_general), game.selected_general, id) + }, + + militia(where) { + push_undo() + goto_battle_vs_militia(where, game.selected_general) + }, + + barbarian(id) { + push_undo() + goto_battle_vs_barbarian(get_selected_region(), game.selected_general, id) + }, + + rival_emperor(id) { + push_undo() + goto_battle_vs_rival_emperor(get_selected_region(), game.selected_general, id) + }, + + region(where) { + push_undo() + move_army_to(game.selected_general, where) + }, + + capital(where) { + push_undo() + if (get_general_location(game.selected_general) !== where) + move_army_to(game.selected_general, where) + enter_capital() + }, + + enter() { + push_undo() + enter_capital() + game.state = "take_actions" + }, + + leave() { + push_undo() + set_general_outside_capital(game.selected_general) + remove_general_castra(game.selected_general) + game.state = "take_actions" + }, +} + +// CARD: Frumentarii + +function can_play_frumentarii() { + return !used_card_event(CARD_S3X) +} + +function play_frumentarii() { + log("Frumentarii.") + game.frumentarii |= (1 << game.current) +} + +// CARD: Mobile Vulgus + +function can_play_mobile_vulgus() { + for (let where = 0; where < 12; ++where) { + if (is_enemy_province(where)) { + let n = get_support(where) * 2 + count_units_in_capital(where) + if (game.pip >= n) + return true + } + } + return false +} + +function play_mobile_vulgus() { + game.state = "mobile_vulgus_where" +} + +states.mobile_vulgus_where = { + prompt() { + prompt("Mobile Vulgus: Choose a province...") + view.color = POPULACE + for (let where = 0; where < 12; ++where) { + if (is_enemy_province(where)) { + let n = get_support(where) * 2 + count_units_in_capital(where) + if (game.pip >= n) + gen_action_region(where) + } + } + }, + region(where) { + log("Mobile Vulgus in %" + where + ".") + game.where = where + game.state = "mobile_vulgus" + }, +} + +states.mobile_vulgus = { + prompt() { + prompt("Mobile Vulgus: " + game.pip + " populace. Reduce support in " + REGION_NAME[game.where] + ".") + let n = get_support(game.where) * 2 + count_units_in_capital(game.where) + if (game.pip >= n) + gen_action_support(game.where, get_support(game.where) - 1) + view.actions.done = 1 + }, + support() { + push_undo() + log("Reduce support level in %" + game.where + ".") + let n = get_support(game.where) * 2 + count_units_in_capital(game.where) + spend_populace(n) + reduce_support(game.where) + if (is_neutral_province(game.where)) + game.state = "take_actions" + }, + done() { + push_undo() + game.state = "take_actions" + }, +} + +// CARD: Triumph + +function play_triumph() { + log("Triumph.") + // TODO +} + +// CARD: Demagogue + +function can_play_demagogue() { + return !used_card_event(CARD_P4X) +} + +function play_demagogue() { + log("Demagogue.") + // TODO +} + // === COMBAT === function play_flanking_maneuver() { game.combat.flanking = 1 } +function play_cavalry() { + game.combat.cavalry = 1 +} + +function play_spiculum() { + game.combat.spiculum = 1 + game.state = "spiculum" + // TODO +} + function goto_battle_vs_general(where, attacker, target) { goto_battle("general", where, attacker, target) } @@ -3004,6 +3312,16 @@ states.initiate_battle = { gen_card_event(CARD_M3) } + if (!game.combat.cavalry && has_card_event(CARD_M2X)) { + view.prompt += " Cavalry?" + gen_card_event(CARD_M2X) + } + + if (!game.combat.spiculum && has_card_event(CARD_M4X)) { + view.prompt += " Spiculum?" + gen_card_event(CARD_M4X) + } + view.actions.roll = 1 }, card(c) { @@ -3419,6 +3737,8 @@ states.combat_victory = { prompt("Combat: There is no winner.") else if (de || game.combat.dtaken > game.combat.ataken) prompt("Combat: You win the battle!") + else if (game.combat.dtaken === game.combat.ataken && game.combat.cavalry) + prompt("Combat: You win the battle!") else prompt("Combat: Defenders win the battle!") view.actions.done = 1 @@ -3552,8 +3872,12 @@ function goto_free_increase_support_level() { } } - game.combat = null - game.state = "take_actions" + if (game.combat.target === "barbarians" && has_card_event(CARD_S4X)) { + game.state = "triumph" + } else { + game.combat = null + game.state = "take_actions" + } } states.free_increase_support_level = { @@ -3581,6 +3905,28 @@ states.free_increase_support_level = { }, } +states.triumph = { + prompt() { + prompt("Combat: You may play Triumph.") + gen_card_event(CARD_S4X) + view.actions.pass = 1 + }, + card(c) { + push_undo() + set_add(game.used, c) + + award_legacy(game.current, "Triumph", game.combat.dtaken) + + game.combat = null + game.state = "take_actions" + }, + pass() { + push_undo() + game.combat = null + game.state = "take_actions" + }, +} + // === SUPPORT CHECK === function goto_support_check() { @@ -3819,13 +4165,40 @@ function goto_buy_trash_cards() { log("Played no cards.") log_br() + //log_h3("Buy/Trash Cards") + + game.pp = count_political_points() + + log_h3(game.pp + " Political Points") + if (used_card_event(CARD_S2X)) { + let n = Math.min(2, game.sip) + if (n > 0) { + logi("+" + n + " for Princeps Senatus") + game.pp += n + } + } + + game.mip = game.sip = game.pip = 0 + for (let i = 0; i < 3; ++i) { + if (game.killed & (1 << i)) { + logi("+2 senate credits") + game.sip += 2 + } + } + for (let i = 3; i < 6; ++i) { + if (game.killed & (1 << i)) { + logi("+2 military credits") + game.mip += 2 + } + } + let discard = current_discard() for (let c of game.played) set_add(discard, c) - game.played.length = 0 + game.used.length = 0 + game.count = 0 - game.pp = count_political_points() if (game.end) goto_end_of_turn() @@ -3862,47 +4235,26 @@ function find_market_with_card(c) { return null } -function has_military_card_bonus() { - let military_bonus = 0 - if (game.killed & CNIVA_BONUS) - military_bonus += 2 - if (game.killed & ARDASHIR_BONUS) - military_bonus += 2 - if (game.killed & SHAPUR_BONUS) - military_bonus += 2 - return military_bonus +function spend_military_credit(cost) { + let credit = Math.min(cost, game.mip) + game.mip -= credit + return cost - credit } -function has_senate_card_bonus() { - let senate_bonus = 0 - if (game.killed & (1 << POSTUMUS)) - senate_bonus += 2 - if (game.killed & (1 << PRIEST_KING)) - senate_bonus += 2 - if (game.killed & (1 << ZENOBIA)) - senate_bonus += 2 - return senate_bonus -} - -function spend_military_card_bonus() { - game.killed &= ~(CNIVA_BONUS | ARDASHIR_BONUS | SHAPUR_BONUS) -} - -function spend_senate_card_bonus() { - game.killed &= ~((1 << POSTUMUS) | (1 << PRIEST_KING) | (1 << ZENOBIA)) +function spend_senate_credit(cost) { + let credit = Math.min(cost, game.sip) + game.mip -= credit + return cost - credit } states.buy_trash = { inactive: "Buy/Trash Cards", prompt() { - let military_bonus = has_military_card_bonus() - let senate_bonus = has_senate_card_bonus() - prompt("Buy/Trash Cards: " + game.pp + " political points.") - if (military_bonus) - view.prompt += " First Military card is 2 cheaper." - if (senate_bonus) - view.prompt += " First Senate card is 2 cheaper." + if (game.mip > 0) + view.prompt += " " + game.mip + " military credits." + if (game.sip > 0) + view.prompt += " " + game.mip + " senate credits." let nprov = count_own_provinces() if (game.pp >= 3) { @@ -3916,10 +4268,10 @@ states.buy_trash = { if (cost > nprov) cost *= 2 cost += game.count - if (military_bonus && card_influence(c) === MILITARY) - cost -= 2 - if (senate_bonus && card_influence(c) === SENATE) - cost -= 2 + if (card_influence(c) === MILITARY) + cost = Math.max(0, cost - game.mip) + if (card_influence(c) === SENATE) + cost = Math.max(0, cost - game.sip) if (game.pp >= cost) gen_action_card(c) } @@ -3933,9 +4285,6 @@ states.buy_trash = { set_delete(current_discard(), c) game.pp -= 3 } else { - let military_bonus = has_military_card_bonus() - let senate_bonus = has_senate_card_bonus() - log("Buy " + card_name(c) + ".") set_add(current_discard(), c) set_delete(find_market_with_card(c), c) @@ -3945,14 +4294,10 @@ states.buy_trash = { cost *= 2 cost += game.count - if (military_bonus && card_influence(c) === MILITARY) { - spend_military_card_bonus() - cost -= 2 - } - if (senate_bonus && card_influence(c) === SENATE) { - spend_senate_card_bonus() - cost -= 2 - } + if (card_influence(c) === MILITARY) + cost = spend_military_credit(cost) + if (card_influence(c) === SENATE) + cost = spend_senate_credit(cost) game.pp -= cost game.count += 1 @@ -4243,6 +4588,10 @@ exports.setup = function (seed, scenario, options) { killed: 0, combat: null, + ambitus: 0, + frumentarii: 0, + force_march: 0, + provinces: new Array(3 * player_count).fill(1), governors: new Array(6 * player_count).fill(UNAVAILABLE), generals: new Array(6 * player_count).fill(UNAVAILABLE), @@ -4264,17 +4613,57 @@ exports.setup = function (seed, scenario, options) { game.events = setup_events() - game.market = [ - setup_market_pile(CARD_M2), - setup_market_pile(CARD_S2), - setup_market_pile(CARD_P2), - setup_market_pile(CARD_M3), - setup_market_pile(CARD_S3), - setup_market_pile(CARD_P3), - setup_market_pile(CARD_M4), - setup_market_pile(CARD_S4), - setup_market_pile(CARD_P4), - ] + switch (scenario) { + default: + case "Standard": + game.market = [ + setup_market_pile(CARD_M2), + setup_market_pile(CARD_S2), + setup_market_pile(CARD_P2), + setup_market_pile(CARD_M3), + setup_market_pile(CARD_S3), + setup_market_pile(CARD_P3), + setup_market_pile(CARD_M4), + setup_market_pile(CARD_S4), + setup_market_pile(CARD_P4), + ] + break + case "Expansion": + game.market = [ + setup_market_pile(CARD_M2), + setup_market_pile(CARD_S2), + setup_market_pile(CARD_P2), + setup_market_pile(CARD_M2X), + setup_market_pile(CARD_S2X), + setup_market_pile(CARD_P2X), + setup_market_pile(CARD_M3), + setup_market_pile(CARD_S3), + setup_market_pile(CARD_P3), + setup_market_pile(CARD_M3X), + setup_market_pile(CARD_S3X), + setup_market_pile(CARD_P3X), + setup_market_pile(CARD_M4), + setup_market_pile(CARD_S4B), + setup_market_pile(CARD_P4), + setup_market_pile(CARD_M4X), + setup_market_pile(CARD_S4X), + setup_market_pile(CARD_P4X), + ] + break + case "Random": + game.market = [ + setup_market_pile(random(2) ? CARD_M2 : CARD_M2X), + setup_market_pile(random(2) ? CARD_S2 : CARD_S2X), + setup_market_pile(random(2) ? CARD_P2 : CARD_P2X), + setup_market_pile(random(2) ? CARD_M3 : CARD_M3X), + setup_market_pile(random(2) ? CARD_S3 : CARD_S3X), + setup_market_pile(random(2) ? CARD_P3 : CARD_P3X), + setup_market_pile(random(2) ? CARD_M4 : CARD_M4X), + setup_market_pile(random(2) ? CARD_S4B : CARD_S4X), + setup_market_pile(random(2) ? CARD_P4 : CARD_P4X), + ] + break + } set_rival_emperor_location(POSTUMUS, AVAILABLE) set_rival_emperor_location(PRIEST_KING, AVAILABLE) -- cgit v1.2.3