summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-06-21 12:58:29 +0200
committerTor Andersson <tor@ccxvii.net>2023-07-07 18:39:37 +0200
commitf32d40bd233555f956d58ffe398218aa2c9cf633 (patch)
tree44f6799df89b68577980e61890253ae8939b14a8
parente374b1ef04542fdfd57a035011f2895560829fd7 (diff)
downloadtime-of-crisis-f32d40bd233555f956d58ffe398218aa2c9cf633.tar.gz
Barbarian invasions.
-rw-r--r--play.css7
-rw-r--r--play.js88
-rw-r--r--rules.js195
3 files changed, 192 insertions, 98 deletions
diff --git a/play.css b/play.css
index 65a5d64..0a283d5 100644
--- a/play.css
+++ b/play.css
@@ -236,6 +236,13 @@ body.p2 #Galatia_NPG { display: block }
.legion.action { box-shadow: 0 0 0 1px #434343, 0 0 0 4px red; }
.militia.action { box-shadow: 0 0 0 1px #434343, 0 0 0 4px red; }
+.alamanni.action { box-shadow: 0 0 0 1px #393204, 0 0 0 4px white; }
+.franks.action { box-shadow: 0 0 0 1px #1d323a, 0 0 0 4px white; }
+.goths.action { box-shadow: 0 0 0 1px #002759, 0 0 0 4px white; }
+.nomads.action { box-shadow: 0 0 0 1px #610700, 0 0 0 4px white; }
+.sassanids.action { box-shadow: 0 0 0 1px #2f0042, 0 0 0 4px white; }
+.rival_emperor.action { box-shadow: 0 0 0 1px #323214, 0 0 0 4px white; }
+
.red.selected { box-shadow: 0 0 0 1px #680000, 0 0 0 4px yellow; }
.blue.selected { box-shadow: 0 0 0 1px #113854, 0 0 0 4px yellow; }
.yellow.selected { box-shadow: 0 0 0 1px #553a00, 0 0 0 4px yellow; }
diff --git a/play.js b/play.js
index 4b767bc..3e06369 100644
--- a/play.js
+++ b/play.js
@@ -594,26 +594,11 @@ function register_action(target, action, id) {
}
function on_click_action(evt, target) {
- if (evt.button === 0) {
- /*
- if (typeof target.my_stack === "number") {
- evt.stopPropagation()
- if (focus_stack(target.my_stack))
- if (!send_action(target.my_action, target.my_id))
- blur_stack()
- } else {
- */
+ if (evt.button === 0)
if (send_action(target.my_action, target.my_id))
evt.stopPropagation()
- //}
- }
}
-document.getElementById("map").addEventListener("mousedown", function (evt) {
- if (evt.button === 0)
- blur_stack()
-})
-
function create_building(region, className, xoff, yoff) {
let [ x, y, w, h ] = LAYOUT_SUPPORT[region]
let e = create_thing({ className })
@@ -712,36 +697,13 @@ function on_init() {
}
let stack_count = new Array(21).fill(0)
-let stack_focus = -1
-let stack_cache = []
-
-function focus_stack(id) {
- if (stack_focus !== id) {
- // if (view.selected_general === undefined) send_action("general", id)
- stack_focus = id
- on_update()
- let stack = stack_cache[id]
- return stack && stack.length <= 1
- }
- return true
-}
-
-function blur_stack() {
- if (stack_focus >= 0) {
- stack_focus = -1
- on_update()
- }
-}
function layout_stack(id, list, region, in_capital) {
let [ x, y, w, h ] = LAYOUT_XY[region]
- let dx = 6
- let dy = 6
+ let dx = 8
+ let dy = 8
let z = 1
- if (id >= 0)
- stack_cache[id] = list
-
x += w >> 1
y += h >> 1
@@ -772,7 +734,8 @@ function layout_stack(id, list, region, in_capital) {
dy = 16
}
- for (let item of list) {
+ for (let i = list.length - 1; i >= 0; --i) {
+ let item = list[i]
item.style.left = x + "px"
item.style.top = y + "px"
item.style.zIndex = z
@@ -812,9 +775,6 @@ function layout_governor_unavailable(e, color, ix) {
function on_update() {
let player_count = view.legacy.length
- for (let i = 0; i < 24; ++i)
- stack_cache[i] = null
-
ui.body.classList.toggle("p2", player_count === 2)
ui.body.classList.toggle("p3", player_count === 3)
ui.body.classList.toggle("p4", player_count === 4)
@@ -949,10 +909,10 @@ function on_update() {
active_barbarians.push(ui.barbarians[id])
}
}
- if (active_barbarians.length > 0)
- layout_stack(-1, active_barbarians, region, false)
if (inactive_barbarians.length > 0)
layout_stack(-1, inactive_barbarians, region, false)
+ if (active_barbarians.length > 0)
+ layout_stack(-1, active_barbarians, region, false)
}
}
@@ -975,7 +935,7 @@ function on_update() {
let mcastra = has_militia_castra(region)
if (mcastra) {
show(ui.mcastra[region])
- layout_stack(-1, [ ui.militia[region], ui.mcastra[region] ], region, true)
+ layout_stack(-1, [ ui.mcastra[region], ui.militia[region] ], region, true)
} else {
hide(ui.mcastra[region])
layout_stack(-1, [ ui.militia[region] ], region, true)
@@ -1007,32 +967,32 @@ function on_update() {
if (region < 21) {
let stack = []
- if (has_militia(region) && inside)
- stack.push(ui.militia[region])
-
- for (let tribe = 0; tribe < TRIBE_COUNT[player_count]; ++tribe) {
- for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) {
- let loc = get_barbarian_location(id)
- if (loc === army)
- stack.push(ui.barbarians[id])
- }
+ if (castra) {
+ show(ui.castra[pi][ai])
+ stack.push(ui.castra[pi][ai])
+ } else {
+ hide(ui.castra[pi][ai])
}
+ stack.push(e)
+
for (let i = 0; i < 33; ++i) {
let loc = get_legion_location(i)
if (loc === army)
stack.push(ui.legions[i])
}
- stack.push(e)
-
- if (castra) {
- show(ui.castra[pi][ai])
- stack.push(ui.castra[pi][ai])
- } else {
- hide(ui.castra[pi][ai])
+ for (let tribe = 0; tribe < TRIBE_COUNT[player_count]; ++tribe) {
+ for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) {
+ let loc = get_barbarian_location(id)
+ if (loc === army)
+ stack.push(ui.barbarians[id])
+ }
}
+ if (has_militia(region) && inside)
+ stack.push(ui.militia[region])
+
if (inside)
layout_stack(pi * 6 + ai, stack, region, true)
else
diff --git a/rules.js b/rules.js
index 8f436cb..7493404 100644
--- a/rules.js
+++ b/rules.js
@@ -2,6 +2,76 @@
// TODO: barbarian leaders -> barbarian list
+/*
+TODO
+----
+
+[x] crisis ira deorum
+[x] crisis barbarians
+[ ] crisis pax deorum
+
+[ ] tribute
+[ ] foederati
+[ ] mobs
+
+[ ] disperse mob
+
+[ ] combat victory
+[ ] combat retreat out of capital
+[ ] combat retreat barbarians to homeland
+[ ] combat advance into capital
+[ ] combat flanking maneuver
+
+[ ] quaestor
+ [ ] place
+ [ ] remove at start
+ [ ] remove when replaced
+
+[ ] castra
+ [ ] place
+ [ ] remove at start
+ [ ] remove when move/attack
+ [ ] take hits in battle
+
+[ ] support check
+
+[ ] gain legacy
+ [ ] emperor
+ [ ] provinces
+ [ ] improvements
+
+[ ] end turn
+ [ ] grow mobs
+ [ ] flip barbarians
+
+[ ] praetorian guard
+[ ] damnatio memoriae
+
+[ ] pretender
+ [ ] place
+ [ ] expand
+ [ ] scoring effects
+ [ ] occupation effects
+
+[ ] game end
+
+[ ] rival emperors
+ [ ] emperor turns
+ [ ] combat
+ [ ] support check
+ [ ] combat bonus
+ [ ] buy/trash bonus
+
+[ ] barbarian leaders
+ [ ] invasion
+ [ ] combat bonus
+ [ ] combat effect
+ [ ] buy/trash bonus
+
+[ ] other events
+
+*/
+
var game
var view
const states = {}
@@ -127,6 +197,7 @@ const GOTHS = 2
const NOMADS = 3
const SASSANIDS = 4
+const TRIBE_COUNT = [ 0, 5, 3, 4, 5 ]
const BARBARIAN_COUNT = [ 0, 50, 30, 40, 50 ]
const first_barbarian = [ 0, 10, 20, 30, 40 ]
const last_barbarian = [ 9, 19, 29, 39, 49 ]
@@ -686,12 +757,6 @@ function find_inactive_barbarian_at_home(tribe) {
return -1
}
-function activate_one_barbarian(tribe) {
- let i = find_inactive_barbarian_at_home(tribe)
- if (i >= 0)
- set_barbarian_active(i)
-}
-
function count_barbarians_in_province(tribe, where) {
let n = 0
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id)
@@ -879,8 +944,6 @@ function goto_crisis() {
let sum = game.dice[0] + game.dice[1]
- return goto_take_actions() // XXX
-
if (sum === 2)
return goto_ira_deorum()
if (sum === 12)
@@ -897,14 +960,36 @@ function goto_crisis() {
function goto_ira_deorum() {
logi("Ira Deorum")
- activate_one_barbarian(ALAMANNI)
- activate_one_barbarian(FRANKS)
- activate_one_barbarian(GOTHS)
- if (game.legacy.length > 3)
- activate_one_barbarian(NOMADS)
- if (game.legacy.length > 2)
- activate_one_barbarian(SASSANIDS)
- goto_take_actions()
+
+ game.count = 0
+ let tribe_count = BARBARIAN_COUNT[get_player_count()]
+ for (let tribe = 0; tribe < tribe_count; ++tribe)
+ if (find_inactive_barbarian_at_home(tribe) >= 0)
+ game.count |= (1 << tribe)
+
+ game.state = "ira_deorum"
+ if (game.count === 0)
+ goto_take_actions()
+}
+
+states.ira_deorum = {
+ prompt() {
+ prompt("Ira Deorum: Activate one Barbarian in each tribe's homeland.")
+ let tribe_count = BARBARIAN_COUNT[get_player_count()]
+ for (let tribe = 0; tribe < tribe_count; ++tribe)
+ if (game.count & (1 << tribe))
+ gen_action_barbarian(find_inactive_barbarian_at_home(tribe))
+ },
+ barbarian(id) {
+ let tribe = get_barbarian_tribe(id)
+ game.count &= ~(1 << tribe)
+
+ log("Activated " + BARBARIAN_NAME[tribe])
+ set_barbarian_active(id)
+
+ if (game.count === 0)
+ goto_take_actions()
+ },
}
function goto_pax_deorum() {
@@ -921,7 +1006,31 @@ function goto_event() {
function goto_barbarian_crisis(tribe) {
logi(BARBARIAN_NAME[tribe])
- activate_one_barbarian(tribe)
+
+ game.crisis = tribe
+
+ if (find_inactive_barbarian_at_home(tribe) >= 0)
+ game.state = "barbarian_crisis"
+ else
+ roll_barbarian_crisis()
+}
+
+states.barbarian_crisis = {
+ prompt() {
+ let tribe = game.crisis
+ prompt(BARBARIAN_NAME[tribe] + " Crisis!")
+ gen_action_barbarian(find_inactive_barbarian_at_home(tribe))
+ },
+ barbarian(id) {
+ let tribe = game.crisis
+ log("Activated " + BARBARIAN_NAME[tribe])
+ set_barbarian_active(id)
+ roll_barbarian_crisis()
+ },
+}
+
+function roll_barbarian_crisis() {
+ let tribe = game.crisis
let black = game.dice[2] = roll_die()
let white = game.dice[3] = roll_die()
@@ -929,39 +1038,57 @@ function goto_barbarian_crisis(tribe) {
logi(`B${black} W${white}`)
if (black <= count_active_barbarians_at_home(tribe))
- goto_barbarian_invasion(tribe, black, white)
+ goto_barbarian_invasion()
else
goto_take_actions()
}
-function invade_with_active_barbarian(tribe, where) {
- // TODO: move leaders first
- let id = find_active_barbarian_at_home(tribe)
- if (id >= 0)
- set_barbarian_location(id, where)
-}
-
function goto_barbarian_invasion(tribe, black, white) {
logi("Invasion!")
+ game.count = game.dice[2]
+ game.state = "barbarian_invasion"
+}
+
+states.barbarian_invasion = {
+ prompt() {
+ let tribe = game.crisis
+ prompt(BARBARIAN_NAME[tribe] + " Invasion!")
+ gen_action_barbarian(find_active_barbarian_at_home(tribe))
+ },
+ barbarian(id) {
+ if (invade_with_barbarian(id) || --game.count === 0)
+ goto_take_actions()
+ },
+}
+
+function invade_with_barbarian(id) {
+ let tribe = game.crisis
+ let white = game.dice[3]
let path = null
for (let list of BARBARIAN_INVASION[tribe])
if (white >= list[0] && white <= list[1])
path = list[2]
- let k = 0
- for (let i = 0; i < black;) {
- let n = count_barbarians_in_province(tribe, path[k])
+ for (let i = 0; i < path.length; ++i) {
+ let n = count_barbarians_in_province(tribe, path[i])
if (n < 3) {
- invade_with_active_barbarian(tribe, path[k])
- ++i
- } else {
- if (++k > path.length)
- break
+ invade_with_barbarian_counter(id, path, path[i])
+ return false
}
}
- goto_take_actions()
+ return true
+}
+
+function invade_with_barbarian_counter(id, path, where) {
+ set_barbarian_location(id, where)
+ for (let loc of path) {
+ if (has_limes(loc))
+ set_barbarian_inactive(id)
+ if (loc === where)
+ break
+ }
}
// === TAKE ACTIONS ===