/** v 0.2 - 03.05 Copyright 2014-2018 David Edler Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. **/ var BOARD = null; // future pointer to dom element //window.alert(js_vars.board1.split(",")); var BOARD_LETTERS = []; var TO_BE_PLAYED_BOARD_LETTER_INDEXES = []; var LETTERS_PLAYED_BY_KI_INDEXES = []; var IS_GAME_FINISHED; var CHECKED_WORD; var PLAYED_WORDS =[]; var SCORE_WORDS = []; var LETTER_STASH; var POINTS_PER_LETTER; var LANGUAGE_CONFIG; var timeClock = performance.now(); const LANG_ENGLISH = 'english'; const LANG_GERMAN = 'german'; const ENGLISH_CONFIG_URL = '/static/conf/english.jsonp'; const GERMAN_CONFIG_URL = '/static/conf/german.jsonp'; loadLanguageConfig(); function setWordScore() { for(var i = 1; i<51; i++) { //window.alert("Setting to 5"); document.getElementById("score_word_"+i+"").value = i+1; //document.write(s); } } function getUrlParameterByName(name, url) { if (!url) url = window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); } function getConfigUrl() { var lang = getUrlParameterByName('lang'); switch (lang) { case LANG_ENGLISH: return ENGLISH_CONFIG_URL; case LANG_GERMAN: default: return GERMAN_CONFIG_URL; } } function i18n(text) { var lang = getUrlParameterByName('lang') || LANG_GERMAN; if (TRANSLATION_MAP[text] && TRANSLATION_MAP[text][lang]) { return TRANSLATION_MAP[text][lang]; } return text; } function loadLanguageConfig() { var request = new XMLHttpRequest(); var configUrl = getConfigUrl(); request.open("GET", configUrl, true); request.onreadystatechange = function() { if (request.readyState === 4) { LANGUAGE_CONFIG = JSON.parse(request.responseText); LETTER_STASH = LANGUAGE_CONFIG.LETTER_STASH; POINTS_PER_LETTER = LANGUAGE_CONFIG.POINTS_PER_LETTER; loadDictionary(); } }; request.send(null); } var PLAYER_1_LETTERS = []; var PLAYER_1_POINTS = 0; var PLAYER_2_LETTERS = []; var PLAYER_2_POINTS = 0; var KI_INTELLIGENCE = 1; var KI_MAX_INTELLIGENCE = 0.2; /*var MAX_POINTS = 0; var MAX_RESULT = {};*/ var BOTH_PLAYERS_PASS_COUNT = 0; var DICTIONARY = []; function loadDictionary() { var request = new XMLHttpRequest(); request.open("GET", '/static/dict/german.txt', true); request.onreadystatechange = function() { if (request.readyState === 4) { DICTIONARY = request.responseText.replace("OE","Ö").replace("UE",'Ü').replace('AE','Ä').toUpperCase(); startGame(); } }; request.send(null); } function showLetterInput(elem) { // get current field var targetPosition = elem.srcElement.id.substring(1,elem.srcElement.id.length).split("_"); var x = parseInt(targetPosition[0]) - 1; var y = parseInt(targetPosition[1]) - 1; // if there is already a active tile, remove it. if (elem.target.classList.contains('player_set_tile')) { var returnedIndex = x * 15 + y; var letter = BOARD_LETTERS[returnedIndex]; BOARD_LETTERS[x*15+y] = ""; TO_BE_PLAYED_BOARD_LETTER_INDEXES.splice(TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(returnedIndex), 1); PLAYER_1_LETTERS.push(letter); elem.target.classList.remove('player_set_tile'); printPlayersLetters(); printBoard(); updatePlayButton(); return; } // there is already a letter if (elem.target.innerHTML !== '') { return; } // mark target cell elem.srcElement.classList.add("input_here"); // show the input layer var input_container = document.getElementById("input_container"); input_container.style.padding= (elem.srcElement.offsetTop + 10) + " 0 0 " + (elem.srcElement.offsetLeft + 55); input_container.style.display= "block"; input_container.innerHTML = i18n('Welchen Buchstaben möchtest du hier setzen?') + "
" + PLAYER_1_LETTERS.join("
") + "
"; // append event listeners to input buttons var buttons=document.getElementsByClassName("input_letter"); for (var i=0; i 0) { var i = seededRandom(0, LETTER_STASH.length); player_var.push(LETTER_STASH[i]); LETTER_STASH.splice(i,1); } if (player_var.length === 0) { endGame(); } } function printPlayersLetters() { var out = ""; for (var i=0; i' + POINTS_PER_LETTER[PLAYER_1_LETTERS[i]] + ''; } document.getElementById("player_1_letters").innerHTML = out; } function printBoard() { for (var i=0; i<15; i++) { for (var j=0; j<15; j++) { var field = BOARD.rows[i].cells[j]; field.innerHTML=BOARD_LETTERS[i * 15 + j]; if (BOARD_LETTERS[i * 15 + j] === '') { field.style.cursor = "pointer"; } else { field.style.cursor = "auto"; } if (TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(i * 15 + j) !== -1) { if (!field.classList.contains('player_set_tile')) { field.classList.add('player_set_tile'); } field.style.cursor = "no-drop"; } else { field.classList.remove('player_set_tile'); } if (LETTERS_PLAYED_BY_KI_INDEXES.indexOf(i * 15 + j) !== -1) { if (!field.classList.contains('ki_set_tile')) { field.classList.add('ki_set_tile'); } } else { field.classList.remove('ki_set_tile'); } } } // score document.getElementById("player_1_points").innerHTML = PLAYER_1_POINTS.toString(); //document.getElementById("player_2_points").innerHTML = PLAYER_2_POINTS.toString(); // remaining tiles document.getElementById("letters_left").innerHTML = LETTER_STASH.length.toString(); } function takeBackCurrentTiles() { for (var i=0; i KI_INTELLIGENCE) { return false; } return DICTIONARY.match("\n" + word + "\n") !== null; } /*function isWordStartInDictionary(word) { return DICTIONARY.match("\n" + word) !== null; }*/ function findWordsAndPointsByActiveLetters() { var words = []; var pointSum = 0; for (var i=0; i < TO_BE_PLAYED_BOARD_LETTER_INDEXES.length; i++) { var cur = TO_BE_PLAYED_BOARD_LETTER_INDEXES[i]; /* * horizontal words */ // find leftest letter var h=cur; while (BOARD_LETTERS[h-1] !== "" && (h % 15) > 0) { h -=1; } //construct word var word_multiplier = 1; var letter_multiplier = 1; var word = BOARD_LETTERS[h]; /* if (TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(h) !== -1) { if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("dl")) { letter_multiplier = 2; } if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("tl")) { letter_multiplier = 3; } if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("dw")) { word_multiplier *= 2; } if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("tw")) { word_multiplier *= 3; } }*/ var points = letter_multiplier * POINTS_PER_LETTER[BOARD_LETTERS[h]]; h++; while (BOARD_LETTERS[h] !== "" && (h % 15) !== 0) { letter_multiplier = 1; /* if (TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(h) !== -1) { if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("dl")) { letter_multiplier = 2; } if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("tl")) { letter_multiplier = 3; } if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("dw")) { word_multiplier *= 2; } if (document.getElementById("s"+ Math.floor(h/15+1) + "_" + Math.floor(h%15+1)).classList.contains("tw")) { word_multiplier *= 3; } }*/ word = word.concat(BOARD_LETTERS[h]); points += letter_multiplier * POINTS_PER_LETTER[BOARD_LETTERS[h]]; h+=1; } if (word.length > 1 && words.indexOf(word) === -1) { words.push(word); pointSum += points * word_multiplier; } /* * vertical words */ // find highest letter var v=cur; while (BOARD_LETTERS[v-15] !== "" && v > 14) { v -= 15; } //construct word word = ''; points = 0; word_multiplier = 1; while (BOARD_LETTERS[v] !== "" && v < 225) { letter_multiplier = 1; /* if (TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(v) !== -1) { if (document.getElementById("s"+ Math.floor(v/15+1) + "_" + Math.floor(v%15+1)).classList.contains("dl")) { letter_multiplier = 2; } if (document.getElementById("s"+ Math.floor(v/15+1) + "_" + Math.floor(v%15+1)).classList.contains("tl")) { letter_multiplier = 3; } if (document.getElementById("s"+ Math.floor(v/15+1) + "_" + Math.floor(v%15+1)).classList.contains("dw")) { word_multiplier *= 2; } if (document.getElementById("s"+ Math.floor(v/15+1) + "_" + Math.floor(v%15+1)).classList.contains("tw")) { word_multiplier *= 3; } }*/ word = word.concat(BOARD_LETTERS[v]); points += letter_multiplier * POINTS_PER_LETTER[BOARD_LETTERS[v]]; v += 15; } if (word.length > 1 && words.indexOf(word) === -1) { words.push(word); pointSum += points * word_multiplier; } } return [words, pointSum]; } /** * is the current position of new letters valid? * * one new word set and no letters on random points of the board * new word is connected to old letters * or opening of the game and center field used **/ function isLetterPositionValid() { var start = 225; var end = 0; for (i=0; i < TO_BE_PLAYED_BOARD_LETTER_INDEXES.length; i++) { if (TO_BE_PLAYED_BOARD_LETTER_INDEXES[i] < start) { start = TO_BE_PLAYED_BOARD_LETTER_INDEXES[i]; } if (TO_BE_PLAYED_BOARD_LETTER_INDEXES[i] > end) { end = TO_BE_PLAYED_BOARD_LETTER_INDEXES[i]; } } var lineEnd = Math.abs(14 - (start % 15)) + start; var isHorizontal = lineEnd >= end; var increment = isHorizontal ? 1 : 15; for (i=start; i 0 && isFieldWithLetter(right)) { return true; } var top = TO_BE_PLAYED_BOARD_LETTER_INDEXES[i]-15; if (top > 0 && isFieldWithLetter(top)) { return true; } var down = TO_BE_PLAYED_BOARD_LETTER_INDEXES[i]+15; if (down < 225 && isFieldWithLetter(down)) { return true; } } return wasBoardEmpty() && isCenterFieldUsed(); } function wasBoardEmpty() { for (var i = 0; i < 225; i++) { if (BOARD_LETTERS[i] !== '' && TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(i) === -1) { return false; } } return true; } function isCenterFieldUsed() { return TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(112) !== -1; } function isFieldWithLetter(index) { return TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(index) === -1 && BOARD_LETTERS[index] !== ''; } function checkValidStateAndCalculatePoints() { if (!isLetterPositionValid()) { return false; } var t = findWordsAndPointsByActiveLetters(); var words = t[0]; var points = t[1]; if (words.length < 1) { return false; } for (var i=0; i= 4) { endGame(); } } function endGame() { IS_GAME_FINISHED = true; for (var i = 0; i < PLAYER_1_LETTERS.length; i++) { var letter = PLAYER_1_LETTERS[i]; PLAYER_1_POINTS -= POINTS_PER_LETTER[letter]; } for (i = 0; i < PLAYER_2_LETTERS.length; i++) { letter = PLAYER_2_LETTERS[i]; PLAYER_2_POINTS -= POINTS_PER_LETTER[letter]; } /*document.getElementById("input_container").innerHTML='game over start new game'; document.getElementById("input_container").style.display= "block"; */ document.getElementById("move").disabled = true; document.getElementById('pass').disabled = true; var winText = i18n('Du gewinnst.'); var looseText = i18n('Du verlierst.'); var resultText = PLAYER_1_POINTS > PLAYER_2_POINTS ? winText : looseText; alert( i18n('Das Spiel ist aus.') + '\n' + resultText + '\n' + i18n("DU") + ": " + PLAYER_1_POINTS + ' ' + i18n("punkte") + '\n' + i18n("KI") + ": " + PLAYER_2_POINTS + ' ' + i18n("punkte") ); } /** * pos: array of positions in game array to be filled with available letters * letters: array of available letters * result: object of indexes in game array and the letters to be set */ /*function tryFreePositions(pos,letters,result) { var tryPos = pos.pop(); TO_BE_PLAYED_BOARD_LETTER_INDEXES.push(tryPos); // try all letters available on current position for (var k = 0; k < letters.length; k++) { var tempLetter = letters.splice(k, 1)[0]; BOARD_LETTERS[tryPos] = tempLetter; result[tryPos] = tempLetter; // more positions to fill, recurse if (pos.length > 0) { // recurse only if we have laid valid starts of words yet var recurse = true; var words = findWordsAndPointsByActiveLetters()[0]; for (var i = 0; i < words.length; i++) { if (!isWordStartInDictionary(words[i])) { recurse = false; break; } } if (recurse) { tryFreePositions(pos, letters, result); } } else { var points = checkValidStateAndCalculatePoints(); // store points // store position and letters in result if (points > MAX_POINTS) { MAX_POINTS = points; //copy by value MAX_RESULT = JSON.parse(JSON.stringify(result)); } } BOARD_LETTERS[tryPos] = ''; result[tryPos] = ''; letters.insert(k, tempLetter); } pos.push(tryPos); TO_BE_PLAYED_BOARD_LETTER_INDEXES.splice(TO_BE_PLAYED_BOARD_LETTER_INDEXES.indexOf(tryPos), 1); }*/ /* //fancy ki comes here function computerMove() { MAX_POINTS = 0; MAX_RESULT = {}; // try all rows for (var row=0; row<15; row++) { // try all starting positions within a row for (var rowStart=0; rowStart < 14; rowStart++) { // beginning field of our word startPos = row*15 + rowStart; // the field left of our current word is not empty if (rowStart !== 0 && BOARD_LETTERS[rowStart-1] !== '') { continue; } // try all possible word lengths for (var wordLength=2; wordLength < 15 - rowStart; wordLength++) { // end field of our word var endPos = row*15 + rowStart + wordLength; // the field right of our current word is not empty if (endPos !== 15 && BOARD_LETTERS[endPos+1] !== '') { continue; } var free_letter_positions=[]; var free_letter_count=0; var set_letter_count=0; for (i=startPos; i < endPos; i++) { if (BOARD_LETTERS[i] === '') { free_letter_positions[free_letter_count] = i; free_letter_count++; } else { set_letter_count++; } } // no letter set or // no free space to set a letter or // too many free spaces (should be up to number of tiles on player hand) if (set_letter_count === 0 || free_letter_count === 0 || free_letter_count > 3) { continue; } best_try = tryFreePositions(free_letter_positions, PLAYER_2_LETTERS, {}); } } } // try all columns var best_try; for (var column = 0; column < 15; column++) { // the starting position inside the column for (var columnStart = 0; columnStart < 14; columnStart++) { // beginning field of our word var startPos = column + 15 * columnStart; // the field on top of our current word is not empty if (startPos > 14 && BOARD_LETTERS[startPos - 15] !== '') { continue; } // try all possible word lengths for (wordLength = 2; wordLength < 15 - columnStart; wordLength++) { // end field of our word endPos = startPos + (15 * wordLength); // the field below our current word is not empty if (endPos + 15 < 225 && BOARD_LETTERS[endPos + 15] !== '') { continue; } free_letter_positions = []; free_letter_count = 0; set_letter_count = 0; for (i = startPos; i < endPos; i += 15) { if (BOARD_LETTERS[i] === '') { free_letter_positions[free_letter_count] = i; free_letter_count++; } else { set_letter_count++; } } // no letter set or // no free space to set a letter or // too many free spaces (should be up to number of tiles on player hand) if (set_letter_count === 0 || free_letter_count === 0 || free_letter_count > 3) { continue; } best_try = tryFreePositions(free_letter_positions, PLAYER_2_LETTERS, {}); } } } PLAYER_2_POINTS += MAX_POINTS; LETTERS_PLAYED_BY_KI_INDEXES = []; for (var i in MAX_RESULT) { LETTERS_PLAYED_BY_KI_INDEXES.push(parseInt(i)); var letter_pos = PLAYER_2_LETTERS.indexOf(MAX_RESULT[i]); PLAYER_2_LETTERS.splice(letter_pos,1); BOARD_LETTERS[i] = MAX_RESULT[i]; } TO_BE_PLAYED_BOARD_LETTER_INDEXES.length=0; drawTiles(PLAYER_2_LETTERS); if (MAX_POINTS === 0) { incrementAndCheckPassCount(); } else { BOTH_PLAYERS_PASS_COUNT = 0; } printBoard(); }*/ function startGame() { BOARD = document.getElementById("board"); // event handlers on board for (var i=0; i<15; i++) { for (var j=0; j<15; j++) { BOARD_LETTERS[i * 15 + j]=''; BOARD.rows[i].cells[j].onclick=showLetterInput; } } document.getElementById("move").disabled = true; BOARD_LETTERS=js_vars.board1.split(","); drawTiles(PLAYER_1_LETTERS); drawTiles(PLAYER_2_LETTERS); printPlayersLetters(); printBoard(); }