You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

658 lines
24 KiB

  1. /**
  2. * @file Board.java
  3. *
  4. * @author
  5. * Anastasia Foti AEM:8959
  6. * <anastaskf@ece.auth.gr>
  7. *
  8. * @author
  9. * Christos Choutouridis AEM:8997
  10. * <cchoutou@ece.auth.gr>
  11. */
  12. package host.labyrinth;
  13. import java.util.ArrayList;
  14. import java.util.function.IntFunction;
  15. /**
  16. * @brief
  17. * This class is the representation of the games's board
  18. *
  19. * The board is the square arrangement of the tiles. This class is also
  20. * the owner of the tile and supply objects.
  21. */
  22. class Board {
  23. /** @name Constructors */
  24. /** @{ */
  25. /**
  26. * The empty constructor for default initialization
  27. */
  28. Board() {
  29. this.N = 0;
  30. this.S = 0;
  31. this.W = 0;
  32. tiles = null;
  33. supplies = null;
  34. walls = new ArrayList<Edge>();
  35. moves = new int[Const.numOfPlayers][Player.MOVE_DATA_SIZE];
  36. playerCount =0;
  37. }
  38. /**
  39. * The main constructor for the application
  40. * @param N The size of each edge of the board
  41. * @param S The number of supplies on the board
  42. */
  43. Board(int N, int S) {
  44. assert (N%2 != 0) : "Board's size has to be an odd number.";
  45. assert (S <= (N*N-2)) : "At least 2 tiles has to be without supplies.";
  46. this.N = Session.boardSize = N;
  47. this.S = S;
  48. this.W = 0;
  49. tiles = new Tile[N*N];
  50. supplies = new Supply[S];
  51. walls = new ArrayList<Edge>();
  52. moves = new int[Const.numOfPlayers][Player.MOVE_DATA_SIZE];
  53. playerCount =0;
  54. }
  55. /**
  56. * Deep copy constructor
  57. * @param b The board to copy
  58. *
  59. * @note
  60. * The lack of value semantics in java is (in author's opinion) one of the greatest
  61. * weakness of the language and one of the reasons why it will never be a language
  62. * to care about. To quote Alexander Stepanof's words in "elements of programming" section 1.5:
  63. * "Assignment is a procedure that takes two objects of the same type and makes the first
  64. * object equal to the second without modifying the second".
  65. * In this class we try to cope with this situation knowing that we can not do anything about
  66. * assignment operator. We just add value semantics to the copy constructor and go on with our lifes...
  67. */
  68. Board(Board b) {
  69. // Copy primitives
  70. this.N = b.N;
  71. this.S = b.S;
  72. this.W = b.W;
  73. tiles = new Tile[b.tiles.length];
  74. supplies = new Supply[b.supplies.length];
  75. walls = new ArrayList<Edge>();
  76. moves = new int[Const.numOfPlayers][Player.MOVE_DATA_SIZE];
  77. playerCount =b.playerCount;
  78. // clone moves array of array of primitives
  79. for (int i=0 ; i<b.moves.length ; ++i)
  80. this.moves[i] = b.moves[i].clone();
  81. // Clone arrays of objects
  82. for (int i=0 ; i<b.tiles.length ; ++i)
  83. this.tiles[i] = new Tile(b.tiles[i]);
  84. for (int i=0 ; i<b.supplies.length ; ++i)
  85. this.supplies[i] = new Supply(b.supplies[i]);
  86. // clone vectors
  87. for (Edge it: b.walls)
  88. this.walls.add(new Edge(it));
  89. }
  90. /** @} */
  91. /** @name Board's main application interface */
  92. /** @{ */
  93. /**
  94. * Creates the board with all the requested walls and supplies.
  95. *
  96. * @param theseusTile
  97. * @param minotaurTile
  98. */
  99. void createBoard(int theseusTile, int minotaurTile) {
  100. createTiles();
  101. createSupplies(theseusTile, minotaurTile);
  102. }
  103. /**
  104. * Returns a 2-D array with the string representation of the board.
  105. *
  106. * The rows of the array represent the Y-coordinate and the columns the X-coordinate.
  107. * The only difference is that between each row there is an extra row with the possible
  108. * walls. This way the number of rows of the returning array are 2N+1 and the number of
  109. * columns N+1.\n
  110. * So each tile of the board is represented by 3 strings. One for the north wall, one for
  111. * the body and one for the south wall.
  112. *
  113. * @param theseusTile The current Theseus tile
  114. * @param minotaurTile The current Minotaur tile
  115. * @return The string representation of the board
  116. */
  117. String[][] getStringRepresentation(int theseusTile, int minotaurTile) {
  118. String[][] frame = new String[2*N+1][N];
  119. for (int row=0 ; row<N ; ++row) {
  120. int col;
  121. for (col =0 ; col<N-1 ; ++col)
  122. renderTile(frame, row, col, theseusTile, minotaurTile);
  123. renderSentinelTile(frame, row, col, theseusTile, minotaurTile);
  124. }
  125. return frame;
  126. }
  127. /**
  128. * Print board utility.
  129. * @param sBoard Reference to string representation of the board to print.
  130. *
  131. * @note
  132. * As the lower row addresses of the string representation of the board contain
  133. * the south rows, in order to view the board correctly we have to print the rows
  134. * in the opposite order.
  135. */
  136. void printBoard (String[][] sBoard) {
  137. for (int i=sBoard.length-1 ; i>=0 ; --i) {
  138. for (String it : sBoard[i])
  139. System.out.print(it);
  140. System.out.println();
  141. }
  142. }
  143. /**
  144. * Predicate to check if a direction is Walkable.
  145. *
  146. * A `walkable` direction is a tile direction where:
  147. * <ul>
  148. * <li>The wall is not the DOWN wall from tile (0, 0).
  149. * <li>There is not already a wall in the desired direction. (Implies no sentinel tile).
  150. * </ul>
  151. *
  152. * @param tileId The starting tileId.
  153. * @param direction The desired direction.
  154. * @return True if it is walkable.
  155. */
  156. boolean isWalkable(int tileId, int direction) {
  157. return !tiles[tileId].hasWall(direction)
  158. && !(tileId == 0 && direction == Direction.DOWN);
  159. }
  160. /**
  161. * Predicate to check if a direction is Walkable.
  162. *
  163. * A `walkable` direction is a tile direction where:
  164. * <ul>
  165. * <li>The wall is not the DOWN wall from tile (0, 0).
  166. * <li>There is not already a wall in the desired direction. (Implies no sentinel tile).
  167. * </ul>
  168. *
  169. * @param row Row position of the starting tile.
  170. * @param col Column position of the starting tile.
  171. * @param direction The desired direction.
  172. * @return True if it is walkable.
  173. */
  174. boolean isWalkable(int row, int col, int direction) {
  175. return !tiles[Position.toID(row, col)].hasWall(direction)
  176. && !(Position.toID(row, col) == 0 && direction == Direction.DOWN);
  177. }
  178. /**
  179. * Utility function to check if there is a supply on the tile or not
  180. * @param tileId The tile to check
  181. * @return Yes/no
  182. */
  183. boolean hasSupply (int tileId) {
  184. return (Const.noSupply != tiles[tileId].hasSupply(supplies)) ? true : false;
  185. }
  186. /**
  187. * Try to pick supply from a tile. If succeed it also erases the
  188. * supply from the board.
  189. *
  190. * @param tileId The tile to check
  191. * @return The id of supply.
  192. * @arg Const.noSupply if there is none
  193. * @arg The ID of supply if there is one.
  194. */
  195. int tryPickSupply(int tileId) {
  196. int supplyId = tiles[tileId].hasSupply(supplies);
  197. if (supplyId != Const.noSupply) {
  198. tiles[tileId].pickSupply(supplies, supplyId);
  199. }
  200. return supplyId;
  201. }
  202. /**
  203. * A plain fair dice functionality provided by the board.
  204. * @return A random direction;
  205. */
  206. int dice () {
  207. ShuffledRange d = new ShuffledRange(DirRange.Begin, DirRange.End, DirRange.Step);
  208. return d.get();
  209. }
  210. /** @return the size of each site of the board. */
  211. int size () { return N; }
  212. /**
  213. * Utility function to create player IDs
  214. * @return The generated player id.
  215. */
  216. int generatePlayerId () throws Exception {
  217. if (playerCount < Const.numOfPlayers)
  218. return playerCount++;
  219. else
  220. throw new Exception("Maximum number of players exceeded");
  221. }
  222. /**
  223. * Boards utility to give access to other player Id.
  224. *
  225. * @param playerId The id of player who asks
  226. * @return The other player's Id.
  227. */
  228. int getOpponentId(int playerId) {
  229. return Const.numOfPlayers - (playerId +1);
  230. }
  231. /**
  232. * Boards utility to give access to other player moves.
  233. *
  234. * @param playerId The id of player who asks
  235. * @return The moves data of other player
  236. */
  237. int[] getOpponentMove (int playerId) {
  238. return moves[getOpponentId(playerId)];
  239. }
  240. /**
  241. * Utility to update the moves of each player.
  242. *
  243. * This function is used by the players to update their position on the board.
  244. * After that a player can read other player positions using getOpponentMoves()
  245. * @see getOpponentMoves()
  246. *
  247. * @param m Reference to new move data
  248. * @param playerId The id of the player who update his/her data.
  249. */
  250. void updateMove(int[] m, int playerId) {
  251. //moves.set(playerId, Arrays.stream(m).boxed().toArray(Integer[]::new));
  252. moves[playerId] = m;
  253. }
  254. /** @} */
  255. /**
  256. * @name Accessor/Mutator interface
  257. * @note
  258. * Please consider not to use mutator interface. Its the abstraction killer :(
  259. */
  260. /** @{ */
  261. int getN() { return N; }
  262. int getS() { return S; }
  263. int getW() { return W; }
  264. /**
  265. * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure".
  266. * <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a>
  267. * @return Reference to inner tiles array.
  268. */
  269. Tile[] getTiles() { return tiles; }
  270. /**
  271. * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure".
  272. * <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a>
  273. * @return Reference to inner supplies array.
  274. */
  275. Supply[] getSupplies() { return supplies; }
  276. /**
  277. * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure".
  278. * <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a>
  279. * @return Reference to inner walls array.
  280. */
  281. ArrayList<Edge> getWalls() { return walls; }
  282. /**
  283. * @note Use it with care. Any use of this function results to what Sean Parent calls "incidental data-structure".
  284. * <a href="https://github.com/sean-parent/sean-parent.github.io/blob/master/better-code/03-data-structures.md"> see also here</a>
  285. * @return Reference to inner walls array.
  286. */
  287. int[][] getMoves() { return moves; }
  288. void setN(int N) { this.N = N; }
  289. void setS(int S) { this.S = S; }
  290. void setW(int W) { this.W = W; }
  291. /**
  292. * @param tiles Reference to tiles that we want to act as replacement for the inner tiles array.
  293. * @note Use with care.
  294. * Any call to this function will probably add memory for the garbage collector.
  295. */
  296. void setTiles(Tile[] tiles) { this.tiles = tiles; }
  297. /**
  298. * @param supplies Reference to supplies that we want to act as replacement for the inner supplies array.
  299. * @note Use with care.
  300. * Any call to this function will probably add memory for the garbage collector.
  301. */
  302. void setSupplies(Supply[] supplies) { this.supplies= supplies; }
  303. /**
  304. * @param walls Reference to walls that we want to act as replacement for the inner walls vector.
  305. * @note Use with care.
  306. * Any call to this function will probably add memory for the garbage collector.
  307. */
  308. void setWalls (ArrayList<Edge> walls) { this.walls= walls; }
  309. /**
  310. * @param moves Reference to moves that we want to act as replacement for the inner moves vector.
  311. * @note Use with care.
  312. * Any call to this function will probably add memory for the garbage collector.
  313. */
  314. void setMoves(int[][] moves) { this.moves =moves; }
  315. /** @} */
  316. /** @name Sentinel predicates */
  317. /** @{ */
  318. private boolean isLeftSentinel (int tileId) { return (Position.toCol(tileId) == 0); }
  319. private boolean isRightSentinel (int tileId) { return (Position.toCol(tileId) == N-1); }
  320. private boolean isUpSentinel (int tileId) { return (Position.toRow(tileId) == N-1); }
  321. private boolean isDownSentinel (int tileId) { return (Position.toRow(tileId) == 0); }
  322. /** @} */
  323. /**
  324. * @name private functionality of the object
  325. */
  326. /** @{ */
  327. /**
  328. * This function creates randomly all the tiles of the board
  329. */
  330. private void createTiles() {
  331. int wallCount;
  332. wallCount = createBasicTileWalls (); // First create tiles with outer walls
  333. wallCount += createInnerWalls(); // Greedy create as many inner walls we can
  334. W = wallCount;
  335. }
  336. /**
  337. * This function create randomly the board's supplies.
  338. *
  339. * The supplies has to be in separate tiles and in tiles with no player
  340. *
  341. * @param theseusTile The tile of the Theseus
  342. * @param minotaurTile The tile of the Minotaur
  343. */
  344. private void createSupplies(int theseusTile, int minotaurTile) {
  345. ShuffledRange rand = new ShuffledRange(0, N*N); // Make a shuffled range of all tiles
  346. for (int tileId, i=0 ; i<supplies.length ; ++i) {
  347. // Pick a tile as long as there is no player in it
  348. do
  349. tileId = rand.get();
  350. while (tileId == theseusTile || tileId == minotaurTile);
  351. supplies[i] = new Supply(i, tileId);
  352. }
  353. }
  354. /**
  355. * Predicate to check if a wall creates a closed room.
  356. *
  357. * This algorithm has a complexity of @f$ O(N^2logN) @f$ where N represents the total
  358. * number of tiles.
  359. * It should be used with care.
  360. *
  361. * @param tileId The tileId of the wall.
  362. * @param direction The wall's relative direction.
  363. * @return True if the wall creates a closed room, false otherwise.
  364. */
  365. private boolean isRoomCreator (int tileId, int direction) {
  366. // Clone the list of all the walls locally.
  367. ArrayList<Edge> w = new ArrayList<Edge>();
  368. for (Edge it : walls)
  369. w.add(new Edge(it));
  370. // Create the largest possible coherent graph from the list of walls(edges)
  371. Graph g = new Graph(new Edge(tileId, direction));
  372. int size;
  373. do {
  374. size = w.size(); // mark the size (before the pass)
  375. for (int i =0, S=w.size() ; i<S ; ++i) // for each edge(wall) on the local wall list
  376. if (g.attach(w.get(i))) { // can we attach the edge(wall) to the graph ?
  377. w.remove(i); // if yes remove it from the local wall list
  378. --i; --S; // decrease iterator and size to match ArrayList's new values
  379. }
  380. } while (size != w.size()); // If the size hasn't change(no new graph leafs) exit
  381. // Search if a vertex is attached to the graph more than once.
  382. // This means that there is at least 2 links to the same node
  383. // so the graph has a closed loop
  384. for (Edge it : walls) {
  385. if (g.count(it.getV1()) > 1) return true;
  386. if (g.count(it.getV2()) > 1) return true;
  387. }
  388. return false;
  389. }
  390. /**
  391. * Predicate to check if a tile direction is `Wallable`.
  392. *
  393. * A `wallable` direction is a tile direction where:
  394. * <ul>
  395. * <li>The wall is not the DOWN wall from tile (0, 0).
  396. * <li>There is not already a wall in the desired direction. (Implies no sentinel tile).
  397. * <li>The neighbor in this direction has at most `Const.maxTileWalls -1` walls.
  398. * <li>The wall does not create a closed room (Optional requirement).
  399. * </ul>
  400. *
  401. * @note
  402. * A wallable direction automatically implies that the direction in not an outer wall.
  403. *
  404. * @param tileId The tile to check.
  405. * @param direction The direction to check
  406. * @return True if the direction is wallable.
  407. */
  408. private boolean isWallableDir (int tileId, int direction) {
  409. // Check list
  410. if (!isWalkable(tileId, direction))
  411. return false;
  412. switch (direction) {
  413. case Direction.UP:
  414. if (tiles[upTileId.apply(tileId)].hasWalls() >= Const.maxTileWalls) return false;
  415. break;
  416. case Direction.DOWN:
  417. if (tiles[downTileId.apply(tileId)].hasWalls() >= Const.maxTileWalls) return false;
  418. break;
  419. case Direction.LEFT:
  420. if (tiles[leftTileId.apply(tileId)].hasWalls() >= Const.maxTileWalls) return false;
  421. break;
  422. case Direction.RIGHT:
  423. if (tiles[rightTileId.apply(tileId)].hasWalls() >= Const.maxTileWalls) return false;
  424. break;
  425. }
  426. if (Session.loopGuard && isRoomCreator(tileId, direction))
  427. return false;
  428. return true;
  429. }
  430. /**
  431. * Predicate to check if a tile is `Wallable`.
  432. *
  433. * A `wallable` tile is a tile where:
  434. * <ul>
  435. * <li>The tile has at most `Const.maxTileWalls -1` walls.
  436. * <li>There is at least one wallable direction on the tile.
  437. * </ul>
  438. * @param tileId The tile to check
  439. * @return True if the tile is wallable.
  440. */
  441. private boolean isWallable (int tileId) {
  442. // Check list
  443. if (tileId == Const.noTileId)
  444. return false;
  445. if (tiles[tileId].hasWalls() >= Const.maxTileWalls)
  446. return false;
  447. Range dirs = new Range(DirRange.Begin, DirRange.End, DirRange.Step);
  448. for (int dir = dirs.get() ; dir != Const.EOR ; dir = dirs.get())
  449. if (isWallableDir(tileId, dir))
  450. return true;
  451. return false;
  452. }
  453. /**
  454. * This utility function create/allocate the tiles of the board and create
  455. * the outer walls at the same time.
  456. *
  457. * @return The number of walls created from the utility.
  458. */
  459. private int createBasicTileWalls () {
  460. int wallCount =0;
  461. for (int i =0 ; i< tiles.length ; ++i) {
  462. boolean up = isUpSentinel(i);
  463. boolean down = isDownSentinel(i) && (i != 0);
  464. boolean left = isLeftSentinel(i);
  465. boolean right = isRightSentinel(i);
  466. wallCount += ((up?1:0) + (down?1:0) + (left?1:0) + (right?1:0));
  467. tiles[i] = new Tile (i, up, down, left, right);
  468. // If we have loopGuard enable we populate walls also.
  469. if (Session.loopGuard) {
  470. if (up) walls.add(new Edge(i, Direction.UP));
  471. if (down) walls.add(new Edge(i, Direction.DOWN));
  472. if (left) walls.add(new Edge(i, Direction.LEFT));
  473. if (right) walls.add(new Edge(i, Direction.RIGHT));
  474. }
  475. }
  476. return wallCount;
  477. }
  478. /**
  479. * Create randomly a wall in the wallable selected tile.
  480. * @param tileId The wallable tile to create the wall
  481. */
  482. private void createInnerWall(int tileId) {
  483. // Randomly pick a wallable direction in that tile.
  484. ShuffledRange randDirections = new ShuffledRange(DirRange.Begin, DirRange.End, DirRange.Step);
  485. int dir;
  486. do
  487. dir = randDirections.get();
  488. while (!isWallableDir(tileId, dir));
  489. // Add wall to tileId and the adjacent tileId
  490. Position neighbor = new Position(Position.toRow(tileId), Position.toCol(tileId), dir);
  491. tiles[tileId].setWall(dir);
  492. tiles[neighbor.getId()].setWall(Direction.opposite(dir));
  493. // If we have loopGuard enable we populate walls also.
  494. if (Session.loopGuard)
  495. walls.add(new Edge(tileId, dir));
  496. }
  497. /**
  498. * This utility creates the inner walls of the board.
  499. *
  500. * @return The number of walls failed to create.
  501. */
  502. private int createInnerWalls () {
  503. ShuffledRange randTiles = new ShuffledRange(0, N*N);
  504. for (int tileId, walls =0, shuffleMark =0 ; true ; ) {
  505. // randomly pick a wallable tile.
  506. do {
  507. if ((tileId = randTiles.get())== Const.EOR) {
  508. if (walls == shuffleMark) // Wallable tiles exhausted.
  509. return walls;
  510. else { // Re-shuffle and continue.
  511. randTiles = new ShuffledRange(0, N*N);
  512. shuffleMark =walls;
  513. }
  514. }
  515. } while (!isWallable(tileId));
  516. ++walls;
  517. createInnerWall(tileId);
  518. }
  519. }
  520. /**
  521. * Utility to get the body (center line) of the string representation of the tile.
  522. *
  523. * @param row What board's row to get.
  524. * @param col What board's column to get.
  525. * @param theseusTile The current tile of the Theseus.
  526. * @param minotaurTile The current tile of the Minotaur.
  527. * @return The body string
  528. */
  529. private String getTileBody (int row, int col, int theseusTile, int minotaurTile) {
  530. int tileId = Position.toID(row, col);
  531. boolean T = (tileId == theseusTile) ? true : false;
  532. boolean M = (tileId == minotaurTile) ? true : false;
  533. int S = tiles[tileId].hasSupply(supplies);
  534. if (T && !M) return " T ";
  535. else if (T && M) return "T+M";
  536. else if (M) {
  537. if (S == Const.noSupply) return " M ";
  538. else return "M+s";
  539. }
  540. else if (S != Const.noSupply)
  541. return String.format("s%02d", S+1);
  542. else return " ";
  543. }
  544. /**
  545. * Utility to render the 3 strings of the tile in the representation frame.
  546. *
  547. * @param frame Reference to the frame to print into.
  548. * @param row The board's row to print.
  549. * @param col The board's column to print.
  550. * @param theseusTile The current tile of the Theseus.
  551. * @param minotaurTile The current tile of the Minotaur.
  552. */
  553. private void renderTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile) {
  554. IntFunction<Integer> toframe = (r)->{ return 2*r+1; };
  555. int tileId = Position.toID(row, col);
  556. frame[toframe.apply(row)+1][col] = tiles[tileId].hasWall(Direction.UP) ? "+---" : "+ ";
  557. frame[toframe.apply(row) ][col] = (tiles[tileId].hasWall(Direction.LEFT)? "|" : " ")
  558. + getTileBody(row, col, theseusTile, minotaurTile);
  559. frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---" : "+ ";
  560. }
  561. /**
  562. * Utility to render the 3 strings of the tile in the representation frame in
  563. * the case the tile lies in the east wall. We call these tiles `sentinel tiles`
  564. *
  565. * @param frame Reference to the frame to print into.
  566. * @param row The board's row to print.
  567. * @param col The board's column to print.
  568. * @param theseusTile The current tile of the Theseus.
  569. * @param minotaurTile The current tile of the Minotaur.
  570. */
  571. private void renderSentinelTile(String[][] frame, int row, int col, int theseusTile, int minotaurTile ) {
  572. IntFunction<Integer> toframe = (r)->{ return 2*r+1; };
  573. int tileId = Position.toID(row, col);
  574. frame[toframe.apply(row)+1][col] = tiles[tileId].hasWall(Direction.UP) ? "+---+" : "+ +";
  575. frame[toframe.apply(row) ][col] = (tiles[tileId].hasWall(Direction.LEFT)? "|" : " ")
  576. + getTileBody(row, col, theseusTile, minotaurTile)
  577. + (tiles[tileId].hasWall(Direction.RIGHT)? "|" : " ");
  578. frame[toframe.apply(row)-1][col] = tiles[tileId].hasWall(Direction.DOWN) ? "+---+" : "+ +";
  579. }
  580. /** @} */
  581. /** @name Neighbor access lambdas */
  582. /** @{ */
  583. private IntFunction<Integer> leftTileId = (id) -> { return Position.toID(Position.toRow(id), Position.toCol(id)-1); };
  584. private IntFunction<Integer> rightTileId = (id) -> { return Position.toID(Position.toRow(id), Position.toCol(id)+1); };
  585. private IntFunction<Integer> upTileId = (id) -> { return Position.toID(Position.toRow(id)+1, Position.toCol(id) ); };
  586. private IntFunction<Integer> downTileId = (id) -> { return Position.toID(Position.toRow(id)-1, Position.toCol(id) ); };
  587. /** @} */
  588. /** @name Class data */
  589. /** @{ */
  590. private int N; /**< The size of each edge of the board */
  591. private int S; /**< The number of the supplies on the board */
  592. private int W; /**< The number of walls on the board */
  593. private Tile[] tiles; /**< Array to hold all the tiles for the board */
  594. private Supply[] supplies; /**< Array to hold all the supplies on the board */
  595. private ArrayList<Edge> walls; /**<
  596. * Array to hold all the walls using the edge representation
  597. * required by the closed room preventing algorithm.
  598. */
  599. private int[][] moves;
  600. private int playerCount;
  601. /** @} */
  602. }