Index: protocol/src/main/java/geniusweb/protocol/session/shaop/BareSHAOPState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/shaop/BareSHAOPState.java	(revision 16)
+++ protocol/src/main/java/geniusweb/protocol/session/shaop/BareSHAOPState.java	(revision 18)
@@ -22,4 +22,5 @@
  */
 public abstract class BareSHAOPState implements SessionState {
+
 	protected final List<Action> actions;
 
@@ -167,3 +168,65 @@
 	}
 
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((actions == null) ? 0 : actions.hashCode());
+		result = prime * result + ((error == null) ? 0 : error.hashCode());
+		result = prime * result
+				+ ((partyNumbers == null) ? 0 : partyNumbers.hashCode());
+		result = prime * result
+				+ ((progress == null) ? 0 : progress.hashCode());
+		result = prime * result
+				+ ((settings == null) ? 0 : settings.hashCode());
+		result = prime * result + teamNr;
+		result = prime * result
+				+ ((totalSpent == null) ? 0 : totalSpent.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		BareSHAOPState other = (BareSHAOPState) obj;
+		if (actions == null) {
+			if (other.actions != null)
+				return false;
+		} else if (!actions.equals(other.actions))
+			return false;
+		if (error == null) {
+			if (other.error != null)
+				return false;
+		} else if (!error.equals(other.error))
+			return false;
+		if (partyNumbers == null) {
+			if (other.partyNumbers != null)
+				return false;
+		} else if (!partyNumbers.equals(other.partyNumbers))
+			return false;
+		if (progress == null) {
+			if (other.progress != null)
+				return false;
+		} else if (!progress.equals(other.progress))
+			return false;
+		if (settings == null) {
+			if (other.settings != null)
+				return false;
+		} else if (!settings.equals(other.settings))
+			return false;
+		if (teamNr != other.teamNr)
+			return false;
+		if (totalSpent == null) {
+			if (other.totalSpent != null)
+				return false;
+		} else if (!totalSpent.equals(other.totalSpent))
+			return false;
+		return true;
+	}
+
 }
Index: protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 16)
+++ protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 18)
@@ -50,5 +50,6 @@
  * party of this type can execute a RequestComparison(userid) action, which
  * increases the total bother with the elicitationcost. The call results in the
- * associated COB party to execute a Comparison action.
+ * associated COB party to execute a Comparison action. If this parameter is not
+ * set, the {@link SHAOPState#DEFAULT_ELICITATATION_COST} is used.
  * <p>
  * A SHAOP party keeps the turn until it does an action that is not a
@@ -58,7 +59,7 @@
  * <p>
  * The Comparison/ComparisonTest actions are private between the
- * {@link ShaopTeam}. A SHAOP party can do a {@link ElicitComparison} action
- * at any time. These actions are completely transparent to the other parties
- * and are not dependent or influencing the normal turn taking.
+ * {@link ShaopTeam}. A SHAOP party can do a {@link ElicitComparison} action at
+ * any time. These actions are completely transparent to the other parties and
+ * are not dependent or influencing the normal turn taking.
  */
 public class SHAOP extends DefaultListenable<ProtocolEvent>
@@ -162,6 +163,6 @@
 			ProtocolToPartyConnFactory connectionfactory)
 			throws InterruptedException, IOException {
-		List<PartyWithProfile> participants = state.getSettings()
-				.getTeams().stream().map(team -> team.getAllParties())
+		List<PartyWithProfile> participants = state.getSettings().getTeams()
+				.stream().map(team -> team.getAllParties())
 				.flatMap(List::stream).collect(Collectors.toList());
 		List<Reference> parties = participants.stream()
Index: protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java	(revision 16)
+++ protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java	(revision 18)
@@ -30,5 +30,5 @@
 public class SHAOPState extends BareSHAOPState {
 
-	private static final double DEFAULT_ELICITATATION_COST = 0.1d;
+	public static final double DEFAULT_ELICITATATION_COST = 0.01d;
 
 	/**
@@ -277,6 +277,9 @@
 			// shaop party does real action, move to next SHAOP party.
 			newTeam = (teamNr + 1) % settings.getTeams().size();
-			if (newprogress instanceof ProgressRounds) {
+			// check if we completed a round
+			if (newprogress instanceof ProgressRounds && newTeam == 0) {
 				newprogress = ((ProgressRounds) newprogress).advance();
+				System.out.println("Progressed rounds " + newprogress
+						+ " after action " + action + "");
 			}
 		}
Index: protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java	(revision 16)
+++ protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java	(revision 18)
@@ -1,6 +1,8 @@
 package geniusweb.protocol.tournament.allpermutations;
 
+import java.math.BigInteger;
 import java.util.Collections;
 import java.util.List;
+import java.util.function.BiFunction;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
@@ -17,5 +19,4 @@
 import geniusweb.references.PartyWithProfile;
 import tudelft.utilities.immutablelist.FixedList;
-import tudelft.utilities.immutablelist.Function2;
 import tudelft.utilities.immutablelist.ImmutableList;
 import tudelft.utilities.immutablelist.MapList;
@@ -25,4 +26,5 @@
 import tudelft.utilities.immutablelist.PermutationsWithReturn;
 import tudelft.utilities.immutablelist.PermutationsWithoutReturn;
+import tudelft.utilities.immutablelist.Repeat;
 import tudelft.utilities.immutablelist.Tuple;
 import tudelft.utilities.immutablelist.Tuples;
@@ -56,5 +58,4 @@
 public class AllPermutationsSettings implements TournamentSettings {
 
-	public static final String COB_PARTY = "comparebids-1.2.0";
 	private final List<Team> teams;
 	private final List<ProfileList> profileslists;
@@ -62,22 +63,27 @@
 	private final int teamsPerSession;
 	private final SessionSettings sessionsettings;
+	private final int numberTournaments;
 
 	/**
 	 * 
-	 * @param teams           a list of {@link Team}s. Must contain at least
-	 *                        {@link #teamsPerSession} elements. The <teamsize>
-	 *                        must match the protocol: (SAOP:1, SHAOP:2)
-	 * @param reuseTeams      if true, we use PermutationsWithReturn, if false
-	 *                        we use PermutationsWithoutReturn to create the
-	 *                        teams.
-	 * @param plists          list of available {@link ProfileList}s to be
-	 *                        permutated over the teams. Each
-	 *                        {@link ProfileList} must contain <teamsize>
-	 *                        elements.
-	 * @param teamsPerSession number of parties per session, must be at least 2.
-	 * @param sesettings      The generic {@link SessionSetting}.
-	 *                        {@link SessionSettings#with(PartyWithProfile)}
-	 *                        will be used to add the required
-	 *                        {@link PartyWithProfile}s
+	 * @param teams             a list of {@link Team}s. Must contain at least
+	 *                          {@link #teamsPerSession} elements. The
+	 *                          <teamsize> must match the protocol: (SAOP:1,
+	 *                          SHAOP:2)
+	 * @param reuseTeams        if true, we use PermutationsWithReturn, if false
+	 *                          we use PermutationsWithoutReturn to create the
+	 *                          teams.
+	 * @param plists            list of available {@link ProfileList}s to be
+	 *                          permutated over the teams. Each
+	 *                          {@link ProfileList} must contain <teamsize>
+	 *                          elements.
+	 * @param teamsPerSession   number of parties per session, must be at least
+	 *                          2.
+	 * @param sesettings        The generic {@link SessionSetting}.
+	 *                          {@link SessionSettings#with(PartyWithProfile)}
+	 *                          will be used to add the required
+	 *                          {@link PartyWithProfile}s
+	 * @param numberTournaments the number of times the tournament should be
+	 *                          run.
 	 */
 	@JsonCreator
@@ -86,5 +92,6 @@
 			@JsonProperty("reuseTeams") boolean reuseTeams,
 			@JsonProperty("teamsPerSession") int teamsPerSession,
-			@JsonProperty("sessionsettings") SessionSettings sesettings) {
+			@JsonProperty("sessionsettings") SessionSettings sesettings,
+			@JsonProperty("numberTournaments") int nTournaments) {
 		if (teamsPerSession < 2)
 			throw new IllegalArgumentException("teamsPerSession must be >=2");
@@ -96,4 +103,6 @@
 					"profileslist must contain at least " + teamsPerSession
 							+ " ProfileList's");
+		if (nTournaments <= 0)
+			throw new IllegalArgumentException("nTournaments must be >0");
 		int teamsize;
 		if (sesettings instanceof SAOPSettings)
@@ -117,5 +126,4 @@
 								+ teamsize + " but found "
 								+ profile.getProfiles().size());
-
 			}
 		}
@@ -125,4 +133,5 @@
 		this.profileslists = plists;
 		this.sessionsettings = sesettings;
+		this.numberTournaments = nTournaments;
 	}
 
@@ -159,5 +168,5 @@
 		return "AllPermutationsSettings[" + teams + "," + reuseTeams + ","
 				+ profileslists + "," + teamsPerSession + "," + sessionsettings
-				+ "]";
+				+ "," + numberTournaments + "]";
 	}
 
@@ -166,6 +175,5 @@
 		final int prime = 31;
 		int result = 1;
-		result = prime * result + ((teams == null) ? 0 : teams.hashCode());
-		result = prime * result + teamsPerSession;
+		result = prime * result + numberTournaments;
 		result = prime * result
 				+ ((profileslists == null) ? 0 : profileslists.hashCode());
@@ -173,4 +181,6 @@
 		result = prime * result
 				+ ((sessionsettings == null) ? 0 : sessionsettings.hashCode());
+		result = prime * result + ((teams == null) ? 0 : teams.hashCode());
+		result = prime * result + teamsPerSession;
 		return result;
 	}
@@ -185,4 +195,18 @@
 			return false;
 		AllPermutationsSettings other = (AllPermutationsSettings) obj;
+		if (numberTournaments != other.numberTournaments)
+			return false;
+		if (profileslists == null) {
+			if (other.profileslists != null)
+				return false;
+		} else if (!profileslists.equals(other.profileslists))
+			return false;
+		if (reuseTeams != other.reuseTeams)
+			return false;
+		if (sessionsettings == null) {
+			if (other.sessionsettings != null)
+				return false;
+		} else if (!sessionsettings.equals(other.sessionsettings))
+			return false;
 		if (teams == null) {
 			if (other.teams != null)
@@ -191,16 +215,4 @@
 			return false;
 		if (teamsPerSession != other.teamsPerSession)
-			return false;
-		if (profileslists == null) {
-			if (other.profileslists != null)
-				return false;
-		} else if (!profileslists.equals(other.profileslists))
-			return false;
-		if (reuseTeams != other.reuseTeams)
-			return false;
-		if (sessionsettings == null) {
-			if (other.sessionsettings != null)
-				return false;
-		} else if (!sessionsettings.equals(other.sessionsettings))
 			return false;
 		return true;
@@ -251,6 +263,9 @@
 				partiesPermutations, profilesPermutations);
 
-		return new MapList<Tuple<ImmutableList<Team>, ImmutableList<ProfileList>>, ImmutableList<TeamOfPartiesAndProfiles>>(
+		MapList<Tuple<ImmutableList<Team>, ImmutableList<ProfileList>>, ImmutableList<TeamOfPartiesAndProfiles>> tournamentsettings = new MapList<Tuple<ImmutableList<Team>, ImmutableList<ProfileList>>, ImmutableList<TeamOfPartiesAndProfiles>>(
 				tuple -> teamlist(tuple), tuples);
+		return new Repeat<ImmutableList<TeamOfPartiesAndProfiles>>(
+				tournamentsettings, BigInteger.valueOf(numberTournaments),
+				true);
 	}
 
@@ -264,5 +279,5 @@
 	private ImmutableList<TeamOfPartiesAndProfiles> teamlist(
 			Tuple<ImmutableList<Team>, ImmutableList<ProfileList>> tuple) {
-		Function2<Team, ProfileList, TeamOfPartiesAndProfiles> makeparty = new Function2<Team, ProfileList, TeamOfPartiesAndProfiles>() {
+		BiFunction<Team, ProfileList, TeamOfPartiesAndProfiles> makeparty = new BiFunction<Team, ProfileList, TeamOfPartiesAndProfiles>() {
 			@Override
 			public TeamOfPartiesAndProfiles apply(Team team,
@@ -288,34 +303,3 @@
 	}
 
-//	/**
-//	 * Extract the raw URL, without the part after the question mark
-//	 * 
-//	 * @param party   a party reference (for another party)
-//	 * @param profile a profile that may have a filter like "?partial=XX"
-//	 * @return profile without the filter and with a cob party on the same
-//	 *         machine. IT IS ASSUMED that there will the default
-//	 *         "comparebids-1.0.0" party on the same machine as where the other
-//	 *         party is
-//	 */
-//	protected static PartyWithProfile makeCob(PartyRef party,
-//			ProfileRef profile) {
-//		try {
-//			URI profileuri = profile.getURI();
-//			URI partyuri = party.getURI();
-//			ProfileRef cobprof = new ProfileRef(profileuri.getScheme() + "://"
-//					+ profileuri.getAuthority() + profileuri.getPath());
-//			String partypath = partyuri.getPath();
-//			partypath = partypath.substring(0, partypath.lastIndexOf('/'));
-//			PartyWithParameters cobparty = new PartyWithParameters(new PartyRef(
-//					partyuri.getScheme() + "://" + partyuri.getAuthority()
-//							+ partypath + "/" + COB_PARTY),
-//					new Parameters());
-//			return new PartyWithProfile(cobparty, cobprof);
-//
-//		} catch (URISyntaxException e) {
-//			throw new IllegalArgumentException(
-//					"Failed making cob party with profile " + profile, e);
-//		}
-//	}
-
 }
