Merge
authorindvdum (gotoindvdum[at]gmail[dot]com)
Wed, 18 Jul 2012 09:42:52 +0400
changeset 5380f5fc954cff
parent 45 d357a16ee62d
parent 52 db49d3e51921
child 54 8a248d789ec7
Merge
     1.1 --- a/icfp-model/src/main/java/ru/bosony/model/game/Game.java	Mon Jul 16 13:19:10 2012 +0400
     1.2 +++ b/icfp-model/src/main/java/ru/bosony/model/game/Game.java	Wed Jul 18 09:42:52 2012 +0400
     1.3 @@ -12,7 +12,9 @@
     1.4  import static ru.bosony.model.cellscontents.CellContent.WadlersBeard;
     1.5  
     1.6  import java.util.ArrayList;
     1.7 +import java.util.HashMap;
     1.8  import java.util.List;
     1.9 +import java.util.Map;
    1.10  
    1.11  import ru.bosony.model.cellscontents.CellContent;
    1.12  import ru.bosony.model.mine.Cell;
    1.13 @@ -32,6 +34,7 @@
    1.14  	protected int				lastScoreChange			= 0;
    1.15  	protected GameState			state					= GameState.Game;
    1.16  	protected int				lambdaCollectedCount	= 0;
    1.17 +	protected List<Mine>		history					= new ArrayList<Mine>();
    1.18  	protected List<Movement>	route					= new ArrayList<Movement>();
    1.19  	protected int				underwater				= 0;
    1.20  
    1.21 @@ -69,6 +72,7 @@
    1.22  
    1.23  		// Moving and scoring
    1.24  		route.add(mov);
    1.25 +		history.add(mine.clone());
    1.26  		Cell robotCell = mine.getRobotCell();
    1.27  		Coordinate robotCoord = robotCell.getCoordinate();
    1.28  		Coordinate nextRobotCoord = null;
    1.29 @@ -349,4 +353,24 @@
    1.30  	public int getUnderwater() {
    1.31  		return underwater;
    1.32  	}
    1.33 +
    1.34 +	public boolean hasViciousCircle() {
    1.35 +		if (route.size() != history.size())
    1.36 +			throw new RuntimeException("Desynchronized history");
    1.37 +		Map<Mine, Movement> state = new HashMap<Mine, Movement>();
    1.38 +		for (int i = route.size() - 1; i >= 0; i--) {
    1.39 +			Mine mine = history.get(i);
    1.40 +			Movement mov = route.get(i);
    1.41 +			if (state.get(mine) == mov)
    1.42 +				return true;
    1.43 +			state.put(mine, mov);
    1.44 +		}
    1.45 +		return false;
    1.46 +	}
    1.47 +
    1.48 +	@Override
    1.49 +	public String toString() {
    1.50 +		return state.toString() + ", score = " + score + ", " + route.size() + " steps: "
    1.51 +				+ (route.size() > 100 ? getStringRoute().substring(0, 100) + "..." : getStringRoute()) + "\n\n" + mine;
    1.52 +	}
    1.53  }
     2.1 --- a/icfp-model/src/main/java/ru/bosony/model/mine/Cell.java	Mon Jul 16 13:19:10 2012 +0400
     2.2 +++ b/icfp-model/src/main/java/ru/bosony/model/mine/Cell.java	Wed Jul 18 09:42:52 2012 +0400
     2.3 @@ -36,4 +36,9 @@
     2.4  		return clone;
     2.5  	}
     2.6  
     2.7 +	@Override
     2.8 +	public String toString() {
     2.9 +		return "Cell [coordinate=" + coordinate + ", content=" + content + "]";
    2.10 +	}
    2.11 +
    2.12  }
     3.1 --- a/icfp-model/src/main/java/ru/bosony/model/mine/Mine.java	Mon Jul 16 13:19:10 2012 +0400
     3.2 +++ b/icfp-model/src/main/java/ru/bosony/model/mine/Mine.java	Wed Jul 18 09:42:52 2012 +0400
     3.3 @@ -8,6 +8,7 @@
     3.4  import static ru.bosony.model.cellscontents.CellContent.OpenLambdaLift;
     3.5  import static ru.bosony.model.cellscontents.CellContent.Rock;
     3.6  
     3.7 +import java.util.Collection;
     3.8  import java.util.HashSet;
     3.9  import java.util.Set;
    3.10  import java.util.regex.Matcher;
    3.11 @@ -23,7 +24,7 @@
    3.12   *         14.07.2012 2:02:18
    3.13   * 
    3.14   */
    3.15 -public class Mine implements TextRepresentable {
    3.16 +public class Mine implements TextRepresentable, Cloneable {
    3.17  
    3.18  	protected Cell[][]			cells;
    3.19  	protected int				sizeX;
    3.20 @@ -48,13 +49,17 @@
    3.21  	protected static String		firstTrampolineRegexp				= "(?s).*?Trampoline ([A-I]) targets ([1-9])";
    3.22  
    3.23  	public Mine(String text) {
    3.24 -		fromText(text);
    3.25 +		this(text, null);
    3.26  		if (findCells(OpenLambdaLift).size() != 0)
    3.27  			throw new RuntimeException("Detected OpenLambdaLift in new map!");
    3.28  		if (findCells(MiningRobot).size() != 1)
    3.29  			throw new RuntimeException("New map does not contain a robot!");
    3.30  		if (findCells(ClosedLambdaLift).size() != 1)
    3.31  			throw new RuntimeException("New map does not contain a ClosedLambdaLift!");
    3.32 +	}
    3.33 +
    3.34 +	protected Mine(String text, Object obj) {
    3.35 +		fromText(text);
    3.36  		lambdasAndHighOrderRocksStartCount = findCells(Lambda).size() + findCells(CellContent.HighOrderRock).size();
    3.37  	}
    3.38  
    3.39 @@ -74,6 +79,10 @@
    3.40  		return text;
    3.41  	}
    3.42  
    3.43 +	public String toTextWithoutRobot() {
    3.44 +		return toText().replaceAll(CellContent.MiningRobot.toText(), CellContent.Empty.toText());
    3.45 +	}
    3.46 +
    3.47  	protected void fromText(String str) {
    3.48  		Matcher matcher = minePattern.matcher(str);
    3.49  		if (!matcher.matches())
    3.50 @@ -174,6 +183,18 @@
    3.51  		return cells[x - 1][sizeY - y];
    3.52  	}
    3.53  
    3.54 +	public Set<Cell> getCells(Collection<Coordinate> coordinates) {
    3.55 +		Set<Cell> cells = new HashSet<Cell>();
    3.56 +		if (coordinates == null)
    3.57 +			return cells;
    3.58 +		for (Coordinate coordinate : coordinates) {
    3.59 +			Cell cell = getCell(coordinate);
    3.60 +			if (cell != null)
    3.61 +				cells.add(cell);
    3.62 +		}
    3.63 +		return cells;
    3.64 +	}
    3.65 +
    3.66  	@Override
    3.67  	public String toString() {
    3.68  		return toText();
    3.69 @@ -215,15 +236,21 @@
    3.70  
    3.71  	public Set<Cell> getNeighboringCells(Cell cell) {
    3.72  		Set<Cell> cells = new HashSet<Cell>();
    3.73 -		for (Coordinate coordinate : cell.getCoordinate().getNeighboringCoordinates())
    3.74 -			cells.add(getCell(coordinate));
    3.75 +		for (Coordinate coordinate : cell.getCoordinate().getNeighboringCoordinates()) {
    3.76 +			Cell nextCell = getCell(coordinate);
    3.77 +			if (nextCell != null)
    3.78 +				cells.add(nextCell);
    3.79 +		}
    3.80  		return cells;
    3.81  	}
    3.82  
    3.83  	public Set<Cell> getAdjacentCells(Cell cell) {
    3.84  		Set<Cell> cells = new HashSet<Cell>();
    3.85 -		for (Coordinate coordinate : cell.getCoordinate().getAdjacentCoordinates())
    3.86 -			cells.add(getCell(coordinate));
    3.87 +		for (Coordinate coordinate : cell.getCoordinate().getAdjacentCoordinates()) {
    3.88 +			Cell nextCell = getCell(coordinate);
    3.89 +			if (nextCell != null)
    3.90 +				cells.add(nextCell);
    3.91 +		}
    3.92  		return cells;
    3.93  	}
    3.94  
    3.95 @@ -309,4 +336,9 @@
    3.96  		return toText().hashCode();
    3.97  	}
    3.98  
    3.99 +	@Override
   3.100 +	public Mine clone() {
   3.101 +		return new Mine(toText(), null);
   3.102 +	}
   3.103 +
   3.104  }
     4.1 --- a/icfp-model/src/main/java/ru/bosony/model/moving/Coordinate.java	Mon Jul 16 13:19:10 2012 +0400
     4.2 +++ b/icfp-model/src/main/java/ru/bosony/model/moving/Coordinate.java	Wed Jul 18 09:42:52 2012 +0400
     4.3 @@ -96,4 +96,9 @@
     4.4  		return super.equals(obj);
     4.5  	}
     4.6  
     4.7 +	@Override
     4.8 +	public String toString() {
     4.9 +		return "Coordinate [x=" + x + ", y=" + y + "]";
    4.10 +	}
    4.11 +
    4.12  }
     5.1 --- a/icfp-model/src/main/java/ru/bosony/model/moving/Movement.java	Mon Jul 16 13:19:10 2012 +0400
     5.2 +++ b/icfp-model/src/main/java/ru/bosony/model/moving/Movement.java	Wed Jul 18 09:42:52 2012 +0400
     5.3 @@ -9,13 +9,13 @@
     5.4   */
     5.5  public enum Movement implements TextRepresentable {
     5.6  	
     5.7 +	WAIT("W"),
     5.8 +	RAZOR("S"),
     5.9  	LEFT("L"),
    5.10 +	UP("U"),
    5.11  	RIGHT("R"),
    5.12 -	UP("U"),
    5.13  	DOWN("D"),
    5.14 -	WAIT("W"),
    5.15 -	ABORT("A"),
    5.16 -	RAZOR("S");
    5.17 +	ABORT("A");
    5.18  
    5.19  	private String	text;
    5.20  
     6.1 --- a/icfp-solver/src/main/java/ru/bosony/graph/CellsLink.java	Mon Jul 16 13:19:10 2012 +0400
     6.2 +++ b/icfp-solver/src/main/java/ru/bosony/graph/CellsLink.java	Wed Jul 18 09:42:52 2012 +0400
     6.3 @@ -56,4 +56,9 @@
     6.4  		return super.equals(obj);
     6.5  	}
     6.6  
     6.7 +	@Override
     6.8 +	public String toString() {
     6.9 +		return "CellsLink [source=" + source + ", target=" + target + ", weight=" + weight + "]";
    6.10 +	}
    6.11 +
    6.12  }
     7.1 --- a/icfp-solver/src/main/java/ru/bosony/solvers/AbstractSolver.java	Mon Jul 16 13:19:10 2012 +0400
     7.2 +++ b/icfp-solver/src/main/java/ru/bosony/solvers/AbstractSolver.java	Wed Jul 18 09:42:52 2012 +0400
     7.3 @@ -1,8 +1,10 @@
     7.4  package ru.bosony.solvers;
     7.5  
     7.6 -import java.util.HashMap;
     7.7 -import java.util.Map;
     7.8 +import java.text.DecimalFormat;
     7.9 +import java.util.HashSet;
    7.10 +import java.util.Set;
    7.11  
    7.12 +import ru.bosony.model.game.Game;
    7.13  import ru.bosony.model.mine.Mine;
    7.14  
    7.15  /**
    7.16 @@ -12,32 +14,39 @@
    7.17   */
    7.18  public abstract class AbstractSolver {
    7.19  
    7.20 -	protected Mine					mine			= null;
    7.21 -	protected SolverListener		listener		= null;
    7.22 -	protected Map<String, Integer>	routesWithScore	= new HashMap<String, Integer>();
    7.23 -	protected long					attemptsCount	= 0;
    7.24 +	protected Mine				initialMine		= null;
    7.25 +	protected SolverListener	listener		= null;
    7.26 +	protected Set<Game>			games			= new HashSet<Game>();
    7.27 +	protected long				attemptsCount	= 0;
    7.28 +	protected long				startTime		= System.currentTimeMillis();
    7.29  
    7.30  	public AbstractSolver(Mine mine, SolverListener listener) {
    7.31 -		this.mine = mine;
    7.32 +		this.initialMine = mine;
    7.33  		this.listener = listener;
    7.34 -		solve();
    7.35  	}
    7.36  
    7.37 -	protected void addNewRoute(String route, int score) {
    7.38 -		if (!routesWithScore.containsKey(route) && score > getMaxFoundScore()) {
    7.39 -			routesWithScore.put(route, score);
    7.40 -			listener.foundNextRoute(route);
    7.41 +	protected void addNewRoute(Game game) {
    7.42 +		Game maxScoreGame = getMaxFoundScoreGame();
    7.43 +		if (maxScoreGame == null || game.getScore() > maxScoreGame.getScore()
    7.44 +				|| game.getScore() == maxScoreGame.getScore()
    7.45 +				&& game.getRoute().size() < maxScoreGame.getRoute().size()) {
    7.46 +			listener.foundNextRoute(game.getStringRoute());
    7.47 +			// TODO delete
    7.48 +			System.out.println(new DecimalFormat("0.00").format((((System.currentTimeMillis() - startTime) / 1000d)))
    7.49 +					+ " seconds, State = " + game.getState() + ", Score = " + game.getScore() + ", Route("
    7.50 +					+ game.getRoute().size() + ") = " + game.getStringRoute());
    7.51  		}
    7.52 +		games.add(game);
    7.53  	}
    7.54  
    7.55 -	protected int getMaxFoundScore() {
    7.56 -		int maxScore = 0;
    7.57 -		for (int foundScore : routesWithScore.values()) {
    7.58 -			if (foundScore > maxScore)
    7.59 -				maxScore = foundScore;
    7.60 +	protected Game getMaxFoundScoreGame() {
    7.61 +		Game game = null;
    7.62 +		for (Game foundGame : games) {
    7.63 +			if (game == null || foundGame.getScore() > game.getScore())
    7.64 +				game = foundGame;
    7.65  		}
    7.66 -		return maxScore;
    7.67 +		return game;
    7.68  	}
    7.69  
    7.70 -	protected abstract void solve();
    7.71 +	public abstract void solve();
    7.72  }
     8.1 --- a/icfp-solver/src/main/java/ru/bosony/solvers/DijkstraSolver.java	Mon Jul 16 13:19:10 2012 +0400
     8.2 +++ b/icfp-solver/src/main/java/ru/bosony/solvers/DijkstraSolver.java	Wed Jul 18 09:42:52 2012 +0400
     8.3 @@ -1,8 +1,10 @@
     8.4  package ru.bosony.solvers;
     8.5  
     8.6  import java.util.ArrayList;
     8.7 +import java.util.HashMap;
     8.8  import java.util.HashSet;
     8.9  import java.util.List;
    8.10 +import java.util.Map;
    8.11  import java.util.Set;
    8.12  
    8.13  import ru.bosony.graph.CellsLink;
    8.14 @@ -12,6 +14,7 @@
    8.15  import ru.bosony.model.game.GameState;
    8.16  import ru.bosony.model.mine.Cell;
    8.17  import ru.bosony.model.mine.Mine;
    8.18 +import ru.bosony.model.moving.Coordinate;
    8.19  import ru.bosony.model.moving.Movement;
    8.20  import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath;
    8.21  import edu.uci.ics.jung.graph.DirectedSparseGraph;
    8.22 @@ -24,77 +27,197 @@
    8.23   */
    8.24  public class DijkstraSolver extends AbstractSolver {
    8.25  
    8.26 +	protected Map<String, Set<Movement>>	loseMovs							= new HashMap<String, Set<Movement>>();
    8.27 +	protected Map<String, Set<CellsLink>>	loseLinks							= new HashMap<String, Set<CellsLink>>();
    8.28 +	protected Map<String, Set<Coordinate>>	attendedWalkingAroundCoordinates	= new HashMap<String, Set<Coordinate>>();
    8.29 +	protected Map<String, Set<Coordinate>>	noWay								= new HashMap<String, Set<Coordinate>>();
    8.30 +
    8.31  	public DijkstraSolver(Mine mine, SolverListener listener) {
    8.32  		super(mine, listener);
    8.33  	}
    8.34  
    8.35  	@Override
    8.36 -	protected void solve() {
    8.37 +	public void solve() {
    8.38  		while (true) {
    8.39 +			Mine mine = null;
    8.40 +			mine = initialMine.clone();
    8.41  			Game game = new Game(mine);
    8.42  
    8.43  			while (game.getState() == GameState.Game) {
    8.44 -				try {
    8.45 -					Set<Cell> targets = mine.findCells(CellContent.Lambda);
    8.46 +				Cell robotCell = mine.getRobotCell();
    8.47 +				String map = mine.toText();
    8.48 +				String mapWithoutRobot = mine.toTextWithoutRobot();
    8.49 +				if (!loseMovs.containsKey(map)) {
    8.50 +					loseMovs.put(map, new HashSet<Movement>());
    8.51 +				}
    8.52 +				if (!loseLinks.containsKey(map)) {
    8.53 +					loseLinks.put(map, new HashSet<CellsLink>());
    8.54 +				}
    8.55 +				if (!noWay.containsKey(map)) {
    8.56 +					noWay.put(map, new HashSet<Coordinate>());
    8.57 +				}
    8.58 +				if (!attendedWalkingAroundCoordinates.containsKey(mapWithoutRobot)) {
    8.59 +					attendedWalkingAroundCoordinates.put(mapWithoutRobot, new HashSet<Coordinate>());
    8.60 +				}
    8.61 +				attendedWalkingAroundCoordinates.get(mapWithoutRobot).add(robotCell.getCoordinate());
    8.62 +				Set<Cell> targets = new HashSet<Cell>();
    8.63 +				boolean isFreeWay = false;
    8.64 +				for (Cell cell : mine.getAdjacentCells(robotCell)) {
    8.65 +					Movement mov = robotCell.getCoordinate().getNecessaryMovement(cell.getCoordinate());
    8.66 +					isFreeWay |= !attendedWalkingAroundCoordinates.get(mapWithoutRobot).contains(cell.getCoordinate())
    8.67 +							&& !loseMovs.get(map).contains(mov);
    8.68 +				}
    8.69 +				if (isFreeWay) {
    8.70 +					targets.addAll(mine.findCells(CellContent.Lambda));
    8.71  					targets.addAll(mine.findCells(CellContent.HighOrderRock));
    8.72  					if (targets.size() == 0)
    8.73 -						targets = mine.findCells(CellContent.OpenLambdaLift);
    8.74 -					if (targets.size() == 0)
    8.75 -						break;
    8.76 -					Graph<Cell, CellsLink> graph = getDirectedGraph();
    8.77 -					DijkstraShortestPath<Cell, CellsLink> alg = new DijkstraShortestPath<Cell, CellsLink>(graph,
    8.78 -							new CellsLinkTransformer<CellsLink, Double>());
    8.79 -					Cell nextTarget = null;
    8.80 -					List<CellsLink> routeToNextTarget = null;
    8.81 -					double shortestDist = Double.MAX_VALUE;
    8.82 -					for (Cell target : targets) {
    8.83 -						List<CellsLink> route = alg.getPath(mine.getRobotCell(), target);
    8.84 -						Number dist = alg.getDistance(mine.getRobotCell(), target);
    8.85 -						if (dist != null && dist.doubleValue() < shortestDist) {
    8.86 +						targets.addAll(mine.findCells(CellContent.OpenLambdaLift));
    8.87 +					targets.removeAll(mine.getCells(noWay.get(map)));
    8.88 +				} else {
    8.89 +					targets.addAll(mine.findCells(CellContent.Empty));
    8.90 +					targets.addAll(mine.findCells(CellContent.Earth));
    8.91 +					targets.addAll(mine.findCells(CellContent.HuttonsRazor));
    8.92 +					for (CellContent content : CellContent.getTrampolines()) {
    8.93 +						targets.addAll(mine.findCells(content));
    8.94 +					}
    8.95 +					targets.removeAll(mine.getCells(attendedWalkingAroundCoordinates.get(mapWithoutRobot)));
    8.96 +					targets.removeAll(mine.getCells(noWay.get(map)));
    8.97 +					if (targets.size() == 0) {
    8.98 +						game.move(Movement.ABORT);
    8.99 +						continue;
   8.100 +					}
   8.101 +				}
   8.102 +				Graph<Cell, CellsLink> graph = getDirectedGraph(mine);
   8.103 +				DijkstraShortestPath<Cell, CellsLink> alg = new DijkstraShortestPath<Cell, CellsLink>(graph,
   8.104 +						new CellsLinkTransformer<CellsLink, Double>());
   8.105 +				Cell nextTarget = null;
   8.106 +				List<CellsLink> routeToNextTarget = null;
   8.107 +				double shortestDist = Double.MAX_VALUE;
   8.108 +				for (Cell target : targets) {
   8.109 +					List<CellsLink> route = null;
   8.110 +					Number dist = null;
   8.111 +					try {
   8.112 +						route = alg.getPath(mine.getRobotCell(), target);
   8.113 +						dist = alg.getDistance(mine.getRobotCell(), target);
   8.114 +					} catch (IllegalArgumentException e) {
   8.115 +						noWay.get(map).add(target.getCoordinate());
   8.116 +						continue;
   8.117 +					}
   8.118 +					if (dist != null && route != null && route.size() > 0 && dist.doubleValue() < shortestDist) {
   8.119 +						CellsLink firstLink = route.get(0);
   8.120 +						Movement mov = firstLink.getSource().getCoordinate()
   8.121 +								.getNecessaryMovement(firstLink.getTarget().getCoordinate());
   8.122 +						if (!loseMovs.get(map).contains(mov)
   8.123 +								&& !attendedWalkingAroundCoordinates.get(mapWithoutRobot).contains(
   8.124 +										target.getCoordinate())) {
   8.125  							shortestDist = dist.doubleValue();
   8.126  							nextTarget = target;
   8.127  							routeToNextTarget = route;
   8.128  						}
   8.129  					}
   8.130 -					if (nextTarget != null) {
   8.131 -						for (CellsLink link : routeToNextTarget) {
   8.132 -							Movement mov = link.getSource().getCoordinate()
   8.133 -									.getNecessaryMovement(link.getTarget().getCoordinate());
   8.134 -							game.move(mov);
   8.135 -							break;
   8.136 +				}
   8.137 +				if (nextTarget != null) {
   8.138 +					for (CellsLink link : routeToNextTarget) {
   8.139 +						Cell source = link.getSource();
   8.140 +						Cell target = link.getTarget();
   8.141 +						if (isSafeMovement(mine, source, target)) {
   8.142 +							Movement mov = source.getCoordinate().getNecessaryMovement(target.getCoordinate());
   8.143 +							GameState state = game.move(mov);
   8.144 +							if (state == GameState.Lose || state == GameState.Abort) {
   8.145 +								loseMovs.get(map).add(mov);
   8.146 +								loseLinks.get(map).add(link);
   8.147 +							}
   8.148 +						}
   8.149 +						break;
   8.150 +					}
   8.151 +				} else {
   8.152 +					// Walking around
   8.153 +					for (Movement mov : Movement.values()) {
   8.154 +						if (!loseMovs.get(map).contains(mov)) {
   8.155 +							if (mov == Movement.RAZOR && mine.getRazorsCount() > 0) {
   8.156 +								boolean isRazorApplied = false;
   8.157 +								for (Cell cell : mine.getNeighboringCells(robotCell)) {
   8.158 +									isRazorApplied |= cell.getContent() == CellContent.WadlersBeard;
   8.159 +								}
   8.160 +								if (!isRazorApplied)
   8.161 +									continue;
   8.162 +							}
   8.163 +							Cell movCell = null;
   8.164 +							for (Cell cell : mine.getAdjacentCells(robotCell)) {
   8.165 +								if (robotCell.getCoordinate().getNecessaryMovement(cell.getCoordinate()) == mov) {
   8.166 +									if (!attendedWalkingAroundCoordinates.get(mapWithoutRobot).contains(
   8.167 +											cell.getCoordinate())) {
   8.168 +										movCell = cell;
   8.169 +										break;
   8.170 +									}
   8.171 +								}
   8.172 +
   8.173 +							}
   8.174 +							if (mov == Movement.WAIT
   8.175 +									|| mov == Movement.RAZOR
   8.176 +									|| movCell != null
   8.177 +									&& !attendedWalkingAroundCoordinates.get(mapWithoutRobot).contains(
   8.178 +											movCell.getCoordinate())) {
   8.179 +								GameState state = game.move(mov);
   8.180 +								if (movCell != null && mapWithoutRobot.equals(mine.toTextWithoutRobot()))
   8.181 +									attendedWalkingAroundCoordinates.get(mapWithoutRobot).add(movCell.getCoordinate());
   8.182 +								if (state == GameState.Game && map.equals(mine.toText())) {
   8.183 +									loseMovs.get(map).add(mov);
   8.184 +								}
   8.185 +								break;
   8.186 +							}
   8.187  						}
   8.188  					}
   8.189 -				} catch (IllegalArgumentException e) {
   8.190 -					// hmmm...
   8.191  				}
   8.192  			}
   8.193 -			if (game.getState() == GameState.Win) {
   8.194 -				addNewRoute(game.getStringRoute(), game.getScore());
   8.195 -			}
   8.196 +			addNewRoute(game);
   8.197  			attemptsCount++;
   8.198  		}
   8.199  	}
   8.200  
   8.201 -	protected Graph<Cell, CellsLink> getDirectedGraph() {
   8.202 +	protected boolean isSafeMovement(Mine mine, Cell source, Cell target) {
   8.203 +		if (source == null || target == null)
   8.204 +			return false;
   8.205 +		if (source.getContent().getTrampolineTarget() == target.getContent())
   8.206 +			return true;
   8.207 +		Cell upCell = mine.getCell(target.getCoordinate().up());
   8.208 +		if (upCell == null)
   8.209 +			return true;
   8.210 +		Cell upUpCell = mine.getCell(target.getCoordinate().up().up());
   8.211 +		Cell upUpLeftCell = mine.getCell(target.getCoordinate().up().up().left());
   8.212 +		Cell upUpRightCell = mine.getCell(target.getCoordinate().up().up().right());
   8.213 +		if (upCell.getContent() == CellContent.Empty
   8.214 +				&& (upUpCell != null
   8.215 +						&& (upUpCell.getContent() == CellContent.Rock || upUpCell.getContent() == CellContent.HighOrderRock)
   8.216 +						|| upUpLeftCell != null
   8.217 +						&& (upUpLeftCell.getContent() == CellContent.Rock || upUpLeftCell.getContent() == CellContent.HighOrderRock) || upUpRightCell != null
   8.218 +						&& (upUpRightCell.getContent() == CellContent.Rock || upUpRightCell.getContent() == CellContent.HighOrderRock))) {
   8.219 +			return false;
   8.220 +		}
   8.221 +		return true;
   8.222 +	}
   8.223 +
   8.224 +	protected Graph<Cell, CellsLink> getDirectedGraph(Mine mine) {
   8.225  		Graph<Cell, CellsLink> graph = new DirectedSparseGraph<Cell, CellsLink>();
   8.226 -		for (CellsLink link : getCellLinks()) {
   8.227 +		for (CellsLink link : getCellLinks(mine)) {
   8.228  			graph.addEdge(link, link.getSource(), link.getTarget());
   8.229  		}
   8.230  		return graph;
   8.231  	}
   8.232  
   8.233 -	protected List<CellsLink> getCellLinks() {
   8.234 +	protected List<CellsLink> getCellLinks(Mine mine) {
   8.235  		List<CellsLink> links = new ArrayList<CellsLink>();
   8.236  		Cell robotCell = mine.getRobotCell();
   8.237 -		findAllCellLinks(robotCell, links, new HashSet<Cell>());
   8.238 +		findAllCellLinks(mine, robotCell, links, new HashSet<Cell>());
   8.239  		return links;
   8.240  	}
   8.241  
   8.242 -	protected void findAllCellLinks(Cell cell, List<CellsLink> links, Set<Cell> processedCells) {
   8.243 +	protected void findAllCellLinks(Mine mine, Cell cell, List<CellsLink> links, Set<Cell> processedCells) {
   8.244  		if (processedCells.contains(cell))
   8.245  			return;
   8.246  		else
   8.247  			processedCells.add(cell);
   8.248 +		String map = mine.toText();
   8.249  		for (Cell neighboringCell : mine.getAdjacentCells(cell)) {
   8.250  			if (neighboringCell == null)
   8.251  				continue;
   8.252 @@ -102,21 +225,29 @@
   8.253  			if (neighboringContent == CellContent.Earth || neighboringContent == CellContent.Empty
   8.254  					|| neighboringContent == CellContent.HuttonsRazor || neighboringContent == CellContent.Lambda
   8.255  					|| neighboringContent == CellContent.OpenLambdaLift) {
   8.256 -				CellsLink link = new CellsLink(mine, cell, neighboringCell);
   8.257 -				links.add(link);
   8.258 -				findAllCellLinks(neighboringCell, links, processedCells);
   8.259 +				if (isSafeMovement(mine, cell, neighboringCell)) {
   8.260 +					CellsLink link = new CellsLink(mine, cell, neighboringCell);
   8.261 +					if (!loseLinks.get(map).contains(link)) {
   8.262 +						links.add(link);
   8.263 +						findAllCellLinks(mine, neighboringCell, links, processedCells);
   8.264 +					}
   8.265 +				}
   8.266  			} else if (!CellContent.getTargets().contains(cell.getContent())
   8.267  					&& CellContent.getTargets().contains(neighboringContent)) {
   8.268 -				findAllCellLinks(neighboringCell, links, processedCells);
   8.269 +				findAllCellLinks(mine, neighboringCell, links, processedCells);
   8.270  			}
   8.271  		}
   8.272  		if (CellContent.getTrampolines().contains(cell.getContent())) {
   8.273  			for (Cell target : mine.findCells(cell.getContent().getTrampolineTarget())) {
   8.274  				if (target == null)
   8.275  					continue;
   8.276 -				CellsLink link = new CellsLink(mine, cell, target);
   8.277 -				links.add(link);
   8.278 -				findAllCellLinks(target, links, processedCells);
   8.279 +				if (isSafeMovement(mine, cell, target)) {
   8.280 +					CellsLink link = new CellsLink(mine, cell, target);
   8.281 +					if (!loseLinks.get(map).contains(link)) {
   8.282 +						links.add(link);
   8.283 +						findAllCellLinks(mine, target, links, processedCells);
   8.284 +					}
   8.285 +				}
   8.286  			}
   8.287  		}
   8.288  	}
     9.1 --- a/icfp-solver/src/main/java/ru/bosony/solvers/SimpleSolver.java	Mon Jul 16 13:19:10 2012 +0400
     9.2 +++ b/icfp-solver/src/main/java/ru/bosony/solvers/SimpleSolver.java	Wed Jul 18 09:42:52 2012 +0400
     9.3 @@ -14,7 +14,7 @@
     9.4  	}
     9.5  
     9.6  	@Override
     9.7 -	protected void solve() {
     9.8 +	public void solve() {
     9.9  		String route = "";
    9.10  		while (true) {
    9.11  			try {
    10.1 --- a/icfp-solver/src/main/java/ru/bosony/solvers/Solver.java	Mon Jul 16 13:19:10 2012 +0400
    10.2 +++ b/icfp-solver/src/main/java/ru/bosony/solvers/Solver.java	Wed Jul 18 09:42:52 2012 +0400
    10.3 @@ -32,6 +32,7 @@
    10.4  				route = newRoute;
    10.5  			}
    10.6  		});
    10.7 +		solver.solve();
    10.8  	}
    10.9  
   10.10  	public static void main(String[] args) throws IOException, InterruptedException {
    11.1 --- a/icfp-submit/pom.xml	Mon Jul 16 13:19:10 2012 +0400
    11.2 +++ b/icfp-submit/pom.xml	Wed Jul 18 09:42:52 2012 +0400
    11.3 @@ -19,7 +19,7 @@
    11.4  					<descriptors>
    11.5  						<descriptor>src/main/assembly/assembly.xml</descriptor>
    11.6  					</descriptors>
    11.7 -					<finalName>icfp-xxxxxxxx</finalName>
    11.8 +					<finalName>icfp-96518158</finalName>
    11.9  				</configuration>
   11.10  				<executions>
   11.11  					<execution>