Index: protocol/src/main/java/geniusweb/protocol/CurrentNegoState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/CurrentNegoState.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/CurrentNegoState.java	(revision 34)
@@ -14,6 +14,41 @@
 	}
 
+	public CurrentNegoState(NegoState state, Long now) {
+		super(now);
+		this.state = state;
+	}
+
 	public NegoState getState() {
 		return state;
 	}
+
+	@Override
+	public String toString() {
+		return "CurrentNegoState[" + getTime() + "," + state + "]";
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = super.hashCode();
+		result = prime * result + ((state == null) ? 0 : state.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (!super.equals(obj))
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		CurrentNegoState other = (CurrentNegoState) obj;
+		if (state == null) {
+			if (other.state != null)
+				return false;
+		} else if (!state.equals(other.state))
+			return false;
+		return true;
+	}
 }
Index: protocol/src/main/java/geniusweb/protocol/ProtocolException.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/ProtocolException.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/ProtocolException.java	(revision 34)
@@ -14,5 +14,7 @@
 	 * @param message the error message
 	 * @param party   offending party, either the {@link PartyId} or a
-	 *                {@link PartyRef}
+	 *                {@link PartyRef}. In exceptional cases this can be null,
+	 *                eg if it can not be determined which party failed. Null
+	 *                should be avoided if possible at all.
 	 */
 	public ProtocolException(String message, PartyId party) {
@@ -29,5 +31,7 @@
 	 * 
 	 * @param message the error message
-	 * @param party   offending {@link PartyId}
+	 * @param party   offending {@link PartyId}. In exceptional cases this can
+	 *                be null, eg if it can not be determined which party
+	 *                failed. Null should be avoided if possible at all.
 	 * @param e       the cause of the error
 	 */
@@ -39,5 +43,6 @@
 	/**
 	 * 
-	 * @return offending party, either the {@link PartyId} or a {@link PartyRef}
+	 * @return offending party, either the {@link PartyId} or a
+	 *         {@link PartyRef}. In exceptional cases this can be null.
 	 */
 	public PartyId getParty() {
Index: protocol/src/main/java/geniusweb/protocol/session/DefaultSessionState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/DefaultSessionState.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/DefaultSessionState.java	(revision 34)
@@ -65,15 +65,15 @@
 			this.partyprofiles = Collections.emptyMap();
 		} else {
-			this.partyprofiles = partyprofiles;
+			this.partyprofiles = new HashMap<>(partyprofiles);
 		}
 		if (conns == null) {
 			this.connections = Collections.emptyList();
 		} else {
-			this.connections = conns;
+			this.connections = new LinkedList<>(conns);
 		}
 		if (actions == null) {
 			this.actions = new LinkedList<>();
 		} else {
-			this.actions = actions;
+			this.actions = new LinkedList<>(actions);
 		}
 
@@ -115,5 +115,5 @@
 	 */
 	public List<PartyId> getConnections() {
-		return connections;
+		return Collections.unmodifiableList(connections);
 	}
 
@@ -124,5 +124,5 @@
 	 */
 	public Map<PartyId, PartyWithProfile> getPartyProfiles() {
-		return partyprofiles;
+		return Collections.unmodifiableMap(partyprofiles);
 	}
 
Index: protocol/src/main/java/geniusweb/protocol/session/SessionResult.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/SessionResult.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/SessionResult.java	(revision 34)
@@ -2,4 +2,5 @@
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 
@@ -49,7 +50,7 @@
 			@JsonProperty("penalties") Map<PartyId, Double> penalties,
 			@JsonProperty("error") Throwable error) {
-		this.participants = participants;
+		this.participants = new HashMap<>(participants);
 		this.agreements = agreements;
-		this.penalties = penalties;
+		this.penalties = new HashMap<>(penalties);
 		this.error = error;
 	}
Index: protocol/src/main/java/geniusweb/protocol/session/SessionState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/SessionState.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/SessionState.java	(revision 34)
@@ -60,7 +60,6 @@
 	/**
 	 * 
-	 * @return the current standing agreement, or null if there is no agreement
-	 *         at this point. An agreement does not necessarily mean
-	 *         {@link #isFinal(long)}.
+	 * @return the current standing {@link Agreements}. An agreement does not
+	 *         necessarily mean {@link #isFinal(long)}.
 	 */
 	Agreements getAgreements();
Index: protocol/src/main/java/geniusweb/protocol/session/TeamInfo.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/TeamInfo.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/TeamInfo.java	(revision 34)
@@ -49,5 +49,5 @@
 	 *         teams combined.
 	 */
-	public List<PartyWithProfile> getAllParties() {
+	public List<PartyWithProfile> getParties() {
 		return Collections.unmodifiableList(parties);
 	}
Index: protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java	(revision 34)
@@ -70,5 +70,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
Index: protocol/src/main/java/geniusweb/protocol/session/learn/LearnSettings.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/learn/LearnSettings.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/learn/LearnSettings.java	(revision 34)
@@ -119,5 +119,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
Index: protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java	(revision 34)
@@ -74,5 +74,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
@@ -155,5 +155,5 @@
 				throw new IllegalArgumentException(
 						"All teams must be size 1 but found " + team);
-			PartyWithProfile party = team.getAllParties().get(0);
+			PartyWithProfile party = team.getParties().get(0);
 			Object power = party.getParty().getParameters().get("power");
 			if (power != null) {
Index: protocol/src/main/java/geniusweb/protocol/session/mopac2/MOPAC2Settings.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/mopac2/MOPAC2Settings.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/mopac2/MOPAC2Settings.java	(revision 34)
@@ -75,5 +75,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
@@ -157,5 +157,5 @@
 				throw new IllegalArgumentException(
 						"All teams must be size 1 but found " + team);
-			PartyWithProfile party = team.getAllParties().get(0);
+			PartyWithProfile party = team.getParties().get(0);
 			Object power = party.getParty().getParameters().get("power");
 			if (power != null) {
Index: protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java	(revision 34)
@@ -326,5 +326,6 @@
 	 * 
 	 * @param message The message to attach to the error
-	 * @param party   the party where the error occured
+	 * @param party   the party where the error occured. Can be null in
+	 *                exceptional cases.
 	 * @param e       the exception that occured.
 	 */
@@ -337,5 +338,6 @@
 			setState(state.with(new ProtocolException(message, party, e)));
 		}
-		setState(state.withoutParty(party));
+		if (party != null)
+			setState(state.withoutParty(party));
 		log.log(Level.WARNING, "SAOP protocol intercepted error due to party "
 				+ party + ":" + message, e);
Index: protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java	(revision 34)
@@ -67,5 +67,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
Index: protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java	(revision 34)
@@ -5,4 +5,7 @@
 import java.util.List;
 import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
 import geniusweb.actions.Accept;
@@ -28,5 +31,5 @@
 	 * 
 	 * @param actions       the actions done by the parties
-	 * @param conns         the existing party connections. If null, default
+	 * @param connections   the existing party connections. If null, default
 	 *                      empty list is used. Can be less than 2 parties in
 	 *                      the first phases of the setup or after parties
@@ -36,11 +39,15 @@
 	 * @param partyprofiles map with the {@link PartyWithProfile} for connected
 	 *                      parties. null is equivalent to an empty map.
-	 * @param e             the {@link ProtocolException}, or null if none
+	 * @param error         the {@link ProtocolException}, or null if none
 	 *                      occurred.
 	 */
-	public SAOPState(List<Action> actions, List<PartyId> conns,
-			Progress progress, SAOPSettings settings,
-			Map<PartyId, PartyWithProfile> partyprofiles, ProtocolException e) {
-		super(actions, conns, progress, settings, partyprofiles, e);
+	@JsonCreator
+	public SAOPState(@JsonProperty("actions") List<Action> actions,
+			@JsonProperty("connections") List<PartyId> connections,
+			@JsonProperty("progress") Progress progress,
+			@JsonProperty("settings") SAOPSettings settings,
+			@JsonProperty("partyprofiles") Map<PartyId, PartyWithProfile> partyprofiles,
+			@JsonProperty("error") ProtocolException error) {
+		super(actions, connections, progress, settings, partyprofiles, error);
 	}
 
Index: protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 34)
@@ -166,5 +166,5 @@
 			throws InterruptedException, IOException {
 		List<PartyWithProfile> participants = state.getSettings().getTeams()
-				.stream().map(team -> team.getAllParties())
+				.stream().map(team -> team.getParties())
 				.flatMap(List::stream).collect(Collectors.toList());
 		List<Reference> parties = participants.stream()
Index: protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPSettings.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPSettings.java	(revision 33)
+++ protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPSettings.java	(revision 34)
@@ -46,6 +46,6 @@
 				throw new IllegalArgumentException(
 						"Team must be size 2 but found " + team);
-			allParties.add(team.getAllParties().get(SHAOP));
-			allParties.add(team.getAllParties().get(COB));
+			allParties.add(team.getParties().get(SHAOP));
+			allParties.add(team.getParties().get(COB));
 		}
 	}
@@ -82,5 +82,5 @@
 	@Override
 	public List<PartyWithProfile> getAllParties() {
-		return participants.stream().map(team -> team.getAllParties())
+		return participants.stream().map(team -> team.getParties())
 				.flatMap(Collection::stream).collect(Collectors.toList());
 	}
