diff options
Diffstat (limited to 'core/src/ch/asynk/tankontank/engine')
-rw-r--r-- | core/src/ch/asynk/tankontank/engine/SearchBoard.java | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/core/src/ch/asynk/tankontank/engine/SearchBoard.java b/core/src/ch/asynk/tankontank/engine/SearchBoard.java new file mode 100644 index 0000000..1c7f67f --- /dev/null +++ b/core/src/ch/asynk/tankontank/engine/SearchBoard.java @@ -0,0 +1,185 @@ +package ch.asynk.tankontank.engine; + +import java.util.List; +import java.util.ArrayDeque; +import java.util.Vector; + +public class SearchBoard +{ + public class Node + { + public int col; + public int row; + public int search; + public int mvtLeft; + public Node parent; + public boolean roadMarch; + + public Node(int col, int row) + { + this.col = col; + this.row = row; + } + } + + private int cols; + private int rows; + private Board board; + private Node nodes[]; + private int searchCount; + private ArrayDeque<Node> stack; + private ArrayDeque<Node> roadMarch; + private List<Node> result; + private Node adjacents[]; + private Board.Orientation directions[]; + + public SearchBoard(Board board, int cols, int rows) + { + this.cols = cols; + this.rows = rows; + this.board = board; + this.nodes = new Node[cols * rows]; + for (int j = 0; j < rows; j++) + for (int i = 0; i < cols; i++) + nodes[i + (j * cols)] = new Node(i, j); + this.searchCount = 0; + this.stack = new ArrayDeque<Node>(20); + this.roadMarch = new ArrayDeque<Node>(5); + this.result = new Vector<Node>(10); + this.adjacents = new Node[6]; + this.directions = new Board.Orientation[6]; + directions[0] = Board.Orientation.NORTH; + directions[1] = Board.Orientation.NORTH_EAST; + directions[2] = Board.Orientation.SOUTH_EAST; + directions[3] = Board.Orientation.SOUTH; + directions[4] = Board.Orientation.SOUTH_WEST; + directions[5] = Board.Orientation.NORTH_WEST; + } + + private Node getNode(int col, int row) + { + if ((col < 0) || (col >= cols) || (row < 0) || (row >= rows)) return null; + return nodes[col + (row * cols)]; + } + + public void adjacents(Node src) + { + adjacents[0] = getNode((src.col - 1), src.row); + adjacents[3] = getNode((src.col + 1), src.row); + if ((src.row % 2) == 0) { + adjacents[1] = getNode((src.col - 1), (src.row + 1)); + adjacents[2] = getNode(src.col, (src.row + 1)); + adjacents[4] = getNode(src.col, (src.row - 1)); + adjacents[5] = getNode((src.col - 1), (src.row - 1)); + } else { + adjacents[1] = getNode(src.col, (src.row + 1)); + adjacents[2] = getNode((src.col + 1), (src.row + 1)); + adjacents[4] = getNode((src.col + 1), (src.row - 1)); + adjacents[5] = getNode(src.col, (src.row - 1)); + } + } + + public List<Node> reachableFrom(Pawn pawn, int col, int row) + { + searchCount += 1; + result.clear(); + + Node start = getNode(col, row); + start.parent = null; + start.search = searchCount; + start.mvtLeft = pawn.getMvt();; + start.roadMarch = true; + stack.push(start); + + boolean first = true; + + while (stack.size() != 0) { + Node src = stack.pop(); + + if (src.mvtLeft <= 0) { + if (src.roadMarch) { + src.mvtLeft = board.getTile(src.col, src.row).roadMarchBonus(pawn); + roadMarch.push(src); + } + continue; + } + + adjacents(src); + + for(int i = 0; i < 6; i++) { + Node dst = adjacents[i]; + if (dst != null) { + + Tile t = board.getTile(dst.col, dst.row); + boolean road = t.road(directions[i]); + int cost = t.costFrom(pawn, directions[i], road); + boolean mayMoveOne = first && t.atLeastOneMove(pawn); + int r = src.mvtLeft - cost; + boolean roadMarch = road && src.roadMarch; + + if (dst.search == searchCount) { + if ((r >= 0) && ((r > dst.mvtLeft) || roadMarch)) { + dst.mvtLeft = r; + dst.parent = src; + dst.roadMarch = roadMarch; + } + } else { + dst.search = searchCount; + if ((r >= 0) || mayMoveOne) { + dst.parent = src; + dst.mvtLeft = r; + dst.roadMarch = roadMarch; + stack.push(dst); + result.add(dst); + } else { + dst.parent = null; + dst.mvtLeft = Integer.MAX_VALUE; + } + } + } + } + first = false; + } + + while(roadMarch.size() != 0) { + Node src = roadMarch.pop(); + + adjacents(src); + + for(int i = 0; i < 6; i++) { + Node dst = adjacents[i]; + if (dst != null) { + + Tile t = board.getTile(dst.col, dst.row); + if (!t.road(directions[i])) + continue; + int cost = t.costFrom(pawn, directions[i], true); + int r = src.mvtLeft - cost; + + if (dst.search == searchCount) { + if ((r >= 0) && (r > dst.mvtLeft)) { + dst.mvtLeft = r; + dst.parent = src; + dst.roadMarch = true; + } + } else { + dst.search = searchCount; + if (r >= 0) { + dst.parent = src; + dst.mvtLeft = r; + dst.roadMarch = true; + roadMarch.push(dst); + result.add(dst); + } else { + dst.parent = null; + dst.mvtLeft = Integer.MAX_VALUE; + } + } + } + } + } + + return result; + } +} + |