X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=sidebyside;f=samples%2Fforfax%2Fforfax.h;fp=samples%2Fforfax%2Fforfax.h;h=fe370a9942a4ebff77f2c6b8d09d9b8e04f57ec7;hb=f91a915d6f64f9d35e867d26e8ddb9c1b1ab0c1e;hp=0000000000000000000000000000000000000000;hpb=b41b9981c516c746a075e96aeeb3d7914617c713;p=progcomp2012.git diff --git a/samples/forfax/forfax.h b/samples/forfax/forfax.h new file mode 100644 index 0000000..fe370a9 --- /dev/null +++ b/samples/forfax/forfax.h @@ -0,0 +1,159 @@ +#ifndef FORFAX_H +#define FORFAX_H + +#include //Uses C++ std::vectors to store pieces +#include //Uses C++ std::string +/** + * Header for the sample Stratego AI "forfax" + * @author Sam Moore 2011 + */ +class Board; +/** + * 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); + Piece(int newX, int newY,const Colour & newColour, const Colour & rankKnownBy, const Type & fixedRank); + 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;} + + + int x; int y; + const Colour colour; //The colour of the piece + Type minRank[2]; //The minimum possible rank of the piece, according to each colour + Type maxRank[2]; //The maximum possible rank of the piece, according to each colour + int lastMove; + + + +}; + +/** + * Class to represent a board + */ +class Board +{ + public: + Board(int width, int height); + virtual ~Board(); + + + std::vector & 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 + Piece * Set(int x, int y, Piece * newPiece); //Add piece to board + + 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); + + + + 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 red; //Store all red pieces + std::vector blue; //Store all blue pieces + + +}; + +/** + * Small class to manage the Forfax AI + */ +class Forfax +{ + public: + Forfax(); + virtual ~Forfax(); + bool Setup(); //Waits for input to determine colour and board size, and then responds with setup + bool MakeMove(); //Should be called each turn - determines Forfax's move + + double CombatSuccessChance(Piece * attacker, Piece * defender, const Piece::Colour & accordingTo) const; + double MovementBaseScore(Piece * move, const Board::Direction & dir, const Piece::Colour & accordingTo) const; + double MovementTotalScore(Piece * move, const Board::Direction & dir, const Piece::Colour & accordingTo) const; + + protected: + bool MakeFirstMove(); //Should only be called on the first turn + bool InterpretMove(); + 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 + + int remainingUnits[14][2][2]; //Known remaining units, accessed by (type, colour, accordingTo) + +}; + +class MovementChoice +{ + public: + MovementChoice(Piece * newPiece, const Board::Direction & newDir, const Forfax & forfax, const Piece::Colour & accordingTo) : piece(newPiece), dir(newDir) + { + score = forfax.MovementBaseScore(piece, dir, accordingTo); + } + + 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; + + +}; + +class MovementTotalChoice : public MovementChoice +{ + public: + MovementTotalChoice(Piece * newPiece, const Board::Direction & newDir, const Forfax & forfax, const Piece::Colour & accordingTo) : MovementChoice(newPiece, newDir, forfax, accordingTo) + { + score = score/(forfax.MovementTotalScore(piece, dir, Piece::Opposite(accordingTo))); + } +}; + +#endif //FORFAX_H + +//EOF + +