From 34d668d46988eccf279cece033f35533aa56904c Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 21 Jun 2021 19:09:35 +0200 Subject: crusader: More siege stuff. --- rules.js | 46 +++++++++++++++++++++++++++++++++++++++------- ui.js | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/rules.js b/rules.js index bf67092..c37c2f6 100644 --- a/rules.js +++ b/rules.js @@ -7,6 +7,7 @@ // TODO: optional rule - force marches // TODO: strict move order for group moves? +// Move Phase -> Group Move / Muster / Sea Move -> Move Phase exports.scenarios = [ "Third Crusade" @@ -595,6 +596,9 @@ function disband(who) { } function eliminate_block(who) { + remove_from_array(game.castle, who); + if (game.sallying) remove_from_array(game.sallying, who); + if (game.storming) remove_from_array(game.storming, who); if (block_plural(who)) log(block_name(who) + " are eliminated."); else @@ -1606,9 +1610,9 @@ states.declare_sally = { if (n == 0) log(game.active + " declines to sally."); else if (n == 1) - log(game.active + " sallies " + n + "block."); + log(game.active + " sallies with 1 block."); else - log(game.active + " sallies " + n + "blocks."); + log(game.active + " sallies with " + n + " blocks."); if (is_contested_battle_field()) { if (!game.was_contested) { log(game.active + " is now the attacker."); @@ -1720,7 +1724,24 @@ states.retreat_to = { function goto_siege_attrition() { console.log("SIEGE ATTRITION"); - end_combat(); + game.active = besieging_player(game.where); + for (let b in BLOCKS) { + if (is_block_in_castle_in(game.where)) { + let die = roll_d6(); + if (die <= 3) { + log("Siege attrition: " + DIE_HIT[die] + "."); + reduce_block(b); + } else { + log("Siege attrition: " + DIE_MISS[die] + "."); + } + } + } + if (!is_under_siege(game.where)) { + log(game.where + " falls to siege attrition."); + goto_regroup(); + } else { + end_combat(); + } } // FIELD BATTLE @@ -1751,14 +1772,14 @@ function resume_field_battle() { if (is_friendly_field(game.where)) { console.log("FIELD BATTLE WON BY", game.active); - log("Field battle won by", game.active); + log("Field battle won by " + game.active); return goto_regroup(); } if (is_enemy_field(game.where)) { game.active = ENEMY[game.active]; console.log("FIELD BATTLE WON BY", game.active); - log("Field battle won by", game.active + "."); + log("Field battle won by " + game.active + "."); return goto_regroup(); } @@ -1795,7 +1816,7 @@ states.field_battle = { gen_action(view, 'battle_fire', b); if (game.sallying.includes(b)) { // Only sallying forces may withdraw into the castle - gen_action(view, 'battle_withdraw'); + gen_action(view, 'battle_withdraw', b); } else { if (can_block_retreat(b)) { gen_action(view, 'battle_retreat', b); @@ -1966,7 +1987,10 @@ function charge_with_block(b) { } function field_withdraw_with_block(b) { - log(game.active[0] + ": " + b + " withdraws."); + if (block_plural(b)) + log(game.active[0] + ": " + b + " withdraw."); + else + log(game.active[0] + ": " + b + " withdraws."); game.moved[b] = true; remove_from_array(game.sallying, b); game.castle.push(b); @@ -2115,6 +2139,12 @@ function setup_game() { // VIEW +function compare_block_initiative(a, b) { + let aa = BLOCKS[a].combat; + let bb = BLOCKS[b].combat; + return (aa < bb) ? -1 : (aa > bb) ? 1 : 0; +} + function make_battle_view() { let battle = { FA: [], FC: [], FR: [], @@ -2133,6 +2163,8 @@ function make_battle_view() { for (let b in BLOCKS) if (game.location[b] == game.where & block_owner(b) == owner && fn(b)) cell.push([b, game.steps[b], game.moved[b]?1:0]) + cell.sort((a,b) => compare_block_initiative(a[0], b[0])); + console.log("CELL", cell); } fill_cell(battle.FR, FRANK, b => is_battle_reserve(b)); diff --git a/ui.js b/ui.js index 71ca0ce..a0273a6 100644 --- a/ui.js +++ b/ui.js @@ -161,6 +161,16 @@ function on_focus_battle_withdraw(evt) { "Withdraw with " + block_name(evt.target.block); } +function on_focus_battle_storm(evt) { + document.getElementById("status").textContent = + "Storm with " + block_name(evt.target.block); +} + +function on_focus_battle_sally(evt) { + document.getElementById("status").textContent = + "Sally with " + block_name(evt.target.block); +} + function on_focus_battle_hit(evt) { document.getElementById("status").textContent = "Take hit on " + block_name(evt.target.block); @@ -176,6 +186,8 @@ function on_click_battle_retreat(evt) { send_action('battle_retreat', evt.target function on_click_battle_charge(evt) { send_action('battle_charge', evt.target.block); } function on_click_battle_harry(evt) { send_action('battle_harry', evt.target.block); } function on_click_battle_withdraw(evt) { send_action('battle_withdraw', evt.target.block); } +function on_click_battle_storm(evt) { send_action('battle_storm', evt.target.block); } +function on_click_battle_sally(evt) { send_action('battle_sally', evt.target.block); } function on_click_card(evt) { let c = evt.target.id.split("+")[1] | 0; @@ -185,10 +197,12 @@ function on_click_card(evt) { function on_button_next(evt) { send_action('next'); } function on_button_pass(evt) { send_action('pass'); } function on_button_undo(evt) { send_action('undo'); } +function on_button_group_move(evt) { send_action('group_move'); } +function on_button_end_group_move(evt) { send_action('end_group_move'); } function on_button_sea_move(evt) { send_action('sea_move'); } +function on_button_end_sea_move(evt) { send_action('end_sea_move'); } function on_button_muster(evt) { send_action('muster'); } function on_button_end_muster(evt) { send_action('end_muster'); } -function on_button_end_sea_move(evt) { send_action('end_sea_move'); } function on_button_end_move_phase(evt) { send_action('end_move_phase'); } function on_button_end_regroup(evt) { send_action('end_regroup'); } function on_button_end_retreat(evt) { send_action('end_retreat'); } @@ -240,6 +254,12 @@ function build_battle_block(b, block) { build_battle_button(menu_list, b, "withdraw", on_click_battle_withdraw, on_focus_battle_withdraw, "/images/stone-tower.svg"); + build_battle_button(menu_list, b, "storm", + on_click_battle_storm, on_focus_battle_storm, + "/images/siege-tower.svg"); + build_battle_button(menu_list, b, "sally", + on_click_battle_sally, on_focus_battle_sally, + "/images/doorway.svg"); let menu = document.createElement("div"); menu.classList.add("battle_menu"); @@ -585,6 +605,10 @@ function update_battle() { for (let [block, steps, moved] of list) { ui.present.add(block); + // TODO: insert in correct order! + if (!cell.contains(ui.battle_menu[block])) + cell.appendChild(ui.battle_menu[block]); + if (block == game.who) ui.battle_block[block].classList.add("selected"); else @@ -596,6 +620,8 @@ function update_battle() { ui.battle_menu[block].classList.remove('fire'); ui.battle_menu[block].classList.remove('harry'); ui.battle_menu[block].classList.remove('withdraw'); + ui.battle_menu[block].classList.remove('storm'); + ui.battle_menu[block].classList.remove('sally'); ui.battle_menu[block].classList.remove('retreat'); if (game.actions && game.actions.block && game.actions.block.includes(block)) @@ -610,6 +636,10 @@ function update_battle() { ui.battle_menu[block].classList.add('charge'); if (game.actions && game.actions.battle_withdraw && game.actions.battle_withdraw.includes(block)) ui.battle_menu[block].classList.add('withdraw'); + if (game.actions && game.actions.battle_storm && game.actions.battle_storm.includes(block)) + ui.battle_menu[block].classList.add('storm'); + if (game.actions && game.actions.battle_sally && game.actions.battle_sally.includes(block)) + ui.battle_menu[block].classList.add('sally'); if (game.actions && game.actions.battle_hit && game.actions.battle_hit.includes(block)) ui.battle_menu[block].classList.add('hit'); if (game.actions && game.actions.battle_charge && game.actions.battle_charge.includes(block)) @@ -633,10 +663,7 @@ function update_battle() { } for (let b in BLOCKS) { - if (ui.present.has(b)) { - if (!cell.contains(ui.battle_menu[b])) - cell.appendChild(ui.battle_menu[b]); - } else { + if (!ui.present.has(b)) { if (cell.contains(ui.battle_menu[b])) cell.removeChild(ui.battle_menu[b]); } -- cgit v1.2.3