Debug stuff
This commit is contained in:
parent
7b920dd6a9
commit
3f0688d0aa
@ -1,7 +1,157 @@
|
|||||||
const chars = ["AN","AR","AT","CA","CH","CO","DE","DI","EL","EN","ER","ES","HE","IA","IL","IN","IO","LA","LE","LI","LL","MA","ME","NA","NE","NO","NT","OL","ON","OR","PE","RA","RE","RI","RO","SE","SI","SO","ST","TA","TE","TI","TO","TR","TT","UN","TO","RE","ER","ON","CO","DI","TA","EN","IN","TE","AT","RA","AN","NO","NT","ST","LA","AR","AL","OR","CH","RI","TI","IO","LE","DE","ES","NE","ME","TT","EL","PE","IL","UN","IA","LI","SE","SO","LL","SI","OL","RO","MA","CA","NA","TR","HE","ALE","ALL","ANC","AND","ANT","ARE","ATO","ATT","CHE","CHI","COM","CON","DEL","ELL","ENT","ERA","ERE","ESS","EST","ETT","GLI","ION","LLA","MEN","NON","NTE","NTI","NTO","OLO","ONE","ONO","PER","QUE","SON","STA","STO","TAT","TRA","TTO","UNA","VER","ZIO","ENT","CHE","ATO","PER","NTE","CON","ELL","STA","ARE","MEN","ION","DEL","LLA","TTO","TAT","ESS","ERE","ETT","EST","ONE","ONO","ZIO","NON","ERA","CHI","GLI","COM","TRA","STO","NTI","SON","VER","ATT","UNA","QUE","NTO","AND","ALL","OLO","ANC","ANT","ALE"];
|
"use strict";
|
||||||
|
|
||||||
|
const SYLLABE_LIST = ["AN","AR","AT","CA","CH","CO","DE","DI","EL","EN","ER","ES","HE","IA","IL","IN","IO","LA","LE","LI","LL","MA","ME","NA","NE","NO","NT","OL","ON","OR","PE","RA","RE","RI","RO","SE","SI","SO","ST","TA","TE","TI","TO","TR","TT","UN","TO","RE","ER","ON","CO","DI","TA","EN","IN","TE","AT","RA","AN","NO","NT","ST","LA","AR","AL","OR","CH","RI","TI","IO","LE","DE","ES","NE","ME","TT","EL","PE","IL","UN","IA","LI","SE","SO","LL","SI","OL","RO","MA","CA","NA","TR","HE","ALE","ALL","ANC","AND","ANT","ARE","ATO","ATT","CHE","CHI","COM","CON","DEL","ELL","ENT","ERA","ERE","ESS","EST","ETT","GLI","ION","LLA","MEN","NON","NTE","NTI","NTO","OLO","ONE","ONO","PER","QUE","SON","STA","STO","TAT","TRA","TTO","UNA","VER","ZIO","ENT","CHE","ATO","PER","NTE","CON","ELL","STA","ARE","MEN","ION","DEL","LLA","TTO","TAT","ESS","ERE","ETT","EST","ONE","ONO","ZIO","NON","ERA","CHI","GLI","COM","TRA","STO","NTI","SON","VER","ATT","UNA","QUE","NTO","AND","ALL","OLO","ANC","ANT","ALE"];
|
||||||
|
const BOARD_DEFINITION = `
|
||||||
|
# # 1 1 1 2 1 1 # #;
|
||||||
|
# # 1 1 1 1 1 1 # #;
|
||||||
|
1 1 2 2 2 2 2 2 1 1;
|
||||||
|
1 1 2 2 2 # 2 2 1 1;
|
||||||
|
2 1 2 2 1 2 2 2 1 1;
|
||||||
|
1 1 2 2 2 2 2 2 1 1;
|
||||||
|
1 1 2 2 2 2 2 2 1 1;
|
||||||
|
1 1 2 2 2 2 2 2 1 1;
|
||||||
|
# # 1 1 1 1 1 1 # #;
|
||||||
|
# # 1 1 1 1 1 1 # #;
|
||||||
|
`
|
||||||
|
|
||||||
|
Array.prototype.removeIf = function(callback) {
|
||||||
|
var i = this.length;
|
||||||
|
while (i--) {
|
||||||
|
if (callback(this[i], i)) {
|
||||||
|
this.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseBoard(boardString) {
|
||||||
|
boardString = boardString.replaceAll(/[^#12;]/gi, "");
|
||||||
|
let boardStringArray = boardString.split(";").filter(x => x.length > 0);
|
||||||
|
const boardHeight = boardStringArray.length;
|
||||||
|
if (boardHeight <= 0) {
|
||||||
|
throw new Error("Board parsing error: empty board");
|
||||||
|
}
|
||||||
|
const boardWidth = boardStringArray[0].length;
|
||||||
|
if (boardWidth <= 0) {
|
||||||
|
throw new Error("Board parsing error: empty board");
|
||||||
|
}
|
||||||
|
boardStringArray.forEach(v => {
|
||||||
|
if (v.length !== boardWidth) {
|
||||||
|
throw new Error(`Board parsing error: expected width ${boardWidth}, got ${v.length}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const board = boardStringArray.map(row => {
|
||||||
|
return Array.from(row).map(char => {
|
||||||
|
switch (char) {
|
||||||
|
case '#': {
|
||||||
|
return {
|
||||||
|
type: "black",
|
||||||
|
cost: NaN,
|
||||||
|
occludedOnRotation: [false, false, false, false]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case '1': {
|
||||||
|
return {
|
||||||
|
type: "occupiable",
|
||||||
|
cost: 1,
|
||||||
|
occludedOnRotation: [false, false, false, false]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case '2': {
|
||||||
|
return {
|
||||||
|
type: "occupiable",
|
||||||
|
cost: 2,
|
||||||
|
occludedOnRotation: [false, false, false, false]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown character: ${char}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Blocks for rotation 0
|
||||||
|
for (let col = 0; col < boardWidth; col++) {
|
||||||
|
let blockedOnThisRotation = false;
|
||||||
|
for (let row = 0; row < boardHeight; row++) {
|
||||||
|
const square = board[row][col];
|
||||||
|
if (!blockedOnThisRotation) {
|
||||||
|
if (square.type === "black") {
|
||||||
|
blockedOnThisRotation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (square.type === "occupiable") {
|
||||||
|
square.occludedOnRotation[0] = blockedOnThisRotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks for rotation 1
|
||||||
|
for (let row = 0; row < boardHeight; row++) {
|
||||||
|
let blockedOnThisRotation = false;
|
||||||
|
for (let col = 0; col < boardWidth; col++) {
|
||||||
|
const square = board[row][col];
|
||||||
|
if (!blockedOnThisRotation) {
|
||||||
|
if (square.type === "black") {
|
||||||
|
blockedOnThisRotation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (square.type === "occupiable") {
|
||||||
|
square.occludedOnRotation[1] = blockedOnThisRotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks for rotation 2
|
||||||
|
for (let col = 0; col < boardWidth; col++) {
|
||||||
|
let blockedOnThisRotation = false;
|
||||||
|
for (let row = boardHeight - 1; row >= 0; row--) {
|
||||||
|
const square = board[row][col];
|
||||||
|
if (!blockedOnThisRotation) {
|
||||||
|
if (square.type === "black") {
|
||||||
|
blockedOnThisRotation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (square.type === "occupiable") {
|
||||||
|
square.occludedOnRotation[2] = blockedOnThisRotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks for rotation 3
|
||||||
|
for (let row = 0; row < boardHeight; row++) {
|
||||||
|
let blockedOnThisRotation = false;
|
||||||
|
for (let col = boardWidth - 1; col >= 0; col--) {
|
||||||
|
const square = board[row][col];
|
||||||
|
if (!blockedOnThisRotation) {
|
||||||
|
if (square.type === "black") {
|
||||||
|
blockedOnThisRotation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (square.type === "occupiable") {
|
||||||
|
square.occludedOnRotation[3] = blockedOnThisRotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return board;
|
||||||
|
}
|
||||||
|
|
||||||
function randomID() {
|
function randomID() {
|
||||||
var u8 = crypto.getRandomValues(new Uint8Array(3));
|
const u8 = crypto.getRandomValues(new Uint8Array(3));
|
||||||
return Array.from(u8).map(n => chars[n % chars.length]).reduce((a, b) => a + b);
|
return Array.from(u8).map(n => SYLLABE_LIST[n % SYLLABE_LIST.length]).reduce((a, b) => a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
const INITIAL_BOARD = parseBoard(BOARD_DEFINITION);
|
||||||
|
|
||||||
|
console.log(INITIAL_BOARD);
|
||||||
|
|
||||||
|
const ACTIONS_QUEUE = []
|
||||||
|
|
||||||
|
function buildGridArray(rows, columns, defaultValue) {
|
||||||
|
const array = new Array(rows);
|
||||||
|
for (let i = 0; i < rows; i++) {
|
||||||
|
array[i] = new Array(columns).fill(defaultValue);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", e => {
|
document.addEventListener("DOMContentLoaded", e => {
|
||||||
@ -10,6 +160,158 @@ document.addEventListener("DOMContentLoaded", e => {
|
|||||||
const gameCodeLink = document.getElementById("game-code-link");
|
const gameCodeLink = document.getElementById("game-code-link");
|
||||||
const newGameLink = document.getElementById("new-game-link");
|
const newGameLink = document.getElementById("new-game-link");
|
||||||
const mainBody = document.getElementById("main-body");
|
const mainBody = document.getElementById("main-body");
|
||||||
|
const boardElem = document.getElementById("board");
|
||||||
|
const rotateLeftElem = document.getElementById("rotate-left");
|
||||||
|
const rotateRightElem = document.getElementById("rotate-right");
|
||||||
|
|
||||||
|
function updateDatasetValue(elem, name, value) {
|
||||||
|
if (elem.dataset[name] !== '' + value) {
|
||||||
|
elem.dataset[name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncBlock(board, boardElems, rowIndex, colIndex, gameState) {
|
||||||
|
const square = board[rowIndex][colIndex];
|
||||||
|
const squareElem = boardElems[rowIndex][colIndex];
|
||||||
|
updateDatasetValue(squareElem, "cost", square.cost);
|
||||||
|
updateDatasetValue(squareElem, "row", rowIndex);
|
||||||
|
updateDatasetValue(squareElem, "col", colIndex);
|
||||||
|
const currentPlacement = gameState.boardPlacements[rowIndex][colIndex];
|
||||||
|
updateDatasetValue(squareElem, "square_type", square.type);
|
||||||
|
updateDatasetValue(squareElem, "occluded", square.occludedOnRotation[gameState.rotation]);
|
||||||
|
|
||||||
|
switch (square.type) {
|
||||||
|
case "occupiable": {
|
||||||
|
switch (currentPlacement) {
|
||||||
|
case "free": {
|
||||||
|
updateDatasetValue(squareElem, "occupation_state", "free");
|
||||||
|
updateDatasetValue(squareElem, "occupied_by", -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "player0": {
|
||||||
|
updateDatasetValue(squareElem, "occupation_state", "occupied");
|
||||||
|
updateDatasetValue(squareElem, "occupied_by", 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "player1": {
|
||||||
|
updateDatasetValue(squareElem, "occupation_state", "occupied");
|
||||||
|
updateDatasetValue(squareElem, "occupied_by", 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new Error("Undefined current placement type: " + currentPlacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "black": {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new Error("Undefined square type: " + square.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneGridArray(array) {
|
||||||
|
const rows = array.length;
|
||||||
|
const cols = array[0].length;
|
||||||
|
const cloned = new Array(rows);
|
||||||
|
for (let row = 0; row < rows; row++) {
|
||||||
|
const clonedRow = new Array(cols);
|
||||||
|
for (let col = 0; col < cols; col++) {
|
||||||
|
clonedRow[col] = array[row][col];
|
||||||
|
}
|
||||||
|
cols[row] = clonedRow;
|
||||||
|
}
|
||||||
|
return cloned;
|
||||||
|
}
|
||||||
|
|
||||||
|
function editState(state, action) {
|
||||||
|
const copy = {
|
||||||
|
myTurn: state.myTurn,
|
||||||
|
rotation: state.rotation,
|
||||||
|
boardPlacements: cloneGridArray(state.boardPlacements)
|
||||||
|
}
|
||||||
|
switch (action) {
|
||||||
|
case "occupy_square": {
|
||||||
|
copy[action.row][action.col] = "";
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function enqueueAction(action) {
|
||||||
|
if (action.type === "occupy_square") {
|
||||||
|
ACTIONS_QUEUE.removeIf(action => action.type === "occupy_square");
|
||||||
|
}
|
||||||
|
ACTIONS_QUEUE.push(action);
|
||||||
|
console.debug("Added an element to the actions queue", ACTIONS_QUEUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRequestRotateBy(board, delta, initialGameState) {
|
||||||
|
initialGameState
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSquareClick(square, squareElem, rowIndex, colIndex) {
|
||||||
|
console.debug(`Clicked square at ${rowIndex},${colIndex}`, square, squareElem);
|
||||||
|
switch (square.type) {
|
||||||
|
case "occupiable": {
|
||||||
|
enqueueAction({
|
||||||
|
actor: "me",
|
||||||
|
type: "occupy_square",
|
||||||
|
row: rowIndex,
|
||||||
|
col: colIndex
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildInitialBoard(board) {
|
||||||
|
const rows = board.length;
|
||||||
|
const columns = board[0].length;
|
||||||
|
boardElem.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
|
||||||
|
boardElem.style.gridTemplateColumns = `repeat(${columns}, 1fr)`;
|
||||||
|
const boardElems = [];
|
||||||
|
const initialGameState = {
|
||||||
|
myTurn: true,
|
||||||
|
rotation: 0,
|
||||||
|
boardPlacements: buildGridArray(rows, columns, "free")
|
||||||
|
};
|
||||||
|
initialGameState.boardPlacements[0][3] = "player1";
|
||||||
|
initialGameState.boardPlacements[1][3] = "player1";
|
||||||
|
initialGameState.boardPlacements[2][3] = "player1";
|
||||||
|
initialGameState.boardPlacements[3][3] = "player1";
|
||||||
|
initialGameState.boardPlacements[0][4] = "player0";
|
||||||
|
initialGameState.boardPlacements[3][3] = "player1";
|
||||||
|
initialGameState.boardPlacements[4][3] = "player1";
|
||||||
|
initialGameState.boardPlacements[5][3] = "player1";
|
||||||
|
board.forEach((row, rowIndex) => {
|
||||||
|
row.forEach((square, colIndex) => {
|
||||||
|
const squareElem = document.createElement("div");
|
||||||
|
squareElem.classList.add("square");
|
||||||
|
squareElem.onclick = () => {
|
||||||
|
onSquareClick(square, squareElem, rowIndex, colIndex);
|
||||||
|
}
|
||||||
|
if (boardElems[rowIndex] == null) {
|
||||||
|
boardElems[rowIndex] = [];
|
||||||
|
}
|
||||||
|
boardElems[rowIndex][colIndex] = squareElem;
|
||||||
|
syncBlock(board, boardElems, rowIndex, colIndex, initialGameState);
|
||||||
|
boardElem.appendChild(squareElem);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
rotateLeftElem.onclick = () => {
|
||||||
|
onRequestRotateBy(board, 1, initialGameState);
|
||||||
|
}
|
||||||
|
rotateRightElem.onclick = () => {
|
||||||
|
onRequestRotateBy(board, -1, initialGameState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildInitialBoard(INITIAL_BOARD);
|
||||||
|
|
||||||
const eb = new EventBus(`${document.location.origin}/eventbus`);
|
const eb = new EventBus(`${document.location.origin}/eventbus`);
|
||||||
eb.enableReconnect(true);
|
eb.enableReconnect(true);
|
||||||
|
@ -12,8 +12,16 @@
|
|||||||
<div id="main-body">
|
<div id="main-body">
|
||||||
<h1>Connect 2x</h1>
|
<h1>Connect 2x</h1>
|
||||||
<p>Game code: <span id="game-code"></span> <a id="game-code-link" href="#">[share]</a> <a id="new-game" href="/">[new game]</a></p>
|
<p>Game code: <span id="game-code"></span> <a id="game-code-link" href="#">[share]</a> <a id="new-game" href="/">[new game]</a></p>
|
||||||
<main id="board">
|
<main id="game">
|
||||||
|
<h2 id="turn-label">Please wait...</h2>
|
||||||
|
<h3 id="move-points-title">Move points remaining: <span id="move-points-value">0</span></h3>
|
||||||
|
<div id="board-viewer">
|
||||||
|
<div id="board"></div>
|
||||||
|
</div>
|
||||||
|
<div id="buttons-container">
|
||||||
|
<button id="rotate-left" class="btn">↺</button>
|
||||||
|
<button id="rotate-right" class="btn">↻</button>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -21,3 +21,60 @@ h1 {
|
|||||||
font-size: 75%;
|
font-size: 75%;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#game {
|
||||||
|
perspective: 2000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#board-viewer {
|
||||||
|
width: 82vmin;
|
||||||
|
height: 82vmin;
|
||||||
|
margin: auto;
|
||||||
|
position: relative;
|
||||||
|
transform: translateY(-10vmin) rotate3d(1, 0, 0, 55deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#board {
|
||||||
|
display: grid;
|
||||||
|
background: black;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 82vmin;
|
||||||
|
height: 82vmin;
|
||||||
|
grid-column-gap: 0.13rem;
|
||||||
|
grid-row-gap: 0.13rem;
|
||||||
|
padding: 0.52rem;
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
transform: rotate(0deg);
|
||||||
|
transition: transform 0.5s ease-in-out;
|
||||||
|
box-shadow: 0 0 40px 0 #00000061;
|
||||||
|
}
|
||||||
|
|
||||||
|
.square {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #b1b1b1;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.square[data-square_type="black"] {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.square[data-square_type="occupiable"][data-cost="2"][data-occupation_state="free"] {
|
||||||
|
background: rgba(255, 230, 190, 1);
|
||||||
|
}
|
||||||
|
.square[data-square_type="occupiable"][data-occluded="true"] {
|
||||||
|
filter: brightness(0.5);
|
||||||
|
}
|
||||||
|
.square[data-square_type="occupiable"][data-occupation_state="occupied"][data-occupied_by="0"] {
|
||||||
|
background: rgb(43, 131, 240);
|
||||||
|
}
|
||||||
|
.square[data-square_type="occupiable"][data-occupation_state="occupied"][data-occupied_by="1"] {
|
||||||
|
background: rgb(122, 215, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user