From 78eb830571c26ebbfbcb8bc0608b11db868aeb90 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 21 Jun 2023 21:18:28 +0200 Subject: Praetorian Guard. --- play.css | 21 +++---- play.js | 6 +- rules.js | 213 ++++++++++++++++++++++++++++++++++++++++++++------------------- 3 files changed, 163 insertions(+), 77 deletions(-) diff --git a/play.css b/play.css index b2ea395..f23699f 100644 --- a/play.css +++ b/play.css @@ -90,6 +90,14 @@ body.senate svg .region.selected { stroke-dasharray: 8 4; } +body.military svg .region.selected { + fill: hsl(358, 78%, 51%); + fill-opacity: 0.3; + stroke: hsl(358, 78%, 51%); + stroke-width: 4px; + stroke-dasharray: 8 4; +} + body.military svg .sea.action { fill: hsl(206, 100%, 35%); fill-opacity: 0.25; @@ -174,20 +182,11 @@ body.military svg .sea.action { .capital.action { display: block; border: 5px solid white; - //box-shadow: 0px 0px 8px white; + background-color: #fff8; + box-shadow: 0 0 6px white, inset 0 0 6px black; z-index: 2; } -body.military .capital.action { - border-color: hsl(358, 78%, 51%); - background-color: hsla(358, 75%, 51%, 0.2); -} - -body.populace .capital.action { - border-color: hsl(44, 80%, 52%); - background-color: hsla(44, 80%, 52%, 0.2); -} - body.p3 #Hispania_NPG { display: block } body.p3 #Africa_NPG { display: block } body.p3 #Aegyptus_NPG { display: block } diff --git a/play.js b/play.js index 18550e4..09e9217 100644 --- a/play.js +++ b/play.js @@ -747,11 +747,13 @@ function layout_available(list, dx, x0, y0) { let y = 1650 + 45 - y0 let x = 25 + x0 for (let item of list) { - item.style.left = x + "px" + let xo = item.my_id % 6 + if (list.length < 6) + xo -= 1 + item.style.left = (x + xo * dx) + "px" item.style.top = y + "px" item.style.zIndex = 1 item.my_stack = 0 - x += dx } } diff --git a/rules.js b/rules.js index 7c2d3e3..d131ceb 100644 --- a/rules.js +++ b/rules.js @@ -50,7 +50,7 @@ TODO [x] grow mobs [x] flip barbarians -[ ] praetorian guard +[x] praetorian guard [ ] damnatio memoriae [ ] pretender [ ] place @@ -1218,7 +1218,7 @@ states.take_actions = { gen_action_governor(id) break case AVAILABLE: - if (sip >= 1) + if (sip >= 1 || has_unused_praetorian_guard()) gen_action_governor(id) break default: @@ -1485,14 +1485,9 @@ states.take_actions = { set_legion_full_strength(find_reduced_legion_in_army(game.selected_general)) }, - capital(where) { - push_undo() - set_general_inside_capital(game.selected_general) - }, - enter() { push_undo() - set_general_inside_capital(game.selected_general) + enter_capital() }, leave() { @@ -1525,10 +1520,17 @@ states.take_actions = { if (get_general_location(game.selected_general) === AVAILABLE) create_army(where) else - move_army_to(game.selected_general, where, true) + 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() + }, + barbarian(id) { push_undo() goto_battle_vs_barbarian(get_general_location(game.selected_general), game.selected_general, id) @@ -1545,6 +1547,13 @@ states.take_actions = { }, } +// FREE ACTION: ENTER PROVINCIAL CAPITAL + +function enter_capital() { + set_general_inside_capital(game.selected_general) + // TODO: seat of power / breakaway +} + // ACTION: IMPROVE SUPPORT function improve_support() { @@ -1633,38 +1642,41 @@ function place_governor(where, new_governor) { update_neutral_italia() } -function calc_needed_votes(where) { +function calc_needed_votes(where, pg) { let n = get_support(where) * 2 // base number of votes let old_governor = get_province_governor(where) let old_player = (old_governor < 0) ? -1 : (old_governor / 6 | 0) - let army_general = get_capital_general(where) - if (army_general >= 0) { - let army_player = army_general / 6 | 0 - let army_size = count_units_in_army(army_general) - if (army_player === old_player) - n += army_size - else if (army_player === game.current) - n -= army_size + // Praetorian Guard ignores units in capital + if (!pg) { + let army_general = get_capital_general(where) + if (army_general >= 0) { + let army_player = army_general / 6 | 0 + let army_size = count_units_in_army(army_general) + if (army_player === old_player) + n += army_size + else if (army_player === game.current) + n -= army_size + } + if (has_militia(where)) + n += 1 } - if (has_militia(where)) - n += 1 return Math.max(1, n) } states.place_governor = { prompt() { let [ mip, sip, pip ] = game.ip - let need = calc_needed_votes(game.misc.where) + let need = calc_needed_votes(game.misc.where, false) let votes = game.misc.spend if (game.misc.where === ITALIA) votes += count_own_basilicas() view.color = SENATE view.selected_region = game.misc.where - prompt(`Place Governor: ${sip} Senate. Rolling ${votes} dice. ${need} votes needed.`) - - view.actions.spend_senate = (sip >= 1) - + if (sip >= 1) + view.actions.spend_senate = 1 + else + view.actions.spend_senate = 0 view.actions.roll = 1 }, spend_senate() { @@ -1673,33 +1685,96 @@ states.place_governor = { game.misc.spend += 1 }, roll() { - let need = calc_needed_votes(game.misc.where) - let have = 0 - - set_placed_governor(game.misc.where) + roll_to_place_governor() + }, +} +states.praetorian_guard = { + prompt() { + let [ mip, sip, pip ] = game.ip + let need = calc_needed_votes(game.misc.where, true) + let votes = game.misc.spend if (game.misc.where === ITALIA) - game.misc.spend += count_own_basilicas() + votes += count_own_basilicas() + view.color = MILITARY + view.selected_region = game.misc.where + prompt(`Praetorian Guard: ${mip} Military. Rolling ${votes} dice. ${need} votes needed.`) + if (mip >= 1) + view.actions.spend_military = 1 + else + view.actions.spend_military = 0 + view.actions.roll = 1 + }, + spend_military() { + push_undo() + spend_ip(MILITARY, 1) + game.misc.spend += 1 + }, + roll() { + roll_to_place_governor() + }, +} +function roll_to_place_governor(pg) { + let need = calc_needed_votes(game.misc.where, pg) + let have = 0 + + set_placed_governor(game.misc.where) + + if (game.misc.where === ITALIA) + game.misc.spend += count_own_basilicas() + + if (pg) + log("Praetorian Guard in S" + game.misc.where) + else log("Place Governor in S" + game.misc.where) - if (is_neutral_province(game.misc.where)) - have = roll_dice(game.misc.spend, 1) - else if (has_quaestor(game.misc.where)) - have = roll_dice(game.misc.spend, 3) - else - have = roll_dice(game.misc.spend, 2) - if (have >= need) { - logi("Success!") - place_governor(game.misc.where, game.selected_governor) - } else { - logi("Failed!") - game.selected_governor = -1 - } + if (is_neutral_province(game.misc.where)) + have = roll_dice(game.misc.spend, 1) + else if (!pg && has_quaestor(game.misc.where)) + have = roll_dice(game.misc.spend, 3) + else + have = roll_dice(game.misc.spend, 2) - game.misc = null - game.state = "take_actions" - }, + if (have >= need) { + logi("Success!") + place_governor(game.misc.where, game.selected_governor) + } else { + logi("Failed!") + } + + game.misc = null + game.state = "take_actions" +} + +// ACTION: PRAETORIAN GUARD + +function has_unused_praetorian_guard() { + return game.ip[MILITARY] >= 1 && !is_own_province(ITALIA) && !has_placed_governor(ITALIA) && has_praetorian_guard_card() +} + +function has_praetorian_guard_card() { + let played = false + let used = false + for (let c of game.played) + if (c >= CARD_M4[0] && c <= CARD_M4[1]) + played = true + for (let c of game.used) + if (c >= CARD_M4[0] && c <= CARD_M4[1]) + used = true + return played && !used +} + +function can_play_praetorian_guard() { + if (game.selected_governor >= 0 && get_governor_location(game.selected_governor) === AVAILABLE) + return game.ip[MILITARY] >= 1 && !is_own_province(ITALIA) && !has_placed_governor(ITALIA) + return false +} + +function play_praetorian_guard() { + spend_ip(MILITARY, 1) + game.misc = { spend: 1, where: ITALIA } + game.state = "praetorian_guard" } // ACTION: CREATE ARMY @@ -1729,9 +1804,11 @@ function gen_move_army() { let from = get_general_location(game.selected_general) if (mip >= 1) { for (let to of ADJACENT[from]) { - if (!is_sea(to)) + if (!is_sea(to)) { gen_action_region(to) - else if (mip >= 2) + if (can_enter_capital(to)) + gen_action_capital(to) + } else if (mip >= 2) gen_action_region(to) } } @@ -1746,23 +1823,22 @@ states.move_army_at_sea = { }, region(to) { push_undo() - move_army_to(game.selected_general, to, true) + move_army_to(game.selected_general, to) }, capital(to) { push_undo() - move_army_to(game.selected_general, to, true) + move_army_to(game.selected_general, to) + enter_capital() }, } -function move_army_to(who, to, go_inside) { +function move_army_to(who, to) { log("Moved Army to S" + to + ".") remove_general_castra(who) spend_ip(MILITARY, 1) set_general_location(who, to) - if (can_enter_capital(to) && go_inside) - set_general_inside_capital(who) if (is_sea(to)) game.state = "move_army_at_sea" @@ -1855,15 +1931,17 @@ function can_foederati_from_region(where) { return false } -function gen_foederati(where) { +function gen_foederati(where, recruit) { let tribe_count = get_tribe_count() for (let tribe = 0; tribe < tribe_count; ++tribe) { let id = find_active_barbarian_of_tribe(where, tribe) if (id >= 0) gen_action_barbarian(id) - id = find_inactive_barbarian_of_tribe(where, tribe) - if (id >= 0) - gen_action_barbarian(id) + if (recruit || is_province(where)) { + id = find_inactive_barbarian_of_tribe(where, tribe) + if (id >= 0) + gen_action_barbarian(id) + } } } @@ -1877,10 +1955,13 @@ function can_foederati_from_region_and_adjacent(from) { } function can_play_foederati() { + let where = get_selected_region() if (game.selected_general >= 0) - if (count_legions_in_army(game.selected_general) > count_barbarians_in_army(game.selected_general)) - if (can_foederati_from_region_and_adjacent(get_general_location(game.selected_general))) - return true + if (can_foederati_from_region_and_adjacent(where)) + return true + if (game.selected_governor >= 0) + if (has_lone_militia(where) && can_foederati_from_region_and_adjacent(where)) + return true return false } @@ -1890,18 +1971,22 @@ function play_foederati() { states.foederati = { prompt() { - prompt("Foederati: Recruit a Barbarian.") + prompt("Foederati: Remove or recruit a Barbarian.") view.selected_general = game.selected_general let from = get_general_location(game.selected_general) - gen_foederati(from) + let recruit = (game.selected_general >= 0 && count_legions_in_army(game.selected_general) > count_barbarians_in_army(game.selected_general)) + gen_foederati(from, recruit) for (let to of ADJACENT[from]) - gen_foederati(to) + gen_foederati(to, recruit) }, barbarian(id) { let tribe = get_barbarian_tribe(id) let from = get_barbarian_location(id) log("Foederati " + BARBARIAN_NAME[tribe] + " from S" + from) - set_barbarian_location(id, ARMY + game.selected_general) + if (game.selected_general >= 0 && count_legions_in_army(game.selected_general) > count_barbarians_in_army(game.selected_general)) + set_barbarian_location(id, ARMY + game.selected_general) + else + eliminate_barbarian(id) game.state = "take_actions" }, } -- cgit v1.2.3