${style}`;
}
@@ -174,12 +191,17 @@ function getGameLink() {
const vname = $.getElementById("selectVariant").value;
const color = $.getElementById("selectColor").value;
for (const select of $.querySelectorAll("#gameOptions select")) {
- let value = select.value;
- if (select.attributes["data-numeric"]) value = parseInt(value, 10);
- if (value) options[ select.id.split("_")[1] ] = value;
+ let value = parseInt(select.value, 10);
+ if (isNaN(value)) //not an integer
+ value = select.value;
+ options[ select.id.split("_")[1] ] = value;
}
- for (const check of $.querySelectorAll("#gameOptions input")) {
- if (check.checked) options[ check.id.split("_")[1] ] = check.checked;
+ for (const input of $.querySelectorAll("#gameOptions input")) {
+ const variable = input.id.split("_")[1];
+ if (input.type == "number")
+ options[variable] = parseInt(input.value, 10); //TODO: real numbers?
+ else if (input.type == "checkbox")
+ options[variable] = input.checked;
}
send("creategame", {
vname: vname,
@@ -206,9 +228,11 @@ function fillGameInfos(gameInfos, oppIndex) {
while (i < options.length) {
htmlContent += '';
for (let j=i; j' +
(opt[1] === true ? opt[0] : `${opt[0]}:${opt[1]}`) + " " +
@@ -241,7 +265,8 @@ function send(code, data, opts) {
const trySend = () => {
if (socket.readyState == 1) {
socket.send(JSON.stringify(Object.assign({code: code}, data)));
- if (opts.success) opts.success();
+ if (opts.success)
+ opts.success();
return true;
}
return false;
@@ -253,13 +278,16 @@ function send(code, data, opts) {
let sendAttempt = 1;
const retryLoop = setInterval(
() => {
- if (trySend() || ++sendAttempt >= 3) clearInterval(retryLoop);
- if (sendAttempt >= 3 && opts.error) opts.error();
+ if (trySend() || ++sendAttempt >= 3)
+ clearInterval(retryLoop);
+ if (sendAttempt >= 3 && opts.error)
+ opts.error();
},
1000
);
}
- else if (opt.error) opts.error();
+ else if (opts.error)
+ opts.error();
}
return firstTry;
}
@@ -306,7 +334,8 @@ const messageCenter = (msg) => {
switch (obj.code) {
// Start new game:
case "gamestart": {
- if (document.hidden) notifyMe("game");
+ if (document.hidden)
+ notifyMe("game");
gid = obj.gid;
initializeGame(obj);
break;
@@ -339,14 +368,17 @@ const messageCenter = (msg) => {
// Receive opponent's move:
case "newmove":
// Basic check: was it really opponent's turn?
- if (vr.turn == playerColor) break;
- if (document.hidden) notifyMe("move");
+ if (vr.turn == playerColor)
+ break;
+ if (document.hidden)
+ notifyMe("move");
vr.playReceivedMove(obj.moves, () => {
if (vr.getCurrentScore(obj.moves[obj.moves.length-1]) != "*") {
localStorage.removeItem("gid");
setTimeout( () => toggleVisible("gameStopped"), 2000 );
}
- else toggleTurnIndicator(true);
+ else
+ toggleTurnIndicator(true);
});
break;
// Opponent stopped game (draw, abort, resign...)
@@ -400,8 +432,10 @@ connectToWSS();
function toggleTurnIndicator(myTurn) {
let indicator =
$.getElementById("boardContainer").querySelector(".chessboard");
- if (myTurn) indicator.style.outline = "thick solid green";
- else indicator.style.outline = "thick solid lightgrey";
+ if (myTurn)
+ indicator.style.outline = "thick solid green";
+ else
+ indicator.style.outline = "thick solid lightgrey";
}
function notifyMe(code) {
@@ -410,55 +444,66 @@ function notifyMe(code) {
new Notification("New " + code, { vibrate: [200, 100, 200] });
new Audio("/assets/new_" + code + ".mp3").play();
}
- if (Notification.permission === "granted") doNotify();
+ if (Notification.permission === "granted")
+ doNotify();
else if (Notification.permission !== "denied") {
Notification.requestPermission().then(permission => {
- if (permission === "granted") doNotify();
+ if (permission === "granted")
+ doNotify();
});
}
}
let curMoves = [],
lastFen;
-const afterPlay = (move) => {
- const callbackAfterSend = () => {
- curMoves = [];
- const result = vr.getCurrentScore(move);
+const afterPlay = (move_s, newTurn, ops) => {
+ if (ops.send) {
+ // Pack into one moves array, then send (if turn changed)
+ if (Array.isArray(move_s))
+ // Array of simple moves (e.g. Chakart)
+ Array.prototype.push.apply(curMoves, move_s);
+ else
+ // Usual case
+ curMoves.push(move_s);
+ if (newTurn != playerColor) {
+ send("newmove",
+ {gid: gid, moves: curMoves, fen: vr.getFen()},
+ {
+ retry: true,
+ success: () => curMoves = [],
+ error: () => alert("Move not sent: reload page")
+ }
+ );
+ }
+ }
+ if (ops.res && newTurn != playerColor) {
+ toggleTurnIndicator(false); //now all moves are sent and animated
+ const result = vr.getCurrentScore(move_s);
if (result != "*") {
setTimeout(() => {
toggleVisible("gameStopped");
send("gameover", {gid: gid});
}, 2000);
}
- };
- // Pack into one moves array, then send
- curMoves.push(move);
- if (vr.turn != playerColor) {
- toggleTurnIndicator(false);
- send("newmove",
- {gid: gid, moves: curMoves, fen: vr.getFen()},
- {
- retry: true,
- success: callbackAfterSend,
- error: () => alert("Move not sent: reload page")
- });
}
};
-let vr, playerColor;
+let vr = null, playerColor, lastVname = undefined;
function initializeGame(obj) {
const options = obj.options || {};
import(`/variants/${obj.vname}/class.js`).then(module => {
window.V = module.default;
- for (const [k, v] of Object.entries(V.Aliases)) window[k] = v;
- // Load CSS. Avoid loading twice the same stylesheet:
- const allIds = [].slice.call($.styleSheets).map(s => s.id);
- const newId = obj.vname + "_css";
- if (!allIds.includes(newId)) {
+ for (const [k, v] of Object.entries(V.Aliases))
+ window[k] = v;
+ if (lastVname != obj.vname) {
+ // Load CSS + unload potential previous one.
+ if (lastVname)
+ document.getElementById(lastVname + "_css").remove();
$.getElementsByTagName("head")[0].insertAdjacentHTML(
"beforeend",
- ``);
+ lastVname = obj.vname;
}
playerColor = (sid == obj.players[0].sid ? "w" : "b");
// Init + remove potential extra DOM elements from a previous game:
@@ -481,7 +526,10 @@ function initializeGame(obj) {
- `;
+ `;
+ if (vr)
+ // Avoid interferences:
+ vr.removeListeners();
vr = new V({
seed: obj.seed, //may be null if FEN already exists (running game)
fen: obj.fen,
@@ -490,8 +538,9 @@ function initializeGame(obj) {
afterPlay: afterPlay,
options: options
});
- if (!obj.fen) {
- // Game creation: both players set FEN, in case of one is offline
+ const gameCreation = !obj.fen;
+ if (gameCreation) {
+ // Both players set FEN, in case of one is offline
send("setfen", {gid: obj.gid, fen: vr.getFen()});
localStorage.setItem("gid", obj.gid);
}
@@ -503,9 +552,12 @@ function initializeGame(obj) {
break;
}
}
- fillGameInfos(obj, playerColor == "w" ? 1 : 0);
- if (obj.randvar) toggleVisible("gameInfos");
- else toggleVisible("boardContainer");
+ const playerIndex = (playerColor == "w" ? 0 : 1);
+ fillGameInfos(obj, 1 - playerIndex);
+ if (obj.players[playerIndex].randvar && gameCreation)
+ toggleVisible("gameInfos");
+ else
+ toggleVisible("boardContainer");
toggleTurnIndicator(vr.turn == playerColor);
});
}
@@ -520,12 +572,15 @@ function confirmStopGame() {
function toggleGameInfos() {
if ($.getElementById("gameInfos").style.display == "none")
toggleVisible("gameInfos");
- else toggleVisible("boardContainer");
+ else
+ toggleVisible("boardContainer");
}
$.body.addEventListener("keydown", (e) => {
- if (!localStorage.getItem("gid")) return;
- if (e.keyCode == 27) confirmStopGame();
+ if (!localStorage.getItem("gid"))
+ return;
+ if (e.keyCode == 27)
+ confirmStopGame();
else if (e.keyCode == 32) {
e.preventDefault();
toggleGameInfos();