diff options
-rw-r--r-- | events.txt | 20 | ||||
-rw-r--r-- | rules.js | 203 |
2 files changed, 178 insertions, 45 deletions
@@ -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 @@ -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 ], +] |