public Move bestMove(Board board, Piece piece, Piece nextPiece, int limitHeight){
		
		Rater[] raters = {
				new HeightRater(FACTORS[0]),
				new RowsClearedRater(FACTORS[1]),
				new CohesionRater(FACTORS[2]),
				new GapFactor(FACTORS[3])
		};
		
		EnhancedMove bestMove = null;
		Piece current = piece;

		do {
			
			final int yBound = limitHeight - current.getHeight() + 1;
			final int xBound = board.getWidth() - current.getWidth() +1;
			
			for (int x = 0; x < xBound; x++) {
				int y = board.dropHeight(current, x);
				
				if ((y < yBound) && board.canPlace(current, x, y)) {
					EnhancedMove move = new EnhancedMove(raters, board, current, x, y);
					if(bestMove == null || move.getScore() > bestMove.getScore()){
						bestMove = move;
					}
				}
				
			}
			
			current = current.nextRotation();
			
		} while(current != piece);

		Move finalMove = bestMove != null ? (Move) bestMove : (Move) new EnhancedMove(raters, board, current, 0, 0);
		//System.out.println(bestMove.getScore());
		return finalMove;
	}