def METHOD_NAME(env_fn, num_games: int = 100, render_mode: str | None = None, **env_kwargs):
    # Evaluate a trained agent vs a random agent
    env = env_fn.env(render_mode=render_mode, **env_kwargs)
    # Pre-process using SuperSuit (color reduction, resizing and frame stacking)
    env = ss.color_reduction_v0(env, mode="B")
    env = ss.resize_v1(env, x_size=84, y_size=84)
    env = ss.frame_stack_v1(env, 3)
    print(
        f"\nStarting evaluation on {str(env.metadata['name'])} (num_games={num_games}, render_mode={render_mode})"
    )
    try:
        latest_policy = max(
            glob.glob(f"{env.metadata['name']}*.zip"), key=os.path.getctime
        )
    except ValueError:
        print("Policy not found.")
        exit(0)
    model = PPO.load(latest_policy)
    rewards = {agent: 0 for agent in env.possible_agents}
    # Note: We train using the Parallel API but evaluate using the AEC API
    # SB3 models are designed for single-agent settings, we get around this by using he same model for every agent
    for i in range(num_games):
        env.reset(seed=i)
        for agent in env.agent_iter():
            obs, reward, termination, truncation, info = env.last()
            if termination or truncation:
                for agent in env.agents:
                    rewards[agent] += env.rewards[agent]
                break
            else:
                act = model.predict(obs, deterministic=True)[0]
            env.step(act)
    # TODO: fix SuperSuit bug where closing the vector env can sometimes crash (disabled for CI)
    env.close()
    avg_reward = sum(rewards.values()) / len(rewards.values())
    print(f"Avg reward: {avg_reward}")
    return avg_reward