anchor.diff:    }
   }
   
  +class EdgeStrategy extends EvaluateStrategy {
  +  const EdgeStrategy(int searchDepth): super("edge $searchDepth", searchDepth,
  +      true);
  +
  +  num _cellScore(Cell cell) {
  +    if (cell.empty) {
  +      return 0;
  +    }
  +    num x = log(cell.val) / log(2);
  +    return x * x;
  +  }
  +
  +  num _edgeCellScore(Cell cell, Board board) {
  +    num s = _cellScore(cell);
  +
  +    if (cell.y == 0) {
  +      s *= s;
  +      if (cell.x == 0) {
  +        s *= s;
  +      }
  +    }
  +    return s / (cell.y + 1);
  +  }
  +
  +  num evaluate(Board board, List<String> moves) {
  +    num score = 0;
  +    board.rows.forEach((row) {
  +      row.forEach((cell) {
  +        score += _edgeCellScore(cell, board);
  +      });
  +    });
  +    return score;
  +  }
  +}
  +
   
   @NgController(selector: "[main-ctrl]", publishAs: "c")
   class AppController {
  
positive.code:   num _search(Board board, List<String> previousMoves) {
      if (previousMoves.length >= searchDepth) {
        return evaluate(board, previousMoves);
      }
  
      num bestScore = null;
      Board.DIRECTIONS.forEach((String dir) {
        Board tmp = new Board.copy(board);
        if (tmp.doDirection(dir)) {
  
          num score = _search(tmp, new List.from(previousMoves)..add(dir));
          if (bestScore == null || score > bestScore) {
            bestScore = score;
          }
  
negative.code:   Timer currentTimer;
  
    final List<Strategy> strategies = const [const RandomStrategy(),
        const UpLeftRightDownStrategy(), const GreedyStrategy(1), const GreedyStrategy(2
        ), const AntiGreedyStrategy(1), const AntiGreedyStrategy(2),
        const GreedyDownStrategy(1), const GreedyDownStrategy(2),
        const GreedyDownStrategy(3), const GreedyDownStrategy(4), const EdgeStrategy(1),
        const EdgeStrategy(2), const EdgeStrategy(3), const EdgeStrategy(4), const EdgeStrategy(5)];
  
    Strategy strategy;
  
  