1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/Rules.java Tue Sep 24 22:20:24 2013 +0200
1.3 @@ -0,0 +1,314 @@
1.4 +/**
1.5 + * The MIT License (MIT)
1.6 + *
1.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
1.8 + *
1.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
1.10 + * of this software and associated documentation files (the "Software"), to deal
1.11 + * in the Software without restriction, including without limitation the rights
1.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1.13 + * copies of the Software, and to permit persons to whom the Software is
1.14 + * furnished to do so, subject to the following conditions:
1.15 + *
1.16 + * The above copyright notice and this permission notice shall be included in
1.17 + * all copies or substantial portions of the Software.
1.18 + *
1.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1.25 + * THE SOFTWARE.
1.26 + */
1.27 +package com.oracle.chess.client.htmljava;
1.28 +
1.29 +import java.util.ArrayList;
1.30 +import java.util.List;
1.31 +
1.32 +/** Common chess rules.
1.33 + *
1.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
1.35 + */
1.36 +class Rules {
1.37 + static void computeAccessible(Board b, Square s) {
1.38 + for (Row r : b.getRows()) {
1.39 + for (Square ts : r.getColumns()) {
1.40 + ts.setAccessible(false);
1.41 + }
1.42 + }
1.43 + if (s == null) {
1.44 + return;
1.45 + }
1.46 +
1.47 + switch (s.getPiece()) {
1.48 + case BISHOP:
1.49 + moveBishop(b, s);
1.50 + break;
1.51 + case KING:
1.52 + computeAccessible(b, s, 1, 1, 1);
1.53 + computeAccessible(b, s, 1, -1, 1);
1.54 + computeAccessible(b, s, -1, -1, 1);
1.55 + computeAccessible(b, s, -1, 1, 1);
1.56 + computeAccessible(b, s, 1, 0, 1);
1.57 + computeAccessible(b, s, 0, -1, 1);
1.58 + computeAccessible(b, s, 0, 1, 1);
1.59 + computeAccessible(b, s, -1, 0, 1);
1.60 + checkRochade(b, s);
1.61 + break;
1.62 + case ROCK:
1.63 + moveRock(b, s);
1.64 + break;
1.65 + case QUEEN:
1.66 + moveRock(b, s);
1.67 + moveBishop(b, s);
1.68 + break;
1.69 + case KNIGHT:
1.70 + computeAccessible(b, s, 2, 1, 1);
1.71 + computeAccessible(b, s, 2, -1, 1);
1.72 + computeAccessible(b, s, -2, -1, 1);
1.73 + computeAccessible(b, s, -2, 1, 1);
1.74 + computeAccessible(b, s, 1, 2, 1);
1.75 + computeAccessible(b, s, -1, 2, 1);
1.76 + computeAccessible(b, s, -1, -2, 1);
1.77 + computeAccessible(b, s, 1, -2, 1);
1.78 + break;
1.79 + case PAWN:
1.80 + pawns(b, s);
1.81 + break;
1.82 + }
1.83 + }
1.84 +
1.85 + private static void moveRock(Board b, Square s) {
1.86 + computeAccessible(b, s, 1, 0, 8);
1.87 + computeAccessible(b, s, 0, -1, 8);
1.88 + computeAccessible(b, s, -1, 0, 8);
1.89 + computeAccessible(b, s, 0, 1, 8);
1.90 + }
1.91 +
1.92 + private static void moveBishop(Board b, Square s) {
1.93 + computeAccessible(b, s, 1, 1, 8);
1.94 + computeAccessible(b, s, 1, -1, 8);
1.95 + computeAccessible(b, s, -1, -1, 8);
1.96 + computeAccessible(b, s, -1, 1, 8);
1.97 + }
1.98 +
1.99 + private static void computeAccessible(
1.100 + Board b, Square s, int dx, int dy,
1.101 + int limit
1.102 + ) {
1.103 + int x = s.getX();
1.104 + int y = s.getY();
1.105 +
1.106 + while (limit-- > 0) {
1.107 + x += dx;
1.108 + y += dy;
1.109 + Square next = BoardModel.findSquare(b, (char)x, y);
1.110 + if (next == null) {
1.111 + break;
1.112 + }
1.113 + if (next.getPieceColor() == s.getPieceColor()) {
1.114 + break;
1.115 + }
1.116 + next.setAccessible(true);
1.117 + if (next.getPieceColor() != null) {
1.118 + break;
1.119 + }
1.120 + }
1.121 + }
1.122 +
1.123 + private static void pawns(Board b, Square s) {
1.124 + final boolean white = s.getPieceColor() == Color.W;
1.125 + int dy = white ? 1 : -1;
1.126 + Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
1.127 + if (step != null && step.getPiece() == null) {
1.128 + step.setAccessible(true);
1.129 + if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
1.130 + Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
1.131 + if (nextSTep != null && step.getPiece() == null && nextSTep.getPiece() == null) {
1.132 + nextSTep.setAccessible(true);
1.133 + }
1.134 + }
1.135 + }
1.136 + Color opposite = white ? Color.B : Color.W;
1.137 + Square takeLeft = BoardModel.findSquare(b, (char)(s.getX() - 1), s.getY() + dy);
1.138 + if (takeLeft != null && takeLeft.getPieceColor() == opposite) {
1.139 + takeLeft.setAccessible(true);
1.140 + }
1.141 + Square takeRight = BoardModel.findSquare(b, (char)(s.getX() + 1), s.getY() + dy);
1.142 + if (takeRight != null && takeRight.getPieceColor() == opposite) {
1.143 + takeRight.setAccessible(true);
1.144 + }
1.145 + if ((white && s.getY() == 5) || (!white && s.getY() == 4)) {
1.146 + int enPassantFrom = white ? 7 : 2;
1.147 + int enPassantTo = white ? 5 : 4;
1.148 + if (!b.getMoves().isEmpty()) {
1.149 + Move last = b.getMoves().get(b.getMoves().size() - 1);
1.150 + if (
1.151 + last.getPiece() == BoardModel.PieceType.PAWN &&
1.152 + last.getFrom().getY() == enPassantFrom &&
1.153 + last.getTo().getY() == enPassantTo
1.154 + ) {
1.155 + if (takeLeft != null && last.getFrom().getX() == s.getX() - 1) {
1.156 + takeLeft.setAccessible(true);
1.157 + }
1.158 + if (takeRight != null && last.getFrom().getX() == s.getX() + 1) {
1.159 + takeRight.setAccessible(true);
1.160 + }
1.161 + }
1.162 + }
1.163 + }
1.164 + }
1.165 +
1.166 + static Board createBoard() {
1.167 + Board b = new Board();
1.168 + initBoardField(b);
1.169 + initBoard(b);
1.170 + return b;
1.171 + }
1.172 +
1.173 + private static void initBoardField(Board b) {
1.174 + List<Row> addRows = new ArrayList<>(8);
1.175 + for (int i = 8; i > 0; i--) {
1.176 + Square[] arr = new Square[8];
1.177 + for (char j = 'A'; j <= 'H'; j++) {
1.178 + arr[j - 'A'] = new Square(
1.179 + new Position(j, i),
1.180 + (i + j) % 2 == 1 ? Color.W : Color.B,
1.181 + null, null, // figure
1.182 + false, false, false
1.183 + );
1.184 + }
1.185 + addRows.add(new Row(arr));
1.186 + }
1.187 + b.getRows().addAll(addRows);
1.188 + }
1.189 +
1.190 + static void initBoard(Board b) {
1.191 + initBoard(b, true);
1.192 + }
1.193 + private static void initBoard(Board b, boolean init) {
1.194 + if (init) {
1.195 + b.setTurn(Color.W);
1.196 + }
1.197 + if (b.getRows().isEmpty()) {
1.198 + for (int i = 8; i > 0; i--) {
1.199 + Row r = b.getRows().get(8 - i);
1.200 + for (char j = 'A'; j <= 'H'; j++) {
1.201 + Square s = r.getColumns().get(j - 'A');
1.202 + s.setAccessible(false);
1.203 + s.setPending(false);
1.204 + r.getColumns().set(j - 'A', s);
1.205 + initialPosition(s, init);
1.206 + }
1.207 + }
1.208 + } else {
1.209 + for (Row r : b.getRows()) {
1.210 + for (Square square : r.getColumns()) {
1.211 + square.setAccessible(false);
1.212 + square.setPending(false);
1.213 + square.setPiece(null);
1.214 + square.setPieceColor(null);
1.215 + square.setSelected(false);
1.216 + initialPosition(square, init);
1.217 + }
1.218 + }
1.219 + }
1.220 + b.setPendingMove(null);
1.221 + }
1.222 +
1.223 + private static void initialPosition(Square s, boolean init) {
1.224 + int row = s.getPosition().getY();
1.225 + char column = s.getPosition().getX();
1.226 + s.setPiece(null);
1.227 + s.setPieceColor(null);
1.228 + if (init) {
1.229 + if (row == 2) {
1.230 + s.setPiece(BoardModel.PieceType.PAWN);
1.231 + s.setPieceColor(Color.W);
1.232 + } else if (row == 7) {
1.233 + s.setPiece(BoardModel.PieceType.PAWN);
1.234 + s.setPieceColor(Color.B);
1.235 + } else if (row == 8 || row == 1) {
1.236 + s.setPieceColor(row == 1 ? Color.W : Color.B);
1.237 + BoardModel.PieceType t;
1.238 + switch (column) {
1.239 + case 'A':
1.240 + case 'H':
1.241 + t = BoardModel.PieceType.ROCK;
1.242 + break;
1.243 + case 'B':
1.244 + case 'G':
1.245 + t = BoardModel.PieceType.KNIGHT;
1.246 + break;
1.247 + case 'C':
1.248 + case 'F':
1.249 + t = BoardModel.PieceType.BISHOP;
1.250 + break;
1.251 + case 'D':
1.252 + t = BoardModel.PieceType.QUEEN;
1.253 + break;
1.254 + default:
1.255 + t = BoardModel.PieceType.KING;
1.256 + break;
1.257 + }
1.258 + s.setPiece(t);
1.259 + }
1.260 + }
1.261 + }
1.262 +
1.263 + static void initBoard(
1.264 + Board board, List<String> whites, List<String> blacks, Color turn
1.265 + ) {
1.266 + initBoard(board, false);
1.267 + for (String w : whites) {
1.268 + assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
1.269 + w = w.toUpperCase();
1.270 + char column = w.charAt(1);
1.271 + int row = (w.charAt(2) - '0');
1.272 +
1.273 + Square s = BoardModel.findSquare(board, column, row);
1.274 + s.setPieceColor(Color.W);
1.275 + s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
1.276 + }
1.277 + for (String w : blacks) {
1.278 + assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
1.279 + w = w.toUpperCase();
1.280 + char column = w.charAt(1);
1.281 + int row = (w.charAt(2) - '0');
1.282 +
1.283 + Square s = BoardModel.findSquare(board, column, row);
1.284 + s.setPieceColor(Color.B);
1.285 + s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
1.286 + }
1.287 + board.setTurn(turn);
1.288 + }
1.289 +
1.290 + private static void checkRochade(Board b, Square s) {
1.291 + if (s.getPosition().getX() == 'E') {
1.292 + int y = s.getPosition().getY();
1.293 + final Square gRow = BoardModel.findSquare(b, 'G', y);
1.294 + if (
1.295 + BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK
1.296 + &&
1.297 + BoardModel.findSquare(b, 'F', y).getPiece() == null
1.298 + &&
1.299 + gRow.getPiece() == null
1.300 + ) {
1.301 + gRow.setAccessible(true);
1.302 + }
1.303 + final Square cRow = BoardModel.findSquare(b, 'C', y);
1.304 + if (
1.305 + BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK
1.306 + &&
1.307 + BoardModel.findSquare(b, 'B', y).getPiece() == null
1.308 + &&
1.309 + BoardModel.findSquare(b, 'D', y).getPiece() == null
1.310 + &&
1.311 + cRow.getPiece() == null
1.312 + ) {
1.313 + cRow.setAccessible(true);
1.314 + }
1.315 + }
1.316 + }
1.317 +}