summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-12-15 22:02:56 +0100
committerTor Andersson <tor@ccxvii.net>2024-01-08 16:36:48 +0100
commit8e53bd21752d446e771074f55ac919467dbcfd7f (patch)
tree8d34b8d47328d1a1104245890a9016d337f1bdae
parent7c2baa827d9ae20722c6ddb34f684e73fe83c473 (diff)
downloadtable-battles-8e53bd21752d446e771074f55ac919467dbcfd7f.tar.gz
Logging.
-rw-r--r--play.html38
-rw-r--r--play.js92
-rw-r--r--rules.js138
3 files changed, 171 insertions, 97 deletions
diff --git a/play.html b/play.html
index 61fb214..bc1e177 100644
--- a/play.html
+++ b/play.html
@@ -34,21 +34,32 @@
padding: 2px 8px;
}
-#log .ind {
+#log .t {
+ text-align: right;
+ background-color: wheat;
+ margin: 8px 0;
+}
+
+#log .i1 {
padding-left: 20px;
}
+#log .i2 {
+ padding-left: 32px;
+}
+
#log .i {
font-style: italic;
}
-#log .blue { background-color: blue; }
-#log .dkblue { background-color: navy; }
-#log .red { background-color: red; }
-#log .pink { background-color: pink; }
+#log .n { padding: 0 3px }
+#log .blue { background-color: aliceblue; }
+#log .dkblue { background-color: skyblue; }
+#log .red { background-color: pink; }
+#log .pink { background-color: mistyrose; }
-.role.blue, .role.dkblue { background-color: #8bf }
-.role.red, .role.pink { background-color: #f88 }
+.role.blue { background-color: #8bf }
+.role.red { background-color: #f88 }
main {
background-color: #666;
@@ -270,6 +281,19 @@ body.shift .number { display: block; }
box-shadow: 0 0 0 1px #333, 1px 2px 3px 1px #0004;
}
+.mini {
+ display: inline-block;
+ vertical-align: -3px;
+ width: 12px;
+ height: 12px;
+ border-width: 1px;
+ background-size: 600% 100%;
+ background-repeat: no-repeat;
+ background-image: url(images/die_black_pips.svg);
+ background-color: #ccc;
+ border: 1px solid black;
+}
+
.d0 { background-position: -100% 0 }
.d1 { background-position: 0% 0; }
.d2 { background-position: 20% 0; }
diff --git a/play.js b/play.js
index edda080..a104ed1 100644
--- a/play.js
+++ b/play.js
@@ -3,6 +3,7 @@
/* global data, view, send_action, action_button, player */
const wing_name = [ "red", "pink", "blue", "dkblue" ]
+const side_color = [ "red", "red", "blue", "blue" ]
const reactions = [ "Screen", "Counterattack", "Absorb" ]
let ui = {
@@ -357,8 +358,8 @@ function on_update() {
let w1 = data.cards[view.front[0][0]].wing
let w2 = data.cards[view.front[1][0]].wing
- ui.role_panel[0].className = "role " + wing_name[w1]
- ui.role_panel[1].className = "role " + wing_name[w2]
+ ui.role_panel[0].className = "role " + side_color[w1]
+ ui.role_panel[1].className = "role " + side_color[w2]
ui.role_name[0].textContent = data.scenarios[view.scenario].players[0].name
ui.role_name[1].textContent = data.scenarios[view.scenario].players[1].name
@@ -454,37 +455,37 @@ for (let i = 0; i < 12; ++i) {
}
const ICONS = {
- D0: '<span class="die black d0"></span>',
- D1: '<span class="die black d1"></span>',
- D2: '<span class="die black d2"></span>',
- D3: '<span class="die black d3"></span>',
- D4: '<span class="die black d4"></span>',
- D5: '<span class="die black d5"></span>',
- D6: '<span class="die black d6"></span>',
- R1: '<span class="die red d1"></span>',
- R2: '<span class="die red d2"></span>',
- R3: '<span class="die red d3"></span>',
- R4: '<span class="die red d4"></span>',
- R5: '<span class="die red d5"></span>',
- R6: '<span class="die red d6"></span>',
- P1: '<span class="die pink d1"></span>',
- P2: '<span class="die pink d2"></span>',
- P3: '<span class="die pink d3"></span>',
- P4: '<span class="die pink d4"></span>',
- P5: '<span class="die pink d5"></span>',
- P6: '<span class="die pink d6"></span>',
- B1: '<span class="die blue d1"></span>',
- B2: '<span class="die blue d2"></span>',
- B3: '<span class="die blue d3"></span>',
- B4: '<span class="die blue d4"></span>',
- B5: '<span class="die blue d5"></span>',
- B6: '<span class="die blue d6"></span>',
- K1: '<span class="die dkblue d1"></span>',
- K2: '<span class="die dkblue d2"></span>',
- K3: '<span class="die dkblue d3"></span>',
- K4: '<span class="die dkblue d4"></span>',
- K5: '<span class="die dkblue d5"></span>',
- K6: '<span class="die dkblue d6"></span>',
+ D0: '<span class="mini black d0"></span>',
+ D1: '<span class="mini black d1"></span>',
+ D2: '<span class="mini black d2"></span>',
+ D3: '<span class="mini black d3"></span>',
+ D4: '<span class="mini black d4"></span>',
+ D5: '<span class="mini black d5"></span>',
+ D6: '<span class="mini black d6"></span>',
+ R1: '<span class="mini red d1"></span>',
+ R2: '<span class="mini red d2"></span>',
+ R3: '<span class="mini red d3"></span>',
+ R4: '<span class="mini red d4"></span>',
+ R5: '<span class="mini red d5"></span>',
+ R6: '<span class="mini red d6"></span>',
+ P1: '<span class="mini pink d1"></span>',
+ P2: '<span class="mini pink d2"></span>',
+ P3: '<span class="mini pink d3"></span>',
+ P4: '<span class="mini pink d4"></span>',
+ P5: '<span class="mini pink d5"></span>',
+ P6: '<span class="mini pink d6"></span>',
+ B1: '<span class="mini blue d1"></span>',
+ B2: '<span class="mini blue d2"></span>',
+ B3: '<span class="mini blue d3"></span>',
+ B4: '<span class="mini blue d4"></span>',
+ B5: '<span class="mini blue d5"></span>',
+ B6: '<span class="mini blue d6"></span>',
+ K1: '<span class="mini dkblue d1"></span>',
+ K2: '<span class="mini dkblue d2"></span>',
+ K3: '<span class="mini dkblue d3"></span>',
+ K4: '<span class="mini dkblue d4"></span>',
+ K5: '<span class="mini dkblue d5"></span>',
+ K6: '<span class="mini dkblue d6"></span>',
}
function sub_icon(match) {
@@ -492,9 +493,10 @@ function sub_icon(match) {
}
function sub_card(match) {
- let wing = ""
- let name = match
- return `<span class="${wing}">${name}</span>`
+ let c = parseInt(match.substring(1))
+ let wing = wing_name[data.cards[c].wing]
+ let name = data.cards[c].name
+ return `<span class="n ${wing}">${name}</span>`
}
function on_log(text) {
@@ -507,14 +509,26 @@ function on_log(text) {
text = text.substring(4)
p.className = "h2"
}
- else if (text.match(/^>/)) {
- text = text.substring(1)
- p.className = "ind"
+ else if (text.match(/^\.t0/)) {
+ text = data.scenarios[view.scenario].players[0].name
+ p.className = "t"
+ }
+ else if (text.match(/^\.t1/)) {
+ text = data.scenarios[view.scenario].players[1].name
+ p.className = "t"
}
else if (text.match(/^\.i /)) {
text = text.substring(3)
p.className = "i"
}
+ else if (text.match(/^>>/)) {
+ text = text.substring(2)
+ p.className = "i2"
+ }
+ else if (text.match(/^>/)) {
+ text = text.substring(1)
+ p.className = "i1"
+ }
text = text.replace(/\bC\d+\b/g, sub_card)
text = text.replace(/\b[DPRBK]\d\b/g, sub_icon)
diff --git a/rules.js b/rules.js
index e1bddda..fe2840f 100644
--- a/rules.js
+++ b/rules.js
@@ -380,6 +380,7 @@ exports.setup = function (seed, scenario, options) {
// dice value placed on what card
rolled: 0,
placed: [],
+ summary: 0,
// current action
routed: [ 0, 0 ],
@@ -533,7 +534,7 @@ function set_sticks(c, n) {
}
function move_sticks(from, to, n) {
- log(`Moved ${n} sticks from C${from} to C${to}.`) // TODO?
+ // log(`Moved ${n} sticks from C${from} to C${to}.`) // TODO?
set_sticks(from, get_sticks(from) - n)
set_sticks(to, get_sticks(to) + n)
}
@@ -575,7 +576,7 @@ function remove_dice(c) {
}
function take_all_dice(from, to) {
- log("Take dice from " + from + " to " + to + ".")
+ log("Dice from C" + from)
for (let i = 0; i < 12; ++i) {
if (get_dice_location(i) === from) {
set_dice_location(i, to)
@@ -584,7 +585,7 @@ function take_all_dice(from, to) {
}
function take_one_die(from, to) {
- log("One die from " + from + " to " + to + ".")
+ log("Die from C" + from)
for (let i = 0; i < 12; ++i) {
if (get_dice_location(i) === from) {
set_dice_location(i, to)
@@ -596,7 +597,7 @@ function take_one_die(from, to) {
}
function take_wild_die(from, to) {
- log("Wild die from " + from + " to " + to + ".")
+ log("Wild die from C" + from)
for (let i = 0; i < 12; ++i) {
if (get_dice_location(i) === from) {
set_dice_location(i, to)
@@ -620,27 +621,26 @@ function rout_card(c) {
let p = find_card_owner(c)
game.lost[p] += get_sticks(c)
game.lost[p] += get_shift_sticks(c)
- log(c + " routed.")
+ log("C" + c + " routed.")
eliminate_card(c)
}
function pursue_card(c) {
let p = find_card_owner(c)
- log(c + " pursued.")
game.lost[p] += get_shift_sticks(c) // TODO ?
eliminate_card(c)
}
function retire_card(c) {
let p = find_card_owner(c)
- log(c + " retired.")
game.lost[p] += get_shift_sticks(c) // TODO ?
eliminate_card(c)
}
function remove_card(c) {
let p = find_card_owner(c)
- log(c + " removed.")
+
+ log("C" + c + " removed.")
game.lost[p] += get_shift_sticks(c) // TODO ?
@@ -669,22 +669,6 @@ function pay_for_action(c) {
remove_dice(c)
}
-function get_player_dice_value(p, i) {
- return game.dice[p * 12 + i * 2]
-}
-
-function get_player_dice_location(p, i) {
- return game.dice[p * 12 + i * 2 + 1]
-}
-
-function set_player_dice_value(p, i, v) {
- game.dice[p * 12 + i * 2] = v
-}
-
-function set_player_dice_location(p, i, v) {
- game.dice[p * 12 + i * 2 + 1] = v
-}
-
function get_dice_value(d) {
return game.dice[d * 2]
}
@@ -840,13 +824,13 @@ function check_victory() {
function is_pool_die(i, v) {
let p = player_index()
- return get_player_dice_location(p, i) < 0 && get_player_dice_value(p, i) === v
+ return get_dice_location(p * 6 + i) < 0 && get_dice_value(p * 6 + i) === v
}
function is_pool_die_range(i, lo, hi) {
let p = player_index()
- if (get_player_dice_location(p, i) < 0) {
- let v = get_player_dice_value(p, i)
+ if (get_dice_location(p * 6 + i) < 0) {
+ let v = get_dice_value(p * 6 + i)
return v >= lo && v <= hi
}
return false
@@ -1273,7 +1257,7 @@ function check_full_house(c) {
function gen_pool_die(v) {
let p = player_index()
for (let i = 0; i < 6; ++i)
- if (get_player_dice_location(p, i) < 0 && get_player_dice_value(p, i) === v)
+ if (get_dice_location(p * 6 + i) < 0 && get_dice_value(p * 6 + i) === v)
gen_action_die(p * 6 + i)
}
@@ -1341,8 +1325,10 @@ function gen_full_house(c) {
function find_and_take_single(c, v) {
let p = player_index()
for (let i = 0; i < 6; ++i) {
- if (get_player_dice_location(p, i) < 0 && get_player_dice_value(p, i) === v) {
- set_player_dice_location(p, i, c)
+ let d = p * 6 + i
+ if (get_dice_location(d) < 0 && get_dice_value(d) === v) {
+ set_dice_location(d, c)
+ game.summary |= (1 << d)
return
}
}
@@ -1351,6 +1337,7 @@ function find_and_take_single(c, v) {
function take_single(c, d) {
set_dice_location(d, c)
+ game.summary |= (1 << d)
map_set(game.placed, c, get_dice_value(d))
}
@@ -1467,16 +1454,25 @@ states.roll = {
}
function roll_dice_in_pool() {
- game.rolled = 0
+ let rolled = []
+
if (game.reacted === player_index())
game.reacted = -1
+
let p = player_index()
for (let i = 0; i < 6; ++i) {
- if (get_player_dice_location(p, i) < 0) {
- set_player_dice_value(p, i, random(6) + 1)
- game.rolled++
+ if (get_dice_location(p * 6 + i) < 0) {
+ let v = random(6) + 1
+ set_dice_value(p * 6 + i, v)
+ rolled.push(v)
}
}
+
+ log("Roll")
+ log(">" + rolled.map(d => "D" + d).join(" "))
+
+ game.rolled = rolled.length
+ game.summary = 0
game.state = "place"
}
@@ -1544,6 +1540,20 @@ function end_roll_phase() {
game.selected = -1
+ if (game.placed.length > 0) {
+ log("Placed")
+ for (let i = 0; i < game.placed.length; i += 2) {
+ let c = game.placed[i]
+ let s = []
+ for (let d = 0; d < 12; ++d)
+ if (game.summary & (1 << d))
+ if (get_dice_location(d) === c)
+ s.push("D" + get_dice_value(d))
+ log(">C" + c)
+ log(">>" + s.join(" "))
+ }
+ }
+
// Remove placed dice to add cube on special cards.
for (let c of game.front[player_index()]) {
let s = data.cards[c].special
@@ -1556,8 +1566,8 @@ function end_roll_phase() {
// Blank out unused dice.
let p = player_index()
for (let i = 0; i < 6; ++i)
- if (get_player_dice_location(p, i) < 0)
- set_player_dice_value(p, i, 0)
+ if (get_dice_location(p * 6 + i) < 0)
+ set_dice_value(p * 6 + i, 0)
if (game.scenario === S26_PEACH_ORCHARD) {
if (player_index() === 0) {
@@ -1995,6 +2005,8 @@ function count_cards_remaining_from_wing(w) {
function goto_start_turn() {
let p = player_index()
+ log(".t" + p)
+
if (check_impossible_to_attack_victory())
return
@@ -2134,6 +2146,9 @@ states.action = {
retire(c) {
push_undo()
+ log("C" + c)
+ log("> Retire")
+
if (game.scenario === S38_FLEURUS) {
if (c === S38_LUXEMBOURGS_HORSE) {
if (is_card_in_play(S38_GOURNAYS_HORSE))
@@ -2273,13 +2288,20 @@ states.shift_to = {
},
card(c) {
game.target2 = c
- move_sticks(game.selected, game.target2, 1)
+
+ set_sticks(game.selected, get_sticks(game.selected) - 1)
+ set_shift_sticks(game.target2, get_shift_sticks(game.target2) + 1)
+
if (get_sticks(game.selected) === 1)
this.next()
},
next() {
// TODO: skip action phase?
- log(`Shifted ${get_shift_sticks(game.target2)} sticks from C${game.selected} to C${game.target2}.`)
+
+ log(`Shift ${get_shift_sticks(game.target2)}`)
+ log(">C" + game.selected)
+ log(">C" + game.target2)
+
end_action_phase()
},
}
@@ -2353,7 +2375,9 @@ states.s42_marlborough = {
}
function goto_null(c) {
- log("Fizzled " + card_number(c))
+ log("Null")
+ log(">C" + c)
+
pay_for_action(c)
end_action_phase()
}
@@ -2462,7 +2486,9 @@ states.bombard = {
view.actions.bombard = 1
},
bombard() {
- log(card_name(game.selected) + " bombarded.")
+ log("Bombard")
+ log(">C" + c)
+
let opp = 1 - player_index()
game.morale[opp] --
pay_for_action(game.selected)
@@ -2702,7 +2728,10 @@ states.attack = {
view.actions.attack = 1
},
attack() {
- log(card_name(game.selected) + " attacked " + card_name(game.target) + ".")
+ log("Attack")
+ log(">C" + game.selected)
+ log(">C" + game.target)
+
if (can_opponent_react()) {
clear_undo()
set_opponent_active()
@@ -2826,7 +2855,10 @@ states.command = {
gen_action_card(t)
},
card(c) {
- log(card_name(game.selected) + " commanded " + card_name(c) + " out of reserve.")
+ log("Command")
+ log(">C" + game.selected)
+ log(">C" + c)
+
let p = player_index()
set_delete(game.reserve[p], c)
set_add(game.front[p], c)
@@ -2903,7 +2935,6 @@ states.s38_retreat_to_nivelles_2 = {
},
}
-
// === REACTION ===
function can_opponent_react() {
@@ -3124,7 +3155,9 @@ states.screen = {
view.actions.screen = 1
},
screen() {
- log(card_name(game.target) + " screened.")
+ log("Screen")
+ log(">C" + game.target)
+
pay_for_action(game.target)
if (card_has_rule(game.target, "remove_after_screen"))
@@ -3199,7 +3232,9 @@ states.absorb = {
view.actions.absorb = 1
},
absorb() {
- log(card_name(game.target) + " absorbed.")
+ log("Absorb")
+ log(">C" + game.target)
+
pay_for_action(game.target)
end_reaction()
},
@@ -3262,7 +3297,9 @@ states.counterattack = {
view.actions.counterattack = 1
},
counterattack() {
- log(card_name(game.target) + " counterattacked.")
+ log("Counterattack")
+ log(">C" + game.target)
+
pay_for_action(game.target)
end_reaction()
},
@@ -3479,18 +3516,17 @@ states.routing = {
},
card(c) {
if (should_rout_card(c)) {
- log(card_name(c) + " routed.")
let p = find_card_owner(c)
game.routed[p] += data.cards[c].morale
rout_card(c)
} else if (should_retire_card(c)) {
- log(card_name(c) + " retired.")
+ log("C" + c + " retired.")
retire_card(c)
} else if (should_pursue(c)) {
- log(card_name(c) + " pursued.")
+ log("C" + c)
+ log(">Pursuit")
pursue_card(c)
} else {
- log(card_name(c) + " removed.")
remove_card(c)
}
resume_routing()
@@ -3592,7 +3628,7 @@ function end_reserve() {
}
function bring_out_of_reserve(c) {
- log(card_name(c) + " came out of reserve.")
+ log("C" + c + " came out of reserve.")
let p = find_card_owner(c)
set_delete(game.reserve[p], c)
set_add(game.front[p], c)