summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.html99
-rw-r--r--play.js167
-rw-r--r--rules.js36
3 files changed, 225 insertions, 77 deletions
diff --git a/play.html b/play.html
index 12f58f7..798fc85 100644
--- a/play.html
+++ b/play.html
@@ -37,46 +37,58 @@ main { background-color: dimgray }
background-image: url(map.svg);
}
-#map div {
+/* #map div {
position: absolute;
transition-property: top, left;
transition-duration: 1s;
transition-timing-function: ease;
-}
-
-#boxes { position: absolute; }
-#cities { position: absolute; }
-#units { position: absolute; }
+} */
/* SPACES */
.box{position:absolute;box-sizing:border-box;border:4px solid transparent}
-.box.city{border-radius:50%}
.box.loc{border-radius:50%}
.box.action{border-color:lemonchiffon;}
-.box.city.action{background-color:#6495ed55;border-color:deepskyblue;}
.box.loc.action{background-color:#fff5;border-color:white;}
.box.selected{border-color:yellow;}
.box.tip { border-color: white; }
+.stack {
+ display: grid;
+ grid-gap: 0.1rem;
+ grid-template-columns: repeat(8, 2px);
+ transition: grid-template-columns 0.5s;
+}
+
+.stack:hover {
+ grid-template-columns: repeat(8, 36px);
+}
+
+.stack:hover div {
+ z-index: 100;
+}
+
+#tracker div {
+ box-sizing: border-box;
+}
/* COUNTERS */
-#map .counter {
+/* #map .counter {
position: absolute;
-}
+} */
.counter {
background-size: 1000%;
background-repeat: no-repeat;
border-style: solid;
- transition: top 200ms, left 200ms, transform 200ms;
+ /* transition: top 200ms, left 200ms, transform 200ms; */
}
.counter {
width: 39px;
height: 39px;
- border-width: 3px;
+ border-width: 2px;
border-radius: 8px;
background-image: url(counters.svg);
}
@@ -226,47 +238,23 @@ main { background-color: dimgray }
<!-- scale 1.80333333333333333333 -->
-<!-- <div id="cities">
-<div id="Bogota" class="box city" style="top:1266px;left:684px;width:141px;height:140px"></div>
-<div id="Cali" class="box city" style="top:1434px;left:328px;width:126px;height:126px"></div>
-<div id="Medellin" class="box city" style="top:1003px;left:450px;width:126px;height:125px"></div>
-<div id="Bucaramanga" class="box city" style="top:920px;left:779px;width:120px;height:120px"></div>
-<div id="Cartagena" class="box city" style="top:457px;left:445px;width:110px;height:110px"></div>
-<div id="Cucuta" class="box city" style="top:809px;left:896px;width:110px;height:110px"></div>
-<div id="Ibague" class="box city" style="top:1219px;left:447px;width:120px;height:119px"></div>
-<div id="Neiva" class="box city" style="top:1488px;left:534px;width:110px;height:109px"></div>
-<div id="Pasto" class="box city" style="top:1728px;left:219px;width:110px;height:110px"></div>
-<div id="Santa Marta" class="box city" style="top:376px;left:622px;width:120px;height:119px"></div>
-<div id="Sincelejo" class="box city" style="top:653px;left:459px;width:110px;height:110px"></div>
-</div> -->
+<div id="tracker">
+</div>
<div id="boxes">
</div>
<div id="markers">
- <div class="counter turn_now" style="left:3px;top:4px;"></div>
- <div class="counter fln_psl" style="left:53px;top:4px;"></div>
- <div class="counter fln_ap" style="left:103px;top:4px;"></div>
- <div class="counter gov_psl" style="left:153px;top:4px;"></div>
- <div class="counter fln_control" style="left:203px;top:4px;"></div>
- <div class="counter gov_control" style="left:253px;top:4px;"></div>
- <div class="counter oas_active" style="left:303px;top:4px;"></div>
- <div class="counter remote" style="left:353px;top:4px;"></div>
- <div class="counter terror" style="left:403px;top:4px;"></div>
-
-
- <!-- top right -->
- <div class="counter turn_now" style="left:1450px;top:4px;"></div>
-
- <!-- bottom right -->
- <div class="counter turn_now" style="left:1450px;top:1051px;"></div>
-
- <!-- bottom left -->
- <div class="counter turn_now" style="left:3px;top:1051px;"></div>
-
- <div class="counter turn_now" style="left:242px;top:330px;"></div>
-
- <div class="counter border_zone" style="left:163px;top:223px;"></div>
+ <div id="turn_now" class="counter turn_now"></div>
+ <div id="fln_psl" class="counter fln_psl"></div>
+ <div id="fln_ap" class="counter fln_ap"></div>
+ <div id="gov_psl" class="counter gov_psl"></div>
+ <div id="air_avail" class="counter air_avail"></div>
+ <div id="air_max" class="counter air_max"></div>
+ <div id="helo_avail" class="counter helo_avail"></div>
+ <div id="helo_max" class="counter helo_max"></div>
+ <div id="naval" class="counter naval_pts"></div>
+ <div id="border_zone" class="counter border_zone"></div>
</div>
<div id="units"></div>
@@ -278,7 +266,7 @@ main { background-color: dimgray }
<div id="gov_supply_header" class="panel_header">Government Supply</div>
<div id="gov_supply" class="panel_body">
-<div class="counter fr_xx_2"></div>
+<!-- <div class="counter fr_xx_2"></div>
<div class="counter fr_xx_4"></div>
<div class="counter fr_xx_9"></div>
<div class="counter fr_xx_12"></div>
@@ -310,7 +298,7 @@ main { background-color: dimgray }
<div class="counter alg_police"></div>
<div class="counter alg_police"></div>
<div class="counter alg_police"></div>
-<div class="counter alg_police"></div>
+<div class="counter alg_police"></div> -->
</div>
</div>
@@ -319,10 +307,17 @@ main { background-color: dimgray }
<div id="fln_supply_header" class="panel_header">FLN Supply</div>
<div id="fln_supply" class="panel_body">
-<div class="counter fln_failek neutralized"></div>
+<!-- <div class="counter fln_failek neutralized"></div>
<div class="counter fln_band"></div>
<div class="counter fln_cadre"></div>
-<div class="counter fln_front neutralized"></div>
+<div class="counter fln_front neutralized"></div> -->
+
+</div>
+</div>
+
+<div id="eliminated_panel" class="panel">
+<div id="eliminated_header" class="panel_header">Eliminated</div>
+<div id="eliminated" class="panel_body">
</div>
</div>
diff --git a/play.js b/play.js
index 463b50b..d668379 100644
--- a/play.js
+++ b/play.js
@@ -9,6 +9,9 @@ const URBAN = 1
const REMOTE = 2
const COUNTRY = 3
+const DEPLOY = 1
+const ELIMINATED = 2
+
const UG = 0
const OPS = 1
const PTL = 2
@@ -16,8 +19,81 @@ const OC = 3
// const BOXES = [UG, OPS, PTL, OC]
const BOX_NAMES = ["UG", "OPS", "PTL", "OC"]
+const unit_count = 120
+
let ui = {
board: document.getElementById("map"),
+ map: document.getElementById("map"),
+ favicon: document.getElementById("favicon"),
+ header: document.querySelector("header"),
+ status: document.getElementById("status"),
+ player: [
+ document.getElementById("role_FLN"),
+ document.getElementById("role_Government"),
+ ],
+ markers: {
+ turn: document.getElementById("turn_now"),
+ fln_psl: document.getElementById("fln_psl"),
+ fln_ap: document.getElementById("fln_ap"),
+ gov_psl: document.getElementById("gov_psl"),
+ air_avail: document.getElementById("air_avail"),
+ air_max: document.getElementById("air_max"),
+ helo_avail: document.getElementById("helo_avail"),
+ helo_max: document.getElementById("helo_max"),
+ naval: document.getElementById("naval"),
+ border_zone: document.getElementById("border_zone"),
+
+ },
+ tracker: [],
+ drm: [],
+ areas: [],
+ locations: [],
+ zones: [],
+ units: [],
+ units_holder: document.getElementById("units"),
+ fln_supply: document.getElementById("fln_supply"),
+ gov_supply: document.getElementById("gov_supply"),
+ eliminated: document.getElementById("eliminated"),
+}
+
+// === UNIT STATE ===
+
+// location (8 bits), dispersed (1 bit), airmobile (1 bit), neutralized (1 bit)
+
+const UNIT_NEUTRALIZED_SHIFT = 0
+const UNIT_NEUTRALIZED_MASK = 1 << UNIT_NEUTRALIZED_SHIFT
+
+const UNIT_AIRMOBILE_SHIFT = 1
+const UNIT_AIRMOBILE_MASK = 1 << UNIT_AIRMOBILE_SHIFT
+
+const UNIT_DISPERSED_SHIFT = 2
+const UNIT_DISPERSED_MASK = 1 << UNIT_DISPERSED_SHIFT
+
+const UNIT_LOC_SHIFT = 3
+const UNIT_LOC_MASK = 255 << UNIT_LOC_SHIFT
+
+function is_unit_neutralized(u) {
+ return (game.units[u] & UNIT_NEUTRALIZED_MASK) === UNIT_NEUTRALIZED_MASK
+}
+
+function unit_loc(u) {
+ return (view.units[u] & UNIT_LOC_MASK) >> UNIT_LOC_SHIFT
+}
+
+function is_unit_airmobile(u) {
+ return (view.units[u] & UNIT_AIRMOBILE_MASK) === UNIT_AIRMOBILE_MASK
+}
+
+function is_unit_not_airmobile(u) {
+ return (view.units[u] & UNIT_AIRMOBILE_MASK) !== UNIT_AIRMOBILE_MASK
+}
+
+function is_unit_dispersed(u) {
+ return (view.units[u] & UNIT_DISPERSED_MASK) === UNIT_DISPERSED_MASK
+}
+
+function is_unit_not_dispersed(u) {
+ return (view.units[u] & UNIT_DISPERSED_MASK) !== UNIT_DISPERSED_MASK
}
let action_register = []
@@ -58,6 +134,36 @@ function create_item(p) {
let on_init_once = false
+function build_units() {
+ function build_unit(u) {
+ let elt = ui.units[u] = document.createElement("div")
+ let klass = data.units[u].class
+ elt.className = `counter unit u${u} ${klass}`
+ elt.addEventListener("mousedown", on_click_unit)
+ // elt.addEventListener("mouseenter", on_focus_unit)
+ // elt.addEventListener("mouseleave", on_blur)
+ elt.unit = u
+ }
+ for (let u = 0; u < unit_count; ++u) {
+ build_unit(u)
+ }
+}
+
+function on_click_loc(evt) {
+ if (evt.button === 0) {
+ console.log('loc', evt.target.loc)
+ if (send_action('loc', evt.target.loc))
+ evt.stopPropagation()
+ }
+}
+
+function on_click_unit(evt) {
+ if (evt.button === 0) {
+ console.log('unit', evt.target.unit)
+ send_action('unit', evt.target.unit)
+ }
+}
+
function on_init() {
if (on_init_once)
return
@@ -67,14 +173,14 @@ function on_init() {
let x = 5
let y = 5
for (let i = 0; i < 100; ++i) {
- let e = document.createElement("div")
- e.id = `tracker-${i}`
- e.className = "box"
+ let e = ui.tracker[i] = document.createElement("div")
+ e.my_id = i
+ e.className = "box stack"
e.style.left = x / SCALE + "px"
e.style.top = y / SCALE + "px"
e.style.width = 85 / SCALE + "px"
e.style.height = 85 / SCALE + "px"
- document.getElementById("boxes").appendChild(e)
+ document.getElementById("tracker").appendChild(e)
if (i < 29) {
x += 90
@@ -87,10 +193,10 @@ function on_init() {
}
}
- // DRM
+ // Border Zone DRM
for (let i = 0; i < 4; ++i) {
- let e = document.createElement("div")
- e.id = `drm-${i}`
+ let e = ui.drm[i] = document.createElement("div")
+ e.my_id = i
e.className = "box"
e.style.left = (288.2 + (i * 99)) / SCALE + "px"
e.style.top = 396 / SCALE + "px"
@@ -99,7 +205,6 @@ function on_init() {
document.getElementById("boxes").appendChild(e)
}
-
// Areas
for (let i = 0; i < data.areas.length; ++i) {
let name = data.areas[i].name
@@ -120,10 +225,12 @@ function on_init() {
if (type !== COUNTRY) {
for (let j = 0; j < 4; ++j) {
- let e = document.createElement("div")
+ let e = ui.locations[i * 4 + j] = document.createElement("div")
let box_name = BOX_NAMES[j]
e.id = `ops-${name}-${box_name}`
- e.className = "box"
+ e.className = "box stack loc"
+ e.addEventListener("mousedown", on_click_loc)
+ e.loc = i * 4 + j
e.style.left = (data.areas[i].x + (j % 2) * 99) / SCALE + "px"
e.style.top = (data.areas[i].y + Math.floor(j / 2) * 99) / SCALE + "px"
e.style.width = 94 / SCALE + "px"
@@ -132,11 +239,51 @@ function on_init() {
}
}
}
+
+ build_units()
+}
+
+function update_map() {
+
+ ui.tracker[view.turn].appendChild(ui.markers.turn)
+ ui.tracker[view.fln_ap].appendChild(ui.markers.fln_ap)
+ ui.tracker[view.fln_psl].appendChild(ui.markers.fln_psl)
+ ui.tracker[view.gov_psl].appendChild(ui.markers.gov_psl)
+ ui.tracker[view.air_avail].appendChild(ui.markers.air_avail)
+ ui.tracker[view.air_max].appendChild(ui.markers.air_max)
+ ui.tracker[view.helo_avail].appendChild(ui.markers.helo_avail)
+ ui.tracker[view.helo_max].appendChild(ui.markers.helo_max)
+ ui.tracker[view.naval].appendChild(ui.markers.naval)
+ ui.drm[view.border_zone].appendChild(ui.markers.border_zone)
+
+ for (let u = 0; u < unit_count; ++u) {
+ let e = ui.units[u]
+ let loc = unit_loc(u)
+
+ if (loc) {
+ e.loc = loc
+ if (loc === DEPLOY) {
+ if (!ui.fln_supply.contains(e))
+ ui.fln_supply.appendChild(e)
+
+ } else if (loc === ELIMINATED) {
+ if (!ui.eliminated.contains(e))
+ ui.eliminated.appendChild(e)
+ } else {
+ if (!ui.locations[loc].contains(e))
+ ui.locations[loc].appendChild(e)
+ }
+ } else {
+ e.remove()
+ }
+ }
}
function on_update() {
on_init()
+ update_map()
+
for (let e of action_register)
e.classList.toggle("action", is_action(e.my_action, e.my_id))
diff --git a/rules.js b/rules.js
index 4a4c44b..5bdd717 100644
--- a/rules.js
+++ b/rules.js
@@ -233,12 +233,16 @@ exports.view = function(state, player) {
fln_ap: game.fln_ap,
fln_psl: game.fln_psl,
gov_psl: game.gov_psl,
- gov_air: game.gov_air,
- gov_helo: game.gov_helo,
- gov_naval: game.gov_naval,
+ air_avail: game.air_avail,
+ air_max: game.air_max,
+ helo_avail: game.helo_avail,
+ helo_max: game.helo_max,
+ naval: game.naval,
is_morocco_tunisia_independent: game.is_morocco_tunisia_independent,
border_zone: game.border_zone,
+
+ units: game.units,
}
if (game.state === "game_over") {
@@ -305,9 +309,11 @@ exports.setup = function (seed, scenario, options) {
fln_ap: 0,
fln_psl: 0,
gov_psl: 0,
- gov_air: 0,
- gov_helo: 0,
- gov_naval: 0,
+ air_avail: 0,
+ air_max: 0,
+ helo_avail: 0,
+ helo_max: 0,
+ naval: 0,
units: new Array(unit_count).fill(0),
moved: [],
@@ -336,26 +342,26 @@ exports.setup = function (seed, scenario, options) {
const SCENARIOS = {
"1954": {
gov_psl: 65,
- gov_air: 0,
- gov_helo: 0,
- gov_naval: 0,
+ air_max: 0,
+ helo_max: 0,
+ naval: 0,
fln_psl: 50,
is_morocco_tunisia_independent: false
},
"1958": {
gov_psl: 50,
- gov_air: 6,
- gov_helo: 4,
- gov_naval: 2,
+ air_avail: 6,
+ helo_avail: 4,
+ naval: 2,
fln_psl: 60,
is_morocco_tunisia_independent: true,
border_zone: -2
},
"1960": {
gov_psl: 45,
- gov_air: 7,
- gov_helo: 5,
- gov_naval: 3,
+ air_avail: 7,
+ helo_avail: 5,
+ naval: 3,
fln_psl: 45,
is_morocco_tunisia_independent: true,
border_zone: -3