Computer mode in rules section almost OK
[vchess.git] / public / javascripts / components / board.js
index 6110cfb..5a75f29 100644 (file)
@@ -1,10 +1,9 @@
 Vue.component('my-board', {
        // Last move cannot be guessed from here, and is required to highlight squares
-       // gotoMove : juste set FEN depuis FEN stocké dans le coup (TODO)
-       // send event after each move (or undo), to notify what was played
-       // also notify end of game (which returns here later through prop...)
-       props: ["fen","moveToPlay","moveToUndo",
-               "analyze","lastMove","orientation","userColor","gameOver"],
+       // vr: object to check moves, print board...
+       // mode: HH, HC or analyze
+       // userColor: for mode HH or HC
+       props: ["vr","lastMove","mode","orientation","userColor"],
        data: function () {
                return {
                        hints: (!localStorage["hints"] ? true : localStorage["hints"] === "1"),
@@ -14,25 +13,11 @@ Vue.component('my-board', {
                        selectedPiece: null, //moving piece (or clicked piece)
                        incheck: [],
                        start: {}, //pixels coordinates + id of starting square (click or drag)
-                       vr: null, //object to check moves, store them, FEN..
                };
        },
-       watch: {
-               // NOTE: maybe next 3 should be encapsulated in object to be watched (?)
-               fen: function(newFen) {
-                       this.vr = new VariantRules(newFen);
-               },
-               moveToPlay: function(move) {
-                       this.play(move, "animate");
-               },
-               moveToUndo: function(move) {
-                       this.undo(move);
-               },
-       },
-       created: function() {
-               this.vr = new VariantRules(this.fen);
-       },
        render(h) {
+               if (!this.vr)
+                       return;
                const [sizeX,sizeY] = [V.size.x,V.size.y];
                // Precompute hints squares to facilitate rendering
                let hintSquares = doubleArray(sizeX, sizeY, false);
@@ -40,6 +25,7 @@ Vue.component('my-board', {
                // Also precompute in-check squares
                let incheckSq = doubleArray(sizeX, sizeY, false);
                this.incheck.forEach(sq => { incheckSq[sq[0]][sq[1]] = true; });
+               const squareWidth = 40; //TODO: compute this
                const choices = h(
                        'div',
                        {
@@ -104,7 +90,8 @@ Vue.component('my-board', {
                                                let cj = (this.orientation=='w' ? j : sizeY-j-1);
                                                let elems = [];
                                                if (this.vr.board[ci][cj] != V.EMPTY && (variant.name!="Dark"
-                                                       || this.gameOver || this.vr.enlightened[this.userColor][ci][cj]))
+                                                       || this.gameOver || this.mode == "analyze"
+                                                       || this.vr.enlightened[this.userColor][ci][cj]))
                                                {
                                                        elems.push(
                                                                h(
@@ -149,12 +136,13 @@ Vue.component('my-board', {
                                                                        'dark-square': (i+j)%2==1,
                                                                        [this.bcolor]: true,
                                                                        'in-shadow': variant.name=="Dark" && !this.gameOver
+                                                                               && this.mode != "analyze"
                                                                                && !this.vr.enlightened[this.userColor][ci][cj],
                                                                        'highlight': showLight && !!lm && _.isMatch(lm.end, {x:ci,y:cj}),
                                                                        'incheck': showLight && incheckSq[ci][cj],
                                                                },
                                                                attrs: {
-                                                                       id: this.getSquareId({x:ci,y:cj}),
+                                                                       id: getSquareId({x:ci,y:cj}),
                                                                },
                                                        },
                                                        elems
@@ -173,7 +161,7 @@ Vue.component('my-board', {
                                myReservePiecesArray.push(h('div',
                                {
                                        'class': {'board':true, ['board'+sizeY]:true},
-                                       attrs: { id: this.getSquareId({x:sizeX+shiftIdx,y:i}) }
+                                       attrs: { id: getSquareId({x:sizeX+shiftIdx,y:i}) }
                                },
                                [
                                        h('img',
@@ -191,13 +179,13 @@ Vue.component('my-board', {
                                ]));
                        }
                        let oppReservePiecesArray = [];
-                       const oppCol = this.vr.getOppCol(this.userColor);
+                       const oppCol = V.GetOppCol(this.userColor);
                        for (let i=0; i<V.RESERVE_PIECES.length; i++)
                        {
                                oppReservePiecesArray.push(h('div',
                                {
                                        'class': {'board':true, ['board'+sizeY]:true},
-                                       attrs: { id: this.getSquareId({x:sizeX+(1-shiftIdx),y:i}) }
+                                       attrs: { id: getSquareId({x:sizeX+(1-shiftIdx),y:i}) }
                                },
                                [
                                        h('img',
@@ -263,16 +251,6 @@ Vue.component('my-board', {
                );
        },
        methods: {
-               // Get the identifier of a HTML square from its numeric coordinates o.x,o.y.
-               getSquareId: function(o) {
-                       // NOTE: a separator is required to allow any size of board
-                       return  "sq-" + o.x + "-" + o.y;
-               },
-               // Inverse function
-               getSquareFromId: function(id) {
-                       let idParts = id.split('-');
-                       return [parseInt(idParts[1]), parseInt(idParts[2])];
-               },
                mousedown: function(e) {
                        e = e || window.event;
                        let ingame = false;
@@ -303,9 +281,9 @@ Vue.component('my-board', {
                                this.selectedPiece.style.top = 0;
                                this.selectedPiece.style.display = "inline-block";
                                this.selectedPiece.style.zIndex = 3000;
-                               const startSquare = this.getSquareFromId(e.target.parentNode.id);
+                               const startSquare = getSquareFromId(e.target.parentNode.id);
                                this.possibleMoves = [];
-                               const color = this.analyze || this.gameOver
+                               const color = this.mode=="analyze" || this.gameOver
                                        ? this.vr.turn
                                        : this.userColor;
                                if (this.vr.canIplay(color,startSquare))
@@ -349,7 +327,7 @@ Vue.component('my-board', {
                                return;
                        }
                        // OK: process move attempt
-                       let endSquare = this.getSquareFromId(landing.id);
+                       let endSquare = getSquareFromId(landing.id);
                        let moves = this.findMatchingMoves(endSquare);
                        this.possibleMoves = [];
                        if (moves.length > 1)
@@ -370,54 +348,8 @@ Vue.component('my-board', {
                        });
                        return moves;
                },
-               animateMove: function(move) {
-                       let startSquare = document.getElementById(this.getSquareId(move.start));
-                       let endSquare = document.getElementById(this.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");
-                       // 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<squares.length; i++)
-                       {
-                               let square = squares.item(i);
-                               if (square.id != this.getSquareId(move.start))
-                                       square.style.zIndex = "-1";
-                       }
-                       movingPiece.style.transform = "translate(" + translation.x + "px," +
-                               translation.y + "px)";
-                       movingPiece.style.transitionDuration = "0.2s";
-                       movingPiece.style.zIndex = "3000";
-                       setTimeout( () => {
-                               for (let i=0; i<squares.length; i++)
-                                       squares.item(i).style.zIndex = "auto";
-                               movingPiece.style = {}; //required e.g. for 0-0 with KR swap
-                               this.play(move);
-                       }, 250);
-               },
-               play: function(move, programmatic) {
-                       if (!!programmatic) //computer or human opponent
-                               return this.animateMove(move);
-                       // Not programmatic, or animation is over
-                       this.vr.play(move);
-                       if (this.sound == 2)
-                               new Audio("/sounds/move.mp3").play().catch(err => {});
-                       // Is opponent in check?
-                       this.incheck = this.vr.getCheckSquares(this.vr.turn);
-                       const eog = this.vr.getCurrentScore();
-                       if (eog != "*")
-                       {
-                               // TODO: notify end of game (give score)
-                       }
-               },
-               undo: function(move) {
-                       this.vr.undo(move);
-                       if (this.sound == 2)
-                               new Audio("/sounds/undo.mp3").play().catch(err => {});
-                       this.incheck = this.vr.getCheckSquares(this.vr.turn);
+               play: function(move) {
+                       this.$emit('play-move', move);
                },
        },
 })