# HG changeset patch # User Jaroslav Tulach # Date 1252617580 -7200 # Node ID 6802034b7a6fcb30f69e87b438f4366fccdd941a # Parent b2af4da1cbbeed363853b854a6769b20302f6508 Support for giving up the game diff -r b2af4da1cbbe -r 6802034b7a6f freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Thu Sep 10 22:48:21 2009 +0200 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Thu Sep 10 23:19:40 2009 +0200 @@ -148,6 +148,10 @@ } WebResource wr = base.path("games").path(id).queryParam("player", user); try { + if (type.equals("resign")) { + wr.queryParam("move", "RESIGN").put(); + return board(id); + } if (type.equals("fence")) { wr.queryParam("move", direction.charAt(0) + column + row).put(); return board(id); diff -r b2af4da1cbbe -r 6802034b7a6f freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Thu Sep 10 22:48:21 2009 +0200 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Thu Sep 10 23:19:40 2009 +0200 @@ -80,6 +80,10 @@ +
+ + +
${doc.game.board}
diff -r b2af4da1cbbe -r 6802034b7a6f freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.properties --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.properties Thu Sep 10 22:48:21 2009 +0200 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.properties Thu Sep 10 23:19:40 2009 +0200 @@ -1,6 +1,7 @@ players={0} vs. {1} PLACE=Place! MOVE=Move! +RESIGN=Resign! H=Horizontal V=Vertical RELOAD=Reload diff -r b2af4da1cbbe -r 6802034b7a6f freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game_cs.properties --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game_cs.properties Thu Sep 10 22:48:21 2009 +0200 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game_cs.properties Thu Sep 10 23:19:40 2009 +0200 @@ -1,6 +1,7 @@ players={0} proti {1} PLACE=Um\u00EDstit MOVE=T\u00E1hnout +RESIGN=Vzd\u00E1t H=Horizont\u00E1ln\u011B V=Vertik\u00E1ln\u011B RELOAD=Obnovit diff -r b2af4da1cbbe -r 6802034b7a6f quoridor/src/main/java/cz/xelfi/quoridor/Board.java --- a/quoridor/src/main/java/cz/xelfi/quoridor/Board.java Thu Sep 10 22:48:21 2009 +0200 +++ b/quoridor/src/main/java/cz/xelfi/quoridor/Board.java Thu Sep 10 23:19:40 2009 +0200 @@ -64,6 +64,8 @@ * @author Jaroslav Tulach */ public final class Board { + /** winner, if any */ + private final Player winner; /** players */ private final List players; /** fences placed on board */ @@ -117,6 +119,7 @@ throw new IllegalStateException (ex.getMessage ()); } this.turn = 0; + this.winner = null; } /** Copy constructor that provides players and fences. @@ -133,6 +136,16 @@ } } this.turn = turn % players.size(); + this.winner = null; + } + + /** Copy constructor for resigning the game */ + private Board(Board previous, int winner) { + this.players = previous.players; + this.turn = winner % players.size(); + this.fences = previous.fences; + this.occupied = previous.occupied; + this.winner = players.get(this.turn); } /** Returns empty board with default starting position. @@ -158,9 +171,12 @@ } /** The player that is supposed to play now. - * @return the player to do next move + * @return the player to do next move, null if the game is over */ public Player getCurrentPlayer() { + if (getWinner() != null) { + return null; + } return players.get(turn); } @@ -169,6 +185,9 @@ * @return the winning player or null */ public Player getWinner() { + if (winner != null) { + return winner; + } for (Player p : players) { if (p.endDirection.reached(p)) { return p; @@ -192,7 +211,11 @@ if (move.direction != null) { return move(getCurrentPlayer(), move.direction); } else { - return fence(getCurrentPlayer(), move.fence); + if (move.fence != null) { + return fence(getCurrentPlayer(), move.fence); + } else { + return new Board(this, turn + 1); + } } } diff -r b2af4da1cbbe -r 6802034b7a6f quoridor/src/main/java/cz/xelfi/quoridor/Move.java --- a/quoridor/src/main/java/cz/xelfi/quoridor/Move.java Thu Sep 10 22:48:21 2009 +0200 +++ b/quoridor/src/main/java/cz/xelfi/quoridor/Move.java Thu Sep 10 23:19:40 2009 +0200 @@ -46,6 +46,10 @@ fence = f; direction = null; } + private Move() { + fence = null; + direction = null; + } /** Moves the player's figure to north */ public static final Move NORTH = new Move(Direction.NORTH); @@ -55,6 +59,8 @@ public static final Move SOUTH = new Move(Direction.SOUTH); /** Moves the player's figure to west */ public static final Move WEST = new Move(Direction.WEST); + /** Allows the player to resign the game */ + public static final Move RESIGN = new Move(); /** Places a fence into given position with specified orientation. * The faces postions are numbered 1-8 and A-H according to following @@ -139,6 +145,10 @@ case 'E': return Move.EAST; case 'W': return Move.WEST; } + case 6: + if ("RESIGN".equals(move)) { + return Move.RESIGN; + } } throw new IllegalPositionException(move); } @@ -152,6 +162,9 @@ } throw new IllegalStateException(); } else { + if (direction == null) { + return "RESIGN"; // NOI18N + } StringBuilder sb = new StringBuilder(); for (Direction d : direction) { sb.append(d.name().charAt(0)); diff -r b2af4da1cbbe -r 6802034b7a6f quoridor/src/test/java/cz/xelfi/quoridor/BoardCase.java --- a/quoridor/src/test/java/cz/xelfi/quoridor/BoardCase.java Thu Sep 10 22:48:21 2009 +0200 +++ b/quoridor/src/test/java/cz/xelfi/quoridor/BoardCase.java Thu Sep 10 23:19:40 2009 +0200 @@ -51,6 +51,32 @@ protected abstract Board apply(Board b, Move move) throws IllegalPositionException; + public void testResignWhite() throws IllegalPositionException { + List list = board.getPlayers(); + assertEquals ("Two", 2, list.size ()); + Board b = board.apply(Move.RESIGN); + assertEquals(b.getPlayers().get(1), b.getWinner()); + try { + b.apply(Move.EAST); + fail("No more moves allowed, the player resigned"); + } catch (IllegalPositionException ex) { + // OK + } + assertNull("No player", b.getCurrentPlayer()); + } + public void testResignBlack() throws IllegalPositionException { + List list = board.getPlayers(); + assertEquals ("Two", 2, list.size ()); + Board b = board.apply(Move.NORTH).apply(Move.RESIGN); + assertEquals(b.getPlayers().get(0), b.getWinner()); + try { + b.apply(Move.EAST); + fail("No more moves allowed, the player resigned"); + } catch (IllegalPositionException ex) { + // OK + } + assertNull("No player", b.getCurrentPlayer()); + } public void testTwoPlayers () { List list = board.getPlayers(); assertEquals ("Two", 2, list.size ()); diff -r b2af4da1cbbe -r 6802034b7a6f quoridor/src/test/java/cz/xelfi/quoridor/MoveTest.java --- a/quoridor/src/test/java/cz/xelfi/quoridor/MoveTest.java Thu Sep 10 22:48:21 2009 +0200 +++ b/quoridor/src/test/java/cz/xelfi/quoridor/MoveTest.java Thu Sep 10 23:19:40 2009 +0200 @@ -28,10 +28,6 @@ import cz.xelfi.quoridor.Fence.Orientation; import cz.xelfi.quoridor.Player.Direction; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; @@ -61,6 +57,10 @@ checkValueOf("W", Move.WEST); } @Test + public void testRegisn() throws Exception { + checkValueOf("RESIGN", Move.RESIGN); + } + @Test public void testJumps() throws Exception { for (Direction d1 : Direction.values()) { for (Direction d2 : Direction.values()) { diff -r b2af4da1cbbe -r 6802034b7a6f webidor/src/test/java/cz/xelfi/quoridor/webidor/FinishedGameTest.java --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/FinishedGameTest.java Thu Sep 10 22:48:21 2009 +0200 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/FinishedGameTest.java Thu Sep 10 23:19:40 2009 +0200 @@ -26,21 +26,11 @@ package cz.xelfi.quoridor.webidor; -import com.sun.jersey.api.client.GenericType; -import com.sun.jersey.api.client.UniformInterfaceException; -import com.sun.jersey.core.header.MediaTypes; import com.sun.jersey.test.framework.JerseyTest; -import cz.xelfi.quoridor.Board; -import cz.xelfi.quoridor.Move; -import cz.xelfi.quoridor.webidor.resources.Games; import java.io.File; -import java.io.FileReader; import java.io.IOException; -import java.util.List; -import java.util.Map; import javax.ws.rs.core.MediaType; import org.junit.Test; -import org.w3c.dom.Document; import static org.junit.Assert.*; /** @@ -103,4 +93,14 @@ assertEquals("BlackWins", GameResult.BLACK_WON, end.getId().getResult()); } + @Test public void testResignAGame() throws Exception { + webResource = webResource.path("api"); + GameId s = webResource.path("games").queryParam("white", "Jarda") + .queryParam("black", "Jirka").post(GameId.class); + + webResource.path("games/" + s.getId()).queryParam("player", "Jarda").queryParam("move", "RESIGN").put(GameId.class); + Game end = webResource.path("games/" + s.getId()).accept(MediaType.TEXT_XML).get(Game.class); + assertEquals("BlackWins", GameResult.BLACK_WON, end.getId().getResult()); + } + }