+ // Update variables and storage after a move:
+ processMove: function(move, data) {
+ if (!data) data = {};
+ const moveCol = this.vr.turn;
+ const doProcessMove = () => {
+ const colorIdx = ["w", "b"].indexOf(moveCol);
+ const nextIdx = 1 - colorIdx;
+ const origMovescount = this.game.moves.length;
+ let addTime =
+ this.game.type == "live"
+ ? (data.addTime || 0)
+ : undefined;
+ if (moveCol == this.game.mycolor && !data.receiveMyMove) {
+ if (this.drawOffer == "received")
+ // I refuse draw
+ this.drawOffer = "";
+ if (this.game.type == "live" && origMovescount >= 2) {
+ const elapsed = Date.now() - this.game.initime[colorIdx];
+ // elapsed time is measured in milliseconds
+ addTime = this.game.increment - elapsed / 1000;
+ }
+ }
+ // Update current game object:
+ playMove(move, this.vr);
+// TODO: notifyTurn: "changeturn" message
+ this.game.moves.push(move);
+ // (add)Time indication: useful in case of lastate infos requested
+ if (this.game.type == "live")
+ this.game.addTimes.push(addTime);
+ this.game.fen = this.vr.getFen();
+ if (this.game.type == "live") this.game.clocks[colorIdx] += addTime;
+ // In corr games, just reset clock to mainTime:
+ else this.game.clocks[colorIdx] = extractTime(this.game.cadence).mainTime;
+ // data.initime is set only when I receive a "lastate" move from opponent
+ this.game.initime[nextIdx] = data.initime || Date.now();
+ this.re_setClocks();
+ // 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 = "";
+ // Since corr games are stored at only one location, update should be
+ // done only by one player for each move:
+ if (!!this.game.mycolor && !data.receiveMyMove) {
+ // NOTE: 'var' to see that variable outside this block
+ var filtered_move = getFilteredMove(move);
+ }
+ 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") {
+ GameStorage.update(this.gameRef.id, {
+ fen: this.game.fen,
+ move: {
+ squares: filtered_move,
+ played: Date.now(),
+ idx: origMovescount
+ },
+ // Code "n" for "None" to force reset (otherwise it's ignored)
+ drawOffer: drawCode || "n"
+ });
+ }
+ else {
+ const updateStorage = () => {
+ GameStorage.update(this.gameRef.id, {
+ fen: this.game.fen,
+ move: filtered_move,
+ moveIdx: origMovescount,
+ clocks: this.game.clocks,
+ initime: this.game.initime,
+ drawOffer: drawCode
+ });
+ };
+ // The active tab can update storage immediately
+ if (!document.hidden) 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) {
+ const sendMove = {
+ move: filtered_move,
+ index: origMovescount,
+ // color is required to check if this is my move (if several tabs opened)
+ color: moveCol,
+ addTime: addTime, //undefined for corr games
+ cancelDrawOffer: this.drawOffer == ""
+ };
+ this.opponentGotMove = false;
+ this.send("newmove", {data: sendMove});
+ // If the opponent doesn't reply gotmove soon enough, re-send move:
+ let retrySendmove = setInterval(
+ () => {
+ if (this.opponentGotMove) {
+ clearInterval(retrySendmove);
+ return;
+ }
+ let oppsid = this.game.players[nextIdx].sid;
+ if (!oppsid) {
+ oppsid = Object.keys(this.people).find(
+ sid => this.people[sid].id == this.game.players[nextIdx].uid
+ );
+ }
+ if (!oppsid || !this.people[oppsid])
+ // Opponent is disconnected: he'll ask last state
+ clearInterval(retrySendmove);
+ else this.send("newmove", {data: sendMove, target: oppsid});
+ },
+ 1000
+ );
+ }
+ };
+ if (
+ this.game.type == "corr" &&
+ moveCol == this.game.mycolor &&
+ !data.receiveMyMove
+ ) {
+ setTimeout(() => {
+ // TODO: remplacer cette confirm box par qqch de plus discret
+ // (et de même pour challenge accepté / refusé)
+ if (
+ !confirm(
+ this.st.tr["Move played:"] +
+ " " +
+ getFullNotation(move) +
+ "\n" +
+ this.st.tr["Are you sure?"]
+ )
+ ) {
+ this.$refs["basegame"].cancelLastMove();
+ return;
+ }
+ doProcessMove();
+ // Let small time to finish drawing current move attempt:
+ }, 500);
+ }
+ else doProcessMove();