summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--about.html13
-rw-r--r--create.html0
-rw-r--r--play.html49
-rw-r--r--play.js88
-rw-r--r--rules.js108
-rw-r--r--title.sql1
6 files changed, 259 insertions, 0 deletions
diff --git a/about.html b/about.html
new file mode 100644
index 0000000..526e01e
--- /dev/null
+++ b/about.html
@@ -0,0 +1,13 @@
+<p>
+Lorem ipsum dolor...
+
+<p>
+Design: Alex Knight.
+<br>
+Published by <a href="https://www.bluepantherllc.com/products/land-and-freedom">Blue Panther</a>.
+<br>
+Programming &copy; 2024 by Frans Bongers.
+
+<ul>
+<li><a href="/land-and-freedom/info/rules.html">Rulebook</a>
+</ul>
diff --git a/create.html b/create.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/create.html
diff --git a/play.html b/play.html
new file mode 100644
index 0000000..ea74288
--- /dev/null
+++ b/play.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!-- vim:set nowrap: -->
+<html lang="en">
+<head>
+<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, interactive-widget=resizes-content, viewport-fit=cover">
+<meta name="theme-color" content="#444">
+<meta charset="UTF-8">
+<title>LAND &amp; FREEDOM</title>
+<link rel="icon" href="favicon.png">
+<link rel="stylesheet" href="/fonts/fonts.css">
+<link rel="stylesheet" href="/common/client.css">
+<script defer src="/common/client.js"></script>
+<script defer src="play.js"></script>
+</head>
+<style>
+/* insert stylesheet here */
+</style>
+<body>
+
+<header>
+ <div id="toolbar">
+ <details>
+ <summary><img src="/images/cog.svg"></summary>
+ <menu>
+ <li><a href="info/rules.html" target="_blank">Rules</a>
+ </menu>
+ </details>
+ </div>
+</header>
+
+<aside>
+ <div id="roles">
+ </div>
+ <div id="log"></div>
+</aside>
+
+<main>
+ <div id="mapwrap">
+ <div id="map">
+ <div id="spaces"></div>
+ <div id="pieces"></div>
+ </div>
+ </div>
+ <div id="hand"></div>
+</main>
+
+<footer id="status"></footer>
+
+</body>
diff --git a/play.js b/play.js
new file mode 100644
index 0000000..35d4bd9
--- /dev/null
+++ b/play.js
@@ -0,0 +1,88 @@
+"use strict"
+
+/* global view, player, send_action, action_button */
+
+const SPACE_COUNT = 64
+const PIECE_COUNT = 32
+const CARD_COUNT = 52
+
+let ui = {
+ map: document.getElementById("map"),
+ hand: document.getElementById("hand"),
+ spaces: [],
+ pieces: [],
+ cards: [],
+}
+
+let action_register = []
+
+function register_action(e, action, id) {
+ e.my_action = action
+ e.my_id = id
+ e.onmousedown = on_click_action
+ action_register.push(e)
+}
+
+function on_click_action(evt) {
+ if (evt.button === 0)
+ if (send_action(evt.target.my_action, evt.target.my_id))
+ evt.stopPropagation()
+}
+
+function is_action(action, arg) {
+ if (arg === undefined)
+ return !!(view.actions && view.actions[action] === 1)
+ return !!(view.actions && view.actions[action] && view.actions[action].includes(arg))
+}
+
+let on_init_once = false
+
+function on_init() {
+ if (on_init_once)
+ return
+ on_init_once = true
+
+ // create space elements
+ for (let s = 0; s < SPACE_COUNT; ++s) {
+ let e = ui.spaces[s].document.createElement("div")
+ e.className = "space"
+ register_action(e, "space", s)
+ ui.map.appendChild(e)
+ }
+
+ // create piece elements
+ for (let p = 0; p < PIECE_COUNT; ++p) {
+ let e = ui.pieces[p] = document.createElement("div")
+ e.className = "piece"
+ register_action(e, "piece", s)
+ }
+
+ // create card elements
+ for (let c = 0; c < CARD_COUNT; ++c) {
+ let e = ui.cards[c] = document.createElement("div")
+ e.className = "card"
+ register_action(e, "card", s)
+ }
+}
+
+function on_update() {
+ on_init()
+
+ for (let s = 0; s < SPACE_COUNT; ++s)
+ ui.spaces[s].replaceChildren()
+
+ for (let p = 0; p < PIECE_COUNT; ++p) {
+ let s = view.location[p]
+ ui.spaces[s].appendChild(ui.pieces[p])
+ }
+
+ ui.hand.replaceChildren()
+ for (let c of view.hand)
+ ui.hand.appendChild(ui.cards[c])
+
+ for (let e of action_register)
+ e.classList.toggle("action", is_action(e.my_action, e.my_id))
+
+ action_button("next", "Next")
+ action_button("undo", "Undo")
+}
diff --git a/rules.js b/rules.js
new file mode 100644
index 0000000..08edea8
--- /dev/null
+++ b/rules.js
@@ -0,0 +1,108 @@
+"use strict"
+
+var states = {}
+var game = null
+var view = null
+
+exports.scenarios = [ "Standard" ]
+
+exports.roles = [ "Anarchist", "Moderate", "Fascist" ]
+
+function gen_action(action, argument) {
+ if (!(action in view.actions))
+ view.actions[action] = []
+ view.actions[action].push(argument)
+}
+
+function gen_action_space(space) {
+ gen_action("space", space)
+}
+
+function gen_action_piece(piece) {
+ gen_action("piece", piece)
+}
+
+function gen_action_card(card) {
+ gen_action("card", card)
+}
+
+exports.action = function (state, player, action, arg) {
+ game = state
+ let S = states[game.state]
+ if (action in S)
+ S[action](arg, player)
+ else if (action === "undo" && game.undo && game.undo.length > 0)
+ pop_undo()
+ else
+ throw new Error("Invalid action: " + action)
+ return game
+}
+
+exports.view = function (state, player) {
+ game = state
+
+ view = {
+ log: game.log,
+ prompt: null,
+ location: game.location,
+ selected: game.selected,
+ }
+
+ if (player !== game.active) {
+ let inactive = states[game.state].inactive || game.state
+ view.prompt = `Waiting for ${game.active} to ${inactive}.`
+ } else {
+ view.actions = {}
+ states[game.state].prompt()
+ if (game.undo && game.undo.length > 0)
+ view.actions.undo = 1
+ else
+ view.actions.undo = 0
+ }
+
+ return view
+}
+
+exports.setup = function (seed, scenario, options) {
+ game = {
+ seed: seed,
+ state: null,
+ active: "Anarchist",
+ log: [],
+ undo: [],
+ }
+
+ game.state = "move"
+
+ return game
+}
+
+states.move = {
+ inactive: "move",
+ prompt() {
+ view.prompt = "Move a piece."
+ for (let p = 0; p < 32; ++p)
+ gen_action_piece(p)
+ },
+ piece(p) {
+ game.selected = p
+ game.state = "move_to"
+ },
+}
+
+states.move_to = {
+ inactive: "move",
+ prompt() {
+ view.prompt = "Move the piece to a space."
+ for (let s = 0; s < 64; ++s)
+ gen_action_space(s)
+ },
+ space(to) {
+ game.location[game.selected] = to
+ game.state = "move"
+ if (game.active === PLAYER1)
+ game.active = PLAYER2
+ else
+ game.active = PLAYER1
+ },
+}
diff --git a/title.sql b/title.sql
new file mode 100644
index 0000000..c6dfb22
--- /dev/null
+++ b/title.sql
@@ -0,0 +1 @@
+insert or ignore into titles ( title_id, title_name, bgg, is_symmetric ) values ( 'land-and-freedom', 'Land and Freedom', 375931, 0 );