diff options
author | Tor Andersson <tor@ccxvii.net> | 2021-06-22 14:01:09 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2022-11-16 19:19:38 +0100 |
commit | 26220db4d462922e8ab90a91332f43ba63cf695e (patch) | |
tree | 0c644dac01b2990ebd8da90ca2d0fdde6e28dbc4 | |
parent | e7f7b3ca0017a9cd12078d4c842685f5e60f8e84 (diff) | |
download | crusader-rex-26220db4d462922e8ab90a91332f43ba63cf695e.tar.gz |
crusader: Show/hide blocks in battle properly.
-rw-r--r-- | SIEGE | 254 | ||||
-rw-r--r-- | play.html | 3 | ||||
-rw-r--r-- | rules.js | 7 | ||||
-rw-r--r-- | ui.js | 38 |
4 files changed, 279 insertions, 23 deletions
@@ -0,0 +1,254 @@ +== SIEGE AND BATTLE PROCEDURE == + +* COMBAT DEPLOYMENT + +if not siege then + defender may withdraw into castle. + if field is empty and no reserves in queue then + attacker may regroup. + goto combat round 1. + end +end + +* COMBAT ROUND 1 TO 3 + +if round 2 then + primary reserves arrive. +end + +if round 3 then + secondary reserves arrive. +end + +if besieged reserves arrive then + withdraw all storming units to field. + besieging is defender. + besieged is attacker. +end + +if field is contested then + besieged may sally into field. + battle with all units in field. + if victorious then + victor may regroup. + if not siege then + end battle. + end + end + +else if currently storming or attacker declares storming then + besieging is attacker + besieged is defender + besieging may add blocks to storm. + battle with all units in castle. + if besieging is victorious then + besieging may regroup. + end battle. + end + +else if defender declares sallying then + besieging is defender. + besieged is attacker. + battle with all units in field. + if victorious then + victor may regroup. + if not siege then + end battle. + end + end + +else if no reserves in queue then + goto siege attrition. +end + +if round 1 or round 2 then + goto next combat round. +else + goto after battle retreat. +end + +* AFTER BATTLE RETREAT + +withdraw all sallying units to castle. +withdraw all storming units to field. + +if field is contested then + attacker must retreat + defender may regroup +end + +if siege then + goto siege attrition. +else + end battle. +end + +* SIEGE ATTRITION + +roll and apply attrition. +if castle falls then + besieging may regroup +end + +end battle. + +== BATTLE UI SCREENS == + +area: "Reserves" +area: "Field" +area: "Withdraw Castle" -- defender +area: "Storming Castle" -- attacker + -> "Castle" + +* Combat Deployment + defender main force can choose to 'withdraw' +* Declare Storming + besieging main force can choose to 'storm' +* Declare Sally + besieged in castle can choose to 'sally' +* Battle round in castle + show field as reserves + +With big screen: + + enemy reserves + enemy castle (optional) + enemy field + my field + my castle (optional) + my reserves + + +============= + +1) New fight! + +Defender deploys (main forces only) in castle and/or field. -- see example on page 5 + +// -- ERROR: reserve blocks moving into same area? -- +// If all withdraw and no reinforcements are coming, attacker may regroup. +// Regroup into other existing siege -- arrive as reinforcements. +// If any attacker blocks stay, goto existing siege. + +If any defenders stay, goto field battle. +Else goto siege. + +2) Field battle! + +Defender may withdraw into castle as combat action. + +If defender is eliminated and there are blocks in the castle, goto existing siege. + +Else regroup. + +3) Existing siege! + +Attacker declares storm? + goto storm round + +Defender declares sally? + goto sally round + +--- + +Combat Deployment + Defender may withdraw into castle if new battle. + +Combat Round 1 + If field has units + -> defender declare sally (if possible) + -> battle round in field. + Else attacker declare storm? + -> battle round in castle + Else defender declare sally? + -> besieged becomes attacker + -> battle round in field + Else if no reinforcements on the way + -> skip to siege attrition + +Combat Round 2 + Reserves arrive. + Besieged becomes attacker if relief forces arrive. + If field is empty + -> attacker may regroup some blocks (see 6.7 regroups note) + Else if field has units + -> defender declare sally (if possible) + -> battle round in field. + Else if storm ongoing? + -> attacker declare more storming units + -> battle round in castle + Else attacker declare storm? + -> battle round in castle + Else defender declare sally? + -> besieged becomes attacker + -> battle round in field + Else if no reinforcements on the way + -> skip to siege attrition + Same as Round 1. + +Combat Round 3 + Same as Round 2. + +>>> Battle round in field + if field is empty + if attacker is in field + attacker may regroup + if attacker is besieging and leaves some + proceed to next combat round + else + end combat + end + else + defender may regroup + end combat + end + end + +Retreat Round + All sallying withdraw. + All storming withdraw. + If field units: + Attacker/besieging must retreat + +Siege Attrition + Roll for attrition. + If defender is eliminated, attacker may regroup. + +--- + +6.56 timing + + new siege: + 2 frank in town + 3 saracen attack main road + 1 saracen attack secondary road + 2 frank reinforce main + 1 frank reinforce secondary + + + round 1: 2 frank vs 3 saracen + round 2: 2+2 frank vs 3+1 saracen + round 3: 2+2+1 frank vs 3+1 saracen + + old siege: + 2 p1 in castle + 2 p2 in field + 1 p1 attack main road (relief) + 1 p1 attack second road + 1 p2 reinforce main road + 1 p2 reinforce second road + + round 1: 2+1 p1 vs 2 p2 + round 2: 2+1 p1 vs 2+1 p2 + round 3: 2+1+1 p1 vs 2+1+1 p2 + + old siege #2: + 2 p1 in field + 2 p2 in castle + p1 pass + 1 p2 reinforce main road (relief) + 1 p2 reinforce second road + + round 1: 2 p1 vs 2 p2 -or- 2 p1 vs 2+1 p2? + -- I believe the rules clarification missed this case -- + @@ -237,8 +237,9 @@ body.shift .block.known:hover { #FA, #FB, #FC, #FD, #FR, #EA, #EB, #EC, #ER { margin: 0px; padding: 5px; } .battle .battle_menu { margin: 10px 5px; } -#FC { min-height: 110px; } +#FC { min-height: 120px; } #EC { min-height: 80px; } +#FF, #EF { min-height: 120px; } #FC, #EC { background-color: gray; margin-left: auto; @@ -2148,6 +2148,9 @@ function resume_field_battle() { return goto_regroup(); } + if (!is_contested_battle_field()) + return next_combat_round(); + game.state = 'field_battle'; pump_battle_step(is_field_attacker, is_field_defender); } @@ -2643,6 +2646,8 @@ function make_battle_view() { sallying: game.sallying, halfhit: game.halfhit, flash: game.flash, + round: game.combat_round, + show_castle: game.storming.length > 0 && game.state != 'declare_storm', }; battle.title = game.attacker[game.where] + " attack " + game.where; @@ -2653,7 +2658,7 @@ function make_battle_view() { function fill_cell(cell, owner, fn) { 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.push(b) // cell.sort((a,b) => compare_block_initiative(a[0], b[0])); } @@ -615,12 +615,12 @@ function update_cards() { } function update_battle() { - function fill_cell(name, list, reserve) { + function fill_cell(name, list, show) { let cell = document.getElementById(name); ui.present.clear(); - for (let [block, steps, moved] of list) { + for (let block of list) { ui.present.add(block); // TODO: insert in correct order! @@ -665,24 +665,20 @@ function update_battle() { if (game.actions && game.actions.battle_treachery && game.actions.battle_treachery.includes(block)) ui.battle_menu[block].classList.add('treachery'); - update_steps(block, steps, ui.battle_block[block], false); + update_steps(block, game.steps[block], ui.battle_block[block], false); if (block == game.battle.halfhit) ui.battle_block[block].classList.add("halfhit"); else ui.battle_block[block].classList.remove("halfhit"); - if (reserve) - ui.battle_block[block].classList.add("secret"); + if (show) + ui.battle_block[block].classList.add("known"); else - ui.battle_block[block].classList.remove("secret"); - if (moved) + ui.battle_block[block].classList.remove("known"); + if (game.moved[block]) ui.battle_block[block].classList.add("moved"); else ui.battle_block[block].classList.remove("moved"); - if (reserve) - ui.battle_block[block].classList.remove("known"); - else - ui.battle_block[block].classList.add("known"); } for (let b in BLOCKS) { @@ -695,19 +691,19 @@ function update_battle() { if (player == FRANKS) { fill_cell("FR", game.battle.FR, true); - fill_cell("FC", game.battle.FC, false); - fill_cell("FF", game.battle.FF, false); - fill_cell("EF", game.battle.SF, false); - fill_cell("EC", game.battle.SC, false); - fill_cell("ER", game.battle.SR, true); + fill_cell("FC", game.battle.FC, true); + fill_cell("FF", game.battle.FF, true); + fill_cell("EF", game.battle.SF, game.battle.round > 0); + fill_cell("EC", game.battle.SC, game.battle.show_castle); + fill_cell("ER", game.battle.SR, false); document.getElementById("FC").className = "c" + game.battle.FCS; document.getElementById("EC").className = "c" + game.battle.SCS; } else { - fill_cell("ER", game.battle.FR, true); - fill_cell("EC", game.battle.FC, false); - fill_cell("EF", game.battle.FF, false); - fill_cell("FF", game.battle.SF, false); - fill_cell("FC", game.battle.SC, false); + fill_cell("ER", game.battle.FR, false); + fill_cell("EC", game.battle.FC, game.battle.show_castle); + fill_cell("EF", game.battle.FF, game.battle.round > 0); + fill_cell("FF", game.battle.SF, true); + fill_cell("FC", game.battle.SC, true); fill_cell("FR", game.battle.SR, true); document.getElementById("EC").className = "c" + game.battle.FCS; document.getElementById("FC").className = "c" + game.battle.SCS; |