Index: exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java
===================================================================
--- exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java	(revision 24)
+++ exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java	(revision 25)
@@ -4,8 +4,11 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.math.RoundingMode;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Random;
 import java.util.logging.Level;
+import java.util.stream.Collectors;
 
 import geniusweb.actions.Accept;
@@ -13,8 +16,12 @@
 import geniusweb.actions.Offer;
 import geniusweb.actions.PartyId;
+import geniusweb.actions.Vote;
+import geniusweb.actions.Votes;
 import geniusweb.inform.ActionDone;
 import geniusweb.inform.Finished;
 import geniusweb.inform.Inform;
+import geniusweb.inform.OptIn;
 import geniusweb.inform.Settings;
+import geniusweb.inform.Voting;
 import geniusweb.inform.YourTurn;
 import geniusweb.issuevalue.Bid;
@@ -23,4 +30,5 @@
 import geniusweb.profile.Profile;
 import geniusweb.profile.utilityspace.LinearAdditive;
+import geniusweb.profile.utilityspace.UtilitySpace;
 import geniusweb.profileconnection.ProfileConnectionFactory;
 import geniusweb.profileconnection.ProfileInterface;
@@ -35,9 +43,33 @@
  * 2^31 (approx 1 billion bids). It may take excessive time and run out of time
  * on bidspaces &gt; 10000 bids. In special cases it may even run out of memory,
+ * 
+ * <p>
+ * Supports parameters as follows
+ * <table summary="parameters">
+ * <tr>
+ * <td>e</td>
+ * <td>e determines how fast the party makes concessions with time. Typically
+ * around 1. 0 means no concession, 1 linear concession, &gt;1 faster than
+ * linear concession.</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>minPower</td>
+ * <td>This value is used as minPower for placed {@link Vote}s. Default value is
+ * 1.</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>maxPower</td>
+ * <td>This value is used as maxPower for placed {@link Vote}s. Default value is
+ * infinity.</td>
+ * </tr>
+ * 
+ * </table>
+ * <p>
+ * TimeDependentParty requires a {@link UtilitySpace}
  */
 public class TimeDependentParty extends DefaultParty {
 
-	private static final BigDecimal DEC0001 = new BigDecimal("0.0001");
-	private static final BigDecimal DEC100 = new BigDecimal("100");
 	private ProfileInterface profileint;
 	private LinearAdditive utilspace = null; // last received space
@@ -47,4 +79,6 @@
 	private ExtendedUtilSpace extendedspace;
 	private double e = 1.2;
+	private Votes lastvotes;
+	private Settings settings;
 
 	public TimeDependentParty() {
@@ -58,5 +92,5 @@
 	@Override
 	public Capabilities getCapabilities() {
-		return new Capabilities(new HashSet<>(Arrays.asList("SAOP")));
+		return new Capabilities(new HashSet<>(Arrays.asList("SAOP", "MOPAC")));
 	}
 
@@ -65,5 +99,5 @@
 		try {
 			if (info instanceof Settings) {
-				Settings settings = (Settings) info;
+				settings = (Settings) info;
 				this.profileint = ProfileConnectionFactory
 						.create(settings.getProfile().getURI(), getReporter());
@@ -80,5 +114,4 @@
 					}
 				}
-
 			} else if (info instanceof ActionDone) {
 				Action otheract = ((ActionDone) info).getAction();
@@ -88,13 +121,16 @@
 			} else if (info instanceof YourTurn) {
 				myTurn();
-				if (progress instanceof ProgressRounds) {
-					progress = ((ProgressRounds) progress).advance();
-				}
 			} else if (info instanceof Finished) {
 				getReporter().log(Level.INFO, "Final ourcome:" + info);
+			} else if (info instanceof Voting) {
+				lastvotes = vote((Voting) info);
+				getConnection().send(lastvotes);
+			} else if (info instanceof OptIn) {
+				getConnection().send(lastvotes);
 			}
-		} catch (Exception e) {
-			getReporter().log(Level.SEVERE, "Failed to handle info", e);
-		}
+		} catch (Exception ex) {
+			getReporter().log(Level.SEVERE, "Failed to handle info", ex);
+		}
+		updateRound(info);
 	}
 
@@ -119,5 +155,44 @@
 	}
 
+	@Override
+	public String getDescription() {
+		return "Time-dependent conceder. Aims at utility u(t) = scale * t^(1/e) "
+				+ "where t is the time (0=start, 1=end), e is the concession speed parameter (default 1.1), and scale such that u(0)=minimum and "
+				+ "u(1) = maximum possible utility. Parameters minPower (default 1) and maxPower (default infinity) are used "
+				+ "when voting";
+	}
+
 	/******************* private support funcs ************************/
+
+	/**
+	 * Update {@link #progress}, depending on the protocol and last received
+	 * {@link Inform}
+	 * 
+	 * @param info the received info.
+	 */
+	private void updateRound(Inform info) {
+		if (settings == null) // not yet initialized
+			return;
+		String protocol = settings.getProtocol().getURI().getPath();
+
+		switch (protocol) {
+		case "SAOP":
+		case "SHAOP":
+			if (!(info instanceof YourTurn))
+				return;
+			break;
+		case "MOPAC":
+			if (!(info instanceof OptIn))
+				return;
+			break;
+		default:
+			return;
+		}
+		// if we get here, round must be increased.
+		if (progress instanceof ProgressRounds) {
+			progress = ((ProgressRounds) progress).advance();
+		}
+
+	}
 
 	private void myTurn() throws IOException {
@@ -153,5 +228,7 @@
 	private Bid makeBid() {
 		double time = progress.get(System.currentTimeMillis());
-		BigDecimal utilityGoal = utilityGoal(time, getE());
+
+		BigDecimal utilityGoal = getUtilityGoal(time, getE(),
+				extendedspace.getMin(), extendedspace.getMax());
 		ImmutableList<Bid> options = extendedspace.getBids(utilityGoal);
 		if (options.size() == BigInteger.ZERO) {
@@ -166,27 +243,64 @@
 	/**
 	 * 
-	 * @param t the time in [0,1] where 0 means start of nego and 1 the end of
-	 *          nego (absolute time/round limit)
-	 * @param e the e value
+	 * @param t       the time in [0,1] where 0 means start of nego and 1 the
+	 *                end of nego (absolute time/round limit)
+	 * @param e       the e value that determinses how fast the party makes
+	 *                concessions with time. Typically around 1. 0 means no
+	 *                concession, 1 linear concession, &gt;1 faster than linear
+	 *                concession.
+	 * @param minUtil the minimum utility possible in our profile
+	 * @param maxUtil the maximum utility possible in our profile
 	 * @return the utility goal for this time and e value
 	 */
-	private BigDecimal utilityGoal(double t, double e) {
-		BigDecimal minUtil = extendedspace.getMin();
-		BigDecimal maxUtil = extendedspace.getMax();
-
-		double ft = 0;
+	protected BigDecimal getUtilityGoal(double t, double e, BigDecimal minUtil,
+			BigDecimal maxUtil) {
+
+		BigDecimal ft1 = BigDecimal.ONE;
 		if (e != 0)
-			ft = Math.pow(t, 1 / e);
-		// we subtract epsilon to correct possibly small round-up errors
-		return new BigDecimal(minUtil.doubleValue()
-				+ (maxUtil.doubleValue() - minUtil.doubleValue()) * (1 - ft))
-						.min(maxUtil).max(minUtil);
-	}
-
-	@Override
-	public String getDescription() {
-		return "Time-dependent conceder. Aims at utility u(t) = scale * t^(1/e) "
-				+ "where t is the time (0=start, 1=end), e is a parameter (default 1.1), and scale such that u(0)=minimum and "
-				+ "u(1) = maximum possible utility. ";
+			ft1 = BigDecimal.valueOf(1 - Math.pow(t, 1 / e)).setScale(6,
+					RoundingMode.HALF_UP);
+		return minUtil.add((maxUtil.subtract(minUtil).multiply(ft1)))
+				.min(maxUtil).max(minUtil);
+	}
+
+	/**
+	 * @param voting the {@link Voting} object containing the options
+	 * 
+	 * @return our next Votes.
+	 */
+	private Votes vote(Voting voting) throws IOException {
+		Object val = settings.getParameters().get("minPower");
+		// max utility requires smallest possible group/power
+		Integer minpower = (val instanceof Integer) ? (Integer) val : 1;
+		val = settings.getParameters().get("maxPower");
+		Integer maxpower = (val instanceof Integer) ? (Integer) val
+				: Integer.MAX_VALUE;
+
+		List<Vote> votes = voting.getBids().stream().distinct()
+				.filter(bid -> isGood(bid))
+				.map(bid -> new Vote(me, bid, minpower, maxpower))
+				.collect(Collectors.toList());
+		return new Votes(me, votes);
+	}
+
+	/**
+	 * @param bid the bid to check
+	 * @return true iff bid is good for us.
+	 */
+	private boolean isGood(Bid bid) {
+		if (bid == null || profileint == null)
+			return false;
+		Profile profile;
+		try {
+			profile = profileint.getProfile();
+		} catch (IOException ex) {
+			throw new IllegalStateException(ex);
+		}
+		// the profile MUST contain UtilitySpace
+		double time = progress.get(System.currentTimeMillis());
+		return ((UtilitySpace) profile).getUtility(bid)
+				.compareTo(getUtilityGoal(time, getE(), extendedspace.getMin(),
+						extendedspace.getMax())) >= 0;
+
 	}
 }
