summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-12-16 03:38:40 +0100
committerTor Andersson <tor@ccxvii.net>2024-01-08 16:36:48 +0100
commit511f63e26b2d150396d917bef2cfbfc32593e81c (patch)
tree7775c2bd1c4a95bbe891f3020d83e76fe91bd72e
parentbcac31232a4c4c44d2eec5fcbe514d06f364a681 (diff)
downloadtable-battles-511f63e26b2d150396d917bef2cfbfc32593e81c.tar.gz
fix counterattack order
-rw-r--r--rules.js43
-rw-r--r--tools/gendata.js14
2 files changed, 44 insertions, 13 deletions
diff --git a/rules.js b/rules.js
index 2316da4..bd4138e 100644
--- a/rules.js
+++ b/rules.js
@@ -2419,21 +2419,32 @@ function current_action() {
function find_target_of_attack(c, a) {
let in_res = card_has_rule(c, "attack_reserve")
- for (let c of a.target_list) {
- if (set_has(game.front[0], c))
- return c
- if (set_has(game.front[1], c))
- return c
+ for (let t of a.target_list) {
+ if (set_has(game.front[0], t))
+ return t
+ if (set_has(game.front[1], t))
+ return t
if (in_res) {
- if (set_has(game.reserve[0], c))
- return c
- if (set_has(game.reserve[1], c))
- return c
+ if (set_has(game.reserve[0], t))
+ return t
+ if (set_has(game.reserve[1], t))
+ return t
}
}
return -1
}
+function find_target_of_counterattack(a) {
+ // Note: only used for no-choice counterattacks
+ for (let t of a.target_list) {
+ if (set_has(game.front[0], t))
+ return t
+ if (set_has(game.front[1], t))
+ return t
+ }
+ return -1
+}
+
function find_first_target_of_command(c, a) {
if (game.scenario === S37_INKERMAN) {
@@ -2998,20 +3009,30 @@ function can_take_reaction(c, a, wild) {
switch (a.type) {
default:
throw new Error("invalid reaction: " + a.type)
+
case "Screen":
// if a friendly formation is attacked by a listed enemy formation
// ... or a listed formation is attacked (Wheatfield Road Artillery, etc)
if (!a.target_list.includes(game.selected) && !a.target_list.includes(game.target))
return false
break
+
case "Counterattack":
// if this formation is attacked
if (game.target !== c)
return false
// ... by one of the listed targets
- if (!a.target_list.includes(game.selected))
- return false
+ if (a.choice) {
+ // if "any" or "or" choice
+ if (!a.target_list.includes(game.selected))
+ return false
+ } else {
+ // if strict order
+ if (find_target_of_counterattack(a) !== game.selected)
+ return false
+ }
break
+
case "Absorb":
// if attack target is listed on absorb action
if (!a.target_list.includes(game.target))
diff --git a/tools/gendata.js b/tools/gendata.js
index ff38695..b2405ec 100644
--- a/tools/gendata.js
+++ b/tools/gendata.js
@@ -327,6 +327,7 @@ function process_card(c, ix) {
for (let a of c.actions) {
if (a.target) {
let tname = a.target.replace(" out of reserve", "")
+
if (tname === "Any enemy attack" || tname === "Any enemy formation" || tname === "Any enemy attacking it")
a.target_list = find_enemy_cards(c.scenario, c.wing)
else if (tname === "Any friendly formation")
@@ -356,12 +357,21 @@ function process_card(c, ix) {
else
a.target_list = tname.split(/, | OR | or | and /).map(name => find_card(c.scenario, name))
- // Hothenfriedberg invisible charles last target in list!
+ // Hohenfriedberg invisible charles last target in list!
if (c.number === "267A" || c.number === "268A" || c.number === "269A")
a.target_list.push(find_card(c.scenario, "Charles"))
}
- if (a.type === "Absorb")
+
+ if (a.type === "Counterattack") {
+ if (/, /.test(a.target))
+ a.choice = 0
+ else
+ a.choice = 1
+ }
+
+ if (a.type === "Absorb") {
a.target_list = a.target_list.filter(x => x !== ix) // never absorb for self
+ }
}
if (c.rules) {
for (let key in c.rules) {