# HG changeset patch # User Jaroslav Tulach # Date 1374851665 -7200 # Node ID 1ebd52ae8ccbbd6af6ef1d09eda1827b8589c3ca # Parent ba6946f6b88027fc99e0ba01e9d4dd6502b530fc Show accessible squares when a figure is selected diff -r ba6946f6b880 -r 1ebd52ae8ccb chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java --- a/chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java Fri Jul 26 17:13:08 2013 +0200 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java Fri Jul 26 17:14:25 2013 +0200 @@ -39,19 +39,24 @@ if (previoslySelected == null) { if (data.getPiece() != null && data.getPieceColor() == b.getTurn()) { data.setSelected(true); + Rules.computeAccessible(b, data); } } else { - previoslySelected.setSelected(false); if (data.getPiece() != null && data.getPieceColor() == previoslySelected.getPieceColor()) { previoslySelected.setSelected(false); data.setSelected(true); + Rules.computeAccessible(b, data); return; } - data.setPieceColor(previoslySelected.getPieceColor()); - data.setPiece(previoslySelected.getPiece()); - b.setTurn(b.getTurn() == ColorType.WHITE ? ColorType.BLACK : ColorType.WHITE); - previoslySelected.setPiece(null); - previoslySelected.setPieceColor(null); + if (data.isAccessible()) { + previoslySelected.setSelected(false); + data.setPieceColor(previoslySelected.getPieceColor()); + data.setPiece(previoslySelected.getPiece()); + b.setTurn(b.getTurn() == ColorType.WHITE ? ColorType.BLACK : ColorType.WHITE); + previoslySelected.setPiece(null); + previoslySelected.setPieceColor(null); + Rules.computeAccessible(b, null); + } } } @@ -124,7 +129,8 @@ @Property(name = "color", type = ColorType.class), @Property(name = "x", type = int.class), @Property(name = "y", type = int.class), - @Property(name = "selected", type = boolean.class) + @Property(name = "selected", type = boolean.class), + @Property(name = "accessible", type = boolean.class), }) static class PieceImpl { @ComputedProperty static String pieceEntity( @@ -136,10 +142,15 @@ return piece.computeEntity(pieceColor); } - @ComputedProperty static String squareColor(ColorType color, boolean selected) { + @ComputedProperty static String squareColor( + ColorType color, boolean selected, boolean accessible + ) { if (selected) { return "selected"; } + if (accessible) { + return "accessible"; + } if (color == null) { return ""; diff -r ba6946f6b880 -r 1ebd52ae8ccb chess/src/main/java/org/apidesign/html/demo/chess/Rules.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Rules.java Fri Jul 26 17:14:25 2013 +0200 @@ -0,0 +1,130 @@ +/** + * The MIT License (MIT) + * + * Copyright (C) 2013 Jaroslav Tulach + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.apidesign.html.demo.chess; + +/** Common chess rules. + * + * @author Jaroslav Tulach + */ +class Rules { + static void computeAccessible(Board b, Square s) { + for (Row r : b.getRows()) { + for (Square ts : r.getColumns()) { + ts.setAccessible(false); + } + } + if (s == null) { + return; + } + + switch (s.getPiece()) { + case BISHOP: + moveBishop(b, s); + break; + case KING: + computeAccessible(b, s, 1, 1, 1); + computeAccessible(b, s, 1, -1, 1); + computeAccessible(b, s, -1, -1, 1); + computeAccessible(b, s, -1, 1, 1); + computeAccessible(b, s, 1, 0, 1); + computeAccessible(b, s, 0, -1, 1); + computeAccessible(b, s, 0, 1, 1); + computeAccessible(b, s, -1, 0, 1); + break; + case ROCK: + moveRock(b, s); + break; + case QUEEN: + moveRock(b, s); + moveBishop(b, s); + break; + case KNIGHT: + computeAccessible(b, s, 2, 1, 1); + computeAccessible(b, s, 2, -1, 1); + computeAccessible(b, s, -2, -1, 1); + computeAccessible(b, s, -2, 1, 1); + computeAccessible(b, s, 1, 2, 1); + computeAccessible(b, s, -1, 2, 1); + computeAccessible(b, s, -1, -2, 1); + computeAccessible(b, s, 1, -2, 1); + break; + case PAWN: + pawns(b, s); + break; + } + } + + private static void moveRock(Board b, Square s) { + computeAccessible(b, s, 1, 0, 8); + computeAccessible(b, s, 0, -1, 8); + computeAccessible(b, s, -1, 0, 8); + computeAccessible(b, s, 0, 1, 8); + } + + private static void moveBishop(Board b, Square s) { + computeAccessible(b, s, 1, 1, 8); + computeAccessible(b, s, 1, -1, 8); + computeAccessible(b, s, -1, -1, 8); + computeAccessible(b, s, -1, 1, 8); + } + + private static void computeAccessible( + Board b, Square s, int dx, int dy, + int limit + ) { + int x = s.getX(); + int y = s.getY(); + + while (limit-- > 0) { + x += dx; + y += dy; + Square next = BoardModel.findSquare(b, (char)x, y); + if (next == null) { + break; + } + if (next.getPieceColor() == s.getPieceColor()) { + break; + } + next.setAccessible(true); + if (next.getPieceColor() != null) { + break; + } + } + } + + private static void pawns(Board b, Square s) { + final boolean white = s.getPieceColor() == BoardModel.ColorType.WHITE; + int dy = white ? 1 : -1; + Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy); + if (step != null && step.getPiece() == null) { + step.setAccessible(true); + if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) { + Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy); + if (nextSTep != null && step.getPiece() == null) { + nextSTep.setAccessible(true); + } + } + } + } +} diff -r ba6946f6b880 -r 1ebd52ae8ccb chess/src/main/webapp/pages/css/chess.css --- a/chess/src/main/webapp/pages/css/chess.css Fri Jul 26 17:13:08 2013 +0200 +++ b/chess/src/main/webapp/pages/css/chess.css Fri Jul 26 17:14:25 2013 +0200 @@ -55,6 +55,9 @@ table.board td.selected { background-color: #B000B0; } +table.board td.accessible { + background-color: #00B0B0; +} .figure { cursor: pointer; } \ No newline at end of file diff -r ba6946f6b880 -r 1ebd52ae8ccb chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java --- a/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java Fri Jul 26 17:13:08 2013 +0200 +++ b/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java Fri Jul 26 17:14:25 2013 +0200 @@ -24,6 +24,7 @@ package org.apidesign.html.demo.chess; import org.apidesign.html.demo.chess.BoardModel.ColorType; +import org.apidesign.html.demo.chess.BoardModel.PieceType; import static org.testng.Assert.*; import org.testng.annotations.Test; @@ -95,4 +96,28 @@ } + @Test public void knightMustMoveToF3() { + Board b = BoardModel.createBoard(); + Square g1 = BoardModel.findSquare(b, 'G', 1); + BoardModel.selected(b, g1); + + Square f3 = BoardModel.findSquare(b, 'F', 3); + assertTrue(f3.isAccessible(), "This is a field where knight can move"); + + Square g3 = BoardModel.findSquare(b, 'G', 3); + assertFalse(g3.isAccessible(), "Not a place for knight"); + + Square e2 = BoardModel.findSquare(b, 'E', 2); + assertFalse(e2.isAccessible(), "Not a place either, occupied"); + + BoardModel.selected(b, g3); + + assertNull(g3.getPiece(), "No figure was moved"); + assertTrue(g1.isSelected(), "Original square still selected"); + + BoardModel.selected(b, f3); + + assertEquals(f3.getPiece(), PieceType.KNIGHT, "Moved"); + assertFalse(g3.isSelected(), "No longer selected"); + } }