summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-12-15 19:18:24 +0100
committerTor Andersson <tor@ccxvii.net>2024-01-08 16:36:48 +0100
commit049d7c8c00af98151f1b35d5481c9116d969f569 (patch)
tree3ffa6f53999b7d5ce4554c0b64bbe4b74547b85f
parent10a85af52ed7f94d65729d5c7a9a9473582cf328 (diff)
downloadtable-battles-049d7c8c00af98151f1b35d5481c9116d969f569.tar.gz
Fleurus.
-rw-r--r--cards.css4
-rw-r--r--play.html9
-rw-r--r--play.js11
-rw-r--r--rules.js101
4 files changed, 98 insertions, 27 deletions
diff --git a/cards.css b/cards.css
index b0b9221..16dde96 100644
--- a/cards.css
+++ b/cards.css
@@ -239,7 +239,7 @@
line-height: 12px;
bottom: 0px;
right: 0px;
- padding: 6px 8px;
+ padding: 7px 8px;
}
.extra {
@@ -249,7 +249,7 @@
line-height: 12px;
bottom: 0px;
left: 0px;
- padding: 6px 8px;
+ padding: 7px 8px;
}
/* SCENARIO CARD */
diff --git a/play.html b/play.html
index 4d105cb..225f3b3 100644
--- a/play.html
+++ b/play.html
@@ -125,12 +125,9 @@ main {
align-items: start;
}
-/* S37 Inkerman - The Fog */
-[data-card="225B"] .slot_sticks { display: none }
-
-/* S?? XXX - Retreat to Nivelles */
-[data-card="237A"] .slot_dice { height: 32px; }
-[data-card="237A"] .slot_sticks { height: 55px; }
+/* S38 Fleurus - Retreat to Nivelles */
+[data-card="237A"] .slot_cubes:empty { display: none }
+[data-card="237A"] .slot_cubes:not(:empty) ~ .slot_sticks { display: none }
.slot_sticks {
margin: 12px;
diff --git a/play.js b/play.js
index a35ec2e..edda080 100644
--- a/play.js
+++ b/play.js
@@ -133,10 +133,15 @@ function create_formation_slot(id, top) {
e.appendChild(ui.cards[id])
}
- if (card.special || card.name === "The Fog" || card.name === "Retreat to Nivelles")
+ if (card.name === "Retreat to Nivelles") {
ui.slot_cubes[id] = append_div(e, "slot_cubes")
- if (!card.special)
ui.slot_sticks[id] = append_div(e, "slot_sticks")
+ } else {
+ if (card.special)
+ ui.slot_cubes[id] = append_div(e, "slot_cubes")
+ else
+ ui.slot_sticks[id] = append_div(e, "slot_sticks")
+ }
if (!top) {
e.appendChild(ui.cards[id])
@@ -177,6 +182,8 @@ function create_formation_card(id) {
append_div(e, "strength", "IV")
else if (card.special === 5)
append_div(e, "strength", "V")
+ else if (card.special === -1)
+ append_div(e, "strength", "?")
else
append_div(e, "strength", card.strength)
diff --git a/rules.js b/rules.js
index b7d99b7..f8a2aae 100644
--- a/rules.js
+++ b/rules.js
@@ -144,9 +144,8 @@ function goto_game_over(result, victory) {
game.state = "game_over"
game.active = "None"
game.result = result
- game.victory = result + " victory! " + victory
+ game.victory = victory
log("")
- log(result + " victory!")
log(victory)
return true
}
@@ -264,6 +263,7 @@ const S35_MONTROSE = find_card(35, "Montrose")
const S35_GORDON = find_card(35, "Gordon")
const S38_FLEURUS = find_scenario(38)
+const S38_WALDECK = find_card(38, "Waldeck")
const S38_RETREAT_TO_NIVELLES = find_card(38, "Retreat to Nivelles")
const S38_LUXEMBOURGS_HORSE = find_card(38, "Luxembourg's Horse")
const S38_GOURNAYS_HORSE = find_card(38, "Gournay's Horse")
@@ -424,7 +424,10 @@ exports.setup = function (seed, scenario, options) {
log("")
if (info.players[0].tactical > 0 || info.players[1].tactical > 0) {
- log("Tactical Victory:")
+ if (game.scenario === S38_FLEURUS)
+ log("Tactical Draw:")
+ else
+ log("Tactical Victory:")
if (info.players[0].tactical > 0)
log(">" + player_name(0) + ": " + info.players[0].tactical)
if (info.players[1].tactical > 0)
@@ -448,6 +451,10 @@ exports.setup = function (seed, scenario, options) {
map_set(game.cubes, S37_THE_FOG, 3)
}
+ if (game.scenario === S38_FLEURUS) {
+ map_set(game.cubes, S38_RETREAT_TO_NIVELLES, 3)
+ }
+
goto_start_turn()
return game
@@ -527,7 +534,7 @@ function set_sticks(c, n) {
}
function move_sticks(from, to, n) {
- log("moved N sticks")
+ log(`Moved ${n} sticks from C${from} to C${to}.`) // TODO?
set_sticks(from, get_sticks(from) - n)
set_sticks(to, get_sticks(to) + n)
}
@@ -770,6 +777,11 @@ function check_impossible_to_attack_victory() {
function get_tactical_victory_points(p) {
let n = game.lost[1-p]
+ if (game.scenario === S38_FLEURUS) {
+ if (p === 1)
+ n += get_sticks(S38_RETREAT_TO_NIVELLES)
+ }
+
if (game.scenario === S46_ROCOUX) {
if (p === 0)
n += get_sticks(S46_AUSTRIANS)
@@ -800,22 +812,27 @@ function check_victory() {
if (game.scenario === S49_LEUTHEN) {
if (is_removed_from_play(S49_NADASDY) && is_card_in_reserve(S49_COLLOREDO))
- return goto_game_over(P1, "Nadasdy routed before Colloredo entered play.")
+ return goto_game_over(P1, "Nadasdy routed before Colloredo entered play!")
}
if (game.morale[0] === 0)
- return goto_game_over(P2, player_name(0) + " has run out of morale!")
+ return goto_game_over(P2, player_name(0) + " ran out of morale!")
if (game.morale[1] === 0)
- return goto_game_over(P1, player_name(1) + " has run out of morale!")
+ return goto_game_over(P1, player_name(1) + " ran out of morale!")
let tv0 = get_tactical_victory_points(0)
let tv1 = get_tactical_victory_points(1)
+ if (game.scenario === S38_FLEURUS) {
+ if (tv1 >= 22)
+ return goto_game_over("Draw", player_name(1) + " secured a draw!")
+ }
+
if (info.players[0].tactical > 0 && tv0 >= info.players[0].tactical)
- return goto_game_over(P1, player_name(0) + " tactical victory!")
+ return goto_game_over(P1, player_name(0) + " won a tactical victory!")
if (info.players[1].tactical > 0 && tv1 >= info.players[1].tactical)
- return goto_game_over(P2, player_name(1) + " tactical victory!")
+ return goto_game_over(P2, player_name(1) + " won a tactical victory!")
return false
}
@@ -2012,7 +2029,7 @@ function goto_start_turn() {
if (is_infantry(c) || is_cavalry(c))
have_inf_or_cav = true
if (!have_inf_or_cav)
- return goto_game_over(P1, "Frederick has no Infantry or Cavalry in play!")
+ return goto_game_over(P1, "Frederick had no Infantry or Cavalry in play!")
}
}
@@ -2117,7 +2134,6 @@ states.action = {
},
retire(c) {
push_undo()
- retire_card(c)
if (game.scenario === S38_FLEURUS) {
if (c === S38_LUXEMBOURGS_HORSE) {
@@ -2126,6 +2142,7 @@ states.action = {
}
}
+ retire_card(c)
end_action_phase()
},
a1(c) {
@@ -2390,6 +2407,11 @@ function find_first_target_of_command(c, a) {
return S37_THE_FOG
}
+ if (game.scenario === S38_FLEURUS) {
+ if (c === S38_WALDECK)
+ return S38_RETREAT_TO_NIVELLES
+ }
+
if (game.scenario === S44_HOHENFRIEDBERG) {
if (c === S44_CHARLES) {
if (game.reserve[1].length > 0)
@@ -2782,6 +2804,18 @@ function goto_command() {
return
}
+ if (game.scenario === S38_FLEURUS && game.selected === S38_WALDECK) {
+ remove_cubes(S38_RETREAT_TO_NIVELLES, 3)
+ remove_dice(game.selected)
+ if (1 || !has_any_cubes_on_card(S38_RETREAT_TO_NIVELLES)) {
+ game.selected = S38_RETREAT_TO_NIVELLES
+ game.state = "s38_retreat_to_nivelles_1"
+ return
+ }
+ end_action_phase()
+ return
+ }
+
game.state = "command"
}
@@ -2842,6 +2876,35 @@ states.command = {
},
}
+states.s38_retreat_to_nivelles_1 = {
+ prompt() {
+ view.prompt = "Retreat to Nivelles: Remove all in-play Grand Alliance cards!"
+ for (let c of game.front[1])
+ if (c !== S38_RETREAT_TO_NIVELLES)
+ gen_action_card(c)
+ },
+ card(c) {
+ move_all_sticks(c, S38_RETREAT_TO_NIVELLES)
+ remove_card(c)
+ if (game.front[1].length === 1)
+ game.state = "s38_retreat_to_nivelles_2"
+ },
+}
+
+states.s38_retreat_to_nivelles_2 = {
+ prompt() {
+ view.prompt = "Retreat to Nivelles: Bring van Aylva & van Weibnom out of reserve."
+ for (let c of game.reserve[1])
+ gen_action_card(c)
+ },
+ card(c) {
+ bring_out_of_reserve(c)
+ if (game.reserve[1].length === 0)
+ end_action_phase()
+ },
+}
+
+
// === REACTION ===
function can_opponent_react() {
@@ -3470,12 +3533,12 @@ function end_routing() {
if (game.routed[0]) {
game.morale[0] -= Math.min(game.routed[0], game.morale[0])
if (game.morale[0] === 0)
- return goto_game_over(P2, player_name(0) + " has run out of morale!")
+ return goto_game_over(P2, player_name(0) + " ran out of morale!")
}
if (game.routed[1]) {
game.morale[1] -= Math.min(game.routed[1], game.morale[1])
if (game.morale[1] === 0)
- return goto_game_over(P1, player_name(1) + " has run out of morale!")
+ return goto_game_over(P1, player_name(1) + " ran out of morale!")
}
}
@@ -3529,6 +3592,13 @@ function end_reserve() {
goto_roll_phase()
}
+function bring_out_of_reserve(c) {
+ log(card_name(c) + " came out of reserve.")
+ let p = find_card_owner(c)
+ set_delete(game.reserve[p], c)
+ set_add(game.front[p], c)
+}
+
states.reserve = {
prompt() {
view.prompt = "Enter reserves!"
@@ -3538,10 +3608,7 @@ states.reserve = {
gen_action_card(c)
},
card(c) {
- log(card_name(c) + " came out of reserve.")
- let p = find_card_owner(c)
- set_delete(game.reserve[p], c)
- set_add(game.front[p], c)
+ bring_out_of_reserve(c)
resume_reserve()
},
}