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 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 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; } } }