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