controller.cpp 3.86 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
	{
Sam Moore's avatar
Sam Moore committed
120
121
122
123
		if (Game::theGame->allowIllegalMoves)
			return MovementResult::OK;
		else
			return MovementResult::BAD_RESPONSE; //Player gave bogus direction - it will lose by default.	
Sam Moore's avatar
Sam Moore committed
124
125
126
127
128
	}

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

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

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

Sam Moore's avatar
Sam Moore committed
163
	
164
165
	if (!Board::LegalResult(moveResult))
	{
Sam Moore's avatar
Sam Moore committed
166
		
167
		if (Game::theGame->allowIllegalMoves)
Sam Moore's avatar
Sam Moore committed
168
169
		{
			
170
			return MovementResult::OK; //HACK - Illegal results returned as legal! (Move not made)
Sam Moore's avatar
Sam Moore committed
171
		}
172
173
174
175
176
177
178
179
180
181
182
		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
183
184

}