Only in mastermind: mastermind.patch
diff -rup omastermind/mastermind/src/Bitarray.h mastermind/src/Bitarray.h
--- omastermind/mastermind/src/Bitarray.h	2013-10-27 15:20:55.000000000 +0100
+++ mastermind/src/Bitarray.h	2013-11-13 14:57:45.885436426 +0100
@@ -1,6 +1,6 @@
 #ifndef __BITARRAY_H
 #define __BITARRAY_H
-/** Bitarray. Think of a Bitarray as a very large word where you can do bit operations on.
+/** Bitarray. Think of a Bitarray as a very large word which you can do bit operations on.
  * @author Danny Milosavljevic (0826039)
  * @brief Array of bits
  * @date 2013-10-26
@@ -43,5 +43,4 @@ int Bitarray_getSetCount(struct Bitarray
 /** retrieves the bit with the given index */
 int Bitarray_get(struct Bitarray* self, unsigned int bitIndex);
 
-
-#endif /* ndef __BITSET_H */
+#endif /* ndef __BITARRAY_H */
diff -rup omastermind/mastermind/src/client.c mastermind/src/client.c
--- omastermind/mastermind/src/client.c	2013-11-11 15:24:35.000000000 +0100
+++ mastermind/src/client.c	2013-11-13 20:56:20.850596879 +0100
@@ -85,7 +85,7 @@ static void perror2(const char* text) {
  * @param portname name of the port to connect to
  * @return file descriptor of a connect()ed socket, or (-1) on error
  */
-static int connectToHost(const char* arg0, const char* hostname, const char* portname) {
+static int connectToHost(const char* hostname, const char* portname) {
 	int fd;
 	struct sockaddr_in addr;
 	struct hostent* hostent;
@@ -93,7 +93,7 @@ static int connectToHost(const char* arg
 	long int direct_port = 0;
 	fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 	if(fd == -1) {
-		(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\"\n", arg0, hostname, portname);
+		(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\"\n", progname, hostname, portname);
 		perror2("socket");
 		return(-1);
 	}
@@ -101,7 +101,7 @@ static int connectToHost(const char* arg
 	if(servent == NULL) {
 		direct_port = strtol(portname, NULL, 10);
 		if(direct_port < 0 || direct_port > 0xFFFF) {
-			(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\": port was unknown.\n", arg0, hostname, portname);
+			(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\": port was unknown.\n", progname, hostname, portname);
 			perror2("strtol");
 			(void) close(fd);
 			return(-1);
@@ -109,7 +109,7 @@ static int connectToHost(const char* arg
 	}
 	hostent = gethostbyname(hostname);
 	if(hostent == NULL) {
-		(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\"\n", arg0, hostname, portname);
+		(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\"\n", progname, hostname, portname);
 		herror("gethostbyname");
 		(void) close(fd);
 		return(-1);
@@ -117,7 +117,7 @@ static int connectToHost(const char* arg
 	addr.sin_family = AF_INET;
 	addr.sin_port = (servent != NULL) ? servent->s_port : htons(direct_port); /* s_port is already in network byte order */
 	if(sizeof(addr.sin_addr) < hostent->h_length) {
-		(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\": no idea how to read the address\n", arg0, hostname, portname);
+		(void) fprintf(stderr, "%s: Could not connect to \"%s:%s\": no idea how to read the address\n", progname, hostname, portname);
 		(void) close(fd);
 		return(-1);
 	}
@@ -215,9 +215,6 @@ static int convertResponseStatus(int res
 				return(-1);
 }
 
-
-/*static void traverse_possibilities(const char* client_name, int fd, struct gamestate* state, int i_slot) {
-}*/
 /**
  * @brief play game
  * @param clientName client name
@@ -225,34 +222,49 @@ static int convertResponseStatus(int res
  * @param state game state
  * @return exit code
  */
-static int playGame(const char* clientName, int fd, struct Gamestate* state) {
+static int playGame(int fd, struct Gamestate* state) {
 	guess_t guess = {0};
 	int response;
-	int exitcode;
+	int exitcode = (-1);
 	int correctCount; /* of server's answer */
 	int opresentCount; /* of server's answer */
 	int i;
-	/* prepare initial guess */
-	for(i = 0; i < SLOTS; ++i) 
-		guess[i] = i % COLORS;
-	while(1 == 1) {
+	int preparedSlotCount = 0;
+	int preparedColorCount = 0;
+	assert(SLOTS > 0);
+	assert(COLORS > 0);
+	assert(COLORS > SLOTS); /* TODO also allow the other case (then use a random guess) */
+	while(exitcode != 0) {
 		Gamestate_startRound(state);
+		if(preparedSlotCount < SLOTS) {
+			for(i = 0; i < SLOTS; ++i)
+				guess[i] = preparedColorCount;
+		} else {
+			i = Gamestate_getBestMove(state, &guess);
+			if(!i)
+				abort();
+		}
 		response = sendGuess(fd, &guess);
 		exitcode = convertResponseStatus(response, &correctCount, &opresentCount);
 		if(exitcode != (-1))
 			return(exitcode);
 		if(correctCount == SLOTS) {
-			if(!printGuess(stdout, &guess) || 
-			   fputc('\n', stdout) == EOF)
-				abort();
-			return(0);
+			exitcode = 0;
+			continue;
 		}
 		Gamestate_removeDifferentlyScoredSecrets(state, &guess, correctCount, opresentCount);
-		i = Gamestate_getBestMove(state, &guess);
-		if(!i)
-			abort();
+		if(preparedSlotCount < SLOTS) {
+			if(correctCount > 0)
+				Gamestate_addPaletteEntry(state, guess[0]);
+			preparedSlotCount += correctCount + opresentCount;
+			++preparedColorCount;
+		}
 	}
-	return(-1);
+	assert(exitcode == 0);
+	if(!printGuess(stdout, &guess) || 
+	   fputc('\n', stdout) == EOF)
+		abort();
+	return(0);
 }
 
 /** 
@@ -274,12 +286,12 @@ int main(int argc, char* argv[]) {
 	}
 	server_hostname = argv[1];
 	server_port = argv[2];
-	fd = connectToHost(argv[0], server_hostname, server_port);
+	fd = connectToHost(server_hostname, server_port);
 	if(fd == -1)
 		return(EXIT_FAILURE);
 	state = alloca(Gamestate_getAllocation());
 	Gamestate_init(state);
-	status = playGame(argv[0], fd, state);
+	status = playGame(fd, state);
 	switch(status) {
 	case 0: /* guessed correctly */
 		(void) printf("%d\n", Gamestate_getRoundCount(state));
diff -rup omastermind/mastermind/src/Gamestate.c mastermind/src/Gamestate.c
--- omastermind/mastermind/src/Gamestate.c	2013-11-11 14:04:59.000000000 +0100
+++ mastermind/src/Gamestate.c	2013-11-13 21:08:21.454099136 +0100
@@ -26,6 +26,8 @@ struct Gamestate {
 	int eliminationCount; /**< current eliminationCount for getBestMove iterations. */
 	int correctCount; /**< number of correct colors at the correct places */
 	int opresentCount; /**< number of present colors at the wrong places */ 
+	int paletteCount; /**< number of colors in palette */
+	uint8_t palette[SLOTS]; /**< colors in palette */
 };
 
 size_t Gamestate_getAllocation(void) {
@@ -47,6 +49,7 @@ void Gamestate_init(struct Gamestate* se
 	/* initially, all secrets are possible */
 	for(secretBitIndex = 0; secretBitIndex < capacity; ++secretBitIndex)
 		Bitarray_set(self->secrets, secretBitIndex, 1);
+	self->paletteCount = 0;
 }
 
 void Gamestate_deinit(struct Gamestate* self) {
@@ -169,7 +172,7 @@ int Gamestate_getBestMove(struct Gamesta
 	  *   Later on, we send that guess.
 	  */
 	int secretCount; /* number of set bits in secrets */
-	unsigned int data; /* possible guess */
+	guess_t guess;
 	unsigned int highestData = 0; /* for storing where the maximum is (i.e. which guess is best) */
 	int first = 1;
 	int highestEliminationCount = -1; /* for storing the maximum */
@@ -180,17 +183,33 @@ int Gamestate_getBestMove(struct Gamesta
 		Bitarray_iterateSet(self->secrets, storeGuess, outGuess);
 		return 1;
 	}
-	for(data = 0; data < pow(COLORS, SLOTS); ++data) { /* for all possible guesses */
-		/** Calculate how many possibilities (secrets) we could (at least) eliminate.
-		  * Take the guess with the highest such value.
-		  */
-		int eliminationCount;
-		eliminationCount = Gamestate_getEliminationCount(self, data);
-		if(eliminationCount > highestEliminationCount) {
-			/* update maximum */
-			highestEliminationCount = eliminationCount;
-			highestData = data;
-			first = 0;
+	assert(SLOTS == 5);
+	for(int s0i = 0; s0i < self->paletteCount; ++s0i) {
+		guess[0] = self->palette[s0i];
+		for(int s1i = 0; s1i < self->paletteCount; ++s1i) {
+			guess[1] = self->palette[s1i];
+			for(int s2i = 0; s2i < self->paletteCount; ++s2i) {
+				guess[2] = self->palette[s2i];
+				for(int s3i = 0; s3i < self->paletteCount; ++s3i) {
+					guess[3] = self->palette[s3i];
+					for(int s4i = 0; s4i < self->paletteCount; ++s4i) {
+						unsigned int data; /* possible guess */
+						guess[4] = self->palette[s4i];
+						data = packGuess(&guess);
+						/** Calculate how many possibilities (secrets) we could (at least) eliminate.
+						  * Take the guess with the highest such value.
+						  */
+						int eliminationCount;
+						eliminationCount = Gamestate_getEliminationCount(self, data);
+						if(eliminationCount > highestEliminationCount) {
+							/* update maximum */
+							highestEliminationCount = eliminationCount;
+							highestData = data;
+							first = 0;
+						}
+					}
+				}
+			}
 		}
 	}
 	unpackGuess(highestData, outGuess);
@@ -200,6 +219,7 @@ int Gamestate_getBestMove(struct Gamesta
 
 /** given a score and a secret, returns whether it DOESN'T match the score. */
 static int differentlyScoredP(void* userdata, unsigned int secretBitIndex) {
+	/* this is NOT allowed to use palette. */
 	struct Gamestate* self = (struct Gamestate*) userdata;
 	int correctCount, opresentCount;
 	guess_t g1, g2;
@@ -221,12 +241,18 @@ int printGuess(FILE* destination, guess_
 }
 
 void Gamestate_removeDifferentlyScoredSecrets(struct Gamestate* self, guess_t* g1, int correctCount, int opresentCount) {
+	/* this is NOT allowed to use palette. */
 	/*(void) fprintf(stderr, "Guessing ");
 	printGuess(g1);*/
 	self->guess = packGuess(g1);
 	self->correctCount = correctCount; /* closure for unsetEach */
 	self->opresentCount = opresentCount; /* closure for unsetEach */
 	Bitarray_unsetEach(self->secrets, differentlyScoredP, self);
+	if(correctCount + opresentCount == 0) { /* no colors in there match anything. TODO is that worth it? */
+		int i;
+		for(i = 0; i < SLOTS; ++i)
+			Gamestate_disqualifyGuessesContainingColor(self, (*g1)[i]);
+	}
 	DEBUG("Removed differently scored secrets.\n");
 }
 void Gamestate_startRound(struct Gamestate* self) {
@@ -236,4 +262,39 @@ void Gamestate_startRound(struct Gamesta
 int Gamestate_getRoundCount(struct Gamestate* self) {
 	return self->roundCount;
 }
-
+uint8_t Gamestate_getPaletteEntry(struct Gamestate* self, int index) {
+	return self->palette[index];
+}
+int Gamestate_getPaletteEntryCount(struct Gamestate* self) {
+	return self->paletteCount;
+}
+void Gamestate_addPaletteEntry(struct Gamestate* self, uint8_t value) {
+	if(self->paletteCount >= SLOTS)
+		abort();
+	self->palette[self->paletteCount++] = value;
+}
+void Gamestate_disqualifyGuessesContainingColor(struct Gamestate* self, uint8_t value) {
+	/* since this is used when building up the palette, don't use it in here. */
+	guess_t guess;
+	assert(SLOTS == 5);
+	for(int s0i = 0; s0i < COLORS; ++s0i) {
+		guess[0] = s0i;
+		for(int s1i = 0; s1i < COLORS; ++s1i) {
+			guess[1] = s1i;
+			for(int s2i = 0; s2i < COLORS; ++s2i) {
+				guess[2] = s2i;
+				for(int s3i = 0; s3i < COLORS; ++s3i) {
+					guess[3] = s3i;
+					for(int s4i = 0; s4i < COLORS; ++s4i) {
+						guess[4] = s4i;
+						if(guess[0] == value || guess[1] == value || guess[2] == value || guess[3] == value || guess[4] == value) {
+							unsigned int data; /* possible guess */
+							data = packGuess(&guess);
+							Bitarray_set(self->secrets, data, 0);
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff -rup omastermind/mastermind/src/Gamestate.h mastermind/src/Gamestate.h
--- omastermind/mastermind/src/Gamestate.h	2013-11-11 07:37:32.000000000 +0100
+++ mastermind/src/Gamestate.h	2013-11-13 20:54:32.390600068 +0100
@@ -69,10 +69,36 @@ int printGuess(FILE* destination, guess_
   */
 void Gamestate_removeDifferentlyScoredSecrets(struct Gamestate* self, guess_t* g1, int correctCount, int opresentCount);
 
+/** get the entry in the palette (of colors) with the given index.
+  * @param self game state.
+  * @param index index in palette. 0 is first.
+  * @return color
+  */
+uint8_t Gamestate_getPaletteEntry(struct Gamestate* self, int index);
+
+/** get the entry count in the palette. 
+  * @param self game state.
+  * @return entry count
+  */
+int Gamestate_getPaletteEntryCount(struct Gamestate* self);
+
+/** add entry to the palette. 
+  * @param self game state.
+  * @param value color.
+  */
+void Gamestate_addPaletteEntry(struct Gamestate* self, uint8_t value);
+
+/** disqualify any guesses that contain the given color. 
+  * @param self game state.
+  * @param value color (NOT using palette).
+  */ 
+void Gamestate_disqualifyGuessesContainingColor(struct Gamestate* self, uint8_t value);
+
 /** increase round count */
 void Gamestate_startRound(struct Gamestate* self);
 
 /** get round count */
 int Gamestate_getRoundCount(struct Gamestate* self);
 
+
 #endif
Only in mastermind: testClient
Only in mastermind: testServer
