Some improvements; to be continuated
authorBenjamin Auder <benjamin.auder@somewhere>
Tue, 25 Dec 2018 10:08:52 +0000 (11:08 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Tue, 25 Dec 2018 10:08:52 +0000 (11:08 +0100)
public/javascripts/base_rules.js
public/javascripts/components/game.js
public/javascripts/variants/Marseille.js
public/stylesheets/variant.sass
views/rules/Baroque/fr.pug
views/translations/en.pug
views/translations/es.pug
views/translations/fr.pug

index 8b8165a..7a42a38 100644 (file)
@@ -956,11 +956,11 @@ class ChessRules
                        board[psq.x][psq.y] = psq.c + psq.p;
        }
 
-       // Before move is played, update variables + flags
+       // After move is played, update variables + flags
        updateVariables(move)
        {
                const piece = move.vanish[0].p;
-               const c = move.vanish[0].c;
+               const c = this.getOppCol(this.turn); //'move.vanish[0].c' doesn't work for Checkered
                const firstRank = (c == "w" ? V.size.x-1 : 0);
 
                // Update king position + flags
index c14130b..085dafa 100644 (file)
@@ -11,7 +11,7 @@ Vue.component('my-game', {
                        selectedPiece: null, //moving piece (or clicked piece)
                        conn: null, //socket connection
                        score: "*", //'*' means 'unfinished'
-                       mode: "idle", //human, chat, friend, problem, computer or idle (if not playing)
+                       mode: "idle", //human, friend, problem, computer or idle (if not playing)
                        myid: "", //our ID, always set
                        oppid: "", //opponent ID in case of HH game
                        gameId: "", //useful if opponent started other human games after we disconnected
@@ -58,12 +58,13 @@ Vue.component('my-game', {
                                        "play": true,
                                        "seek": this.seek,
                                        "playing": this.mode == "human",
-                                       "spaceright": true,
                                },
                        },
                        [h('i', { 'class': { "material-icons": true } }, "accessibility")])
                );
-               if (variant!="Dark" && ["idle","chat","computer"].includes(this.mode))
+               if (variant != "Dark" &&
+                       (["idle","computer","friend"].includes(this.mode)
+                               || ["friend","human"].includes(this.mode) && this.score != "*"))
                {
                        actionArray.push(
                                h('button',
@@ -74,13 +75,15 @@ Vue.component('my-game', {
                                                "tooltip":true,
                                                "play": true,
                                                "playing": this.mode == "computer",
-                                               "spaceright": true,
+                                               "spaceleft": true,
                                        },
                                },
                                [h('i', { 'class': { "material-icons": true } }, "computer")])
                        );
                }
-               if (variant!="Dark" && ["idle","chat","friend"].includes(this.mode))
+               if (variant != "Dark" &&
+                       (["idle","friend"].includes(this.mode)
+                               || ["computer","human"].includes(this.mode) && this.score != "*"))
                {
                        actionArray.push(
                                h('button',
@@ -91,7 +94,7 @@ Vue.component('my-game', {
                                                "tooltip":true,
                                                "play": true,
                                                "playing": this.mode == "friend",
-                                               "spaceright": true,
+                                               "spaceleft": true,
                                        },
                                },
                                [h('i', { 'class': { "material-icons": true } }, "people")])
@@ -114,7 +117,7 @@ Vue.component('my-game', {
                                parseFloat(settingsStyle.height.slice(0,-2)) - 2
                        ];
                        let aboveBoardElts = [];
-                       if (["chat","human"].includes(this.mode))
+                       if (this.mode == "human")
                        {
                                const connectedIndic = h(
                                        'div',
@@ -132,7 +135,7 @@ Vue.component('my-game', {
                                );
                                aboveBoardElts.push(connectedIndic);
                        }
-                       if (this.mode == "chat")
+                       if (this.mode == "human" && this.score != "*")
                        {
                                const chatButton = h(
                                        'button',
@@ -153,14 +156,14 @@ Vue.component('my-game', {
                                );
                                aboveBoardElts.push(chatButton);
                        }
-                       else if (this.mode == "computer")
+                       if (["human","computer","friend"].includes(this.mode))
                        {
                                const clearButton = h(
                                        'button',
                                        {
-                                               on: { click: this.clearComputerGame },
+                                               on: { click: this.clearCurrentGame },
                                                attrs: {
-                                                       "aria-label": translations['Clear game versus computer'],
+                                                       "aria-label": translations['Clear current game'],
                                                        "id": "clearBtn",
                                                },
                                                'class': {
@@ -277,7 +280,8 @@ Vue.component('my-game', {
                        // Create board element (+ reserves if needed by variant or mode)
                        const lm = this.vr.lastMove;
                        const showLight = this.hints && variant!="Dark" &&
-                               (!["idle","chat"].includes(this.mode) || this.cursor==this.vr.moves.length);
+                               (this.mode != "idle" ||
+                                       (this.vr.moves.length > 0 && this.cursor==this.vr.moves.length));
                        const gameDiv = h('div',
                                {
                                        'class': {
@@ -358,47 +362,51 @@ Vue.component('my-game', {
                                        );
                                }), choices]
                        );
-                       if (!["idle","chat"].includes(this.mode))
+                       if (["human","computer"].includes(this.mode))
                        {
-                               actionArray.push(
-                                       h('button',
-                                               {
-                                                       on: { click: this.resign },
-                                                       attrs: { "aria-label": translations['Resign'] },
-                                                       'class': {
-                                                               "tooltip":true,
-                                                               "play": true,
+                               if (this.score == "*")
+                               {
+                                       actionArray.push(
+                                               h('button',
+                                                       {
+                                                               on: { click: this.resign },
+                                                               attrs: { "aria-label": translations['Resign'] },
+                                                               'class': {
+                                                                       "tooltip":true,
+                                                                       "play": true,
+                                                                       "spaceleft": true,
+                                                               },
                                                        },
-                                               },
-                                               [h('i', { 'class': { "material-icons": true } }, "flag")])
-                               );
-                       }
-                       else if (this.vr.moves.length > 0)
-                       {
-                               // A game finished, and another is not started yet: allow navigation
-                               actionArray = actionArray.concat([
-                                       h('button',
-                                               {
-                                                       on: { click: e => this.undo() },
-                                                       attrs: { "aria-label": translations['Undo'] },
-                                                       "class": {
-                                                               "play": true,
-                                                               "spaceleft": true,
+                                                       [h('i', { 'class': { "material-icons": true } }, "flag")])
+                                       );
+                               }
+                               else
+                               {
+                                       // A game finished, and another is not started yet: allow navigation
+                                       actionArray = actionArray.concat([
+                                               h('button',
+                                                       {
+                                                               on: { click: e => this.undo() },
+                                                               attrs: { "aria-label": translations['Undo'] },
+                                                               "class": {
+                                                                       "play": true,
+                                                                       "big-spaceleft": true,
+                                                               },
                                                        },
-                                               },
-                                               [h('i', { 'class': { "material-icons": true } }, "fast_rewind")]),
-                                       h('button',
-                                               {
-                                                       on: { click: e => this.play() },
-                                                       attrs: { "aria-label": translations['Play'] },
-                                                       "class": {
-                                                               "play": true,
-                                                               "spaceleft": true,
+                                                       [h('i', { 'class': { "material-icons": true } }, "fast_rewind")]),
+                                               h('button',
+                                                       {
+                                                               on: { click: e => this.play() },
+                                                               attrs: { "aria-label": translations['Play'] },
+                                                               "class": {
+                                                                       "play": true,
+                                                                       "spaceleft": true,
+                                                               },
                                                        },
-                                               },
-                                               [h('i', { 'class': { "material-icons": true } }, "fast_forward")]),
-                                       ]
-                               );
+                                                       [h('i', { 'class': { "material-icons": true } }, "fast_forward")]),
+                                               ]
+                                       );
+                               }
                        }
                        if (["friend","problem"].includes(this.mode))
                        {
@@ -410,7 +418,7 @@ Vue.component('my-game', {
                                                        attrs: { "aria-label": translations['Undo'] },
                                                        "class": {
                                                                "play": true,
-                                                               "spaceleft": true,
+                                                               "big-spaceleft": true,
                                                        },
                                                },
                                                [h('i', { 'class': { "material-icons": true } }, "undo")]
@@ -989,6 +997,7 @@ Vue.component('my-game', {
                const url = socketUrl;
                const humanContinuation = (localStorage.getItem("variant") === variant);
                const computerContinuation = (localStorage.getItem("comp-variant") === variant);
+               const friendContinuation = (localStorage.getItem("anlz-variant") === variant);
                this.myid = (humanContinuation ? localStorage.getItem("myid") : getRandString());
                this.conn = new WebSocket(url + "/?sid=" + this.myid + "&page=" + variant);
                const socketOpenListener = () => {
@@ -996,6 +1005,8 @@ Vue.component('my-game', {
                                this.continueGame("human");
                        else if (computerContinuation)
                                this.continueGame("computer");
+                       else if (friendContinuation)
+                               this.continueGame("friend");
                };
                const socketMessageListener = msg => {
                        const data = JSON.parse(msg.data);
@@ -1072,9 +1083,9 @@ Vue.component('my-game', {
                                // TODO: also use (dis)connect info to count online players?
                                case "connect":
                                case "disconnect":
-                                       if (["human","chat"].includes(this.mode) && this.oppid == data.id)
+                                       if (this.mode=="human" && this.oppid == data.id)
                                                this.oppConnected = (data.code == "connect");
-                                       if (this.oppConnected && this.mode == "chat")
+                                       if (this.oppConnected && this.score != "*")
                                        {
                                                // Send our name to the opponent, in case of he hasn't it
                                                this.conn.send(JSON.stringify({
@@ -1174,9 +1185,16 @@ Vue.component('my-game', {
                                this.conn.send(JSON.stringify({
                                        code:"myname", name:this.myname, oppid:this.oppid}));
                        }
-                       this.mode = (this.mode=="human" ? "chat" : "idle");
                        this.cursor = this.vr.moves.length; //to navigate in finished game
                },
+               getStoragePrefix: function(mode) {
+                       let prefix = "";
+                       if (mode == "computer")
+                               prefix = "comp-";
+                       else if (mode == "friend")
+                               prefix = "anlz-";
+                       return prefix;
+               },
                setStorage: function() {
                        if (this.mode=="human")
                        {
@@ -1184,8 +1202,7 @@ Vue.component('my-game', {
                                localStorage.setItem("oppid", this.oppid);
                                localStorage.setItem("gameId", this.gameId);
                        }
-                       // 'prefix' = "comp-" to resume games vs. computer
-                       const prefix = (this.mode=="computer" ? "comp-" : "");
+                       const prefix = this.getStoragePrefix(this.mode);
                        localStorage.setItem(prefix+"variant", variant);
                        localStorage.setItem(prefix+"mycolor", this.mycolor);
                        localStorage.setItem(prefix+"fenStart", this.fenStart);
@@ -1194,7 +1211,7 @@ Vue.component('my-game', {
                        localStorage.setItem(prefix+"score", "*");
                },
                updateStorage: function() {
-                       const prefix = (this.mode=="computer" ? "comp-" : "");
+                       const prefix = this.getStoragePrefix(this.mode);
                        localStorage.setItem(prefix+"moves", JSON.stringify(this.vr.moves));
                        localStorage.setItem(prefix+"fen", this.vr.getFen());
                        if (this.score != "*")
@@ -1202,13 +1219,13 @@ Vue.component('my-game', {
                },
                // "computer mode" clearing is done through the menu
                clearStorage: function() {
-                       if (["human","chat"].includes(this.mode))
+                       if (this.mode == "human")
                        {
                                delete localStorage["myid"];
                                delete localStorage["oppid"];
                                delete localStorage["gameId"];
                        }
-                       const prefix = (this.mode=="computer" ? "comp-" : "");
+                       const prefix = this.getStoragePrefix(this.mode);
                        delete localStorage[prefix+"variant"];
                        delete localStorage[prefix+"mycolor"];
                        delete localStorage[prefix+"fenStart"];
@@ -1226,9 +1243,9 @@ Vue.component('my-game', {
                        this.getRidOfTooltip(e.currentTarget);
                        document.getElementById("modal-chat").checked = true;
                },
-               clearComputerGame: function(e) {
+               clearCurrentGame: function(e) {
                        this.getRidOfTooltip(e.currentTarget);
-                       this.clearStorage(); //this.mode=="computer" (already checked)
+                       this.clearStorage();
                        location.reload(); //to see clearing effects
                },
                showSettings: function(e) {
@@ -1285,10 +1302,11 @@ Vue.component('my-game', {
                        if (mode=="human" && !oppId)
                        {
                                const storageVariant = localStorage.getItem("variant");
-                               if (!!storageVariant && storageVariant !== variant)
+                               if (!!storageVariant && storageVariant !== variant
+                                       && localStorage["score"] == "*")
                                {
                                        return alert(translations["Finish your "] +
-                                                       storageVariant + translations[" game first!"]);
+                                               storageVariant + translations[" game first!"]);
                                }
                                // Send game request and wait..
                                try {
@@ -1302,17 +1320,13 @@ Vue.component('my-game', {
                                setTimeout(() => { modalBox.checked = false; }, 2000);
                                return;
                        }
-                       if (["human","chat"].includes(this.mode))
-                       {
-                               // Start a new game vs. another human (or...) => forget about current one
-                               this.clearStorage();
-                       }
+                       const prefix = this.getStoragePrefix(mode);
                        if (mode == "computer")
                        {
-                               const storageVariant = localStorage.getItem("comp-variant");
+                               const storageVariant = localStorage.getItem(prefix+"variant");
                                if (!!storageVariant)
                                {
-                                       const score = localStorage.getItem("comp-score");
+                                       const score = localStorage.getItem(prefix+"score");
                                        if (storageVariant !== variant && score == "*")
                                        {
                                                if (!confirm(storageVariant +
@@ -1325,12 +1339,30 @@ Vue.component('my-game', {
                                                return this.continueGame("computer");
                                }
                        }
+                       else if (mode == "friend")
+                       {
+                               const storageVariant = localStorage.getItem(prefix+"variant");
+                               if (!!storageVariant)
+                               {
+                                       const score = localStorage.getItem(prefix+"score");
+                                       if (storageVariant !== variant && score == "*")
+                                       {
+                                               if (!confirm(storageVariant +
+                                                       translations[": current analysis will be erased"]))
+                                               {
+                                                       return;
+                                               }
+                                       }
+                               }
+                       }
                        this.vr = new VariantRules(fen, []);
                        this.score = "*";
                        this.pgnTxt = ""; //redundant with this.score = "*", but cleaner
                        this.mode = mode;
                        this.incheck = [];
                        this.fenStart = V.ParseFen(fen).position; //this is enough
+                       if (mode != "problem")
+                               this.setStorage(); //store game state in case of interruptions
                        if (mode=="human")
                        {
                                // Opponent found!
@@ -1342,13 +1374,11 @@ Vue.component('my-game', {
                                if (this.sound >= 1)
                                        new Audio("/sounds/newgame.mp3").play().catch(err => {});
                                document.getElementById("modal-newgame").checked = false;
-                               this.setStorage(); //in case of interruptions
                        }
                        else if (mode == "computer")
                        {
                                this.compWorker.postMessage(["init",this.vr.getFen()]);
                                this.mycolor = (Math.random() < 0.5 ? 'w' : 'b');
-                               this.setStorage(); //store game state
                                if (this.mycolor != this.vr.turn)
                                        this.playComputerMove();
                        }
@@ -1359,7 +1389,7 @@ Vue.component('my-game', {
                continueGame: function(mode) {
                        this.mode = mode;
                        this.oppid = (mode=="human" ? localStorage.getItem("oppid") : undefined);
-                       const prefix = (mode=="computer" ? "comp-" : "");
+                       const prefix = this.getStoragePrefix(mode);
                        this.mycolor = localStorage.getItem(prefix+"mycolor");
                        const moves = JSON.parse(localStorage.getItem(prefix+"moves"));
                        const fen = localStorage.getItem(prefix+"fen");
@@ -1374,12 +1404,13 @@ Vue.component('my-game', {
                                this.conn.send(JSON.stringify({
                                        code:"ping",oppid:this.oppid,gameId:this.gameId}));
                        }
-                       else
+                       else if (mode == "computer")
                        {
                                this.compWorker.postMessage(["init",fen]);
                                if (this.mycolor != this.vr.turn)
                                        this.playComputerMove();
                        }
+                       //else: nothing special to do in friend mode
                        if (score != "*")
                        {
                                // Small delay required when continuation run faster than drawing page
@@ -1432,7 +1463,7 @@ Vue.component('my-game', {
                                this.selectedPiece.style.zIndex = 3000;
                                const startSquare = this.getSquareFromId(e.target.parentNode.id);
                                this.possibleMoves = [];
-                               if (!["idle","chat"].includes(this.mode))
+                               if (this.score == "*")
                                {
                                        const color = ["friend","problem"].includes(this.mode)
                                                ? this.vr.turn
@@ -1440,7 +1471,6 @@ Vue.component('my-game', {
                                        if (this.vr.canIplay(color,startSquare))
                                                this.possibleMoves = this.vr.getPossibleMovesFrom(startSquare);
                                }
-                               console.log(this.possibleMoves);
                                // Next line add moving piece just after current image
                                // (required for Crazyhouse reserve)
                                e.target.parentNode.insertBefore(this.selectedPiece, e.target.nextSibling);
@@ -1538,14 +1568,11 @@ Vue.component('my-game', {
                                move = this.vr.moves[this.cursor++];
                        }
                        if (!!programmatic) //computer or human opponent
-                       {
-                               this.animateMove(move);
-                               return;
-                       }
+                               return this.animateMove(move);
                        // Not programmatic, or animation is over
                        if (this.mode == "human" && this.vr.turn == this.mycolor)
                                this.conn.send(JSON.stringify({code:"newmove", move:move, oppid:this.oppid}));
-                       if (!["idle","chat"].includes(this.mode))
+                       if (this.score == "*")
                        {
                                // Emergency check, if human game started "at the same time"
                                // TODO: robustify this...
@@ -1567,22 +1594,19 @@ Vue.component('my-game', {
                                VariantRules.PlayOnBoard(this.vr.board, move);
                                this.$forceUpdate(); //TODO: ?!
                        }
-                       if (!["idle","chat"].includes(this.mode))
+                       const eog = this.vr.checkGameOver();
+                       if (eog != "*")
                        {
-                               const eog = this.vr.checkGameOver();
-                               if (eog != "*")
+                               if (["human","computer"].includes(this.mode))
+                                       this.endGame(eog);
+                               else
                                {
-                                       if (["human","computer"].includes(this.mode))
-                                               this.endGame(eog);
-                                       else
-                                       {
-                                               // Just show score on screen (allow undo)
-                                               this.score = eog;
-                                               this.showScoreMsg();
-                                       }
+                                       // Just show score on screen (allow undo)
+                                       this.score = eog;
+                                       this.showScoreMsg();
                                }
                        }
-                       if (["human","computer"].includes(this.mode))
+                       if (["human","computer","friend"].includes(this.mode))
                                this.updateStorage(); //after our moves and opponent moves
                        if (this.mode == "computer" && this.vr.turn != this.mycolor && this.score == "*")
                                this.playComputerMove();
index ab7a3af..f4d7929 100644 (file)
@@ -1,3 +1,16 @@
-//TODO: turn en fonction de la parité des coups...
+//TODO:
 //adapter alphabeta (dans baserules ? --> basé sur turn OK)
 // le reste == standard
+
+class MarseilleRules extends ChessRules
+{
+       // TODO: fen indication pour turn : w1, w2 ou b1, ou b2 (about to play 1st or 2nd sub-turn)
+       // + quelque chose pour indiquer si c'est le tout premier coup ("w" sans + d'indications)
+       //
+       // this.turn == "w" ou "b"
+       // this.subTurn == 0 ou 1 (ou 1 et 2)
+       //
+       // Alpha-beta ?
+}
+
+const VariantRules = MarseilleRules;
index c3df08c..c2e28a1 100644 (file)
@@ -77,6 +77,10 @@ button.play.spaceleft
   margin-left: 15px
 button.play.spaceright
   margin-right: 15px
+button.play.big-spaceleft
+  margin-left: 25px
+button.play.big-spaceright
+  margin-right: 25px
 
 .aboveboard-wrapper
   width: 80vh
index b49a66b..ff69845 100644 (file)
@@ -27,7 +27,7 @@ ul
        li Tour : coordinateur
        li Cavalier : "sauteur long"
        li Fou : caméléon
-       li Dame : "supprimeur"
+       li Dame : "retireur"
        li King : roi (même comportement qu'aux échecs orthodoxes)
 p.
        En outre, une nouvelle pièce est ajoutée : l'immobiliseur, dénoté par la
@@ -117,7 +117,7 @@ figure.diagram-container
                | fen:2n4k/3r4/5b2/3p4/1m6/3b4/3N4/K7 d4,d6,d8,a5:
        figcaption Toutes les captures marquées sont jouables depuis d2.
 
-h4 "Supprimeur" (dame)
+h4 "Retireur" (dame)
 
 p.
        La dame capture en s'éloignant d'une pièce adverse adjacente, dans la direction
@@ -135,7 +135,7 @@ p.
        Ainsi, il
 ul
        li pince les pions (s'il bouge comme un pion),
-       li supprime les supprimeurs,
+       li retire les retireurs,
        li saute par dessus les sauteurs longs,
        li coordonne les coordinateurs.
 p ...et ces captures peuvent se cumuler.
index 5253c97..a05b1fa 100644 (file)
@@ -34,7 +34,7 @@
                "New game versus computer": "New game versus computer",
                "Analysis mode": "Analysis mode",
                "Start chat": "Start chat",
-               "Clear game versus computer": "Clear game versus computer",
+               "Clear current game": "Clear current game",
                "Settings": "Settings",
                "Resign": "Resign",
                "Undo": "Undo",
@@ -79,4 +79,6 @@
                " game first!": " game first!",
                ": unfinished computer game will be erased":
                        ": unfinished computer game will be erased",
+               ": current analysis will be erased":
+                       ": current analysis will be erased",
        };
index a839ef8..6c2dbcf 100644 (file)
@@ -34,7 +34,7 @@
                "New game versus computer": "Nueva partida contra la computadora",
                "Analysis mode": "Modo de análisis",
                "Start chat": "Iniciar chat",
-               "Clear game versus computer": "Borrar la partida contra la computadora",
+               "Clear current game": "Borrar la partida actual",
                "Settings": "Ajustes",
                "Resign": "Abandonar",
                "Undo": "Deshacer",
@@ -79,4 +79,6 @@
                " game first!": " partida primero !",
                ": unfinished computer game will be erased":
                        " : una partida inconclusa contra la computadora será borrado",
+               ": current analysis will be erased":
+                       " : el análisis actual será borrado",
        };
index c4229fe..e4197b4 100644 (file)
@@ -34,7 +34,7 @@
                "New game versus computer": "Nouvelle partie contre l'ordinateur",
                "Analysis mode": "Mode analyse",
                "Start chat": "Démarrer le chat",
-               "Clear game versus computer": "Effacer la partie contre l'ordinateur",
+               "Clear current game": "Effacer la partie courante",
                "Settings": "Réglages",
                "Resign": "Abandonner",
                "Undo": "Annuler",
@@ -79,4 +79,6 @@
                " game first!": " partie d'abord !",
                ": unfinished computer game will be erased":
                        " : une partie inachevée contre l'ordinateur sera effacée",
+               ": current analysis will be erased":
+                       " : l'analyse en cours sera effacée",
        };