summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.js41
-rw-r--r--rules.js91
2 files changed, 88 insertions, 44 deletions
diff --git a/play.js b/play.js
index 4e560aa..b87f53f 100644
--- a/play.js
+++ b/play.js
@@ -677,27 +677,20 @@ function on_blur_piece() {
/* UPDATE UI */
-function layout_general_offset(g, s) {
- // if not selected: number of unselected generals below us
- // if not selected: (number of unselected generals + 1) + number of selected generals below us
- if (!set_has(view.selected, g)) {
- let n = 0
- for (let i = g+1; i < 20; ++i)
- if (view.pos[i] === s && !set_has(view.selected, i))
- ++n
- return n
- } else {
- let n = 0
- for (let i = 0; i < 20; ++i)
- if (view.pos[i] === s && !set_has(view.selected, i))
- ++n
- if (n > 0)
- ++n
- for (let i = g+1; i < 20; ++i)
- if (view.pos[i] === s && set_has(view.selected, i))
- ++n
- return n
- }
+function layout_general_offset(who, here) {
+ let other = -1
+ for (let p = 0; p < 20; ++p)
+ if (view.pos[p] === here && who !== p)
+ other = p
+ if (other < 0)
+ return 0
+ if ((view.supreme & (1 << who)) || view.selected === who)
+ return 1
+ if ((view.supreme & (1 << other)) || view.selected === other)
+ return 0
+ if (who < other)
+ return 1
+ return 0
}
function layout_general_offset_elim(g) {
@@ -1026,10 +1019,8 @@ function on_update() {
for (let v = 16; v >= 0; --v)
action_button_with_argument("value", v, v)
- for (let p = 0; p < 20; ++p) {
- action_button_with_argument("promote", p, "Promote " + piece_abbr[p])
- action_button_with_argument("demote", p, "Demote " + piece_abbr[p])
- }
+ for (let p = 0; p < 20; ++p)
+ action_button_with_argument("supreme", p, power_name[piece_power[p]])
action_button("force_march", "Force march")
diff --git a/rules.js b/rules.js
index 390494b..f4491a5 100644
--- a/rules.js
+++ b/rules.js
@@ -5,7 +5,6 @@
/* TODO
victory check
-supreme commander in mixed stacks
supply phase
hussar payment
re-entering supply trains during movement (10.2)
@@ -188,6 +187,15 @@ const piece_power = [
P_AUSTRIA, P_AUSTRIA
]
+const piece_rank = [
+ 1, 2, 3, 4, 5,
+ 1,
+ 1, 2, 3, 4,
+ 1,
+ 1, 2, 3,
+ 1, 2, 3, 4, 5, 6,
+]
+
const piece_name = [
"Moritz",
"Belle-Isle",
@@ -219,6 +227,7 @@ const piece_name = [
]
const all_pieces = [ ...all_power_generals.flat(), ...all_power_trains.flat() ]
+const all_trains = [ ...all_power_trains.flat() ]
const all_generals = [ ...all_power_generals.flat() ]
const all_france_bavaria_generals = [
@@ -634,16 +643,18 @@ function current_player() {
}
function get_top_piece(s) {
- for (let p of all_pieces)
+ for (let p of all_trains)
if (game.pos[p] === s)
return p
- return -1
+ return get_supreme_commander(s)
}
function get_supreme_commander(s) {
- // TODO: promoted minor power (check who is actually on top!)
for (let p of all_generals)
- if (game.pos[p] === s)
+ if ((game.supreme & (1<<p)) && game.pos[p] === s)
+ return p
+ for (let p of all_generals)
+ if (!(game.supreme & (1<<p)) && game.pos[p] === s)
return p
return -1
}
@@ -768,7 +779,10 @@ function count_generals(to) {
function select_stack(s) {
let list = []
for (let p of all_generals)
- if (game.pos[p] === s)
+ if ((game.supreme & (1<<p)) && game.pos[p] === s)
+ list.push(p)
+ for (let p of all_generals)
+ if (!(game.supreme & (1<<p)) && game.pos[p] === s)
list.push(p)
return list
}
@@ -787,6 +801,7 @@ function eliminate_general(p, indent) {
log(">P" + p + " eliminated")
else
log("P" + p + " eliminated.")
+ game.supreme &= ~(1 << p)
game.pos[p] = ELIMINATED
game.troops[p] = 0
set_in_supply(p)
@@ -1207,8 +1222,10 @@ states.movement = {
game.move_path = [ here ]
if (is_supply_train(p))
game.state = "move_supply_train"
- else
+ else {
+ game.supreme &= ~(1 << p)
game.state = "move_general"
+ }
},
confirm_end_movement() {
this.end_movement()
@@ -1224,7 +1241,6 @@ states.movement = {
log_conquest(game.move_conq)
delete game.move_conq
- // MARIA: recruit during winter goto_recruit()
goto_combat()
},
}
@@ -1545,14 +1561,7 @@ states.move_give = {
function end_move_piece() {
let here = game.pos[game.selected]
- // uniting stacks: flag all as moved
- if (is_general(game.selected)) {
- for (let p of all_coop_generals(game.power))
- if (game.pos[p] === here)
- set_add(game.moved, p)
- } else {
- set_add(game.moved, game.selected)
- }
+ set_add(game.moved, game.selected)
log_move_path()
@@ -1563,10 +1572,52 @@ function end_move_piece() {
}
delete game.move_path
- game.selected = -1
- game.state = "movement"
- set_active_to_current_action_step()
+ // uniting stacks: flag all as moved
+ let supreme = false
+ if (is_general(game.selected)) {
+ for (let p of all_coop_generals(game.power)) {
+ if (game.pos[p] === here && p !== game.selected) {
+ if (piece_rank[p] === piece_rank[game.selected])
+ supreme = true
+ set_add(game.moved, p)
+ }
+ }
+ }
+
+ if (supreme) {
+ game.state = "move_supreme"
+ } else {
+ game.selected = -1
+ game.state = "movement"
+ set_active_to_current_action_step()
+ }
+}
+
+states.move_supreme = {
+ inactive: "move",
+ prompt() {
+ prompt("Choose supreme commander for mixed stack.")
+ let here = game.pos[game.selected]
+ for (let p of all_coop_generals(game.power)) {
+ if (game.pos[p] === here) {
+ gen_action("supreme", p)
+ gen_action_piece(p)
+ }
+ }
+ },
+ supreme(p) {
+ let here = game.pos[game.selected]
+ for (let p of all_coop_generals(game.power))
+ if (game.pos[p] === here)
+ game.supreme &= ~(1<<p)
+ game.supreme |= (1<<p)
+ game.selected = -1
+ game.state = "movement"
+ },
+ piece(p) {
+ this.supreme(p)
+ },
}
/* RECRUITMENT */
@@ -2830,6 +2881,7 @@ exports.setup = function (seed, _scenario, _options) {
pos: setup_piece_position.slice(),
oos: 0,
+ supreme: 0,
troops: new Array(20).fill(0),
victory: [],
elector: [],
@@ -3015,6 +3067,7 @@ exports.view = function (state, player) {
turn: game.turn,
pos: game.pos,
oos: game.oos,
+ supreme: game.supreme,
victory: game.victory,
elector: game.elector,
troops: mask_troops(player),