protected boolean isSafeMovement(Mine mine, Cell source, Cell target) { if (source == null || target == null) return false; if (source.getContent().getTrampolineTarget() == target.getContent()) return true; Cell upCell = mine.getCell(target.getCoordinate().up()); if (upCell == null) return true; Cell upUpCell = mine.getCell(target.getCoordinate().up().up()); Cell upUpLeftCell = mine.getCell(target.getCoordinate().up().up().left()); Cell upUpRightCell = mine.getCell(target.getCoordinate().up().up().right()); if (upCell.getContent() == CellContent.Empty && (upUpCell != null && (upUpCell.getContent() == CellContent.Rock || upUpCell.getContent() == CellContent.HighOrderRock) || upUpLeftCell != null && (upUpLeftCell.getContent() == CellContent.Rock || upUpLeftCell.getContent() == CellContent.HighOrderRock) || upUpRightCell != null && (upUpRightCell.getContent() == CellContent.Rock || upUpRightCell.getContent() == CellContent.HighOrderRock))) { return false; } return true; }
protected void findAllCellLinks( Mine mine, Cell cell, List<CellsLink> links, Set<Cell> processedCells) { if (processedCells.contains(cell)) return; else processedCells.add(cell); String map = mine.toText(); for (Cell neighboringCell : mine.getAdjacentCells(cell)) { if (neighboringCell == null) continue; CellContent neighboringContent = neighboringCell.getContent(); if (neighboringContent == CellContent.Earth || neighboringContent == CellContent.Empty || neighboringContent == CellContent.HuttonsRazor || neighboringContent == CellContent.Lambda || neighboringContent == CellContent.OpenLambdaLift) { if (isSafeMovement(mine, cell, neighboringCell)) { CellsLink link = new CellsLink(mine, cell, neighboringCell); if (!loseLinks.get(map).contains(link)) { links.add(link); findAllCellLinks(mine, neighboringCell, links, processedCells); } } } else if (!CellContent.getTargets().contains(cell.getContent()) && CellContent.getTargets().contains(neighboringContent)) { findAllCellLinks(mine, neighboringCell, links, processedCells); } } if (CellContent.getTrampolines().contains(cell.getContent())) { for (Cell target : mine.findCells(cell.getContent().getTrampolineTarget())) { if (target == null) continue; if (isSafeMovement(mine, cell, target)) { CellsLink link = new CellsLink(mine, cell, target); if (!loseLinks.get(map).contains(link)) { links.add(link); findAllCellLinks(mine, target, links, processedCells); } } } } }
@Override public void solve() { while (true) { Mine mine = null; mine = initialMine.clone(); Game game = new Game(mine); while (game.getState() == GameState.Game) { Cell robotCell = mine.getRobotCell(); String map = mine.toText(); String mapWithoutRobot = mine.toTextWithoutRobot(); if (!loseMovs.containsKey(map)) { loseMovs.put(map, new HashSet<Movement>()); } if (!loseLinks.containsKey(map)) { loseLinks.put(map, new HashSet<CellsLink>()); } if (!noWay.containsKey(map)) { noWay.put(map, new HashSet<Coordinate>()); } if (!attendedWalkingAroundCoordinates.containsKey(mapWithoutRobot)) { attendedWalkingAroundCoordinates.put(mapWithoutRobot, new HashSet<Coordinate>()); } attendedWalkingAroundCoordinates.get(mapWithoutRobot).add(robotCell.getCoordinate()); Set<Cell> targets = new HashSet<Cell>(); boolean isFreeWay = false; for (Cell cell : mine.getAdjacentCells(robotCell)) { Movement mov = robotCell.getCoordinate().getNecessaryMovement(cell.getCoordinate()); isFreeWay |= !attendedWalkingAroundCoordinates.get(mapWithoutRobot).contains(cell.getCoordinate()) && !loseMovs.get(map).contains(mov); } if (isFreeWay) { targets.addAll(mine.findCells(CellContent.Lambda)); targets.addAll(mine.findCells(CellContent.HighOrderRock)); if (targets.size() == 0) targets.addAll(mine.findCells(CellContent.OpenLambdaLift)); targets.removeAll(mine.getCells(noWay.get(map))); } else { targets.addAll(mine.findCells(CellContent.Empty)); targets.addAll(mine.findCells(CellContent.Earth)); targets.addAll(mine.findCells(CellContent.HuttonsRazor)); for (CellContent content : CellContent.getTrampolines()) { targets.addAll(mine.findCells(content)); } targets.removeAll(mine.getCells(attendedWalkingAroundCoordinates.get(mapWithoutRobot))); targets.removeAll(mine.getCells(noWay.get(map))); if (targets.size() == 0) { game.move(Movement.ABORT); continue; } } Graph<Cell, CellsLink> graph = getDirectedGraph(mine); DijkstraShortestPath<Cell, CellsLink> alg = new DijkstraShortestPath<Cell, CellsLink>( graph, new CellsLinkTransformer<CellsLink, Double>()); Cell nextTarget = null; List<CellsLink> routeToNextTarget = null; double shortestDist = Double.MAX_VALUE; for (Cell target : targets) { List<CellsLink> route = null; Number dist = null; try { route = alg.getPath(mine.getRobotCell(), target); dist = alg.getDistance(mine.getRobotCell(), target); } catch (IllegalArgumentException e) { noWay.get(map).add(target.getCoordinate()); continue; } if (dist != null && route != null && route.size() > 0 && dist.doubleValue() < shortestDist) { CellsLink firstLink = route.get(0); Movement mov = firstLink .getSource() .getCoordinate() .getNecessaryMovement(firstLink.getTarget().getCoordinate()); if (!loseMovs.get(map).contains(mov) && !attendedWalkingAroundCoordinates .get(mapWithoutRobot) .contains(target.getCoordinate())) { shortestDist = dist.doubleValue(); nextTarget = target; routeToNextTarget = route; } } } if (nextTarget != null) { for (CellsLink link : routeToNextTarget) { Cell source = link.getSource(); Cell target = link.getTarget(); if (isSafeMovement(mine, source, target)) { Movement mov = source.getCoordinate().getNecessaryMovement(target.getCoordinate()); GameState state = game.move(mov); if (state == GameState.Lose || state == GameState.Abort) { loseMovs.get(map).add(mov); loseLinks.get(map).add(link); } } break; } } else { // Walking around for (Movement mov : Movement.values()) { if (!loseMovs.get(map).contains(mov)) { if (mov == Movement.RAZOR && mine.getRazorsCount() > 0) { boolean isRazorApplied = false; for (Cell cell : mine.getNeighboringCells(robotCell)) { isRazorApplied |= cell.getContent() == CellContent.WadlersBeard; } if (!isRazorApplied) continue; } Cell movCell = null; for (Cell cell : mine.getAdjacentCells(robotCell)) { if (robotCell.getCoordinate().getNecessaryMovement(cell.getCoordinate()) == mov) { if (!attendedWalkingAroundCoordinates .get(mapWithoutRobot) .contains(cell.getCoordinate())) { movCell = cell; break; } } } if (mov == Movement.WAIT || mov == Movement.RAZOR || movCell != null && !attendedWalkingAroundCoordinates .get(mapWithoutRobot) .contains(movCell.getCoordinate())) { GameState state = game.move(mov); if (movCell != null && mapWithoutRobot.equals(mine.toTextWithoutRobot())) attendedWalkingAroundCoordinates .get(mapWithoutRobot) .add(movCell.getCoordinate()); if (state == GameState.Game && map.equals(mine.toText())) { loseMovs.get(map).add(mov); } break; } } } } } addNewRoute(game); attemptsCount++; } }
protected List<CellsLink> getCellLinks(Mine mine) { List<CellsLink> links = new ArrayList<CellsLink>(); Cell robotCell = mine.getRobotCell(); findAllCellLinks(mine, robotCell, links, new HashSet<Cell>()); return links; }