anchor.diff:      return s / (cell.y + 1);
     }
   
  -  num evaluate(Board board, List<String> moves) {
  +  num evaluate(List<Board> boards, List<String> moves) {
       num score = 0;
  -    board.rows.forEach((row) {
  +    boards.last.rows.forEach((row) {
         row.forEach((cell) {
  -        score += _edgeCellScore(cell, board);
  +        score += _edgeCellScore(cell, boards.last);
         });
       });
       return score;
  
positive.code:     return changed;
    }
  
    bool _collapseCells(Iterable<List<Cell>> cellLists) {
      return cellLists.fold(false, (a, cells) => _collapse(cells) || a);
    }
  
    bool left() {
      return _collapseCells(rows);
    }
  
    bool right() {
      return _collapseCells(rows.map((row) => row.reversed.toList()));
    }
  
    bool up() {
      return _collapseCells(columns);
    }
  
    bool down() {
      return _collapseCells(columns.map((column) => column.reversed.toList()));
    }
  
    bool doDirection(String direction) {
      switch (direction) {
        case "up":
          return up();
        case "down":
          return down();
        case "left":
          return left();
        case "right":
          return right();
        default:
          throw "unknown direction: $direction";
      }
  
negative.code:         break;
        case 40:
          down();
          break;
  
        // wasd
        case 65:
          doDirectionOnlyNonEmpty("left");
          break;
        case 87:
          doDirectionOnlyNonEmpty("up");
          break;
        case 68:
          doDirectionOnlyNonEmpty("right");
          break;
        case 83:
          doDirectionOnlyNonEmpty("down");
          break;
      }
    }
  