Browse Source

highlight valid moves; use version of chess.js from github

romanmatiasko 9 years ago
parent
commit
76289095d9
6 changed files with 58 additions and 30 deletions
  1. 0 0
      dist/css/main.css
  2. 0 0
      dist/js/play.js
  3. 1 1
      package.json
  4. 15 2
      src/css/_chessboard.scss
  5. 33 25
      src/js/components/Chessboard.js
  6. 9 2
      src/js/stores/GameStore.js

File diff suppressed because it is too large
+ 0 - 0
dist/css/main.css


File diff suppressed because it is too large
+ 0 - 0
dist/js/play.js


+ 1 - 1
package.json

@@ -10,7 +10,7 @@
   "dependencies": {
     "babel": "^4.7.13",
     "body-parser": "^1.12.0",
-    "chess.js": "^0.1.0",
+    "chess.js": "jhlywa/chess.js",
     "classnames": "^1.2.0",
     "debug": "^2.1.3",
     "es6-shim": "^0.27.1",

+ 15 - 2
src/css/_chessboard.scss

@@ -79,11 +79,24 @@
       background: #fefefe;
       display: block;
       float: left;
+      position: relative;
 
-      &.moving { background: lighten($red, 30%) !important; }
-      &.selected { background: lighten($red, 30%) !important; }
+      &.moving, &.selected { background: lighten($red, 30%) !important; }
       &.from { background: lighten($blue, 25%) !important; }
       &.to { background: lighten($blue, 20%) !important; }
+      &.droppable::after {
+        position: absolute;
+        content: "";
+        width: 6px;
+        height: 6px;
+        border: 2px solid $red;
+        top: 50%;
+        left: 50%;
+        margin-left: -5px;
+        margin-top: -5px;
+        background: lighten($red, 15%);
+        transform: rotate(45deg);
+      }
 
       a {
         font-family: 'Smart Regular';

+ 33 - 25
src/js/components/Chessboard.js

@@ -8,7 +8,7 @@ import onGameChange from '../mixins/onGameChange';
 import maybeReverse from '../mixins/maybeReverse';
 import omit from 'lodash.omit';
 import cx from 'classnames';
-import {Seq, Repeat, List} from 'immutable';
+import {Seq, Repeat, List, Set} from 'immutable';
 
 const FILES = Seq.Indexed('abcdefgh');
 const RANKS = Seq.Indexed('12345678');
@@ -64,7 +64,8 @@ const Chessboard = React.createClass({
   },
   render() {
     const {color, isOpponentAvailable, gameOver} = this.props;
-    const fenArray = this.state.fen.split(' ');
+    const {fen, moveFrom, lastMove, kingInCheck} = this.state;
+    const fenArray = fen.split(' ');
     const placement = fenArray[0];
     const isItMyTurn = fenArray[1] === color.charAt(0);
     const rows = this._maybeReverse(placement.split('/'));
@@ -79,10 +80,11 @@ const Chessboard = React.createClass({
             placement={placement}
             color={color}
             isMoveable={isItMyTurn && isOpponentAvailable && !gameOver}
-            moveFrom={this.state.moveFrom}
-            lastMove={this.state.lastMove}
+            moveFrom={moveFrom}
+            lastMove={lastMove}
             setMoveFrom={this._setMoveFrom}
-            kingInCheck={this.state.kingInCheck} />)}
+            kingInCheck={kingInCheck}
+            validMoves={GameStore.getValidMoves(moveFrom)} />)}
       </table>
     );
   },
@@ -134,7 +136,8 @@ const Row = React.createClass({
     moveFrom: React.PropTypes.string,
     lastMove: React.PropTypes.object,
     setMoveFrom: React.PropTypes.func.isRequired,
-    kingInCheck: React.PropTypes.oneOf([false, 'K', 'k']).isRequired
+    kingInCheck: React.PropTypes.oneOf([false, 'K', 'k']).isRequired,
+    validMoves: React.PropTypes.instanceOf(Set).isRequired
   },
   mixins: [maybeReverse],
 
@@ -172,35 +175,39 @@ const Column = React.createClass({
     moveFrom: React.PropTypes.string,
     lastMove: React.PropTypes.object,
     setMoveFrom: React.PropTypes.func.isRequired,
-    kingInCheck: React.PropTypes.oneOf([false, 'K', 'k']).isRequired
+    kingInCheck: React.PropTypes.oneOf([false, 'K', 'k']).isRequired,
+    validMoves: React.PropTypes.instanceOf(Set).isRequired
   },
 
   render() {
     const {moveFrom, lastMove, square, color,
-           isMoveable, kingInCheck} = this.props;
+           isMoveable, kingInCheck, validMoves} = this.props;
     const piece = ChessPieces[this.props.piece];
     const rgx = color === 'white' ? /^[KQRBNP]$/ : /^[kqrbnp]$/;
     const isDraggable = rgx.test(this.props.piece);
+    const isDroppable = moveFrom && validMoves.has(square);
 
-    return piece ? 
+    return (
       <td className={cx({
-            selected: moveFrom === square,
-            to: lastMove.get('to') === square
+            selected: moveFrom === square && !validMoves.isEmpty(),
+            from: lastMove.get('from') === square,
+            to: lastMove.get('to') === square,
+            droppable: isDroppable
           })}
-          onDragOver={!isDraggable ? this._onDragOver : null}
-          onDrop={!isDraggable ? this._onDrop : null}>
-
-        <a className={kingInCheck === this.props.piece ? 'in-check' : null}
-           onClick={this._onClickSquare}
-           onDragStart={this._onDragStart}
-           draggable={isDraggable && isMoveable}>
-          {piece}
-        </a>
-      </td> :
-      <td className={lastMove.get('from') === square ? 'from' : null}
-          onClick={this._onClickSquare}
-          onDragOver={this._onDragOver}
-          onDrop={this._onDrop} />;
+          onClick={!piece ? this._onClickSquare : null}
+          onDragOver={isDroppable ? this._onDragOver : null}
+          onDrop={isDroppable ? this._onDrop : null}>
+
+        {piece ?
+          <a className={kingInCheck === this.props.piece ? 'in-check' : null}
+             onClick={this._onClickSquare}
+             onDragStart={this._onDragStart}
+             draggable={isDraggable && isMoveable}>
+            {piece}
+          </a>
+        :null}
+      </td>
+    );
   },
   _onClickSquare() {
     const {isMoveable, color, moveFrom, square, piece} = this.props;
@@ -219,6 +226,7 @@ const Column = React.createClass({
     e.dataTransfer.effectAllowed = 'move';
     // setData is required by firefox
     e.dataTransfer.setData('text/plain', '');
+
     this.props.setMoveFrom(this.props.square);
   },
   _onDragOver(e) {

+ 9 - 2
src/js/stores/GameStore.js

@@ -5,7 +5,7 @@ import {EventEmitter2 as EventEmitter} from 'eventemitter2';
 import GameConstants from '../constants/GameConstants';
 import ChessPieces from '../constants/ChessPieces';
 import {Chess} from 'chess.js';
-import {List, Map, OrderedMap} from 'immutable';
+import {List, Map, OrderedMap, Set} from 'immutable';
 
 const CHANGE_EVENT = 'change';
 const MOVE_EVENT = 'new-move';
@@ -42,6 +42,13 @@ const GameStore = Object.assign({}, EventEmitter.prototype, {
       lastMove: _lastMove,
       check: _check
     };
+  },
+  getValidMoves(square) {
+    return square ? Set(
+      _chess.moves({
+        square: square,
+        verbose: true
+      }).map(move => move.to)) : Set();
   }
 });
 
@@ -84,7 +91,7 @@ function makeMove(from, to, capture, emitMove) {
 
   if (capture || move.flags === 'e') {
     const capturedPiece = capture ||
-      (_turn === 'w' ? '\u2659' : '\u265f'); // en passant
+      ChessPieces[_turn === 'w' ? 'P' : 'p']; // en passant
 
     _capturedPieces = _capturedPieces
       .update(_turn, list => list.push(capturedPiece));

Some files were not shown because too many files changed in this diff