summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data.js1
-rw-r--r--rules.js149
2 files changed, 109 insertions, 41 deletions
diff --git a/data.js b/data.js
index 0638ebe..95a9a70 100644
--- a/data.js
+++ b/data.js
@@ -18644,4 +18644,3 @@ cards: [
],
}
if (typeof module!=='undefined') module.exports = data
-
diff --git a/rules.js b/rules.js
index 49ad7ba..91d0a4e 100644
--- a/rules.js
+++ b/rules.js
@@ -51,6 +51,7 @@ function find_card(s, n) {
}
// for (let c of data.cards) for (let a of c.actions) console.log(a.type, a.effect)
+// for (let c of data.cards) console.log(c.dice)
const P1 = "First"
const P2 = "Second"
@@ -230,6 +231,10 @@ const S15_WENLOCK = find_card(15, "Wenlock")
const S16_STOKE_FIELD = find_scenario(16)
+const S22_GABIENE = find_scenario(22)
+const S22_EUMENES_CAMP = find_card(22, "Eumenes's Camp")
+const S22_SILVER_SHIELDS = find_card(22, "The Silver Shields")
+
// === SETUP ===
exports.setup = function (seed, scenario, options) {
@@ -1237,7 +1242,7 @@ function is_mandatory_reaction(c, a) {
function can_take_action(c, a) {
if (a.type === "Attack") {
- if (find_target_of_attack(a) < 0)
+ if (find_target_of_attack(c, a) < 0)
return false
}
@@ -1386,7 +1391,7 @@ function goto_take_action(c, ix) {
if (card_has_rule(game.selected, "attack_choose_target"))
goto_attack_choose_target()
else
- goto_attack(find_target_of_attack(a))
+ goto_attack(find_target_of_attack(c, a))
break
case "Bombard":
game.state = "bombard"
@@ -1401,12 +1406,19 @@ function current_action() {
return data.cards[game.selected].actions[game.action]
}
-function find_target_of_attack(a) {
+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
+ if (in_res) {
+ if (set_has(game.reserve[0], c))
+ return c
+ if (set_has(game.reserve[1], c))
+ return c
+ }
}
return -1
}
@@ -1529,6 +1541,14 @@ function goto_attack(target) {
}
}
+ if (game.scenario === S22_GABIENE) {
+ if (game.target === S22_SILVER_SHIELDS) {
+ if (is_card_in_play(S22_EUMENES_CAMP)) {
+ game.hits = Math.min(1, game.hits - 1)
+ }
+ }
+ }
+
if (card_has_rule(game.target, "suffer_1_less_1_max"))
game.hits = Math.max(0, Math.min(1, game.hits - 1))
if (card_has_rule(game.target, "suffer_1_less"))
@@ -1945,17 +1965,21 @@ function get_attack_hits(c, a) {
case "1 hit. Warwick Retires upon completing this Attack Action.":
case "1 hit. You CHOOSE the target.":
case "1 hit. 1 self per action.":
+ case "1 hit per action. 1 self per action.":
return 1
case "1 hit per die.":
case "1 hit per die. 1 self per action.":
case "1 hit per die. Ignore first target until it comes out of Reserve.":
case "1 hit per die (but see below). 1 self per action.":
+ case "1 hit per die (plus dice from E. Phalanx).":
return count_dice_on_card(c)
case "1 hit per pair.":
case "1 hit per pair. 1 self per action.":
return count_dice_on_card(c) >> 1
case "1 hit, PLUS 1 hit per die. 1 self per action.":
return 1 + count_dice_on_card(c)
+ case "5 hits.":
+ return 5
}
}
@@ -1968,9 +1992,12 @@ function get_attack_self(c, a) {
case "1 hit. You CHOOSE the target.":
case "1 hit per die.":
case "1 hit per die. Ignore first target until it comes out of Reserve.":
+ case "1 hit per die (plus dice from E. Phalanx).":
case "1 hit per pair.":
+ case "5 hits.":
return 0
case "1 hit. 1 self per action.":
+ case "1 hit per action. 1 self per action.":
case "1 hit per die. 1 self per action.":
case "1 hit per die (but see below). 1 self per action.":
case "1 hit per pair. 1 self per action.":
@@ -1981,6 +2008,37 @@ function get_attack_self(c, a) {
// === ROUTING ===
+function find_card_owner(c) {
+ if (set_has(game.front[0], c) || set_has(game.reserve[0], c))
+ return 0
+ if (set_has(game.front[1], c) || set_has(game.reserve[1], c))
+ return 1
+ throw new Error("card not found in any player area")
+}
+
+function should_rout_card(c) {
+ if (!data.cards[c].special) {
+ if (map_get(game.sticks, c, 0) === 0)
+ return true
+
+ let rout_with = card_has_rule(c, "rout_with")
+ if (rout_with) {
+ for (let other of rout_with)
+ if (is_card_in_play(other))
+ return false
+ return true
+ }
+ }
+ return false
+}
+
+function should_pursue(c) {
+ let pursuit = data.cards[c].pursuit
+ if (pursuit !== undefined)
+ return !set_has(game.front[0], pursuit) && !set_has(game.front[1], pursuit)
+ return false
+}
+
function should_remove_card(c) {
let remove_with = card_has_rule(c, "remove_with")
if (remove_with) {
@@ -2003,22 +2061,6 @@ function should_retire_card(c) {
return false
}
-function should_rout_card(c) {
- if (!data.cards[c].special) {
- if (map_get(game.sticks, c, 0) === 0)
- return true
-
- let rout_with = card_has_rule(c, "rout_with")
- if (rout_with) {
- for (let other of rout_with)
- if (is_card_in_play(other))
- return false
- return true
- }
- }
- return false
-}
-
function goto_routing() {
game.routed = [ 0, 0 ]
@@ -2045,10 +2087,10 @@ function resume_routing() {
game.state = "routing"
for (let p = 0; p <= 1; ++p) {
for (let c of game.front[p])
- if (should_rout_card(c) || should_remove_card(c) || should_retire_card(c))
+ if (should_rout_card(c))
return
for (let c of game.reserve[p])
- if (should_rout_card(c) || should_remove_card(c) || should_retire_card(c))
+ if (should_rout_card(c))
return
}
end_routing()
@@ -2105,23 +2147,15 @@ function end_routing() {
goto_pursuit()
}
-function find_card_owner(c) {
- if (set_has(game.front[0], c) || set_has(game.reserve[0], c))
- return 0
- if (set_has(game.front[1], c) || set_has(game.reserve[1], c))
- return 1
- throw new Error("card not found in any player area")
-}
-
states.routing = {
prompt() {
- view.prompt = "Rout and remove cards."
+ view.prompt = "Rout cards!"
for (let p = 0; p <= 1; ++p) {
for (let c of game.front[p])
- if (should_rout_card(c) || should_remove_card(c) || should_retire_card(c))
+ if (should_rout_card(c))
gen_action_card(c)
for (let c of game.reserve[p])
- if (should_rout_card(c) || should_remove_card(c) || should_retire_card(c))
+ if (should_rout_card(c))
gen_action_card(c)
}
},
@@ -2142,13 +2176,6 @@ states.routing = {
// === PURSUIT ===
-function should_pursue(c) {
- let pursuit = data.cards[c].pursuit
- if (pursuit !== undefined)
- return !set_has(game.front[0], pursuit) && !set_has(game.front[1], pursuit)
- return false
-}
-
function goto_pursuit() {
resume_pursuit()
}
@@ -2163,7 +2190,7 @@ function resume_pursuit() {
}
function end_pursuit() {
- goto_reserve()
+ goto_removing()
}
states.pursuit = {
@@ -2181,6 +2208,48 @@ states.pursuit = {
},
}
+// === REMOVING ===
+
+function goto_removing() {
+ resume_removing()
+}
+
+function resume_removing() {
+ game.state = "removing"
+ for (let p = 0; p <= 1; ++p) {
+ for (let c of game.front[p])
+ if (should_remove_card(c) || should_retire_card(c))
+ return
+ for (let c of game.reserve[p])
+ if (should_remove_card(c) || should_retire_card(c))
+ return
+ }
+ end_removing()
+}
+
+function end_removing() {
+ goto_reserve()
+}
+
+states.removing = {
+ prompt() {
+ view.prompt = "Remove cards!"
+ for (let p = 0; p <= 1; ++p) {
+ for (let c of game.front[p])
+ if (should_remove_card(c) || should_retire_card(c))
+ gen_action_card(c)
+ for (let c of game.reserve[p])
+ if (should_remove_card(c) || should_retire_card(c))
+ gen_action_card(c)
+ }
+ },
+ card(c) {
+ log(card_name(c) + " removed.")
+ eliminate_card(c)
+ resume_removing()
+ },
+}
+
// === RESERVE ===
function should_enter_reserve(c) {