{{ vr.getFen() }}
@@ -192,32 +209,28 @@ Vue.component('my-game', {
this.conn.addEventListener('message', socketMessageListener);
this.conn.addEventListener('close', socketCloseListener);
};
- this.conn.onmessage = socketMessageListener;
- this.conn.onclose = socketCloseListener;
+ if (!!this.conn)
+ {
+ this.conn.onmessage = socketMessageListener;
+ this.conn.onclose = socketCloseListener;
+ }
// Computer moves web worker logic: (TODO: also for observers in HH games)
this.compWorker.postMessage(["scripts",variant.name]);
- const self = this;
- this.compWorker.onmessage = function(e) {
+ this.compWorker.onmessage = e => {
+ this.lockCompThink = true; //to avoid some ghost moves
let compMove = e.data;
- if (!compMove)
- return; //may happen if MarseilleRules and subTurn==2 (TODO: a bit ugly...)
if (!Array.isArray(compMove))
compMove = [compMove]; //to deal with MarseilleRules
- // TODO: imperfect attempt to avoid ghost move:
- compMove.forEach(m => { m.computer = true; });
- // (first move) HACK: small delay to avoid selecting elements
- // before they appear on page:
- const delay = Math.max(500-(Date.now()-self.timeStart), 0);
+ // Small delay for the bot to appear "more human"
+ const delay = Math.max(500-(Date.now()-this.timeStart), 0);
setTimeout(() => {
- const animate = (variant.name!="Dark" ? "animate" : null);
- if (self.mode == "computer") //warning: mode could have changed!
- self.play(compMove[0], animate);
+ const animate = variant.name != "Dark";
+ this.play(compMove[0], animate);
if (compMove.length == 2)
- setTimeout( () => {
- if (self.mode == "computer")
- self.play(compMove[1], animate);
- }, 750);
+ setTimeout( () => { this.play(compMove[1], animate); }, 750);
+ else //250 == length of animation (TODO: should be a constant somewhere)
+ setTimeout( () => this.lockCompThink = false, 250);
}, delay);
}
},
@@ -227,7 +240,14 @@ Vue.component('my-game', {
methods: {
translate: translate,
loadGame: function() {
- // TODO: load this.gameId ...
+ const game = getGameFromStorage(this.gameId);
+ this.oppid = game.oppid; //opponent ID in case of running HH game
+ this.score = game.score;
+ this.mycolor = game.mycolor || "w";
+ this.fenStart = game.fenStart;
+ this.moves = game.moves;
+ this.cursor = game.moves.length-1;
+ this.lastMove = (game.moves.length > 0 ? game.moves[this.cursor] : null);
},
setEndgameMessage: function(score) {
let eogMessage = "Undefined";
@@ -249,15 +269,45 @@ Vue.component('my-game', {
this.endgameMessage = eogMessage;
},
download: function() {
- // Variants may have special PGN structure (so next function isn't defined here)
- // TODO: get fenStart from local game (using gameid)
- const content = V.GetPGN(this.moves, this.mycolor, this.score, fenStart, this.mode);
+ const content = this.getPgn();
// Prepare and trigger download link
let downloadAnchor = document.getElementById("download");
downloadAnchor.setAttribute("download", "game.pgn");
downloadAnchor.href = "data:text/plain;charset=utf-8," + encodeURIComponent(content);
downloadAnchor.click();
},
+ getPgn: function() {
+ let pgn = "";
+ pgn += '[Site "vchess.club"]\n';
+ const opponent = (this.mode=="human" ? "Anonymous" : "Computer");
+ pgn += '[Variant "' + variant.name + '"]\n';
+ pgn += '[Date "' + getDate(new Date()) + '"]\n';
+ const whiteName = ["human","computer"].includes(this.mode)
+ ? (this.mycolor=='w'?'Myself':opponent)
+ : "analyze";
+ const blackName = ["human","computer"].includes(this.mode)
+ ? (this.mycolor=='b'?'Myself':opponent)
+ : "analyze";
+ pgn += '[White "' + whiteName + '"]\n';
+ pgn += '[Black "' + blackName + '"]\n';
+ pgn += '[Fen "' + this.fenStart + '"]\n';
+ pgn += '[Result "' + this.score + '"]\n\n';
+ let counter = 1;
+ let i = 0;
+ while (i < this.moves.length)
+ {
+ pgn += (counter++) + ".";
+ for (let color of ["w","b"])
+ {
+ let move = "";
+ while (i < this.moves.length && this.moves[i].color == color)
+ move += this.moves[i++].notation[0] + ",";
+ move = move.slice(0,-1); //remove last comma
+ pgn += move + (i < this.moves.length-1 ? " " : "");
+ }
+ }
+ return pgn + "\n";
+ },
showScoreMsg: function(score) {
this.setEndgameMessage(score);
let modalBox = document.getElementById("modal-eog");
@@ -266,20 +316,18 @@ Vue.component('my-game', {
},
endGame: function(score) {
this.score = score;
- if (["human","computer"].includes(this.mode))
- {
- const prefix = (this.mode=="computer" ? "comp-" : "");
- localStorage.setItem(prefix+"score", score);
- }
this.showScoreMsg(score);
- if (this.mode == "human" && this.oppConnected)
+ this.$emit("game-over", score);
+ if (this.mode == "human")
{
- // Send our nickname to opponent
- this.conn.send(JSON.stringify({
- code:"myname", name:this.myname, oppid:this.oppid}));
+ localStorage["score"] = score;
+ if (this.oppConnected)
+ {
+ // Send our nickname to opponent
+ this.conn.send(JSON.stringify({
+ code:"myname", name:this.myname, oppid:this.oppid}));
+ }
}
- // TODO: what about cursor ?
- //this.cursor = this.vr.moves.length; //to navigate in finished game
},
resign: function(e) {
this.getRidOfTooltip(e.currentTarget);
@@ -298,20 +346,20 @@ Vue.component('my-game', {
this.compWorker.postMessage(["askmove"]);
},
animateMove: function(move) {
- let startSquare = document.getElementById(this.getSquareId(move.start));
- let endSquare = document.getElementById(this.getSquareId(move.end));
+ let startSquare = document.getElementById(getSquareId(move.start));
+ let endSquare = document.getElementById(getSquareId(move.end));
let rectStart = startSquare.getBoundingClientRect();
let rectEnd = endSquare.getBoundingClientRect();
let translation = {x:rectEnd.x-rectStart.x, y:rectEnd.y-rectStart.y};
let movingPiece =
- document.querySelector("#" + this.getSquareId(move.start) + " > img.piece");
+ document.querySelector("#" + getSquareId(move.start) + " > img.piece");
// HACK for animation (with positive translate, image slides "under background")
// Possible improvement: just alter squares on the piece's way...
squares = document.getElementsByClassName("board");
for (let i=0; i