diff --git a/agents/bishop.py b/agents/bishop.py
index 8c88a1f5c9bd6227eb181a9acfe6e943c09c47e8..3c7738e540bc9d17f2496d6ff6e137089e07998a 100755
--- a/agents/bishop.py
+++ b/agents/bishop.py
@@ -291,8 +291,8 @@ def main(argv):
 	
 	agent = Agent(argv[0], colour) # Creates your agent
 
-	graphics = AgentGraphics(agent.board, title="Agent Bishop (" + str(colour) + ") - DEBUG VIEW")
-	graphics.start()
+	#graphics = AgentGraphics(agent.board, title="Agent Bishop (" + str(colour) + ") - DEBUG VIEW")
+	#graphics.start()
 
 	# Plays quantum chess using your agent
 	while True:
@@ -312,8 +312,8 @@ def main(argv):
 		else:
 			agent.update(line) # Updates agent.board
 
-	graphics.stop()
-	graphics.join()
+	#graphics.stop()
+	#graphics.join()
 	return 0
 
 # Don't touch this
diff --git a/agents/win32_bishop.bat b/agents/win32_bishop.bat
new file mode 100755
index 0000000000000000000000000000000000000000..92d9440cdb3487b817a4047dd2555e3f931456c0
--- /dev/null
+++ b/agents/win32_bishop.bat
@@ -0,0 +1,4 @@
+:: Replace the path to the python interpreter if necessary
+:: Picking this in qchess *should* work for running bishop.py
+:: I hope
+C:\\Python27\\python.exe bishop.py
diff --git a/qchess/Makefile b/qchess/Makefile
index 2ad3fefe0ff88665f8af00fe8e25317385f7fcfa..9da58858ffaa9a10c5691c1b62c1ca47c42545d2 100644
--- a/qchess/Makefile
+++ b/qchess/Makefile
@@ -1,16 +1,40 @@
-# Makefile that builds qchess.py from the component files
+# Makefile that builds qchess for UCC::Progcomp2013
 
-TARGET = qchess.py
-COMPONENTS = piece.py board.py player.py network.py thread_util.py game.py graphics.py main.py
-#COMPONENTS=$(shell ls *.py | tr '\t' '\n' | grep -v $(TARGET))
+SCRIPT=qchess.py
+DLL_PATH=win32_dll
 
-$(TARGET) : $(COMPONENTS)
-	echo "#!/usr/bin/python -u" > $(TARGET)
-	for f in $(COMPONENTS); do echo "# +++ $$f +++ #" >> $(TARGET); cat $$f >> $(TARGET); echo "# --- $$f --- #" >> $(TARGET); done
-	echo "# EOF - created from make on $$(date)" >> $(TARGET)
-	chmod u+x $(TARGET)
+all : python_native frozen
+
+frozen : win32_frozen linux64_frozen
+	cd build; for d in $$(ls); do zip -r $$d.zip $$d; rm -r $$d; done
+
+python_native : 
+	make -C src
+	mv src/$(SCRIPT) ./
+
+images :
+	cd tools; python image_builder.py 
+
+win32_frozen : $(SCRIPT) images
+	sed -i 's:create_images(grid_sz):load_images():g' $(SCRIPT)
+	wine "C:\\Python27\\python.exe" build.py build
+	for d in $$(ls $(DLL_PATH)); do cp $(DLL_PATH)/$$d build/exe.win32-2.7/; done
+	for b in $$(ls build); do if [ -d build/$$b ]; then cp -r data build/$$b; fi; done
+	sed -i 's:load_images():create_images(grid_sz):g' $(SCRIPT)
+
+linux64_frozen : $(SCRIPT) images
+	sed -i 's:create_images(grid_sz):load_images():g' $(SCRIPT)
+	python build.py build
+	for b in $$(ls build); do if [ -d build/$$b ]; then cp -r data build/$$b; fi; done
+	sed -i 's:load_images():create_images(grid_sz):g' $(SCRIPT)	
+	
+	
 
 clean :
+	make -C src clean
+	rm -f $(SCRIPT)
 	rm -f *~
-	rm -f *.pyc
-	rm -f $(TARGET)
+	rm -rf build
+	rm -rf data/images
+	rm -f tools/*~
+	rm -f tools/*.pyc
diff --git a/qchess/build.py b/qchess/build.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d854ddd28febaae33d73f38f8c3f5918460ad4c
--- /dev/null
+++ b/qchess/build.py
@@ -0,0 +1,4 @@
+import sys
+from cx_Freeze import setup, Executable
+
+setup(name="qchess", executables=[Executable("qchess.py")])
diff --git a/qchess/build/exe.linux-x86_64-2.7.zip b/qchess/build/exe.linux-x86_64-2.7.zip
new file mode 100644
index 0000000000000000000000000000000000000000..41103d12600d24adbce56639cff4d43c26033861
Binary files /dev/null and b/qchess/build/exe.linux-x86_64-2.7.zip differ
diff --git a/qchess/build/exe.win32-2.7.zip b/qchess/build/exe.win32-2.7.zip
new file mode 100644
index 0000000000000000000000000000000000000000..4ef51c0f37a7af4ca804a2b82b809606d7fd61b4
Binary files /dev/null and b/qchess/build/exe.win32-2.7.zip differ
diff --git a/qchess/qchess.py b/qchess/qchess.py
index 501b3fd8e64a05bfca256c52cea94aea335118f8..8347a753272162510b1d535035c34ee33473d804 100755
--- a/qchess/qchess.py
+++ b/qchess/qchess.py
@@ -1,5 +1,4 @@
 #!/usr/bin/python -u
-# +++ piece.py +++ #
 import random
 
 # I know using non-abreviated strings is inefficient, but this is python, who cares?
@@ -96,7 +95,6 @@ class Piece():
 
 	# The sad moment when you realise that you do not understand anything about a subject you studied for 4 years...
 # --- piece.py --- #
-# +++ board.py +++ #
 [w,h] = [8,8] # Width and height of board(s)
 
 # Class to represent a quantum chess board
@@ -501,11 +499,11 @@ class Board():
 	def on_board(self, x, y):
 		return (x >= 0 and x < w) and (y >= 0 and y < h)
 # --- board.py --- #
-# +++ player.py +++ #
 import subprocess
 import select
 import platform
 
+
 agent_timeout = -1.0 # Timeout in seconds for AI players to make moves
 			# WARNING: Won't work for windows based operating systems
 
@@ -689,8 +687,80 @@ class AgentRandom(Player):
 
 	def quit(self, final_result):
 		pass
+
+
 # --- player.py --- #
-# +++ network.py +++ #
+import multiprocessing
+
+# Hacky alternative to using select for timing out players
+
+# WARNING: Do not wrap around HumanPlayer or things breakify
+
+class Sleeper(multiprocessing.Process):
+	def __init__(self, timeout):
+		multiprocessing.Process.__init__(self)
+		self.timeout = timeout
+
+	def run(self):
+		time.sleep(self.timeout)
+
+
+class Worker(multiprocessing.Process):
+	def __init__(self, function, args, q):
+		multiprocessing.Process.__init__(self)
+		self.function = function
+		self.args = args
+		self.q = q
+
+	def run(self):
+		#print str(self) + " runs " + str(self.function) + " with args " + str(self.args) 
+		self.q.put(self.function(*self.args))
+		
+		
+
+def TimeoutFunction(function, args, timeout):
+	q = multiprocessing.Queue()
+	w = Worker(function, args, q)
+	s = Sleeper(timeout)
+	w.start()
+	s.start()
+	while True: # Busy loop of crappyness
+		if not w.is_alive():
+			s.terminate()
+			result = q.get()
+			w.join()
+			#print "TimeoutFunction gets " + str(result)
+			return result
+		elif not s.is_alive():
+			w.terminate()
+			s.join()
+			raise Exception("UNRESPONSIVE")
+
+	
+		
+
+# A player that wraps another player and times out its moves
+# Uses threads
+# A (crappy) alternative to the use of select()
+class TimeoutPlayer(Player):
+	def __init__(self, base_player, timeout):
+		Player.__init__(self, base_player.name, base_player.colour)
+		self.base_player = base_player
+		self.timeout = timeout
+		
+	def select(self):
+		return TimeoutFunction(self.base_player.select, [], self.timeout)
+		
+	
+	def get_move(self):
+		return TimeoutFunction(self.base_player.get_move, [], self.timeout)
+
+	def update(self, result):
+		return TimeoutFunction(self.base_player.update, [result], self.timeout)
+
+	def quit(self, final_result):
+		return TimeoutFunction(self.base_player.quit, [final_result], self.timeout)
+# --- timeout_player.py --- #
 import socket
 import select
 
@@ -883,7 +953,6 @@ class NetworkReceiver(Player,Network):
 		self.src.close()
 	
 # --- network.py --- #
-# +++ thread_util.py +++ #
 import threading
 
 # A thread that can be stopped!
@@ -900,7 +969,6 @@ class StoppableThread(threading.Thread):
 	def stopped(self):
 		return self._stop.isSet()
 # --- thread_util.py --- #
-# +++ game.py +++ #
 
 # A thread that runs the game
 class GameThread(StoppableThread):
@@ -925,7 +993,8 @@ class GameThread(StoppableThread):
 						self.state["turn"] = p.base_player # "turn" contains the player who's turn it is
 					else:
 						self.state["turn"] = p
-				try:
+				#try:
+				if True:
 					[x,y] = p.select() # Player selects a square
 					if self.stopped():
 						break
@@ -983,13 +1052,13 @@ class GameThread(StoppableThread):
 							graphics.state["moves"] = None
 
 			# Commented out exception stuff for now, because it makes it impossible to tell if I made an IndentationError somewhere
-				except Exception,e:
-					result = e.message
-					#sys.stderr.write(result + "\n")
-					
-					self.stop()
-					with self.lock:
-						self.final_result = self.state["turn"].colour + " " + e.message
+			#	except Exception,e:
+			#		result = e.message
+			#		#sys.stderr.write(result + "\n")
+			#		
+			#		self.stop()
+			#		with self.lock:
+			#			self.final_result = self.state["turn"].colour + " " + e.message
 
 				if self.board.king["black"] == None:
 					if self.board.king["white"] == None:
@@ -1023,8 +1092,8 @@ def opponent(colour):
 	else:
 		return "white"
 # --- game.py --- #
-# +++ graphics.py +++ #
 import pygame
+import os
 
 # Dictionary that stores the unicode character representations of the different pieces
 # Chess was clearly the reason why unicode was invented
@@ -1047,6 +1116,44 @@ piece_char = {"white" : {"king" : u'\u2654',
 images = {"white" : {}, "black" : {}}
 small_images = {"white" : {}, "black" : {}}
 
+def create_images(grid_sz, font_name=os.path.join(os.path.curdir, "data", "DejaVuSans.ttf")):
+
+	# Get the font sizes
+	l_size = 5*(grid_sz[0] / 8)
+	s_size = 3*(grid_sz[0] / 8)
+
+	for c in piece_char.keys():
+		
+		if c == "black":
+			for p in piece_char[c].keys():
+				images[c].update({p : pygame.font.Font(font_name, l_size).render(piece_char[c][p], True,(0,0,0))})
+				small_images[c].update({p : pygame.font.Font(font_name, s_size).render(piece_char[c][p],True,(0,0,0))})		
+		elif c == "white":
+			for p in piece_char[c].keys():
+				images[c].update({p : pygame.font.Font(font_name, l_size+1).render(piece_char["black"][p], True,(255,255,255))})
+				images[c][p].blit(pygame.font.Font(font_name, l_size).render(piece_char[c][p], True,(0,0,0)),(0,0))
+				small_images[c].update({p : pygame.font.Font(font_name, s_size+1).render(piece_char["black"][p],True,(255,255,255))})
+				small_images[c][p].blit(pygame.font.Font(font_name, s_size).render(piece_char[c][p],True,(0,0,0)),(0,0))
+	
+
+def load_images(image_dir=os.path.join(os.path.curdir, "data", "images")):
+	if not os.path.exists(image_dir):
+		raise Exception("Couldn't load images from " + image_dir + " (path doesn't exist)")
+	for c in piece_char.keys():
+		for p in piece_char[c].keys():
+			images[c].update({p : pygame.image.load(os.path.join(image_dir, c + "_" + p + ".png"))})
+			small_images[c].update({p : pygame.image.load(os.path.join(image_dir, c + "_" + p + "_small.png"))})
+# --- images.py --- #
+import pygame
+
+
+
+
+
+
+
+
+
 # A thread to make things pretty
 class GraphicsThread(StoppableThread):
 	def __init__(self, board, title = "UCC::Progcomp 2013 - QChess", grid_sz = [80,80]):
@@ -1056,25 +1163,27 @@ class GraphicsThread(StoppableThread):
 		pygame.init()
 		self.window = pygame.display.set_mode((grid_sz[0] * w, grid_sz[1] * h))
 		pygame.display.set_caption(title)
+
+		#print "Initialised properly"
+		
 		self.grid_sz = grid_sz[:]
 		self.state = {"select" : None, "dest" : None, "moves" : None, "overlay" : None, "coverage" : None}
 		self.error = 0
 		self.lock = threading.RLock()
 		self.cond = threading.Condition()
 
-		# Get the font sizes
-		l_size = 5*(self.grid_sz[0] / 8)
-		s_size = 3*(self.grid_sz[0] / 8)
-		for p in piece_types.keys():
-			c = "black"
-			images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", l_size).render(piece_char[c][p], True,(0,0,0))})
-			small_images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", s_size).render(piece_char[c][p],True,(0,0,0))})
-			c = "white"
+		#print "Test font"
+		pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), 32).render("Hello", True,(0,0,0))
+
+		#create_images(grid_sz)
+		create_images(grid_sz)
 
-			images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", l_size+1).render(piece_char["black"][p], True,(255,255,255))})
-			images[c][p].blit(pygame.font.Font("data/DejaVuSans.ttf", l_size).render(piece_char[c][p], True,(0,0,0)),(0,0))
-			small_images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", s_size+1).render(piece_char["black"][p],True,(255,255,255))})
-			small_images[c][p].blit(pygame.font.Font("data/DejaVuSans.ttf", s_size).render(piece_char[c][p],True,(0,0,0)),(0,0))
+		"""
+		for c in images.keys():
+			for p in images[c].keys():
+				images[c][p] = images[c][p].convert(self.window)
+				small_images[c][p] = small_images[c][p].convert(self.window)
+		"""
 
 		
 	
@@ -1085,10 +1194,13 @@ class GraphicsThread(StoppableThread):
 		
 		while not self.stopped():
 			
+			#print "Display grid"
 			self.board.display_grid(window = self.window, grid_sz = self.grid_sz) # Draw the board
 
+			#print "Display overlay"
 			self.overlay()
 
+			#print "Display pieces"
 			self.board.display_pieces(window = self.window, grid_sz = self.grid_sz) # Draw the board		
 
 			pygame.display.flip()
@@ -1238,7 +1350,7 @@ class GraphicsThread(StoppableThread):
 						mp = [self.grid_sz[i] * [x,y][i] for i in range(2)]
 						square_img.fill(pygame.Color(255,0,255,int(m[x][y] * 128))) # Draw in purple
 						self.window.blit(square_img, mp)
-						font = pygame.font.Font(None, 14)
+						font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), 14)
 						text = font.render("{0:.2f}".format(round(m[x][y],2)), 1, pygame.Color(0,0,0))
 						self.window.blit(text, mp)
 				
@@ -1250,7 +1362,7 @@ class GraphicsThread(StoppableThread):
 				mp = [self.grid_sz[i] * [p.x,p.y][i] for i in range(2)]
 				square_img.fill(pygame.Color(0,255,255, int(m[p] * 196))) # Draw in pale blue
 				self.window.blit(square_img, mp)
-				font = pygame.font.Font(None, 14)
+				font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), 14)
 				text = font.render("{0:.2f}".format(round(m[p],2)), 1, pygame.Color(0,0,0))
 				self.window.blit(text, mp)
 			# Draw a square where the mouse is
@@ -1273,8 +1385,9 @@ class GraphicsThread(StoppableThread):
 			self.window.blit(square_img, mp)
 
 	# Message in a bottle
-	def message(self, string, pos = None, colour = None, font_size = 32):
-		font = pygame.font.Font(None, font_size)
+	def message(self, string, pos = None, colour = None, font_size = 20):
+		#print "Drawing message..."
+		font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), font_size)
 		if colour == None:
 			colour = pygame.Color(0,0,0)
 		
@@ -1332,11 +1445,13 @@ class GraphicsThread(StoppableThread):
 
 
 	# Function to pick a button
-	def SelectButton(self, choices, prompt = None, font_size=32):
+	def SelectButton(self, choices, prompt = None, font_size=20):
+
+		#print "Select button called!"
 		self.board.display_grid(self.window, self.grid_sz)
 		if prompt != None:
 			self.message(prompt)
-		font = pygame.font.Font(None, font_size)
+		font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), font_size)
 		targets = []
 		sz = self.window.get_size()
 
@@ -1385,6 +1500,7 @@ class GraphicsThread(StoppableThread):
 	def SelectPlayers(self, players = []):
 
 
+		#print "SelectPlayers called"
 		
 		missing = ["white", "black"]
 		for p in players:
@@ -1393,11 +1509,11 @@ class GraphicsThread(StoppableThread):
 		for colour in missing:
 			
 			
-			choice = self.SelectButton(["human", "agent", "network"],prompt = "Choose " + str(colour) + " player", font_size=32)
+			choice = self.SelectButton(["human", "agent", "network"],prompt = "Choose " + str(colour) + " player")
 			if choice == 0:
 				players.append(HumanPlayer("human", colour))
 			elif choice == 1:
-				try:
+				if True:
 					import Tkinter
 					from tkFileDialog import askopenfilename
 					root = Tkinter.Tk() # Need a root to make Tkinter behave
@@ -1407,7 +1523,7 @@ class GraphicsThread(StoppableThread):
 					if path == "":
 						return self.SelectPlayers()
 					players.append(make_player(path, colour))	
-				except Exception,e:
+				else:
 					print "Exception was " + str(e.message)
 					p = None
 					while p == None:
@@ -1456,7 +1572,6 @@ class GraphicsThread(StoppableThread):
 				
 			
 # --- graphics.py --- #
-# +++ main.py +++ #
 #!/usr/bin/python -u
 
 # Do you know what the -u does? It unbuffers stdin and stdout
@@ -1558,11 +1673,8 @@ def main(argv):
 			# Timeout
 			if len(arg[2:].split("=")) == 1:
 				agent_timeout = -1
-			elif platform.system() != "Windows": # Windows breaks this option
-				agent_timeout = float(arg[2:].split("=")[1])
 			else:
-				sys.stderr.write(sys.argv[0] + " : Warning - You are using Windows\n")
-				agent_timeout = -1
+				agent_timeout = float(arg[2:].split("=")[1])
 				
 		elif (arg[1] == '-' and arg[2:] == "help"):
 			# Help
@@ -1578,6 +1690,7 @@ def main(argv):
 	if graphics_enabled == True:
 		try:
 			graphics = GraphicsThread(board, grid_sz = [64,64]) # Construct a GraphicsThread!
+
 		except Exception,e:
 			graphics = None
 			sys.stderr.write(sys.argv[0] + " : Got exception trying to initialise graphics\n"+str(e.message)+"\nDisabled graphics\n")
@@ -1617,6 +1730,22 @@ def main(argv):
 				graphics.message("Connecting to " + p.colour + " player...")
 			p.connect()
 
+	
+	# If using windows, select won't work; use horrible TimeoutPlayer hack
+	if agent_timeout > 0 and platform.system() == "Windows":
+		sys.stderr.write(sys.argv[0] + " : Warning - You are using Windows\n")
+		sys.stderr.write(sys.argv[0] + " :	   - Timeouts will be implemented with a terrible hack.\n")
+
+		for i in range(len(players)):
+			if isinstance(players[i], AgentPlayer):
+				players[i] = TimeoutPlayer(players[i], agent_timeout)
+
+	# Could potentially wrap TimeoutPlayer around internal classes...
+	# But that would suck
+
+		
+			
+
 
 	# Construct a GameThread! Make it global! Damn the consequences!
 	game = GameThread(board, players) 
@@ -1636,4 +1765,4 @@ def main(argv):
 if __name__ == "__main__":
 	sys.exit(main(sys.argv))
 # --- main.py --- #
-# EOF - created from make on Thu Jan 24 17:04:54 WST 2013
+# EOF - created from make on Mon Jan 28 22:52:28 WST 2013
diff --git a/qchess/src/Makefile b/qchess/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..8ed1944638d7bf27e0d9570faa3c5b14043acc23
--- /dev/null
+++ b/qchess/src/Makefile
@@ -0,0 +1,16 @@
+# Makefile that builds qchess.py from the component files
+
+TARGET = qchess.py
+COMPONENTS = piece.py board.py player.py timeout_player.py network.py thread_util.py game.py images.py graphics.py main.py
+#COMPONENTS=$(shell ls *.py | tr '\t' '\n' | grep -v $(TARGET))
+
+$(TARGET) : $(COMPONENTS)
+	echo "#!/usr/bin/python -u" > $(TARGET)
+	for f in $(COMPONENTS); do echo "# +++ $$f +++ #" >> ../$(TARGET); cat $$f >> $(TARGET); echo "# --- $$f --- #" >> $(TARGET); done
+	echo "# EOF - created from make on $$(date)" >> $(TARGET)
+	chmod u+x $(TARGET)
+
+clean :
+	rm -f *~
+	rm -f *.pyc
+	rm -f $(TARGET)
diff --git a/qchess/board.py b/qchess/src/board.py
similarity index 100%
rename from qchess/board.py
rename to qchess/src/board.py
diff --git a/qchess/game.py b/qchess/src/game.py
similarity index 92%
rename from qchess/game.py
rename to qchess/src/game.py
index efca0f8a6825fb6997f176c8f3fed9ce7735fc3d..934c043d5cbd8f63ecefadc59e887a7f24db46e8 100644
--- a/qchess/game.py
+++ b/qchess/src/game.py
@@ -22,7 +22,8 @@ class GameThread(StoppableThread):
 						self.state["turn"] = p.base_player # "turn" contains the player who's turn it is
 					else:
 						self.state["turn"] = p
-				try:
+				#try:
+				if True:
 					[x,y] = p.select() # Player selects a square
 					if self.stopped():
 						break
@@ -80,13 +81,13 @@ class GameThread(StoppableThread):
 							graphics.state["moves"] = None
 
 			# Commented out exception stuff for now, because it makes it impossible to tell if I made an IndentationError somewhere
-				except Exception,e:
-					result = e.message
-					#sys.stderr.write(result + "\n")
-					
-					self.stop()
-					with self.lock:
-						self.final_result = self.state["turn"].colour + " " + e.message
+			#	except Exception,e:
+			#		result = e.message
+			#		#sys.stderr.write(result + "\n")
+			#		
+			#		self.stop()
+			#		with self.lock:
+			#			self.final_result = self.state["turn"].colour + " " + e.message
 
 				if self.board.king["black"] == None:
 					if self.board.king["white"] == None:
diff --git a/qchess/graphics.py b/qchess/src/graphics.py
similarity index 85%
rename from qchess/graphics.py
rename to qchess/src/graphics.py
index 8e2a5fae864de8289b45708bad12437c3d993449..c068900e64b5d6dbfc517765a7c84f2dd787de64 100644
--- a/qchess/graphics.py
+++ b/qchess/src/graphics.py
@@ -1,25 +1,12 @@
 import pygame
 
-# Dictionary that stores the unicode character representations of the different pieces
-# Chess was clearly the reason why unicode was invented
-# For some reason none of the pygame chess implementations I found used them!
-piece_char = {"white" : {"king" : u'\u2654',
-			 "queen" : u'\u2655',
-			 "rook" : u'\u2656',
-			 "bishop" : u'\u2657',
-			 "knight" : u'\u2658',
-			 "pawn" : u'\u2659',
-			 "unknown" : '?'},
-		"black" : {"king" : u'\u265A',
-			 "queen" : u'\u265B',
-			 "rook" : u'\u265C',
-			 "bishop" : u'\u265D',
-			 "knight" : u'\u265E',
-			 "pawn" : u'\u265F',
-			 "unknown" : '?'}}
-
-images = {"white" : {}, "black" : {}}
-small_images = {"white" : {}, "black" : {}}
+
+
+
+
+
+
+
 
 # A thread to make things pretty
 class GraphicsThread(StoppableThread):
@@ -30,25 +17,27 @@ class GraphicsThread(StoppableThread):
 		pygame.init()
 		self.window = pygame.display.set_mode((grid_sz[0] * w, grid_sz[1] * h))
 		pygame.display.set_caption(title)
+
+		#print "Initialised properly"
+		
 		self.grid_sz = grid_sz[:]
 		self.state = {"select" : None, "dest" : None, "moves" : None, "overlay" : None, "coverage" : None}
 		self.error = 0
 		self.lock = threading.RLock()
 		self.cond = threading.Condition()
 
-		# Get the font sizes
-		l_size = 5*(self.grid_sz[0] / 8)
-		s_size = 3*(self.grid_sz[0] / 8)
-		for p in piece_types.keys():
-			c = "black"
-			images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", l_size).render(piece_char[c][p], True,(0,0,0))})
-			small_images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", s_size).render(piece_char[c][p],True,(0,0,0))})
-			c = "white"
+		#print "Test font"
+		pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), 32).render("Hello", True,(0,0,0))
 
-			images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", l_size+1).render(piece_char["black"][p], True,(255,255,255))})
-			images[c][p].blit(pygame.font.Font("data/DejaVuSans.ttf", l_size).render(piece_char[c][p], True,(0,0,0)),(0,0))
-			small_images[c].update({p : pygame.font.Font("data/DejaVuSans.ttf", s_size+1).render(piece_char["black"][p],True,(255,255,255))})
-			small_images[c][p].blit(pygame.font.Font("data/DejaVuSans.ttf", s_size).render(piece_char[c][p],True,(0,0,0)),(0,0))
+		#load_images()
+		create_images(grid_sz)
+
+		"""
+		for c in images.keys():
+			for p in images[c].keys():
+				images[c][p] = images[c][p].convert(self.window)
+				small_images[c][p] = small_images[c][p].convert(self.window)
+		"""
 
 		
 	
@@ -59,10 +48,13 @@ class GraphicsThread(StoppableThread):
 		
 		while not self.stopped():
 			
+			#print "Display grid"
 			self.board.display_grid(window = self.window, grid_sz = self.grid_sz) # Draw the board
 
+			#print "Display overlay"
 			self.overlay()
 
+			#print "Display pieces"
 			self.board.display_pieces(window = self.window, grid_sz = self.grid_sz) # Draw the board		
 
 			pygame.display.flip()
@@ -212,7 +204,7 @@ class GraphicsThread(StoppableThread):
 						mp = [self.grid_sz[i] * [x,y][i] for i in range(2)]
 						square_img.fill(pygame.Color(255,0,255,int(m[x][y] * 128))) # Draw in purple
 						self.window.blit(square_img, mp)
-						font = pygame.font.Font(None, 14)
+						font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), 14)
 						text = font.render("{0:.2f}".format(round(m[x][y],2)), 1, pygame.Color(0,0,0))
 						self.window.blit(text, mp)
 				
@@ -224,7 +216,7 @@ class GraphicsThread(StoppableThread):
 				mp = [self.grid_sz[i] * [p.x,p.y][i] for i in range(2)]
 				square_img.fill(pygame.Color(0,255,255, int(m[p] * 196))) # Draw in pale blue
 				self.window.blit(square_img, mp)
-				font = pygame.font.Font(None, 14)
+				font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), 14)
 				text = font.render("{0:.2f}".format(round(m[p],2)), 1, pygame.Color(0,0,0))
 				self.window.blit(text, mp)
 			# Draw a square where the mouse is
@@ -247,8 +239,9 @@ class GraphicsThread(StoppableThread):
 			self.window.blit(square_img, mp)
 
 	# Message in a bottle
-	def message(self, string, pos = None, colour = None, font_size = 32):
-		font = pygame.font.Font(None, font_size)
+	def message(self, string, pos = None, colour = None, font_size = 20):
+		#print "Drawing message..."
+		font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), font_size)
 		if colour == None:
 			colour = pygame.Color(0,0,0)
 		
@@ -306,11 +299,13 @@ class GraphicsThread(StoppableThread):
 
 
 	# Function to pick a button
-	def SelectButton(self, choices, prompt = None, font_size=32):
+	def SelectButton(self, choices, prompt = None, font_size=20):
+
+		#print "Select button called!"
 		self.board.display_grid(self.window, self.grid_sz)
 		if prompt != None:
 			self.message(prompt)
-		font = pygame.font.Font(None, font_size)
+		font = pygame.font.Font(os.path.join(os.path.curdir, "data", "DejaVuSans.ttf"), font_size)
 		targets = []
 		sz = self.window.get_size()
 
@@ -359,6 +354,7 @@ class GraphicsThread(StoppableThread):
 	def SelectPlayers(self, players = []):
 
 
+		#print "SelectPlayers called"
 		
 		missing = ["white", "black"]
 		for p in players:
@@ -367,11 +363,11 @@ class GraphicsThread(StoppableThread):
 		for colour in missing:
 			
 			
-			choice = self.SelectButton(["human", "agent", "network"],prompt = "Choose " + str(colour) + " player", font_size=32)
+			choice = self.SelectButton(["human", "agent", "network"],prompt = "Choose " + str(colour) + " player")
 			if choice == 0:
 				players.append(HumanPlayer("human", colour))
 			elif choice == 1:
-				try:
+				if True:
 					import Tkinter
 					from tkFileDialog import askopenfilename
 					root = Tkinter.Tk() # Need a root to make Tkinter behave
@@ -381,7 +377,7 @@ class GraphicsThread(StoppableThread):
 					if path == "":
 						return self.SelectPlayers()
 					players.append(make_player(path, colour))	
-				except Exception,e:
+				else:
 					print "Exception was " + str(e.message)
 					p = None
 					while p == None:
diff --git a/qchess/src/images.py b/qchess/src/images.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd79b107c71d94e61cc7ac7f26b19a773209928c
--- /dev/null
+++ b/qchess/src/images.py
@@ -0,0 +1,51 @@
+import pygame
+import os
+
+# Dictionary that stores the unicode character representations of the different pieces
+# Chess was clearly the reason why unicode was invented
+# For some reason none of the pygame chess implementations I found used them!
+piece_char = {"white" : {"king" : u'\u2654',
+			 "queen" : u'\u2655',
+			 "rook" : u'\u2656',
+			 "bishop" : u'\u2657',
+			 "knight" : u'\u2658',
+			 "pawn" : u'\u2659',
+			 "unknown" : '?'},
+		"black" : {"king" : u'\u265A',
+			 "queen" : u'\u265B',
+			 "rook" : u'\u265C',
+			 "bishop" : u'\u265D',
+			 "knight" : u'\u265E',
+			 "pawn" : u'\u265F',
+			 "unknown" : '?'}}
+
+images = {"white" : {}, "black" : {}}
+small_images = {"white" : {}, "black" : {}}
+
+def create_images(grid_sz, font_name=os.path.join(os.path.curdir, "data", "DejaVuSans.ttf")):
+
+	# Get the font sizes
+	l_size = 5*(grid_sz[0] / 8)
+	s_size = 3*(grid_sz[0] / 8)
+
+	for c in piece_char.keys():
+		
+		if c == "black":
+			for p in piece_char[c].keys():
+				images[c].update({p : pygame.font.Font(font_name, l_size).render(piece_char[c][p], True,(0,0,0))})
+				small_images[c].update({p : pygame.font.Font(font_name, s_size).render(piece_char[c][p],True,(0,0,0))})		
+		elif c == "white":
+			for p in piece_char[c].keys():
+				images[c].update({p : pygame.font.Font(font_name, l_size+1).render(piece_char["black"][p], True,(255,255,255))})
+				images[c][p].blit(pygame.font.Font(font_name, l_size).render(piece_char[c][p], True,(0,0,0)),(0,0))
+				small_images[c].update({p : pygame.font.Font(font_name, s_size+1).render(piece_char["black"][p],True,(255,255,255))})
+				small_images[c][p].blit(pygame.font.Font(font_name, s_size).render(piece_char[c][p],True,(0,0,0)),(0,0))
+	
+
+def load_images(image_dir=os.path.join(os.path.curdir, "data", "images")):
+	if not os.path.exists(image_dir):
+		raise Exception("Couldn't load images from " + image_dir + " (path doesn't exist)")
+	for c in piece_char.keys():
+		for p in piece_char[c].keys():
+			images[c].update({p : pygame.image.load(os.path.join(image_dir, c + "_" + p + ".png"))})
+			small_images[c].update({p : pygame.image.load(os.path.join(image_dir, c + "_" + p + "_small.png"))})
diff --git a/qchess/main.py b/qchess/src/main.py
similarity index 89%
rename from qchess/main.py
rename to qchess/src/main.py
index 82aad82fd66545a64335fe6a113c8c801e3a4945..8dac056306f38d70b6f725c25e950f56c640b9af 100644
--- a/qchess/main.py
+++ b/qchess/src/main.py
@@ -99,11 +99,8 @@ def main(argv):
 			# Timeout
 			if len(arg[2:].split("=")) == 1:
 				agent_timeout = -1
-			elif platform.system() != "Windows": # Windows breaks this option
-				agent_timeout = float(arg[2:].split("=")[1])
 			else:
-				sys.stderr.write(sys.argv[0] + " : Warning - You are using Windows\n")
-				agent_timeout = -1
+				agent_timeout = float(arg[2:].split("=")[1])
 				
 		elif (arg[1] == '-' and arg[2:] == "help"):
 			# Help
@@ -119,6 +116,7 @@ def main(argv):
 	if graphics_enabled == True:
 		try:
 			graphics = GraphicsThread(board, grid_sz = [64,64]) # Construct a GraphicsThread!
+
 		except Exception,e:
 			graphics = None
 			sys.stderr.write(sys.argv[0] + " : Got exception trying to initialise graphics\n"+str(e.message)+"\nDisabled graphics\n")
@@ -158,6 +156,22 @@ def main(argv):
 				graphics.message("Connecting to " + p.colour + " player...")
 			p.connect()
 
+	
+	# If using windows, select won't work; use horrible TimeoutPlayer hack
+	if agent_timeout > 0 and platform.system() == "Windows":
+		sys.stderr.write(sys.argv[0] + " : Warning - You are using Windows\n")
+		sys.stderr.write(sys.argv[0] + " :	   - Timeouts will be implemented with a terrible hack.\n")
+
+		for i in range(len(players)):
+			if isinstance(players[i], AgentPlayer):
+				players[i] = TimeoutPlayer(players[i], agent_timeout)
+
+	# Could potentially wrap TimeoutPlayer around internal classes...
+	# But that would suck
+
+		
+			
+
 
 	# Construct a GameThread! Make it global! Damn the consequences!
 	game = GameThread(board, players) 
diff --git a/qchess/network.py b/qchess/src/network.py
similarity index 100%
rename from qchess/network.py
rename to qchess/src/network.py
diff --git a/qchess/piece.py b/qchess/src/piece.py
similarity index 100%
rename from qchess/piece.py
rename to qchess/src/piece.py
diff --git a/qchess/player.py b/qchess/src/player.py
similarity index 99%
rename from qchess/player.py
rename to qchess/src/player.py
index ce0ec71f81d4baa47d970bb422d465e7da8db13a..3e6fabadb566b04e856d3ea4e9709345b7498558 100644
--- a/qchess/player.py
+++ b/qchess/src/player.py
@@ -2,6 +2,7 @@ import subprocess
 import select
 import platform
 
+
 agent_timeout = -1.0 # Timeout in seconds for AI players to make moves
 			# WARNING: Won't work for windows based operating systems
 
@@ -185,3 +186,5 @@ class AgentRandom(Player):
 
 	def quit(self, final_result):
 		pass
+
+
diff --git a/qchess/thread_util.py b/qchess/src/thread_util.py
similarity index 100%
rename from qchess/thread_util.py
rename to qchess/src/thread_util.py
diff --git a/qchess/src/timeout_player.py b/qchess/src/timeout_player.py
new file mode 100644
index 0000000000000000000000000000000000000000..36f9e204a90587cbdb4e20c71ae65da30e7e20a6
--- /dev/null
+++ b/qchess/src/timeout_player.py
@@ -0,0 +1,70 @@
+import multiprocessing
+
+# Hacky alternative to using select for timing out players
+
+# WARNING: Do not wrap around HumanPlayer or things breakify
+
+class Sleeper(multiprocessing.Process):
+	def __init__(self, timeout):
+		multiprocessing.Process.__init__(self)
+		self.timeout = timeout
+
+	def run(self):
+		time.sleep(self.timeout)
+
+
+class Worker(multiprocessing.Process):
+	def __init__(self, function, args, q):
+		multiprocessing.Process.__init__(self)
+		self.function = function
+		self.args = args
+		self.q = q
+
+	def run(self):
+		#print str(self) + " runs " + str(self.function) + " with args " + str(self.args) 
+		self.q.put(self.function(*self.args))
+		
+		
+
+def TimeoutFunction(function, args, timeout):
+	q = multiprocessing.Queue()
+	w = Worker(function, args, q)
+	s = Sleeper(timeout)
+	w.start()
+	s.start()
+	while True: # Busy loop of crappyness
+		if not w.is_alive():
+			s.terminate()
+			result = q.get()
+			w.join()
+			#print "TimeoutFunction gets " + str(result)
+			return result
+		elif not s.is_alive():
+			w.terminate()
+			s.join()
+			raise Exception("UNRESPONSIVE")
+
+	
+		
+
+# A player that wraps another player and times out its moves
+# Uses threads
+# A (crappy) alternative to the use of select()
+class TimeoutPlayer(Player):
+	def __init__(self, base_player, timeout):
+		Player.__init__(self, base_player.name, base_player.colour)
+		self.base_player = base_player
+		self.timeout = timeout
+		
+	def select(self):
+		return TimeoutFunction(self.base_player.select, [], self.timeout)
+		
+	
+	def get_move(self):
+		return TimeoutFunction(self.base_player.get_move, [], self.timeout)
+
+	def update(self, result):
+		return TimeoutFunction(self.base_player.update, [result], self.timeout)
+
+	def quit(self, final_result):
+		return TimeoutFunction(self.base_player.quit, [final_result], self.timeout)
diff --git a/qchess/tools/image_builder.py b/qchess/tools/image_builder.py
new file mode 100644
index 0000000000000000000000000000000000000000..c9760eff621db87432ccd2063bc4ed577fe0d1b3
--- /dev/null
+++ b/qchess/tools/image_builder.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+import sys
+from images import *
+
+def main(argv):
+	pygame.init()
+	try:
+		target = str(argv[1])
+	except:
+		target = os.path.join(os.path.curdir, "..","data","images")
+
+	try:
+		grid_size = int(argv[2])
+	except:
+		grid_size = 64
+		
+
+	if not os.path.exists(target):
+		os.mkdir(target)
+
+	create_images([grid_size, grid_size], font_name=os.path.join(os.path.curdir, "..", "data", "DejaVuSans.ttf"))
+
+	for colour in piece_char.keys():
+		for piece in piece_char[colour].keys():
+			pygame.image.save(images[colour][piece], os.path.join(target,str(colour)+"_"+str(piece)+".png"))
+			pygame.image.save(small_images[colour][piece], os.path.join(target,str(colour)+"_"+str(piece)+"_small.png"))
+
+	pygame.quit()
+	return 0
+
+if __name__ == "__main__":
+	sys.exit(main(sys.argv))
diff --git a/qchess/tools/images.py b/qchess/tools/images.py
new file mode 120000
index 0000000000000000000000000000000000000000..a1ec45aa605d80fd643857c0e37ae8ff18a8013b
--- /dev/null
+++ b/qchess/tools/images.py
@@ -0,0 +1 @@
+../src/images.py
\ No newline at end of file
diff --git a/qchess/tools/images.pyc b/qchess/tools/images.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0a48eb3c42ed7b00e35fe3a13bf90f07bd66a2be
Binary files /dev/null and b/qchess/tools/images.pyc differ
diff --git a/qchess/update.sh b/qchess/update.sh
deleted file mode 100644
index bec40eacca5f653b0ac81b954050cb62ecffe0a5..0000000000000000000000000000000000000000
--- a/qchess/update.sh
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/bash
-
-# I still can't believe I am doing this
-
-# This updates the component files from the target, as well as the target from the components
-# You can't do that with gnu make, because of the circular dependency
-# But this should probably not be used by any sane person
-
-exit 1
-
-target=qchess.py
-components="piece.py board.py player.py network.py thread_util.py game.py graphics.py main.py"
-# The below seems nicer, but doesn't work because things need to be imported in the right order :(
-#components=$(ls *.py | tr '\t' '\n' | grep -v $target)
-
-header="#!/usr/bin/python -u"
-footer="# EOF - created from update.sh on $(date)"
-
-
-
-# If the target was modified more recently than any of the components, update the component file
-target_mod=$(stat -c %Y $target 2>/dev/null)
-
-if [ $? -ne 0 ]; then
-	merge_required=true
-else
-	merge_required=true
-
-
-	for f in $components; do
-		
-		component_mod=$(stat -c %Y $f 2>/dev/null)
-		if [ $? -ne 0 ]; then
-			update_required=true
-		elif [ $component_mod -lt $target_mod ]; then
-			update_required=true
-		else
-			update_required=false
-		fi
-
-		if $update_required; then
-			echo "$0 - update $f from $target"
-			sanity=$(egrep "(+++ $f +++)|(--- $f ---)" $target | wc -l)
-			if [ $sanity -ne 2 ]; then
-				$(echo "$0 - $target does not have markers for $f in it!") 1>&2
-				exit 1
-			fi
-			cp $f $f~
-			new_contents=$(nawk "/+++ $f +++/, /--- $f ---/" $target | grep -v "+++ $f +++" | grep -v "\--- $f ---")
-			
-			echo "$new_contents" > $f
-		else
-			echo "$0 - $f is newer than $target"
-			merge_required=true
-		fi
-	done
-
-
-fi
-
-# If any components were modified more recently than the target, merge the components into the target
-if $merge_required; then
-	echo $header > $target
-	for f in $components; do
-		echo "$0 - merge $f into $target"
-		echo "# +++ $f +++ #" >> $target
-		cat $f >> $target
-		echo "# --- $f --- #" >> $target
-	done
-
-	echo $footer >> $target
-	chmod u+x $target
-fi
diff --git a/qchess/win32_dll/SDL.dll b/qchess/win32_dll/SDL.dll
new file mode 100644
index 0000000000000000000000000000000000000000..69fd61ecb81cf1423e7f387f87682540cabaff4a
Binary files /dev/null and b/qchess/win32_dll/SDL.dll differ
diff --git a/qchess/win32_dll/SDL_image.dll b/qchess/win32_dll/SDL_image.dll
new file mode 100644
index 0000000000000000000000000000000000000000..e891b16748723cda486e046a694660edebcec978
Binary files /dev/null and b/qchess/win32_dll/SDL_image.dll differ
diff --git a/qchess/win32_dll/SDL_mixer.dll b/qchess/win32_dll/SDL_mixer.dll
new file mode 100644
index 0000000000000000000000000000000000000000..89def7635876d1b176aa86a2c52075e0d69b39ee
Binary files /dev/null and b/qchess/win32_dll/SDL_mixer.dll differ
diff --git a/qchess/win32_dll/SDL_ttf.dll b/qchess/win32_dll/SDL_ttf.dll
new file mode 100644
index 0000000000000000000000000000000000000000..a8f1bcc1b08316b5a8866726a958a8a370bb9d4f
Binary files /dev/null and b/qchess/win32_dll/SDL_ttf.dll differ
diff --git a/qchess/win32_dll/jpeg.dll b/qchess/win32_dll/jpeg.dll
new file mode 100644
index 0000000000000000000000000000000000000000..72c33d246917d0a79a0121b4138f5c2f7ee0682e
Binary files /dev/null and b/qchess/win32_dll/jpeg.dll differ
diff --git a/qchess/win32_dll/libfreetype-6.dll b/qchess/win32_dll/libfreetype-6.dll
new file mode 100644
index 0000000000000000000000000000000000000000..3b2e69dfa9a7e55c7c27b7feb64a4c71f345aca1
Binary files /dev/null and b/qchess/win32_dll/libfreetype-6.dll differ
diff --git a/qchess/win32_dll/libjpeg-8.dll b/qchess/win32_dll/libjpeg-8.dll
new file mode 100644
index 0000000000000000000000000000000000000000..74285d2518b7257283dee41a6f512d5b0418623c
Binary files /dev/null and b/qchess/win32_dll/libjpeg-8.dll differ
diff --git a/qchess/win32_dll/libpng12-0.dll b/qchess/win32_dll/libpng12-0.dll
new file mode 100644
index 0000000000000000000000000000000000000000..f9709be371ee219560b8f14837e78f652754ac49
Binary files /dev/null and b/qchess/win32_dll/libpng12-0.dll differ
diff --git a/qchess/win32_dll/libpng15-15.dll b/qchess/win32_dll/libpng15-15.dll
new file mode 100644
index 0000000000000000000000000000000000000000..a5854d5db78e4099facf505e4621c957cf1e8b47
Binary files /dev/null and b/qchess/win32_dll/libpng15-15.dll differ
diff --git a/qchess/win32_dll/libtiff-5.dll b/qchess/win32_dll/libtiff-5.dll
new file mode 100644
index 0000000000000000000000000000000000000000..f449d75060835ef05b392aba8598ff671afc2661
Binary files /dev/null and b/qchess/win32_dll/libtiff-5.dll differ
diff --git a/qchess/win32_dll/libwebp-2.dll b/qchess/win32_dll/libwebp-2.dll
new file mode 100644
index 0000000000000000000000000000000000000000..e89ac8bfa4361bc674d7fdae80ac396fa69d0ba7
Binary files /dev/null and b/qchess/win32_dll/libwebp-2.dll differ
diff --git a/qchess/win32_dll/mfc42.dll b/qchess/win32_dll/mfc42.dll
new file mode 100644
index 0000000000000000000000000000000000000000..27692e53318b1c8c0723a91a094940600eac695f
Binary files /dev/null and b/qchess/win32_dll/mfc42.dll differ
diff --git a/qchess/win32_dll/smpeg.dll b/qchess/win32_dll/smpeg.dll
new file mode 100644
index 0000000000000000000000000000000000000000..3742ad21ed0048328fc7e13288e7c9dc47df3e69
Binary files /dev/null and b/qchess/win32_dll/smpeg.dll differ
diff --git a/qchess/win32_dll/tcl85.dll b/qchess/win32_dll/tcl85.dll
new file mode 100644
index 0000000000000000000000000000000000000000..a933e79f78e7d8f16eff3ccde771fad615803f98
Binary files /dev/null and b/qchess/win32_dll/tcl85.dll differ
diff --git a/qchess/win32_dll/tk85.dll b/qchess/win32_dll/tk85.dll
new file mode 100644
index 0000000000000000000000000000000000000000..163c2a36dcde77f01525f22caef6d9168d6021c3
Binary files /dev/null and b/qchess/win32_dll/tk85.dll differ
diff --git a/qchess/win32_dll/zlib1.dll b/qchess/win32_dll/zlib1.dll
new file mode 100644
index 0000000000000000000000000000000000000000..53f3376a6635b0f6bc4227181fd46087f1d0324a
Binary files /dev/null and b/qchess/win32_dll/zlib1.dll differ