def evaluate_single_puzzle(model_output, puzzle_data, game_type):
    """
    Evaluate a single puzzle solution.

    Processes model output and puzzle data to determine if the model correctly
    understood the puzzle and provided a valid solution.

    Args:
        model_output (str): The raw output from the model
        puzzle_data (dict): Puzzle data including initialization
        game_type (str): Type of puzzle game (e.g., "thermometers", "sudoku")
    Returns:
        dict: Evaluation results including perception_correct, answer_correct, and score
    """
    # Add puzzle directory to path if needed
    curr_dir = os.path.dirname(os.path.abspath(__file__))
    puzzle_dir = os.path.join(curr_dir, "puzzles")
    if puzzle_dir not in sys.path:
        sys.path.append(puzzle_dir)

    # Initialize the appropriate game factory for the puzzle type
    GameFactory = get_game_factory.get_game_factory(game_type)

    init_board = puzzle_data['initialization']

    game_factory = GameFactory(size=4)

    # Game-specific initialization handling
    if game_type == "coloredsudoku":
        colors = puzzle_data.get('colors', None)
        game_factory.current_colors = colors
    elif game_type == "binairo":
        init_board = puzzle_data.get('initialization', None)
    elif game_type == "futoshiki":
        row_inequalities = puzzle_data.get('row_inequalities', None)
        col_inequalities = puzzle_data.get('col_inequalities', None)
        game_factory.current_inequalities = {
            "row": row_inequalities,
            "col": col_inequalities
        }
    elif game_type == "killersudoku":
        cages = puzzle_data.get('cages', None)
        game_factory.cages = cages
    elif game_type == "renzoku":
        hints = puzzle_data.get('hints', None)
        game_factory.hints = hints
    elif game_type == "kakuro":
        sums = puzzle_data.get('sums', None)
        game_factory.current_sums = sums
    elif game_type == "skyscraper":
        clues = puzzle_data.get('initialization', None).get('clues')
        init_board = puzzle_data.get('initialization', None).get('board')  # Special case
        game_factory.clues = clues
    elif game_type == "thermometers":
        clues = puzzle_data.get('initialization', None).get('clues')
        game_factory.clues = clues
        init_board = puzzle_data.get('initialization', None).get('board')
    elif game_type == "treesandtents":
        clues = puzzle_data.get('clues', None)
        game_factory.clues = clues
        init_board = puzzle_data.get('initialization', None)
    elif game_type == "starbattle":
        init_board = puzzle_data.get('initialization', None)
        game_factory.regions = puzzle_data.get('regions', None)
    elif game_type == "hitori":
        init_board = puzzle_data.get('initialization').get('numbers', None)
        game_factory.numbers = puzzle_data.get('initialization', None).get('numbers')
        game_factory.additional_board = puzzle_data.get('initialization', None).get('board')
    elif game_type == "aquarium":
        init_board = puzzle_data.get('initialization', None).get('board')
        game_factory.clues = puzzle_data.get('initialization', None).get('clues', None)
    elif game_type == "kakurasu":
        init_board = puzzle_data.get('initialization', None).get('board')
        game_factory.clues = puzzle_data.get('initialization', None).get('clues', None)
    elif game_type == "oddevensudoku":
        game_factory.cell_types = puzzle_data.get('cell_types')
        init_board = puzzle_data.get('initialization', None)
    elif game_type == "battleships":
        init_board = puzzle_data.get('initialization', None)
        game_factory.hints = puzzle_data.get('hints', None)
    elif game_type == "jigsawsudoku":
        init_board = puzzle_data.get('initialization', None)
    elif game_type == "nonogram":
        init_board = puzzle_data.get('initialization', None)
        game_factory.hints = puzzle_data.get('hints', None)
    elif game_type == "lightup":
        init_board = puzzle_data.get('initialization', None)
        game_factory.wall_numbers = puzzle_data.get('wall_numbers', None)
    # Set grid size
    global GRID_SIZE
    GRID_SIZE = len(init_board) if GRID_SIZE is None else GRID_SIZE

    # Extract model's perception and answer from its output
    thoughts, answer = extract_perception_and_answer(model_output)
    # Early return if parsing failed
    if thoughts is None or answer is None:
        return {
            "perception_correct": False,
            "answer_correct": False,
            "number_of_samples": 1
        }

    # Game-specific preprocessing
    try:
        if game_type == "starbattle":
            for i in range(len(thoughts)):
                for j in range(len(thoughts[i])):
                    if thoughts[i][j] == "*":
                        thoughts[i][j] = "0"
    except Exception as e:
        print(f"starbattle: Error converting thoughts to 0: {e}")
    try:
        if game_type == "killersudoku":
            answer = [[int(cell) for cell in row] for row in answer]
    except Exception as e:
        answer = None

    # Special handling for trees and tents
    if game_type == "treesandtents":
        # Convert shorthand symbols to standard format
        for i in range(len(thoughts)):
            for j in range(len(thoughts[i])):
                if thoughts[i][j] == 't':
                    thoughts[i][j] = 'tt'
                elif thoughts[i][j] == 'r':
                    thoughts[i][j] = 'tr'
        for i in range(len(answer)):
            for j in range(len(answer[i])):
                if answer[i][j] == 't':
                    answer[i][j] = 'tt'
                elif answer[i][j] == 'r':
                    answer[i][j] = 'tr'

    # Check perception and answer
    perception_correct = check_perception(thoughts, init_board, game_type)
    answer_correct = check_answer(answer, init_board, game_factory) if perception_correct else False

    return {
        "perception_correct": perception_correct,
        "answer_correct": answer_correct,
        "number_of_samples": 1
    }

    Evaluate a single puzzle solution.

    Processes model output and puzzle data to determine if the model correctly
    understood the puzzle and provided a valid solution.

    Args:
        model_output (str): The raw output from the model
        puzzle_data (dict): Puzzle data including initialization
        game_type (str): Type of puzzle game (e.g., "thermometers", "sudoku")
    Returns:
        dict: Evaluation results including perception_correct, answer_correct, and score
    
vlmeval/dataset/utils/vgrpbench/score.py