new board can be rectangular and rack length can be changed

This commit is contained in:
Laurent Mazet 2021-04-24 10:59:57 +02:00
parent d51ae94441
commit f817c0b5ab
6 changed files with 150 additions and 95 deletions

View File

@ -166,11 +166,11 @@ msgstr "Êtes-vous sûr·e de vouloir de changer la langue du plateau à '{0}' ?
msgid "Board language:" msgid "Board language:"
msgstr "Langue du plateau :" msgstr "Langue du plateau :"
msgid "You changed the board to {0}x{0} for language {1}" msgid "You changed the board to {0} for language {1}"
msgstr "Vous avez changé le plateau pour {0}x{0} en {1}" msgstr "Vous avez changé le plateau pour {0} en {1}"
msgid "{0} changed the board to {1}x{1} for language {2}" msgid "{0} changed the board to {1} for language {2}"
msgstr "{0} a changé le plateau pour {1}x{1} en {2}" msgstr "{0} a changé le plateau pour {1} en {2}"
msgid "Settings" msgid "Settings"
msgstr "Paramètres" msgstr "Paramètres"
@ -262,9 +262,10 @@ msgstr "Chronométrer la partie"
msgid "To measure playing time, activate the timer." msgid "To measure playing time, activate the timer."
msgstr "Pour mesurer les temps de jeu, activez le chronomètre." msgstr "Pour mesurer les temps de jeu, activez le chronomètre."
msgid "Board size:" msgid "Board label:"
msgstr "Taille du plateau" msgstr "Type du plateau"
msgid "Are you sure you want to change board to {0}x{0}? This will put all the tiles back in the bag and start another game."
msgstr "Êtes-vous sûr·e de vouloir de changer la taille du plateau à {0}x{0} ? Cela remettra toutes les lettres du jeu dans le sac et commencera une nouvelle partie."
msgid "Are you sure you want to change board to {0}? This will put all the tiles back in the bag and start another game."
msgstr "Êtes-vous sûr·e de vouloir de changer le type du plateau à {0} ? Cela remettra toutes les lettres du jeu dans le sac et commencera une nouvelle partie."
msgid "Can't find board '{0}'. Change board or start a new game."
msgstr "Impossible de trouver le plateau de type '{0}'. Changez de type de plateau ou démarrez une nouvelle partie."

View File

@ -172,10 +172,10 @@ msgstr ""
msgid "Board language:" msgid "Board language:"
msgstr "" msgstr ""
msgid "You changed the board to {0}x{0} for language {1}" msgid "You changed the board to {0} for language {1}"
msgstr "" msgstr ""
msgid "{0} changed the board to {1}x{1} for language {2}" msgid "{0} changed the board to {1} for language {2}"
msgstr "" msgstr ""
msgid "Settings" msgid "Settings"
@ -267,8 +267,11 @@ msgstr ""
msgid "To measure playing time, activate the timer." msgid "To measure playing time, activate the timer."
msgstr "" msgstr ""
msgid "Board size:" msgid "Board label:"
msgstr "" msgstr ""
msgid "Are you sure you want to change board to {0}x{0}? This will put all the tiles back in the bag and start another game." msgid "Are you sure you want to change board to {0}? This will put all the tiles back in the bag and start another game."
msgstr ""
msgid "Can't find board '{0}'. Change board or start a new game."
msgstr "" msgstr ""

View File

@ -1,5 +1,6 @@
window.BoardList = { window.BoardList = {
"8x8": { "8x8-7": {
factor: 0.25,
TW: [ TW: [
"A1", "A8", "A1", "A8",
"H1", "H8" "H1", "H8"
@ -27,14 +28,16 @@ window.BoardList = {
"D4" "D4"
] ]
}, },
"15x15": { "15x15-7": {
factor: 1,
TW: ["A1", "A8", "A15", "H1", "H15", "O1", "O8", "O15"], TW: ["A1", "A8", "A15", "H1", "H15", "O1", "O8", "O15"],
DW: ["B2", "B14", "C3", "C13", "D4", "D12", "E5", "E11", "K5", "K11", "L4", "L12", "M3", "M13", "N2", "N14"], DW: ["B2", "B14", "C3", "C13", "D4", "D12", "E5", "E11", "K5", "K11", "L4", "L12", "M3", "M13", "N2", "N14"],
TL: ["B6", "B10", "F2", "F6", "F10", "F14", "J2", "J6", "J10", "J14", "N6", "N10"], TL: ["B6", "B10", "F2", "F6", "F10", "F14", "J2", "J6", "J10", "J14", "N6", "N10"],
DL: ["A4", "A12", "C7", "C9", "D1", "D8", "D15", "G3", "G7", "G9", "G13", "H4", "H12", "I3", "I7", "I9", "I13", "L1", "L8", "L15", "M7", "M9", "O4", "O11"], DL: ["A4", "A12", "C7", "C9", "D1", "D8", "D15", "G3", "G7", "G9", "G13", "H4", "H12", "I3", "I7", "I9", "I13", "L1", "L8", "L15", "M7", "M9", "O4", "O11"],
CS: ["H8"] CS: ["H8"]
}, },
"22x22": { "22x22-7": {
factor: 2,
TW: [ TW: [
"A1", "A8", "A15", "A22", "A1", "A8", "A15", "A22",
"H1", "H8", "H15", "H22", "H1", "H8", "H15", "H22",

View File

@ -47,12 +47,10 @@
<option value="fr">French</option> <option value="fr">French</option>
</select> </select>
</p> </p>
<p id="board-size-selection"> <p id="board-label-selection" hidden="true">
<label for="board-size" data-l10n="text-content">Board size: </label> <label for="board-label" data-l10n="text-content">Board label: </label>
<select id="board-size"> <select id="board-label">
<option value="8">8x8</option> <option value="15x15-7">15x15-7</option>
<option value="15">15x15</option>
<option value="22">22x22</option>
</select> </select>
</p> </p>
</div> </div>

View File

@ -152,7 +152,7 @@
DisableSpellChecker: "boolean", DisableSpellChecker: "boolean",
GameNumber: "number", GameNumber: "number",
BoardLang: "string", BoardLang: "string",
BoardSize: "number", BoardLabel: "string",
Lang: "string", Lang: "string",
PlayerName: "string", PlayerName: "string",
Timer: "number", Timer: "number",
@ -180,7 +180,7 @@
let scoreOf; let scoreOf;
let bag; let bag;
let boardLangSelect; let boardLangSelect;
let boardSizeSelect; let boardLabelSelect;
const downloadedDictionaries = {}; const downloadedDictionaries = {};
const playerLetters = []; const playerLetters = [];
@ -234,13 +234,15 @@
} }
function setRack(rack) { function setRack(rack) {
for (let i = 0; i < 7; i++) { const rackLength = getBoardDimensions(getSetting("BoardLabel"))[2];
for (let i = 0; i < rackLength; i++) {
setTileParent(playerLetters[i], rack[i] || ""); setTileParent(playerLetters[i], rack[i] || "");
} }
} }
function getFreeRackSpaceIndex() { function getFreeRackSpaceIndex() {
for (let i = 0; i < 7; i++) { const rackLength = getBoardDimensions(getSetting("BoardLabel"))[2];
for (let i = 0; i < rackLength; i++) {
if (!playerLetters[i].getElementsByClassName("tile")[0]) { if (!playerLetters[i].getElementsByClassName("tile")[0]) {
return i; return i;
} }
@ -449,7 +451,8 @@
} }
} }
} else if (tileInitDest.getElementsByClassName("tile")[0]) { } else if (tileInitDest.getElementsByClassName("tile")[0]) {
for (let i = 0; i < 7; i++) { const rackLength = getBoardDimensions(getSetting("BoardLabel"))[2];
for (let i = 0; i < rackLength; i++) {
if (!playerLetters[i].getElementsByClassName("tile")[0]) { if (!playerLetters[i].getElementsByClassName("tile")[0]) {
playerLetters[i].appendChild(movingTile); playerLetters[i].appendChild(movingTile);
break; break;
@ -754,8 +757,17 @@
setTileParent(boardCells[index].getElementsByClassName("tile-placeholder")[0], letter, highlight); setTileParent(boardCells[index].getElementsByClassName("tile-placeholder")[0], letter, highlight);
} }
function getBoardDimensions(boardLabel) {
return (typeof boardLabel === "undefined") ? [] : boardLabel
.match(/[0-9]*/gu)
.filter(function (x) {return (x.length !== 0);})
.map(function (x) {return parseInt(x);});
}
function setBoard(board) { function setBoard(board) {
for (let i = 0; i < getSetting("BoardSize") * getSetting("BoardSize"); i++) { const [nbRows, nbColumns] = getBoardDimensions(getSetting("BoardLabel"));
for (let i = 0; i < nbRows * nbColumns; i++) {
setCell(i, board[i]); setCell(i, board[i]);
} }
} }
@ -775,9 +787,9 @@
setSetting("BoardLang", value); setSetting("BoardLang", value);
checkDictionaryExistance(value); checkDictionaryExistance(value);
break; break;
case "boardSize": case "boardLabel":
document.getElementById("board-size").value = value; document.getElementById("board-label").value = value;
setSetting("BoardSize", value); setSetting("BoardLabel", value);
initBoard(value); initBoard(value);
break; break;
} }
@ -914,11 +926,11 @@
case "changeBoardDef": { case "changeBoardDef": {
const newLang = boardLangSelect.querySelector("[value=" + msg.specialMsg.newBoardLang + "]").textContent; const newLang = boardLangSelect.querySelector("[value=" + msg.specialMsg.newBoardLang + "]").textContent;
const newSize = msg.specialMsg.newBoardSize; const newLabel = msg.specialMsg.newBoardLabel;
infoMessage( infoMessage(
(msg.sender === getSetting("PlayerName")) (msg.sender === getSetting("PlayerName"))
? format(_("You changed the board to {0}x{0} for language {1}"), newSize, newLang) ? format(_("You changed the board to {0} for language {1}"), newLabel, newLang)
: format(_("{0} changed the board to {1}x{1} for language {2}"), msg.sender, newSize, newLang) : format(_("{0} changed the board to {1} for language {2}"), msg.sender, newLabel, newLang)
); );
break; break;
} }
@ -1220,9 +1232,9 @@
(boardLangSelect || {}).value = data.boardLang; (boardLangSelect || {}).value = data.boardLang;
} }
if (data.boardSize) { if (data.boardLabel) {
set("boardSize", Number(data.boardSize)); set("boardLabel", data.boardLabel);
(boardSizeSelect || {}).value = data.boardSize; (boardLabelSelect || {}).value = data.boardLabel;
} }
if (data.letterValues) { if (data.letterValues) {
@ -1513,7 +1525,7 @@
gameNumber: getSetting("GameNumber") || "", gameNumber: getSetting("GameNumber") || "",
playerName: getSetting("PlayerName"), playerName: getSetting("PlayerName"),
boardLang: getSetting("BoardLang"), boardLang: getSetting("BoardLang"),
boardSize: getSetting("BoardSize"), boardLabel: getSetting("BoardLabel"),
version: VERSION, version: VERSION,
cmds: cmds cmds: cmds
}; };
@ -1655,7 +1667,7 @@
myConfirm( myConfirm(
format(_("Are you sure you want to change board to '{0}'? This will put all the tiles back in the bag and start another game."), _(lang)), format(_("Are you sure you want to change board to '{0}'? This will put all the tiles back in the bag and start another game."), _(lang)),
function () { function () {
sendCmds([{cmd: "changeBoard", lang: code, size: getSetting("BoardSize")}]); sendCmds([{cmd: "changeBoard", lang: code, label: getSetting("BoardLabel")}]);
}, },
function () { function () {
boardLangSelect.value = getSetting("BoardLang"); boardLangSelect.value = getSetting("BoardLang");
@ -1663,16 +1675,16 @@
); );
} }
function onChangeBoardSize() { function onChangeBoardLabel() {
const size = document.getElementById("board-size").value; const label = document.getElementById("board-label").value;
myConfirm( myConfirm(
format(_("Are you sure you want to change board to {0}x{0}? This will put all the tiles back in the bag and start another game."), size), format(_("Are you sure you want to change board to {0}? This will put all the tiles back in the bag and start another game."), label),
function () { function () {
sendCmds([{cmd: "changeBoard", lang: getSetting("BoardLang"), size: size}]); sendCmds([{cmd: "changeBoard", lang: getSetting("BoardLang"), label: label}]);
}, },
function () { function () {
boardSizeSelect.value = getSetting("BoardLang"); boardLabelSelect.value = getSetting("BoardLabel");
} }
); );
} }
@ -1739,11 +1751,13 @@
} }
function getLetterFromBoard(row, col) { function getLetterFromBoard(row, col) {
if ((row < 0) || (row >= getSetting("BoardSize")) || (col < 0) || (col >= getSetting("BoardSize"))) { const [nbRows, nbColumns] = getBoardDimensions(getSetting("BoardLabel"));
if ((row < 0) || (row >= nbRows) || (col < 0) || (col >= nbColumns)) {
return ""; return "";
} }
try { try {
const index = (row * getSetting("BoardSize")) + col; const index = (row * nbColumns) + col;
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0]; const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
const tile = tilePlaceholder.getElementsByClassName("tile")[0]; const tile = tilePlaceholder.getElementsByClassName("tile")[0];
return tile.firstChild.textContent; return tile.firstChild.textContent;
@ -1789,13 +1803,14 @@
} }
function searchNewWords() { function searchNewWords() {
const nbColumns = getBoardDimensions(getSetting("BoardLabel"))[1];
const words = []; const words = [];
for (const i of Object.keys(currentTilePlayed)) { for (const i of Object.keys(currentTilePlayed)) {
/* Get board position */ /* Get board position */
const row = Math.floor(i / getSetting("BoardSize")); const row = Math.floor(i / nbColumns);
const col = i % getSetting("BoardSize"); const col = i % nbColumns;
/* Look for word in column */ /* Look for word in column */
const newWordInCol = searchWordInLine(row, col, 1, 0); const newWordInCol = searchWordInLine(row, col, 1, 0);
@ -1821,6 +1836,7 @@
} }
function modifyTileClass(word, value, action) { function modifyTileClass(word, value, action) {
const [nbRows, nbColumns] = getBoardDimensions(getSetting("BoardLabel"));
/* action: true for add, false for remove */ /* action: true for add, false for remove */
@ -1828,7 +1844,7 @@
/* only for new words */ /* only for new words */
for (let l = 0; l < word.letters.length; l++) { for (let l = 0; l < word.letters.length; l++) {
const index = ((word.row + (l * word.incRow)) * getSetting("BoardSize")) + word.col + (l * word.incCol); const index = ((word.row + (l * word.incRow)) * nbColumns) + word.col + (l * word.incCol);
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0]; const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
const tile = tilePlaceholder.getElementsByClassName("tile")[0]; const tile = tilePlaceholder.getElementsByClassName("tile")[0];
@ -1838,7 +1854,7 @@
} else { } else {
/* tiles on board */ /* tiles on board */
for (let index = 0; index < getSetting("BoardSize") * getSetting("BoardSize"); index++) { for (let index = 0; index < nbRows * nbColumns; index++) {
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0]; const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
const tile = tilePlaceholder.getElementsByClassName("tile")[0]; const tile = tilePlaceholder.getElementsByClassName("tile")[0];
if (typeof tile !== "undefined") { if (typeof tile !== "undefined") {
@ -1919,6 +1935,7 @@
} }
function scoreWords() { function scoreWords() {
const [nbColumns, rackLength] = getBoardDimensions(getSetting("BoardLabel")).slice(1);
let totalScore = 0; let totalScore = 0;
const newWords = searchNewWords(); const newWords = searchNewWords();
@ -1928,7 +1945,7 @@
const word = newWords[k]; const word = newWords[k];
for (let l = 0; l < word.letters.length; l++) { for (let l = 0; l < word.letters.length; l++) {
const index = ((word.row + (l * word.incRow)) * getSetting("BoardSize")) + word.col + (l * word.incCol); const index = ((word.row + (l * word.incRow)) * nbColumns) + word.col + (l * word.incCol);
/* Letter score */ /* Letter score */
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0]; const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
@ -1967,7 +1984,7 @@
} }
/* Check for trivabble (the premium score) */ /* Check for trivabble (the premium score) */
if (Object.keys(currentTilePlayed).length === 7) { if (Object.keys(currentTilePlayed).length === rackLength) {
totalScore += getSetting("PREMIUM_SEVEN_TILES"); totalScore += getSetting("PREMIUM_SEVEN_TILES");
} }
@ -2001,7 +2018,8 @@
return; return;
} }
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const nbColumns = getBoardDimensions(getSetting("BoardLabel"))[1];
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const col = cell.cellIndex - 1; const col = cell.cellIndex - 1;
const row = getRowIndex(cell.parentNode) - 1; const row = getRowIndex(cell.parentNode) - 1;
@ -2010,7 +2028,7 @@
msg: _("Look at:") + " " + letters[row] + (cell.cellIndex + 1), msg: _("Look at:") + " " + letters[row] + (cell.cellIndex + 1),
specialMsg: { specialMsg: {
type: "highlightCell", type: "highlightCell",
cell: (row * getSetting("BoardSize")) + col cell: (row * nbColumns) + col
} }
}]); }]);
} }
@ -2412,7 +2430,7 @@
chatMessages = document.getElementById("chat-messages"); chatMessages = document.getElementById("chat-messages");
chatTextarea = document.getElementById("chat-ta"); chatTextarea = document.getElementById("chat-ta");
participantPlaceholder = document.getElementById("participants-placeholder"); participantPlaceholder = document.getElementById("participants-placeholder");
boardSizeSelect = document.getElementById("board-size"); boardLabelSelect = document.getElementById("board-label");
} }
function initEvents() { function initEvents() {
@ -2420,7 +2438,7 @@
document.getElementById("clear-game").onclick = clearGame; document.getElementById("clear-game").onclick = clearGame;
document.getElementById("board-lang").onchange = onChangeBoardLang; document.getElementById("board-lang").onchange = onChangeBoardLang;
document.getElementById("board-size").onchange = onChangeBoardSize; document.getElementById("board-label").onchange = onChangeBoardLabel;
document.getElementById("change-name").onclick = changeName; document.getElementById("change-name").onclick = changeName;
document.getElementById("join-game").onclick = joinGame; document.getElementById("join-game").onclick = joinGame;
document.getElementById("clear-rack").onclick = clearRack; document.getElementById("clear-rack").onclick = clearRack;
@ -2453,15 +2471,17 @@
return; return;
} }
name.textContent = getSetting("PlayerName"); if (Object.keys(BoardList).length > 1) {
boardLabelSelect.textContent = "";
for (let i = 0; i < 7; i++) { for (const key of Object.keys(BoardList)) {
const span = document.createElement("span"); boardLabelSelect.add(new Option(key, key));
span.className = "tile-placeholder"; }
rack.appendChild(span);
playerLetters.push(span); document.getElementById("board-label-selection").hidden = false;
} }
name.textContent = getSetting("PlayerName");
if (getSetting("GameNumber")) { if (getSetting("GameNumber")) {
document.getElementById("number").textContent = getSetting("GameNumber"); document.getElementById("number").textContent = getSetting("GameNumber");
@ -2471,33 +2491,42 @@
document.getElementById("board-lang").value = getSetting("BoardLang"); document.getElementById("board-lang").value = getSetting("BoardLang");
} }
if (getSetting("BoardSize")) { if (getSetting("BoardLabel")) {
document.getElementById("board-size").value = getSetting("BoardSize"); document.getElementById("board-label").value = getSetting("BoardLabel");
} }
startGame(getSetting("GameNumber")); startGame(getSetting("GameNumber"));
} }
function initBoard(boardSize) { function initBoard(boardLabel) {
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const boardDef = BoardList[boardSize + "x" + boardSize]; if (Object.keys(BoardList).indexOf(boardLabel) === -1) {
myAlert("Can't find board '" + boardLabel + "'. Change board or start a new game.");
return;
}
const boardDef = BoardList[boardLabel];
const [nbRows, nbColumns, rackLength] = getBoardDimensions(boardLabel);
let cell; let cell;
let row; let row;
board.innerHTML = "<tr><td class=\"corner\"></td></tr>"; board.innerHTML = "<tr><td class=\"corner\"></td></tr>";
for (let i = 0; i < boardSize; i++) { for (let j = 0; j < nbColumns; j++) {
board.rows[0].appendChild(document.createElement("th")); board.rows[0].appendChild(document.createElement("th"));
board.rows[0].lastChild.textContent = i + 1; board.rows[0].lastChild.textContent = j + 1;
}
for (let i = 0; i < nbRows; i++) {
row = board.insertRow(-1); row = board.insertRow(-1);
row.appendChild(document.createElement("th")); row.appendChild(document.createElement("th"));
row.lastChild.textContent = letters[i]; row.lastChild.textContent = letters[i];
for (let j = 0; j < boardSize; j++) { for (let j = 0; j < nbColumns; j++) {
cell = document.createElement("td"); cell = document.createElement("td");
boardCells.push(cell); boardCells.push(cell);
row.appendChild(cell); row.appendChild(cell);
@ -2531,12 +2560,23 @@
row = board.insertRow(-1); row = board.insertRow(-1);
row.appendChild(board.rows[0].cells[0].cloneNode(false)); row.appendChild(board.rows[0].cells[0].cloneNode(false));
for (let i = 0; i < boardSize; i++) { for (let i = 0; i < nbColumns; i++) {
row.appendChild(document.createElement("th")); row.appendChild(document.createElement("th"));
row.lastChild.textContent = i + 1; row.lastChild.textContent = i + 1;
} }
row.appendChild(board.rows[0].cells[0].cloneNode(false)); row.appendChild(board.rows[0].cells[0].cloneNode(false));
rack.innerHTML = "";
playerLetters.length = 0;
for (let i = 0; i < rackLength; i++) {
const span = document.createElement("span");
span.className = "tile-placeholder";
rack.appendChild(span);
playerLetters.push(span);
}
} }
function initLang() { function initLang() {

View File

@ -35,7 +35,7 @@ const SAVE_TIMEOUT = 5000;
const KEEP_ALIVE = 30000; const KEEP_ALIVE = 30000;
const GAMES_BACKUP = process.env.TRIVABBLE_GAMES_BACKUP || "games.backup.json"; const GAMES_BACKUP = process.env.TRIVABBLE_GAMES_BACKUP || "games.backup.json";
const DEFAULT_BOARD_LANG = process.env.TRIVABBLE_DEFAULT_BOARD_LANG || "fr"; const DEFAULT_BOARD_LANG = process.env.TRIVABBLE_DEFAULT_BOARD_LANG || "fr";
const DEFAULT_BOARD_SIZE = process.env.TRIVABBLE_DEFAULT_BOARD_SIZE || 15; const DEFAULT_BOARD_LABEL = process.env.TRIVABBLE_DEFAULT_BOARD_LABEL || "15x15-7";
const VERSION = 202005070100; const VERSION = 202005070100;
@ -207,19 +207,28 @@ function keepAlive(responseAndType) {
}, KEEP_ALIVE); }, KEEP_ALIVE);
} }
function newBoard(size) { function getBoardDimensions(boardLabel) {
const res = new Array(size * size); return boardLabel
.match(/[0-9]*/gu)
.filter(function (x) {return (x.length !== 0);})
.map(function (x) {return parseInt(x);});
}
for (let i = 0; i < size * size; i++) { function newBoard(label) {
const [nbRows, nbColumns] = getBoardDimensions(label);
const res = new Array(nbRows * nbColumns);
for (let i = 0; i < nbRows * nbColumns; i++) {
res[i] = ""; res[i] = "";
} }
return res; return res;
} }
Game.prototype.init = function (lang, size) { Game.prototype.init = function (lang, label) {
this.size = size || DEFAULT_BOARD_SIZE; this.label = label || DEFAULT_BOARD_LABEL;
this.board = newBoard(this.size); this.board = newBoard(this.label);
this.lang = lang || DEFAULT_BOARD_LANG; this.lang = lang || DEFAULT_BOARD_LANG;
this.bag = boardTilesPerLang[this.lang].bag.slice(); this.bag = boardTilesPerLang[this.lang].bag.slice();
this.letterValues = boardTilesPerLang[this.lang].letterValues; this.letterValues = boardTilesPerLang[this.lang].letterValues;
@ -235,7 +244,7 @@ Game.prototype.toJSON = function () {
return { return {
board: this.board, board: this.board,
lang: this.lang, lang: this.lang,
size: this.size, label: this.label,
bag: this.bag, bag: this.bag,
letterValues: this.letterValues, letterValues: this.letterValues,
racks: this.racks, racks: this.racks,
@ -247,8 +256,8 @@ Game.prototype.toJSON = function () {
Game.fromJSON = function (obj) { Game.fromJSON = function (obj) {
const game = new Game(); const game = new Game();
game.size = obj.size || DEFAULT_BOARD_SIZE; game.label = obj.label || DEFAULT_BOARD_LABEL;
game.board = obj.board || newBoard(game.size); game.board = obj.board || newBoard(game.label);
game.lang = obj.lang || DEFAULT_BOARD_LANG; game.lang = obj.lang || DEFAULT_BOARD_LANG;
game.bag = boardTilesPerLang[game.lang].bag.slice(); game.bag = boardTilesPerLang[game.lang].bag.slice();
game.letterValues = boardTilesPerLang[game.lang].letterValues; game.letterValues = boardTilesPerLang[game.lang].letterValues;
@ -406,12 +415,12 @@ Game.prototype.bagPushLetter = function (letter, player) {
}; };
Game.prototype.reset = function (player) { Game.prototype.reset = function (player) {
this.init(this.lang, this.size); this.init(this.lang, this.label);
this.pendingEvents.push({ this.pendingEvents.push({
player: player, player: player,
action: "reset", action: "reset",
board: this.board, board: this.board,
size: this.size, label: this.label,
remainingLetters: this.bag.length, remainingLetters: this.bag.length,
rack: [] rack: []
}); });
@ -476,6 +485,7 @@ function handleCommand(cmdNumber, message, response) {
game.lastUpdated = new Date(); game.lastUpdated = new Date();
const playerName = message.playerName; const playerName = message.playerName;
const [nbRows, nbColumns, rackLength] = getBoardDimensions(game.label);
let rack = null; let rack = null;
const cmd = message.cmds[cmdNumber]; const cmd = message.cmds[cmdNumber];
@ -488,7 +498,7 @@ function handleCommand(cmdNumber, message, response) {
gameNumber: gameNumber, gameNumber: gameNumber,
playerName: playerName, playerName: playerName,
boardLang: game.lang, boardLang: game.lang,
boardSize: game.size, boardLabel: game.label,
availableBoardLangs: availableBoardLangs, availableBoardLangs: availableBoardLangs,
currentPlayer: game.currentPlayer, currentPlayer: game.currentPlayer,
rack: game.getPlayerRack(playerName), rack: game.getPlayerRack(playerName),
@ -502,7 +512,7 @@ function handleCommand(cmdNumber, message, response) {
case "hello": { case "hello": {
game.playerJoined(playerName); game.playerJoined(playerName);
reply(message, response, cmdNumber, {error: 0, boardLang: game.lang, boardSize: game.size, version: VERSION}); reply(message, response, cmdNumber, {error: 0, boardLang: game.lang, boardLabel: game.label, version: VERSION});
break; break;
} }
@ -548,7 +558,7 @@ function handleCommand(cmdNumber, message, response) {
break; break;
case "board": case "board":
if (cmd.indexFrom < 0 || cmd.indexFrom >= game.size * game.size) { if (cmd.indexFrom < 0 || cmd.indexFrom >= nbRows * nbColumns) {
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexFrom"}); reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexFrom"});
return false; return false;
} }
@ -593,7 +603,7 @@ function handleCommand(cmdNumber, message, response) {
break; break;
case "board": case "board":
if (cmd.indexTo < 0 || cmd.indexTo >= game.size * game.size) { if (cmd.indexTo < 0 || cmd.indexTo >= nbRows * nbColumns) {
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexTo"}); reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexTo"});
return false; return false;
} }
@ -636,7 +646,7 @@ function handleCommand(cmdNumber, message, response) {
} }
case "setRack": { case "setRack": {
if (cmd.rack.length > 7) { if (cmd.rack.length > rackLength) {
reply(message, response, cmdNumber, { reply(message, response, cmdNumber, {
error: 1, error: 1,
rack: rack, rack: rack,
@ -653,7 +663,7 @@ function handleCommand(cmdNumber, message, response) {
const newRackSorted = cmd.rack.filter((l) => l); const newRackSorted = cmd.rack.filter((l) => l);
newRackSorted.sort(); newRackSorted.sort();
for (let i = 0; i < 7; i++) { for (let i = 0; i < rackLength; i++) {
if ((oldRackSorted[i] !== newRackSorted[i]) && (oldRackSorted[i] || newRackSorted[i])) { if ((oldRackSorted[i] !== newRackSorted[i]) && (oldRackSorted[i] || newRackSorted[i])) {
reply(message, response, cmdNumber, { reply(message, response, cmdNumber, {
error: 1, error: 1,
@ -664,7 +674,7 @@ function handleCommand(cmdNumber, message, response) {
} }
} }
for (let i = 0; i < 7; i++) { for (let i = 0; i < rackLength; i++) {
rack[i] = cmd.rack[i]; rack[i] = cmd.rack[i];
} }
@ -681,24 +691,24 @@ function handleCommand(cmdNumber, message, response) {
case "changeBoard": { case "changeBoard": {
game.lang = cmd.lang || DEFAULT_BOARD_LANG; game.lang = cmd.lang || DEFAULT_BOARD_LANG;
game.size = cmd.size || DEFAULT_BOARD_SIZE; game.label = cmd.label || DEFAULT_BOARD_LABEL;
game.reset(); game.reset();
reply(message, response, cmdNumber, { reply(message, response, cmdNumber, {
error: 0, error: 0,
boardLang: game.lang, boardLang: game.lang,
boardSize: game.size, boardLabel: game.label,
letterValues: game.letterValues letterValues: game.letterValues
}); });
game.pendingEvents.push({ game.pendingEvents.push({
msg: { msg: {
sender: playerName, sender: playerName,
content: "I changed the board to " + game.size + "x" + game.size + " in language " + game.lang, content: "I changed the board to " + game.label + " in language " + game.lang,
specialMsg: { specialMsg: {
type: "changeBoardDef", type: "changeBoardDef",
newBoardLang: game.lang, newBoardLang: game.lang,
newBoardSize: game.size newBoardLabel: game.label
} }
} }
}); });
@ -739,7 +749,7 @@ function handleCommands(message, responseAndType) {
currentPlayer: game.currentPlayer, currentPlayer: game.currentPlayer,
gameNumber: gameNumber, gameNumber: gameNumber,
boardLang: game.lang, boardLang: game.lang,
boardSize: game.size, boardLabel: game.label,
availableBoardLangs: availableBoardLangs, availableBoardLangs: availableBoardLangs,
letterValues: game.letterValues, letterValues: game.letterValues,
rack: game.getPlayerRack(message.playerName), rack: game.getPlayerRack(message.playerName),