summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-12-09 19:58:23 +0100
committerTor Andersson <tor@ccxvii.net>2024-01-08 16:36:47 +0100
commit3d4909f946f724562d354a55a721ded43a12c268 (patch)
tree7e6659790356e7c021c51f85b9537f85a8d54d23 /rules.js
parentc5f35f99aa9605a7baf43d6c407b126a51e878f8 (diff)
downloadtable-battles-3d4909f946f724562d354a55a721ded43a12c268.tar.gz
Towton and Edgecote Moor. take_from, rout_with, and remove_with.
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js77
1 files changed, 70 insertions, 7 deletions
diff --git a/rules.js b/rules.js
index 7862704..33b87d8 100644
--- a/rules.js
+++ b/rules.js
@@ -13,12 +13,12 @@ Special card rules implemented:
suffer_1_less_1_max
suffer_1_less
start_with_no_cubes
+ take_from
TODO:
- remove_with
rout_with
+ remove_with
wild
- take_from
attack_reserve
no_morale
@@ -210,6 +210,9 @@ const S3201_DH_HILL = find_card(3201, "D.H. Hill")
const S3201_AP_HILL = find_card(3201, "A.P. Hill")
const S3201_LONGSTREET = find_card(3201, "Longstreet")
+const S12_TOWTON = find_scenario(12)
+const S13_EDGECOTE_MOOR = find_scenario(13)
+
// === SETUP ===
exports.setup = function (seed, scenario, options) {
@@ -296,6 +299,13 @@ exports.setup = function (seed, scenario, options) {
// === GAME STATE ACCESSORS ===
+function count_total_cubes() {
+ let n = game.morale[0] + game.morale[1]
+ for (let i = 1; i < game.cubes.length; i += 2)
+ n += game.cubes[i]
+ return n
+}
+
function card_has_rule(c, name) {
let rules = data.cards[c].rules
if (rules)
@@ -359,6 +369,14 @@ function remove_dice(c) {
}
}
+function move_dice(from, to) {
+ for (let i = 0; i < 12; ++i) {
+ if (get_dice_location(i) === from) {
+ set_dice_location(i, to)
+ }
+ }
+}
+
function eliminate_card(c) {
remove_dice(c)
remove_cubes(c, 3)
@@ -647,10 +665,22 @@ function can_place_dice(c) {
}
// At cube limit?
- if (data.cards[c].special)
+ if (data.cards[c].special) {
+ // Max on card
if (map_get(game.cubes, c, 0) >= data.cards[c].special)
return false
+ // Max available
+ let n_cubes = count_total_cubes()
+ if (n_cubes >= 10)
+ return false
+
+ if (game.scenario === S12_TOWTON) {
+ if (n_cubes >= 8)
+ return false
+ }
+ }
+
// At per wing limit?
let wing = data.cards[c].wing
let n_wing = 0
@@ -1355,7 +1385,11 @@ states.bombard = {
function goto_attack() {
let a = current_action()
- // TODO: 88B German Infantry - take dice from Saxon Infantry
+ let take_from = card_has_rule(game.selected, "take_from")
+ if (take_from) {
+ for (let from of take_from)
+ move_dice(from, game.selected)
+ }
game.state = "attack"
game.target = find_target_of_attack(a)
@@ -1457,6 +1491,18 @@ states.command = {
}
}
+ if (game.scenario === S13_EDGECOTE_MOOR) {
+ // TODO: pay all 3 cubes? remove cards from play?
+ if (game.reserve[0].length === 0 && game.reserve[1].length > 0) {
+ log("Gained a second morale cube.")
+ game.morale[0] += 1
+ }
+ if (game.reserve[1].length === 0 && game.reserve[0].length > 0) {
+ log("Gained a second morale cube.")
+ game.morale[1] += 1
+ }
+ }
+
if (find_first_target_of_command(game.selected, current_action()) < 0) {
pay_for_action(game.selected)
end_action_phase()
@@ -1742,6 +1788,7 @@ function get_attack_hits(c, a) {
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.":
return count_dice_on_card(c)
case "1 hit per pair.":
case "1 hit per pair. 1 self per action.":
@@ -1762,6 +1809,7 @@ function get_attack_self(c, a) {
return 0
case "1 hit. 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.":
case "1 hit, PLUS 1 hit per die. 1 self per action.":
return 1
@@ -1771,15 +1819,30 @@ function get_attack_self(c, a) {
// === ROUTING ===
function should_remove_card(c) {
- // TODO: remove after X routs special rules
+ let remove_with = card_has_rule(c, "remove_with")
+ if (remove_with) {
+ for (let other of remove_with)
+ if (is_card_in_play(other))
+ return false
+ return true
+ }
+
return false
}
function should_rout_card(c) {
- // TODO: rout after X routs special rules
- if (!data.cards[c].special)
+ 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
}