瀏覽代碼

Fixes Game Play and partially verifies moves + Calculates Winner

Nikatlas 6 年之前
父節點
當前提交
021990e877

+ 33 - 0
src/Game/game/machine/GameMachine.js

@@ -15,6 +15,10 @@ class GameMachine {
         };
     }
 
+    flush() {
+        console.log(this.state);
+    }
+
     setState(state) {
         this.state = { ...this.state, ...state};
     }
@@ -46,6 +50,30 @@ class GameMachine {
         return this.state.players.indexOf(this.state.board.owners[x]);
     }
 
+    hasFinished() {
+        return this.state.stack.length >= 10;
+    }
+
+    getWinner() {
+        const score1 = this.state.board.getScore(this.state.players[0]);
+        const score2 = this.state.board.getScore(this.state.players[1]) + 1;
+        return  score1 == score2 ? -1 
+            : (
+                score1 > score2
+                    ? this.state.players[0]
+                    : this.state.players[1]
+            );
+    }
+
+    isMyTurn(player) {
+        let moves = this.state.stack.length;
+        return this.getPlayerNumber(player) === moves % 2 && moves < 10;
+    }
+
+    needFinalization() {
+        return this.state.stack.length === 9;
+    }
+
     runMove(move) {
         const spray = SHA256(JSON.stringify(move)).toString();
         if (this.state.stack.includes(spray)) {
@@ -53,6 +81,7 @@ class GameMachine {
             return;
         }
         try {
+            move.verify(this.state);
             move.performMove(this.state.board);
             this.state.stack.push(spray);
         } catch (e) {
@@ -82,6 +111,10 @@ class Board {
         }
     }
 
+    getScore(player) {
+        return this.owners.reduce((a,b) => b === player ? a + 1 : a, 0);
+    }
+
     debug() {
         console.log('BOARD');
         console.log('---------------------------');

+ 25 - 4
src/Game/game/machine/GameMoves.js

@@ -8,7 +8,7 @@ class GameMove {
 }
 GameMove.TYPES = {
     PLACE: 1,
-    PLACE_AND_REVEAL: 2,
+    REVEAL: 2,
     SELECT_CARDS: 0
 };
 
@@ -21,10 +21,10 @@ class PlaceMove extends GameMove {
         this.player = player;
     }
     verify(state) {
-        if (state.board.isEmpty(this.position)) {
+        if (!state.board.isEmpty(this.position)) {
             throw Error('Not a valid move, there is already a card there!');
         }
-
+        // Verify the hash of the card to be sure it was there from the beginning
         return true;
     }
 
@@ -42,6 +42,27 @@ class PlaceMove extends GameMove {
     }
 }
 
+class RevealMove extends GameMove {
+    constructor(card, player) {
+        super(GameMove.TYPES.REVEAL, {});
+        this.card = card;
+        this.player = player;
+    }
+
+    verify(state) {
+        if (state.stack.length != 9) {
+            throw Error('Not a valid move, Need to play all cards to reveal!');
+        }
+        // TODO - Verify the last card from hashes
+        return true;
+    }
+
+    performMove() {
+        console.log("Reveal move processed");
+    }
+}
+
 module.exports = {
-    PlaceMove
+    PlaceMove,
+    RevealMove
 };

+ 20 - 0
src/Game/services/GameService.js

@@ -40,16 +40,36 @@ class GameService {
         const move = new Game.GameMoves.PlaceMove(card, position, player);
         try{
             this.GameMachine.runMove(move);
+            let ind = this.state.cards.indexOf(cardid);
+            this.state.cards.splice(ind,1);
         } catch (e) {
             console.log(e);
             throw e;
         }
+
         // require UI Update where a card is placed and Board updated
         if(this.onUpdate) this.onUpdate(1);
+        if(this.GameMachine.hasFinished()) this.end();
+        else if(this.GameMachine.needFinalization() && this.GameMachine.isMyTurn()) this.sendFinalization();
+    }
+
+    sendFinalization() {
+        const card = new Game.Card(this.state.cards[0]);
+        const move = new Game.GameMoves.RevealMove(card, UserService.getToken());
+        try {
+            this.GameMachine.runMove(move);
+            SocketService.emit('broadcast', move);
+            this.end();
+        } catch(e) {
+            console.log("[ /!\\ ] GameService: Cannot run Reveal Move!");
+            throw e;
+        }
     }
 
     end(data) {
         SocketService.close();
+        if(this.onEnd)
+            this.onEnd();
     }
 }
 

+ 5 - 4
src/Game/views/base/CardHolder.js

@@ -105,8 +105,8 @@ class CardHolder extends GuiableContainer {
     lock(card = null) {
         this.unsetEvents();
         this._locked = true;
-        this._card = card;
         if(card) {
+            this._card = card;
             card.attach(this);
             if(this._lockable)card.unsetEvents();
         }
@@ -123,9 +123,10 @@ class CardHolder extends GuiableContainer {
     }
 
     unlock() {
-        this.setEvents();
-        this._locked = false;
-        this._card = null;
+        if(!this._lockable || !this._card) {
+            this.setEvents();
+            this._locked = false;
+        }
     }
 
     scaleTo(s) {

+ 18 - 2
src/Game/views/buildings/Board.js

@@ -6,6 +6,8 @@ import GuiableContainer from '../../../helpers/Guiable';
 import CardHolder from '../base/CardHolder';
 // import CollectionHolder from '../base/CollectionHolder';
 import Injector from '../../services/Injector';
+import UserService from '../../services/UserService';
+
 import Text from '../misc/Text';
 import Card from '../base/Card';
 
@@ -65,6 +67,9 @@ class BoardHandler extends GuiableContainer{
 
         this.score = new Text({GameLayer, x: 350, y: 0, text: '0 - 0'});
         this.addChild(this.score);
+        
+        // this.disable();
+
     }
 
     sync = (GameMachine) => {
@@ -81,8 +86,10 @@ class BoardHandler extends GuiableContainer{
                 holder.occupy(card);
                 card.setTeam(GameMachine.getPositionTeam(index));
             }
-        })
+        });
         this.updateScore();
+        GameMachine.flush();
+        GameMachine.isMyTurn(UserService.getToken()) ? this.enable() : this.disable();
     }
 
     updateScore() {
@@ -109,8 +116,17 @@ class BoardHandler extends GuiableContainer{
         return this.holders[3*y+x].getCard();
     }
 
+    disable() { 
+        this.holders.forEach((item) => item.lock());
+        this.disabled = true; 
+    }
+    enable() {
+        this.holders.forEach((item) => item.unlock());
+        this.disabled = false; 
+    }
+
     placeCard(position, card) {
-        if(this.onCardPlaced) {
+        if(this.onCardPlaced && !this.disabled) {
             this.onCardPlaced(position, card);
         }
     }

+ 15 - 2
src/Game/views/demo/Board.js

@@ -23,9 +23,9 @@ class BoardDemo extends PIXI.Container{
 
         this.board.onCardPlaced = (position, card) => {
             const move = {
-                cardid: card.id,
+                cardid  : card.id,
                 position: position,
-                player: UserService.getToken()
+                player  : UserService.getToken()
             };
             SocketService.emit('broadcast', move);
         }
@@ -33,12 +33,25 @@ class BoardDemo extends PIXI.Container{
         GameService.onInit = () => {
             console.log("GameService onInit : from './demo/Board.js'");
             this.deck.sync(GameService.state.cards, GameService.getMyTeam());
+            this.board.sync(GameService.GameMachine);
         }
 
         GameService.onUpdate = () => {
             console.log("GameService onUpdate : from './demo/Board.js'");
             this.board.sync(GameService.GameMachine);
         }
+
+        GameService.onEnd = () => {
+            console.log("Game Finished!");
+            let winner = GameService.GameMachine.getWinner();
+            if (winner == -1) {
+                console.log("Tie");
+            } else if (winner == UserService.getToken()) {
+                console.log("You won!");
+            } else {
+                console.log("You lost!");
+            }
+        }
     }
     
     update() {}