From 2ab27eb698cfd57977cc9cc25edcbfbeb3b1b1ee Mon Sep 17 00:00:00 2001
From: Sam Moore <matches@ucc.asn.au>
Date: Wed, 30 Nov 2011 12:36:18 +0800
Subject: [PATCH] Modified Turn Response Protocol, added handling for SIGPIPE,
 changed placeholder images

The "outcome" of a move is now listed as:

TYPE [ATTACKER_RANK] [DEFENDER_RANK]

Where ATTACKER_RANK and DEFENDER_RANK will be present if TYPE is one of: KILLS, DIES, BOTHDIE, and indicate the ranks of the pieces involved.
This involved adding a class MovementResult, which stores the ranks of pieces in addition to an enum, replacing the enum Board::MovementResult

The sample agent "forfax" was causing broken pipes, which caused the manager program to exit.
I added a handler for SIGPIPE in manager/main.cpp to ensure that the manager program reports a DEFAULT victory to the other AI, and exits gracefully.
However, I still don't know WHY forfax causes broken pipes, but hopefully its a problem with forfax and not with the manager program.

I edited the images used by the graphical display to show the ordered ranks of the pieces, rather than some obscure characters.
Unfortunately I have just realised that the enum used for Piece::Type stores ranks in the wrong order.
In the actual game, LOWER numbers are better, in my enum, HIGHER numbers are better.
To make things more confusing, I made the printed ATTACKER_RANK and DEFENDER_RANK correspond to the traditional numbering, not the enum numbering...
---
 manager/controller.cpp     |  53 +++++++++++++++++-----------
 manager/controller.h       |   4 +--
 manager/forfax             |   1 +
 manager/images/piece10.bmp | Bin 1322 -> 1330 bytes
 manager/images/piece11.bmp | Bin 1354 -> 1298 bytes
 manager/images/piece12.bmp | Bin 1370 -> 1162 bytes
 manager/images/piece13.bmp | Bin 1374 -> 1114 bytes
 manager/images/piece2.bmp  | Bin 1238 -> 1094 bytes
 manager/images/piece3.bmp  | Bin 1306 -> 1414 bytes
 manager/images/piece4.bmp  | Bin 1310 -> 1338 bytes
 manager/images/piece5.bmp  | Bin 1258 -> 1370 bytes
 manager/images/piece6.bmp  | Bin 1246 -> 1226 bytes
 manager/images/piece7.bmp  | Bin 1342 -> 1382 bytes
 manager/images/piece8.bmp  | Bin 1206 -> 1270 bytes
 manager/images/piece9.bmp  | Bin 1282 -> 1214 bytes
 manager/main.cpp           |  69 ++++++++++++++++++++++++++-----------
 manager/movementresult.h   |  34 ++++++++++++++++++
 manager/program.cpp        |  17 ++++++---
 manager/program.h          |   2 ++
 manager/stratego.cpp       |  42 ++++++++++++----------
 manager/stratego.h         |   7 ++--
 samples/forfax/forfax.cpp  |  19 +++++++++-
 samples/forfax/main.cpp    |   9 ++++-
 web/index.html             |   7 ++--
 24 files changed, 189 insertions(+), 75 deletions(-)
 create mode 120000 manager/forfax
 create mode 100644 manager/movementresult.h

diff --git a/manager/controller.cpp b/manager/controller.cpp
index dad6e44..736663e 100644
--- a/manager/controller.cpp
+++ b/manager/controller.cpp
@@ -8,9 +8,10 @@ using namespace std;
 
 /**
  * Queries the AI program to setup its pieces
+ * @param opponentName - string containing the name/id of the opponent AI program
  * @returns the result of the response
  */
-Board::MovementResult Controller::Setup(const char * opponentName)
+MovementResult Controller::Setup(const char * opponentName)
 {
 	int y;
 	switch (colour)
@@ -48,12 +49,12 @@ Board::MovementResult Controller::Setup(const char * opponentName)
 		if (!GetMessage(line, 2.5))
 		{
 			fprintf(stderr, "Timeout on setup\n");
-			return Board::BAD_RESPONSE;
+			return MovementResult::BAD_RESPONSE;
 		}
 		if ((int)(line.size()) != Board::theBoard.Width())
 		{
 			fprintf(stderr, "Bad length of \"%s\" on setup\n", line.c_str());
-			return Board::BAD_RESPONSE;
+			return MovementResult::BAD_RESPONSE;
 		}
 	
 		for (int x = 0; x < (int)(line.size()); ++x)
@@ -69,7 +70,7 @@ Board::MovementResult Controller::Setup(const char * opponentName)
 				if (usedUnits[type] > Piece::maxUnits[(int)type])
 				{
 					fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
-					return Board::BAD_RESPONSE;
+					return MovementResult::BAD_RESPONSE;
 				}
 	
 				Board::theBoard.AddPiece(x, y+ii, type, colour);
@@ -79,10 +80,10 @@ Board::MovementResult Controller::Setup(const char * opponentName)
 
 	if (usedUnits[(int)Piece::FLAG] <= 0)
 	{
-		return Board::BAD_RESPONSE; //You need to include a flag!
+		return MovementResult::BAD_RESPONSE; //You need to include a flag!
 	}
 
-	return Board::OK;
+	return MovementResult::OK;
 }
 
 
@@ -90,11 +91,11 @@ Board::MovementResult Controller::Setup(const char * opponentName)
  * Queries the AI program to respond to a state of Board::theBoard
  * @returns The result of the response and/or move if made
  */
-Board::MovementResult Controller::MakeMove(string & buffer)
+MovementResult Controller::MakeMove(string & buffer)
 {
 	
 	if (!Running())
-		return Board::NO_MOVE; //AI has quit
+		return MovementResult::NO_MOVE; //AI has quit
 	Board::theBoard.Print(output, colour);
 
 	
@@ -103,7 +104,7 @@ Board::MovementResult Controller::MakeMove(string & buffer)
 	buffer.clear();
 	if (!GetMessage(buffer,2))
 	{
-		return Board::NO_MOVE; //AI did not respond. It will lose by default.
+		return MovementResult::NO_MOVE; //AI did not respond. It will lose by default.
 	}
 
 	int x; int y; string direction="";
@@ -133,29 +134,39 @@ Board::MovementResult Controller::MakeMove(string & buffer)
 	else
 	{
 		fprintf(stderr, "BAD_RESPONSE \"%s\"\n", buffer.c_str());
-		return Board::BAD_RESPONSE; //AI gave bogus direction - it will lose by default.	
+		return MovementResult::BAD_RESPONSE; //AI gave bogus direction - it will lose by default.	
 	}
 
 	int multiplier = 1;
 	if (s.peek() != EOF)
 		s >> multiplier;
-	Board::MovementResult moveResult = Board::theBoard.MovePiece(x, y, dir, multiplier, colour);
-	switch (moveResult)
+	MovementResult moveResult = Board::theBoard.MovePiece(x, y, dir, multiplier, colour);
+
+	s.clear(); 	s.str("");
+
+	//I stored the ranks in the wrong order; rank 1 is the marshal, 2 is the general etc...
+	//So I am reversing them in the output... great work
+	s << (Piece::BOMB - moveResult.attackerRank) << " " << (Piece::BOMB - moveResult.defenderRank) << "\n";	
+	switch (moveResult.type)
 	{
-		case Board::OK:
+		case MovementResult::OK:
 			buffer += " OK";
 			break;
-		case Board::VICTORY:
+		case MovementResult::VICTORY:
 			buffer += " FLAG";
 			break;
-		case Board::KILLS:
-			buffer += " KILLS";
+		case MovementResult::KILLS:
+			buffer += " KILLS ";
+			buffer += s.str();
+
 			break;
-		case Board::DIES:
-			buffer += " DIES";
+		case MovementResult::DIES:
+			buffer += " DIES ";
+			buffer += s.str();
 			break;
-		case Board::BOTH_DIE:
-			buffer += " BOTHDIE";
+		case MovementResult::BOTH_DIE:
+			buffer += " BOTHDIE ";
+			buffer += s.str();
 			break;	
 		default:
 			buffer += " ILLEGAL";
@@ -164,7 +175,7 @@ Board::MovementResult Controller::MakeMove(string & buffer)
 	}
 
 	if (!Board::LegalResult(moveResult))
-		return Board::OK; //HACK - Legal results returned!
+		return MovementResult::OK; //HACK - Legal results returned!
 	else
 		return moveResult; 	
 
diff --git a/manager/controller.h b/manager/controller.h
index 0e2e5cc..1fac88d 100644
--- a/manager/controller.h
+++ b/manager/controller.h
@@ -15,9 +15,9 @@ class Controller : public Program
 		Controller(const Piece::Colour & newColour, const char * executablePath) : Program(executablePath), colour(newColour) {}
 		virtual ~Controller() {}
 
-		Board::MovementResult Setup(const char * opponentName); //Requests the AI program for the initial positioning of its pieces.
+		MovementResult Setup(const char * opponentName); //Requests the AI program for the initial positioning of its pieces.
 
-		Board::MovementResult MakeMove(std::string & buffer); //Queries the AI program for a response to the state of Board::theBoard
+		MovementResult MakeMove(std::string & buffer); //Queries the AI program for a response to the state of Board::theBoard
 
 		const Piece::Colour colour; //Colour identifying the side of the AI program.
 
diff --git a/manager/forfax b/manager/forfax
new file mode 120000
index 0000000..a715b0f
--- /dev/null
+++ b/manager/forfax
@@ -0,0 +1 @@
+../samples/forfax/forfax
\ No newline at end of file
diff --git a/manager/images/piece10.bmp b/manager/images/piece10.bmp
index cfeda8a32d1e402e4ddd5bf8872a71fb1bfe0e39..cf77ed49ee52d4408c156a7a666200e1dcd4d674 100644
GIT binary patch
literal 1330
zcmd6lOKVy|6vzKF$@RvYTyyiP-X?AH(j+Fajjes9wVIU(S&N8*8y9L6TnHk9f?vR$
zxbO=IE?l?}UFgQ=ce3}9P)Z!zW&UtxhVwgTICJLQ-8(sGauVQNIUPP4!J6jBD)6wb
z+b_kV+I&9O*lae#WHLcMpNGw61IKX?MG+p42aQGp)9DmGpAQa)1MzqqR;v{zlL_s1
z8|88tu~-bl;Sh;L0@-X9g+c-0a2VBU6{FDzcDo&^R0_Rb4_>bqE|&|PP6vTN0D>T(
zUaw;?7@*Z^A(zWRk|fBojApY5qtS?3t%hJQh*GJ9VzG!yrGj)i4W8%G@AoktkC99!
zVK$p#Fc=UDh0yJG;rIIyjYg5lWMHvaKq-aW?M5UL(R=dJSF%ulswT>do=F*iC;cz~
ze*0tdr`xDswIKhK>+=_S@b#OZMl9erH!5&)9~oSAD|-Jyja!hfQA)3gV=2ERSIhYM
z1+laE%E_tKM$Tjwmky5z;g1!}s_)><+jlBvaVo#wU&`qou`u%Yw8p+7W(MEdRswc5
q$S#8m>l>nIBAXI})0I`uz^~~a%<jLM&3>Ow|K|Ug&!;(jf%|XDR$Kc3

literal 1322
zcmdUtO>0^~6o%h3_g+o!wI;RsFfq+%V^fo~CMM>qA_Npfg5biXisC{cuJsSN5kwF{
z5M8<#T&Nqtg^2o}%xDsV*FqLuq<P_-nK=(LbLPysySGS~%0j>)pY1#wVPP7F2s|iH
z=HQWujmP6D8;wR73<juHs|W^zFqup!m&>qPtq=qOMxzngY!>x;9UhMddc7W6trlLd
z7rkB&l}ZKSa2Sj+M59pz0s-W5Iiyl4h@yy0CIhF_iF`f}o6UwqB7xy>2#rRAVzCIf
z+YP(jj#{k-v)K%tPKQ>jg;*?xP$+~>rvq7*5s$~w?RKFk3M5HFqtQSl5`o|EN4wod
zzu$+?=Yz}TLZMJVI-N!`nMAYMM5$DQ!!ddF2N3;LuZa_{^qly|zv!R2;eyD1d2%Jw
z(e=&kAEH$Qn>k<jO;(=4DV=d|BRXfZoc*F7oE($H{Ru5|KeL~ipZU*s<%cx6-$F;~
z{I+*!m&f*KUtsJz9jLhBD=n|At{K-CH%uFw-)Kw41yRy4?ZPKnVY<)y#icJQ&X;qV
Ut<M}*)$e`z8~ypxhyUUD2pL>kEC2ui

diff --git a/manager/images/piece11.bmp b/manager/images/piece11.bmp
index f4ebeb2c867a5a6b435191b45a9e3ba6e8292599..b006d3d6959103121fee30d248ae54aac5149ced 100644
GIT binary patch
literal 1298
zcmd6lO>Y5F6o%h>4Q0^kw5Cd{`axAc^t%f?5^TD$vhWjh!#@yviG{?5#DYX(gOw%X
z`#<U2K^mDMU3!yy&*VJkJ!fw24Sow+$Px(PmA+idMWC1S;D8_FVtq*&w&wG>%x1G0
z#^W*4=``GKH*`83EEWsG;V>GF21cV10)YT{o`=upgTvu~!C*k8Qb97AL@*dcx7$Uj
zRDvjq@OV6!PN$emCh+_H==b|56bfjyT4=Z1$Ye68)oKs~0UXDn*XyCv>7ZV(Bb7=a
z9*-jyiy@oMA{vb%pU)!_iJ(|4VmKV4TrMLN3Slr9AdyI**=(X(t-@?J!|8M)m&+~A
zyz4tr)!$zesv_xvSNb16+gpwKWbKsxxAza}+C<T6ROj@`|ICQ(<yF;B>4W}}74YX9
zIQ89YSOJrAKFfOVY%EAp=hSn1vX$Gd?ya11mp5|3hW_-L2wORIU0$&Qh5y_s`)nq1
zp~`Kic9wS#a;D1Zp>Ra$v6YDO2^IY*Z#0?r2|2JZyK+9I8cwU*(;H;0#us3@EBmkE
PHUH}2ti{#q+v)fV%pO*>

literal 1354
zcmdUuy^j)M5XPU`y@f^axbp)~J@r7;6Hynz4@5mhE+Ll)4I$JtR1zp@pn*U|LrEZn
z5a=ifAyiQC5d!>AxVs!-5ps<d`Xn=%%x~s>C-2U>e_U{obwR+X7@b@iftT~x1Ac0k
zb}nWlTPzkbo6qN%PN&G_a`1ROFc=KrI1UWMz~yqGTCKupG{WokqFgRxJRYOjY$6;E
z!)~{uP$(dkN}*ILL8H;YVzHpp=|HE`As7rIkx0N~G9eHMfMr>9yIo8s6KJ(s*lacw
zi$&Dyb%a78<nwt%A`w(76^uqBs8lLgtyZ|*ZV(aL?KWz)8vK4gTCEmhu^6J!C}y)6
zve_)0PA7)LA(F`?1VKP1lR>}VM>?H`!{LC>=fhwyK(E(BJRXN$uLsZbFq_S2G#bmd
z`q#bq5IeM<n#3=+C2=uU`YZhG>)|)6`@7k5dDCy_zdxc6PT`~A`t<pWT(QY*L~rbJ
z-tKt&P6{^oE1q7<RB{3<`3?SptS_acLP~!6oGc0?hf4m8==duBgy`v?@W({vtNI_E
zka5jTa;Th-Ii?2>R|WfqZGPv7?ymT~``etkp{AS5f?KzD^fSygE$OcBv-$%y9q#C7
c7<P|Ssd;J7G&}k7^tD&czhgVafA@dTFXlIA5C8xG

diff --git a/manager/images/piece12.bmp b/manager/images/piece12.bmp
index 6c9544ea1b387113d435ea0307dd2a9e54367adf..8c67a48b1c13257dc3f4290193548353fa1c6af0 100644
GIT binary patch
literal 1162
zcmeH_Jqm+B5QX1tOyX+(e?YsGX>F_}eU6d?Sa<=?pdc24y`_bvg?BQmMl6&Kq_W6^
zH#^I>48!a^p1y)szKD0>+s6b|WI}?!^v+jtZCuxNLr_%}f*^ox+enfGVHhIIGQ@F=
zJkP;7hhZ2nO%r8VB8nmuMFG$A;5ZH}%Yy5=NYk{fH~T=78rmi{AsX@h;Yf5kU%JO*
z&e&F?U0-U7Go6-FzWH<Me5CVRt6Y=LZ>5lwGqzCV|I;@o&dLA%k$>6GVH0PUy#Ye(
BCi?&Y

literal 1370
zcmd6l&5xOJ5XZmsJnOA&wcFCFrCY_WcB@-jPhaSZR!gXZ8xa@8sV6r_iMw!j5Q#*P
zkT{Sy5FuXvC*{$nr6j%du#?RECi9t@-()iG?-3Dri4btH^3HxKLCVK*1pJV1)VGSP
zb-7&fY_V8iKA)pdC?FUNLZ{O~CX<0>S%^d;wA*c1tyb9WcI5MU42MJXdOc(^8K_h$
zOs7*c8Vx9wN+gp>7z_ps1_O-8W9apIxLhvOYBewngKoErbUKZ4xeTw@i&m=zv)K%d
zMuXXGhJL>fkH>>*wTf^!jL~R>R4N6x+YN`q0gmI4NF*?sOi(J75RFC=kH^t$HW3H}
zkj-YHP$(c4ixCQi(CKs_m&@UFI#DbZ5s5@lsZ?OGSdh!*;Pd%lGMP}X*Wvg3A(2R+
zR;yvN*$|7xHoLp-mJZ6FscE(OJy{)!ApeCMkH2U*&)09>E0+K3um0~1^x>nDHJ*PW
z_vdxOE_ZU|GV*msDZSd`Z{E_oO<RWH4)E7RTE2Q^4sfG`)B--l?L;pH&Yte~zan}e
za4nH-?QhS2PIR&1mM2dyFP~YT?{X87S*RD@?Rv&QkA*nHobZd-;d-KnzZ1?Lt=%1d
zUqcUs{b)~hdz`s*msFbsrJC;TbLNJe6vsDN<*nO9CkHsg9*M*f>H5-SYrOkEAK5kA
N^ZnyKg*&{4?@!Z3Yt8@w

diff --git a/manager/images/piece13.bmp b/manager/images/piece13.bmp
index 0878912192750045445f6f1924eb4799133bac61..f822c241c48e20bcdb334d1cd8fda8e99caafe3b 100644
GIT binary patch
literal 1114
zcmd6l$qfQA3`KutAwe|3k^6MOeHus)l);G#!kunHE3^<CCz?gJ=75AWmh3os-m+Xr
z-+{%Gy^x-(8aVPuh~G{{kF?F2QpyA|M&L#M^8?)9fPY{Z280lp@7@?y=CMtqh*3D#
zsj&*LZAyUT89P{0+6m6t)`8YsLFdN0ZO&CT^8d#hE}acufS7;cjJ5NXh=LVf!LPho
hKeL>#KP)>4-gf;aN4vyw{uN!n?{srZXa0XX_P)Wa6B+;j

literal 1374
zcmdVaJ#!L47zgnGbA*=&0zwP|q7f8xAmZC$1O-GuWpD;4DN+Cfl_eAuq)3yYp`u_i
zd;tauN}vOVBIG;8y~~S2j><-#ncdmh-|e%{?CxCb$DtBZ91^h4MtfI{ppoXW1^m=r
zwiKHY+r`C&WasDSI6gi`I-Q1EtwyuiM5oh1C=^1uT!zo*!*aPqBocww>qVo{fI^`_
zx7)>VID|%{fz@h7JRZl<(Gh~dAoO}Y^7%Y6nGATIM>3g2EEYqdPyi8OFc@GuokFM6
zq1WqSG#WvvR3ewlp<1m%rBY!$9^>rn3=W3_?RFdeejlY$39VKOE|&}8a2N)I0rUAB
zfj|JKr>CgZYA~5hSS%Lscs#J%?Z{@cs8lLAIXOYSUdLoIfz4)v+wDdokw7Yyg4t}w
zY&L_@XoTPIM>HBmu~>v42$$#gulMXwW#V_$#K{DEEZ6bZuJ}rHu+294<`ui|teTzG
z{IM_ZnZzx-VkLZnlH95b5(q?2@q;LRUUU6Jab1KALD6kwU-SE-e<b>332$`m0e#?u
zp^g5INZ_0SR;YabSM>S~$Gz2W@E1frmiwh&E5F`K&-a=09<Qvsp3*bM9OvGZbq76q
zEcxCOr%Zjj7Sc(~aSyDwU2h;VUim$fnReFBZ=2|j_R2XO(cKkSY$=IU*UYKe{c2Y4
S@5XKhf4a=;WdDKxA$|e!J!c;P

diff --git a/manager/images/piece2.bmp b/manager/images/piece2.bmp
index ef4927b479da1014200e9e1ec660b40e155f1787..0a11b1167eeb48de88e0c58eae5be69febc03d7c 100644
GIT binary patch
literal 1094
zcmZ?rbz@-w12-V40mKSW%*en2WB~zCK9?JUK}tdR|Ns9W8HO`w&M+`Ub%WW1o?yfZ
z5YA>~!U7mk<(Zk$)QmiNMqoGrLlQ&)!ve$qKmkUOAdtW+j|k5}Di3l!(0?ETtN&mg
e2gzdiA1sDUfPw-FAR3S*(ex8YpD=R<Aq@aOu?xol

literal 1238
zcmdUu&2EA~6ot>7s<pLXOaGMqDD-!SA;cA{ZcL1Q2-)`q+!@zyT>22~a6t$g6JyY|
zuVV*lt;wL>xM)vuCnVo+?%@ve_P)p<(Son9ysE1r<oOd9=O2Zyig{ei<uWFi&*$j%
zda!L9vMfVU6c7=@Foa<kP*oMP*$k7(1f5O?zVD;iY(m#{SeAv+XoOa)g?_&e*LC4I
z4uT*+qtQSvmjh!Ap68)nuVXkIVmuyWFc?77G?=CdNs=&~PSNdlQLEL^ZnqIdQIhS?
zFMLob`iV{a>jlw%`D2MkczS+W_YwRx(jV58F@YDUx`9Q0PN#d}_m#v(=>P41ceRTb
zZf>`7DwoSD(N>=1zb@_O?D7}B8p786j9ujU9)TCv^E*@0_z@i!V($})WRV|a`1xk}
XRmvU`rTWM3ZfLWA%HPTF_J7bP)#N?B

diff --git a/manager/images/piece3.bmp b/manager/images/piece3.bmp
index 4209648f0382661bfa3d6f5bd8a37906de070a43..40ca3f83243022110e8927558f78138512e5519c 100644
GIT binary patch
literal 1414
zcmdUt-EY}p6vw}ws+CfEQC73fY^#^q46D7VcC~q%+GZ|XAw=RvA`&iKiG-F2NfUZe
zH=<Wf<4PiNN4zBEf3hE4(-7J2mhPLJ=Xr8I$vNNW<m~NdmN8X^2FR$F_;=8-GR=by
zgjX-aMP(*29*?JNG#cUJ;sP$03l@t7TCEo0a2UyC5+acZPNx$pl?qHI6E>R--EJ3F
zs}&xP2gPC$d_Et+U=YX0$51E~Xf~Vhdc7D722iWj2m}IXG#U^Jg$RX05C{Y)m&@q)
z`!E`fsMTs<Fc>&IJj8G~ghr!5DwRSk7K2nOh0o`M-EK!FlR-M229L*sQmI6}UPqx&
zz}eXuSS%LIW;5FDHhR4t^m;ww@i=rk9b_^YB9RE(Za1RQD2|Sfkj-XcFc{G3bRdyP
zkjv#jr_*tIdWwUC12`NGoS&b=WHKR<NTAhfp<1n?R4SoTsesGn;^gE6e!m}VHXHeT
z{&LPY{iH3_wQCw#AZn?u^pE(;x6SXAksr>V6FUp~Z%QX%-@)1X6DPzjo9Cu=^R9(#
z%B>qV3VoH&^KAp!*(Fr{PkTl}wm*NF>%S$|ao$cidH0@>4<Ge&oJe1(UQfANL^Rs9
zH{x0UlBds}lPQ<UiQ)xOzMSQ}b;1|i-w-Z65ItOa^q7dB%<?7rGUL_?leNm`tZ`|#
Z$(_6R7R-nG)wTX7{+Io{+QS=o{{rfZfVltw

literal 1306
zcmdUuyNg;u6vn@A+`GP_*W8Wfu8Gm?W*_EZ%wzLt19mF5+SzCo{{R&Wv9eN2OA$dE
zK|!z)5v=roGNZejEP9oc$p>c`&X05E%sDeZVqOIsc?n$0UEt0L%f^o*;HUl8zDv*A
zR;$&9EtgAFt5qZt2{@fj*laeq-EIVfL8MYC^m;wy^LeydEsRDZWV2ZaAyBW^(d~AT
z%jIA)nJ^p<(P%U<9*<Efl`x%7Q7jfwsZ=l+3^18YV6|FNE|+08o6&B!u~;lHo6XSa
zbdbqp5R1hypU<Hv3gYoNB9REv=`@<nCZf?O`u#o}4hKS^5DJ9?{C+=lT}Q1}Lo%6!
zs;VFfP16t#hi~uxudlLT1O2I*vfDe7gTB|_@K2v_$S+@SROOqduaoV>he?+Zm#z=|
z_|AyC$j9qIPl)f0xciQax1>z4lm9n=O};tAgQVvG4_xtj-}x`k&R_X>ak+>4{3oO(
zAnD%x&rgqiFAi`ayi}j<j~7BGPY-bq`P7Kt_gCY|6C-XX9|_@bs;XV$?f#mM6!O@t
cC>E=2jko#6_i)*n&qKHsZ}2+hANwEl3mm6ZA^-pY

diff --git a/manager/images/piece4.bmp b/manager/images/piece4.bmp
index 63161fb91013e20a3492aeecd04326842b39e3e4..0a27a46897b10c6084abcba4221d0368f6215d72 100644
GIT binary patch
literal 1338
zcmd7QzmF0@6bJC{n*)KxMG((D&pYInQ_)r75Pt!3YC%CF4GAR$6(JD{{sCwRG!zsx
zbc6;%2sE@Lgh2T5KjH2IYHrtPc`uor$$Z|M*}TlR?;#`92od0wSML2FnALq4fFIV~
z_$u!xW4qm|w%Kg3SS(N|6c7%F5sSs(^Z5{u$1xlZF`v&73<lx%`>|TBkW40Fu~^V*
zwUEhV&}cN^a5&&}Ix(3{V6|E?olcQRB+%(}U^bgkEEdshHo+J}rBVUMap-ot==FN2
z*Xvj=mk<O2>2w;^Y86JK5$p9DwOS3OQVAZ92cjs#<#HjL%_5abVK$q=ZnvY|ZX=)1
zBNB<gWHMnq9%C>Vz-F_dTrPv>c?1Fhj7B5maydwnglII1e!su#&29gZZv6ghlDn!2
z`5_$Q|NM)E|ML({z58?YTJ-)((KuuLr%*U@NYHV{K3skb>=SgIUA((`ze~_}_LhQw
zcj4IUzoOj@+Imr<)7NiK$fq8l@fURdlIPDPdZp|9B|TN(89i5<aI@Y`bfLIN<Wc6E
zen#hNe_ixMVU0hcQ+59_nRNZ=AqfhckU`g(gYL_~IUgMBJ7>MiG2V91uCnHS#*Pfe
WJ0`Pb$2z_T9skGsJiNnOIR6A?Ctf`O

literal 1310
zcmd6ly>CHL7{;G-d#M)fZPi6_dv9B<YE{2g6H8a=B(d0R1|OTj%wUy>#m6WH6N^M7
zgaQAPUKb_TN0$zLllPpH^Lw86e13j$3P`~bz%GvXSrVwEdC)*aJ<ShsW|HIaSYo5m
z2-$2FX0sVIO(PbIq0wj{olb*gS@1lMN~MB)J`bf*iB6{jo6Uyda0rLPfkYyKYPAZB
z#ez&GgTY{cP$-0OI1G;CV6|FNuh)@GCgF5CQ7jhWcDvE<_o372P$(1-2n3Kyr4Wrq
z;q`ja>-Es>cH#H?5s5@lE|-zZ<sb+Gg25o-@i+_y16r*Xn$0GBJ|9Y@5{yP8+U+(x
z9uHhD7izWI^!)$5C2M1`YeKCF@v-OeC*1DVzI&F|k=K6_H~IRu5Xd>B(my@lZ{`zn
z@bLH}kozTY@7m7qoXlLX*6$#<+qhjIH`}<4T$!$Cf;IJdft+7lZsrzZWw^7AoHY?W
z#hjX_g4OzZa>7!S!MK4lN90&Ux|8V@toSuVdoZycYNP^kzC#m*a+ji1d;98%K+Yx8
PQnSo|`JeND_z(MU;Wk)}

diff --git a/manager/images/piece5.bmp b/manager/images/piece5.bmp
index 9163c1235ff19392b556aadd2ce18c94753db693..051bd432f840b8cd2a659ca080ea673bb0aba9ab 100644
GIT binary patch
literal 1370
zcmd7QzmF0@6bJC{%&~}zf+w7!o{FBr33w_eAR->3fEFZ#@@NPR2|+5LfrN^Nf&@wu
zAp8mqH3i`s2!vn%6S9j$lU<_ay=3NX<}+`1@^;+*O9p&g65w?6r2RbzWc)fLz)$&h
z{Mf8;W4&JUwpy*QSS*muW?{G6;q`jqa5!KxnUKk3uv{*o)9G+^b%j=|1({5SP$-0Q
zxr}^1k3b**N-2iJA)?VJ3WWl?-7Zq86r4^c+-^4%3I(RqDF%Z9lu9KckqGMbI*P?2
zYPA|zmW9jZLZ{O~yWNILr9wCy#(X|UsZ@f&V1UhL!)P=@I-Q1Etwz7!2g5M1SS+Yi
zDo7@is8*}U<#GrHgJ?FJ@cDf3`~B$kdhmEWh{xlY&1Nv0&5+CGXfzrakH;_?jYuRC
z(ChWETCIr1Vwg-O+umLGnTW=pQ<Kf#5ya-A?Baj@_?yQh_4>Z^?-JI3zHoh^)P3>w
znA;$932}08PR_*rBhhl;AfLqDMm}($A$D;;C+|04IU!bYr)O{8vYL0qe6Yu<!Du3c
zdCjrN`6<=u2|0bmvzR|WAukS@m;3zj6Y`X$TE#PdgRnmu@_^mY!$*7icSP=Sl}F@0
zmxT3q$RP)JRcdi(rSe;p-c~3%7OAHP5=MGMc9U<9nDceJN%;MpZ1dm#kNdg1hu1Lw
E0?My%!vFvP

literal 1258
zcmd7QyJ`YK6b9h`%$lr;F^RcsHZj@NTwHUru&_|Dh>gwmA|e)IXS<bHSPO!Mg^yvO
zU|}I5f<B2aVa8p-W`;B=Ja7&(d~-Pi^JA}laAVDDoM&X01V10~;9d`S`OT->+-x>m
z!D_X_a=C=#ILPI4D3{Afr_-p_YG^bX&~+X2`5eV!5tT{>sZ<J<WnnUzAe+r%u~=X<
z8lm6sLs1l%ripI1i(an>P17(Qk1?H2QLR>?sw!r)8CtCt27>_%!$7;;MkbR%v)M$a
z(?K$sM4?bXB9TC;RDx~W$mjDI4u@{P2VY1S`?iS*g8tuQ6o3Et{PHdnoFB6k#)8p+
zyFlPCVJ@%qCUcWRBudXRXDs~qM4BOW{hlcF;4%~3e{)OPou^FXA@W}_b}ik1e!=N7
jDD{(5{`51sE54&+mHg8E9_*^1|AX~E{^$ND9^B{`9UevJ

diff --git a/manager/images/piece6.bmp b/manager/images/piece6.bmp
index 321bf557d21a756277fd6495e7321e0354eca1bd..5ca389b1fa7d5e8701303f37b7742f336d537718 100644
GIT binary patch
literal 1226
zcmd6ly>fy;6ot=jgqRpeLVh7Xn1l=zFf@*pW05{DVPV5$Xm|o%z|J?Yv9N#{hY~E+
zcOomOOvW9GRGyi8_wIgo&)#CczLyOYTC!}hXm5j{$totse_CaHvh61FJl_zk*K3SM
zBXql6^m;u=k_6kf;kqtN(?k#ih~pTYP6vy{0$~_pKA&Se9wSK-^!t4{j)N@AAc`V<
z-$xWhuq+E{nnDl+c%FyZYzD(HFdPmsolc?aI##O{27>`6lL<6UE9N=+M7XNPCX^%c
z53U$*dnev~nS9i8ReP`HRB7)Y;Q3RT=sN>0SGCt#PL-E>E|ceN1J|Fb+EXp3%40p3
z$wS$|_ouga_k4bJU7jm9eBQc{3LulqVm<H|#M36z89C?klie?B@Og1sr33#89o*kJ
L|5>a5cf{2%wY51>

literal 1246
zcmd6l&1%9x6ot>7q=~Jut+7qp^d~m`vvnni574ay-Q+R4%_6ViLK1MHxDFU_W3q4=
z&}Z;f?8Fwb8R({q95|Od^TFlJa6g@$jDvQ(wz!+WCRBLG#raqD#~=Kdd%xf31l#Qv
zS(afu9>aBAwA*cLHXHc957RUu%QCv%F5);w5Cm`>2Zmu_Fc@Gs9K!QFbUGa@mrF>J
zgfI-TUaz4j3RbHX(lmvpX|OB{^Z6XMZDTf@AxRQMQ3O?0q3b#(lL>mg9{T-0rqd}F
ziv>ob(II2$3kg-kCMFR5JAZy5dVOoviIjK71oI!sRvA;DsK)aMc$04Ppbun;xmgZ=
zNB81<7j$Vbc6CiRLS8$iv-7&%pa#c+_e=7TqE?Pis+ySRw}k}%S3usCiT|;m#U_@n
F`v%h^LH+;$

diff --git a/manager/images/piece7.bmp b/manager/images/piece7.bmp
index e69019073f57cc07d1de541fddb21f0f42beb541..aaf28a105c96d5c5b08104cc55801babf4ae235e 100644
GIT binary patch
literal 1382
zcmdVZ&5Ke|7zXg?y*Xx%I!>0BHItd;*qDudm+6$1meoSHZWP3Y&_ZzQ%8e^QQBW76
z;Kq%JiV7}7XH@+7pX}aiQ;>I}Wxa4Nm-Bnx!?}lZonOOS;44hP0sE%=F$fZV9wOk|
z_Ii9_XSlIit$155mzYc@=ytn^L?UoF9Ps=7NTpIZJv~Jr5P(D?K`<D^a5#j~XoOTM
zMX^}KU@(AAr$a86gWK(f*Xu>OTt=hOfXCy3!C*ilk$}Zwfm|+!R;z{2=R>E{!D6w1
zQmKSmtwuZ^N3B*vp-_O`Zih;xLaWt6uh&B+lfisGht+C@)9FON-$y!~2E#BoIXOYS
zUdL!OLbX~&yWNINCPS%If?lsjKA(p|p+K|QL?{$OI2^`!JO&X#qtReGog$mfA{vb%
znM}fLHe)uMp;D>9WHQ0!a=~V^Ar_0R&+%V>vL7Z;zjjURscjT{Y0m1e-7Wt3$@AI8
zuO-m`{%HS@v3?NqflU|f?7d}Mo%D`dVAEfdodd`58=auPpqHF8ugE6kkBOf0{*0ar
z`6HrT&e_}(AvX|NIDbe-Rv|YL-Dl?y&GdkaZR}rnoAh@Kckhw$K+u_MbX|Mn=HC7-
zjyL-mHIas=bDX(CSO4g{mr3<Au(3Z@M2a2dSwP5{OVVwbe4P+<c8M+VMG2QU$2q$2
Ny9?Y-_Fw!T>N}S<cW3|r

literal 1342
zcmdUvyN?o46vn?Z><;T*Ws%pe;OfA-E3POyJ`hyYO`srw0!V16prNs*BZPv4777v?
z3K|kx5)vvN;Su0}!pqDWO}um#`X%RPa({E~`OcY}xrv7lp(#v&mp>`DK{(R(aR7X0
zdff1xU2L~ojcqm?)a!MqstQ?_K}7I+y(kuoNG6jQ4u@E+R_Js(2!%qhSS%QgMlc$U
zu-olOBobIImuNPdP!t8T*$fVc1O0v<tyT;9d>-v~8`J3&CX)%3N(Jln8uR%ai^T%9
zS`EQq5Z!JUHk%ESBq5znV>})sm&?KBa-rAjArJ__YPBMjN+FxgA|8*!?RLZG^P$mb
zAR3J#7K>pp7{KH4pj0ZMP$<CZbYe1@Ad|@;5{aN%t%5NIzu%8?xvb6LpI`V#5$Km~
z;#2!W{4)I1-{N8J;>-2<*Kdz`HNp8o3K^L6@e_S!LjLab{mv!}&<7z`-{@Vur3)c{
zrDOJ*R3X2`FNys7`I(RC#qmDweP$-Qe$G!4^e0J%OQNf%C%Zx-?vaTup6E6N{NXv7
zAMIwRxP|!-hzwe?(<S6KvTN9JdM4y2=KFl`60^uwA(xKm&M~`tk4*e6fj{2g!69#f
UjQhA&USEFC7u-(%ANe2j1A1#-v;Y7A

diff --git a/manager/images/piece8.bmp b/manager/images/piece8.bmp
index 8ada9115e5faa4d72145baa94576652df8c485fa..b2ea5b7dae39fa9590befeccc8d8133809c1f421 100644
GIT binary patch
literal 1270
zcmd6lJ!`^H7=_QhwQ7w`(`wV!^uso-+K;r|T*RS+lU<#h99*R0=zkC#+*Je-90YY!
z1i`^U{XMSs=0l{$1iJacdvn8c&YQ!{{rX-ypw*JC5!OMY3EXVQit!&#?@#us_G-0K
z2^Nb5#^W&>jRuCpA)HPp2qEb8ddOrl;CUXRC?c6mVltUvFc_dvC?J(eVLF{ck|dPN
zWz1$Xlu9MYvW#}SjZUY7VzCHCQ6LBcy4^13^Esl?DC+e(D5Z$U<EU1v$mMdV)oRG+
z^GGBTs8lLwwOZ)+``|bZ&1MtnbQ-Z(4B2cJqtQsqzV{0|$Q`wbP1q@ziu{xN-?*Tp
zynn0*ZTlmHgn0TI2pfWJeiM$U<oV@M7i@FGMneI6{zQ09VC9#I{sAj~Paf?2cR{=P
zH$D%!waVweyb2H^U0d*Tm->^$3msEazEh5zd3}BZn>jrZ)=Yhx{PdX9PexanIX&{Q
jYtDHs`Jq!y=yGd<9e&+-;IQYq>Q6p(tf@BlZ;yAsv-3|2

literal 1206
zcmds$J8pwO5QhI<JH+9U2XR7Pb_`V{3K~kP6cmVDfD_Q<5QuZoQo3}B5E4Q{+=+}G
zh$D<#rAYEiGsEt;%*-y!>)U3Eoi^lO$X1;(%;<?k{9XFA6%Du6wk>&}X&S_F499U`
znkIrEKv|ZsEDMUFpsFf(o(Emm;rl)e!$46K$g&J+nj%ROXqtw)u3_6YR8>Wu=UA`T
z2*VJ9ARvk&xULJv7(`KoEX%vvzur;9Bigsk_=wnmKR!{8#qxQ%pg7@t$T`1Zw;Cmy
z-`zh*V_ahAT^;p$KJvcu#kp{GoL^iX=Tzsgzi;{fC6}1oo$odr?tjM4#QlOHpG@hy
Xo(QM?iXrdk`}mW5<aW|O_80U4hk`Eb

diff --git a/manager/images/piece9.bmp b/manager/images/piece9.bmp
index e22c4b6a2eb0941f10c16d633236b222c6159af6..e37e251da7457e960aceb22edada16a34f6d7ecb 100644
GIT binary patch
literal 1214
zcmd6lJ!^wd6o%h>leTL5{b9dslXh})a1mDr!J(_G;NIQQDWh}n2ROJmIwekmp#RBU
zO^YEh77B&Da1KWw&bjYBYJ9B5XtiQlW-<E?0*+NojDJqn@y;HbsO!2RsHzIC>p~Po
zEEWq8La<yep(qN<vV>t62*VJRQh1(+IF6yJDvF{&p65uC1h#F%_k9FG0Mj&)rYU4u
zMwVr;EDM^Z!Eqc2f`BNBpzAv3^Er5)Z#^7*VoT{!XPdC??1=n{zm0ze_4of9pLRE#
zwHCI{e|nZ0krzpN?c?_kkIn1Tz5ee+evs3f+hKmiT@THt^!(y-;CwdxY&6VyVY1&p
m>!&B&@!tD2oF4tc>1epW9kNba``;kDy!&<=RrmiLaP<Xl6*f=+

literal 1282
zcmdUu%WA?v6o&s9O*Jv5P48{mYHz7c+w>9;TnG|S5b45aa1jvd#=Q#>*RIr!YcC6*
zK?N70?_?8WC`9YF_J=bJ=R0TS%$XVelQLL{5+GvE!b>CYFZ}QVUjf@R(_`6uK3}le
zY=-G{igLM(cs!0oA^};J5sgOCY&J2OOpr>YpzAtDqY;L~Avlf$Aq0&^1BPKh6h&k*
z8RT*~jK^cJEQ@S5i@{)kYPE`by^ef7k5Z|GN~MBWEQVgM2TCcr-7bp7A{0e|BuQwu
z+eoL=Xti4CbUNU99-5}1P$;0^?<1K^LJ$Nn3<FhFQLEMLGj986Hf)W4swQSPR%BkN
zqb=bt>g(J4hg0ZEeUAzuz9;2*8Q|ugJ8~~m8hnV@0d5{9*Ebg7ZrAfG60*T^bmw1^
zqm5i57aRHU$*IN9&VzQCdwsfpV39*-n-$Il_#hQ__rzcFsmIIg`24Jmtq<$y&+m85
K>oouPf6zB)%}6@{

diff --git a/manager/main.cpp b/manager/main.cpp
index 96569eb..4f203d9 100644
--- a/manager/main.cpp
+++ b/manager/main.cpp
@@ -18,8 +18,12 @@ using namespace std;
 
 Controller * red;
 Controller * blue;
+Colour turn;
 
 void cleanup();
+
+void BrokenPipe(int sig);
+
 int main(int argc, char ** argv)
 {
 	assert(argc == 3);
@@ -39,17 +43,18 @@ int main(int argc, char ** argv)
 	red = new Controller(Piece::RED, argv[1]);
 	blue = new Controller(Piece::BLUE, argv[2]);
 	atexit(cleanup);
+	signal(SIGPIPE, BrokenPipe);
 
-	Board::MovementResult redSetup = red->Setup(argv[2]);
-	Board::MovementResult blueSetup = blue->Setup(argv[1]);
-	if (redSetup != Board::OK)
+	MovementResult redSetup = red->Setup(argv[2]);
+	MovementResult blueSetup = blue->Setup(argv[1]);
+	if (redSetup != MovementResult::OK)
 	{
 		fprintf(stderr, "Blue wins by DEFAULT!\n");
 		red->SendMessage("ILLEGAL");
 		blue->SendMessage("DEFAULT");
 		exit(EXIT_SUCCESS);
 	}
-	if (blueSetup != Board::OK)
+	if (blueSetup != MovementResult::OK)
 	{
 		fprintf(stderr, "Red wins by DEFAULT!\n");
 		red->SendMessage("DEFAULT");
@@ -57,7 +62,7 @@ int main(int argc, char ** argv)
 		exit(EXIT_SUCCESS);
 	}
 
-	Board::MovementResult result = Board::OK;
+	MovementResult result(MovementResult::OK);
 	system("clear");
 	int count = 1;
 
@@ -70,17 +75,17 @@ int main(int argc, char ** argv)
 	string buffer;
 
 	red->SendMessage("START");
-	Colour turn = Piece::RED;
+	turn = Piece::RED;
 	while (Board::LegalResult(result))
 	{
 
-		fprintf(stderr, "This is move %d...\n", count);
-		fprintf(stderr,"---RED's turn---\n");
+		
 		turn = Piece::RED;
+		fprintf(stderr, "%d RED: ", count);
 		result = red->MakeMove(buffer);
 		red->SendMessage(buffer);
 		blue->SendMessage(buffer);
-
+		fprintf(stderr, "%s\n", buffer.c_str());
 		if (!Board::LegalResult(result))
 			break;
 		#ifdef GRAPHICS
@@ -92,11 +97,13 @@ int main(int argc, char ** argv)
 				exit(EXIT_SUCCESS);
 			}
 		#endif //GRAPHICS
-		fprintf(stderr,"---BLUE's turn---\n");
+		
 		turn = Piece::BLUE;
+		fprintf(stderr, "%d BLU: ", count);
 		result = blue->MakeMove(buffer);
 		blue->SendMessage(buffer);
 		red->SendMessage(buffer);
+		fprintf(stderr, "%s\n", buffer.c_str());
 
 		if (!Board::LegalResult(result))
 			break;
@@ -148,36 +155,36 @@ int main(int argc, char ** argv)
 		fprintf(stderr,"Game ends on ERROR's turn - REASON: ");
 			
 	}
-	switch (result)
+	switch (result.type)
 	{
-		case Board::NO_BOARD:
+		case MovementResult::NO_BOARD:
 			fprintf(stderr,"Board does not exit?!\n");
 			break;
-		case Board::INVALID_POSITION:
+		case MovementResult::INVALID_POSITION:
 			fprintf(stderr,"Coords outside board\n");
 			break;
-		case Board::NO_SELECTION:
+		case MovementResult::NO_SELECTION:
 			fprintf(stderr,"Move does not select a piece\n");
 			break;
-		case Board::NOT_YOUR_UNIT:
+		case MovementResult::NOT_YOUR_UNIT:
 			fprintf(stderr,"Selected piece belongs to other player\n");
 			break;
-		case Board::IMMOBILE_UNIT:
+		case MovementResult::IMMOBILE_UNIT:
 			fprintf(stderr,"Selected piece is not mobile (FLAG or BOMB)\n");
 			break;
-		case Board::INVALID_DIRECTION:
+		case MovementResult::INVALID_DIRECTION:
 			fprintf(stderr,"Selected unit cannot move that way\n");
 			break;
-		case Board::POSITION_FULL:
+		case MovementResult::POSITION_FULL:
 			fprintf(stderr,"Attempted move into square occupied by allied piece\n");
 			break;
-		case Board::VICTORY:
+		case MovementResult::VICTORY:
 			fprintf(stderr,"Captured the flag\n");
 			break;
-		case Board::BAD_RESPONSE:
+		case MovementResult::BAD_RESPONSE:
 			fprintf(stderr,"Unintelligable response\n");
 			break;
-		case Board::NO_MOVE:
+		case MovementResult::NO_MOVE:
 			fprintf(stderr,"Did not make a move (may have exited)\n");
 			break;
 	}
@@ -221,4 +228,24 @@ void cleanup()
 	delete blue;
 }
 
+void BrokenPipe(int sig)
+{
+	if (turn == Piece::RED)
+	{
+		fprintf(stderr,"Game ends on RED's turn - REASON: Broken pipe\n");
+		blue->SendMessage("DEFAULT");	
+	}
+	else if (turn == Piece::BLUE)
+	{
+		fprintf(stderr,"Game ends on BLUE's turn - REASON: Broken pipe\n");
+		red->SendMessage("DEFAULT");
+	}
+	else
+	{
+		fprintf(stderr,"Game ends on ERROR's turn - REASON: Broken pipe\n");
+			
+	}
+	exit(EXIT_SUCCESS);
+}
+	
 #endif //GRAPHICS
diff --git a/manager/movementresult.h b/manager/movementresult.h
new file mode 100644
index 0000000..8df375c
--- /dev/null
+++ b/manager/movementresult.h
@@ -0,0 +1,34 @@
+/**
+ * Contains declaration for MovementResult class
+ */
+#ifndef MOVERESULT_H
+#define MOVERESULT_H
+
+class Board;
+class Piece;
+
+/**
+ * Class used to indicate the result of a move in stratego
+ */
+class MovementResult
+{
+	public:
+		typedef enum {OK, DIES, KILLS, BOTH_DIE, NO_BOARD, INVALID_POSITION, NO_SELECTION, NOT_YOUR_UNIT, IMMOBILE_UNIT, INVALID_DIRECTION, POSITION_FULL, VICTORY, BAD_RESPONSE, NO_MOVE} Type;
+
+		MovementResult(const Type & result = OK, const Piece::Type & newAttackerRank = Piece::NOTHING, const Piece::Type & newDefenderRank = Piece::NOTHING)
+			: type(result), attackerRank(newAttackerRank), defenderRank(newDefenderRank) {}
+		MovementResult(const MovementResult & cpy) : type(cpy.type), attackerRank(cpy.attackerRank), defenderRank(cpy.defenderRank) {}
+		virtual ~MovementResult() {}
+		
+
+		bool operator==(const Type & equType) const {return type == equType;}
+		bool operator!=(const Type & equType) const {return type != equType;}
+
+		Type type;
+		Piece::Type attackerRank;
+		Piece::Type defenderRank;
+};
+
+#endif //MOVERESULT_H
+
+//EOF
diff --git a/manager/program.cpp b/manager/program.cpp
index ea5304c..8b4e4af 100644
--- a/manager/program.cpp
+++ b/manager/program.cpp
@@ -10,6 +10,7 @@
 
 using namespace std;
 
+
 /**
  * Constructor
  * @param executablePath - path to the program that will be run
@@ -21,6 +22,8 @@ using namespace std;
  */
 Program::Program(const char * executablePath) : input(NULL), output(NULL), pid(0)
 {
+	
+
 	int readPipe[2]; int writePipe[2];
 	assert(pipe(readPipe) == 0);
 	assert(pipe(writePipe) == 0);
@@ -88,6 +91,7 @@ Program::~Program()
  * Sends a message to the wrapped AI program
  * WARNING: Always prints a new line after the message (so don't include a new line)
  *	This is because everything is always line buffered.
+ * @returns true if the message was successfully sent; false if it was not (ie: the process was not running!)
  */
 bool Program::SendMessage(const char * print, ...)
 {
@@ -97,12 +101,15 @@ bool Program::SendMessage(const char * print, ...)
 	va_list ap;
 	va_start(ap, print);
 
-	vfprintf(output, print, ap);
-	fprintf(output, "\n");
-
+	if (vfprintf(output, print, ap) < 0 || fprintf(output, "\n") < 0)
+	{
+		va_end(ap);
+		return false;
+	}
+	va_end(ap);
 	
 
-	va_end(ap);
+
 
 	return true;
 }
@@ -161,3 +168,5 @@ bool Program::Running() const
 }
 
 
+
+
diff --git a/manager/program.h b/manager/program.h
index 406d954..bddde0f 100644
--- a/manager/program.h
+++ b/manager/program.h
@@ -24,6 +24,8 @@ class Program
 
 		bool Running() const;
 
+		
+
 	protected:
 		FILE * input;	//Stream used for sending information TO the process
 		FILE * output; //Stream used for retrieving information FROM the process
diff --git a/manager/stratego.cpp b/manager/stratego.cpp
index 8ffad72..871d382 100644
--- a/manager/stratego.cpp
+++ b/manager/stratego.cpp
@@ -232,32 +232,32 @@ Piece * Board::GetPiece(int x, int y)
  * @param colour - Colour which the piece must match for the move to be valid
  * @returns A MovementResult which indicates the result of the move - OK is good, VICTORY means that a flag was captured, anything else is an error
  */
-Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction, int multiplier,const Piece::Colour & colour)
+MovementResult Board::MovePiece(int x, int y, const Direction & direction, int multiplier,const Piece::Colour & colour)
 {
 	if (board == NULL) 
 	{
-		return NO_BOARD;
+		return MovementResult(MovementResult::NO_BOARD);
 	}
 	if (!(x >= 0 && x < width && y >= 0 && y < height)) 
 	{
-		return INVALID_POSITION;
+		return MovementResult(MovementResult::INVALID_POSITION);
 	}
 	Piece * target = board[x][y];
 	if (target == NULL) 
 	{
-		return NO_SELECTION;
+		return MovementResult(MovementResult::NO_SELECTION);
 	}
 	if (!(colour == Piece::NONE || target->colour == colour)) 
 	{
-		return NOT_YOUR_UNIT;
+		return MovementResult(MovementResult::NOT_YOUR_UNIT);
 	}
 	if (target->type == Piece::FLAG || target->type == Piece::BOMB || target->type == Piece::BOULDER) 
 	{
-		return IMMOBILE_UNIT;
+		return MovementResult(MovementResult::IMMOBILE_UNIT);
 	}
 	if (multiplier > 1 && target->type != Piece::SCOUT)
 	{
-		return INVALID_DIRECTION; //Can only move a scout multiple times.
+		return MovementResult(MovementResult::INVALID_DIRECTION); //Can only move a scout multiple times.
 	}
 	int x2 = x; int y2 = y;
 
@@ -280,11 +280,11 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
 		}
 		if (!(x2 >= 0 && x2 < width && y2 >= 0 && y2 < height)) 
 		{
-			return INVALID_DIRECTION;
+			return MovementResult(MovementResult::INVALID_DIRECTION);
 		}
 		if (ii < multiplier-1 && board[x2][y2] != NULL)
 		{
-			return POSITION_FULL;
+			return MovementResult(MovementResult::POSITION_FULL);
 		}
 	}
 	Piece * defender = board[x2][y2];
@@ -295,23 +295,27 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
 	}
 	else if (defender->colour != target->colour)
 	{
+		Piece::Type defenderType = defender->type;
+		Piece::Type attackerType = target->type;
+
 		if (defender->colour == Piece::NONE) 
 		{
-			return POSITION_FULL;
+			return MovementResult(MovementResult::POSITION_FULL);
 		}
 		if (defender->type == Piece::FLAG)
 		{
 			winner = target->colour;
-			return VICTORY;
+			return MovementResult(MovementResult::VICTORY);
 		}
 		else if (defender->type == Piece::BOMB)
 		{
 			if (target->type == Piece::MINER)
 			{
+
 				delete defender;
 				board[x][y] = NULL;
 				board[x2][y2] = target;
-				return KILLS;
+				return MovementResult(MovementResult::KILLS, attackerType, defenderType);
 			}
 			else
 			{
@@ -319,7 +323,7 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
 				delete target;
 				board[x][y] = NULL;
 				board[x2][y2] = NULL;
-				return BOTH_DIE;
+				return MovementResult(MovementResult::BOTH_DIE, attackerType, defenderType);
 			}
 		}
 		else if (defender->type == Piece::MARSHAL && target->type == Piece::SPY)
@@ -327,34 +331,34 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
 			delete defender;
 			board[x][y] = NULL;
 			board[x2][y2] = target;
-			return KILLS;
+			return MovementResult(MovementResult::KILLS, attackerType, defenderType);
 		}
 		else if (target->operator > (*defender))
 		{
 			delete defender;
 			board[x][y] = NULL;
 			board[x2][y2] = target;
-			return KILLS;
+			return MovementResult(MovementResult::KILLS, attackerType, defenderType);
 		}
 		else if (target->operator==(*defender) && rand() % 2 == 0)
 		{
 			delete defender;
 			board[x][y] = NULL;
 			board[x2][y2] = target;	
-			return KILLS;
+			return MovementResult(MovementResult::KILLS, attackerType, defenderType);
 		}
 		else
 		{
 			delete target;
 			board[x][y] = NULL;
-			return DIES;
+			return MovementResult(MovementResult::DIES, attackerType, defenderType);
 		}
 	}
 	else
 	{
-		return POSITION_FULL;
+		return MovementResult(MovementResult::POSITION_FULL);
 	}
-	return OK;
+	return MovementResult(MovementResult::OK);
 }	
 
 
diff --git a/manager/stratego.h b/manager/stratego.h
index 877af2d..25aa5cc 100644
--- a/manager/stratego.h
+++ b/manager/stratego.h
@@ -89,6 +89,8 @@ class Piece
 		
 };
 
+#include "movementresult.h"
+
 /**
  * A Stratego board
  */
@@ -112,12 +114,11 @@ class Board
 
 		typedef enum {UP, DOWN, LEFT, RIGHT} Direction;
 
-		typedef enum {OK, DIES, KILLS, BOTH_DIE, NO_BOARD, INVALID_POSITION, NO_SELECTION, NOT_YOUR_UNIT, IMMOBILE_UNIT, INVALID_DIRECTION, POSITION_FULL, VICTORY, BAD_RESPONSE, NO_MOVE} MovementResult; //The possible results from a move
-		//WARNING: Some of the MovementResults are returned by the Controller class in "controller.h", in Controller::MakeMove
+		
 		
 		static bool LegalResult(const MovementResult & result)
 		{
-			return (result == OK || result == DIES || result == KILLS || result == BOTH_DIE);
+			return (result == MovementResult::OK || result == MovementResult::DIES || result == MovementResult::KILLS || result == MovementResult::BOTH_DIE);
 		}	
 
 		MovementResult MovePiece(int x, int y, const Direction & direction, int multiplier=1,const Piece::Colour & colour=Piece::NONE); //Move piece from position in direction
diff --git a/samples/forfax/forfax.cpp b/samples/forfax/forfax.cpp
index e27af9f..6fa0ba3 100644
--- a/samples/forfax/forfax.cpp
+++ b/samples/forfax/forfax.cpp
@@ -525,7 +525,7 @@ bool Forfax::MakeMove()
 
 bool Forfax::InterpretMove()
 {
-	int x; int y; string direction; string result; int multiplier = 1; 
+	int x; int y; string direction; string result; int multiplier = 1; int attackerVal = (int)(Piece::BOMB); int defenderVal = (int)(Piece::BOMB);
 
 	cerr << "Forfax " << strColour << " waiting for movement information...\n";
 	cin >> x; cin >> y; cin >> direction; cin >> result;
@@ -536,6 +536,20 @@ bool Forfax::InterpretMove()
 		s >> multiplier;
 		result.clear();
 		cin >> result;
+
+		if (cin.peek() != '\n')
+		{
+			cerr << "Forfax " << strColour << " reading ranks of pieces\n";
+			s.clear(); s.str(result);
+			s >> attackerVal;
+			result.clear();
+			cin >> result;	
+			s.clear(); s.str(result);
+			s >> defenderVal;
+			result.clear();
+
+			cin >> result;
+		}
 	}
 	if (cin.get() != '\n')
 	{
@@ -544,6 +558,9 @@ bool Forfax::InterpretMove()
 		return false;
 	}
 
+	Piece::Type attackerRank = Piece::Type(Piece::BOMB - attackerVal);
+	Piece::Type defenderRank = Piece::Type(Piece::BOMB - defenderVal);
+
 	cerr << "Forfax " << strColour << " interpreting movement result of " << x << " " << y <<  " " << direction << " " << result << " ...\n";
 
 
diff --git a/samples/forfax/main.cpp b/samples/forfax/main.cpp
index d0cea95..2b31fee 100644
--- a/samples/forfax/main.cpp
+++ b/samples/forfax/main.cpp
@@ -6,13 +6,15 @@
 using namespace std;
 
 #include <stdio.h>
-
+void quit();
 Forfax forfax;
 int main(int argc, char ** argv)
 {
 	setbuf(stdin, NULL);
 	setbuf(stdout, NULL);
 
+	atexit(&quit);
+
 	if (!forfax.Setup())
 		exit(EXIT_SUCCESS);
 
@@ -25,3 +27,8 @@ int main(int argc, char ** argv)
 
 	
 }
+
+void quit()
+{
+	cerr << " Forfax quit\n";
+}
diff --git a/web/index.html b/web/index.html
index 25c2dae..7736907 100644
--- a/web/index.html
+++ b/web/index.html
@@ -84,11 +84,12 @@
 	<tr> <th> OUTCOME </th> <th> Description </th>	</tr>
 	<tr> <td> OK </td> <td> The piece was successfully moved, nothing eventful happened </td> </tr>
 	<tr> <td> FLAG </td> <td> The piece moved onto the opposing Flag; the game will end shortly </td> </tr>
-	<tr> <td> KILLS </td> <td> The piece landed on a square occupied by an enemy, and destroyed it, moving into the square </td> </tr>
-	<tr> <td> DIES </td> <td> The piece landed on a square occupied by an enemy, and was destroyed. The piece is removed from the board. </td> </tr>
-	<tr> <td> BOTHDIE </td> <td> The piece landed on a square occupied by an enemy, and <i>both</i> pieces were destroyed. </td> </tr>
+	<tr> <td> KILLS RANK1 RANK2 </td> <td> The piece landed on a square occupied by an enemy, and destroyed it, moving into the square </td> </tr>
+	<tr> <td> DIES RANK1 RANK2</td> <td> The piece landed on a square occupied by an enemy, and was destroyed. The piece is removed from the board. </td> </tr>
+	<tr> <td> BOTHDIE RANK1 RANK2</td> <td> The piece landed on a square occupied by an enemy, and <i>both</i> pieces were destroyed. </td> </tr>
 	<tr> <td> ILLEGAL </td> <td> The moving player attempted to make an illegal move, and has hence lost the game. The game will end shortly. </td> </tr>
 </table>
+<p> If printed, RANK1 and RANK2 indicate the ranks of the moved piece and the defending piece (the piece who occupied the destination square) respectively. </p>
 		
 
 <h4> Additional Turns </h4>
-- 
GitLab