--- /dev/null
+#include "controller.h"
+
+#include <sstream>
+#include "game.h"
+
+using namespace std;
+
+/**
+ * Queries the player to setup their pieces
+ *
+ */
+
+MovementResult Controller::Setup(const char * opponentName)
+{
+ string setup[4] = {"","","",""};
+ MovementResult query = this->QuerySetup(opponentName, setup);
+ if (query != MovementResult::OK)
+ return query;
+
+
+
+ int usedUnits[(int)(Piece::BOMB)];
+ for (int ii = 0; ii <= (int)(Piece::BOMB); ++ii)
+ usedUnits[ii] = 0;
+
+ int yStart = 0;
+ switch (colour)
+ {
+ case Piece::RED:
+ yStart = 0;
+ break;
+ case Piece::BLUE:
+ yStart = Game::theGame->theBoard.Height()-4;
+ break;
+ default:
+ return MovementResult::COLOUR_ERROR;
+ break;
+ }
+
+
+ for (int y = 0; y < 4; ++y)
+ {
+ if ((int)setup[y].length() != Game::theGame->theBoard.Width())
+ return MovementResult::BAD_RESPONSE;
+
+ for (int x = 0; x < Game::theGame->theBoard.Width(); ++x)
+ {
+ Piece::Type type = Piece::GetType(setup[y][x]);
+ if (type != Piece::NOTHING)
+ {
+ usedUnits[(int)(type)]++;
+ if (usedUnits[type] > Piece::maxUnits[(int)type])
+ {
+ //fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
+ return MovementResult::BAD_RESPONSE;
+ }
+ Game::theGame->theBoard.AddPiece(x, yStart+y, type, colour);
+ }
+ }
+ }
+ if (usedUnits[(int)Piece::FLAG] <= 0)
+ {
+ return MovementResult::BAD_RESPONSE; //You need to include a flag!
+ }
+
+ return MovementResult::OK;
+
+}
+
+
+/**
+ * Queries the player to respond to a state of Game::theGame->theBoard
+ * @param buffer String which is used to store the player's responses
+ * @returns The result of the response and/or move if made
+ */
+MovementResult Controller::MakeMove(string & buffer)
+{
+ buffer.clear();
+ MovementResult query = this->QueryMove(buffer);
+ if (query != MovementResult::OK)
+ return query;
+
+ if (buffer == "NO_MOVE")
+ {
+ buffer += " OK";
+ return MovementResult::OK;
+ }
+ if (buffer == "SURRENDER")
+ {
+ buffer += " OK";
+ return MovementResult::SURRENDER;
+ }
+
+ int x; int y; string direction="";
+ stringstream s(buffer);
+ s >> x;
+ s >> y;
+
+
+ s >> direction;
+ Board::Direction dir;
+ if (direction == "UP")
+ {
+ dir = Board::UP;
+ }
+ else if (direction == "DOWN")
+ {
+ dir = Board::DOWN;
+ }
+ else if (direction == "LEFT")
+ {
+ dir = Board::LEFT;
+ }
+ else if (direction == "RIGHT")
+ {
+ dir = Board::RIGHT;
+ }
+ else
+ {
+ if (Game::theGame->allowIllegalMoves)
+ return MovementResult::OK;
+ else
+ return MovementResult::BAD_RESPONSE; //Player gave bogus direction - it will lose by default.
+ }
+
+ int multiplier = 1;
+ if (s.peek() != EOF)
+ s >> multiplier;
+ MovementResult moveResult = Game::theGame->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::tokens[(int)(moveResult.attackerRank)] << " " << Piece::tokens[(int)(moveResult.defenderRank)];
+ switch (moveResult.type)
+ {
+ case MovementResult::OK:
+ buffer += " OK";
+ break;
+ case MovementResult::VICTORY:
+ buffer += " FLAG";
+ break;
+ case MovementResult::KILLS:
+ buffer += " KILLS ";
+ buffer += s.str();
+
+ break;
+ case MovementResult::DIES:
+ buffer += " DIES ";
+ buffer += s.str();
+ break;
+ case MovementResult::BOTH_DIE:
+ buffer += " BOTHDIE ";
+ buffer += s.str();
+ break;
+ default:
+ buffer += " ILLEGAL";
+ break;
+
+ }
+
+
+ if (!Board::LegalResult(moveResult))
+ {
+
+ if (Game::theGame->allowIllegalMoves)
+ {
+
+ return MovementResult::OK; //HACK - Illegal results returned as legal! (Move not made)
+ }
+ else if (this->HumanController()) //Cut human controllers some slack and let them try again...
+ {
+ //Yes, checking type of object is "not the C++ way"
+ // But sometimes its bloody useful to know!!!
+ Message("Bad move: \'" + buffer + "\' <- Please try again!");
+ buffer = "";
+ return this->MakeMove(buffer);
+ }
+ }
+
+ return moveResult;
+
+}