controller.cpp 3.83 KB
Newer Older
Sam Moore's avatar
Sam Moore committed
1
2
#include "controller.h"

3
4
5
#include <sstream>
#include "game.h"

Sam Moore's avatar
Sam Moore committed
6
7
8
using namespace std;

/**
9
10
 * Queries the player to setup their pieces
 *
Sam Moore's avatar
Sam Moore committed
11
 */
12

13
MovementResult Controller::Setup(const char * opponentName)
Sam Moore's avatar
Sam Moore committed
14
{
15
16
17
18
19
20
21
22
23
24
25
26
	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;
Sam Moore's avatar
Sam Moore committed
27
28
29
	switch (colour)
	{
		case Piece::RED:
30
			yStart = 0;
Sam Moore's avatar
Sam Moore committed
31
32
			break;
		case Piece::BLUE:
33
			yStart = Game::theGame->theBoard.Height()-4;
Sam Moore's avatar
Sam Moore committed
34
			break;
35
36
		default:
			return MovementResult::COLOUR_ERROR; 
Sam Moore's avatar
Sam Moore committed
37
38
39
40
			break;
	}


41
	for (int y = 0; y < 4; ++y)
Sam Moore's avatar
Sam Moore committed
42
	{
43
		if ((int)setup[y].length() != Game::theGame->theBoard.Width())
44
			return MovementResult::BAD_RESPONSE;
45
46

		for (int x = 0; x < Game::theGame->theBoard.Width(); ++x)
Sam Moore's avatar
Sam Moore committed
47
		{
48
			Piece::Type type = Piece::GetType(setup[y][x]);
Sam Moore's avatar
Sam Moore committed
49
50
			if (type != Piece::NOTHING)
			{
51
				usedUnits[(int)(type)]++;
Sam Moore's avatar
Sam Moore committed
52
53
				if (usedUnits[type] > Piece::maxUnits[(int)type])
				{
54
					//fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
55
					return MovementResult::BAD_RESPONSE;
Sam Moore's avatar
Sam Moore committed
56
				}
57
				Game::theGame->theBoard.AddPiece(x, yStart+y, type, colour);
Sam Moore's avatar
Sam Moore committed
58
			}
59
		}
Sam Moore's avatar
Sam Moore committed
60
61
62
	}
	if (usedUnits[(int)Piece::FLAG] <= 0)
	{
63
		return MovementResult::BAD_RESPONSE; //You need to include a flag!
Sam Moore's avatar
Sam Moore committed
64
65
	}

66
	return MovementResult::OK;
67

Sam Moore's avatar
Sam Moore committed
68
69
70
71
}


/**
72
73
 * Queries the player to respond to a state of Game::theGame->theBoard
 * @param buffer String which is used to store the player's responses
Sam Moore's avatar
Sam Moore committed
74
75
 * @returns The result of the response and/or move if made
 */
76
MovementResult Controller::MakeMove(string & buffer)
Sam Moore's avatar
Sam Moore committed
77
78
{
	buffer.clear();
79
80
81
	MovementResult query = this->QueryMove(buffer);
	if (query != MovementResult::OK)
		return query;
Sam Moore's avatar
Sam Moore committed
82

83
84
85
86
87
88
89
90
91
92
	if (buffer == "NO_MOVE")
	{
		buffer += " OK";
		return MovementResult::OK;
	}
	if (buffer == "SURRENDER")
	{
		buffer += " OK";
		return MovementResult::SURRENDER;
	}
93
	
Sam Moore's avatar
Sam Moore committed
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	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
	{
120
		//fprintf(stderr, "BAD_RESPONSE \"%s\"\n", buffer.c_str());
121
		return MovementResult::BAD_RESPONSE; //Player gave bogus direction - it will lose by default.	
Sam Moore's avatar
Sam Moore committed
122
123
124
125
126
	}

	int multiplier = 1;
	if (s.peek() != EOF)
		s >> multiplier;
127
	MovementResult moveResult = Game::theGame->theBoard.MovePiece(x, y, dir, multiplier, colour);
128
129
130
131
132

	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
133
	s << Piece::tokens[(int)(moveResult.attackerRank)] << " " << Piece::tokens[(int)(moveResult.defenderRank)];	
134
	switch (moveResult.type)
Sam Moore's avatar
Sam Moore committed
135
	{
136
		case MovementResult::OK:
Sam Moore's avatar
Sam Moore committed
137
138
			buffer += " OK";
			break;
139
		case MovementResult::VICTORY:
Sam Moore's avatar
Sam Moore committed
140
141
			buffer += " FLAG";
			break;
142
143
144
145
		case MovementResult::KILLS:
			buffer += " KILLS ";
			buffer += s.str();

Sam Moore's avatar
Sam Moore committed
146
			break;
147
148
149
		case MovementResult::DIES:
			buffer += " DIES ";
			buffer += s.str();
Sam Moore's avatar
Sam Moore committed
150
			break;
151
152
153
		case MovementResult::BOTH_DIE:
			buffer += " BOTHDIE ";
			buffer += s.str();
Sam Moore's avatar
Sam Moore committed
154
155
156
157
158
159
160
			break;	
		default:
			buffer += " ILLEGAL";
			break;			
		
	}

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	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; 	
Sam Moore's avatar
Sam Moore committed
176
177

}