chess/src/main/java/org/apidesign/html/demo/chess/Rules.java
author Jaroslav Tulach <jtulach@netbeans.org>
Wed, 25 Sep 2013 04:18:47 +0200
branchchess
changeset 53 bc0094a5f88c
parent 51 3f1866fdb2a1
permissions -rw-r--r--
Can now play game against ownself
     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 org.apidesign.html.demo.chess;
    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
   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                     r.getColumns().set(j - 'A', s);
   201                     initialPosition(s, init);
   202                 }
   203             }
   204         } else {
   205             for (Row r : b.getRows()) {
   206                 for (Square square : r.getColumns()) {
   207                     square.setAccessible(false);
   208                     square.setPiece(null);
   209                     square.setPieceColor(null);
   210                     square.setSelected(false);
   211                     initialPosition(square, init);
   212                 }
   213             }
   214         }
   215         b.setPendingMove(null);
   216     }
   217 
   218     private static void initialPosition(Square s, boolean init) {
   219         int row = s.getPosition().getY();
   220         char column = s.getPosition().getX();
   221         s.setPiece(null);
   222         s.setPieceColor(null);
   223         if (init) {
   224             if (row == 2) {
   225                 s.setPiece(BoardModel.PieceType.PAWN);
   226                 s.setPieceColor(Color.W);
   227             } else if (row == 7) {
   228                 s.setPiece(BoardModel.PieceType.PAWN);
   229                 s.setPieceColor(Color.B);
   230             } else if (row == 8 || row == 1) {
   231                 s.setPieceColor(row == 1 ? Color.W : Color.B);
   232                 BoardModel.PieceType t;
   233                 switch (column) {
   234                     case 'A':
   235                     case 'H':
   236                         t = BoardModel.PieceType.ROCK;
   237                         break;
   238                     case 'B':
   239                     case 'G':
   240                         t = BoardModel.PieceType.KNIGHT;
   241                         break;
   242                     case 'C':
   243                     case 'F':
   244                         t = BoardModel.PieceType.BISHOP;
   245                         break;
   246                     case 'D':
   247                         t = BoardModel.PieceType.QUEEN;
   248                         break;
   249                     default:
   250                         t = BoardModel.PieceType.KING;
   251                         break;
   252                 }
   253                 s.setPiece(t);
   254             }
   255         }
   256     }
   257 
   258     static void initBoard(
   259         Board board, List<String> whites, List<String> blacks, Color turn
   260     ) {
   261         initBoard(board, false);
   262         for (String w : whites) {
   263             assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
   264             w = w.toUpperCase();
   265             char column = w.charAt(1);
   266             int row = (w.charAt(2) - '0');
   267             
   268             Square s = BoardModel.findSquare(board, column, row);
   269             s.setPieceColor(Color.W);
   270             s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
   271         }
   272         for (String w : blacks) {
   273             assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
   274             w = w.toUpperCase();
   275             char column = w.charAt(1);
   276             int row = (w.charAt(2) - '0');
   277             
   278             Square s = BoardModel.findSquare(board, column, row);
   279             s.setPieceColor(Color.B);
   280             s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
   281         }
   282         board.setTurn(turn);
   283     }
   284 
   285     private static void checkRochade(Board b, Square s) {
   286         if (s.getPosition().getX() == 'E') {
   287             int y = s.getPosition().getY();
   288             final Square gRow = BoardModel.findSquare(b, 'G', y);
   289             if (
   290                 BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK 
   291                 &&
   292                 BoardModel.findSquare(b, 'F', y).getPiece() == null
   293                 &&
   294                 gRow.getPiece() == null
   295             ) {
   296                 gRow.setAccessible(true);
   297             }
   298             final Square cRow = BoardModel.findSquare(b, 'C', y);
   299             if (
   300                 BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK 
   301                 &&
   302                 BoardModel.findSquare(b, 'B', y).getPiece() == null
   303                 &&
   304                 BoardModel.findSquare(b, 'D', y).getPiece() == null
   305                 &&
   306                 cRow.getPiece() == null
   307             ) {
   308                 cRow.setAccessible(true);
   309             }
   310         }
   311     }
   312 }