Spaces:
Running
Running
| import java.awt.Color; | |
| import java.util.Random; | |
| public class Agent { | |
| private int x, y; | |
| private final int id; | |
| private final MazeManager maze; | |
| private final Color color; | |
| private final String name; | |
| private boolean phaseWallUsed = false; | |
| private boolean passedWall = false; | |
| private final Stack<String> moveHistory; | |
| private final Random random = new Random(); | |
| private boolean gotPowerUp = false; | |
| private int powerUpUses = 0; | |
| private int stepCount = 0; | |
| private int trapHits = 0; | |
| public Agent(int startX, int startY, MazeManager maze, Color color, String name, int id) { | |
| this.id=id; | |
| this.x = startX; | |
| this.y = startY; | |
| this.maze = maze; | |
| this.color = color; | |
| this.name = name; | |
| this.moveHistory = new Stack<>(maze.getCols() * maze.getRows()); | |
| moveHistory.push("(" + x + ", " + y + ")"); | |
| } | |
| public int getId() | |
| { | |
| return id; | |
| } | |
| public int getX() { | |
| return x; | |
| } | |
| public int getY() { | |
| return y; | |
| } | |
| public Color getColor() { | |
| return color; | |
| } | |
| public int getTrapHits() { | |
| return trapHits; | |
| } | |
| public String getName() { | |
| return name; | |
| } | |
| public Stack<String> getMoveHistory() { | |
| return moveHistory; | |
| } | |
| public boolean passedWallThisTurn() { | |
| return passedWall; | |
| } | |
| public void setPassedWall(boolean value) { | |
| this.passedWall = value; | |
| } | |
| public int getStepCount() { | |
| return stepCount; | |
| } | |
| public int getPowerUpUses() { | |
| return powerUpUses; | |
| } | |
| public void moveTowardsGoal() { | |
| boolean canPhaseWall = false; | |
| if (gotPowerUp && !phaseWallUsed) { | |
| if (random.nextInt(100) < 20) { | |
| canPhaseWall = true; | |
| passedWall = true; | |
| powerUpUses++; | |
| } | |
| } else { | |
| passedWall = false; | |
| } | |
| Node[] openSet = new Node[maze.getCols() * maze.getRows()]; | |
| boolean[][] closedSet = new boolean[maze.getCols()][maze.getRows()]; | |
| int openSetSize = 0; | |
| int goalX = maze.getCols() / 2; | |
| int goalY = maze.getRows() / 2; | |
| Node start = new Node(x, y, null, 0, heuristic(x, y, goalX, goalY)); | |
| openSet[openSetSize++] = start; | |
| Node goalNode = null; | |
| while (openSetSize > 0) { | |
| int bestIndex = 0; | |
| for (int i = 1; i < openSetSize; i++) { | |
| if (openSet[i].f < openSet[bestIndex].f) bestIndex = i; | |
| } | |
| Node current = openSet[bestIndex]; | |
| openSet[bestIndex] = openSet[--openSetSize]; | |
| if (current.x == goalX && current.y == goalY) { | |
| goalNode = current; | |
| break; | |
| } | |
| closedSet[current.x][current.y] = true; | |
| for (int dir = 0; dir < 4; dir++) { | |
| int nx = current.x; | |
| int ny = current.y; | |
| switch (dir) { | |
| case 0: | |
| ny--; | |
| break; | |
| case 1: | |
| nx++; | |
| break; | |
| case 2: | |
| ny++; | |
| break; | |
| case 3: | |
| nx--; | |
| break; | |
| } | |
| if (!maze.isInMaze(nx, ny)) { | |
| continue; | |
| } | |
| boolean isWall = maze.hasWall(current.x, current.y, dir); | |
| if (isWall && !canPhaseWall) { | |
| continue; | |
| } | |
| if (closedSet[nx][ny]) { | |
| continue; | |
| } | |
| boolean alreadyInOpenSet = false; | |
| for (int i = 0; i < openSetSize; i++) { | |
| if (openSet[i].x == nx && openSet[i].y == ny) { | |
| alreadyInOpenSet = true; | |
| break; | |
| } | |
| } | |
| if (!alreadyInOpenSet) { | |
| openSet[openSetSize++] = new Node(nx, ny, current, | |
| current.g + 1, heuristic(nx, ny, goalX, goalY)); | |
| } | |
| } | |
| } | |
| if (goalNode != null && goalNode.parent != null) { | |
| Node moveTo = goalNode; | |
| while (moveTo.parent.parent != null) { | |
| moveTo = moveTo.parent; | |
| } | |
| int oldX = x; | |
| int oldY = y; | |
| if (maze.hasWall(x, y, directionTo(moveTo.x, moveTo.y)) && canPhaseWall) { | |
| phaseWallUsed = true; | |
| } | |
| this.x = moveTo.x; | |
| this.y = moveTo.y; | |
| if (x != oldX || y != oldY) { | |
| moveHistory.push("(" + x + ", " + y + ")"); | |
| stepCount++; | |
| } | |
| MazeTile tile = maze.getTile(x, y); | |
| if (tile.getEntity() == MazeTile.EntityType.TRAP && tile.isTrapActive()) { | |
| tile.deactivateTrap(); | |
| trapHits++; | |
| stepBackTwice(); | |
| } | |
| if (tile.getEntity() == MazeTile.EntityType.POWER_UP && tile.isPowerUpActive()) { | |
| tile.deactivatePowerUp(); | |
| gotPowerUp = true; | |
| phaseWallUsed = false; | |
| } | |
| } | |
| } | |
| private int directionTo(int toX, int toY) { | |
| if (toX == x + 1) return 1; | |
| if (toX == x - 1) return 3; | |
| if (toY == y + 1) return 2; | |
| if (toY == y - 1) return 0; | |
| return -1; | |
| } | |
| private void stepBackTwice() { | |
| if (moveHistory.getSize() < 3) return; | |
| moveHistory.pop(); | |
| moveHistory.pop(); | |
| String coord = (String) moveHistory.pop(); | |
| String[] parts = coord.replace("(", "").replace(")", "").split(", "); | |
| this.x = Integer.parseInt(parts[0]); | |
| this.y = Integer.parseInt(parts[1]); | |
| } | |
| private int heuristic(int x1, int y1, int x2, int y2) { | |
| return Math.abs(x1 - x2) + Math.abs(y1 - y2); | |
| } | |
| private static class Node { | |
| int x, y; | |
| Node parent; | |
| int g; | |
| int f; | |
| public Node(int x, int y, Node parent, int g, int h) { | |
| this.x = x; | |
| this.y = y; | |
| this.parent = parent; | |
| this.g = g; | |
| this.f = g + h; | |
| } | |
| } | |
| } |