chess/src/main/java/com/oracle/chess/client/htmljava/Rules.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 24 Sep 2013 22:20:24 +0200
branchchess
changeset 49 945fbfff28f3
permissions -rw-r--r--
Advanced version of the chess game
     1 /**
     2  * The MIT License (MIT)
     3  *
     4  * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5  *
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
     7  * of this software and associated documentation files (the "Software"), to deal
     8  * in the Software without restriction, including without limitation the rights
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10  * copies of the Software, and to permit persons to whom the Software is
    11  * furnished to do so, subject to the following conditions:
    12  *
    13  * The above copyright notice and this permission notice shall be included in
    14  * all copies or substantial portions of the Software.
    15  *
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    22  * THE SOFTWARE.
    23  */
    24 package com.oracle.chess.client.htmljava;
    25 
    26 import java.util.ArrayList;
    27 import java.util.List;
    28 
    29 /** Common chess rules.
    30  *
    31  * @author Jaroslav Tulach <jtulach@netbeans.org>
    32  */
    33 class Rules {
    34     static void computeAccessible(Board b, Square s) {
    35         for (Row r : b.getRows()) {
    36             for (Square ts : r.getColumns()) {
    37                 ts.setAccessible(false);
    38             }
    39         }
    40         if (s == null) {
    41             return;
    42         }
    43         
    44         switch (s.getPiece()) {
    45             case BISHOP: 
    46                 moveBishop(b, s);
    47                 break;
    48             case KING:
    49                 computeAccessible(b, s, 1, 1, 1);
    50                 computeAccessible(b, s, 1, -1, 1);
    51                 computeAccessible(b, s, -1, -1, 1);
    52                 computeAccessible(b, s, -1, 1, 1);
    53                 computeAccessible(b, s, 1, 0, 1);
    54                 computeAccessible(b, s, 0, -1, 1);
    55                 computeAccessible(b, s, 0, 1, 1);
    56                 computeAccessible(b, s, -1, 0, 1);
    57                 checkRochade(b, s);
    58                 break;
    59             case ROCK:
    60                 moveRock(b, s);
    61                 break;
    62             case QUEEN:
    63                 moveRock(b, s);
    64                 moveBishop(b, s);
    65                 break;
    66             case KNIGHT:
    67                 computeAccessible(b, s, 2, 1, 1);
    68                 computeAccessible(b, s, 2, -1, 1);
    69                 computeAccessible(b, s, -2, -1, 1);
    70                 computeAccessible(b, s, -2, 1, 1);
    71                 computeAccessible(b, s, 1, 2, 1);
    72                 computeAccessible(b, s, -1, 2, 1);
    73                 computeAccessible(b, s, -1, -2, 1);
    74                 computeAccessible(b, s, 1, -2, 1);
    75                 break;
    76             case PAWN:
    77                 pawns(b, s);
    78                 break;
    79         }
    80     }
    81 
    82     private static void moveRock(Board b, Square s) {
    83         computeAccessible(b, s, 1, 0, 8);
    84         computeAccessible(b, s, 0, -1, 8);
    85         computeAccessible(b, s, -1, 0, 8);
    86         computeAccessible(b, s, 0, 1, 8);
    87     }
    88 
    89     private static void moveBishop(Board b, Square s) {
    90         computeAccessible(b, s, 1, 1, 8);
    91         computeAccessible(b, s, 1, -1, 8);
    92         computeAccessible(b, s, -1, -1, 8);
    93         computeAccessible(b, s, -1, 1, 8);
    94     }
    95     
    96     private static void computeAccessible(
    97         Board b, Square s, int dx, int dy,
    98         int limit
    99     ) {
   100         int x = s.getX();
   101         int y = s.getY();
   102         
   103         while (limit-- > 0) {
   104             x += dx;
   105             y += dy;
   106             Square next = BoardModel.findSquare(b, (char)x, y);
   107             if (next == null) {
   108                 break;
   109             }
   110             if (next.getPieceColor() == s.getPieceColor()) {
   111                 break;
   112             }
   113             next.setAccessible(true);
   114             if (next.getPieceColor() != null) {
   115                 break;
   116             }
   117         }
   118     }
   119     
   120     private static void pawns(Board b, Square s) {
   121         final boolean white = s.getPieceColor() == Color.W;
   122         int dy = white ? 1 : -1;
   123         Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
   124         if (step != null && step.getPiece() == null) {
   125             step.setAccessible(true);
   126             if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
   127                 Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
   128                 if (nextSTep != null && step.getPiece() == null && nextSTep.getPiece() == null) {
   129                     nextSTep.setAccessible(true);
   130                 }
   131             }
   132         }
   133         Color opposite = white ? Color.B : Color.W;
   134         Square takeLeft = BoardModel.findSquare(b, (char)(s.getX() - 1), s.getY() + dy);
   135         if (takeLeft != null && takeLeft.getPieceColor() == opposite) {
   136             takeLeft.setAccessible(true);
   137         }
   138         Square takeRight = BoardModel.findSquare(b, (char)(s.getX() + 1), s.getY() + dy);
   139         if (takeRight != null && takeRight.getPieceColor() == opposite) {
   140             takeRight.setAccessible(true);
   141         }
   142         if ((white && s.getY() == 5) || (!white && s.getY() == 4)) {
   143             int enPassantFrom = white ? 7 : 2;
   144             int enPassantTo = white ? 5 : 4;
   145             if (!b.getMoves().isEmpty()) {
   146                 Move last = b.getMoves().get(b.getMoves().size() - 1);
   147                 if (
   148                     last.getPiece() == BoardModel.PieceType.PAWN &&
   149                     last.getFrom().getY() == enPassantFrom &&
   150                     last.getTo().getY() == enPassantTo
   151                 ) {
   152                     if (takeLeft != null && last.getFrom().getX() == s.getX() - 1) {
   153                         takeLeft.setAccessible(true);
   154                     }
   155                     if (takeRight != null && last.getFrom().getX() == s.getX() + 1) {
   156                         takeRight.setAccessible(true);
   157                     }
   158                 }
   159             }
   160         }
   161     }
   162 
   163     static Board createBoard() {
   164         Board b = new Board();
   165         initBoardField(b);
   166         initBoard(b);
   167         return b;
   168     }
   169 
   170     private static void initBoardField(Board b) {
   171         List<Row> addRows = new ArrayList<>(8);
   172         for (int i = 8; i > 0; i--) {
   173             Square[] arr = new Square[8];
   174             for (char j = 'A'; j <= 'H'; j++) {
   175                 arr[j - 'A'] = new Square(
   176                     new Position(j, i),
   177                     (i + j) % 2 == 1 ? Color.W : Color.B,
   178                     null, null, // figure
   179                     false, false, false
   180                 );
   181             }
   182             addRows.add(new Row(arr));
   183         }
   184         b.getRows().addAll(addRows);
   185     }
   186     
   187     static void initBoard(Board b) {
   188         initBoard(b, true);
   189     }
   190     private static void initBoard(Board b, boolean init) {
   191         if (init) {
   192             b.setTurn(Color.W);
   193         }
   194         if (b.getRows().isEmpty()) {
   195             for (int i = 8; i > 0; i--) {
   196                 Row r = b.getRows().get(8 - i);
   197                 for (char j = 'A'; j <= 'H'; j++) {
   198                     Square s = r.getColumns().get(j - 'A');
   199                     s.setAccessible(false);
   200                     s.setPending(false);
   201                     r.getColumns().set(j - 'A', s);
   202                     initialPosition(s, init);
   203                 }
   204             }
   205         } else {
   206             for (Row r : b.getRows()) {
   207                 for (Square square : r.getColumns()) {
   208                     square.setAccessible(false);
   209                     square.setPending(false);
   210                     square.setPiece(null);
   211                     square.setPieceColor(null);
   212                     square.setSelected(false);
   213                     initialPosition(square, init);
   214                 }
   215             }
   216         }
   217         b.setPendingMove(null);
   218     }
   219 
   220     private static void initialPosition(Square s, boolean init) {
   221         int row = s.getPosition().getY();
   222         char column = s.getPosition().getX();
   223         s.setPiece(null);
   224         s.setPieceColor(null);
   225         if (init) {
   226             if (row == 2) {
   227                 s.setPiece(BoardModel.PieceType.PAWN);
   228                 s.setPieceColor(Color.W);
   229             } else if (row == 7) {
   230                 s.setPiece(BoardModel.PieceType.PAWN);
   231                 s.setPieceColor(Color.B);
   232             } else if (row == 8 || row == 1) {
   233                 s.setPieceColor(row == 1 ? Color.W : Color.B);
   234                 BoardModel.PieceType t;
   235                 switch (column) {
   236                     case 'A':
   237                     case 'H':
   238                         t = BoardModel.PieceType.ROCK;
   239                         break;
   240                     case 'B':
   241                     case 'G':
   242                         t = BoardModel.PieceType.KNIGHT;
   243                         break;
   244                     case 'C':
   245                     case 'F':
   246                         t = BoardModel.PieceType.BISHOP;
   247                         break;
   248                     case 'D':
   249                         t = BoardModel.PieceType.QUEEN;
   250                         break;
   251                     default:
   252                         t = BoardModel.PieceType.KING;
   253                         break;
   254                 }
   255                 s.setPiece(t);
   256             }
   257         }
   258     }
   259 
   260     static void initBoard(
   261         Board board, List<String> whites, List<String> blacks, Color turn
   262     ) {
   263         initBoard(board, false);
   264         for (String w : whites) {
   265             assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
   266             w = w.toUpperCase();
   267             char column = w.charAt(1);
   268             int row = (w.charAt(2) - '0');
   269             
   270             Square s = BoardModel.findSquare(board, column, row);
   271             s.setPieceColor(Color.W);
   272             s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
   273         }
   274         for (String w : blacks) {
   275             assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
   276             w = w.toUpperCase();
   277             char column = w.charAt(1);
   278             int row = (w.charAt(2) - '0');
   279             
   280             Square s = BoardModel.findSquare(board, column, row);
   281             s.setPieceColor(Color.B);
   282             s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
   283         }
   284         board.setTurn(turn);
   285     }
   286 
   287     private static void checkRochade(Board b, Square s) {
   288         if (s.getPosition().getX() == 'E') {
   289             int y = s.getPosition().getY();
   290             final Square gRow = BoardModel.findSquare(b, 'G', y);
   291             if (
   292                 BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK 
   293                 &&
   294                 BoardModel.findSquare(b, 'F', y).getPiece() == null
   295                 &&
   296                 gRow.getPiece() == null
   297             ) {
   298                 gRow.setAccessible(true);
   299             }
   300             final Square cRow = BoardModel.findSquare(b, 'C', y);
   301             if (
   302                 BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK 
   303                 &&
   304                 BoardModel.findSquare(b, 'B', y).getPiece() == null
   305                 &&
   306                 BoardModel.findSquare(b, 'D', y).getPiece() == null
   307                 &&
   308                 cRow.getPiece() == null
   309             ) {
   310                 cRow.setAccessible(true);
   311             }
   312         }
   313     }
   314 }