summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.html30
-rw-r--r--play.js60
-rw-r--r--rules.js170
3 files changed, 201 insertions, 59 deletions
diff --git a/play.html b/play.html
index 350979e..e5ccf97 100644
--- a/play.html
+++ b/play.html
@@ -14,6 +14,16 @@
</head>
<style>
+#log { background-color: whitesmoke; }
+#log .h1 { font-weight: bold; padding-top:2px; padding-bottom:2px; margin: 8px 0; text-align: center; }
+#log .h2 { padding-top:1px; padding-bottom:1px; text-align: center; }
+#log .h1 { border-bottom: 1px solid #444; border-top: 1px solid #444; }
+#log .h2 { border-bottom: 1px solid #444; border-top: 1px solid #444; }
+#log .h1 { background-color: silver; }
+#log .h2 { background-color: gainsboro; }
+#log div { padding-left: 20px; text-indent: -12px; }
+#log div.i { padding-left: 32px; text-indent: -12px; }
+
main {
background-color: dimgray;
}
@@ -202,6 +212,26 @@ main {
.small.flip.y5 { background-position: -34px -136px }
.small.flip.y6 { background-position: -34px -170px }
+#log .dice {
+ display: inline-block;
+ vertical-align: -2px;
+ width: 12px;
+ height: 12px;
+ background-size: 600% 100%;
+ background-repeat: no-repeat;
+ background-image: url(die_black_pips.svg);
+ background-color: #fff;
+ border: 1px solid #444;
+}
+
+.d0 { background-position: -100% 0 }
+.d1 { background-position: 0% 0; }
+.d2 { background-position: 20% 0; }
+.d3 { background-position: 40% 0; }
+.d4 { background-position: 60% 0; }
+.d5 { background-position: 80% 0; }
+.d6 { background-position: 100% 0; }
+
</style>
<body>
diff --git a/play.js b/play.js
index a661ae1..70e5476 100644
--- a/play.js
+++ b/play.js
@@ -347,5 +347,65 @@ function on_update() {
action_button("undo", "Undo")
}
+const DICE = {
+ D0: '0',
+ D1: '1',
+ D2: '2',
+ D3: '3',
+ D4: '4',
+ D5: '5',
+ D6: '6',
+}
+
+function sub_dice(match) {
+ return DICE[match]
+}
+
+function sub_hex(match, p1) {
+ let x = p1 | 0
+ let n = data.map.names[x]
+ if (n)
+ return x + " (" + n + ")"
+ return x
+}
+
+function sub_piece(match, p1) {
+ let x = p1 | 0
+ return data.pieces[x].name
+}
+
+function on_log(text) {
+ let p = document.createElement("div")
+
+ if (text.match(/^>/)) {
+ text = text.substring(1)
+ p.className = 'i'
+ }
+
+ text = text.replace(/&/g, "&amp;")
+ text = text.replace(/</g, "&lt;")
+ text = text.replace(/>/g, "&gt;")
+
+ text = text.replace(/\b(\d\d\d\d)\b/g, sub_hex)
+ text = text.replace(/P(\d+)/g, sub_piece)
+ text = text.replace(/\bD\d\b/g, sub_dice)
+
+ if (text.match(/^\.h1 /)) {
+ text = text.substring(4)
+ p.className = "h1"
+ }
+ else if (text.match(/^\.h2/)) {
+ text = text.substring(4)
+ p.className = "h2"
+ }
+ else if (text.match(/^\.h3/)) {
+ text = text.substring(4)
+ p.className = "h3"
+ }
+
+ p.innerHTML = text
+ return p
+}
+
build_hexes()
scroll_with_middle_mouse("main")
diff --git a/rules.js b/rules.js
index b187dd9..473b6fc 100644
--- a/rules.js
+++ b/rules.js
@@ -421,9 +421,9 @@ function update_zoc() {
function goto_command_phase() {
log("")
- log("Turn " + game.turn)
+ log(".h1 Turn " + game.turn)
log("")
- log("Command Phase")
+ log(".h2 Command Phase")
log("")
bring_on_reinforcements()
goto_hq_placement_step()
@@ -840,7 +840,7 @@ function goto_organization_phase() {
}
log("")
- log("Organization Phase")
+ log(".h2 Organization Phase")
// F: ADVANCE FORMATION
game.active = P1
@@ -878,23 +878,26 @@ function can_withdraw_any() {
function goto_withdrawal() {
log("")
- log("Withdrawal.")
- game.active = P1
- game.state = "withdrawal"
+ log(".h2 Withdrawal")
game.remain = 0
- if (!can_withdraw_any())
- pass_withdrawal()
+ game.active = P2
+ next_withdrawal()
}
function next_withdrawal() {
game.state = "withdrawal"
+
if (game.remain === 0) {
set_next_player()
- if (!can_withdraw_any())
- pass_withdrawal()
- } else if (--game.remain === 0) {
- end_withdrawal()
+ } else {
+ if (--game.remain === 0) {
+ end_withdrawal()
+ return
+ }
}
+
+ if (!can_withdraw_any())
+ pass_withdrawal()
}
function pass_withdrawal() {
@@ -979,23 +982,74 @@ function bring_on_reinforcements() {
set_piece_hex(p, BLOWN)
}
+function can_move_any() {
+ update_zoc()
+ for (let info of data.reinforcements)
+ if (info.turn === game.turn && info.side === game.active)
+ for (let p of info.list)
+ if (piece_hex(p) === REINFORCEMENTS)
+ return true
+ for (let p of friendly_cavalry_corps())
+ if (piece_is_not_in_enemy_cav_zoc(p))
+ return true
+ for (let p of friendly_infantry_corps())
+ if (piece_is_not_in_enemy_zoc(p))
+ return true
+ return false
+}
+
function goto_movement_phase() {
log("")
- log("Movement Phase")
+ log(".h2 Movement Phase")
log("")
- game.active = P1
- game.state = "movement"
game.remain = 0
+ game.active = P2
+ next_movement()
}
-// TODO: can move or auto-pass
-
function next_movement() {
game.state = "movement"
- if (game.remain === 0)
+ game.who = -1
+
+ if (game.remain === 0) {
set_next_player()
- else if (--game.remain === 0)
+ } else {
+ if (--game.remain === 0) {
+ end_movement()
+ return
+ }
+ }
+
+ if (!can_move_any())
+ pass_movement()
+}
+
+function pass_movement() {
+ log(game.active + " passed movement.")
+ if (game.remain > 0) {
end_movement()
+ } else {
+ update_zoc()
+ set_next_player()
+
+ game.remain = roll_die()
+ log("Rolled D" + game.remain)
+
+ let n = 0
+ for (let p of friendly_corps()) {
+ if (piece_is_not_in_enemy_zoc_or_zoi(p))
+ ++n
+ if (piece_hex(p) === REINFORCEMENTS)
+ ++n
+ }
+
+ log(n + " Corps not in ZOC/ZOI")
+
+ game.remain += n
+
+ if (!can_move_any())
+ pass_movement()
+ }
}
function end_movement() {
@@ -1038,27 +1092,7 @@ states.movement = {
game.state = "movement_to"
},
pass() {
- log(game.active + " passed movement.")
- if (game.remain > 0) {
- end_movement()
- } else {
- update_zoc()
- set_next_player()
- game.remain = roll_die()
- log("Rolled D" + game.remain)
-
- let n = 0
- for (let p of friendly_corps()) {
- if (piece_is_not_in_enemy_zoc_or_zoi(p))
- ++n
- if (piece_hex(p) === REINFORCEMENTS)
- ++n
- }
-
- log(n + " Corps not in ZOC/ZOI")
-
- game.remain += n
- }
+ pass_movement()
},
}
@@ -1386,26 +1420,53 @@ function search_retreat(result, here, from_list, n) {
// === ATTACK PHASE ===
+function can_attack_any() {
+ for (let p of friendly_corps())
+ if (piece_is_in_enemy_zoc(p))
+ return true
+ return false
+}
+
function goto_attack_phase() {
log("")
- log("Attack Phase")
+ log(".h2 Attack Phase")
log("")
- game.active = P1
- game.state = "attack"
game.remain = 0
+ game.active = P2
+ next_attack()
}
-// TODO: can attack or auto-pass
-
function next_attack() {
game.state = "attack"
game.who = -1
game.target = -1
game.attack = 0
- if (game.remain === 0)
+
+ if (game.remain === 0) {
set_next_player()
- else if (--game.remain === 0)
+ } else {
+ if (--game.remain === 0) {
+ end_attack()
+ return
+ }
+ }
+
+ if (!can_attack_any())
+ pass_attack()
+}
+
+function pass_attack() {
+ log(game.active + " passed attack.")
+ if (game.remain > 0) {
end_attack()
+ } else {
+ set_next_player()
+ game.remain = roll_die()
+ console.log("roll", game.remain)
+ log("Rolled D" + game.remain)
+ if (!can_attack_any())
+ pass_attack()
+ }
}
function end_attack() {
@@ -1427,19 +1488,10 @@ states.attack = {
game.state = "attack_who"
},
pass() {
- log(game.active + " passed attack.")
- if (game.remain > 0) {
- end_attack()
- } else {
- set_next_player()
- game.remain = roll_die()
- log("Rolled D" + game.remain)
- }
+ pass_attack()
},
}
-// === ATTACK
-
function can_attack_cavalry_support(p) {
if (p === game.who)
return false
@@ -1481,7 +1533,7 @@ states.attack_who = {
pop_undo()
return
}
- log("Attacked " + p)
+ log("Attacked P" + p)
game.target = p
game.attack = piece_hex(game.target)
begin_attack()
@@ -1577,7 +1629,7 @@ function goto_resolve_attack() {
let town = is_town_hex(d_hex)
log("")
- log("ATTACK H" + d_hex)
+ log("ATTACK " + d_hex)
// ATTACKER DRM