summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--images/die_black_pips.svg37
-rw-r--r--images/die_white_pips.svg37
-rw-r--r--play.css47
-rw-r--r--play.js79
-rw-r--r--rules.js106
5 files changed, 244 insertions, 62 deletions
diff --git a/images/die_black_pips.svg b/images/die_black_pips.svg
new file mode 100644
index 0000000..d641f28
--- /dev/null
+++ b/images/die_black_pips.svg
@@ -0,0 +1,37 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="336" height="56">
+<g fill="black">
+<g transform="translate(0 0)">
+<circle r="6" cx="28" cy="28"/>
+</g>
+<g transform="translate(56 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="44" cy="44"/>
+</g>
+<g transform="translate(112 0)">
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="28" cy="28"/>
+</g>
+<g transform="translate(168 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="44" cy="44"/>
+</g>
+<g transform="translate(224 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="44" cy="44"/>
+<circle r="6" cx="28" cy="28"/>
+</g>
+<g transform="translate(280 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="12" cy="28"/>
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="44" cy="28"/>
+<circle r="6" cx="44" cy="44"/>
+</g>
+</g>
+</svg>
diff --git a/images/die_white_pips.svg b/images/die_white_pips.svg
new file mode 100644
index 0000000..efc864b
--- /dev/null
+++ b/images/die_white_pips.svg
@@ -0,0 +1,37 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="336" height="56">
+<g fill="white">
+<g transform="translate(0 0)">
+<circle r="6" cx="28" cy="28"/>
+</g>
+<g transform="translate(56 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="44" cy="44"/>
+</g>
+<g transform="translate(112 0)">
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="28" cy="28"/>
+</g>
+<g transform="translate(168 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="44" cy="44"/>
+</g>
+<g transform="translate(224 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="44" cy="44"/>
+<circle r="6" cx="28" cy="28"/>
+</g>
+<g transform="translate(280 0)">
+<circle r="6" cx="12" cy="12"/>
+<circle r="6" cx="12" cy="28"/>
+<circle r="6" cx="12" cy="44"/>
+<circle r="6" cx="44" cy="12"/>
+<circle r="6" cx="44" cy="28"/>
+<circle r="6" cx="44" cy="44"/>
+</g>
+</g>
+</svg>
diff --git a/play.css b/play.css
index e9485b7..452afc2 100644
--- a/play.css
+++ b/play.css
@@ -23,6 +23,42 @@ body.America header.your_turn { background-color: hsl(211, 50%, 75%) }
#log .n { margin: 6px 0; }
#log .m { margin-top: 6px; }
+#log .die {
+ display: inline-block;
+ vertical-align: -3px;
+ width: 12px;
+ height: 12px;
+ background-size: 600% 100%;
+ background-repeat: no-repeat;
+ background-image: url(images/die_black_pips.svg);
+ background-color: #fff;
+ border: 1px solid #444;
+}
+
+#log .d0 { background-position: -100% 0 }
+#log .d1 { background-position: 0% 0; }
+#log .d2 { background-position: 20% 0; }
+#log .d3 { background-position: 40% 0; }
+#log .d4 { background-position: 60% 0; }
+#log .d5 { background-position: 80% 0; }
+#log .d6 { background-position: 100% 0; }
+
+#log .number {
+ display: inline-block;
+ margin: 0;
+ text-indent: 0;
+ text-align: center;
+ width: 12px;
+ height: 12px;
+ line-height: 12px;
+ border: 1px solid #444;
+}
+
+#log .number.ar { background-color: gold; border-radius: 50%; }
+#log .number.br_a { background-color: hsl(211, 50%, 75%); }
+#log .number.br_b { background-color: hsl(15, 90%, 75%); }
+#log .number.br_f { background-color: hsl(103, 30%, 75%); }
+
#log .tip { cursor: pointer; }
#log .tip:hover { text-decoration: underline; }
@@ -31,7 +67,6 @@ body.America header.your_turn { background-color: hsl(211, 50%, 75%) }
#log div.ii { padding-left: 44px; text-indent: -12px; }
#tooltip {
- display: none;
pointer-events: none;
position: fixed;
z-index: 600;
@@ -39,8 +74,14 @@ body.America header.your_turn { background-color: hsl(211, 50%, 75%) }
top: 60px;
}
-#tooltip.show {
- display: block;
+@media (max-width: 800px) {
+ #tooltip {
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ }
}
#mapwrap {
diff --git a/play.js b/play.js
index 3b11b69..2a792f5 100644
--- a/play.js
+++ b/play.js
@@ -225,6 +225,12 @@ function build_piece(cn, w, h) {
}
function on_init() {
+ document.getElementById("war_ends").addEventListener("mouseenter", on_focus_war_ends)
+ document.getElementById("war_ends").addEventListener("mouseleave", on_blur_war_ends)
+
+ document.getElementById("last_played").addEventListener("mouseenter", on_focus_last_played)
+ document.getElementById("last_played").addEventListener("mouseleave", on_blur_last_played)
+
for (let c = 0; c <= 110; ++c) {
let e = ui.cards[c] = document.createElement("div")
e.className = "card card_" + c
@@ -792,6 +798,10 @@ function sub_general(_match, p1) {
return `<span class="tip" onclick="on_click_general_tip(${x})" onmouseenter="on_focus_general_tip(${x})" onmouseleave="on_blur_general_tip(${x})">${n}</span>`
}
+function sub_minus(match, p1) {
+ return "\u2212" + p1
+}
+
function sub_card(_match, p1) {
let x = p1 | 0
let n = data.cards[x].title
@@ -822,12 +832,67 @@ function on_blur_general_tip(s) {
ui.generals[s].classList.remove("tip")
}
-function on_focus_card_tip(s) {
- ui.last_played.className = "card shrink card_" + s
+function on_focus_card_tip(c) {
+ document.getElementById("tooltip").className = "card card_" + c
}
function on_blur_card_tip() {
- ui.last_played.className = "card shrink card_" + view.last_played
+ document.getElementById("tooltip").classList = "hide"
+}
+
+function on_focus_last_played() {
+ if (view.last_played)
+ document.getElementById("tooltip").className = "card card_" + view.last_played
+}
+
+function on_blur_last_played() {
+ document.getElementById("tooltip").classList = "hide"
+}
+
+function on_focus_war_ends() {
+ if (view.war_ends)
+ document.getElementById("tooltip").className = "card card_" + view.war_ends
+}
+
+function on_blur_war_ends() {
+ document.getElementById("tooltip").classList = "hide"
+}
+
+const ICONS = {
+ D1: '<span class="die white d1"></span>',
+ D2: '<span class="die white d2"></span>',
+ D3: '<span class="die white d3"></span>',
+ D4: '<span class="die white d4"></span>',
+ D5: '<span class="die white d5"></span>',
+ D6: '<span class="die white d6"></span>',
+ A1: '<span class="number ar n1">1</span>',
+ A2: '<span class="number ar n2">2</span>',
+ A3: '<span class="number ar n3">3</span>',
+ A4: '<span class="number ar n4">4</span>',
+ A5: '<span class="number ar n5">5</span>',
+ A6: '<span class="number ar n6">6</span>',
+ AB1: '<span class="number br_a n1">1</span>',
+ AB2: '<span class="number br_a n2">2</span>',
+ AB3: '<span class="number br_a n3">3</span>',
+ AB4: '<span class="number br_a n4">4</span>',
+ AB5: '<span class="number br_a n5">5</span>',
+ AB6: '<span class="number br_a n6">6</span>',
+ BB1: '<span class="number br_b n1">1</span>',
+ BB2: '<span class="number br_b n2">2</span>',
+ BB3: '<span class="number br_b n3">3</span>',
+ BB4: '<span class="number br_b n4">4</span>',
+ BB5: '<span class="number br_b n5">5</span>',
+ BB6: '<span class="number br_b n6">6</span>',
+ FB1: '<span class="number br_f n1">1</span>',
+ FB2: '<span class="number br_f n2">2</span>',
+ FB3: '<span class="number br_f n3">3</span>',
+ FB4: '<span class="number br_f n4">4</span>',
+ FB5: '<span class="number br_f n5">5</span>',
+ FB6: '<span class="number br_f n6">6</span>',
+}
+
+function sub_icon(match) {
+ return ICONS[match] || match
}
function on_log(text) {
@@ -870,6 +935,14 @@ function on_log(text) {
text = text.replace(/</g, "&lt;")
text = text.replace(/>/g, "&gt;")
+ text = text.replace(/-(\d)/g, sub_minus)
+
+ text = text.replace(/\b[D][1-6]\b/g, sub_icon)
+ text = text.replace(/\b[A][1-6]\b/g, sub_icon)
+ text = text.replace(/\bAB[1-6]\b/g, sub_icon)
+ text = text.replace(/\bBB[1-6]\b/g, sub_icon)
+ text = text.replace(/\bFB[1-6]\b/g, sub_icon)
+
text = text.replace(/C(\d+)/g, sub_card)
text = text.replace(/S(\d+)/g, sub_space)
text = text.replace(/G(\d+)/g, sub_general)
diff --git a/rules.js b/rules.js
index 9446d70..fc283b9 100644
--- a/rules.js
+++ b/rules.js
@@ -2401,10 +2401,11 @@ states.intercept_roll = {
},
roll() {
clear_undo()
- let g = game.intercept.who
+ let who = game.intercept.who
let die = roll_d6()
- if (die <= GENERALS[g].agility) {
- log("Intercept G" + g + "\nrolled " + die + " <= " + GENERALS[g].agility + "\nfrom S" + game.intercept.from)
+ let agility = GENERALS[who].agility
+ if (die <= agility) {
+ log(`Intercept with G${who}\nD${die} \xd7 A${agility} from S${game.intercept.from}`)
game.move.did_intercept = 1
move_army(game.intercept)
@@ -2414,7 +2415,7 @@ states.intercept_roll = {
else
end_intercept()
} else {
- log("Intercept G" + g + "\nrolled " + die + " > " + GENERALS[g].agility + "\nfailure")
+ log(`Intercept with G${who}\nD${die} \xd7 A${agility} failed`)
delete game.intercept
if (can_intercept_to(game.move.to))
game.state = "intercept_who"
@@ -2523,11 +2524,13 @@ states.retreat_before_battle_roll = {
let who = game.retreat.who
let to = game.retreat.to
let agility = GENERALS[who].agility
- if (GENERALS[who].bonus)
- agility += 2
+ let bonus = GENERALS[who].bonus ? 2 : 0
let roll = roll_d6()
- if (roll <= agility) {
- log("Retreat G" + who + "\nrolled " + roll + " <= " + agility + "\nto S" + to)
+ if (roll <= agility + bonus) {
+ if (bonus)
+ log(`Retreat with G${who}\nD${roll} \xd7 A${agility}+2R to S${to}`)
+ else
+ log(`Retreat with G${who}\nD${roll} \xd7 A${agility} to S${to}`)
move_army(game.retreat)
if (has_enemy_general(to))
capture_enemy_general(to)
@@ -2536,7 +2539,10 @@ states.retreat_before_battle_roll = {
delete game.retreat
goto_remove_general_after_retreat_before_battle(to)
} else {
- log("Retreat G" + who + "\nrolled " + roll + " > " + agility + "\nfailure")
+ if (bonus)
+ log(`Retreat with G${who}\nD${roll} \xd7 A${agility}+2R failed`)
+ else
+ log(`Retreat with G${who}\nD${roll} \xd7 A${agility} failed`)
delete game.retreat
end_retreat_before_battle()
}
@@ -2803,10 +2809,9 @@ function gen_battle_card() {
/* RESOLVE BATTLE */
-function roll_loser_combat_losses(log) {
+function roll_loser_combat_losses(side) {
let roll = roll_d6()
let losses = 0
- log.push("Loser Combat Loss Roll: " + roll)
switch (roll) {
case 1:
case 2:
@@ -2821,14 +2826,13 @@ function roll_loser_combat_losses(log) {
losses = 3
break
}
+ log(`${side} LOSSES:\n${-losses} CU ( D${roll} )`)
return losses
}
-function roll_winner_combat_losses(log, losing_general) {
+function roll_winner_combat_losses(side, losing_general) {
let agility = losing_general !== NOBODY ? GENERALS[losing_general].agility : 0
let roll = roll_d6()
- log.push("Enemy Agility Rating: " + agility)
- log.push("Winner Combat Loss Roll: " + roll)
let losses = 0
switch (agility) {
case 0:
@@ -2844,6 +2848,10 @@ function roll_winner_combat_losses(log, losing_general) {
losses = roll <= 4 ? 1 : 0
break
}
+ if (losing_general === NOBODY)
+ log(`${side} LOSSES:\n${-losses} CU ( D${roll} \xd7 Nobody)`)
+ else
+ log(`${side} LOSSES:\n${-losses} CU ( D${roll} \xd7 A${agility} G${losing_general} )`)
return losses
}
@@ -2883,6 +2891,7 @@ function apply_american_and_french_combat_losses(max) {
function resolve_battle() {
let a_log = []
let b_log = []
+ let r_log = []
game.active = ENEMY[game.active]
let b_g = find_british_general(game.move.to)
@@ -2892,10 +2901,14 @@ function resolve_battle() {
let b_br = 0
let a_br = 0
- if (b_g !== NOBODY)
- b_log.push("General: G" + b_g)
- if (a_g !== NOBODY)
- a_log.push("General: G" + a_g)
+ let b_roll = roll_d6()
+ let a_roll = roll_d6()
+
+ b_log.push("D" + b_roll + " Roll")
+ a_log.push("D" + a_roll + " Roll")
+
+ b_log.push("+" + b_cu + " CU")
+ a_log.push("+" + a_cu + " CU")
if (b_g !== NOBODY) {
let roll = roll_d6()
@@ -2903,7 +2916,7 @@ function resolve_battle() {
b_br = Math.min(Math.floor(GENERALS[b_g].battle / 2), b_cu)
else
b_br = Math.min(GENERALS[b_g].battle, b_cu)
- b_log.push("Actual Battle Rating Roll: " + roll)
+ b_log.push(`+${b_br} G${b_g} ( D${roll} \xd7 BB${GENERALS[b_g].battle} )`)
}
if (a_g !== NOBODY) {
@@ -2912,14 +2925,12 @@ function resolve_battle() {
a_br = Math.min(Math.floor(GENERALS[a_g].battle / 2), a_cu)
else
a_br = Math.min(GENERALS[a_g].battle, a_cu)
- a_log.push("Actual Battle Rating Roll: " + roll)
+ if (a_g === ROCHAMBEAU)
+ a_log.push(`+${a_br} G${a_g} ( D${roll} \xd7 FB${GENERALS[a_g].battle} )`)
+ else
+ a_log.push(`+${a_br} G${a_g} ( D${roll} \xd7 AB${GENERALS[a_g].battle} )`)
}
- b_log.push("+" + b_cu + " CU")
- a_log.push("+" + a_cu + " CU")
- b_log.push("+" + b_br + " Actual Battle Rating")
- a_log.push("+" + a_br + " Actual Battle Rating")
-
let b_drm = b_cu + b_br + game.combat.b_bonus
if (has_flag(F_REGULARS)) {
b_log.push("+1 British Regulars' Advantage")
@@ -2958,18 +2969,14 @@ function resolve_battle() {
a_log.push("+2 Battle Card")
else if (game.combat.a_bonus === 1)
a_log.push("+1 Discard of an Event Card")
+
if (game.move.did_intercept) {
a_log.push("+1 Interception")
a_drm += 1
}
- let b_roll = roll_d6()
- let a_roll = roll_d6()
-
- b_log.push("Battle Roll: " + b_roll)
- b_log.push("Battle Total: " + (b_roll + b_drm))
- a_log.push("Battle Roll: " + a_roll)
- a_log.push("Battle Total: " + (a_roll + a_drm))
+ b_log.push("Total: " + (b_roll + b_drm))
+ a_log.push("Total: " + (a_roll + a_drm))
if (game.combat.attacker === P_BRITAIN) {
log("BRITISH ATTACK:\n" + b_log.join("\n"))
@@ -2979,9 +2986,6 @@ function resolve_battle() {
log("BRITISH DEFENSE:\n" + b_log.join("\n"))
}
- a_log = []
- b_log = []
-
let victor
if (game.active === P_BRITAIN)
victor = b_roll + b_drm >= a_roll + a_drm ? P_BRITAIN : P_AMERICA
@@ -2990,38 +2994,28 @@ function resolve_battle() {
let a_lost_cu, b_lost_cu
if (victor === P_BRITAIN) {
- b_lost_cu = roll_winner_combat_losses(b_log, a_g)
- a_lost_cu = roll_loser_combat_losses(a_log)
+ log("RESULT:\nBritish victory!")
+ b_lost_cu = roll_winner_combat_losses("BRITISH", a_g)
+ a_lost_cu = roll_loser_combat_losses("AMERICAN")
} else {
- b_lost_cu = roll_loser_combat_losses(b_log)
- a_lost_cu = roll_winner_combat_losses(a_log, b_g)
+ log("RESULT:\nAmerican victory!")
+ a_lost_cu = roll_winner_combat_losses("AMERICAN", b_g)
+ b_lost_cu = roll_loser_combat_losses("BRITISH")
}
game.combat.british_losses = apply_british_combat_losses(b_lost_cu)
let american_losses = apply_american_and_french_combat_losses(a_lost_cu)
- b_log.push("Losses: " + game.combat.british_losses + " CU")
- a_log.push("Losses: " + american_losses + " CU")
-
// Special case: winning general with no CU on enemy PC is captured
if (victor === P_BRITAIN) {
- log("RESULT:\nBritish victory!")
if (b_g && count_british_cu(game.move.to) === 0 && has_american_pc(game.move.to))
capture_british_general(game.move.to)
} else {
- log("RESULT:\nAmerican victory!")
if (a_g && count_american_and_french_cu(game.move.to) === 0 && has_british_pc(game.move.to))
capture_american_or_french_general(game.move.to)
}
-
- if (game.combat.attacker === P_BRITAIN) {
- log("BRITISH LOSSES:\n" + b_log.join("\n"))
- log("AMERICAN LOSSES:\n" + a_log.join("\n"))
- } else {
- log("AMERICAN LOSSES:\n" + a_log.join("\n"))
- log("BRITISH LOSSES:\n" + b_log.join("\n"))
- }
+ log(r_log.join("\n"))
if (victor === P_AMERICA)
advance_french_alliance(1)
@@ -3797,18 +3791,17 @@ states.george_washington_captured_during_move = {
function apply_single_winter_attrition(remove_cu, space) {
let die = roll_d6()
- log("Roll " + die + " at S" + space)
if (die <= 3) {
- log(">Lost 1 CU")
+ log(`-1 CU at S${space} ( D${die} )`)
remove_cu(space, 1)
} else {
- log(">Lost 0 CU")
+ log(`-0 CU at S${space} ( D${die} )`)
}
}
function apply_winter_attrition(remove_cu, space, n) {
let half = Math.floor(n / 2)
- log("Lost " + half + " CU at S" + space + ".")
+ log(`-${half} CU at S${space}.`)
remove_cu(space, half)
}
@@ -4187,6 +4180,7 @@ function resume_place_pc_markers_segment() {
game.active = P_AMERICA
game.state = "place_american_pc_markers_segment"
} else if (has_british_place_pc_markers_segment()) {
+ log("=b Place PC Markers")
game.active = P_BRITAIN
game.state = "place_british_pc_markers_segment"
} else {