Merge branch 'custon_board_layout' into 'develop'
WIP: Add custom boards Closes #21 See merge request raphj/trivabble!25
This commit is contained in:
commit
3fba842e71
|
@ -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 language of the board to {0}"
|
||||
msgstr "Vous avez changé la langue du plateau en {0}"
|
||||
msgid "You changed the board to {0} for language {1}"
|
||||
msgstr "Vous avez changé le plateau pour {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} for language {2}"
|
||||
msgstr "{0} a changé le plateau pour {1} en {2}"
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Paramètres"
|
||||
|
@ -277,3 +277,14 @@ msgstr "Pas de légende"
|
|||
msgid "Short caption"
|
||||
msgstr "Légendes courtes"
|
||||
|
||||
msgid "Board configuration:"
|
||||
msgstr "Configuration 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."
|
||||
|
||||
msgid "Caution, this feature is experimental; any feedback will be appreciated"
|
||||
msgstr "Attention, cette fonctionnalité est expérimentale ; tout commentaire sera grandement apprécié"
|
||||
|
|
|
@ -172,10 +172,10 @@ msgstr ""
|
|||
msgid "Board language:"
|
||||
msgstr ""
|
||||
|
||||
msgid "You changed the language of the board to {0}"
|
||||
msgid "You changed the board to {0} for language {1}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{0} changed the language of the board to {1}"
|
||||
msgid "{0} changed the board to {1} for language {2}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
|
@ -281,3 +281,15 @@ msgstr ""
|
|||
|
||||
msgid "Short caption"
|
||||
msgstr ""
|
||||
|
||||
msgid "Board configuration:"
|
||||
msgstr ""
|
||||
|
||||
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 ""
|
||||
|
||||
msgid "Caution, this feature is experimental; any feedback will be appreciated"
|
||||
msgstr ""
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
window.BoardList = {
|
||||
"8x8-7": {
|
||||
factor: 0.3,
|
||||
premium: 50,
|
||||
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"]
|
||||
},
|
||||
"9x9-8": {
|
||||
factor: 0.4,
|
||||
premium: 65,
|
||||
TW: ["A1", "A9", "I1", "I9"],
|
||||
DW: ["B2", "C7", "G3", "H8"],
|
||||
TL: ["B5", "C3", "D6", "E2", "E8", "F4", "G7", "H5"],
|
||||
DL: ["A4", "A6", "B8", "D1", "D4", "D9", "F1", "F6", "F9", "H2", "I4", "I6"],
|
||||
CS: ["E5"]
|
||||
},
|
||||
"8x15-7": {
|
||||
factor: 0.6,
|
||||
premium: 50,
|
||||
TW: ["A1", "A8", "A15", "H1", "H8", "H15"],
|
||||
DW: ["B2", "C3", "C10", "E9", "F6", "F13", "G14"],
|
||||
TL: ["B6", "B13", "C14", "D11", "E5", "F2", "G3", "G10"],
|
||||
DL: ["A5", "A12", "B4", "B9", "B11", "C8", "D2", "D4", "D15", "E1", "E12", "E14", "F8", "G5", "G7", "G12", "H4", "H11"],
|
||||
CS: ["D7"]
|
||||
},
|
||||
"9x17-8": {
|
||||
factor: 0.7,
|
||||
premium: 65,
|
||||
TW: ["A1", "A9", "A17", "I1", "I9", "I17"],
|
||||
DW: ["B2", "B16", "C3", "C15", "F10", "G3", "G15", "H2", "H16"],
|
||||
TL: ["B6", "B12", "C7", "C11", "D14", "E5", "E13", "F4", "G7", "G11", "H6", "H12"],
|
||||
DL: ["A5", "A13", "B4", "C13", "D1", "D4", "D10", "D17", "E2", "E9", "E16", "F1", "F8", "F14", "F17", "G5", "H14", "I5", "I13"],
|
||||
CS: ["D8"]
|
||||
},
|
||||
"13x13-6": {
|
||||
factor: 0.75,
|
||||
premium: 35,
|
||||
TW: ["A1", "A7", "A13", "G1", "G13", "M1", "M7", "M13"],
|
||||
DW: ["B2", "B12", "C3", "C11", "D4", "D10", "J4", "J10", "K3", "K11", "L2", "L12"],
|
||||
TL: ["B5", "B9", "E2", "E12", "F6", "F8", "H6", "H8", "I2", "I12", "L5", "L9"],
|
||||
DL: ["A4", "A10", "C6", "C8", "D1", "D7", "D13", "E5", "E9", "F3", "F11", "G4", "G10", "H3", "H11", "I5", "I9", "J1", "J7", "J13", "K6", "K8", "M4", "M10"],
|
||||
CS: ["G7"]
|
||||
},
|
||||
"8x22-7": {
|
||||
factor: 0.8,
|
||||
premium: 50,
|
||||
TW: ["A1", "A8", "A15", "A22", "H1", "H8", "H15", "H22"],
|
||||
DW: ["B3", "B10", "B18", "C4", "C11", "C19", "E5", "E21", "G7", "G15", "G23", "H8", "H16", "H24"],
|
||||
TL: ["B3", "B13", "B17", "C2", "C10", "C16", "D5", "E18", "F7", "F13", "F21", "G6", "G10", "G20"],
|
||||
DL: ["A5", "A11", "A19", "B9", "C14", "D8", "D19", "D22", "E1", "E4", "E15", "F9", "G14", "H4", "H12", "H18"],
|
||||
CS: ["D11"]
|
||||
},
|
||||
"9x25-8": {
|
||||
factor: 1,
|
||||
premium: 65,
|
||||
TW: ["A1", "A9", "A17", "A25", "I1", "I9", "I17", "I25"],
|
||||
DW: ["B2", "B10", "B18", "C3", "C19", "E5", "E21", "G7", "G23", "H8", "H16", "H24"],
|
||||
TL: ["B6", "B14", "B22", "C7", "C15", "D8", "D16", "D24", "F2", "F10", "F18", "G11", "G19", "H4", "H12", "H20"],
|
||||
DL: ["A5", "A13", "A21", "C11", "C23", "D4", "D12", "D20", "E1", "E9", "E17", "E25", "F6", "F14", "F22", "G3", "G15", "I5", "I13", "I21"],
|
||||
CS: ["E13"]
|
||||
},
|
||||
"15x15-7": {
|
||||
factor: 1,
|
||||
premium: 50,
|
||||
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", "O12"],
|
||||
CS: ["H8"]
|
||||
},
|
||||
"17x17-8": {
|
||||
factor: 1.3,
|
||||
premium: 65,
|
||||
TW: ["A1", "A9", "A17", "I1", "I17", "Q1", "Q9", "Q17"],
|
||||
DW: ["B2", "B16", "C3", "C15", "D4", "D14", "E5", "E13", "M5", "M13", "N4", "N14", "O3", "O15", "P2", "P16"],
|
||||
TL: ["B6", "B12", "C7", "C11", "F2", "F16", "G3", "G7", "G11", "G15", "K3", "K7", "K11", "K15", "L2", "L16", "O7", "O11", "P6", "P12"],
|
||||
DL: ["A5", "A13", "D8", "D10", "E1", "E9", "E17", "F6", "F12", "H4", "H8", "H10", "H14", "I5", "I13", "J4", "J8", "J10", "J14", "L6", "L12", "M1", "M9", "M17", "N8", "N10", "Q5", "Q13"],
|
||||
CS: ["I9"]
|
||||
},
|
||||
"19x19-6": {
|
||||
factor: 1.6,
|
||||
premium: 35,
|
||||
TW: ["A1", "A7", "A13", "A19", "G1", "G7", "G13", "G19", "M1", "M7", "M13", "M19", "S1", "S7", "S13", "S19"],
|
||||
DW: ["B2", "B8", "B18", "C3", "C17", "D4", "D10", "D16", "H9", "H18", "J4", "J16", "L2", "L11", "P4", "P10", "P16", "Q3", "Q17", "R2", "R12", "R18"],
|
||||
TL: ["B5", "B15", "C11", "E2", "E8", "E12", "E18", "F6", "F14", "H5", "H15", "I3", "I12", "K8", "K17", "L5", "L15", "N6", "N14", "O2", "O8", "O12", "O18", "Q9", "R5", "R15"],
|
||||
DL: ["A4", "A10", "A16", "B12", "C6", "C9", "C14", "D1", "D7", "D13", "D19", "E5", "E15", "F3", "F9", "F11", "F17", "G4", "G10", "G16", "H2", "H11", "I6", "I8", "I14", "I17", "J1", "J7", "J13", "J19", "K3", "K6", "K12", "K14", "L9", "L18", "M4", "M10", "M16", "N3", "N9", "N11", "N17", "O5", "O15", "P1", "P7", "P13", "P19", "Q6", "Q11", "Q14", "R8", "S4", "S10", "S16"],
|
||||
CS: ["J10"]
|
||||
},
|
||||
"22x22-7": {
|
||||
factor: 2,
|
||||
premium: 50,
|
||||
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"]
|
||||
},
|
||||
"25x25-8": {
|
||||
factor: 2.8,
|
||||
premium: 65,
|
||||
TW: ["A1", "A9", "A17", "A25", "I1", "I9", "I17", "I25", "Q1", "Q9", "Q17", "Q25", "Y1", "Y9", "Y17", "Y25"],
|
||||
DW: ["B2", "B24", "D4", "D14", "D22", "E5", "E13", "E21", "F12", "H8", "H18", "L4", "L20", "M5", "M21", "N6", "N22", "R8", "R18", "T14", "U5", "U13", "U21", "V4", "V12", "V22", "X2", "X24"],
|
||||
TL: ["C3", "C7", "C11", "C15", "C19", "C23", "G3", "G7", "G11", "G15", "G19", "G23", "K3", "K7", "K11", "K15", "K19", "K23", "O3", "O7", "O11", "O15", "O19", "O23", "S3", "S7", "S11", "S15", "S19", "S23", "W3", "W7", "W11", "W15", "W19", "W23"],
|
||||
DL: ["A5", "A13", "A21", "B6", "B12", "B16", "B20", "D10", "D18", "E1", "E9", "E17", "E25", "F2", "F6", "F16", "F20", "F24", "H4", "H14", "I5", "I13", "I21", "J2", "J6", "J10", "J16", "J22", "L8", "L12", "L24", "M1", "M9", "M17", "M25", "N2", "N14", "N18", "P4", "P10", "P16", "P20", "P24", "Q5", "Q13", "Q21", "R12", "R22", "T2", "T6", "T10", "T20", "T24", "U1", "U9", "U17", "U25", "V8", "V16", "X6", "X10", "X14", "X20", "Y5", "Y13", "Y21"],
|
||||
CS: ["M13"]
|
||||
}
|
||||
};
|
|
@ -53,6 +53,9 @@ window.TrivabbleConf = {
|
|||
// Cell captions. Could be "clip", "dots", "none" or "short"
|
||||
//CELL_CAPTIONS: "dots",
|
||||
|
||||
// Enable custom board definitions
|
||||
//ENABLE_CUSTOM_BOARD: false,
|
||||
|
||||
// I don't like trailing commas, here is a nice message for you reading this file :-)
|
||||
HAVE_FUN: true
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<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>
|
||||
|
@ -30,7 +31,7 @@
|
|||
<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">
|
||||
|
@ -46,6 +47,12 @@
|
|||
<option value="fr">French</option>
|
||||
</select>
|
||||
</p>
|
||||
<p id="board-label-selection" hidden="true">
|
||||
<label for="board-label" data-l10n="text-content">Board configuration: </label>
|
||||
<select id="board-label">
|
||||
<option value="15x15-7">15x15-7</option>
|
||||
</select>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
const DictionaryList = window.DictionaryList || {};
|
||||
|
||||
const BoardList = window.BoardList || {};
|
||||
|
||||
function setConf(parameterName, defaultValue) {
|
||||
if (typeof Conf[parameterName] === "undefined") {
|
||||
Conf[parameterName] = defaultValue;
|
||||
|
@ -64,6 +66,7 @@
|
|||
setConf("SCORE_LAST_PLAYER", true);
|
||||
setConf("ENABLE_TIMER", false);
|
||||
setConf("CELL_CAPTIONS", "dots"); // "clip", "dots", "none", "short"
|
||||
setConf("ENABLE_CUSTOM_BOARD", false);
|
||||
|
||||
function isSetting(key) {
|
||||
return Object.prototype.hasOwnProperty.call(Conf, key) ||
|
||||
|
@ -156,6 +159,7 @@
|
|||
BoardLang: "string",
|
||||
DisableSpellChecker: "boolean",
|
||||
GameNumber: "number",
|
||||
BoardLabel: "string",
|
||||
Lang: "string",
|
||||
PlayerName: "string",
|
||||
SpellCheckerEnabledOnce: "boolean",
|
||||
|
@ -171,9 +175,9 @@
|
|||
|
||||
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;
|
||||
|
@ -182,8 +186,10 @@
|
|||
let scoreOf;
|
||||
let bag;
|
||||
let boardLangSelect;
|
||||
let boardLabelSelect;
|
||||
const downloadedDictionaries = {};
|
||||
|
||||
const boardDef = {nbRows: 0, nbColumns: 0, rackLength: 0};
|
||||
let warningCustomBoard = false;
|
||||
const playerLetters = [];
|
||||
let currentPlayer = "";
|
||||
|
||||
|
@ -235,13 +241,13 @@
|
|||
}
|
||||
|
||||
function setRack(rack) {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
for (let i = 0; i < boardDef.rackLength; i++) {
|
||||
setTileParent(playerLetters[i], rack[i] || "");
|
||||
}
|
||||
}
|
||||
|
||||
function getFreeRackSpaceIndex() {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
for (let i = 0; i < boardDef.rackLength; i++) {
|
||||
if (!playerLetters[i].getElementsByClassName("tile")[0]) {
|
||||
return i;
|
||||
}
|
||||
|
@ -450,7 +456,7 @@
|
|||
}
|
||||
}
|
||||
} else if (tileInitDest.getElementsByClassName("tile")[0]) {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
for (let i = 0; i < boardDef.rackLength; i++) {
|
||||
if (!playerLetters[i].getElementsByClassName("tile")[0]) {
|
||||
playerLetters[i].appendChild(movingTile);
|
||||
break;
|
||||
|
@ -756,7 +762,7 @@
|
|||
}
|
||||
|
||||
function setBoard(board) {
|
||||
for (let i = 0; i < 15 * 15; i++) {
|
||||
for (let i = 0; i < boardDef.nbRows * boardDef.nbColumns; i++) {
|
||||
setCell(i, board[i]);
|
||||
}
|
||||
}
|
||||
|
@ -776,6 +782,16 @@
|
|||
setSetting("BoardLang", value);
|
||||
checkDictionaryExistance(value);
|
||||
break;
|
||||
case "boardLabel":
|
||||
document.getElementById("board-label").value = value;
|
||||
setSetting("BoardLabel", value);
|
||||
[boardDef.nbRows, boardDef.nbColumns, boardDef.rackLength] =
|
||||
(typeof value === "undefined") ? [0, 0, 0] : value
|
||||
.match(/[0-9]*/gu)
|
||||
.filter(function (x) {return (x.length !== 0);})
|
||||
.map(function (x) {return parseInt(x);});
|
||||
initBoard();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -908,13 +924,18 @@
|
|||
return;
|
||||
}
|
||||
|
||||
case "changeBoardLang": {
|
||||
case "changeBoardDef": {
|
||||
const newLang = boardLangSelect.querySelector("[value=" + msg.specialMsg.newBoardLang + "]").textContent;
|
||||
const newLabel = msg.specialMsg.newBoardLabel;
|
||||
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} for language {1}"), newLabel, newLang)
|
||||
: format(_("{0} changed the board to {1} for language {2}"), msg.sender, newLabel, newLang)
|
||||
);
|
||||
if ((newLabel !== "15x15-7") && (!warningCustomBoard)) {
|
||||
infoMessage(_("Caution, this feature is experimental; any feedback will be appreciated"));
|
||||
warningCustomBoard = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1214,6 +1235,16 @@
|
|||
set("boardLang", data.boardLang);
|
||||
(boardLangSelect || {}).value = data.boardLang;
|
||||
}
|
||||
|
||||
if (data.boardLabel) {
|
||||
if (Object.keys(BoardList).indexOf(data.boardLabel) === -1) {
|
||||
myAlert("Can't find board '" + data.boardLabel + "'. Change board or start a new game.");
|
||||
(boardLabelSelect || {}).value = "";
|
||||
} else {
|
||||
set("boardLabel", data.boardLabel);
|
||||
(boardLabelSelect || {}).value = data.boardLabel;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.letterValues) {
|
||||
scoreOf = data.letterValues;
|
||||
|
@ -1503,6 +1534,8 @@
|
|||
gameNumber: getSetting("GameNumber") || "",
|
||||
playerName: getSetting("PlayerName"),
|
||||
boardLang: getSetting("BoardLang"),
|
||||
boardLabel: getSetting("BoardLabel"),
|
||||
bagFactor: (typeof getSetting("BoardLabel") === "undefined") ? 1 : BoardList[getSetting("BoardLabel")].factor,
|
||||
version: VERSION,
|
||||
cmds: cmds
|
||||
};
|
||||
|
@ -1652,13 +1685,27 @@
|
|||
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, label: getSetting("BoardLabel"), factor: BoardList[getSetting("BoardLabel")].factor}]);
|
||||
},
|
||||
function () {
|
||||
boardLangSelect.value = getSetting("BoardLang");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function onChangeBoardLabel() {
|
||||
const label = document.getElementById("board-label").value;
|
||||
|
||||
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."), label),
|
||||
function () {
|
||||
sendCmds([{cmd: "changeBoard", lang: getSetting("BoardLang"), label: label, factor: BoardList[label].factor}]);
|
||||
},
|
||||
function () {
|
||||
boardLabelSelect.value = getSetting("BoardLabel");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function clearRack() {
|
||||
myConfirm(
|
||||
|
@ -1722,11 +1769,11 @@
|
|||
}
|
||||
|
||||
function getLetterFromBoard(row, col) {
|
||||
if ((row < 0) || (row >= 15) || (col < 0) || (col >= 15)) {
|
||||
if ((row < 0) || (row >= boardDef.nbRows) || (col < 0) || (col >= boardDef.nbColumns)) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
const index = (row * 15) + col;
|
||||
const index = (row * boardDef.nbColumns) + col;
|
||||
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
|
||||
const tile = tilePlaceholder.getElementsByClassName("tile")[0];
|
||||
return tile.firstChild.textContent;
|
||||
|
@ -1772,13 +1819,12 @@
|
|||
}
|
||||
|
||||
function searchNewWords() {
|
||||
|
||||
const words = [];
|
||||
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 / boardDef.nbColumns);
|
||||
const col = i % boardDef.nbColumns;
|
||||
|
||||
/* Look for word in column */
|
||||
const newWordInCol = searchWordInLine(row, col, 1, 0);
|
||||
|
@ -1811,7 +1857,7 @@
|
|||
|
||||
/* 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)) * boardDef.nbColumns) + word.col + (l * word.incCol);
|
||||
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
|
||||
const tile = tilePlaceholder.getElementsByClassName("tile")[0];
|
||||
|
||||
|
@ -1821,7 +1867,7 @@
|
|||
} else {
|
||||
|
||||
/* tiles on board */
|
||||
for (let index = 0; index < 15 * 15; index++) {
|
||||
for (let index = 0; index < boardDef.nbRows * boardDef.nbColumns; index++) {
|
||||
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
|
||||
const tile = tilePlaceholder.getElementsByClassName("tile")[0];
|
||||
if (typeof tile !== "undefined") {
|
||||
|
@ -1911,7 +1957,7 @@
|
|||
|
||||
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)) * boardDef.nbColumns) + word.col + (l * word.incCol);
|
||||
|
||||
/* Letter score */
|
||||
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
|
||||
|
@ -1950,8 +1996,12 @@
|
|||
}
|
||||
|
||||
/* Check for trivabble (the premium score) */
|
||||
if (Object.keys(currentTilePlayed).length === 7) {
|
||||
totalScore += getSetting("PREMIUM_SEVEN_TILES");
|
||||
if (Object.keys(currentTilePlayed).length === boardDef.rackLength) {
|
||||
if (Object.prototype.hasOwnProperty.call(BoardList[getSetting("BoardLabel")], "premium")) {
|
||||
totalScore += BoardList[getSetting("BoardLabel")].premium;
|
||||
} else {
|
||||
totalScore += getSetting("PREMIUM_SEVEN_TILES");
|
||||
}
|
||||
}
|
||||
|
||||
/* Ѕcore last player or the one who pressed the button */
|
||||
|
@ -1984,7 +2034,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
const letters = "ABCDEFGHIJKLMNO";
|
||||
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
const col = cell.cellIndex - 1;
|
||||
const row = getRowIndex(cell.parentNode) - 1;
|
||||
|
||||
|
@ -1993,7 +2043,7 @@
|
|||
msg: _("Look at:") + " " + letters[row] + (cell.cellIndex + 1),
|
||||
specialMsg: {
|
||||
type: "highlightCell",
|
||||
cell: (row * 15) + col
|
||||
cell: (row * boardDef.nbColumns) + col
|
||||
}
|
||||
}]);
|
||||
}
|
||||
|
@ -2422,6 +2472,7 @@
|
|||
chatMessages = document.getElementById("chat-messages");
|
||||
chatTextarea = document.getElementById("chat-ta");
|
||||
participantPlaceholder = document.getElementById("participants-placeholder");
|
||||
boardLabelSelect = document.getElementById("board-label");
|
||||
}
|
||||
|
||||
function initEvents() {
|
||||
|
@ -2429,6 +2480,7 @@
|
|||
|
||||
document.getElementById("clear-game").onclick = clearGame;
|
||||
document.getElementById("board-lang").onchange = onChangeBoardLang;
|
||||
document.getElementById("board-label").onchange = onChangeBoardLabel;
|
||||
document.getElementById("change-name").onclick = changeName;
|
||||
document.getElementById("join-game").onclick = joinGame;
|
||||
document.getElementById("clear-rack").onclick = clearRack;
|
||||
|
@ -2462,43 +2514,59 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if (getSetting("ENABLE_CUSTOM_BOARD") && (Object.keys(BoardList).length > 1)) {
|
||||
boardLabelSelect.textContent = "";
|
||||
|
||||
for (const key of Object.keys(BoardList)) {
|
||||
boardLabelSelect.add(new Option(key, key));
|
||||
}
|
||||
|
||||
document.getElementById("board-label-selection").hidden = false;
|
||||
}
|
||||
|
||||
name.textContent = getSetting("PlayerName");
|
||||
|
||||
const letters = "ABCDEFGHIJKLMNO";
|
||||
if (getSetting("GameNumber")) {
|
||||
document.getElementById("number").textContent = getSetting("GameNumber");
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
if (getSetting("BoardLang")) {
|
||||
document.getElementById("board-lang").value = getSetting("BoardLang");
|
||||
}
|
||||
|
||||
if (getSetting("BoardLabel")) {
|
||||
document.getElementById("board-label").value = getSetting("BoardLabel");
|
||||
}
|
||||
|
||||
startGame(getSetting("GameNumber"));
|
||||
}
|
||||
|
||||
function initBoard() {
|
||||
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
const def = BoardList[getSetting("BoardLabel")];
|
||||
|
||||
let cell;
|
||||
let row;
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const span = document.createElement("span");
|
||||
span.className = "tile-placeholder";
|
||||
rack.appendChild(span);
|
||||
playerLetters.push(span);
|
||||
/* empty board */
|
||||
while (board.firstChild) {
|
||||
board.removeChild(board.lastChild);
|
||||
}
|
||||
cell = board.insertRow(0).insertCell(0);
|
||||
cell.className = "corner";
|
||||
boardCells.length = 0;
|
||||
|
||||
for (let j = 0; j < boardDef.nbColumns; j++) {
|
||||
board.rows[0].appendChild(document.createElement("th"));
|
||||
board.rows[0].lastChild.textContent = j + 1;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 15; i++) {
|
||||
board.rows[0].appendChild(document.createElement("th"));
|
||||
board.rows[0].lastChild.textContent = i + 1;
|
||||
|
||||
for (let i = 0; i < boardDef.nbRows; i++) {
|
||||
row = board.insertRow(-1);
|
||||
row.appendChild(document.createElement("th"));
|
||||
row.lastChild.textContent = letters[i];
|
||||
|
||||
for (let j = 0; j < 15; j++) {
|
||||
for (let j = 0; j < boardDef.nbColumns; j++) {
|
||||
cell = document.createElement("td");
|
||||
boardCells.push(cell);
|
||||
row.appendChild(cell);
|
||||
|
@ -2506,18 +2574,19 @@
|
|||
cell.appendChild(document.createElement("div"));
|
||||
cell.lastChild.className = "tile-placeholder";
|
||||
|
||||
if (i === j && i === 7) {
|
||||
const cellName = letters[i] + (j + 1);
|
||||
if (def.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 (def.TW.indexOf(cellName) !== -1) {
|
||||
specialCell("tripleWord", row.lastChild);
|
||||
} else if ((i === j || i + j === 14) && (i < 5 || i > 9)) {
|
||||
} else if (def.DW.indexOf(cellName) !== -1) {
|
||||
specialCell("doubleWord", row.lastChild);
|
||||
} else if ((i % 4 === 1) && (j % 4 === 1)) {
|
||||
} else if (def.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 (def.DL.indexOf(cellName) !== -1) {
|
||||
specialCell("doubleLetter", row.lastChild);
|
||||
}
|
||||
}
|
||||
|
@ -2531,22 +2600,26 @@
|
|||
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 < boardDef.nbColumns; 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");
|
||||
while (rack.firstChild) {
|
||||
rack.removeChild(rack.lastChild);
|
||||
}
|
||||
playerLetters.length = 0;
|
||||
|
||||
for (let i = 0; i < boardDef.rackLength; i++) {
|
||||
const span = document.createElement("span");
|
||||
span.className = "tile-placeholder";
|
||||
rack.appendChild(span);
|
||||
playerLetters.push(span);
|
||||
}
|
||||
|
||||
if (getSetting("BoardLang")) {
|
||||
document.getElementById("board-lang").value = getSetting("BoardLang");
|
||||
}
|
||||
|
||||
startGame(getSetting("GameNumber"));
|
||||
setCellCaptions(getSetting("CELL_CAPTIONS"));
|
||||
}
|
||||
|
||||
function initLang() {
|
||||
|
|
|
@ -35,6 +35,8 @@ 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_LABEL = process.env.TRIVABBLE_DEFAULT_BOARD_LABEL || "15x15-7";
|
||||
const DEFAULT_BAG_FACTOR = process.env.TRIVABBLE_DEFAULT_BAG_FACTOR || 1;
|
||||
|
||||
const VERSION = 202005070100;
|
||||
|
||||
|
@ -206,26 +208,47 @@ function keepAlive(responseAndType) {
|
|||
}, KEEP_ALIVE);
|
||||
}
|
||||
|
||||
function newBoard() {
|
||||
const res = new Array(15 * 15);
|
||||
function getBoardDimensions(boardLabel) {
|
||||
return boardLabel
|
||||
.match(/[0-9]*/gu)
|
||||
.filter(function (x) {return (x.length !== 0);})
|
||||
.map(function (x) {return parseInt(x);});
|
||||
}
|
||||
|
||||
for (let i = 0; i < 15 * 15; 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] = "";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Game.prototype.init = function (lang) {
|
||||
this.board = newBoard();
|
||||
Game.prototype.init = function (lang, label, factor) {
|
||||
this.label = label || DEFAULT_BOARD_LABEL;
|
||||
this.factor = factor || DEFAULT_BAG_FACTOR;
|
||||
this.board = newBoard(this.label);
|
||||
this.lang = lang || DEFAULT_BOARD_LANG;
|
||||
this.bag = boardTilesPerLang[this.lang].bag.slice();
|
||||
const bag = boardTilesPerLang[this.lang].bag.slice();
|
||||
this.letterValues = boardTilesPerLang[this.lang].letterValues;
|
||||
this.racks = {};
|
||||
this.scores = {};
|
||||
this.lastUpdated = new Date();
|
||||
this.currentPlayer = "";
|
||||
|
||||
factor = this.factor;
|
||||
this.bag = [];
|
||||
while (factor > 1) {
|
||||
this.bag = this.bag.concat(bag.slice());
|
||||
factor--;
|
||||
}
|
||||
if (Math.round(bag.length * factor) > 0) {
|
||||
shuffleInPlace(bag);
|
||||
this.bag = this.bag.concat(bag.slice(0, Math.round(bag.length * factor)));
|
||||
}
|
||||
shuffleInPlace(this.bag);
|
||||
};
|
||||
|
||||
|
@ -233,6 +256,8 @@ Game.prototype.toJSON = function () {
|
|||
return {
|
||||
board: this.board,
|
||||
lang: this.lang,
|
||||
label: this.label,
|
||||
factor: this.factor,
|
||||
bag: this.bag,
|
||||
letterValues: this.letterValues,
|
||||
racks: this.racks,
|
||||
|
@ -244,7 +269,9 @@ Game.prototype.toJSON = function () {
|
|||
|
||||
Game.fromJSON = function (obj) {
|
||||
const game = new Game();
|
||||
game.board = obj.board || newBoard();
|
||||
game.label = obj.label || DEFAULT_BOARD_LABEL;
|
||||
game.factor = obj.factor || DEFAULT_BAG_FACTOR;
|
||||
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;
|
||||
|
@ -402,11 +429,13 @@ Game.prototype.bagPushLetter = function (letter, player) {
|
|||
};
|
||||
|
||||
Game.prototype.reset = function (player) {
|
||||
this.init(this.lang);
|
||||
this.init(this.lang, this.label, this.factor);
|
||||
this.pendingEvents.push({
|
||||
player: player,
|
||||
action: "reset",
|
||||
board: this.board,
|
||||
label: this.label,
|
||||
factor: this.factor,
|
||||
remainingLetters: this.bag.length,
|
||||
rack: []
|
||||
});
|
||||
|
@ -471,6 +500,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];
|
||||
|
@ -483,6 +513,8 @@ function handleCommand(cmdNumber, message, response) {
|
|||
gameNumber: gameNumber,
|
||||
playerName: playerName,
|
||||
boardLang: game.lang,
|
||||
boardLabel: game.label,
|
||||
bagFactor: game.factor,
|
||||
availableBoardLangs: availableBoardLangs,
|
||||
currentPlayer: game.currentPlayer,
|
||||
rack: game.getPlayerRack(playerName),
|
||||
|
@ -496,7 +528,7 @@ function handleCommand(cmdNumber, message, response) {
|
|||
|
||||
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, boardLabel: game.label, bagFactor: game.factor, version: VERSION});
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -524,7 +556,7 @@ function handleCommand(cmdNumber, message, response) {
|
|||
case "rack":
|
||||
rack = game.getPlayerRack(playerName);
|
||||
|
||||
if (cmd.indexFrom > 6 || cmd.indexFrom < 0) {
|
||||
if (cmd.indexFrom > rackLength - 1 || cmd.indexFrom < 0) {
|
||||
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexFrom"});
|
||||
return false;
|
||||
}
|
||||
|
@ -542,7 +574,7 @@ function handleCommand(cmdNumber, message, response) {
|
|||
break;
|
||||
|
||||
case "board":
|
||||
if (cmd.indexFrom < 0 || cmd.indexFrom >= 15 * 15) {
|
||||
if (cmd.indexFrom < 0 || cmd.indexFrom >= nbRows * nbColumns) {
|
||||
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexFrom"});
|
||||
return false;
|
||||
}
|
||||
|
@ -569,7 +601,7 @@ function handleCommand(cmdNumber, message, response) {
|
|||
|
||||
switch (cmd.to) {
|
||||
case "rack":
|
||||
if (cmd.indexTo < 0 || cmd.indexTo > 6) {
|
||||
if (cmd.indexTo < 0 || cmd.indexTo > rackLength - 1) {
|
||||
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexTo"});
|
||||
return false;
|
||||
}
|
||||
|
@ -587,7 +619,7 @@ function handleCommand(cmdNumber, message, response) {
|
|||
break;
|
||||
|
||||
case "board":
|
||||
if (cmd.indexTo < 0 || cmd.indexTo >= 15 * 15) {
|
||||
if (cmd.indexTo < 0 || cmd.indexTo >= nbRows * nbColumns) {
|
||||
reply(message, response, cmdNumber, {error: 1, reason: "Wrong indexTo"});
|
||||
return false;
|
||||
}
|
||||
|
@ -630,7 +662,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,
|
||||
|
@ -647,7 +679,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,
|
||||
|
@ -658,7 +690,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];
|
||||
}
|
||||
|
||||
|
@ -675,21 +707,27 @@ function handleCommand(cmdNumber, message, response) {
|
|||
|
||||
case "changeBoard": {
|
||||
game.lang = cmd.lang || DEFAULT_BOARD_LANG;
|
||||
game.label = cmd.label || DEFAULT_BOARD_LABEL;
|
||||
game.factor = cmd.factor || DEFAULT_BAG_FACTOR;
|
||||
game.reset();
|
||||
|
||||
reply(message, response, cmdNumber, {
|
||||
error: 0,
|
||||
boardLang: game.lang,
|
||||
boardLabel: game.label,
|
||||
bagFactor: game.factor,
|
||||
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.label + " in language " + game.lang,
|
||||
specialMsg: {
|
||||
type: "changeBoardLang",
|
||||
newBoardLang: game.lang
|
||||
type: "changeBoardDef",
|
||||
newBoardLang: game.lang,
|
||||
newBoardLabel: game.label,
|
||||
newBagFactor: game.factor
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -730,6 +768,8 @@ function handleCommands(message, responseAndType) {
|
|||
currentPlayer: game.currentPlayer,
|
||||
gameNumber: gameNumber,
|
||||
boardLang: game.lang,
|
||||
boardLabel: game.label,
|
||||
bagFactor: game.factor,
|
||||
availableBoardLangs: availableBoardLangs,
|
||||
letterValues: game.letterValues,
|
||||
rack: game.getPlayerRack(message.playerName),
|
||||
|
|
Loading…
Reference in New Issue