msgid "Board language:"
msgstr "Langue du plateau :"
-msgid "You changed the language of the board to {0}"
-msgstr "Vous avez changé la langue du plateau en {0}"
+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 "{0} changed the language of the board to {1}"
-msgstr "{0} a changé la langue du plateau 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 "Settings"
msgstr "Paramètres"
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 language:"
msgstr ""
-msgid "You changed the language of the board to {0}"
+msgid "You changed the board to {0}x{0} for language {1}"
msgstr ""
-msgid "{0} changed the language of the board to {1}"
+msgid "{0} changed the board to {1}x{1} for language {2}"
msgstr ""
msgid "Settings"
msgid "To measure playing time, activate the timer."
msgstr ""
+
+msgid "Board size:"
+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."
+msgstr ""
--- /dev/null
+window.BoardList = {
+ "8x8": {
+ TW: [
+ "A1", "A8",
+ "H1", "H8"
+ ],
+ DW: [
+ "B2", "B7",
+ "E5",
+ "G2", "G7"
+ ],
+ TL: [
+ "B5",
+ "E2",
+ "D7",
+ "G4"
+ ],
+ DL: [
+ "A4",
+ "C3", "C6",
+ "D1",
+ "E8",
+ "F3", "F6",
+ "H5"
+ ],
+ CS: [
+ "D4"
+ ]
+ },
+ "15x15": {
+ 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": {
+ TW: [
+ "A1", "A8", "A15", "A22",
+ "H1", "H8", "H15", "H22",
+ "O1", "O8", "O15", "O22",
+ "V1", "V8", "V15", "V22"
+ ],
+ DW: [
+ "B2", "B10", "B21",
+ "C3", "C20",
+ "D4", "D12", "D19",
+ "E5", "E18",
+ "I9", "I14",
+ "J21",
+ "K4",
+ "L12", "L19",
+ "M2",
+ "N9", "N14",
+ "R5", "R18",
+ "S4", "S11", "S19",
+ "T3", "T20",
+ "U2", "U13", "U21"
+ ],
+ TL: [
+ "B6", "B17",
+ "E14",
+ "F2", "F6", "F10", "F17", "F21",
+ "I5",
+ "J13", "J17",
+ "M6", "M10",
+ "N18",
+ "Q2", "Q6", "Q13", "Q17", "Q21",
+ "R9",
+ "U6", "U17"
+ ],
+ DL: [
+ "A4", "A12", "A19",
+ "B13",
+ "C7", "C11", "C16",
+ "D1", "D8", "D15", "D22",
+ "E9",
+ "F13",
+ "G3", "G7", "G11", "G16", "G20",
+ "H4", "H12", "H19",
+ "I18",
+ "J2", "J6", "J10",
+ "K1", "K8", "K16", "K20",
+ "L3", "L7", "L15", "L22",
+ "M13", "M17", "M21",
+ "N5",
+ "O4", "O11", "O19",
+ "P3", "P7", "P12", "P16", "P20",
+ "Q10",
+ "R14",
+ "S1", "S8", "S15", "S22",
+ "T7", "T12", "T16",
+ "U10",
+ "V4", "V11", "V19"
+ ],
+ CS: [
+ "K11"
+ ]
+ }
+};
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="format-detection" content="telephone=no" />
+ <script src="boards.js"></script>
<script src="config.js"></script>
<script src="dict/list.js"></script>
<script src="l10n.js"></script>
<div id="chat-messages"></div>
<textarea id="chat-ta" placeholder="Write a message to your adversaries here" data-l10n="placeholder"></textarea>
<button id="chat-btn" class="minibutton" data-l10n="text-content">Send message</button>
- <div id="lang-selection">
+ <div id="board-selection">
<p>
<label for="select-lang" data-l10n="text-content">Interface language: </label>
<select id="select-lang">
<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>
+ </select>
+ </p>
</div>
</div>
const DictionaryList = window.DictionaryList || {};
+ const BoardList = window.BoardList || {};
+
function setConf(parameterName, defaultValue) {
if (typeof Conf[parameterName] === "undefined") {
Conf[parameterName] = defaultValue;
DisableSpellChecker: "boolean",
GameNumber: "number",
BoardLang: "string",
+ BoardSize: "number",
Lang: "string",
PlayerName: "string",
Timer: "number",
function format(s, v1, v2, v3) {
return s
- .replace("{0}", v1)
- .replace("{1}", v2)
- .replace("{2}", v3);
+ .replace(/\{0\}/gu, v1)
+ .replace(/\{1\}/gu, v2)
+ .replace(/\{2\}/gu, v3);
}
let board;
let scoreOf;
let bag;
let boardLangSelect;
+ let boardSizeSelect;
const downloadedDictionaries = {};
const playerLetters = [];
}
function setBoard(board) {
- for (let i = 0; i < 15 * 15; i++) {
+ for (let i = 0; i < getSetting("BoardSize") * getSetting("BoardSize"); i++) {
setCell(i, board[i]);
}
}
setSetting("BoardLang", value);
checkDictionaryExistance(value);
break;
+ case "boardSize":
+ document.getElementById("board-size").value = value;
+ setSetting("BoardSize", value);
+ initBoard(value);
+ break;
}
}
return;
}
- case "changeBoardLang": {
+ case "changeBoardDef": {
const newLang = boardLangSelect.querySelector("[value=" + msg.specialMsg.newBoardLang + "]").textContent;
+ const newSize = msg.specialMsg.newBoardSize;
infoMessage(
(msg.sender === getSetting("PlayerName"))
- ? format(_("You changed the language of the board to {0}"), newLang)
- : format(_("{0} changed the language of the board to {1}"), msg.sender, newLang)
+ ? 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)
);
break;
}
set("boardLang", data.boardLang);
(boardLangSelect || {}).value = data.boardLang;
}
+
+ if (data.boardSize) {
+ set("boardSize", Number(data.boardSize));
+ (boardSizeSelect || {}).value = data.boardSize;
+ }
if (data.letterValues) {
scoreOf = data.letterValues;
gameNumber: getSetting("GameNumber") || "",
playerName: getSetting("PlayerName"),
boardLang: getSetting("BoardLang"),
+ boardSize: getSetting("BoardSize"),
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}]);
+ sendCmds([{cmd: "changeBoard", lang: code, size: getSetting("BoardSize")}]);
},
function () {
boardLangSelect.value = getSetting("BoardLang");
}
);
}
+
+ function onChangeBoardSize() {
+ const size = document.getElementById("board-size").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),
+ function () {
+ sendCmds([{cmd: "changeBoard", lang: getSetting("BoardLang"), size: size}]);
+ },
+ function () {
+ boardSizeSelect.value = getSetting("BoardLang");
+ }
+ );
+ }
function clearRack() {
myConfirm(
}
function getLetterFromBoard(row, col) {
- if ((row < 0) || (row >= 15) || (col < 0) || (col >= 15)) {
+ if ((row < 0) || (row >= getSetting("BoardSize")) || (col < 0) || (col >= getSetting("BoardSize"))) {
return "";
}
try {
- const index = (row * 15) + col;
+ const index = (row * getSetting("BoardSize")) + col;
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
const tile = tilePlaceholder.getElementsByClassName("tile")[0];
return tile.firstChild.textContent;
for (const i of Object.keys(currentTilePlayed)) {
/* Get board position */
- const row = Math.floor(i / 15);
- const col = i % 15;
+ const row = Math.floor(i / getSetting("BoardSize"));
+ const col = i % getSetting("BoardSize");
/* Look for word in column */
const newWordInCol = searchWordInLine(row, col, 1, 0);
/* only for new words */
for (let l = 0; l < word.letters.length; l++) {
- const index = ((word.row + (l * word.incRow)) * 15) + word.col + (l * word.incCol);
+ const index = ((word.row + (l * word.incRow)) * getSetting("BoardSize")) + 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 < 15 * 15; index++) {
+ for (let index = 0; index < getSetting("BoardSize") * getSetting("BoardSize"); index++) {
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
const tile = tilePlaceholder.getElementsByClassName("tile")[0];
if (typeof tile !== "undefined") {
const word = newWords[k];
for (let l = 0; l < word.letters.length; l++) {
- const index = ((word.row + (l * word.incRow)) * 15) + word.col + (l * word.incCol);
+ const index = ((word.row + (l * word.incRow)) * getSetting("BoardSize")) + word.col + (l * word.incCol);
/* Letter score */
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
return;
}
- const letters = "ABCDEFGHIJKLMNO";
+ const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const col = cell.cellIndex - 1;
const row = getRowIndex(cell.parentNode) - 1;
msg: _("Look at:") + " " + letters[row] + (cell.cellIndex + 1),
specialMsg: {
type: "highlightCell",
- cell: (row * 15) + col
+ cell: (row * getSetting("BoardSize")) + col
}
}]);
}
chatMessages = document.getElementById("chat-messages");
chatTextarea = document.getElementById("chat-ta");
participantPlaceholder = document.getElementById("participants-placeholder");
+ boardSizeSelect = document.getElementById("board-size");
}
function initEvents() {
document.getElementById("clear-game").onclick = clearGame;
document.getElementById("board-lang").onchange = onChangeBoardLang;
+ document.getElementById("board-size").onchange = onChangeBoardSize;
document.getElementById("change-name").onclick = changeName;
document.getElementById("join-game").onclick = joinGame;
document.getElementById("clear-rack").onclick = clearRack;
name.textContent = getSetting("PlayerName");
- const letters = "ABCDEFGHIJKLMNO";
-
- const doubleLetter = {
- "0,3": true,
- "0,11": true,
- "2,6": true,
- "2,8": true,
- "3,0": true,
- "3,7": true,
- "3,14": true,
- "6,2": true,
- "6,6": true,
- "6,8": true,
- "6,12": true
- };
-
- let cell;
- let row;
-
for (let i = 0; i < 7; i++) {
const span = document.createElement("span");
span.className = "tile-placeholder";
playerLetters.push(span);
}
- for (let i = 0; i < 15; i++) {
+
+ if (getSetting("GameNumber")) {
+ document.getElementById("number").textContent = getSetting("GameNumber");
+ }
+
+ if (getSetting("BoardLang")) {
+ document.getElementById("board-lang").value = getSetting("BoardLang");
+ }
+
+ if (getSetting("BoardSize")) {
+ document.getElementById("board-size").value = getSetting("BoardSize");
+ }
+
+ startGame(getSetting("GameNumber"));
+ }
+
+ function initBoard(boardSize) {
+
+ const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ const boardDef = BoardList[boardSize + "x" + boardSize];
+
+ let cell;
+ let row;
+
+ board.innerHTML = "<tr><td class=\"corner\"></td></tr>";
+
+ for (let i = 0; i < boardSize; i++) {
board.rows[0].appendChild(document.createElement("th"));
board.rows[0].lastChild.textContent = i + 1;
row.appendChild(document.createElement("th"));
row.lastChild.textContent = letters[i];
- for (let j = 0; j < 15; j++) {
+ for (let j = 0; j < boardSize; j++) {
cell = document.createElement("td");
boardCells.push(cell);
row.appendChild(cell);
cell.appendChild(document.createElement("div"));
cell.lastChild.className = "tile-placeholder";
- if (i === j && i === 7) {
+ const cellName = letters[i] + (j + 1);
+ if (boardDef.CS.indexOf(cellName) !== -1) {
specialCell("doubleWord", row.lastChild);
cell = row.lastChild.getElementsByClassName("special-cell-label")[0];
cell.textContent = "★";
row.lastChild.id = "center-cell";
- } else if (i % 7 === 0 && j % 7 === 0) {
+ } else if (boardDef.TW.indexOf(cellName) !== -1) {
specialCell("tripleWord", row.lastChild);
- } else if ((i === j || i + j === 14) && (i < 5 || i > 9)) {
+ } else if (boardDef.DW.indexOf(cellName) !== -1) {
specialCell("doubleWord", row.lastChild);
- } else if ((i % 4 === 1) && (j % 4 === 1)) {
+ } else if (boardDef.TL.indexOf(cellName) !== -1) {
specialCell("tripleLetter", row.lastChild);
- } else if ((i < 8 && doubleLetter[i + "," + j]) || (i > 7 && doubleLetter[(14 - i) + "," + j]) || (i === 7 && (j === 3 || j === 11))) {
+ } else if (boardDef.DL.indexOf(cellName) !== -1) {
specialCell("doubleLetter", row.lastChild);
}
}
row = board.insertRow(-1);
row.appendChild(board.rows[0].cells[0].cloneNode(false));
- for (let i = 0; i < 15; i++) {
+ for (let i = 0; i < boardSize; i++) {
row.appendChild(document.createElement("th"));
row.lastChild.textContent = i + 1;
}
row.appendChild(board.rows[0].cells[0].cloneNode(false));
-
- if (getSetting("GameNumber")) {
- document.getElementById("number").textContent = getSetting("GameNumber");
- }
-
- if (getSetting("BoardLang")) {
- document.getElementById("board-lang").value = getSetting("BoardLang");
- }
-
- startGame(getSetting("GameNumber"));
}
function initLang() {
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 VERSION = 202005070100;
}, KEEP_ALIVE);
}
-function newBoard() {
- const res = new Array(15 * 15);
+function newBoard(size) {
+ const res = new Array(size * size);
- for (let i = 0; i < 15 * 15; i++) {
+ for (let i = 0; i < size * size; i++) {
res[i] = "";
}
return res;
}
-Game.prototype.init = function (lang) {
- this.board = newBoard();
+Game.prototype.init = function (lang, size) {
+ this.size = size || DEFAULT_BOARD_SIZE;
+ this.board = newBoard(this.size);
this.lang = lang || DEFAULT_BOARD_LANG;
this.bag = boardTilesPerLang[this.lang].bag.slice();
this.letterValues = boardTilesPerLang[this.lang].letterValues;
return {
board: this.board,
lang: this.lang,
+ size: this.size,
bag: this.bag,
letterValues: this.letterValues,
racks: this.racks,
Game.fromJSON = function (obj) {
const game = new Game();
- game.board = obj.board || newBoard();
+ game.size = obj.size || DEFAULT_BOARD_SIZE;
+ game.board = obj.board || newBoard(game.size);
game.lang = obj.lang || DEFAULT_BOARD_LANG;
game.bag = boardTilesPerLang[game.lang].bag.slice();
game.letterValues = boardTilesPerLang[game.lang].letterValues;
};
Game.prototype.reset = function (player) {
- this.init(this.lang);
+ this.init(this.lang, this.size);
this.pendingEvents.push({
player: player,
action: "reset",
board: this.board,
+ size: this.size,
remainingLetters: this.bag.length,
rack: []
});
gameNumber: gameNumber,
playerName: playerName,
boardLang: game.lang,
+ boardSize: game.size,
availableBoardLangs: availableBoardLangs,
currentPlayer: game.currentPlayer,
rack: game.getPlayerRack(playerName),
case "hello": {
game.playerJoined(playerName);
- reply(message, response, cmdNumber, {error: 0, boardLang: game.lang, version: VERSION});
+ reply(message, response, cmdNumber, {error: 0, boardLang: game.lang, boardSize: game.size, version: VERSION});
break;
}
break;
case "board":
- if (cmd.indexFrom < 0 || cmd.indexFrom >= 15 * 15) {
+ if (cmd.indexFrom < 0 || cmd.indexFrom >= game.size * game.size) {
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexFrom"});
return false;
}
break;
case "board":
- if (cmd.indexTo < 0 || cmd.indexTo >= 15 * 15) {
+ if (cmd.indexTo < 0 || cmd.indexTo >= game.size * game.size) {
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexTo"});
return false;
}
case "changeBoard": {
game.lang = cmd.lang || DEFAULT_BOARD_LANG;
+ game.size = cmd.size || DEFAULT_BOARD_SIZE;
game.reset();
reply(message, response, cmdNumber, {
error: 0,
boardLang: game.lang,
+ boardSize: game.size,
letterValues: game.letterValues
});
game.pendingEvents.push({
msg: {
sender: playerName,
- content: "I changed the language of the board to " + game.lang,
+ content: "I changed the board to " + game.size + "x" + game.size + " in language " + game.lang,
specialMsg: {
- type: "changeBoardLang",
- newBoardLang: game.lang
+ type: "changeBoardDef",
+ newBoardLang: game.lang,
+ newBoardSize: game.size
}
}
});
currentPlayer: game.currentPlayer,
gameNumber: gameNumber,
boardLang: game.lang,
+ boardSize: game.size,
availableBoardLangs: availableBoardLangs,
letterValues: game.letterValues,
rack: game.getPlayerRack(message.playerName),