1<!DOCTYPE HTML> 2<html> 3 4<!-- 5 pgn4web javascript chessboard 6 copyright (C) 2009-2015 Paolo Casaschi 7 see README file and http://pgn4web.casaschi.net 8 for credits, license and more details 9--> 10 11<head> 12 13<title>pgn4web analysis board</title> 14 15<!-- AppCheck: meta --> 16 17<link rel="icon" sizes="16x16" href="pawn.ico" /> 18 19<style type="text/css"> 20 21html, 22body { 23 margin: 0px; 24 padding: 0px; 25} 26 27body { 28 font-family: sans-serif; 29 overflow: hidden; 30 color: #F4F4F4; 31 background: #F4F4F4; 32 33 -webkit-user-select: none; 34 -moz-user-select: none; 35 -ms-user-select: none; 36 -o-user-select: none; 37 user-select: none; 38 -webkit-text-size-adjust: none; 39 -moz-text-size-adjust: none; 40 -ms-text-size-adjust: none; 41 -o-text-size-adjust: none; 42 text-size-adjust: none; 43 -webkit-touch-callout: none; 44} 45 46a { 47 text-decoration: none; 48} 49 50.container { 51 overflow: hidden; 52 position: relative; 53} 54 55.gameCustomButtons { 56 width: 100%; 57} 58 59.gameCustomButtonsHidden { 60 visibility: hidden; 61} 62 63.gameEval { 64 position: absolute; 65 right: -5px; /* this and the next fix some pv showing at the right of the eval */ 66 padding-right: 5px; 67 bottom: 0px; 68 z-index: 3; 69} 70 71.gameTablebase { 72 display: none; 73 padding-right: 1em; 74} 75 76.gameAnalysis { 77 white-space: nowrap; 78 text-align: left; 79} 80 81.gameAnalysisHidden { 82 visibility: hidden; 83} 84 85.gameFlagAndMoves { 86 position: absolute; 87 bottom: 0px; 88 z-index: 2; 89 white-space: nowrap; 90} 91 92.gameFlagToMove { 93 display: inline-block; 94 border-style: solid; 95 border-width: 1px; 96} 97 98.gameShowFen { 99 display: inline-block; 100 overflow: hidden; 101} 102 103.gameMoves { 104 white-space: nowrap; 105} 106 107</style> 108 109<style type="text/css"> 110 111/* for dynamically redefined variables */ 112 113</style> 114 115<!-- AppCheck: fonts --> 116 117 118<script type="text/javascript"> 119"use strict"; 120 121var thisParamString = window.location.search || window.location.hash; 122 123var thisRegExp; 124 125var fenString; 126thisRegExp = /(&|\?)(fenString|fs)=([^&]*)(&|$)/i; 127if (thisParamString.match(thisRegExp) !== null) { 128 fenString = unescape(thisParamString.match(thisRegExp)[3]); 129} 130// action on fenString postponed after definying pgnText in the html body 131 132var defaultAnalysisSeconds = 13; 133var analysisSeconds = defaultAnalysisSeconds; 134var minAnalysisSeconds = 3; 135var maxAnalysisSeconds = 313; 136thisRegExp = /(&|\?)(analysisSeconds|as)=([1-9][0-9]*)(&|$)/i; 137if (thisParamString.match(thisRegExp) !== null) { 138 analysisSeconds = parseInt(unescape(thisParamString.match(thisRegExp)[3]), 10); 139 if (analysisSeconds < minAnalysisSeconds) { analysisSeconds = minAnalysisSeconds; } 140 if (analysisSeconds > maxAnalysisSeconds) { analysisSeconds = maxAnalysisSeconds; } 141 defaultAnalysisSeconds = analysisSeconds; 142} 143 144var disableEngine; 145thisRegExp = /(&|\?)(disableEngine|de)=([^&]*)(&|$)/i; 146if (thisParamString.match(thisRegExp) !== null) { 147 disableEngine = unescape(thisParamString.match(thisRegExp)[3]); 148} 149disableEngine = ((disableEngine == "true") || (disableEngine == "t")); 150// action on disableEngine postponed at the end of this file when all engine functions are ready 151 152var disableInputs; 153thisRegExp = /(&|\?)(disableInputs|di)=([^&]*)(&|$)/i; 154if (thisParamString.match(thisRegExp) !== null) { 155 disableInputs = unescape(thisParamString.match(thisRegExp)[3]); 156} 157disableInputs = ((disableInputs == "true") || (disableInputs == "t")); 158 159var autoUpdate; 160thisRegExp = /(&|\?)(autoUpdate|au)=([^&]*)(&|$)/i; 161if (thisParamString.match(thisRegExp) !== null) { 162 autoUpdate = unescape(thisParamString.match(thisRegExp)[3]); 163} 164autoUpdate = ((autoUpdate == "true") || (autoUpdate == "t")); 165 166 167var lightColorHex = "#F4F4F4"; 168thisRegExp = /(&|\?)(lightColorHex|lch)=([0-9A-F]*)(&|$)/i; 169if (thisParamString.match(thisRegExp) !== null) { 170 lightColorHex = "#" + unescape(thisParamString.match(thisRegExp)[3]); 171} 172var darkColorHex = "#DDDDDD"; 173thisRegExp = /(&|\?)(darkColorHex|dch)=([0-9A-F]*)(&|$)/i; 174if (thisParamString.match(thisRegExp) !== null) { 175 darkColorHex = "#" + unescape(thisParamString.match(thisRegExp)[3]); 176} 177var highlightColorHex = "#BBBBBB"; 178thisRegExp = /(&|\?)(highlightColorHex|hch)=([0-9A-F]*)(&|$)/i; 179if (thisParamString.match(thisRegExp) !== null) { 180 highlightColorHex = "#" + unescape(thisParamString.match(thisRegExp)[3]); 181} 182var fontMovesColorHex = "#000000"; 183thisRegExp = /(&|\?)(fontMovesColorHex|fmch)=([0-9A-F]*)(&|$)/i; 184if (thisParamString.match(thisRegExp) !== null) { 185 fontMovesColorHex = "#" + unescape(thisParamString.match(thisRegExp)[3]); 186} 187var controlTextColorHex = "#BBBBBB"; 188thisRegExp = /(&|\?)(controlTextColorHex|ctch)=([0-9A-F]*)(&|$)/i; 189if (thisParamString.match(thisRegExp) !== null) { 190 controlTextColorHex = "#" + unescape(thisParamString.match(thisRegExp)[3]); 191} 192var backgroundColorHex = lightColorHex; 193thisRegExp = /(&|\?)(backgroundColorHex|bch)=([0-9A-F]*)(&|$)/i; 194if (thisParamString.match(thisRegExp) !== null) { 195 backgroundColorHex = "#" + unescape(thisParamString.match(thisRegExp)[3]); 196} 197 198var framePaddingRatio = 1; 199thisRegExp = /(&|\?)(framePaddingRatio|fpr)=([0-9.]+)(&|$)/i; 200if (thisParamString.match(thisRegExp) !== null) { 201 framePaddingRatio = parseFloat(unescape(thisParamString.match(thisRegExp)[3])); 202} 203 204var squareSize; 205thisRegExp = /(&|\?)(squareSize|ss)=([1-9][0-9]*)(&|$)/i; 206if (thisParamString.match(thisRegExp) !== null) { 207 squareSize = parseInt(unescape(thisParamString.match(thisRegExp)[3]), 10); 208} 209 210var pieceSizeOptions = new Array(20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 52, 56, 60, 64, 72, 80, 88, 96, 112, 128, 144, 300); 211function defaultPieceSize(squareSize) { 212 var targetPieceSize = Math.floor(0.8 * squareSize); 213 for (var ii=(pieceSizeOptions.length-1); ii>=0; ii--) { 214 if (pieceSizeOptions[ii] <= targetPieceSize) { return pieceSizeOptions[ii]; } 215 } 216 return pieceSizeOptions[0]; 217} 218var pieceSize; 219thisRegExp = /(&|\?)(pieceSize|ps)=([1-9][0-9]*)(&|$)/i; 220if (thisParamString.match(thisRegExp) !== null) { 221 pieceSize = parseInt(unescape(thisParamString.match(thisRegExp)[3]), 10); 222} 223 224// undocumented feature 225var fixedPieceImageSize; 226thisRegExp = /(&|\?)(fixedPieceImageSize|fpis)=([1-9][0-9]*)(&|$)/i; 227if (thisParamString.match(thisRegExp) !== null) { 228 fixedPieceImageSize = parseInt(unescape(thisParamString.match(thisRegExp)[3]), 10); 229} 230 231var pieceFont = "alpha"; 232thisRegExp = /(&|\?)(pieceFont|pf)=([^&]*)(&|$)/i; 233if (thisParamString.match(thisRegExp) !== null) { 234 pieceFont = unescape(thisParamString.match(thisRegExp)[3]); 235 if (pieceFont == "a") { pieceFont = "alpha"; } 236 if (pieceFont == "m") { pieceFont = "merida"; } 237 if (pieceFont == "u") { pieceFont = "uscf"; } 238 if ((pieceFont != "alpha") && (pieceFont != "merida") && (pieceFont != "uscf")) { pieceFont = "alpha"; } 239} 240 241var fontMovesSize; 242thisRegExp = /(&|\?)(fontMovesSize|fms)=([1-9][0-9]*)(&|$)/i; 243if (thisParamString.match(thisRegExp) !== null) { 244 fontMovesSize = parseInt(unescape(thisParamString.match(thisRegExp)[3]), 10); 245} 246var fontCommentsSize; 247thisRegExp = /(&|\?)(fontCommentsSize|fcs)=([1-9][0-9]*)(&|$)/i; 248if (thisParamString.match(thisRegExp) !== null) { 249 fontCommentsSize = parseInt(unescape(thisParamString.match(thisRegExp)[3]), 10); 250} 251 252thisRegExp = /(&|\?)(help|h)=(t|true)(&|$)/i; 253if (thisParamString.match(thisRegExp) !== null) { 254 document.write("<PRE>"); 255 document.write("URL parameters\n"); 256 document.write("\n"); 257 document.write(" - fenString = FEN position to analyze\n"); 258 document.write(" - analysisSeconds = analysis timeout in seconds (default 13)\n"); 259 document.write(" - disableEngine = true | false (default false)\n"); 260 document.write(" - disableInputs = true | false (default false)\n"); 261 document.write(" - autoUpdate = true | false (default false)\n"); 262 // document.write(" - autoPlay = true | false (default false)\n"); 263 // document.write(" - enableLocalStorage = true | false (default false)\n"); 264 // document.write(" - engineSignature = positive number (default -1)\n"); 265 document.write("\n"); 266 document.write(" - squareSize = size of square (default selects square size based on window size)\n"); 267 document.write(" - pieceSize = size of pieces | default (default selects piece size based on square size)\n"); 268 // document.write(" - fixedPieceImageSize = size of piece images (default as size of pieces)\n"); 269 document.write(" - pieceFont = alpha | merida | uscf (default alpha)\n"); 270 document.write("\n"); 271 document.write(" - lightColorHex = light square color hex code, like FF0000 (default F4F4F4)\n"); 272 document.write(" - darkColorHex = dark square color hex code, like FF0000 (default DDDDDD)\n"); 273 document.write(" - highlightColorHex = highlight color hex code, like FF0000 (default BBBBBB)\n"); 274 document.write(" - backgroundColorHex = page background color hex code, like FF0000 (default as lightColorHex)\n"); 275 document.write(" - controlTextColorHex = control buttons text color hex code, like FF0000 (default BBBBBB)\n"); 276 document.write(" - fontMovesColorHex = moves color hex code, like FF0000 (default 000000)\n"); 277 document.write("\n"); 278 document.write(" - fontMovesSize = moves font size (default selects moves font size based on square size)\n"); 279 document.write(" - fontCommentsSize = analysis comments font size (default selects comments font size based on square size)\n"); 280 document.write("\n"); 281 document.write(" - framePaddingRatio = frame padding as a square ratio (default 1)\n"); 282 document.write("\n"); 283 document.write(" - help = true\n"); 284 document.write("\n"); 285 document.write("</PRE>"); 286} 287 288 289// undocumented feature 290var autoPlay; 291thisRegExp = /(&|\?)(autoPlay|ap)=([^&]*)(&|$)/i; 292if (thisParamString.match(thisRegExp) !== null) { 293 autoPlay = unescape(thisParamString.match(thisRegExp)[3]); 294} 295autoPlay = ((autoPlay == "true") || (autoPlay == "t")); 296 297// undocumented feature 298var enableLocalStorage; 299thisRegExp = /(&|\?)(enableLocalStorage|els)=([^&]*)(&|$)/i; 300if (thisParamString.match(thisRegExp) !== null) { 301 enableLocalStorage = unescape(thisParamString.match(thisRegExp)[3]); 302} 303enableLocalStorage = ((enableLocalStorage == "true") || (enableLocalStorage == "t")); 304 305 306function myRulesLength(sheet) { 307 if (sheet.cssRules) { return sheet.cssRules.length; } 308 if (sheet.rules) { return sheet.rules.length; } 309 return null; 310} 311 312function myInsertRule(sheet, selector, declaration) { 313 if (sheet.insertRule) { sheet.insertRule(selector + "{ " + declaration + " }", myRulesLength(sheet)); } 314 else if (sheet.addRule) { sheet.addRule(selector, declaration); } 315} 316 317function myDeleteRule(sheet, index) { 318 if (sheet.deleteRule) { sheet.deleteRule(index); } 319 else if (sheet.removeRule) { sheet.removeRule(index); } 320} 321 322var mySheet = document.styleSheets[0]; 323myInsertRule(mySheet, "body", "color: " + fontMovesColorHex + "; background: " + backgroundColorHex + ";"); 324myInsertRule(mySheet, "a", "color: " + fontMovesColorHex + ";"); 325myInsertRule(mySheet, ".boardTable", "background: " + lightColorHex + ";"); 326myInsertRule(mySheet, ".whiteSquare", "background: " + lightColorHex + ";"); 327myInsertRule(mySheet, ".highlightWhiteSquare", "background: " + highlightColorHex + ";"); 328myInsertRule(mySheet, ".blackSquare", "background: " + darkColorHex + ";"); 329myInsertRule(mySheet, ".highlightBlackSquare", "background: " + highlightColorHex + ";"); 330myInsertRule(mySheet, ".gameCustomButtons", "color: " + controlTextColorHex + ";"); 331myInsertRule(mySheet, ".gameFlagToMove", "border-color: " + fontMovesColorHex + ";"); 332myInsertRule(mySheet, ".gameEval", "background: " + backgroundColorHex + ";"); 333 334var oldSquareSizeCss; 335function myOnResize() { 336 337 if (!fixedPieceImageSize && oldSquareSizeCss) { return; } 338 339 var sheet = document.styleSheets[1]; 340 var oldRules = myRulesLength(sheet); 341 342 var squareSizeCss; 343 if (typeof(squareSize) != "undefined") { squareSizeCss = squareSize; } 344 else { 345 var ww = 0, wh = 0; 346 if (window.innerWidth && window.innerHeight) { ww = window.innerWidth; wh = window.innerHeight; } 347 else if (document.documentElement && document.documentElement.clientWidth) { ww = document.documentElement.clientWidth; wh = document.documentElement.clientHeight; } 348 else if (document.body && document.body.clientWidth) { ww = document.body.clientWidth; wh = document.body.clientHeight; } 349 if (Math.min(ww, wh) > 0) { 350 squareSizeCss = Math.floor(Math.min(ww / (8 + 2 * framePaddingRatio), wh / (10 + 2 * framePaddingRatio))); 351 } else { 352 squareSizeCss = 30; 353 } 354 } 355 if (squareSizeCss < 20) { squareSizeCss = 20; } 356 357 if (squareSizeCss === oldSquareSizeCss) { return; } 358 359 var framePaddingCss = framePaddingRatio * squareSizeCss; 360 var pieceSizeCss = typeof(pieceSize) != "undefined" ? pieceSize : defaultPieceSize(squareSizeCss); 361 var fontMovesSizeCss = typeof(fontMovesSize) != "undefined" ? fontMovesSize : Math.ceil(squareSizeCss * 11 / 30); 362 var fontCommentsSizeCss = typeof(fontCommentsSize) != "undefined" ? fontCommentsSize : Math.ceil(squareSizeCss * 19 / 30); 363 364 myInsertRule(sheet, "body", "padding: " + framePaddingCss + "px;" + (wh ? " height: " + (wh - 2 * framePaddingCss) + "px;" : "")); 365 myInsertRule(sheet, ".boardTable", "width: " + (squareSizeCss * 8) + "px; height: " + (squareSizeCss * 8) + "px;"); 366 myInsertRule(sheet, ".pieceImage", "width: " + pieceSizeCss + "px; height: " + pieceSizeCss + "px;"); 367 myInsertRule(sheet, ".whiteSquare", "width: " + squareSizeCss + "px; height: " + squareSizeCss + "px;"); 368 myInsertRule(sheet, ".highlightWhiteSquare", "width: " + squareSizeCss + "px; height: " + squareSizeCss + "px;"); 369 myInsertRule(sheet, ".blackSquare", "width: " + squareSizeCss + "px; height: " + squareSizeCss + "px;"); 370 myInsertRule(sheet, ".highlightBlackSquare", "width: " + squareSizeCss + "px; height: " + squareSizeCss + "px;"); 371 myInsertRule(sheet, ".container", "width: " + (squareSizeCss * 8) + "px;"); 372 myInsertRule(sheet, ".gameCustomButtons", "height: " + squareSizeCss + "px; padding-bottom: " + Math.floor(squareSizeCss / 6) + "px; font-size: " + fontMovesSizeCss + "px; margin-left: " + Math.floor((2 * squareSizeCss - 5 * Math.floor(squareSizeCss * 0.4)) / 2) + "px;"); 373 myInsertRule(sheet, ".gameButtonCell", "width: " + squareSizeCss + "px;"); 374 myInsertRule(sheet, ".gameButtonSpacer", "width: " + Math.floor(squareSizeCss * 0.4) + "px;"); 375 myInsertRule(sheet, ".gameAnalysis", "height: " + squareSizeCss + "px;"); 376 myInsertRule(sheet, ".gameFlagToMove", "height: " + Math.floor(fontMovesSizeCss / 2) + "px; width: " + Math.floor(fontMovesSizeCss / 2) + "px;"); 377 myInsertRule(sheet, ".gameShowFen", "width: " + (squareSizeCss - 2 * Math.floor(squareSizeCss / 3)) + "px; margin-left:" + Math.floor(squareSizeCss / 3) + "px; margin-right:" + Math.floor(squareSizeCss / 3) + "px;"); 378 myInsertRule(sheet, ".gameMoves", "font-size: " + fontMovesSizeCss + "px;"); 379 myInsertRule(sheet, ".gameTablebase", "font-size: " + fontMovesSizeCss + "px;"); 380 myInsertRule(sheet, ".gameEval", "padding-left: " + squareSizeCss + "px; font-size: " + fontCommentsSizeCss + "px;"); 381 382 SetImagePath("images/" + pieceFont + "/" + (fixedPieceImageSize ? fixedPieceImageSize : pieceSizeCss)); 383 384 for (var ii = 0; ii < oldRules; ii++) { myDeleteRule(sheet, 0); } 385 386 var theObj; 387 if (theObj = document.getElementById("boardTable")) { theObj.style.height = (8 * squareSizeCss) + "px"; } 388 389 oldSquareSizeCss = squareSizeCss; 390} 391 392</script> 393 394<script src="pgn4web.js" type="text/javascript"></script> 395<!-- patch: fonts folder: if the "fonts" folder is relocated please update the next line accordingly --> 396<script src="fonts/chess-informant-NAG-symbols.js" type="text/javascript"></script> 397 398<script type="text/javascript"> 399"use strict"; 400 401SetImageType("png"); 402SetHighlightOption(false); 403SetShortcutKeysEnabled(true); 404myOnResize(); 405 406<!-- AppCheck: myOnOrientationchange --> 407 408 409</script> 410 411</head> 412 413<body onResize="myOnResize();"> 414 415<!-- paste your PGN below and make sure you dont specify an external source with SetPgnUrl() --> 416<form style="display: none;"><textarea style="display: none;" id="pgnText"> 417 418</textarea></form> 419<!-- paste your PGN above and make sure you dont specify an external source with SetPgnUrl() --> 420 421<center> 422<div class="container"> 423<div id="GameBoard"></div> 424<table id="GameCustomButtons" class="gameCustomButtons gameCustomButtonsHidden" cellspacing="0" cellpadding="0" border="0"><tr valign="bottom"> 425<td id="GameAnalysisFlag" class="gameButtonCell" align="center" onclick="clickedGameAnalysisFlag(this, event);"> </td> 426<td class="gameButtonSpacer"></td> 427<td class="gameButtonCell" align="center" onclick="clickedButtonStart(this, event);" title="go to start"><<</td> 428<td class="gameButtonSpacer"></td> 429<td class="gameButtonCell" align="center" onclick="clickedButtonBackward(this, event);" title="move backward"><</td> 430<td class="gameButtonSpacer"></td> 431<td class="gameButtonCell" align="center" onclick="clickedButtonForward(this, event);" title="move forward">></td> 432<td class="gameButtonSpacer"></td> 433<td class="gameButtonCell" align="center" onclick="clickedButtonEnd(this, event);" title="go to end">>></td> 434<td class="gameButtonSpacer"></td> 435<td id="GameAutoUpdateFlag" class="gameButtonCell" align="center" onclick="clickedGameAutoUpdateFlag(this, event);"> </td> 436</tr></table> 437<div class="gameAnalysis gameAnalysisHidden" id="GameAnalysis"> 438<div class="gameEval" id="GameEval" onclick="clickedGameEval(this, event);"> </div> 439</div> 440<div class="gameFlagAndMoves"> 441<span class="gameFlagToMove" id="GameFlagToMove" onclick="clickedGameFlagToMove(this, event);"></span><span class="gameShowFen" onclick="clickedGameShowFen(this, event);"> </span><span class="gameTablebase" id="GameTablebase" onclick="clickedGameTablebase(this, event);" title="probe endgame tablebase">⊥</span><span id="GameMoves" class="gameMoves" onclick="clickedGameMoves(this, event);"> </span> 442</div> 443</div> 444</center> 445 446<script type="text/javascript"> 447"use strict"; 448 449var theObj; 450 451if (typeof(fenString) == "undefined") { fenString = FenStringStart; } 452if (theObj = document.getElementById("pgnText")) { 453 theObj.innerHTML = '[Setup "1"]\n[FEN "' + fenString + '"]\n'; 454} 455 456 457function clickedButtonStart(t,e) { 458 if (e.shiftKey) { 459 analysisSeconds = analysisSeconds <= defaultAnalysisSeconds ? minAnalysisSeconds : defaultAnalysisSeconds; 460 } else { 461 if (CurrentPly > StartPlyVar[0]) { GoToMove(StartPlyVar[0], 0); } 462 } 463} 464 465function clickedButtonBackward(t,e) { 466 if (e.shiftKey) { 467 analysisSeconds = Math.max(Math.floor(analysisSeconds / 1.15), minAnalysisSeconds); 468 } else { 469 if (CurrentPly > StartPlyVar[0]) { GoToMove(CurrentPly - 1); } 470 } 471} 472 473function clickedButtonForward(t,e) { 474 if (e.shiftKey) { 475 analysisSeconds = Math.min(Math.ceil(analysisSeconds * 1.15), maxAnalysisSeconds); 476 } else { 477 if (CurrentPly < StartPlyVar[0] + PlyNumberVar[0]) { GoToMove(CurrentPly + 1); } 478 } 479} 480 481function clickedButtonEnd(t,e) { 482 if (e.shiftKey) { 483 analysisSeconds = analysisSeconds >= defaultAnalysisSeconds ? maxAnalysisSeconds : defaultAnalysisSeconds; 484 } else { 485 if (CurrentPly < StartPlyVar[0] + PlyNumberVar[0]) { GoToMove(StartPlyVar[0] + PlyNumberVar[0], 0); } 486 } 487} 488 489function clickedGameMoves(t,e) { 490 if (e.shiftKey) { 491 save_cache_to_localStorage(); 492 } else { 493 var candidateMove = t.innerHTML.replace(/^\s*(\S+).*$/, "$1"); 494 if (candidateMove) { addPly(candidateMove); } 495 } 496} 497 498function clickedGameEval(t,e) { 499 if (e.shiftKey) { 500 if (!disableEngine) { 501 displayHelp("informant_symbols"); 502 } 503 } else { 504 setDisableEngine(!disableEngine); 505 } 506} 507 508var maxMenInTablebase = 0; 509var minMenInTablebase = 3; 510function probeTablebase() {} 511 512 513// DeploymentCheck: tablebase glue code 514 515// end DeploymentCheck 516 517 518function clickedGameTablebase() { 519 var menPosition = CurrentFEN().replace(/\s.*$/, "").replace(/[0-9\/]/g, "").length; 520 if ((menPosition >= minMenInTablebase) && (menPosition <= maxMenInTablebase)) { 521 probeTablebase(); 522 } else { 523 myAlert("warning: endgame tablebase only supports positions with " + minMenInTablebase + " to " + maxMenInTablebase + " men"); 524 } 525} 526 527function updateTablebaseFlag() { 528 var menPosition = CurrentFEN().replace(/\s.*$/, "").replace(/[0-9\/]/g, "").length; 529 var theObj = document.getElementById("GameTablebase"); 530 var showTablebase = (menPosition >= minMenInTablebase) && (menPosition <= maxMenInTablebase) && (!g_initErrors) && (!disableEngine); 531 if (theObj) { 532 theObj.style.display = showTablebase ? "inline" : "none"; 533 } 534} 535 536 537function clickedGameAutoUpdateFlag(t,e) { 538 if (openerCheck()) { 539 autoUpdate = !autoUpdate; 540 if ((autoUpdate) && ((CurrentFEN() !== window.opener.CurrentFEN()) || (!g_backgroundEngine && !disableEngine))) { 541 window.opener.showEngineAnalysisBoard(disableEngine); 542 } 543 544<!-- AppCheck: clickedGameAutoUpdateFlag --> 545 546 } 547 updateGameAutoUpdateFlag(); 548} 549 550function clickedGameAnalysisFlag(t,e) { 551 if (e.shiftKey) { 552 cache_clear(); 553 clear_cache_from_localStorage(); 554 } else { 555 if (g_backgroundEngine) { 556 StopBackgroundEngine(); 557 } else { 558 if (openerCheck()) { 559 window.opener.showEngineAnalysisBoard(disableEngine); 560 } else { 561 StartEngineAnalysis(); 562 } 563 } 564 } 565} 566 567function clickedGameFlagToMove(t,e) { 568 if (e.shiftKey) { 569 if (autoPlay) { stopAutoPlay(); } 570 else { startAutoPlay(); } 571 } else { 572 if ((!autoPlay) && (!IsCheck(PieceCol[MoveColor][0], PieceRow[MoveColor][0], MoveColor))) { 573 if ((CurrentPly > StartPly) && (Moves[CurrentPly - 1] == "--")) { MoveBackward(1); } 574 else { addPly("--"); } 575 } 576 } 577} 578 579function clickedGameShowFen(t, e) { 580 if (e.shiftKey) { displayFenData(); } 581 else if (PlyNumber > 0) { 582 var oldCurrentPly = CurrentPly; 583 MoveBackward(CurrentPly - StartPly, true); 584 displayFenData(true); 585 MoveForward(oldCurrentPly - CurrentPly); 586 } 587} 588 589function pgn4web_handleKey(e) { 590 var keycode, colRow, colRowList, theObj; 591 592 if (!e) { e = window.event; } 593 594 keycode = e.keyCode; 595 596 if (e.altKey || e.ctrlKey || e.metaKey) { return true; } 597 598 if (!shortcutKeysEnabled) { return true; } 599 600 switch (keycode) { 601 602 case 32: // space 603 if (theObj = document.getElementById("GameMoves")) { 604 clickedGameMoves(theObj, {shiftKey: false}); 605 } 606 break; 607 608 case 189: // dash 609 if (colRowList = prompt("Enter shortcut square coordinates to click:", "")) { 610 colRowList = colRowList.toUpperCase().replace(/[^A-Z0-9]/g,""); 611 while (colRow = colRowFromSquare(colRowList)) { 612 boardOnClick[colRow.col][colRow.row]({"id": "img_tcol" + colRow.col + "trow" + colRow.row}, e); 613 colRowList = colRowList.substr(2); 614 } 615 } 616 break; 617 618 case 90: // z 619 if (e.shiftKey) { window.open(pgn4web_project_url); } 620 else { displayDebugInfo(); } 621 break; 622 623 case 37: // left-arrow 624 case 74: // j 625 backButton(e); 626 break; 627 628 case 38: // up-arrow 629 case 72: // h 630 startButton(e); 631 break; 632 633 case 39: // right-arrow 634 case 75: // k 635 forwardButton(e); 636 break; 637 638 case 40: // down-arrow 639 case 76: // l 640 endButton(e); 641 break; 642 643<!-- AppCheck: pgn4web_handleKey --> 644 645 case 82: // r 646 setDisableEngine(true); 647 break; 648 649 case 89: // y 650 setDisableEngine(false); 651 break; 652 653 case 70: // f 654 clickedGameFlagToMove(null, {shiftKey: false}); 655 break; 656 657 default: 658 return true; 659 } 660 return stopEvProp(e); 661} 662 663 664var pgn4web_chess_engine_id = "garbochess-pgn4web-" + pgn4web_version; 665 666var engineWorker = "libs/garbochess/garbochess.js"; 667 668var g_backgroundEngine; 669var g_topNodesPerSecond = 0; 670var g_ev = ""; 671var g_pv = ""; 672var g_depth = ""; 673var g_nodes = ""; 674var g_initErrors = 0; 675var g_lastFenError = ""; 676 677function InitializeBackgroundEngine() { 678 var theObj; 679 680 if (!g_backgroundEngine) { 681 try { 682 g_backgroundEngine = new Worker(engineWorker); 683 g_backgroundEngine.addEventListener("message", function (e) { 684 var theObj; 685 if ((e.data.match("^pv")) && (fenString == CurrentFEN())) { 686 var matches = e.data.substr(3, e.data.length - 3).match(/Ply:(\d+) Score:(-*\d+) Nodes:(\d+) NPS:(\d+) (.*)/); 687 if (matches) { 688 g_depth = parseInt(matches[1], 10); 689 if (isNaN(g_ev = parseInt(matches[2], 10))) { 690 g_ev = ""; 691 } else { 692 var maxEv = 99.9; 693 g_ev = Math.round(g_ev / 100) / 10; 694 if (g_ev < -maxEv) { g_ev = -maxEv; } else if (g_ev > maxEv) { g_ev = maxEv; } 695 if (fenString.indexOf(" b ") !== -1) { g_ev = -g_ev; } 696 } 697 g_nodes = parseInt(matches[3], 10); 698 var nodesPerSecond = parseInt(matches[4], 10); 699 g_topNodesPerSecond = Math.max(nodesPerSecond, g_topNodesPerSecond); 700 g_pv = matches[5].replace(/(^\s+|\s*[x+=]|\s+$)/g, "").replace(/\s*stalemate/, "=").replace(/\s*checkmate/, "#"); // patch: pgn notation: remove/add '+' 'x' '=' chars for full chess informant style or pgn style for the game text 701 validateSearchWithCache(); 702 if (theObj = document.getElementById("GameEval")) { 703 theObj.innerHTML = ev2NAG(g_ev); 704 theObj.title = (g_ev > 0 ? " +" : " ") + g_ev + (g_ev == Math.floor(g_ev) ? ".0 " : " "); 705 } 706 if (theObj = document.getElementById("GameMoves")) { 707 theObj.innerHTML = g_pv; 708 theObj.title = g_pv; 709 } 710 updateGameAnalysisFlag(); 711 if (detectGameEnd(g_pv, "")) { StopBackgroundEngine(); } 712 } 713 } else if (e.data.match("^message Invalid FEN")) { 714 if (theObj = document.getElementById("GameEval")) { 715 theObj.innerHTML = NAG[2]; 716 theObj.title = "?"; 717 } 718 if (theObj = document.getElementById("GameMoves")) { 719 theObj.innerHTML = "invalid position"; 720 theObj.title = e.data.replace(/^message /, ""); 721 } 722 if (fenString != g_lastFenError) { 723 g_lastFenError = fenString; 724 myAlert("error: engine: " + e.data.replace(/^message /, "") + "\n" + fenString, false); 725 } 726 } 727 }, false); 728 g_initErrors = 0; 729 return true; 730 } catch(e) { 731 if (theObj = document.getElementById("GameEval")) { 732 theObj.innerHTML = useNAGeval ? translateNAGs("$255") + "<span class='NAGs'> </span>" + translateNAGs("$147") : "X X"; 733 theObj.title = "engine analysis unavailable"; 734 } 735 if (theObj = document.getElementById("GameMoves")) { 736 theObj.innerHTML = " "; 737 theObj.title = ""; 738 } 739 if (!g_initErrors++) { myAlert("error: engine exception " + e); } 740 updateTablebaseFlag(); 741 return false; 742 } 743 } 744} 745 746 747var moderateDefiniteThreshold = 1.85; 748var slightModerateThreshold = 0.85; 749var equalSlightThreshold = 0.25; 750 751var useNAGeval = (NAGstyle != 'default'); 752function ev2NAG(ev) { 753 if ((ev === null) || (ev === "") || (isNaN(ev = parseFloat(ev)))) { return ""; } 754 if (!useNAGeval) { return (ev > 0 ? "+" : "") + ev + (ev == Math.floor(ev) ? ".0" : ""); } 755 if (ev < -moderateDefiniteThreshold) { return NAG[19]; } // -+ 756 if (ev > moderateDefiniteThreshold) { return NAG[18]; } // +- 757 if (ev < -slightModerateThreshold) { return NAG[17]; } // -/+ 758 if (ev > slightModerateThreshold) { return NAG[16]; } // +/- 759 if (ev < -equalSlightThreshold) { return NAG[15]; } // =/+ 760 if (ev > equalSlightThreshold) { return NAG[14]; } // +/= 761 return NAG[11]; // = 762} 763 764 765var localStorage_supported; 766try { localStorage_supported = ((enableLocalStorage) && ("localStorage" in window) && (window["localStorage"] !== null)); } 767catch (e) { localStorage_supported = false; } 768 769var cache_local_storage_prefix = "pgn4web_chess_engine_cache_"; // default "pgn4web_chess_engine_cache_" 770 771function load_cache_from_localStorage() { 772 if (!localStorage_supported) { return; } 773 if (pgn4web_chess_engine_id != localStorage[cache_local_storage_prefix + "id"]) { 774 clear_cache_from_localStorage(); 775 localStorage[cache_local_storage_prefix + "id"] = pgn4web_chess_engine_id; 776 return; 777 } 778 if (cache_pointer = localStorage[cache_local_storage_prefix + "pointer"]) { 779 cache_pointer = parseInt(cache_pointer, 10) % cache_max; 780 } else { cache_pointer = -1; } 781 if (cache_fen = localStorage[cache_local_storage_prefix + "fen"]) { 782 cache_fen = cache_fen.split(","); 783 } else { cache_fen = new Array(); } 784 if (cache_ev = localStorage[cache_local_storage_prefix + "ev"]) { 785 cache_ev = cache_ev.split(",").map(parseFloat); 786 if (typeof(cache_ev.map == "function")) { cache_ev = cache_ev.map(parseFloat); } 787 } else { cache_ev = new Array(); } 788 if (cache_pv = localStorage[cache_local_storage_prefix + "pv"]) { 789 cache_pv = cache_pv.split(","); 790 } else { cache_pv = new Array(); } 791 if (cache_depth = localStorage[cache_local_storage_prefix + "depth"]) { 792 cache_depth = cache_depth.split(","); 793 if (typeof(cache_depth.map == "function")) { cache_depth = cache_depth.map(parseFloat); } 794 } else { cache_depth = new Array(); } 795 cache_needs_sync = 0; 796 if ((cache_fen.length !== cache_ev.length) || (cache_fen.length !== cache_pv.length) || (cache_fen.length !== cache_depth.length)) { 797 clear_cache_from_localStorage(); 798 cache_clear(); 799 } 800} 801 802function save_cache_to_localStorage() { 803 if (!localStorage_supported) { return; } 804 if (!cache_needs_sync) { return; } 805 localStorage[cache_local_storage_prefix + "pointer"] = cache_pointer; 806 localStorage[cache_local_storage_prefix + "fen"] = cache_fen.toString(); 807 localStorage[cache_local_storage_prefix + "ev"] = cache_ev.toString(); 808 localStorage[cache_local_storage_prefix + "pv"] = cache_pv.toString(); 809 localStorage[cache_local_storage_prefix + "depth"] = cache_depth.toString(); 810 cache_needs_sync = 0; 811} 812 813function clear_cache_from_localStorage() { 814 if (!localStorage_supported) { return; } 815 localStorage.removeItem(cache_local_storage_prefix + "pointer"); 816 localStorage.removeItem(cache_local_storage_prefix + "fen"); 817 localStorage.removeItem(cache_local_storage_prefix + "ev"); 818 localStorage.removeItem(cache_local_storage_prefix + "pv"); 819 localStorage.removeItem(cache_local_storage_prefix + "depth"); 820 localStorage.removeItem(cache_local_storage_prefix + "nodes"); // backward compatibility 821 cache_needs_sync++; 822} 823 824function cacheDebugInfo() { 825 var dbg = ""; 826 if (localStorage_supported) { 827 dbg += " cache="; 828 try { 829 dbg += num2string(localStorage[cache_local_storage_prefix + "pointer"].length + localStorage[cache_local_storage_prefix + "fen"].length + localStorage[cache_local_storage_prefix + "ev"].length + localStorage[cache_local_storage_prefix + "pv"].length + localStorage[cache_local_storage_prefix + "depth"].length); 830 } catch(e) { 831 dbg += "0"; 832 } 833 } 834 return dbg; 835} 836 837var cache_pointer = -1; 838var cache_max = 2000; // ~ 16 games of 60 moves ~ 256KB of local storage 839var cache_fen = new Array(); 840var cache_ev = new Array(); 841var cache_pv = new Array(); 842var cache_depth = new Array(); 843 844var cache_needs_sync = 0; 845 846load_cache_from_localStorage(); 847 848function validateSearchWithCache() { 849 var id = cache_fen_lastIndexOf(fenString); 850 if (id == -1) { 851 cache_last = cache_pointer = (cache_pointer + 1) % cache_max; 852 cache_fen[cache_pointer] = fenString.replace(/\s+\d+\s+\d+\s*$/, ""); 853 cache_ev[cache_pointer] = g_ev; 854 cache_pv[cache_pointer] = g_pv; 855 cache_depth[cache_pointer] = g_depth; 856 cache_needs_sync++; 857 } else { 858 if (g_depth > cache_depth[id]) { 859 cache_ev[id] = g_ev; 860 cache_pv[id] = g_pv; 861 cache_depth[id] = g_depth; 862 cache_needs_sync++; 863 } else { 864 g_ev = parseFloat(cache_ev[id]); 865 g_pv = cache_pv[id]; 866 g_depth = parseInt(cache_depth[id], 10); 867 } 868 } 869 if (cache_needs_sync > cache_max / 10) { save_cache_to_localStorage(); } 870} 871 872var cache_last = 0; 873function cache_fen_lastIndexOf(fenString) { 874 fenString = fenString.replace(/\s+\d+\s+\d+\s*$/, ""); 875 if (fenString === cache_fen[cache_last]) { return cache_last; } 876 if (typeof(cache_fen.lastIndexOf) == "function") { return (cache_last = cache_fen.lastIndexOf(fenString)); } 877 for (var n = cache_fen.length - 1; n >= 0; n--) { 878 if (fenString === cache_fen[n]) { return (cache_last = n); } 879 } 880 return -1; 881} 882 883function cache_clear() { 884 cache_pointer = -1; 885 cache_fen = new Array(); 886 cache_ev = new Array(); 887 cache_pv = new Array(); 888 cache_depth = new Array(); 889} 890 891 892function StopBackgroundEngine() { 893 if (analysisTimeout) { clearTimeout(analysisTimeout); } 894 if (g_backgroundEngine) { 895 g_backgroundEngine.terminate(); 896 g_backgroundEngine = null; 897 updateGameAnalysisFlag(); 898 if ((autoPlay) && (g_pv !== "")) { 899 if (detectGameEnd(g_pv, CurrentFEN()) === true) { 900 stopAutoPlay(); 901 } else { 902 addPly(g_pv.replace(/^\s*(\S+).*$/, "$1")); 903 } 904 } 905 g_pv = ""; 906 } 907 updateTablebaseFlag(); 908} 909 910var analysisTimeout; 911function setAnalysisTimeout(seconds) { 912 if (analysisTimeout) { clearTimeout(analysisTimeout); } 913 analysisTimeout = setTimeout("analysisTimeout = null; save_cache_to_localStorage(); StopBackgroundEngine();", seconds * 1000); 914} 915 916function StartEngineAnalysis() { 917 StopBackgroundEngine(); 918 if (InitializeBackgroundEngine()) { 919 fenString = CurrentFEN(); 920 g_backgroundEngine.postMessage("position " + fenString); 921 g_backgroundEngine.postMessage("analyze"); 922 setAnalysisTimeout(analysisSeconds); 923 } 924 updateTablebaseFlag(); 925} 926 927 928function openerCheck(skipSignature) { 929 try { // bugfix: Opera generating bogus security error 930 return ((typeof(window.opener) == "object") && (window.opener !== null) && (!window.opener.closed) && (typeof(window.opener.pgn4web_engineWinSignature) != "undefined") && ((window.opener.pgn4web_engineWinSignature === engineSignature) || (skipSignature))); 931 } catch(e) { return false; } 932} 933 934function updateGameAnalysisFlag() { 935 var theObj = document.getElementById("GameAnalysisFlag"); 936 if (theObj = document.getElementById("GameAnalysisFlag")) { 937 if (g_backgroundEngine) { 938 theObj.innerHTML = "="; 939 theObj.title = "pause engine analysis"; 940 } else { 941 if ((openerCheck()) && (CurrentFEN() != window.opener.CurrentFEN())) { 942 theObj.innerHTML = "+"; 943 theObj.title = "update analysis board"; 944 } else if (disableEngine) { 945 theObj.innerHTML = " "; 946 theObj.title = ""; 947 } else { 948 theObj.innerHTML = "·"; 949 theObj.title = "restart engine analysis"; 950 } 951 } 952 } 953} 954 955function updateGameAutoUpdateFlag() { 956 var theObj = document.getElementById("GameAutoUpdateFlag"); 957 if (theObj) { 958 if (openerCheck()) { 959 if (autoUpdate) { 960 theObj.innerHTML = "="; 961 theObj.title = "pause auto updating analysis board"; 962 } else { 963 theObj.innerHTML = "+"; 964 theObj.title = "start auto updating analysis board"; 965 } 966 967<!-- AppCheck: updateGameAutoUpdateFlag --> 968 969 } else { 970 theObj.innerHTML = " "; 971 theObj.title = ""; 972 } 973 } 974} 975 976function updateGameFlagToMove() { 977 var theObj = document.getElementById("GameFlagToMove"); 978 if (theObj) { 979 theObj.style.backgroundColor = CurrentPly % 2 ? "black" : "white"; 980 theObj.title = (CurrentPly % 2 ? "black" : "white") + " to move" + (autoPlay ? ": autoplay" : ""); 981 } 982} 983 984 985var firstCustomFunctionOnPgnTextLoad = true; 986function customFunctionOnPgnTextLoad() { 987 if (firstCustomFunctionOnPgnTextLoad) { 988 firstCustomFunctionOnPgnTextLoad = false; 989 setDisableEngine(disableEngine); 990 var theObj; 991 if (theObj = document.getElementById("GameAnalysis")) { 992 theObj.className = "gameAnalysis"; 993 } 994 if ((!disableInputs) && (!autoPlay) && (theObj = document.getElementById("GameCustomButtons"))) { 995 theObj.className = "gameCustomButtons"; 996 } 997 998 // undocumented parameter for internal use after pgn4web has started 999 thisRegExp = /(&|\?)(engineSignature|es)=([1-9][0-9]*)(&|$)/i; 1000 if (thisParamString.match(thisRegExp) !== null) { 1001 engineSignature = parseInt(unescape(thisParamString.match(thisRegExp)[3]), 10); 1002 } 1003 updateGameAnalysisFlag(); 1004 updateGameAutoUpdateFlag(); 1005 } 1006} 1007 1008function customFunctionOnMove() { 1009 var theObj; 1010 1011 updateGameFlagToMove(); 1012 1013 if (!disableEngine) { 1014 var id = cache_fen_lastIndexOf(CurrentFEN()); 1015 if (theObj = document.getElementById("GameMoves")) { 1016 theObj.innerHTML = (id != -1) ? cache_pv[id] : ""; 1017 theObj.title = ""; 1018 } 1019 if (theObj = document.getElementById("GameEval")) { 1020 theObj.innerHTML = (id != -1) ? ev2NAG(parseFloat(cache_ev[id])) : ""; 1021 theObj.title = ""; 1022 } 1023 StartEngineAnalysis(); 1024 } 1025 1026 if (clickFromCol !== "") { 1027 highlightSquare("abcdefgh".indexOf(clickFromCol), "12345678".indexOf(clickFromRow), false); 1028 } 1029 clickFromCol = ""; 1030 clickFromRow = ""; 1031 clickFromPiece = ""; 1032 1033 updateTablebaseFlag(); 1034 updateGameAnalysisFlag(); 1035 updateGameAutoUpdateFlag(); 1036} 1037 1038function customDebugInfo() { 1039 var dbg = "autoUpdate=" + autoUpdate; 1040 dbg += " engine="; 1041 if (disableEngine) { dbg += "disabled"; } 1042 else if (!window.Worker) { dbg += "unavailable"; } 1043 else { dbg += (g_backgroundEngine ? (autoPlay ? "autoplay" : "pondering") : "idle") + " analysisSeconds=" + analysisSeconds + " topNodesPerSecond=" + num2string(g_topNodesPerSecond) + cacheDebugInfo(); } 1044 return dbg; 1045} 1046 1047function num2string(num) { 1048 var unit = ""; 1049 if (num >= Math.pow(10, 12)) { num = Math.round(num / Math.pow(10, 11)) / 10; unit = "T"; } 1050 else if (num >= Math.pow(10, 9)) { num = Math.round(num / Math.pow(10, 8)) / 10; unit = "G"; } 1051 else if (num >= Math.pow(10, 6)) { num = Math.round(num / Math.pow(10, 5)) / 10; unit = "M"; } 1052 else if (num >= Math.pow(10, 3)) { num = Math.round(num / Math.pow(10, 2)) / 10; unit = "K"; } 1053 if ((unit !== "") && (num === Math.floor(num))) { num += ".0"; } 1054 return num + unit; 1055} 1056 1057 1058var overwrittenPly = ""; 1059var overwrittenPlyNumber; 1060function addPly(thisPly) { 1061 if (!thisPly) { return; } 1062 if ((PlyNumber < CurrentPly + 1 - StartPly) || (thisPly !== Moves[CurrentPly])) { 1063 overwrittenPly = Moves[CurrentPly]; 1064 Moves[CurrentPly] = MovesVar[0][CurrentPly] = thisPly; 1065 overwrittenPlyNumber = PlyNumber; 1066 PlyNumber = PlyNumberVar[0] = CurrentPly + 1 - StartPly; 1067 } else { 1068 overwrittenPly = ""; 1069 } 1070 MoveForward(1); 1071} 1072 1073function customFunctionOnAlert(msg) { 1074 if (msg.indexOf("error: invalid ply") !== 0) { return; } 1075 stopAlertPrompt(); 1076 if (overwrittenPly === "") { return; } 1077 Moves[CurrentPly] = MovesVar[0][CurrentPly] = overwrittenPly; 1078 PlyNumber = PlyNumberVar[0] = overwrittenPlyNumber; 1079 overwrittenPly = ""; 1080} 1081 1082for (var cc=0; cc<8; cc++) { for (var rr=0; rr<8; rr++) { 1083 boardShortcut("ABCDEFGH".charAt(cc) + "12345678".charAt(rr), "explore variations by clicking from/to squares for the intended move", detectClick, false); 1084} } 1085 1086var doubleclickH8Timeout = null; 1087var clickFromCol = ""; 1088var clickFromRow = ""; 1089var clickFromPiece = ""; 1090function detectClick(t,e) { 1091 if (disableInputs) { return; } 1092 var matches = t.id.match(/img_tcol([0-7])trow([0-7])/); 1093 if (!matches) { return; } 1094 var thisCol = IsRotated ? 7 - matches[1] : matches[1]; 1095 var thisColChar = "abcdefgh".charAt(thisCol); 1096 var thisRow = IsRotated ? matches[2] : 7 - matches[2]; 1097 var thisRowChar = "12345678".charAt(thisRow); 1098 if (e !== null) { 1099 if (doubleclickH8Timeout !== null) { 1100 clearTimeout(doubleclickH8Timeout); 1101 doubleclickH8Timeout = null; 1102 if ((thisColChar == "h") && (thisRowChar == "8")) { 1103 displayHelp(); 1104 return; 1105 } 1106 } 1107 if ((thisColChar == "h") && (thisRowChar == "8")) { 1108 doubleclickH8Timeout = setTimeout('doubleclickH8Timeout = null;', 333); 1109 } 1110 } 1111 if (clickFromCol !== "") { 1112 var thisCurrentPly = CurrentPly; 1113 setTimeout('highlightSquare("abcdefgh".indexOf("' + clickFromCol + '"), "12345678".indexOf("' + clickFromRow + '"), false);', 77); 1114 var clickToCol = thisColChar; 1115 var clickToRow = thisRowChar; 1116 if ((clickFromCol !== clickToCol) || (clickFromRow !== clickToRow)) { 1117 var thisMove = clickFromPiece + clickFromCol + clickFromRow + clickToCol + clickToRow; 1118 if (thisMove == "Ke1g1") { thisMove = "O-O"; } 1119 else if (thisMove == "Ke1c1") { thisMove = "O-O-O"; } 1120 else if (thisMove == "Ke8g8") { thisMove = "O-O"; } 1121 else if (thisMove == "Ke8c8") { thisMove = "O-O-O"; } 1122 else if (("KQRBN".indexOf(thisMove.charAt(0)) == -1) && (thisMove.charAt(3) == (CurrentPly % 2 ? "1" : "8"))) { 1123 thisMove += "Q"; 1124 } 1125 if (autoPlay) { stopAutoPlay(); } 1126 addPly(thisMove); 1127 } 1128 clickFromCol = clickFromRow = clickFromPiece = ""; 1129 if (CurrentPly === thisCurrentPly) { 1130 detectClick({id: "img_tcol" + matches[1] + "trow" + matches[2]}, null); 1131 } 1132 } else if ((CurrentPly > StartPly) && (matches = Moves[CurrentPly - 1].match(new RegExp("^(.*" + thisColChar + thisRowChar + ")([QRBN])$", "")))) { 1133 MoveBackward(1); 1134 addPly(matches[1] + "RBNQ".charAt("QRBN".indexOf(matches[2]))); 1135 } else { 1136 cc = CurrentPly % 2; 1137 for (var ii=0; ii<16; ii++) { 1138 if ((PieceCol[cc][ii] == thisCol) && (PieceRow[cc][ii] == thisRow)) { 1139 if (PieceType[cc][ii] != -1) { 1140 clickFromPiece = " KQRBNP".charAt(PieceType[cc][ii]); 1141 if (clickFromPiece == "P") { clickFromPiece = ""; } 1142 clickFromCol = thisColChar; 1143 clickFromRow = thisRowChar; 1144 setTimeout('highlightSquare(' + thisCol + ', ' + thisRow + ', true);', 77); 1145 } 1146 } 1147 } 1148 } 1149} 1150 1151function detectGameEnd(pv, FEN) { 1152 if ((pv !== "") && (pv.match(/^[#=]/))) { return true; } 1153 var matches = FEN.match(/\s*\S+\s+\S+\s+\S+\s+\S+\s+(\d+)\s+\S+\s*/); 1154 if (matches) { 1155 if (parseInt(matches[1], 10) > 100) { return true; } 1156 } 1157 return false; 1158} 1159 1160function startAutoPlay() { 1161 if ((disableEngine) || (!window.Worker)) { return; } 1162 var theObj = document.getElementById("GameCustomButtons"); 1163 if (theObj) { 1164 theObj.className = "gameCustomButtons gameCustomButtonsHidden"; 1165 } 1166 autoPlay = true; 1167 updateGameFlagToMove(); 1168 if (autoUpdate) { 1169 autoUpdate = false; 1170 updateGameAutoUpdateFlag(); 1171 } 1172 if (!g_backgroundEngine) { StartEngineAnalysis(); } 1173} 1174 1175function stopAutoPlay() { 1176 autoPlay = false; 1177 StopBackgroundEngine(); 1178 updateGameFlagToMove(); 1179 var theObj = document.getElementById("GameCustomButtons"); 1180 if ((!disableInputs) && (!autoPlay) && (theObj)) { 1181 theObj.className = "gameCustomButtons"; 1182 } 1183} 1184 1185 1186var engineSignature = -1; 1187 1188function updateFEN(newFEN) { 1189 if (autoPlay) { stopAutoPlay(); } 1190 var theObj = document.getElementById("pgnText"); 1191 if (theObj) { 1192 theObj.innerHTML = '[Setup "1"]\n[FEN "' + newFEN + '"]\n'; 1193 } 1194 firstStart = true; 1195 start_pgn4web(); 1196} 1197 1198function setDisableEngine(de) { 1199 if (disableEngine = de) { 1200 if (autoPlay) { stopAutoPlay(); } 1201 else { StopBackgroundEngine(); } 1202 var theObj; 1203 if (theObj = document.getElementById("GameEval")) { 1204 theObj.innerHTML = useNAGeval ? translateNAGs("$147") : "X"; 1205 theObj.title = "engine analysis disabled"; 1206 } 1207 if (theObj = document.getElementById("GameMoves")) { 1208 theObj.innerHTML = ""; 1209 theObj.title = ""; 1210 } 1211 updateGameAnalysisFlag(); 1212 } else { 1213 StartEngineAnalysis(); 1214 } 1215} 1216 1217function sameEngineDisabled(engineDisabled) { 1218 return ((typeof(engineDisabled) == "undefined") || (engineDisabled && disableEngine) || (!engineDisabled && !disableEngine)); 1219} 1220 1221 1222function customFunctionOnTouch(deltaX, deltaY) { 1223 if (disableInputs) { return; } 1224 if (Math.max(Math.abs(deltaX), Math.abs(deltaY)) < 13) { return; } 1225 if (Math.abs(deltaY) > 1.5 * Math.abs(deltaX)) { // vertical up or down 1226 GoToMove(StartPlyVar[CurrentVar] + (deltaY > 0 ? PlyNumberVar[CurrentVar] : 0)); 1227 } else if (Math.abs(deltaX) > 1.5 * Math.abs(deltaY)) { // horizontal left or right 1228 GoToMove(CurrentPly + sign(deltaX)); 1229 } 1230} 1231 1232// touchGestures_helpActions unchanged 1233touchGestures_helpText = [ "go to variation end", "go to variation start", "move forward", "move backward" ]; 1234 1235<!-- AppCheck: footer --> 1236 1237</script> 1238 1239</body> 1240 1241</html> 1242