anchor.diff:  % New state:
   % Actor PID (as before)
   % Actor type name (as before)
  -% Protocol |-> Conversation ID mapping (as we can be involved in mult protocols)
  +% Protocol <-|-> Conversation ID mapping (as we can be involved in mult protocols)
   % Protocol |-> Role mapping (where Role is the role we can play in a protocol)
   % Monitors (Protocol |-> Monitor Instance)
   % Active protocol
  
positive.code: %  | {next_state,NextStateName,NewStateData,Timeout}
  %  | {next_state,NextStateName,NewStateData,hibernate}
  
  handle_invitation(ConversationID, RoleName, CurrentState, StateData) ->
    AddRoleResult = add_role(RoleName, StateData),
    % Try and add the role.
    % If we succeed, add the role to the conversation_roles list, set the
    % conversation ID, and transition to setup.
  
negative.code: % Returns {ok, NewState} if we can fulfil the role, or either:
  %   * {error, already_fulfilled} --> if we've already fulfilled the role
  %   * {error, cannot_fulfil} --> if this role isn't offered by the actor
  add_role(ProtocolName, RoleName, ConversationID, State) ->
    % Firstly, check to see we're registered for the role
    ProtocolRoleMap = State#conv_state.protocol_role_map,
    ActiveProtocols = State#conv_state.active_protocols,
    RoleFindRes = orddict:find(ProtocolName, ProtocolRoleMap),
    AlreadyFulfilled = bidirectional_map:contains_left(ProtocolName, ActiveProtocols),
    case {RoleFindRes, AlreadyFulfilled} of
      {_, true} -> {error, already_fulfilled};
      {{ok, RoleRes}, false} when RoleRes == RoleName ->
        % We can fulfil it!
        NewActiveProtocols = bidirectional_map:store(ProtocolName, ConversationID),
        {ok, State#conv_state{active_protocols=NewActiveProtocols}};
      Other -> {error, cannot_fulfil}
    end.
  
  
  % We'll have a mixture of synchronous and asynchronous messages.
  