new board can be rectangular and rack length can be changed
authorLaurent Mazet <mazet@softndesign.org>
Sat, 24 Apr 2021 08:59:57 +0000 (10:59 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Sat, 24 Apr 2021 08:59:57 +0000 (10:59 +0200)
l10n/po/fr/trivabble.po
l10n/pot/trivabble.pot
public/boards.js
public/index.html
public/trivabble.js
server/trivabble-server.js

index b8114cea5db2d033238eb909b48de2fde7c75a10..a626f2070fe86a261380ad528545060570554482 100644 (file)
@@ -166,11 +166,11 @@ msgstr "Êtes-vous sûr·e de vouloir de changer la langue du plateau à '{0}' ?
 msgid  "Board language:"
 msgstr "Langue du plateau :"
 
-msgid  "You changed the board to {0}x{0} for language {1}"
-msgstr "Vous avez changé le plateau pour {0}x{0} en {1}"
+msgid  "You changed the board to {0} for language {1}"
+msgstr "Vous avez changé le plateau pour {0} en {1}"
 
-msgid  "{0} changed the board to {1}x{1} for language {2}"
-msgstr "{0} a changé le plateau pour {1}x{1} en {2}"
+msgid  "{0} changed the board to {1} for language {2}"
+msgstr "{0} a changé le plateau pour {1} en {2}"
 
 msgid  "Settings"
 msgstr "Paramètres"
@@ -262,9 +262,10 @@ msgstr "Chronométrer la partie"
 msgid  "To measure playing time, activate the timer."
 msgstr "Pour mesurer les temps de jeu, activez le chronomètre."
 
-msgid  "Board size:"
-msgstr "Taille 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  "Board label:"
+msgstr "Type du plateau"
 
+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."
index 4714921176bdd958fb6c366ee70fe8b1b957e8e3..a2b2f2b44ef68eafeb87e7e725bd3eb8c29c6df9 100644 (file)
@@ -172,10 +172,10 @@ msgstr ""
 msgid  "Board language:"
 msgstr ""
 
-msgid  "You changed the board to {0}x{0} for language {1}"
+msgid  "You changed the board to {0} for language {1}"
 msgstr ""
 
-msgid  "{0} changed the board to {1}x{1} for language {2}"
+msgid  "{0} changed the board to {1} for language {2}"
 msgstr ""
 
 msgid  "Settings"
@@ -267,8 +267,11 @@ msgstr ""
 msgid  "To measure playing time, activate the timer."
 msgstr ""
 
-msgid  "Board size:"
+msgid  "Board label:"
 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 ""
index 0eb4ac8ec16239fd961d0a4b903322cc071f2161..62dad8310be4b138e06ea366e4b24026ea9198f2 100644 (file)
@@ -1,5 +1,6 @@
 window.BoardList = {
-    "8x8":  {
+    "8x8-7":  {
+        factor: 0.25,
         TW: [
             "A1", "A8",
             "H1", "H8"
@@ -27,14 +28,16 @@ window.BoardList = {
             "D4"
         ]
     },
-    "15x15": {
+    "15x15-7": {
+        factor: 1,
         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"],
         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"],
         CS: ["H8"]
     },
-    "22x22": {
+    "22x22-7": {
+        factor: 2,
         TW: [
             "A1", "A8", "A15", "A22",
             "H1", "H8", "H15", "H22",
index 6d4244e3a4dfbb93a029a998f850adb1e4234b70..6ba07e0f5bf7e5b9fb8bed40512dae7379a90134 100644 (file)
                         <option value="fr">French</option>
                     </select>
                 </p>
-                <p id="board-size-selection">
-                    <label for="board-size" data-l10n="text-content">Board size: </label>
-                    <select id="board-size">
-                        <option value="8">8x8</option>
-                        <option value="15">15x15</option>
-                        <option value="22">22x22</option>
+                <p id="board-label-selection" hidden="true">
+                    <label for="board-label" data-l10n="text-content">Board label: </label>
+                    <select id="board-label">
+                        <option value="15x15-7">15x15-7</option>
                     </select>
                 </p>
             </div>
index c849d883ebc11151cfe565e4b39cc5d47834bc2c..53125e53688899001260b4bd9d418884de57b1ac 100644 (file)
         DisableSpellChecker: "boolean",
         GameNumber: "number",
         BoardLang: "string",
-        BoardSize: "number",
+        BoardLabel: "string",
         Lang: "string",
         PlayerName: "string",
         Timer: "number",
     let scoreOf;
     let bag;
     let boardLangSelect;
-    let boardSizeSelect;
+    let boardLabelSelect;
     const downloadedDictionaries = {};
 
     const playerLetters = [];
     }
 
     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] || "");
         }
     }
 
     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]) {
                 return i;
             }
                 }
             }
         } 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]) {
                     playerLetters[i].appendChild(movingTile);
                     break;
         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) {
-        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]);
         }
     }
                 setSetting("BoardLang", value);
                 checkDictionaryExistance(value);
                 break;
-            case "boardSize":
-                document.getElementById("board-size").value = value;
-                setSetting("BoardSize", value);
+            case "boardLabel":
+                document.getElementById("board-label").value = value;
+                setSetting("BoardLabel", value);
                 initBoard(value);
                 break;
         }
 
                 case "changeBoardDef": {
                     const newLang = boardLangSelect.querySelector("[value=" + msg.specialMsg.newBoardLang + "]").textContent;
-                    const newSize = msg.specialMsg.newBoardSize;
+                    const newLabel = msg.specialMsg.newBoardLabel;
                     infoMessage(
                         (msg.sender === getSetting("PlayerName"))
-                            ? format(_("You changed the board to {0}x{0} for language {1}"), newSize, newLang)
-                            : format(_("{0} changed the board to {1}x{1} for language {2}"), msg.sender, newSize, newLang)
+                            ? format(_("You changed the board to {0} for language {1}"), newLabel, newLang)
+                            : format(_("{0} changed the board to {1} for language {2}"), msg.sender, newLabel, newLang)
                     );
                     break;
                 }
             (boardLangSelect || {}).value = data.boardLang;
         }
         
-        if (data.boardSize) {
-            set("boardSize", Number(data.boardSize));
-            (boardSizeSelect || {}).value = data.boardSize;
+        if (data.boardLabel) {
+            set("boardLabel", data.boardLabel);
+            (boardLabelSelect || {}).value = data.boardLabel;
         }
 
         if (data.letterValues) {
             gameNumber: getSetting("GameNumber") || "",
             playerName: getSetting("PlayerName"),
             boardLang: getSetting("BoardLang"),
-            boardSize: getSetting("BoardSize"),
+            boardLabel: getSetting("BoardLabel"),
             version: VERSION,
             cmds: cmds
         };
         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)),
             function () {
-                sendCmds([{cmd: "changeBoard", lang: code, size: getSetting("BoardSize")}]);
+                sendCmds([{cmd: "changeBoard", lang: code, label: getSetting("BoardLabel")}]);
             },
             function () {
                 boardLangSelect.value = getSetting("BoardLang");
         );
     }
     
-    function onChangeBoardSize() {
-        const size = document.getElementById("board-size").value;
+    function onChangeBoardLabel() {
+        const label = document.getElementById("board-label").value;
 
         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 () {
-                sendCmds([{cmd: "changeBoard", lang: getSetting("BoardLang"), size: size}]);
+                sendCmds([{cmd: "changeBoard", lang: getSetting("BoardLang"), label: label}]);
             },
             function () {
-                boardSizeSelect.value = getSetting("BoardLang");
+                boardLabelSelect.value = getSetting("BoardLabel");
             }
         );
     }
     }
 
     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 "";
         }
         try {
-            const index = (row * getSetting("BoardSize")) + col;
+            const index = (row * nbColumns) + col;
             const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
             const tile = tilePlaceholder.getElementsByClassName("tile")[0];
             return tile.firstChild.textContent;
     }
 
     function searchNewWords() {
+        const nbColumns = getBoardDimensions(getSetting("BoardLabel"))[1];
 
         const words = [];
         for (const i of Object.keys(currentTilePlayed)) {
 
             /* Get board position */
-            const row = Math.floor(i / getSetting("BoardSize"));
-            const col = i % getSetting("BoardSize");
+            const row = Math.floor(i / nbColumns);
+            const col = i % nbColumns;
 
             /* Look for word in column */
             const newWordInCol = searchWordInLine(row, col, 1, 0);
     }
 
     function modifyTileClass(word, value, action) {
+        const [nbRows, nbColumns] = getBoardDimensions(getSetting("BoardLabel"));
 
         /* action: true for add, false for remove */
 
 
             /* only for new words */
             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 tile = tilePlaceholder.getElementsByClassName("tile")[0];
 
         } else {
 
             /* 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 tile = tilePlaceholder.getElementsByClassName("tile")[0];
                 if (typeof tile !== "undefined") {
     }
 
     function scoreWords() {
+        const [nbColumns, rackLength] = getBoardDimensions(getSetting("BoardLabel")).slice(1);
         let totalScore = 0;
 
         const newWords = searchNewWords();
 
             const word = newWords[k];
             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 */
                 const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
         }
 
         /* Check for trivabble (the premium score) */
-        if (Object.keys(currentTilePlayed).length === 7) {
+        if (Object.keys(currentTilePlayed).length === rackLength) {
             totalScore += getSetting("PREMIUM_SEVEN_TILES");
         }
 
             return;
         }
 
-        const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+        const nbColumns = getBoardDimensions(getSetting("BoardLabel"))[1];
+        const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
         const col = cell.cellIndex - 1;
         const row = getRowIndex(cell.parentNode) - 1;
 
             msg: _("Look at:") + " " + letters[row] + (cell.cellIndex + 1),
             specialMsg: {
                 type: "highlightCell",
-                cell: (row * getSetting("BoardSize")) + col
+                cell: (row * nbColumns) + col
             }
         }]);
     }
         chatMessages  = document.getElementById("chat-messages");
         chatTextarea  = document.getElementById("chat-ta");
         participantPlaceholder = document.getElementById("participants-placeholder");
-        boardSizeSelect = document.getElementById("board-size");
+        boardLabelSelect = document.getElementById("board-label");
     }
 
     function initEvents() {
 
         document.getElementById("clear-game").onclick  = clearGame;
         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("join-game").onclick   = joinGame;
         document.getElementById("clear-rack").onclick  = clearRack;
             return;
         }
 
-        name.textContent = getSetting("PlayerName");
+        if (Object.keys(BoardList).length > 1) {
+            boardLabelSelect.textContent = "";
 
-        for (let i = 0; i < 7; i++) {
-            const span = document.createElement("span");
-            span.className = "tile-placeholder";
-            rack.appendChild(span);
-            playerLetters.push(span);
+            for (const key of Object.keys(BoardList)) {
+                boardLabelSelect.add(new Option(key, key));
+            }
+
+            document.getElementById("board-label-selection").hidden = false;
         }
 
+        name.textContent = getSetting("PlayerName");
 
         if (getSetting("GameNumber")) {
             document.getElementById("number").textContent = getSetting("GameNumber");
             document.getElementById("board-lang").value = getSetting("BoardLang");
         }
 
-        if (getSetting("BoardSize")) {
-            document.getElementById("board-size").value = getSetting("BoardSize");
+        if (getSetting("BoardLabel")) {
+            document.getElementById("board-label").value = getSetting("BoardLabel");
         }
 
         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 row;
 
         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].lastChild.textContent = i + 1;
+            board.rows[0].lastChild.textContent = j + 1;
+        }
 
+        for (let i = 0; i < nbRows; i++) {
             row = board.insertRow(-1);
             row.appendChild(document.createElement("th"));
             row.lastChild.textContent = letters[i];
 
-            for (let j = 0; j < boardSize; j++) {
+            for (let j = 0; j < nbColumns; j++) {
                 cell = document.createElement("td");
                 boardCells.push(cell);
                 row.appendChild(cell);
         row = board.insertRow(-1);
         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.lastChild.textContent = i + 1;
         }
 
         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() {
index 8e916c507df2e4f17c290286f7c4c5b624ff9d5b..61fb576eafff7af18ffabce85920344f58616ca9 100644 (file)
@@ -35,7 +35,7 @@ const SAVE_TIMEOUT = 5000;
 const KEEP_ALIVE = 30000;
 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_SIZE = process.env.TRIVABBLE_DEFAULT_BOARD_SIZE || 15;
+const DEFAULT_BOARD_LABEL = process.env.TRIVABBLE_DEFAULT_BOARD_LABEL || "15x15-7";
 
 const VERSION = 202005070100;
 
@@ -207,19 +207,28 @@ function keepAlive(responseAndType) {
     }, KEEP_ALIVE);
 }
 
-function newBoard(size) {
-    const res = new Array(size * size);
+function getBoardDimensions(boardLabel) {
+    return boardLabel
+        .match(/[0-9]*/gu)
+        .filter(function (x) {return (x.length !== 0);})
+        .map(function (x) {return parseInt(x);});
+}
+
+function newBoard(label) {
+    const [nbRows, nbColumns] = getBoardDimensions(label);
+
+    const res = new Array(nbRows * nbColumns);
 
-    for (let i = 0; i < size * size; i++) {
+    for (let i = 0; i < nbRows * nbColumns; i++) {
         res[i] = "";
     }
 
     return res;
 }
 
-Game.prototype.init = function (lang, size) {
-    this.size = size || DEFAULT_BOARD_SIZE;
-    this.board = newBoard(this.size);
+Game.prototype.init = function (lang, label) {
+    this.label = label || DEFAULT_BOARD_LABEL;
+    this.board = newBoard(this.label);
     this.lang = lang || DEFAULT_BOARD_LANG;
     this.bag = boardTilesPerLang[this.lang].bag.slice();
     this.letterValues = boardTilesPerLang[this.lang].letterValues;
@@ -235,7 +244,7 @@ Game.prototype.toJSON = function () {
     return {
         board:            this.board,
         lang:             this.lang,
-        size:             this.size,
+        label:            this.label,
         bag:              this.bag,
         letterValues:     this.letterValues,
         racks:            this.racks,
@@ -247,8 +256,8 @@ Game.prototype.toJSON = function () {
 
 Game.fromJSON = function (obj) {
     const game = new Game();
-    game.size             = obj.size   || DEFAULT_BOARD_SIZE;
-    game.board            = obj.board  || newBoard(game.size);
+    game.label            = obj.label  || DEFAULT_BOARD_LABEL;
+    game.board            = obj.board  || newBoard(game.label);
     game.lang             = obj.lang   || DEFAULT_BOARD_LANG;
     game.bag              = boardTilesPerLang[game.lang].bag.slice();
     game.letterValues     = boardTilesPerLang[game.lang].letterValues;
@@ -406,12 +415,12 @@ Game.prototype.bagPushLetter = function (letter, player) {
 };
 
 Game.prototype.reset = function (player) {
-    this.init(this.lang, this.size);
+    this.init(this.lang, this.label);
     this.pendingEvents.push({
         player: player,
         action: "reset",
         board: this.board,
-        size: this.size,
+        label: this.label,
         remainingLetters: this.bag.length,
         rack: []
     });
@@ -476,6 +485,7 @@ function handleCommand(cmdNumber, message, response) {
     game.lastUpdated = new Date();
 
     const playerName = message.playerName;
+    const [nbRows, nbColumns, rackLength] = getBoardDimensions(game.label);
 
     let rack = null;
     const cmd = message.cmds[cmdNumber];
@@ -488,7 +498,7 @@ function handleCommand(cmdNumber, message, response) {
                 gameNumber: gameNumber,
                 playerName: playerName,
                 boardLang: game.lang,
-                boardSize: game.size,
+                boardLabel: game.label,
                 availableBoardLangs: availableBoardLangs,
                 currentPlayer: game.currentPlayer,
                 rack: game.getPlayerRack(playerName),
@@ -502,7 +512,7 @@ function handleCommand(cmdNumber, message, response) {
 
         case "hello": {
             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;
         }
 
@@ -548,7 +558,7 @@ function handleCommand(cmdNumber, message, response) {
                     break;
 
                 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"});
                         return false;
                     }
@@ -593,7 +603,7 @@ function handleCommand(cmdNumber, message, response) {
                     break;
 
                 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"});
                         return false;
                     }
@@ -636,7 +646,7 @@ function handleCommand(cmdNumber, message, response) {
         }
 
         case "setRack": {
-            if (cmd.rack.length > 7) {
+            if (cmd.rack.length > rackLength) {
                 reply(message, response, cmdNumber, {
                     error: 1,
                     rack: rack,
@@ -653,7 +663,7 @@ function handleCommand(cmdNumber, message, response) {
             const newRackSorted = cmd.rack.filter((l) => l);
             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])) {
                     reply(message, response, cmdNumber, {
                         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];
             }
 
@@ -681,24 +691,24 @@ function handleCommand(cmdNumber, message, response) {
 
         case "changeBoard": {
             game.lang = cmd.lang || DEFAULT_BOARD_LANG;
-            game.size = cmd.size || DEFAULT_BOARD_SIZE;
+            game.label = cmd.label || DEFAULT_BOARD_LABEL;
             game.reset();
 
             reply(message, response, cmdNumber, {
                 error: 0,
                 boardLang: game.lang,
-                boardSize: game.size,
+                boardLabel: game.label,
                 letterValues: game.letterValues
             });
 
             game.pendingEvents.push({
                 msg: {
                     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: {
                         type: "changeBoardDef",
                         newBoardLang: game.lang,
-                        newBoardSize: game.size
+                        newBoardLabel: game.label
                     }
                 }
             });
@@ -739,7 +749,7 @@ function handleCommands(message, responseAndType) {
                 currentPlayer:       game.currentPlayer,
                 gameNumber:          gameNumber,
                 boardLang:           game.lang,
-                boardSize:           game.size,
+                boardLabel:          game.label,
                 availableBoardLangs: availableBoardLangs,
                 letterValues:        game.letterValues,
                 rack:                game.getPlayerRack(message.playerName),