forfax.h 5.91 KB
Newer Older
Sam Moore's avatar
Sam Moore committed
1
2
3
4
5
6
7
8
9
/**
 * "forfax", a sample Stratego AI for the UCC Programming Competition 2012
 * Declarations for classes Piece, Board and Forfax, Declaration/Implementation of helper class MovementChoice
 * @author Sam Moore (matches) [SZM]
 * @website http://matches.ucc.asn.au/stratego
 * @email [email protected] or [email protected]
 * @git git.ucc.asn.au/progcomp2012.git
 */

Sam Moore's avatar
Sam Moore committed
10
11
12
13
14
#ifndef FORFAX_H
#define FORFAX_H

#include <vector> //Uses C++ std::vectors to store pieces
#include <string> //Uses C++ std::string
Sam Moore's avatar
Sam Moore committed
15
16
17
18
19
20
21
#include <iostream> //For debug
#include <cassert> //For debug



class Board;	//Forward declaration used by class Piece
	
Sam Moore's avatar
Sam Moore committed
22
23
24
25
26
27
28
29
30
31
/**
 * Class to represent a piece on the board
 */
class Piece
{
	public:
		typedef enum {ERROR=14,BOMB=13,MARSHAL=12, GENERAL=11, COLONEL=10, MAJOR=9, CAPTAIN=8, LIEUTENANT=7, SERGEANT=6, MINER=5, SCOUT=4, SPY=3, FLAG=2,BOULDER=1, NOTHING=0} Type; //Type basically defines how strong the piece is
		typedef enum {RED=0, BLUE=1, NONE, BOTH} Colour; //Used for the allegiance of the pieces - terrain counts as NONE.

		Piece(int newX, int newY,const Colour & newColour);
Sam Moore's avatar
Sam Moore committed
32
		Piece(int newX, int newY,const Colour & newColour, const Type & fixedRank);
Sam Moore's avatar
Sam Moore committed
33
34
35
36
37
38
39
40
41
42
43
		virtual ~Piece() {}
		
		void SetCoords(int newX, int newY) {x = newX; y = newY;}
		void GetCoords(int & storeX, int & storeY) const {storeX = x; storeY = y;}
		const Colour & GetColour() const {return colour;}

		static  char tokens[]; //The tokens used to identify various pieces
		static int maxUnits[]; //The maximum allowed number of units of each piece

		static Type GetType(char fromToken); //Retrieves the type of a piece given its character token
		static Colour Opposite(const Colour & colour) {return colour == RED ? BLUE : RED;}
Sam Moore's avatar
Sam Moore committed
44
45
46
47
48
49
50
		bool Mobile() const
		{
			if (minRank == maxRank)
				return (minRank != Piece::FLAG && minRank != Piece::BOMB);
			else
				return true;
		}
Sam Moore's avatar
Sam Moore committed
51
52
53

		int x; int y;
		const Colour colour; //The colour of the piece
Sam Moore's avatar
Sam Moore committed
54
55
		Type minRank; //The minimum possible rank of the piece
		Type maxRank; //The maximum possible rank of the piece
Sam Moore's avatar
Sam Moore committed
56
		int lastMove;
Sam Moore's avatar
Sam Moore committed
57
		int lastx; int lasty;
Sam Moore's avatar
Sam Moore committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
		
		

};

/**
 * Class to represent a board
 */
class Board
{
	public:
		Board(int width, int height);
		virtual ~Board();


		std::vector<Piece*> & GetPieces(const Piece::Colour & colour) {return colour == Piece::RED ? red : blue;} //retrieve array of pieces
		
		Piece * Get(int x, int y) const; //Retrieve single piece
Sam Moore's avatar
Sam Moore committed
76
		Piece * GetClosest(int x, int y, const Piece::Colour & search = Piece::BOTH) const; //Retrieve closest piece of specified colour to the point
Sam Moore's avatar
Sam Moore committed
77
78
		Piece *  Set(int x, int y, Piece * newPiece); //Add piece to board

Sam Moore's avatar
Sam Moore committed
79
80
		bool ValidPosition(int x, int y) const {return (x > 0 && x < width && y > 0 && y < height);}

Sam Moore's avatar
Sam Moore committed
81
82
83
84
85
86
87
88
89
		int Width() const {return width;}
		int Height() const {return height;}

		typedef enum {UP=0, DOWN=1, LEFT=2, RIGHT=3, NONE=4} Direction;
		static Direction StrToDir(const std::string & str);
		static void DirToStr(const Direction & dir, std::string & buffer);

		static void MoveInDirection(int & x, int & y, const Direction & dir, int multiplier = 1);
		static Direction DirectionBetween(int x1, int y1, int x2, int y2);
Sam Moore's avatar
Sam Moore committed
90
		static int NumberOfMoves(int x1, int y1, int x2, int y2);
Sam Moore's avatar
Sam Moore committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
		

		static int redUnits[];
		static int blueUnits[];
	

		bool ForgetPiece(Piece * forget); //removes piece from the red and blue vectors

	private:
		friend class Forfax;

		int width;
		int height;
		Piece ** * board;

		std::vector<Piece*> red; //Store all red pieces
		std::vector<Piece*> blue; //Store all blue pieces
	

};

/** 
Sam Moore's avatar
Sam Moore committed
113
 * Class to manage the Forfax AI
Sam Moore's avatar
Sam Moore committed
114
115
116
117
118
119
120
 */
class Forfax
{
	public:
		Forfax();
		virtual ~Forfax();

Sam Moore's avatar
Sam Moore committed
121
122
123
124
125
126
127
128
129
		typedef enum {OK, NO_NEWLINE, EXPECTED_ATTACKER, UNEXPECTED_DEFENDER, NO_ATTACKER, NO_DEFENDER, COLOUR_MISMATCH, INVALID_QUERY, BOARD_ERROR, VICTORY} Status;

		Status Setup(); //Waits for input to determine colour and board size, and then responds with setup
		Status MakeMove(); //Should be called each turn - determines Forfax's move


		//Move score functions
		double MovementScore(Piece * move, const Board::Direction & dir) const; //Calculate total score
		double CombatSuccessChance(Piece * attacker, Piece * defender) const; //Calculate chance of success in combat
Sam Moore's avatar
Sam Moore committed
130
		double CombatScore(int x, int y, Piece * attacker) const; //Calculate total worth of combat at a point
Sam Moore's avatar
Sam Moore committed
131
132
133
134
135
136
		double IntrinsicWorth(int x, int y) const; //How much a given point on the board is worth
		double VictoryScore(Piece * attacker, Piece * defender) const; //How much killing the defender is worth
		double DefeatScore(Piece * attacker, Piece * defender) const; //How much losing is worth


		void PrintBoard(std::ostream & out);
Sam Moore's avatar
Sam Moore committed
137
138

	protected:
Sam Moore's avatar
Sam Moore committed
139
140
		Status MakeFirstMove(); //Should only be called on the first turn
		Status InterpretMove();
Sam Moore's avatar
Sam Moore committed
141
142
143
144
145
146
	private:
		Board * board; //Forfax stores the state on a board
		Piece::Colour colour; //Forfax needs to know his colour
		std::string strColour; //String of colour
		int turnNumber; //Forfax needs to know what turn number it is
		
Sam Moore's avatar
Sam Moore committed
147
		static int remainingUnits[2][15]; //Known remaining units, accessed by [colour][type]
Sam Moore's avatar
Sam Moore committed
148
149
150

};

Sam Moore's avatar
Sam Moore committed
151
152
153
/**
 * Helper class used to store various moves in the board, and their associated scores
 */
Sam Moore's avatar
Sam Moore committed
154
155
156
class MovementChoice
{
	public:
Sam Moore's avatar
Sam Moore committed
157
		MovementChoice(Piece * newPiece, const Board::Direction & newDir, const Forfax & forfax) : piece(newPiece), dir(newDir) 
Sam Moore's avatar
Sam Moore committed
158
		{
Sam Moore's avatar
Sam Moore committed
159
			score = forfax.MovementScore(piece, dir);
Sam Moore's avatar
Sam Moore committed
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
		}

		MovementChoice(const MovementChoice & cpy) : piece(cpy.piece), dir(cpy.dir), score(cpy.score)
		{

		}
		
		bool operator<(const MovementChoice & a) const {return score < a.score;}
		bool operator>(const MovementChoice & a) const {return score > a.score;}
		bool operator<=(const MovementChoice & a) const {return score <= a.score;}
		bool operator>=(const MovementChoice & a) const {return score >= a.score;}
		bool operator==(const MovementChoice & a) const {return score == a.score;}
		bool operator!=(const MovementChoice & a) const {return score != a.score;}

		Piece * piece;
		Board::Direction dir;
		double score;
				
	
};


Sam Moore's avatar
Sam Moore committed
182

Sam Moore's avatar
Sam Moore committed
183
184
185
186
187
#endif //FORFAX_H

//EOF