diff --git a/judge/manager/Makefile b/judge/manager/Makefile
index 199a3afda0d975e50e71472d941a25d78292f2eb..e06e1810c2667599266dea70288d75c2ad8643b6 100644
--- a/judge/manager/Makefile
+++ b/judge/manager/Makefile
@@ -1,13 +1,13 @@
 #Makefile for Stratego
 
 #Use this to build with graphics
-#LIBRARIES = -lSDL -lGL -lpthread
+LIBRARIES = -lSDL -lGL -lpthread
 #Use this to build without graphics
-LIBRARIES = -lpthread
+#LIBRARIES = -lpthread
 #Use this on Mac OSX (Thanks spartan)
 #LIBRARIES = -I/opt/local/include/ -L/opt/local/lib/ -lSDL -framework OpenGL -lpthread
 CPP = g++ -Wall -pedantic -g
-OBJ = main.o controller.o network_controller.o ai_controller.o human_controller.o program.o thread_util.o stratego.o graphics.o game.o
+OBJ = main.o controller.o network_controller.o ai_controller.o human_controller.o program.o network.o thread_util.o stratego.o graphics.o game.o
 
 BIN = stratego
 
diff --git a/judge/manager/ai_controller.h b/judge/manager/ai_controller.h
index f4682eb2de00bda227f8952e77a4690d6083c2bd..0a4baeb7cbbb66730f39d9d6271484a45c8d2c0d 100644
--- a/judge/manager/ai_controller.h
+++ b/judge/manager/ai_controller.h
@@ -19,7 +19,11 @@ class AI_Controller : public Controller, private Program
 		virtual MovementResult QuerySetup(const char * opponentName,std::string setup[]);
 		virtual MovementResult QueryMove(std::string & buffer);
 
-		virtual void Message(const char * message) {Program::SendMessage(message);}
+		virtual void Message(const char * message) 
+		{
+			//fprintf(stderr, "Sending message \"%s\" to AI program...\n", message);
+			Program::SendMessage(message);
+		}
 		virtual void Pause() {Program::Pause();} //Hack wrapper
 		virtual void Continue() {Program::Continue();} //Hack wrapper
 
diff --git a/judge/manager/game.cpp b/judge/manager/game.cpp
index 92dc71ab349c96d0bad905ee9ae82926a1f8c176..f25c9f381cfcc62f25eaa951b3928bd34e44468d 100644
--- a/judge/manager/game.cpp
+++ b/judge/manager/game.cpp
@@ -7,7 +7,7 @@ using namespace std;
 Game* Game::theGame = NULL;
 bool Game::gameCreated = false;
 
-Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const  Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime, bool server, bool client) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime)
+Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const  Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime)
 {
 	gameCreated = false;
 	if (gameCreated)
@@ -26,34 +26,24 @@ Game::Game(const char * redPath, const char * bluePath, const bool enableGraphic
 	#endif //BUILD_GRAPHICS
 
 
-	if (client)
-	{
-		red = new Client(Piece::RED, "server", redPath); //TODO: Retrieve server address
-	}
-	else
-	{
-		assert(redPath != NULL);
-		if (strcmp(redPath, "human") == 0)
-			red = new Human_Controller(Piece::RED, graphicsEnabled);
-		else
-			red = new AI_Controller(Piece::RED, redPath, timeoutTime);
-	}
-	
-	
-	if (server)
-	{
-		blue = new Server(Piece::BLUE, "client");
-	}
-	else
+
+	MakeControllers(redPath, bluePath);
+
+	if (red == NULL || blue == NULL)
 	{
-		assert(bluePath != NULL);
-		if (strcmp(bluePath, "human") == 0)
-			blue = new Human_Controller(Piece::BLUE, graphicsEnabled);
+		fprintf(stderr, "Game::Game - Error creating controller: ");
+		if (red == NULL)
+		{
+			if (blue == NULL)
+				fprintf(stderr, " BOTH! (red: \"%s\", blue: \"%s\"\n", redPath, bluePath);
+			else
+				fprintf(stderr, " RED! (red: \"%s\")\n", redPath);
+		}
 		else
-			blue = new AI_Controller(Piece::BLUE, bluePath, timeoutTime);
+			fprintf(stderr, "BLUE! (blue: \"%s\")\n", bluePath);
+		exit(EXIT_FAILURE);
 	}
-
-
+	logMessage("Game initialised.\n");
 }
 
 Game::Game(const char * fromFile, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const  Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime)
@@ -489,7 +479,7 @@ MovementResult Game::Play()
 	
 	
 
-
+	logMessage("Messaging red with \"START\"\n");
 	red->Message("START");
 	
 
@@ -770,4 +760,101 @@ int Game::Tokenise(std::vector<string> & buffer, std::string & str, char split)
 	return buffer.size();
 }
 
+/**
+ * Creates Controller baseds off strings. Takes into account controllers other than AI_Controller.
+ * @param redPath - Either the path to an AI_Controller compatable executable, or one of %human or %network or %network:[IP_ADDRESS]
+ * @param bluePath - Ditto
+ * Sets this->red to a controller using redPath, and this->blue to a controller using bluePath
+ * TODO: Make nicer (this function should be ~half the length)
+ */
+void Game::MakeControllers(const char * redPath, const char * bluePath)
+{
+	Network * redNetwork = NULL;
+	Network * blueNetwork = NULL;
+
+	if (redPath[0] == '@')
+	{
+		if (strcmp(redPath, "@human") == 0)
+			red = new Human_Controller(Piece::RED, graphicsEnabled);
+		else
+		{
+			const char * network = strstr(redPath, "@network");
+			if (network == NULL)
+			{
+				red = NULL;
+				return;
+			}
+			network = strstr(network, ":");
+		
+			if (network == NULL)
+			{
+				logMessage("Creating server for red AI... ");
+				redNetwork = new Server();
+				logMessage("Successful!\n");
+
+			}
+			else
+			{
+				network = (const char*)(network+1);
+				logMessage("Creating client for red AI... ");
+				redNetwork = new Client(network);
+				logMessage("Connected to address %s\n", network);
+			}
+
+			logMessage("	(Red's responses will be received over the connection)\n");
+			red = new NetworkReceiver(Piece::RED, redNetwork);
+		}		
+	}
+	else
+		red = new AI_Controller(Piece::RED, redPath, timeoutTime);
+
+	if (bluePath[0] == '@')
+	{
+		if (strcmp(bluePath, "@human") == 0)
+			blue = new Human_Controller(Piece::BLUE, graphicsEnabled);
+		else
+		{
+			const char * network = strstr(bluePath, "@network");
+			if (network == NULL)
+			{
+				blue = NULL;
+				return;
+			}
+			network = strstr(network, ":");
+		
+			if (network == NULL)
+			{
+				logMessage("Creating server for blue AI... ");
+				blueNetwork = new Server();
+				logMessage("Successful!\n");
+
+			}
+			else
+			{
+				network = (const char*)(network+1);
+				logMessage("Creating client for blue AI... ");
+				blueNetwork = new Client(network);
+				logMessage("Connected to address %s\n", network);
+			}
+			logMessage("	(Blue's responses will be received over the connection)\n");
+			blue = new NetworkReceiver(Piece::BLUE, blueNetwork);
+		}		
+	}
+	else
+		blue = new AI_Controller(Piece::BLUE, bluePath, timeoutTime);
+
+	if (redNetwork != NULL)
+	{
+		
+		blue = new NetworkSender(Piece::BLUE,blue, redNetwork);
+		logMessage("	(Blue's responses will be copied over the connection)\n");
+	}
+	if (blueNetwork != NULL)
+	{
+		
+		red = new NetworkSender(Piece::RED, red, blueNetwork);
+		logMessage("	(Red's responses will be copied over the connection)\n");
+	}
+	
+}
 
diff --git a/judge/manager/game.h b/judge/manager/game.h
index cc79e656bd278be678ebc1b4467c314836eb9551..3f46abb43ff8a4c5d4f3151a6a60bbcc44281d87 100644
--- a/judge/manager/game.h
+++ b/judge/manager/game.h
@@ -15,7 +15,7 @@
 class Game
 {
 	public:
-		Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false, double newTimeoutTime = 2.0, bool server=false, bool client=false);
+		Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false, double newTimeoutTime = 2.0);
 		Game(const char * fromFile, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false, double newTimeoutTime = 2.0);
 		virtual ~Game();
 
@@ -38,6 +38,9 @@ class Game
 
 		static Game * theGame;
 		static int Tokenise(std::vector<std::string> & buffer, std::string & str, char split = ' '); //Helper - Split a string into tokens
+
+	private:
+		void MakeControllers(const char * redPath, const char * bluePath); //Create a controller based off a path
 	public:
 		int logMessage(const char * format, ...);
 		FILE * GetLogFile() const {return log;}
diff --git a/judge/manager/graphics.h b/judge/manager/graphics.h
index 2a969327d8a14790564067c76e9426ce8ee76083..caa57c69e49c3df05631a792c4bbff060aa3e1e9 100644
--- a/judge/manager/graphics.h
+++ b/judge/manager/graphics.h
@@ -1,4 +1,4 @@
-//#define BUILD_GRAPHICS
+#define BUILD_GRAPHICS
 #ifdef BUILD_GRAPHICS
 
 #ifndef GRAPHICS_H
diff --git a/judge/manager/main.cpp b/judge/manager/main.cpp
index 08c381ce9492421599ed02e6b73ac6128fcb46e7..e65ef0d1b6a142781f821fc076a2d42b21b0d29d 100644
--- a/judge/manager/main.cpp
+++ b/judge/manager/main.cpp
@@ -64,7 +64,7 @@ Piece::Colour SetupGame(int argc, char ** argv)
 {
 	char * red = NULL; char * blue = NULL; double stallTime = 0.0; bool graphics = false; bool allowIllegal = false; FILE * log = NULL;
 	Piece::Colour reveal = Piece::BOTH; char * inputFile = NULL; int maxTurns = 5000; bool printBoard = false; double timeoutTime = 2.0;
-	bool server = false; bool client = false;
+
 	for (int ii=1; ii < argc; ++ii)
 	{
 		if (argv[ii][0] == '-')
@@ -185,26 +185,6 @@ Piece::Colour SetupGame(int argc, char ** argv)
 						system("less manual.txt");
 						exit(EXIT_SUCCESS);
 					}
-					else if (strcmp(argv[ii]+2, "server") == 0)
-					{
-						if (client == true)
-						{
-							fprintf(stderr, "ARGUMENT_ERROR - Can't be both a server and a client!\n");
-							exit(EXIT_FAILURE);
-						}
-						server = true;
-						
-					}
-					else if (strcmp(argv[ii]+2, "client") == 0)
-					{
-						if (server == true)
-						{
-							fprintf(stderr, "ARGUMENT_ERROR - Can't be both a server and a client!\n");
-							exit(EXIT_FAILURE);
-						}
-						client = true;	
-						
-					}
 					else
 					{
 						fprintf(stderr, "ARGUMENT_ERROR - Unrecognised switch \"%s\"...\n", argv[ii]);
@@ -232,37 +212,16 @@ Piece::Colour SetupGame(int argc, char ** argv)
 
 	if (inputFile == NULL)
 	{
-		if (server)  
+		if (red == NULL || blue == NULL) //Not enough players
 		{
-			if (red != NULL && blue != NULL)
-			{
-				fprintf(stderr, "ARGUMENT_ERROR - When using the --server switch, only supply ONE (1) player.\n");
-				exit(EXIT_FAILURE);
-			}
-		}
-		else if (red == NULL || blue == NULL) //Not enough players
-		{
-			if (client)
-				fprintf(stderr, "ARGUMENT_ERROR - When using the --client switch, supply an IP for the Red player.\n");
-			else			
-				fprintf(stderr, "ARGUMENT_ERROR - Did not recieve enough players (did you mean to use the -f switch?)\n");	
+			fprintf(stderr, "ARGUMENT_ERROR - Did not recieve enough players (did you mean to use the -f switch?)\n");	
 			exit(EXIT_FAILURE);	
 		}
-		
-		if (client)
-		{
-			blue = red; red = NULL;
-		}
 
-		Game::theGame = new Game(red,blue, graphics, stallTime, allowIllegal,log, reveal,maxTurns, printBoard, timeoutTime, server, client);
+		Game::theGame = new Game(red,blue, graphics, stallTime, allowIllegal,log, reveal,maxTurns, printBoard, timeoutTime);
 	}
 	else
 	{
-		if (server || client)
-		{
-			fprintf(stderr, "ARGUMENT_ERROR - The -f switch is incompatable with the --server or --client switches!\n");
-			exit(EXIT_FAILURE);
-		}
 		Game::theGame = new Game(inputFile, graphics, stallTime, allowIllegal,log, reveal,maxTurns, printBoard, timeoutTime);
 	}
 
diff --git a/judge/manager/network.cpp b/judge/manager/network.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e349fea4cabfb85749929a7918cd0951189105a3
--- /dev/null
+++ b/judge/manager/network.cpp
@@ -0,0 +1,186 @@
+#include "network.h"
+#include <stdarg.h>
+
+using namespace std;
+
+Network::Network(int newPort) : sfd(-1), port(newPort), file(NULL)
+{
+    	sfd = socket(PF_INET, SOCK_STREAM, 0);
+	if (sfd < 0)
+	{
+		perror("Network::Network - Error creating TCP socket");
+		exit(EXIT_FAILURE);
+	}
+}
+
+Network::~Network()
+{
+	if (Valid())
+	{
+		if (shutdown(sfd, SHUT_RDWR) == -1)
+		{
+			perror("Network::~Network - shutting down socket... ");
+			close(sfd);
+			sfd = -1;
+		}
+	}
+	close(sfd);
+}
+
+Server::Server(int newPort) : Network(newPort)
+{
+	struct   sockaddr_in name;
+//	char   buf[1024];
+//	int    cc;
+
+	
+	name.sin_family = AF_INET;
+	name.sin_addr.s_addr = htonl(INADDR_ANY);
+	name.sin_port = htons(port);
+
+	if (bind( sfd, (struct sockaddr *) &name, sizeof(name) ) < 0)
+	{
+		perror("Server::Server - Error binding socket");
+		close(sfd); sfd = -1;
+		exit(EXIT_FAILURE);
+	}
+
+	if (listen(sfd,1) < 0)
+	{
+		perror("Server::Server - Error listening on socket");
+		close(sfd); sfd = -1;
+		exit(EXIT_FAILURE);
+	}
+	int psd = accept(sfd, 0, 0);
+	close(sfd);
+	sfd = psd;
+	if (sfd < 0)
+	{
+		perror("Server::Server - Error accepting connection");
+		close(sfd); sfd = -1;
+		exit(EXIT_FAILURE);
+	}
+
+
+
+	/*
+	for(;;) 
+	{
+		cc=recv(sfd,buf,sizeof(buf), 0) ;
+		if (cc == 0) exit (0);
+		buf[cc] = '\0';
+		printf("message received: %s\n", buf);
+	}
+	*/
+}
+
+Client::Client(const char * serverAddress, int newPort) : Network(newPort)
+{
+	struct	sockaddr_in server;
+	struct  hostent *hp;
+
+
+	server.sin_family = AF_INET;
+	hp = gethostbyname(serverAddress);
+	bcopy ( hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
+	server.sin_port = htons(port);
+
+	if (connect(sfd, (struct sockaddr *) &server, sizeof(server)) < 0)
+	{
+		fprintf(stderr, "Client::Client - Error connecting to server at address %s: ", serverAddress);
+		perror("");
+		close(sfd); sfd = -1;
+		exit(EXIT_FAILURE);
+	}
+
+
+
+
+	/*
+        for (;;) {
+	   send(sfd, "HI", 2,0 );
+           sleep(2);
+        }
+	*/
+}
+
+/**
+ * Sends a message accross the network
+ * WARNING: Always terminates the message with a newline '\n'
+ * @returns true if the message was successfully sent; false if it was not (ie: the network was not connected!)
+ */
+bool Network::SendMessage(const char * print, ...)
+{
+	if (!Valid()) //Is the process running...
+		return false; 
+
+	if (file == NULL)
+	{
+		file = fdopen(sfd, "r+");
+		setbuf(file, NULL);
+	}
+
+	va_list ap;
+	va_start(ap, print);
+
+	if (vfprintf(file, print, ap) < 0 || fprintf(file, "\n") < 0)
+	{
+		va_end(ap);
+		return false;
+	}
+	va_end(ap);
+
+	return true;
+}
+
+/**
+ * Retrieves a message from the network, waiting a maximum amount of time
+ * @param buffer - C++ string to store the resultant message in
+ * @param timeout - Maximum amount of time to wait before failure. If timeout <= 0, then GetMessage will wait indefinately.
+ * @returns true if the response was recieved within the specified time, false if it was not, or an EOF was recieved, or the process was not running.
+ */
+bool Network::GetMessage(string & buffer, double timeout)
+{
+	if (!Valid() || timeout == 0)
+		return false;
+
+	if (file == NULL)
+	{
+		file = fdopen(sfd, "r+");
+		setbuf(file, NULL);
+	}
+
+	assert(&buffer != NULL);
+	GetterThread getterThread(file, buffer);
+	assert(&(getterThread.buffer) != NULL);
+
+	TimerThread timerThread(timeout*1000000);
+
+	getterThread.Start();
+	if (timeout > 0)
+		timerThread.Start();
+
+	
+	while (!getterThread.Finished())
+	{
+		if (timeout > 0 && timerThread.Finished())
+		{
+			getterThread.Stop();
+			timerThread.Stop();
+			return false;
+		}
+	}
+
+	getterThread.Stop();
+	if (timeout > 0)
+		timerThread.Stop();
+
+	
+
+	if (buffer.size() == 1 && buffer[0] == EOF)
+		return false;
+	return true;
+
+
+}
+
diff --git a/judge/manager/network.h b/judge/manager/network.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cd0a11fd7c45b0cf2b48886760b49fc5809cb1c
--- /dev/null
+++ b/judge/manager/network.h
@@ -0,0 +1,53 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <string>
+#include "thread_util.h"
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+
+class Network
+{
+	public:
+		Network(int newPort = 666);
+		virtual ~Network();
+		bool Valid() const {return sfd != -1;}
+
+		bool SendMessage(const char * print, ...); //Sends a formated message (NOTE: Prints a newline)
+		bool SendMessage(const std::string & buffer) {return SendMessage(buffer.c_str());} //Sends a C++ string message
+		bool GetMessage(std::string & buffer, double timeout=-1); //Retrieves a message, or waits for a timeout (if positive)
+
+	protected:
+		int sfd;
+		int port;
+		FILE * file;
+		
+};
+
+class Server : public Network
+{
+	public:
+		Server(int newPort = 4560);
+		virtual ~Server() {}
+		
+};
+
+class Client : public Network
+{
+	public:
+		Client(const char * server = "127.0.0.1", int newPort = 4560);
+		virtual ~Client() {}
+};
+
+#endif //NETWORK_H
diff --git a/judge/manager/network_controller.cpp b/judge/manager/network_controller.cpp
index 9d14676309feb47ca6b6ae90586ea3b06119cbc0..fcca84e619b9616248617eac6184db14ef4787e0 100644
--- a/judge/manager/network_controller.cpp
+++ b/judge/manager/network_controller.cpp
@@ -1,102 +1,39 @@
 #include "network_controller.h"
 
-NetworkController::NetworkController(const Piece::Colour & newColour, const char * newName) : Controller(newColour, newName), sfd(-1)
-{
-	//struct protoent * tcp = getprotobyname("tcp");
- 
-    	sfd = socket(PF_INET, SOCK_STREAM, 0);
-	if (sfd < 0)
-	{
-		perror("NetworkController::NetworkController - Error creating TCP socket");
-		return;
-	}
-}
-
-NetworkController::~NetworkController()
-{
-	if (Valid())
-	{
-		if (shutdown(sfd, SHUT_RDWR) == -1)
-		{
-			perror("NetworkController::~NetworkController - shutting down socket... ");
-			close(sfd);
-			sfd = -1;
-		}
-	}
-	close(sfd);
-}
+using namespace std;
 
-void NetworkController::Message(const char * string)
+MovementResult NetworkSender::QuerySetup(const char * opponentName, string setup[])
 {
+	//fprintf(stderr,"	NetworkSender::QuerySetup... ");
+	MovementResult result = controller->QuerySetup(opponentName, setup);
 	
+	for (int ii=0; ii < 4; ++ii)
+		assert(network->SendMessage("%s",setup[ii].c_str())); //TODO: Proper error check
+
+	//fprintf(stderr,"Done!\n");
+	return result;
 }
 
-Server::Server(const Piece::Colour & newColour, const char * newName) : NetworkController(newColour, newName)
+MovementResult NetworkReceiver::QuerySetup(const char * opponentName, string setup[])
 {
-	struct   sockaddr_in name;
-	char   buf[1024];
-	int    cc;
-
-	
-	name.sin_family = AF_INET;
-	name.sin_addr.s_addr = htonl(INADDR_ANY);
-	name.sin_port = htons(NetworkController::port);
-
-	if (bind( sfd, (struct sockaddr *) &name, sizeof(name) ) < 0)
+	//fprintf(stderr,"	NetworkReceiver::QuerySetup... ");
+	for (int ii=0; ii < 4; ++ii)
 	{
-		perror("Server::Server - Error binding socket");
-		close(sfd); sfd = -1; return;
-	}
-
-	if (listen(sfd,1) < 0)
-	{
-		perror("Server::Server - Error listening on socket");
-		close(sfd); sfd = -1; return;
-	}
-	int psd = accept(sfd, 0, 0);
-	close(sfd);
-	sfd = psd;
-	if (sfd < 0)
-	{
-		perror("Server::Server - Error accepting connection");
-		close(sfd); sfd = -1; return;
-	}
-
-
-	for(;;) 
-	{
-		cc=recv(sfd,buf,sizeof(buf), 0) ;
-		if (cc == 0) exit (0);
-		buf[cc] = '\0';
-		printf("message received: %s\n", buf);
+		assert(network->GetMessage(setup[ii], 20));
 	}
+	//fprintf(stderr,"Done!\n");
+	return MovementResult::OK;
 }
 
-
-Client::Client(const Piece::Colour & newColour, const char * newName, const char * address) : NetworkController(newColour, newName)
+MovementResult NetworkSender::QueryMove(string & buffer)
 {
-	struct	sockaddr_in server;
-	struct  hostent *hp;
-
-
-	server.sin_family = AF_INET;
-	hp = gethostbyname("127.0.0.1");
-	bcopy ( hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
-	server.sin_port = htons(NetworkController::port);
-
-	if (connect(sfd, (struct sockaddr *) &server, sizeof(server)) < 0)
-	{
-		perror("Client::Client - Error connecting to server at address %s");
-		close(sfd); sfd = -1;
-		return;
-	}
-
-        for (;;) {
-	   send(sfd, "HI", 2,0 );
-           sleep(2);
-        }
-
+	MovementResult result = controller->QueryMove(buffer);
+	network->SendMessage("%s", buffer.c_str());
+	return result;
 }
-//EOF
-
 
+MovementResult NetworkReceiver::QueryMove(string & buffer)
+{
+	assert(network->GetMessage(buffer, 20));
+	return MovementResult::OK;
+}
diff --git a/judge/manager/network_controller.h b/judge/manager/network_controller.h
index 7b9af300f35910f7d0dcf3a8e6c7ca23f68dd3e1..31b0c92b06e69ac292daeb566abca14a4427d95a 100644
--- a/judge/manager/network_controller.h
+++ b/judge/manager/network_controller.h
@@ -1,51 +1,57 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <errno.h>
-
-
 #include "controller.h"
+#include "ai_controller.h"
+#include "human_controller.h"
+#include "network.h"
 
 #ifndef NETWORK_CONTROLLER_H
 #define NETWORK_CONTROLLER_H
 
-
 class NetworkController : public Controller
 {
 	public:
-		NetworkController(const Piece::Colour & newColour, const char * newName = "no-name");
-		virtual ~NetworkController();
+		NetworkController(const Piece::Colour & colour, Network * newNetwork) : Controller(colour), network(newNetwork) {}
+		virtual ~NetworkController() {}
 
-		virtual bool Valid() {return sfd != -1;}
-
-		virtual void Message(const char * string);
-		virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]) {fprintf(stderr, "NetworkController unimplemented!\n"); assert(false);}
-		virtual MovementResult QueryMove(std::string & buffer) {fprintf(stderr, "NetworkController unimplemented!\n"); assert(false);}
+		//virtual void Message(const char * message) = 0; 
+		virtual bool Valid() const {return network->Valid();}
 
 	protected:
-		int sfd; int cfd;
-		static const int port = 4950;	
+		Network * network;
 };
 
-class Server : public NetworkController
+class NetworkSender : public NetworkController
 {
 	public:
-		Server(const Piece::Colour & newColour, const char * newName = "no-name");
-		virtual ~Server() {}
+		NetworkSender(const Piece::Colour & colour, Controller * newController, Network * newNetwork) : NetworkController(colour, newNetwork), controller(newController) {}
+		virtual ~NetworkSender() {delete controller;}
+
+		virtual bool Valid() const {return NetworkController::Valid() && controller->Valid();}
+
+		virtual void Message(const char * message) 
+		{
+			//fprintf(stderr,"NetworkSender sending message %s to underlying controller\n", message);
+			controller->Message(message);
+		}
+
+		virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]);
+		virtual MovementResult QueryMove(std::string & buffer);
+
+	private:
+		Controller * controller;
+
 };
 
-class Client : public NetworkController
+class NetworkReceiver : public NetworkController
 {
 	public:
-		Client(const Piece::Colour & newColour, const char * newName = "no-name", const char * server="127.0.0.1");
-		virtual ~Client() {}
+		NetworkReceiver(const Piece::Colour & colour, Network * newNetwork) : NetworkController(colour, newNetwork) {}
+		virtual ~NetworkReceiver() {}
+
+		virtual void Message(const char * message) {} //Do nothing (Counter intuitive much)
+		virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]);
+		virtual MovementResult QueryMove(std::string & buffer);
+		
+
 };
 
 #endif //NETWORK_CONTROLLER_H