Show accessible squares when a figure is selected chess
authorJaroslav Tulach <jtulach@netbeans.org>
Fri, 26 Jul 2013 17:14:25 +0200
branchchess
changeset 341ebd52ae8ccb
parent 33 ba6946f6b880
child 35 7ae0125d57b2
Show accessible squares when a figure is selected
chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java
chess/src/main/java/org/apidesign/html/demo/chess/Rules.java
chess/src/main/webapp/pages/css/chess.css
chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java
     1.1 --- a/chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java	Fri Jul 26 17:13:08 2013 +0200
     1.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java	Fri Jul 26 17:14:25 2013 +0200
     1.3 @@ -39,19 +39,24 @@
     1.4          if (previoslySelected == null) {
     1.5              if (data.getPiece() != null && data.getPieceColor() == b.getTurn()) {
     1.6                  data.setSelected(true);
     1.7 +                Rules.computeAccessible(b, data);
     1.8              }
     1.9          } else {
    1.10 -            previoslySelected.setSelected(false);
    1.11              if (data.getPiece() != null && data.getPieceColor() == previoslySelected.getPieceColor()) {
    1.12                  previoslySelected.setSelected(false);
    1.13                  data.setSelected(true);
    1.14 +                Rules.computeAccessible(b, data);
    1.15                  return;
    1.16              }
    1.17 -            data.setPieceColor(previoslySelected.getPieceColor());
    1.18 -            data.setPiece(previoslySelected.getPiece());
    1.19 -            b.setTurn(b.getTurn() == ColorType.WHITE ? ColorType.BLACK : ColorType.WHITE);
    1.20 -            previoslySelected.setPiece(null);
    1.21 -            previoslySelected.setPieceColor(null);
    1.22 +            if (data.isAccessible()) {
    1.23 +                previoslySelected.setSelected(false);
    1.24 +                data.setPieceColor(previoslySelected.getPieceColor());
    1.25 +                data.setPiece(previoslySelected.getPiece());
    1.26 +                b.setTurn(b.getTurn() == ColorType.WHITE ? ColorType.BLACK : ColorType.WHITE);
    1.27 +                previoslySelected.setPiece(null);
    1.28 +                previoslySelected.setPieceColor(null);
    1.29 +                Rules.computeAccessible(b, null);
    1.30 +            }
    1.31          }
    1.32      }
    1.33      
    1.34 @@ -124,7 +129,8 @@
    1.35          @Property(name = "color", type = ColorType.class),
    1.36          @Property(name = "x", type = int.class),
    1.37          @Property(name = "y", type = int.class),
    1.38 -        @Property(name = "selected", type = boolean.class)
    1.39 +        @Property(name = "selected", type = boolean.class),
    1.40 +        @Property(name = "accessible", type = boolean.class),
    1.41      })
    1.42      static class PieceImpl {
    1.43          @ComputedProperty static String pieceEntity(
    1.44 @@ -136,10 +142,15 @@
    1.45              return piece.computeEntity(pieceColor);
    1.46          }
    1.47          
    1.48 -        @ComputedProperty static String squareColor(ColorType color, boolean selected) {
    1.49 +        @ComputedProperty static String squareColor(
    1.50 +            ColorType color, boolean selected, boolean accessible
    1.51 +        ) {
    1.52              if (selected) {
    1.53                  return "selected";
    1.54              }
    1.55 +            if (accessible) {
    1.56 +                return "accessible";
    1.57 +            }
    1.58              
    1.59              if (color == null) {
    1.60                  return "";
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Rules.java	Fri Jul 26 17:14:25 2013 +0200
     2.3 @@ -0,0 +1,130 @@
     2.4 +/**
     2.5 + * The MIT License (MIT)
     2.6 + *
     2.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.8 + *
     2.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    2.10 + * of this software and associated documentation files (the "Software"), to deal
    2.11 + * in the Software without restriction, including without limitation the rights
    2.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    2.13 + * copies of the Software, and to permit persons to whom the Software is
    2.14 + * furnished to do so, subject to the following conditions:
    2.15 + *
    2.16 + * The above copyright notice and this permission notice shall be included in
    2.17 + * all copies or substantial portions of the Software.
    2.18 + *
    2.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    2.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    2.25 + * THE SOFTWARE.
    2.26 + */
    2.27 +package org.apidesign.html.demo.chess;
    2.28 +
    2.29 +/** Common chess rules.
    2.30 + *
    2.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    2.32 + */
    2.33 +class Rules {
    2.34 +    static void computeAccessible(Board b, Square s) {
    2.35 +        for (Row r : b.getRows()) {
    2.36 +            for (Square ts : r.getColumns()) {
    2.37 +                ts.setAccessible(false);
    2.38 +            }
    2.39 +        }
    2.40 +        if (s == null) {
    2.41 +            return;
    2.42 +        }
    2.43 +        
    2.44 +        switch (s.getPiece()) {
    2.45 +            case BISHOP: 
    2.46 +                moveBishop(b, s);
    2.47 +                break;
    2.48 +            case KING:
    2.49 +                computeAccessible(b, s, 1, 1, 1);
    2.50 +                computeAccessible(b, s, 1, -1, 1);
    2.51 +                computeAccessible(b, s, -1, -1, 1);
    2.52 +                computeAccessible(b, s, -1, 1, 1);
    2.53 +                computeAccessible(b, s, 1, 0, 1);
    2.54 +                computeAccessible(b, s, 0, -1, 1);
    2.55 +                computeAccessible(b, s, 0, 1, 1);
    2.56 +                computeAccessible(b, s, -1, 0, 1);
    2.57 +                break;
    2.58 +            case ROCK:
    2.59 +                moveRock(b, s);
    2.60 +                break;
    2.61 +            case QUEEN:
    2.62 +                moveRock(b, s);
    2.63 +                moveBishop(b, s);
    2.64 +                break;
    2.65 +            case KNIGHT:
    2.66 +                computeAccessible(b, s, 2, 1, 1);
    2.67 +                computeAccessible(b, s, 2, -1, 1);
    2.68 +                computeAccessible(b, s, -2, -1, 1);
    2.69 +                computeAccessible(b, s, -2, 1, 1);
    2.70 +                computeAccessible(b, s, 1, 2, 1);
    2.71 +                computeAccessible(b, s, -1, 2, 1);
    2.72 +                computeAccessible(b, s, -1, -2, 1);
    2.73 +                computeAccessible(b, s, 1, -2, 1);
    2.74 +                break;
    2.75 +            case PAWN:
    2.76 +                pawns(b, s);
    2.77 +                break;
    2.78 +        }
    2.79 +    }
    2.80 +
    2.81 +    private static void moveRock(Board b, Square s) {
    2.82 +        computeAccessible(b, s, 1, 0, 8);
    2.83 +        computeAccessible(b, s, 0, -1, 8);
    2.84 +        computeAccessible(b, s, -1, 0, 8);
    2.85 +        computeAccessible(b, s, 0, 1, 8);
    2.86 +    }
    2.87 +
    2.88 +    private static void moveBishop(Board b, Square s) {
    2.89 +        computeAccessible(b, s, 1, 1, 8);
    2.90 +        computeAccessible(b, s, 1, -1, 8);
    2.91 +        computeAccessible(b, s, -1, -1, 8);
    2.92 +        computeAccessible(b, s, -1, 1, 8);
    2.93 +    }
    2.94 +    
    2.95 +    private static void computeAccessible(
    2.96 +        Board b, Square s, int dx, int dy,
    2.97 +        int limit
    2.98 +    ) {
    2.99 +        int x = s.getX();
   2.100 +        int y = s.getY();
   2.101 +        
   2.102 +        while (limit-- > 0) {
   2.103 +            x += dx;
   2.104 +            y += dy;
   2.105 +            Square next = BoardModel.findSquare(b, (char)x, y);
   2.106 +            if (next == null) {
   2.107 +                break;
   2.108 +            }
   2.109 +            if (next.getPieceColor() == s.getPieceColor()) {
   2.110 +                break;
   2.111 +            }
   2.112 +            next.setAccessible(true);
   2.113 +            if (next.getPieceColor() != null) {
   2.114 +                break;
   2.115 +            }
   2.116 +        }
   2.117 +    }
   2.118 +    
   2.119 +    private static void pawns(Board b, Square s) {
   2.120 +        final boolean white = s.getPieceColor() == BoardModel.ColorType.WHITE;
   2.121 +        int dy = white ? 1 : -1;
   2.122 +        Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
   2.123 +        if (step != null && step.getPiece() == null) {
   2.124 +            step.setAccessible(true);
   2.125 +            if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
   2.126 +                Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
   2.127 +                if (nextSTep != null && step.getPiece() == null) {
   2.128 +                    nextSTep.setAccessible(true);
   2.129 +                }
   2.130 +            }
   2.131 +        }
   2.132 +    }
   2.133 +}
     3.1 --- a/chess/src/main/webapp/pages/css/chess.css	Fri Jul 26 17:13:08 2013 +0200
     3.2 +++ b/chess/src/main/webapp/pages/css/chess.css	Fri Jul 26 17:14:25 2013 +0200
     3.3 @@ -55,6 +55,9 @@
     3.4  table.board td.selected {
     3.5  	background-color:  	#B000B0;
     3.6  }
     3.7 +table.board td.accessible {
     3.8 +	background-color:  	#00B0B0;
     3.9 +}
    3.10  .figure {
    3.11  	cursor: pointer;
    3.12  }
    3.13 \ No newline at end of file
     4.1 --- a/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java	Fri Jul 26 17:13:08 2013 +0200
     4.2 +++ b/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java	Fri Jul 26 17:14:25 2013 +0200
     4.3 @@ -24,6 +24,7 @@
     4.4  package org.apidesign.html.demo.chess;
     4.5  
     4.6  import org.apidesign.html.demo.chess.BoardModel.ColorType;
     4.7 +import org.apidesign.html.demo.chess.BoardModel.PieceType;
     4.8  import static org.testng.Assert.*;
     4.9  import org.testng.annotations.Test;
    4.10  
    4.11 @@ -95,4 +96,28 @@
    4.12          
    4.13      }
    4.14      
    4.15 +    @Test public void knightMustMoveToF3() {
    4.16 +        Board b = BoardModel.createBoard();
    4.17 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
    4.18 +        BoardModel.selected(b, g1);
    4.19 +        
    4.20 +        Square f3 = BoardModel.findSquare(b, 'F', 3);
    4.21 +        assertTrue(f3.isAccessible(), "This is a field where knight can move");
    4.22 +
    4.23 +        Square g3 = BoardModel.findSquare(b, 'G', 3);
    4.24 +        assertFalse(g3.isAccessible(), "Not a place for knight");
    4.25 +
    4.26 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
    4.27 +        assertFalse(e2.isAccessible(), "Not a place either, occupied");
    4.28 +
    4.29 +        BoardModel.selected(b, g3);
    4.30 +        
    4.31 +        assertNull(g3.getPiece(), "No figure was moved");
    4.32 +        assertTrue(g1.isSelected(), "Original square still selected");
    4.33 +        
    4.34 +        BoardModel.selected(b, f3);
    4.35 +        
    4.36 +        assertEquals(f3.getPiece(), PieceType.KNIGHT, "Moved");
    4.37 +        assertFalse(g3.isSelected(), "No longer selected");
    4.38 +    }
    4.39  }