-// // Poll all players except me (if I'm playing) to know online status.
-// // --> Send ping to server (answer pong if players[s] are connected)
-// if (this.gameInfo.players.some(p => p.sid == this.st.user.sid))
-// {
-// this.game.players.forEach(p => {
-// if (p.sid != this.st.user.sid)
-// this.st.conn.send(JSON.stringify({code:"ping", oppid:p.sid}));
-// });
-// }
- },
- // TODO: refactor this old "oppConnected" logic
-// oppConnected: function(uid) {
-// return this.opponents.some(o => o.id == uid && o.online);
-// },
- // Post-process a move (which was just played)
- processMove: function(move) {
- if (!this.game.mycolor)
- return; //I'm just an observer
- // Update storage (corr or live)
- const colorIdx = ["w","b","g","r"].indexOf(move.color);
- // https://stackoverflow.com/a/38750895
- const allowed_fields = ["appear", "vanish", "start", "end"];
- const filtered_move = Object.keys(move)
- .filter(key => allowed_fields.includes(key))
- .reduce((obj, key) => {
- obj[key] = move[key];
- return obj;
- }, {});
- // Send move ("newmove" event) to opponent(s) (if ours)
- let addTime = undefined;
- if (move.color == this.game.mycolor)
- {
- const elapsed = Date.now() - this.game.initime[colorIdx];
- // elapsed time is measured in milliseconds
- addTime = this.game.increment - elapsed/1000;
- this.game.players.forEach(p => {
- if (p.sid != this.st.user.sid)
- {
- this.st.conn.send(JSON.stringify({
- code: "newmove",
- target: p.sid,
- move: Object.assign({}, filtered_move, {addTime: addTime}),
- }));
+ const currentTurn = this.vr.turn;
+ const currentMovesCount = this.game.moves.length;
+ const colorIdx = ["w", "b"].indexOf(currentTurn);
+ this.clockUpdate = setInterval(
+ () => {
+ if (
+ this.game.clocks[colorIdx] < 0 ||
+ this.game.moves.length > currentMovesCount ||
+ this.game.score != "*"
+ ) {
+ clearInterval(this.clockUpdate);
+ this.clockUpdate = null;
+ if (this.game.clocks[colorIdx] < 0)
+ this.gameOver(
+ currentTurn == "w" ? "0-1" : "1-0",
+ "Time"
+ );
+ } else {
+ this.$set(
+ this.virtualClocks,
+ colorIdx,
+ ppt(Math.max(0, --this.game.clocks[colorIdx])).split(':')
+ );
+ }
+ },
+ 1000
+ );
+ },
+ // Update variables and storage after a move:
+ processMove: function(move, data) {
+ if (this.game.type == "import")
+ // Shouldn't receive any messages in this mode:
+ return;
+ if (!data) data = {};
+ const moveCol = this.vr.turn;
+ const colorIdx = ["w", "b"].indexOf(moveCol);
+ const nextIdx = 1 - colorIdx;
+ const doProcessMove = () => {
+ const origMovescount = this.game.moves.length;
+ // The move is (about to be) played: stop clock
+ clearInterval(this.clockUpdate);
+ this.clockUpdate = null;
+ if (moveCol == this.game.mycolor && !data.receiveMyMove) {
+ if (this.drawOffer == "received")
+ // I refuse draw
+ this.drawOffer = "";
+ if (this.game.type == "live" && origMovescount >= 2) {
+ this.game.clocks[colorIdx] += this.game.increment;
+ // For a correct display in casqe of disconnected opponent:
+ this.$set(
+ this.virtualClocks,
+ colorIdx,
+ ppt(this.game.clocks[colorIdx]).split(':')
+ );
+ GameStorage.update(this.gameRef, {
+ // It's not my turn anymore:
+ initime: null
+ });
+ }
+ }
+ // Update current game object:
+ playMove(move, this.vr);
+ if (!data.score)
+ // Received move, score is computed in BaseGame, but maybe not yet.
+ // ==> Compute it here, although this is redundant (TODO)
+ data.score = this.vr.getCurrentScore();
+ if (data.score != "*") this.gameOver(data.score);
+ this.game.moves.push(move);
+ this.game.fen = this.vr.getFen();
+ if (this.game.type == "corr") {
+ // In corr games, just reset clock to mainTime:
+ this.game.clocks[colorIdx] = extractTime(this.game.cadence).mainTime;
+ }
+ // If repetition detected, consider that a draw offer was received:
+ const fenObj = this.vr.getFenForRepeat();
+ this.repeat[fenObj] =
+ !!this.repeat[fenObj]
+ ? this.repeat[fenObj] + 1
+ : 1;
+ if (this.repeat[fenObj] >= 3) this.drawOffer = "threerep";
+ else if (this.drawOffer == "threerep") this.drawOffer = "";
+ if (!!this.game.mycolor && !data.receiveMyMove) {
+ // NOTE: 'var' to see that variable outside this block
+ var filtered_move = getFilteredMove(move);
+ }
+ if (moveCol == this.game.mycolor && !data.receiveMyMove) {
+ // Notify turn on MyGames page:
+ this.notifyMyGames(
+ "turn",
+ {
+ gid: this.gameRef,
+ turn: this.vr.turn
+ }
+ );
+ }
+ // Since corr games are stored at only one location, update should be
+ // done only by one player for each move:
+ if (
+ this.game.type == "live" &&
+ !!this.game.mycolor &&
+ moveCol != this.game.mycolor &&
+ this.game.moves.length >= 2
+ ) {
+ // Receive a move: update initime
+ this.game.initime = Date.now();
+ GameStorage.update(this.gameRef, {
+ // It's my turn now!
+ initime: this.game.initime
+ });
+ }
+ if (
+ !!this.game.mycolor &&
+ !data.receiveMyMove &&
+ (this.game.type == "live" || moveCol == this.game.mycolor)
+ ) {
+ let drawCode = "";
+ switch (this.drawOffer) {
+ case "threerep":
+ drawCode = "t";
+ break;
+ case "sent":
+ drawCode = this.game.mycolor;
+ break;
+ case "received":
+ drawCode = V.GetOppCol(this.game.mycolor);
+ break;
+ }
+ if (this.game.type == "corr") {
+ // corr: only move, fen and score
+ this.updateCorrGame({
+ fen: this.game.fen,
+ move: {
+ squares: filtered_move,
+ idx: origMovescount
+ },
+ // Code "n" for "None" to force reset (otherwise it's ignored)
+ drawOffer: drawCode || "n"
+ });
+ }
+ else {
+ const updateStorage = () => {
+ GameStorage.update(this.gameRef, {
+ fen: this.game.fen,
+ move: filtered_move,
+ moveIdx: origMovescount,
+ clocks: this.game.clocks,
+ drawOffer: drawCode
+ });
+ };
+ // The active tab can update storage immediately
+ if (this.focus) updateStorage();
+ // Small random delay otherwise
+ else setTimeout(updateStorage, 500 + 1000 * Math.random());
+ }
+ }
+ // Send move ("newmove" event) to people in the room (if our turn)
+ if (moveCol == this.game.mycolor && !data.receiveMyMove) {
+ let sendMove = {
+ move: filtered_move,
+ index: origMovescount,
+ // color is required to check if this is my move
+ // (if several tabs opened)
+ color: moveCol,
+ cancelDrawOffer: this.drawOffer == ""
+ };
+ if (this.game.type == "live")
+ sendMove["clock"] = this.game.clocks[colorIdx];
+ // (Live) Clocks will re-start when the opponent pingback arrive
+ this.opponentGotMove = false;
+ this.send("newmove", {data: sendMove});
+ // If the opponent doesn't reply gotmove soon enough, re-send move:
+ // Do this at most 2 times, because mpore would mean network issues,
+ // opponent would then be expected to disconnect/reconnect.
+ let counter = 1;
+ const currentUrl = document.location.href;
+ this.retrySendmove = setInterval(
+ () => {
+ if (
+ counter >= 3 ||
+ this.opponentGotMove ||
+ document.location.href != currentUrl //page change
+ ) {
+ clearInterval(this.retrySendmove);
+ return;
+ }
+ const oppsid = this.getOppsid();
+ if (!oppsid)
+ // Opponent is disconnected: he'll ask last state
+ clearInterval(this.retrySendmove);
+ else {
+ this.send("newmove", { data: sendMove, target: oppsid });
+ counter++;
+ }
+ },
+ 1500
+ );
+ }
+ else
+ // Not my move or I'm an observer: just start other player's clock
+ this.re_setClocks();
+ };
+ if (
+ this.game.type == "corr" &&
+ moveCol == this.game.mycolor &&
+ !data.receiveMyMove
+ ) {
+ let boardDiv = document.querySelector(".game");
+ const afterSetScore = () => {
+ doProcessMove();
+ if (this.st.settings.gotonext && this.nextIds.length > 0)
+ this.showNextGame();
+ else {
+ // The board might have been hidden:
+ if (boardDiv.style.visibility == "hidden")
+ boardDiv.style.visibility = "visible";
+ if (data.score == "*") this.re_setClocks();