def run_scenes(
    environment: game_master.GameMaster,
    scenes: Sequence[scene_lib.SceneSpec],
    players: Sequence[deprecated_agent.BasicAgent | entity_agent.EntityAgent],
    clock: game_clock.GameClock,
    verbose: bool = False,
    compute_metrics: Mapping[str, logging_lib.Metric] | None = None,
) -> None:
  """Run a sequence of scenes.

  Args:
    environment: the game master
    scenes: sequence of scene configurations
    players: full list of players (a subset may participate in each scene)
    clock: the game clock which may be advanced between scenes
    verbose: if true then print intermediate outputs
    compute_metrics: Optionally, a function to compute metrics.
  """
  players_by_name = {player.name: player for player in players}
  if len(players_by_name) != len(players):
    raise ValueError('Duplicate player names')

  for scene_idx, scene in enumerate(scenes):
    if scene.scene_type.override_game_master:
      this_scene_environment = scene.scene_type.override_game_master
      this_scene_game_master_memory = this_scene_environment.get_memory()
    else:
      this_scene_environment = environment
      this_scene_game_master_memory = environment.get_memory()

    participant_names = [config.name for config in scene.participant_configs]
    if verbose:
      print(f'\n\n    Scene {scene_idx}    Participants: {participant_names}\n')
    participants = [players_by_name[name] for name in participant_names]

    # Prepare to run the scene
    clock.set(scene.start_time)

    all_premises = ''
    for participant in participants:
      premise_messages = _get_interscene_messages(
          key='premise',
          agent_name=participant.name,  # pytype: disable=attribute-error
          scene_type_spec=scene.scene_type,
      )
      for message in premise_messages:
        all_premises += f'{participant.name} -- premise: {message}      \n'  # pytype: disable=attribute-error
        if verbose:
          print(f'{participant.name} -- premise: {message}')  # pytype: disable=attribute-error
        participant.observe(message)  # pytype: disable=attribute-error
        this_scene_game_master_memory.add(message)

    # Add the scene and its premise to the history
    scene_update_log_entry = game_master.LogEntry(
        date=clock.now(),
        event_statement=all_premises,
        summary=f'Scene {scene_idx} --- Participants: {participant_names}',
    )
    environment.insert_history(log_entry=scene_update_log_entry)

    # Run the scene
    for _ in range(scene.num_rounds):
      this_scene_game_master_memory.add(f'[scene type] {scene.scene_type.name}')
      this_scene_environment.step(
          active_players=participants,
          action_spec_override=scene.scene_type.action_spec,
      )
      if this_scene_environment.terminate_episode():
        break

    # Conclude the scene
    for participant in participants:
      conclusion_messages = _get_interscene_messages(
          key='conclusion',
          agent_name=participant.name,  # pytype: disable=attribute-error
          scene_type_spec=scene.scene_type,
      )
      for message in conclusion_messages:
        if verbose:
          print(f'{participant.name} -- conclusion: {message}')  # pytype: disable=attribute-error
        participant.observe(message)  # pytype: disable=attribute-error
        this_scene_game_master_memory.add(message)

    # Branch off a metric scene if applicable
    if scene.scene_type.save_after_each_scene:
      serialized_agents = {}
      for participant in participants:
        serialized_agents = {}
        json_representation = json_lib.save_to_json(participant)
        serialized_agents[participant.name] = json_representation  # pytype: disable=attribute-error

      if compute_metrics is not None:
        compute_metrics(serialized_agents)
Run a sequence of scenes.

  Args:
    environment: the game master
    scenes: sequence of scene configurations
    players: full list of players (a subset may participate in each scene)
    clock: the game clock which may be advanced between scenes
    verbose: if true then print intermediate outputs
    compute_metrics: Optionally, a function to compute metrics.
  
concordia/environment/deprecated/scenes/runner.py