def outcome_summary_fn(
    # `binary_joint_action` should be type Mapping[str, bool] (ie bool not int).
    joint_action: Mapping[str, str],
    rewards: Mapping[str, float],
    relational_matrix: Mapping[str, Mapping[str, float]],
    player_multipliers: Mapping[str, Mapping[str, float]],
    option_multipliers: Mapping[str, float],
) -> Mapping[str, str]:
  """Function of joint actions, rewards, relational matrix and player multipliers which returns an outcome description message for each player.

  Args:
    joint_action: A mapping from player name to their chosen action.
    rewards: A mapping from player name to their reward.
    relational_matrix: A matrix of relationships between players. The entry
      [i][j] specifies the value for player i of making the same choice as
      player j. Matrix is not assumed to be symmetric or having a particular
      value on the diagonal. If `None`, all players are assumed to have value of
      1, including self relationships (diagonal).
    player_multipliers: A mapping from player name to a mapping from action to
      their multiplier.
    option_multipliers: A mapping from option (pub) to their multiplier.

  Returns:
    A mapping from player name to their outcome description message.
  """

  player_names = list(joint_action.keys())

  if len(relational_matrix) != len(player_names):
    raise ValueError(
        'Relationship matrix must have the same length as the number of'
        ' acting players.'
    )
  for _, row in relational_matrix.items():
    if len(row) != len(player_names):
      raise ValueError(
          'Relationship matrix rows must have the same length as the number'
          ' of acting players.'
      )

  players_by_choice = {}
  choice_by_player = {}
  for name, choice in joint_action.items():
    if choice not in players_by_choice:
      players_by_choice[choice] = []
    players_by_choice[choice].append(name)
    choice_by_player[name] = choice

  summary_of_attendance = ''

  for choice in players_by_choice:
    if players_by_choice[choice]:
      all_players_with_this_choice = ', '.join(players_by_choice[choice])
      summary_of_attendance += (
          f'{all_players_with_this_choice} went to {choice}. '
      )

  results = {}

  for player in player_names:
    player_action = joint_action[player]
    same_choice_by_relation = 0
    score = rewards[player]
    was_pub_closed = player_action in option_multipliers and (
        option_multipliers[player_action] == 0.0
    )

    if score > 0.9:
      enjoyment = f'Overall, {player} had a great time watching the game!'
    elif score > 0.5:
      enjoyment = f'Overall, {player} had an ok time watching the game.'
    elif score < 1e-8:
      enjoyment = f'Overall, {player} had the worst time ever.'
    else:
      enjoyment = f'Overall, {player} had a bad time watching the game.'

    for other_player in player_names:
      if player_action == joint_action[other_player] and player != other_player:
        same_choice_by_relation += relational_matrix[player][other_player]
    max_reward_possible = (
        sum(max(0, r) for r in relational_matrix[player].values())
        - relational_matrix[player][player]
    )
    if same_choice_by_relation == max_reward_possible:
      friends_attendance = (
          f"All of {player}'s friends went to the same"
          " pub! It couldn't have been better."
      )
    elif same_choice_by_relation > 0.5 * max_reward_possible:
      friends_attendance = (
          'It could have been better if more friends showed up.'
      )
    elif same_choice_by_relation > 0.0:
      friends_attendance = (
          f'{player} would have'
          ' been a lot happier if more of their friends had shown up.'
      )
    else:
      friends_attendance = (
          f"None of {player}'s friends showed up, it couldn't have been worse!"
      )

    if was_pub_closed:
      choice_of_pub = f'{player} went to a closed pub.'
    elif player_multipliers[player][choice_by_player[player]] > 0.99:
      choice_of_pub = f'{player} watched the game at their favourite pub.'
    else:
      choice_of_pub = (
          f'{player} watched the game at the pub that is not their favourite.'
      )
    results[player] = (
        f'{summary_of_attendance} {choice_of_pub} {friends_attendance} {enjoyment}'
    )

  print(summary_of_attendance)
  return results
Function of joint actions, rewards, relational matrix and player multipliers which returns an outcome description message for each player.

  Args:
    joint_action: A mapping from player name to their chosen action.
    rewards: A mapping from player name to their reward.
    relational_matrix: A matrix of relationships between players. The entry
      [i][j] specifies the value for player i of making the same choice as
      player j. Matrix is not assumed to be symmetric or having a particular
      value on the diagonal. If `None`, all players are assumed to have value of
      1, including self relationships (diagonal).
    player_multipliers: A mapping from player name to a mapping from action to
      their multiplier.
    option_multipliers: A mapping from option (pub) to their multiplier.

  Returns:
    A mapping from player name to their outcome description message.
  
examples/deprecated/modular/environment/pub_coordination.py