summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoël Simoneau <simoneaujoel@gmail.com>2025-03-12 20:24:05 -0400
committerJoël Simoneau <simoneaujoel@gmail.com>2025-03-12 20:24:05 -0400
commit041a30e48bea02b754b1782bfea8da467929f025 (patch)
treee07c96ab36ed3d151fac17ca818eb985e27a1a71
parentdb486cfb273bafaf6fae7a49dc09737ccaec96bd (diff)
downloadvijayanagara-041a30e48bea02b754b1782bfea8da467929f025.tar.gz
Timurid part 2
-rw-r--r--events.txt20
-rw-r--r--rules.js203
2 files changed, 178 insertions, 45 deletions
diff --git a/events.txt b/events.txt
index c260271..921084c 100644
--- a/events.txt
+++ b/events.txt
@@ -762,3 +762,23 @@ SUCC 3
force_current VE
loge "Vast, unifying medieval metropolis."
influence_succession
+
+SUCC 5
+ force_current DS
+ prompt "Invaders are attacking in the Mountain Passes!"
+ space 1 (s === S_MOUNTAIN_PASSES && has_ds_unit(s) && has_mi_unit(s))
+ free_attack DS
+ timurid_advance S_MOUNTAIN_PASSES S_PUNJAB
+ endspace
+ prompt "Invaders are moving towards Delhi!"
+ space 1 (s === S_PUNJAB && has_ds_unit(s) && has_mi_unit(s))
+ free_attack DS
+ timurid_advance S_PUNJAB S_DELHI
+ endspace
+ prompt "Invaders are laying a siege to Delhi!"
+ space 1 (s === S_DELHI && has_ds_unit(s) && has_mi_unit(s))
+ while (has_ds_unit(game.vm.s))
+ free_attack DS
+ endwhile
+ endspace
+ end_game
diff --git a/rules.js b/rules.js
index 5e89b65..a43fe61 100644
--- a/rules.js
+++ b/rules.js
@@ -352,9 +352,12 @@ function goto_card() {
} else if (this_card() >= 41 && this_card() <= 44) {
log_h1("Mongol Invaders C" + this_card())
goto_mongol_invaders(VE)
- } else if (this_card() >= 45 && this_card() <= 49) {
+ } else if (this_card() >= 45 && this_card() <= 47) {
log_h1("C" + this_card())
succession()
+ } else if (this_card() >= 48 && this_card() <= 49) {
+ log_h1("Mongol Invaders C" + this_card())
+ succession()
} else {
log_h1("C" + this_card())
adjust_eligibility(DS)
@@ -571,7 +574,7 @@ function succession() {
else if (game.succ === 4) {
timurid_step1()
} else if (game.succ === 5) {
-
+ goto_vm(game.succ * 2 + 72)
}
}
@@ -579,6 +582,10 @@ function is_succession() {
return (game.vm && game.vm.fp > 72)
}
+function is_timurid() {
+ return (game.vm && game.vm.fp > 78)
+}
+
function timurid_step1() {
let n = Math.floor(count_pieces(AVAILABLE, MI, TROOPS) / 2)
@@ -590,6 +597,7 @@ function timurid_step1() {
place_piece(p, S_MOUNTAIN_PASSES)
}
pop_summary()
+ end_card()
}
/* STATES */
@@ -1107,11 +1115,6 @@ function attack_use_cavalry(d, f) {
} else if (!is_a_die && !is_attacker) {
charge_die(d)
}
-
- if (game.cmd.cav_faction === MI) {
- game.cmd.step += 1
- next_attack_cavalry_step()
- }
}
function charge_die(d) {
@@ -1287,23 +1290,31 @@ function next_attack_cavalry_step() {
}
function goto_attack_cavalry(curr) {
- if (curr === MI && curr === game.cmd.target) {
- if (game.dice[4] - 1 === game.cmd.n_units[1] || (game.dice[4] === 6 && game.cmd.n_units[1] >= 5)) {
- log(`${faction_acronyms[game.current]} is using Cavalry.`)
- attack_use_cavalry(4, MI)
- } else if (game.dice[5] - 1 === game.cmd.n_units[1] || (game.dice[5] === 6 && game.cmd.n_units[1] >= 5)) {
- log(`${faction_acronyms[game.current]} is using Cavalry.`)
- attack_use_cavalry(5, MI)
+ if (curr === MI) {
+ let u = curr === game.cmd.attacker ? 0 : 1
+ let dices = game.dice.slice(
+ curr === game.cmd.attacker ? 0 : 4,
+ curr === game.cmd.attacker ? 4 : 6,
+ )
+
+ let d_hit = dices.findIndex(d =>
+ (d - 1 === game.cmd.n_units[u] || (d === 6 && game.cmd.n_units[u] >= 5))
+ )
+
+ if (d_hit !== -1) {
+ log(`${faction_acronyms[curr]} is using Cavalry.`)
+ attack_use_cavalry(d_hit + (curr === game.cmd.attacker ? 0 : 4), MI)
+ } else {
+ let d_hit2 = dices.findIndex(d => d ===2)
+ if (d_hit2 !== -1) {
+ log(`${faction_acronyms[curr]} is using Cavalry.`)
+ attack_use_cavalry(d_hit + (curr === game.cmd.attacker ? 0 : 4), MI)
+ }
}
game.cmd.step += 1
next_attack_cavalry_step()
- } else if (curr === MI) {
- game.current = game.cmd.sa_faction,
- game.cmd.cav_faction = MI
- game.state = "attack_cavalry"
} else {
game.current = curr
- game.cmd.cav_faction = curr
game.state = "attack_cavalry"
}
}
@@ -1311,37 +1322,21 @@ function goto_attack_cavalry(curr) {
states.attack_cavalry = {
prompt() {
let curr_die = [0, 1, 2, 3, 4, 5]
- let can_charge = false
- if (game.cmd.cav_faction === MI) {
- view.prompt = "Attack: Use the Mongol Cavalry to Charge a die."
- curr_die = [0, 1, 2, 3]
- if (has_cavalry(game.cmd.cav_faction))
- for (let d of curr_die)
- if (game.dice[d] === 2 || game.dice[d] === game.cmd.n_units[0] + 1 || (game.dice[d] === 6 && game.cmd.n_units[0] >= 5)) {
- gen_action_die(d)
- can_charge = true
- }
- if (!can_charge)
- view.prompt = "Attack: No Charge possible for the Mongol Cavalry."
- } else {
- view.prompt = "Attack: Use cavalry to Charge your dice or Screen your opponent's dice."
- if (has_cavalry(game.cmd.cav_faction))
- for (let d of curr_die)
- if (game.dice[d] > 1)
- gen_action_die(d)
- }
-
- if (game.cmd.cav_faction !== MI || game.cmd.cavalry || !can_charge)
- view.actions.next = 1
+ view.prompt = "Attack: Use cavalry to Charge your dice or Screen your opponent's dice."
+ if (has_cavalry(game.current))
+ for (let d of curr_die)
+ if (game.dice[d] > 1)
+ gen_action_die(d)
+ view.actions.next = 1
view.who = game.cmd.selected
},
die(d) {
if (!game.cmd.cavalry) {
- log(`${faction_acronyms[game.cmd.cav_faction]} is using Cavalry.`)
+ log(`${faction_acronyms[game.current]} is using Cavalry.`)
game.cmd.cavalry = true
}
- attack_use_cavalry(d, game.cmd.cav_faction)
+ attack_use_cavalry(d, game.current)
},
next() {
game.cmd.step += 1
@@ -1424,7 +1419,7 @@ function goto_attack_resolution() {
if (is_rebel_faction(game.cmd.target) && is_rebel_faction(game.cmd.attacker))
attack_influence_shift()
- if (game.cmd.attacker === MI) {
+ if (game.cmd.attacker === MI && !is_timurid()) {
game.current = game.cmd.sa_faction
game.state = "plunder"
} else if (game.vm) {
@@ -2933,6 +2928,10 @@ function has_ds_unit(s) {
return has_piece(s, DS, ELITE) || has_piece(s, DS, TROOPS)
}
+function has_mi_unit(s) {
+ return has_piece(s, MI, TROOPS)
+}
+
function is_adjacent(a, b) {
return set_has(SPACES[a].adjacent, b)
}
@@ -4097,6 +4096,17 @@ states.vm_return = {
end_event,
}
+function vm_while() {
+ if (vm_operand(1))
+ vm_next()
+ else
+ vm_goto(vm_endwhile, vm_while, 1, 1)
+}
+
+function vm_endwhile() {
+ vm_goto(vm_while, vm_endwhile, -1, 0)
+}
+
// VM: SPACE
function vm_space() {
@@ -4584,7 +4594,11 @@ function vm_free_attack() {
pieces: pieces,
where: game.vm.s,
}
- game.cmd.attacker = game.current
+
+ if (is_timurid())
+ game.cmd.attacker = MI
+ else
+ game.cmd.attacker = game.current
game.cmd.support_space = null
if (game.vm.fp === 43)
@@ -4725,6 +4739,82 @@ states.influence_succession = {
next: vm_next
}
+// VM : TIMURID ADVANCE
+
+function vm_timurid_advance() {
+ let s1 = vm_operand(1)
+ let s2 = vm_operand(2)
+
+ let n = count_pieces(s1, MI, TROOPS)
+ push_summary()
+ for (let i = 0; i < n; ++i) {
+ let p = find_piece(s1, MI, TROOPS)
+ log_summary_place(p)
+ place_piece(p, s2)
+ }
+ log_action("S" + s2 + " - Advance")
+ pop_summary()
+ vm_next()
+}
+
+// VM : END GAME
+
+function vm_end_game() {
+ // Aftermath
+ let vp = Math.max(3 - count_pieces(S_DELHI, MI, TROOPS), -3)
+ log_action("Invasion's aftermath...")
+ if (vp > 0)
+ logi(faction_acronyms[DS] + " VP +" + vp + ".")
+ else
+ logi(faction_acronyms[DS] + " VP " + vp + ".")
+ game.vp[DS] += vp
+
+ log_h2("Victory Phase")
+ for (let i = 0; i < 3; i++) {
+ logi(faction_name[i] + " " + game.vp[i] + " VP")
+ }
+
+ game.vp = [0,12,12]
+ game.resources = [0, 12, 12]
+
+ let result = get_result()
+ goto_game_over(result)
+}
+
+function get_idx_max(arr) {
+ let m = Math.max(...arr)
+ return arr
+ .map((v, i) => (v === m ? i : -1))
+ .filter(i => i !== -1)
+}
+
+function get_result() {
+ let i_vp = get_idx_max([...game.vp])
+
+ if (i_vp.length === 1)
+ return faction_name[i_vp[0]]
+
+ let i_res = get_idx_max(i_vp.map(i => game.resources[i]))
+
+ if (i_res.length === 1)
+ return faction_name[i_vp[i_res]]
+
+ return i_res.map(i => faction_name[i_vp[i]]).join(",")
+}
+
+// === GAME END ===
+
+function goto_game_over(result) {
+ game.state = "game_over"
+ game.current = -1
+ game.active = "None"
+ game.result = result
+ game.victory = game.result + " won!"
+ log_br()
+ log(game.victory)
+ return true
+}
+
// VM: MIX
@@ -5954,3 +6044,26 @@ CODE[3 * 2 + 72] = [
[ vm_influence_succession ],
[ vm_return ],
]
+
+// SUCC 5
+CODE[5 * 2 + 72] = [
+ [ vm_force_current, DS ],
+ [ vm_prompt, "Invaders are attacking in the Mountain Passes!" ],
+ [ vm_space, true, 1, 1, (s)=>(s === S_MOUNTAIN_PASSES && has_ds_unit(s) && has_mi_unit(s)) ],
+ [ vm_free_attack, DS ],
+ [ vm_timurid_advance, S_MOUNTAIN_PASSES, S_PUNJAB ],
+ [ vm_endspace ],
+ [ vm_prompt, "Invaders are moving towards Delhi!" ],
+ [ vm_space, true, 1, 1, (s)=>(s === S_PUNJAB && has_ds_unit(s) && has_mi_unit(s)) ],
+ [ vm_free_attack, DS ],
+ [ vm_timurid_advance, S_PUNJAB, S_DELHI ],
+ [ vm_endspace ],
+ [ vm_prompt, "Invaders are laying a siege to Delhi!" ],
+ [ vm_space, true, 1, 1, (s)=>(s === S_DELHI && has_ds_unit(s) && has_mi_unit(s)) ],
+ [ vm_while, ()=>(has_ds_unit(game.vm.s)) ],
+ [ vm_free_attack, DS ],
+ [ vm_endwhile ],
+ [ vm_endspace ],
+ [ vm_end_game ],
+ [ vm_return ],
+]