UNPKG

jocly

Version:

Board games 3D/2D UI and AI web library

1 lines 25.7 kB
"use strict";function _typeof(e){"@babel/helpers - typeof";return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}try{exports.Game=JocGame=function(){},exports.Board=JocBoard=function(){},exports.Move=JocMove=function(){}}catch(e){global.JocGame=exports.Game=function(){},global.JocBoard=exports.Board=function(){},global.JocMove=exports.Move=function(){},function(){var e=require,t=e("./jocly.util.js");global.MersenneTwister=t.MersenneTwister,global.JocUtil=t.JocUtil,global.JoclyUCT=e("./jocly.uct.js").JoclyUCT}()}JocGame.PLAYER_A=1,JocGame.PLAYER_B=-1,JocGame.DRAW=2,"undefined"!=typeof document?JocGame.CLICK="ontouchstart"in document.documentElement?"touchstart":"click":JocGame.CLICK="click",JocGame.MOUSEMOVE_EVENT="touchmove mousemove",JocGame.MOUSEDOWN_EVENT="touchstart mousedown",JocGame.MOUSEUP_EVENT="touchend mouseup joclyclick",JocGame.MAX_VALUE=Math.pow(2,53),JocGame.prototype={},JocGame.prototype.Init=function(e){this.mWho=JocGame.PLAYER_A,this.mViewAs=JocGame.PLAYER_A,this.mTopLevel=3,this.mLoopMax=300,this.mPreventRepeat=!1,e&&(this.mOptions=e.game,this.mViewOptions=e.view,this.mSkin=this.mViewOptions.skins[0].name,this.mNotation=!1,this.mShowMoves=this.mViewOptions.useShowMoves,this.mSounds=!!this.mViewOptions.sounds,this.mAutoComplete=!1,void 0!==this.mOptions.level&&(this.mTopLevel=this.mOptions.level),void 0!==this.mOptions.loopMax&&(this.mLoopMax=this.mOptions.loopMax),this.mVisitedBoards={},void 0!==this.mOptions.viewAs?this.mViewAs=this.mOptions.viewAs:this.mOptions.viewAs=this.mViewAs),this.mNextSchedule=null,this.mPlayedMoves=[],this.mFullPlayedMoves=[],this.mViewInited=!1,this.mGameInited=!1,e&&e.initial?this.GameInitGame(e.initial):this.GameInitGame(),this.mBoard=new(this.GetBoardClass())(this),this.mBoard.InitialPosition&&this.mBoard.InitialPosition(this),this.mBoard.mMoves=[],this.mBoard.mWho=this.mWho,this.listeners=[]},JocGame.prototype.AddListener=function(e){this.listeners.push(e)},JocGame.prototype.RemoveListener=function(e){for(var t=this.listeners.length-1;t>=0;t--)this.listeners[t]==e&&this.listeners.splice(t,1)},JocGame.prototype.DispatchMessage=function(e){var t=this;this.listeners.forEach(function(o){o.call(t,e)})},JocGame.prototype.HumanMove=function(e){this.DispatchMessage({type:"human-move",move:e})},JocGame.prototype.MakeMove=function(e){this.HumanMove(e)},JocGame.prototype.MachineMove=function(e){this.DispatchMessage({type:"machine-move",result:e})},JocGame.prototype.MachineProgress=function(e){this.DispatchMessage({type:"machine-progress",progress:e})},JocGame.prototype.PlayMove=function(e){var t=this;return new Promise(function(o,i){t.mOldBoard=new(t.GetBoardClass())(t),t.mOldBoard.CopyFrom(t.mBoard),t.ApplyMove(e),t.MoveShown=function(){delete t.MoveShown,o()},t.mBoard.PlayedMove(t,e)&&(delete t.MoveShown,o())})},JocGame.prototype.InvertWho=function(){var e=this.GetWho();this.SetWho(-e)},JocGame.prototype.AttachElement=function(e,t){t=t||{};var o=this;return this.widget=e,new Promise(function(e,t){if(o.gamePreAttachProto)t(new Error("Game already attached"));else{var i={meta:{"jocly-xdview.js":{globals:{jQuery:"jquery.js",THREE:"three.js"}}}};i.meta["games/"+o.module+"/"+o.name+"-view.js"]={globals:{xdview:"jocly-xdview.js",jQuery:"jquery.js",THREE:"three.js"}}}SystemJS.config(i),Promise.all([SystemJS.import("jocly-xdview.js"),SystemJS.import("games/"+o.module+"/"+o.name+"-view.js")]).then(function(t){var i=t[0],s=t[1];o.gamePreAttachProto=Object.getPrototypeOf(o);var a=Object.assign({},o.gamePreAttachProto,i.view.Game,s.view.Game);Object.setPrototypeOf(o,a);var r=o.mBoardClass;o.boardPreAttachProto=r.prototype,Object.assign(r.prototype,o.boardPreAttachProto,i.view.Board,s.view.Board);var n=o.mMoveClass;o.movePreAttachProto=n.prototype,Object.assign(n.prototype,o.movePreAttachProto,s.view.Move),o.mGeometry={width:o.widget.clientWidth,height:o.widget.clientHeight},o.mWidget=jQuery(o.widget);var m=o.mViewOptions&&o.mViewOptions.defaultOptions;if(m){var h={mSkin:"skin",mNotation:"notation",mSounds:"sounds",mShowMoves:"moves",mAutoComplete:"autocomplete"};for(var d in h)void 0!==m[h[d]]&&(o[d]=m[h[d]])}o.UpdateSounds(),e()},function(e){t(e)})})},JocGame.prototype.DetachElement=function(){var e=this;return this.widget=element,new Promise(function(t,o){e.gamePreAttachProto?t():o(new Error("Game not attached"))})},JocGame.prototype.GetBoardClass=function(){return this.mBoardClass},JocGame.prototype.GetMoveClass=function(){return this.mMoveClass},JocGame.prototype.CreateMove=function(e){return new this.mMoveClass(e)},JocGame.prototype.CloneBoard=function(e){var t=new(this.GetBoardClass())(this);return t.CopyFrom(e),t},JocGame.prototype.InitView=function(){console.log("Abstract InitView called")},JocGame.prototype.LoadCss=function(){document.querySelectorAll("head link[class='jocly-css']").forEach(function(e){e.parentNode.removeChild(e)});var e=this,t=document.querySelector("head");(this.mViewOptions.css||[]).forEach(function(o){var i=document.createElement("link");i.setAttribute("rel","stylesheet"),i.setAttribute("type","text/css"),i.setAttribute("class","jocly-css"),i.setAttribute("href",e.mViewOptions.fullPath+"/"+o),t.appendChild(i)})},JocGame.prototype.GameInitView=function(){this.mGeometry.width>0&&this.mGeometry.height>0&&(this.LoadCss(),this.InitView(),this.mViewInited=!0)},JocGame.prototype.DestroyView=function(){this.mWidget&&this.mWidget.empty()},JocGame.prototype.GameDestroyView=function(){this.mViewInited&&(this.DestroyView(),this.mViewInited=!1)},JocGame.prototype.CanPlaySound=function(e){return!0},JocGame.prototype.UpdateSounds=function(){function e(e,o,i){var s=$("<audio/>").attr("id","jocly-sound-"+e).attr("preload","auto");$("<source/>").attr("src",o+"/res/sounds/"+i+".ogg").attr("type","audio/ogg").appendTo(s),$("<source/>").attr("src",o+"/res/sounds/"+i+".mp3").attr("type","audio/mp3").appendTo(s),s.appendTo(t)}var t=$("#jocly-sounds");0==t.length&&(t=$("<div/>").attr("id","jocly-sounds").css({display:"none"}).appendTo($("body"))),t.empty();var o={useraction:"bells1",usermove:"bells1",win:"winblues",loss:"lose",end:"draw"};for(var i in o)e(i,this.config.baseURL,o[i]);if(this.config.view.sounds)for(var i in this.config.view.sounds)$("#jocly-sound-"+i).remove(),this.config.view.sounds[i]&&this.config.view.sounds[i]&&e(i,this.config.baseURL+"games/"+this.config.model.module,this.config.view.sounds[i])},JocGame.prototype.PlaySound=function(e){if(this.CanPlaySound(e)){var t=document.getElementById("jocly-sound-"+e);if(t&&this.mSounds)if(void 0===this.mNeedPhonegapMedia&&(this.mNeedPhonegapMedia=!1,this.mNeedPhonegapMedia=window&&window.cordova&&"undefined"!=typeof Media),this.mNeedPhonegapMedia){if(void 0===this.mPhonegapMediaLib&&(this.mPhonegapMediaLib={}),void 0===this.mPhonegapMediaLib[e]){for(var o=t.firstChild;o&&(!/source/i.test(o.nodeName)||"audio/mp3"!=o.getAttribute("type"));)o=o.nextSibling;if(o){var i=o.getAttribute("src"),s=/^([^#\?]*)\/[^#\?]+/.exec(window.location.pathname);s&&(i=i.replace(/^\./,s[1])),i=i.replace(/%20/g," "),this.mPhonegapMediaLib[e]=new Media(i,function(){},function(e){console.warn("Jocly PlaySound: Media did not play "+e.code)},function(e){})}else this.mPhonegapMediaLib[e]=null}this.mPhonegapMediaLib[e]&&this.mPhonegapMediaLib[e].play()}else t.cloneNode(!0).play()}},JocGame.prototype.InitGame=function(){},JocGame.prototype.GameInitGame=function(){0==this.mGameInited&&(this.mVisitedBoards={},arguments.length>0&&arguments[0]?this.mInitial=arguments[0]:this.mInitial=null,this.InitGame(),this.mGameInited=!0)},JocGame.prototype.DestroyGame=function(){},JocGame.prototype.GameDestroyGame=function(){if(this.mGameInited&&(this.DestroyGame(),this.mGameInited=!1),this.aiWorker)try{this.aiWorker.terminate(),delete this.aiWorker}catch(e){console.warn("Cannot terminate worker",e)}},JocGame.prototype.DisplayBoard=function(){this.mBoard.Display&&this.mBoard.Display(this)},JocGame.prototype.SetWho=function(e){this.mWho=e,this.mBoard.mWho=e},JocGame.prototype.GetWho=function(){return this.mWho},JocGame.prototype.HumanTurn=function(){this.mBoard.mMoves&&0!=this.mBoard.mMoves.length||(this.mCurrentLevel=-1,this.mBoard.GenerateMoves(this)),this.mBoard.HumanTurn(this)},JocGame.prototype.HumanTurnEnd=function(){this.mBoard.HumanTurnEnd(this)},JocGame.prototype.PlayedMove=function(e,t){return this.mOldBoard=t,this.mBoard.PlayedMove(this,e)},JocGame.prototype.ShowEnd=function(){return this.mBoard.ShowEnd(this)},JocGame.prototype.EvaluateBoard=function(){this.mBoard.mFinished=!1,this.mBoard.mMoves=[],this.mCurrentLevel=-1,this.mBoard.GenerateMoves(this),0==this.mBoard.mFinished&&this.mBoard.Evaluate(this,!0,!0)},JocGame.prototype.GetFinished=function(){return this.EvaluateBoard(),this.mBoard.mFinished?this.mBoard.mWinner:0},JocGame.prototype.IsValidMove=function(e){var t=new(this.GetMoveClass())(e);return this.mBoard.IsValidMove(this,t)},JocGame.prototype.AddVisit=function(e,t){e&&(t=e.GetSignature()),void 0===this.mVisitedBoards[t]?this.mVisitedBoards[t]=1:this.mVisitedBoards[t]++},JocGame.prototype.RemoveVisit=function(e,t){e&&(t=e.GetSignature());var o=this.mVisitedBoards[t];void 0!==o&&(o>1?this.mVisitedBoards[t]--:delete this.mVisitedBoards[t])};var engdbg_loops,engdbg_time,engdbg_t0;JocGame.prototype.StartMachine=function(e){if(engdbg_loops=0,engdbg_time=0,engdbg_t0=Date.now(),this.mDoneCallback=e.Done||this.MachineMove,this.mProgressCallback=e.Progress||this.MachineProgress,void 0!==e.level&&(this.mTopLevel=e.level),void 0!==e.maxDepth&&(this.mTopLevel=e.maxDepth),this.mStartTime=(new Date).getTime(),this.mExploredCount=0,this.mPickedMoveIndex=0,this.mBestMoves=[],this.mContexts=[],this.mDuration=0,this.mAborted=!1,this.mRandomSeed=0,e.randomSeed&&!isNaN(parseInt(e.randomSeed))&&(this.mRandomSeed=parseInt(e.randomSeed)),"function"==typeof this.mBoard.StaticGenerateMoves){var t=this.mBoard.StaticGenerateMoves(this);if(t&&t.length>0)return this.mBestMoves=t,void JocUtil.schedule(this,"Done",{})}this.mOptions.levelOptions&&(this.mOptions.levelOptionsSaved=JSON.parse(JSON.stringify(this.mOptions.levelOptions)),e.level&&Object.assign(this.mOptions.levelOptions,e.level));var o=e.threaded&&"object"==("undefined"==typeof window?"undefined":_typeof(window))&&window.Worker;if(e.level&&"uct"==e.level.ai&&JoclyUCT)o?this.StartThreadedMachine(e,"uct"):JoclyUCT.startMachine(this,e);else if(o)this.StartThreadedMachine(e,"alpha-beta");else{this.mSavedVisitedBoards={};for(var i in this.mVisitedBoards)this.mSavedVisitedBoards[i]=this.mVisitedBoards[i];this.Engine(this.mBoard,this.mTopLevel,!1,0,e.potential),this.Run()}},JocGame.prototype.StartThreadedMachine=function(e,t){var o=this;delete e.Done,delete e.Progress;var i=Date.now();this.aiWorker||(this.aiWorker=new Worker(this.config.baseURL+"jocly.aiworker.js"),this.aiWorker.postMessage({type:"Init",baseURL:this.config.baseURL,options:e,t0:i})),this.aiWorker.onmessage=function(e){var t=e.data;switch(t.type){case"Progress":o.mProgressCallback(t.percent);break;case"Done":o.mBestMoves=t.data.moves,o.mPickedMoveIndex=t.data.moveIndex,o.mExploredCount=t.data.explored,o.mDuration=t.data.duration,o.mBoard.evaluation=t.data.evaluation,o.Done()}},this.aiWorker.postMessage({type:"Play",playedMoves:this.mPlayedMoves,gameOptions:this.mOptions,gameName:this.name,options:e,algo:t,t0:i})},JocGame.prototype.StopThreadedMachine=function(){if(this.aiWorker)try{this.aiWorker.terminate(),delete this.aiWorker}catch(e){console.warn("Cannot terminate worker",e)}},JocGame.prototype.ScheduleStep=function(){this.mNextSchedule=this.ExecuteStep},JocGame.prototype.Random=function(e){return this.mRandomSeed?this.mRandomSeed%e:Math.floor(Math.random()*e)},JocGame.prototype.ArrayShuffle=function(e){var t=e.length;if(!(t<=0))for(;--t;){var o;o=this.mRandomSeed?this.mRandomSeed%(t+1):Math.floor(Math.random()*(t+1));var i=e[t];e[t]=e[o],e[o]=i}},JocGame.prototype.Done=function(){if(this.mDuration=(new Date).getTime()-this.mStartTime,this.mOptions.levelOptionsSaved&&(this.mOptions.levelOptions=this.mOptions.levelOptionsSaved,this.mOptions.levelOptionsSaved=null),this.mSavedVisitedBoards&&(this.mVisitedBoards=this.mSavedVisitedBoards),this.mDoneCallback){this.mPickedMoveIndex=this.Random(this.mBestMoves.length);try{this.mProgressCallback&&this.mProgressCallback(100),this.mDoneCallback({moves:this.mBestMoves,move:this.mBestMoves[this.mPickedMoveIndex],moveIndex:this.mPickedMoveIndex,explored:this.mExploredCount,duration:this.mDuration,evaluation:this.mBoard.mEvaluation})}catch(e){JocLog("!!! Done:"+e,e.stack?e.stack:"")}}},JocGame.prototype.Run=function(){var e=Date.now();try{for(var t=(new Date).getTime();this.mNextSchedule&&(new Date).getTime()-t<20&&0==this.mAborted;){var o=this.mNextSchedule;this.mNextSchedule=null,o.call(this)}this.mAborted?this.mAbortCallback():this.mNextSchedule&&JocUtil.schedule(this,"Run",{})}catch(e){JocLog("JocGame.Run "+e+"\n"+e.stack)}var i=Date.now();engdbg_loops++,engdbg_time+=i-e},JocGame.prototype.Abort=function(e){var t=this;this.mAbortCallback=function(){t.mOptions.levelOptionsSaved&&(t.mOptions.levelOptions=t.mOptions.levelOptionsSaved,t.mOptions.levelOptionsSaved=null),t.mSavedVisitedBoards&&(t.mVisitedBoards=t.mSavedVisitedBoards,t.mSavedVisitedBoards=null),e()},this.mAborted=!0},JocGame.prototype.Engine=function(e,t,o,i,s){var a={mBoard:e,mLevel:t,mBAlpha:o,mAlpha:i,mBestEvaluation:0,mMoveIndex:0,mNextBoard:null,mNextBoards:null};if(this.mContexts.push(a),a.mBoard.mFinished=!1,a.mBoard.mWinner=JocGame.DRAW,this.mCurrentLevel=t,void 0===a.mBoard.mMoves&&(a.mBoard.mMoves=[]),0==a.mBoard.mMoves.length&&a.mBoard.GenerateMoves(this),0==a.mBoard.mMoves.length&&0==a.mBoard.mFinished&&(a.mBoard.Evaluate(this,!0,!1),0==a.mBoard.mFinished&&(JocLog("!!! No move possible while not finished - player",this.mWho,"board",a.mBoard),a.mBoard.mFinished=!0)),a.mBoard.mFinished){switch(a.mBoard.mWinner){case JocGame.PLAYER_A:a.mBoard.mEvaluation=JocGame.MAX_VALUE-(this.mTopLevel-a.mLevel);break;case JocGame.PLAYER_B:a.mBoard.mEvaluation=-JocGame.MAX_VALUE+(this.mTopLevel-a.mLevel)}return a.mBestEvaluation=a.mBoard.mEvaluation,void this.ExecuteStep2()}if(a.mExploCtrl={exploFrom:this.mExploredCount,exploTo:this.mExploredCount+s},a.mBoard.QuickEvaluate){var r=function(e,t){return(t.evaluation-e.evaluation)*a.mBoard.mWho},n=[];for(var m in a.mBoard.mMoves){var h=a.mBoard.MakeAndApply(this,m),d=h.QuickEvaluate(this);n.push({move:a.mBoard.mMoves[m],board:h,evaluation:d})}n.sort(r),a.mBoard.mMoves=[],a.mNextBoards=[],void 0!==this.mOptions.capMoves&&(n=n.slice(0,this.mOptions.capMoves));for(var m in n)a.mBoard.mMoves.push(n[m].move),a.mNextBoards.push(n[m].board)}this.ExecuteStep()},JocGame.prototype.ExecuteStep=function(){this.mExploredCount++;var e=this.mContexts[this.mContexts.length-1];if(e.mNextBoards?e.mNextBoard=e.mNextBoards[e.mMoveIndex]:e.mNextBoard=e.mBoard.MakeAndApply(this,e.mMoveIndex),this.mProgressCallback){var t=null;if(e.mLevel==this.mTopLevel)t=Math.floor(100*e.mMoveIndex/e.mBoard.mMoves.length);else if(e.mLevel==this.mTopLevel-1){var o=this.mContexts[0],i=1/o.mBoard.mMoves.length;t=Math.floor(100*(o.mMoveIndex*i+e.mMoveIndex*i/e.mBoard.mMoves.length))}if(null!=t)try{this.mProgressCallback(t)}catch(e){}}var s=e.mNextBoard;if(s.mFinished=!1,s.mWinner=0,s.Evaluate(this,0==e.mLevel,!1,this),e.mLevel<0&&(s.mEvaluation=0),s.mFinished)switch(s.mWinner){case JocGame.PLAYER_A:s.mEvaluation=JocGame.MAX_VALUE-(this.mTopLevel-e.mLevel);break;case JocGame.PLAYER_B:s.mEvaluation=-JocGame.MAX_VALUE+(this.mTopLevel-e.mLevel);break;case JocGame.DRAW:s.mEvaluation=0}else if(e.mLevel==this.mTopLevel&&1==e.mBoard.mMoves.length);else if(e.mLevel>0){var a=(e.mExploCtrl.exploTo-this.mExploredCount)/e.mBoard.mMoves.length;if(a>=1)return s.mWho=-s.mWho,void this.Engine(s,e.mLevel-1,0!=e.mMoveIndex,e.mBestEvaluation,a)}this.ExecuteStep2()},JocGame.prototype.ExecuteStep2=function(){var e=this.mContexts[this.mContexts.length-1];if(e.mBoard.mMoves.length>0&&(0==e.mMoveIndex?(e.mBestEvaluation=e.mNextBoard.mEvaluation,e.mLevel==this.mTopLevel&&this.SetBest(e.mBoard.mMoves[0],e.mBoard)):e.mNextBoard.mWho>0?e.mNextBoard.mEvaluation>e.mBestEvaluation?(e.mBestEvaluation=e.mNextBoard.mEvaluation,e.mLevel==this.mTopLevel&&this.SetBest(e.mBoard.mMoves[e.mMoveIndex],e.mBoard)):e.mLevel==this.mTopLevel&&e.mNextBoard.mEvaluation==e.mBestEvaluation&&this.AddBest(e.mBoard.mMoves[e.mMoveIndex],e.mBoard):e.mNextBoard.mEvaluation<e.mBestEvaluation?(e.mBestEvaluation=e.mNextBoard.mEvaluation,e.mLevel==this.mTopLevel&&this.SetBest(e.mBoard.mMoves[e.mMoveIndex],e.mBoard)):e.mLevel==this.mTopLevel&&e.mNextBoard.mEvaluation==e.mBestEvaluation&&this.AddBest(e.mBoard.mMoves[e.mMoveIndex],e.mBoard)),e.mBoard.mEvaluation=e.mBestEvaluation,e.mBAlpha&&(e.mBoard.mWho==JocGame.PLAYER_A&&e.mBestEvaluation>e.mAlpha||e.mBoard.mWho==JocGame.PLAYER_B&&e.mBestEvaluation<e.mAlpha)&&(e.mMoveIndex=e.mBoard.mMoves.length-1),++e.mMoveIndex<e.mBoard.mMoves.length)this.ScheduleStep();else if(this.mContexts.pop(),this.mContexts.length>0){var e=this.mContexts[this.mContexts.length-1];e.mNextBoard.mWho=-e.mNextBoard.mWho,this.ExecuteStep2()}else delete e.mBoard.mMoves,this.Done()},JocGame.prototype.SetBest=function(e,t){var o=new(this.GetMoveClass())({});o.CopyFrom(e),this.mBestMoves=[o]},JocGame.prototype.AddBest=function(e,t){var o=new(this.GetMoveClass())({});o.CopyFrom(e),this.mBestMoves.push(o)},JocGame.prototype.GetRepeatOccurence=function(e){return this.mOptions.preventRepeat?this.mVisitedBoards[e.GetSignature()]:-1},JocGame.prototype.HandleRepeat=function(e){if(this.mOptions.preventRepeat){var t=e.GetSignature(!0);void 0===this.mVisitedBoards[t]?this.mVisitedBoards[t]=1:this.mVisitedBoards[t]++}},JocGame.prototype.UnhandleRepeat=function(e){if(this.mOptions.preventRepeat){var t=e.GetSignature(!0);1==this.mVisitedBoards[t]?delete this.mVisitedBoards[t]:this.mVisitedBoards[t]>1&&this.mVisitedBoards[t]--}},JocGame.prototype.ApplyMove=function(e){var t=new(this.GetMoveClass())({});t.CopyFrom(e),this.mPlayedMoves.push(t),this.mFullPlayedMoves.length<this.mPlayedMoves.length?this.mFullPlayedMoves.push(t):t.Equals(this.mFullPlayedMoves[this.mPlayedMoves.length-1])||(this.mFullPlayedMoves=this.mFullPlayedMoves.slice(0,this.mPlayedMoves.length-1),this.mFullPlayedMoves.push(t)),this.mBoard.ApplyMove(this,e),this.mBoard.mMoves=[],this.HandleRepeat(this.mBoard)},JocGame.prototype.BackTo=function(e,t){t||(t=this.mFullPlayedMoves),this.mWho=JocGame.PLAYER_A,this.mBoard=new(this.GetBoardClass())(this),this.mBoard.InitialPosition&&this.mBoard.InitialPosition(this),this.mInitial&&this.mInitial.turn&&(this.mWho=this.mInitial.turn),this.mBoard.mMoves=[],this.mBoard.mWho=this.mWho,this.mBestMoves=[],this.mVisitedBoards={},this.mPlayedMoves=[];for(var o=0;o<e;o++)this.mBoard.ApplyMove(this,t[o]),this.HandleRepeat(this.mBoard),this.mBoard.mWho=-this.mBoard.mWho,this.mPlayedMoves.push(t[o]);this.mWho=this.mBoard.mWho},JocGame.prototype.ExportInitialBoardState=function(e){if(!this.mInitialString)return null;if("function"!=typeof this.Import)return null;try{if(!this.Import("pjn",this.mInitialString).status)return null;var t=new(this.GetBoardClass())(this);t.InitialPosition&&t.InitialPosition(this);return{boardState:t.ExportBoardState(this,e),turn:t.mWho}}catch(e){return null}},JocGame.prototype.Load=function(e){if(this.mWho=JocGame.PLAYER_A,this.mBoard=new(this.GetBoardClass())(this),this.mBoard.mMoves=[],e.initialBoard){if("function"!=typeof this.Import)throw new Error("Import not supported");var t=this.Import("pjn",e.initialBoard);if(!t.status){var o=new Error("import failed");switch(t.error){case"parse":o=new Error("import failed: parse error");break;case"unsupported":o=new Error("import failed: unsupported format")}throw o}this.mInitial=t.initial,this.mInitial.turn&&(this.mWho=this.mInitial.turn),this.mInitialString=e.initialBoard}this.mBoard.InitialPosition&&this.mBoard.InitialPosition(this),this.mBoard.mWho=this.mWho,this.mBestMoves=[],this.mVisitedBoards={};var i=e.playedMoves;this.mPlayedMoves=[],this.mFullPlayedMoves=[];for(var s in i){var a=new(this.GetMoveClass())(i[s]);if(!this.IsValidMove(a))throw"invalid-move";this.mBoard.ApplyMove(this,a),this.HandleRepeat(this.mBoard),this.mBoard.mWho=-this.mBoard.mWho,this.mPlayedMoves.push(a),this.mFullPlayedMoves.push(a),this.mBoard.mMoves=[]}this.mWho=this.mBoard.mWho,0==this.mBoard.mFinished&&this.mBoard.Evaluate(this,!0,!0)},JocGame.prototype.CloseView=function(){},JocMove.prototype={},JocMove.prototype.CopyFrom=function(e){var t=JSON.parse(JSON.stringify(e));for(var o in t)this[o]=t[o]},JocMove.prototype.Equals=function(e){return JSON.stringify(this)==JSON.stringify(e)},JocMove.prototype.ToString=function(){return JSON.stringify(this)},JocMove.prototype.Strip=function(){return this},JocBoard.prototype={},JocBoard.prototype.Init=function(e){},JocBoard.prototype.InitBoard=function(e){this.mDepth=0,this.mMoves=[],this.mEvaluation=0,this.mFinished=!1,this.mWinner=0,this.Init(e)},JocBoard.prototype.CopyFrom=function(e){var t=e.mSignature;delete e.mSignature;var o=JSON.parse(JSON.stringify(e));for(var i in o)this[i]=o[i];e.mSignature=t},JocBoard.prototype.GetSignature=function(){if(arguments[0]||!this.mSignature){var e=this.mMoves;delete this.mMoves,delete this.mSignature,this.mSignature=JocUtil.md5(JSON.stringify(this)),this.mMoves=e}return this.mSignature},JocBoard.prototype.ApplyMove=function(e,t){JocLog("Method JocBoard:ApplyMove() must be overloaded")},JocBoard.prototype.GenerateMoves=function(e){JocLog("Method JocBoard:GenerateMoves() must be overloaded")},JocBoard.prototype.Evaluate=function(e,t,o){JocLog("Method JocBoard:Evaluate() must be overloaded"),this.mEvaluation=0},JocBoard.prototype.HumanTurn=function(){},JocBoard.prototype.HumanTurnEnd=function(){},JocBoard.prototype.PlayedMove=function(){},JocBoard.prototype.ShowEnd=function(){},JocBoard.prototype.MakeAndApply=function(e,t){var o=new(e.GetBoardClass())(e);return o.CopyFrom(this),o.mWho=this.mWho,o.mBoardClass=this.mBoardClass,o.ApplyMove(e,this.mMoves[t]),o.mMoves=[],o},JocBoard.prototype.IsValidMove=function(e,t){"function"!=typeof t.Equals&&(t=e.CreateMove(t)),this.mMoves&&0!=this.mMoves.length||(this.mCurrentLevel=-1,this.GenerateMoves(e));for(var o in this.mMoves)if(t.Equals(this.mMoves[o]))return!0;return console.error("Invalid move "+JSON.stringify(t)+" in "+JSON.stringify(this.mMoves)),!1},JocBoard.prototype.PushMove=function(e,t){this.mMoves.push(e.CreateMove(t))},JocBoard.prototype.GenerateMoveObjects=function(e){var t=[];this.mMoves=[],this.GenerateMoves(e);for(var o=0;o<this.mMoves.length;o++)t.push(e.CreateMove(this.mMoves[o]));this.mMoves=t},JocBoard.prototype.ExportBoardState=function(e){return JSON.stringify(this)},JocGame.prototype.GetBestMatchingMove=function(e,t){var o=[],i=this;t.forEach(function(e){"function"==typeof e.ToString?o.push(e.ToString()):o.push(i.CreateMove(e).ToString())});var s=1/0,a=[];if(t.forEach(function(t,i){var r=JocGame.Levenshtein(e,o[i])/(Math.max(o[i].length,e.length)+1);r==s?a.push(i):r<s&&(a=[i],s=r)}),1==a.length)return t[a[0]];var r=a,n=[];return r.forEach(function(t){var i=o[t];(e.indexOf(i)>=0||i.indexOf(e)>=0)&&n.push(t)}),1==n.length?t[n[0]]:(s=1/0,a=[],r.forEach(function(t){var i=0,r=e.replace(/[A-Z]/g,""),n=o[t].replace(/[A-Z]/g,"");i+=JocGame.Levenshtein(r,n)/(Math.max(r.length,n.length)+1),i+=r.indexOf(n)>=0||n.indexOf(r)>=0?0:1,r=e.replace(/[a-z]/g,""),n=o[t].replace(/[a-z]/g,""),i+=JocGame.Levenshtein(r,n)/(Math.max(r.length,n.length)+1),i+=r.indexOf(n)>=0||n.indexOf(r)>=0?0:1,i==s?a.push(t):i<s&&(a=[t],s=i)}),1==a.length?t[a[0]]:null)},JocBoard.prototype.PickMoveFromDatabase=function(e,t){if(!this.mMoves||0==this.mMoves.length){var o=[];this.mMoves=[],this.GenerateMoves(e);for(var i=0;i<this.mMoves.length;i++)o.push(e.CreateMove(this.mMoves[i]));this.mMoves=o}if(0==this.mMoves.length)return null;var s=this.mWho+"#"+this.GetSignature(),a=t[s];if(!a)return null;for(var r=0,i=0;i<a.length;i++)r+=a[i].e;for(var n=Math.random()*r,m=0,i=0;i<a.length;i++){var h=a[i];if((m+=h.e)>n){var d=e.GetBestMatchingMove(h.m,this.mMoves);if(d)return[d]}}return null},JocBoard.prototype.CompactMoveString=function(e,t){return"function"!=typeof t.ToString&&(t=e.CreateMove(t)),t.ToString()},JocGame.Zobrist=function(e){var t=new MersenneTwister(12345),o=[];for(var i in e)o.push(i);o.sort(),this.seed={};for(var s=0;s<o.length;s++){for(var i=o[s],a=e[i],r={values:{},seeds:[]},n=0,m=0;m<a.values.length;m++)r.values[a.values[m]]=n++;switch(a.type){case"array":for(var h=0;h<a.size;h++){for(var d=[],l=0;l<n;l++)d.push(t.genrand_int32());r.seeds.push(d)}r.type="array";break;default:for(var l=0;l<n;l++)r.seeds.push(t.genrand_int32());r.type="simple"}this.seed[i]=r}},JocGame.Zobrist.prototype={update:function(e,t){var o=this.seed[t];if(void 0===o)return console.error("Unknown Zobrist parameter",t),0;var i=o.values[arguments[2]];if(void 0===i)return console.error("Undeclared Zobrist value",arguments[2],"as param",t),0;switch(o.type){case"simple":e^=o.seeds[i];break;case"array":var s=o.seeds[arguments[3]];if(void 0===s)return console.error("Undeclared Zobrist array index",arguments[3],"as param",t),0;e^=s[i]}return e}},JocGame.Levenshtein=function(e,t){if(e==t)return 0;var o=e.length,i=t.length;if(0===o)return i;if(0===i)return o;var s=!1;try{s=!"0"[0]}catch(e){s=!0}s&&(e=e.split(""),t=t.split(""));for(var s=Array(o+1),a=Array(o+1),r=0,n=0,m=0,r=0;r<o+1;r++)s[r]=r;for(var h="",d="",n=1;n<=i;n++){for(a[0]=n,d=t[n-1],r=0;r<o;r++){var h=e[r],m=h==d?0:1,h=s[r+1]+1,l=a[r]+1,m=s[r]+m;l<h&&(h=l),m<h&&(h=m),a[r+1]=h}r=s,s=a,a=r}return s[o]};