quoridor/src/main/java/cz/xelfi/quoridor/Move.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 14 Sep 2010 08:56:13 +0200
changeset 264 d60370059c3c
parent 253 ee02205edf13
permissions -rw-r--r--
Changing headers to GPLv3
jtulach@3
     1
/*
jaroslav@264
     2
 * Quoridor server and related libraries
jaroslav@264
     3
 * Copyright (C) 2009-2010 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jtulach@8
     4
 *
jaroslav@264
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@264
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@264
     7
 * the Free Software Foundation, either version 3 of the License.
jtulach@8
     8
 *
jaroslav@264
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@264
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@264
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@264
    12
 * GNU General Public License for more details.
jtulach@8
    13
 *
jaroslav@264
    14
 * You should have received a copy of the GNU General Public License
jaroslav@264
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@264
    16
 * If not, see http://www.gnu.org/licenses/.
jtulach@3
    17
 */
jtulach@3
    18
package cz.xelfi.quoridor;
jtulach@3
    19
jtulach@15
    20
import cz.xelfi.quoridor.Player.Direction;
jaroslav@253
    21
import java.util.ArrayList;
jtulach@30
    22
import java.util.Arrays;
jaroslav@253
    23
import java.util.List;
jtulach@3
    24
jtulach@16
    25
/** Encapsulates one possible move that can be applied to existing {@link Board}
jtulach@16
    26
 * by calling its {@link Board#apply} method.
jtulach@3
    27
 *
jtulach@3
    28
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jtulach@3
    29
 */
jtulach@3
    30
public final class Move extends Object {
jtulach@3
    31
    final Direction[] direction;
jtulach@3
    32
    final Fence fence;
jtulach@3
    33
jtulach@3
    34
    private Move(Direction... arr) {
jtulach@3
    35
        direction = arr;
jtulach@3
    36
        fence = null;
jtulach@3
    37
    }
jtulach@3
    38
    private Move(Fence f) {
jtulach@3
    39
        fence = f;
jtulach@3
    40
        direction = null;
jtulach@3
    41
    }
jtulach@75
    42
    private Move() {
jtulach@75
    43
        fence = null;
jtulach@75
    44
        direction = null;
jtulach@75
    45
    }
jtulach@3
    46
jtulach@4
    47
    /** Moves the player's figure to north */
jtulach@3
    48
    public static final Move NORTH = new Move(Direction.NORTH);
jtulach@4
    49
    /** Moves the player's figure to east */
jtulach@3
    50
    public static final Move EAST = new Move(Direction.EAST);
jtulach@4
    51
    /** Moves the player's figure to south */
jtulach@3
    52
    public static final Move SOUTH = new Move(Direction.SOUTH);
jtulach@4
    53
    /** Moves the player's figure to west */
jtulach@3
    54
    public static final Move WEST = new Move(Direction.WEST);
jtulach@75
    55
    /** Allows the player to resign the game */
jtulach@75
    56
    public static final Move RESIGN = new Move();
jtulach@3
    57
jtulach@4
    58
    /** Places a fence into given position with specified orientation.
jtulach@4
    59
     * The faces postions are numbered 1-8 and A-H according to following
jtulach@4
    60
     * graph: <pre>
jtulach@4
    61
            H   G   F   E   D   C   B   A
jtulach@4
    62
            |   |   |   |   |   |   |   |
jtulach@4
    63
        +-----------------------------------+
jtulach@4
    64
        |                                   |
jtulach@4
    65
     1--|   +   +   +   +   +   +   +   +   |--1
jtulach@4
    66
        |                                   |
jtulach@4
    67
     2--|   +   +   +   +   +   +   +   +   |--2
jtulach@4
    68
        |                                   |
jtulach@4
    69
     3--|   +   +   +   +   +   +   +   +   |--3
jtulach@4
    70
        |                                   |
jtulach@4
    71
     4--|   +   +   +   +   +   +   +   +   |--4
jtulach@4
    72
[E]     |                                   |     [W]
jtulach@4
    73
     5--|   +   +   +   +   +   +   +   +   |--5
jtulach@4
    74
        |                                   |
jtulach@4
    75
     6--|   +   +   +   +   +   +   +   +   |--6
jtulach@4
    76
        |                                   |
jtulach@4
    77
     7--|   +   +   +   +   +   +   +   +   |--7
jtulach@4
    78
        |                                   |
jtulach@4
    79
     8--|   +   +   +   +   +   +   +   +   |--8
jtulach@4
    80
        |                                   |
jtulach@4
    81
        +-----------------------------------+
jtulach@4
    82
            |   |   |   |   |   |   |   |
jtulach@4
    83
            H   G   F   E   D   C   B   A
jtulach@4
    84
     * </pre>
jtulach@4
    85
     *
jtulach@4
    86
     *
jtulach@21
    87
     * @param column x-coordinate of the middle of the fence from 'A' to 'B'
jtulach@21
    88
     * @param row y-coordinate of the middle of the fence
jtulach@4
    89
     * @param orientation place the fence horizontally or vertically
jtulach@4
    90
     * @return the new board
jtulach@4
    91
     * @exception IllegalPositionException if the move is not possible
jtulach@4
    92
     */
jtulach@21
    93
    public static Move fence(char column, int row, Fence.Orientation orientation) throws IllegalPositionException {
jtulach@21
    94
        if (column < 'A' || 'H' < column) {
jtulach@3
    95
            throw new IllegalPositionException ("x coordinate has to be from A to H"); // NOI18N
jtulach@3
    96
        }
jtulach@31
    97
        if (row < 1 || row > 8) {
jtulach@31
    98
            throw new IllegalPositionException ("y coordinate has to be from 1 to 8"); // NOI18N
jtulach@31
    99
        }
jtulach@21
   100
        return new Move(new Fence ((column - 'A') * 2 + 1, row * 2 - 1, orientation));
jtulach@3
   101
    }
jtulach@3
   102
jtulach@4
   103
    /** Moves the player in given directions. After applying
jtulach@4
   104
     * the first direction, the pawn has to get on a position
jtulach@4
   105
     * that is occupied by other player's pawn.
jtulach@4
   106
     *
jtulach@4
   107
     * @param where one or two directions saying where
jtulach@4
   108
     * @return the new board
jtulach@4
   109
     * @exception IllegalPositionException if the move is not possible
jtulach@4
   110
     */
jtulach@3
   111
    public static Move jump(Direction first, Direction second) {
jtulach@3
   112
        return new Move(first, second);
jtulach@3
   113
    }
jtulach@30
   114
jtulach@34
   115
    /** Converts the value of the move string into valid move, if possible.
jtulach@34
   116
     *
jtulach@34
   117
     * @param move the string in format used by {@link #toString()}
jtulach@34
   118
     * @return the move which's toString() returns the move parameter
jtulach@34
   119
     * @throws IllegalPositionException raised in case the parameter does not
jtulach@34
   120
     *      represent a valid move
jtulach@34
   121
     */
jtulach@34
   122
    public static Move valueOf(String move) throws IllegalPositionException {
jtulach@34
   123
        switch (move.length()) {
jtulach@34
   124
            case 3:
jtulach@34
   125
            if (move.startsWith("H")) {
jtulach@34
   126
                return Move.fence(move.charAt(1), move.charAt(2) - '0', Fence.Orientation.HORIZONTAL);
jtulach@34
   127
            }
jtulach@34
   128
            if (move.startsWith("V")) {
jtulach@34
   129
                return Move.fence(move.charAt(1), move.charAt(2) - '0', Fence.Orientation.VERTICAL);
jtulach@34
   130
            }
jtulach@34
   131
            break;
jtulach@34
   132
            case 2:
jtulach@34
   133
                return Move.jump(Direction.valueOf(move.charAt(0)), Direction.valueOf(move.charAt(1)));
jtulach@34
   134
            case 1:
jtulach@34
   135
                switch (move.charAt(0)) {
jtulach@34
   136
                    case 'N': return Move.NORTH;
jtulach@34
   137
                    case 'S': return Move.SOUTH;
jtulach@34
   138
                    case 'E': return Move.EAST;
jtulach@34
   139
                    case 'W': return Move.WEST;
jtulach@34
   140
                }
jtulach@75
   141
            case 6:
jtulach@75
   142
                if ("RESIGN".equals(move)) {
jtulach@75
   143
                    return Move.RESIGN;
jtulach@75
   144
                }
jtulach@34
   145
        }
jtulach@34
   146
        throw new IllegalPositionException(move);
jtulach@34
   147
    }
jtulach@34
   148
jtulach@30
   149
    @Override
jtulach@30
   150
    public String toString() {
jtulach@30
   151
        if (fence != null) {
jtulach@34
   152
            switch (fence.getOrientation()) {
jtulach@34
   153
                case HORIZONTAL: return "H" + fence.getColumn() + fence.getRow();
jtulach@34
   154
                case VERTICAL: return "V" + fence.getColumn() + fence.getRow();
jtulach@34
   155
            }
jtulach@34
   156
            throw new IllegalStateException();
jtulach@30
   157
        } else {
jtulach@75
   158
            if (direction == null) {
jtulach@75
   159
                return "RESIGN"; // NOI18N
jtulach@75
   160
            }
jtulach@34
   161
            StringBuilder sb = new StringBuilder();
jtulach@34
   162
            for (Direction d : direction) {
jtulach@34
   163
                sb.append(d.name().charAt(0));
jtulach@34
   164
            }
jtulach@34
   165
            return sb.toString();
jtulach@30
   166
        }
jtulach@30
   167
    }
jtulach@30
   168
jtulach@30
   169
    @Override
jtulach@30
   170
    public boolean equals(Object obj) {
jtulach@30
   171
        if (obj == null) {
jtulach@30
   172
            return false;
jtulach@30
   173
        }
jtulach@30
   174
        if (getClass() != obj.getClass()) {
jtulach@30
   175
            return false;
jtulach@30
   176
        }
jtulach@30
   177
        final Move other = (Move) obj;
jtulach@30
   178
        if (!Arrays.deepEquals(this.direction, other.direction)) {
jtulach@30
   179
            return false;
jtulach@30
   180
        }
jtulach@30
   181
        if (this.fence != other.fence && (this.fence == null || !this.fence.equals(other.fence))) {
jtulach@30
   182
            return false;
jtulach@30
   183
        }
jtulach@30
   184
        return true;
jtulach@30
   185
    }
jtulach@30
   186
jtulach@30
   187
    @Override
jtulach@30
   188
    public int hashCode() {
jtulach@30
   189
        int hash = 3;
jtulach@30
   190
        hash = 47 * hash + Arrays.deepHashCode(this.direction);
jtulach@30
   191
        hash = 47 * hash + (this.fence != null ? this.fence.hashCode() : 0);
jtulach@30
   192
        return hash;
jtulach@30
   193
    }
jtulach@30
   194
jaroslav@178
   195
    public Move getMirrorMove(){
jaroslav@178
   196
        if(fence != null){
jaroslav@178
   197
            return new Move(new Fence(16-fence.getX(), fence.getY(), fence.getOrientation()));
jaroslav@178
   198
        }
jaroslav@178
   199
        if(direction == null)
jaroslav@178
   200
            return new Move();
jaroslav@178
   201
        int dirSize = direction.length;
jaroslav@178
   202
        Direction[] mirrorDirection = new Direction[dirSize];
jaroslav@178
   203
        for(int i = 0; i < dirSize; i++){
jaroslav@178
   204
            if(direction[i].equals(Direction.NORTH))
jaroslav@178
   205
                mirrorDirection[i] = Direction.NORTH;
jaroslav@178
   206
            else if(direction[i].equals(Direction.SOUTH))
jaroslav@178
   207
                mirrorDirection[i] = Direction.SOUTH;
jaroslav@178
   208
            else if(direction[i].equals(Direction.EAST))
jaroslav@178
   209
                mirrorDirection[i] = Direction.WEST;
jaroslav@178
   210
            else if(direction[i].equals(Direction.WEST))
jaroslav@178
   211
                mirrorDirection[i] = Direction.EAST;
jaroslav@178
   212
        }
jaroslav@178
   213
        return new Move(mirrorDirection);
jaroslav@178
   214
    }
jaroslav@178
   215
jtulach@30
   216
jaroslav@253
   217
    static List<Move> allMovements() {
jaroslav@253
   218
        List<Move> arr = new ArrayList<Move>();
jaroslav@253
   219
        
jaroslav@253
   220
        arr.add(Move.EAST);
jaroslav@253
   221
        arr.add(Move.WEST);
jaroslav@253
   222
        arr.add(Move.NORTH);
jaroslav@253
   223
        arr.add(Move.SOUTH);
jaroslav@253
   224
        
jaroslav@253
   225
        for (Direction d1 : Player.Direction.values()) {
jaroslav@253
   226
            for (Direction d2 : Player.Direction.values()) {
jaroslav@253
   227
                arr.add(Move.jump(d1, d2));
jaroslav@253
   228
            }
jaroslav@253
   229
        }
jaroslav@253
   230
        return arr;
jaroslav@253
   231
    }
jtulach@3
   232
}