Commit 15970878 authored by Sam Moore's avatar Sam Moore

Stuff happened

- Fixed C++ agent (yay)
- Added Java agent (ew)
- Renamed some things (why?)
parent c2fbd2e5
# Makefile for agent++
CXX = g++ -std=gnu++0x -g -Werror -Wall -pedantic
LINK_OBJ = qchess.o agent.o main.o
BIN = agent++
$(BIN) : $(LINK_OBJ)
$(CXX) -o $(BIN) $(LINK_OBJ)
%.o : %.c
$(CXX) $(FLAGS) -c $<
clean :
$(RM) $(BIN) $(OBJ) $(LINK_OBJ)
clean_full: #cleans up all backup files
$(RM) $(BIN) $(OBJ) $(LINK_OBJ)
$(RM) *.*~
$(RM) *~
......@@ -13,9 +13,9 @@ using namespace std;
* @constructor Agent
* @param new_colour - colour of the Agent
*/
Agent::Agent(const string & new_colour) : colour(new_colour), board(), selected(NULL)
Agent::Agent(const string & new_colour) : colour(Piece::str2colour(new_colour)), board(), selected(NULL)
{
assert(colour == "white" || colour == "black");
}
/**
......
......@@ -28,7 +28,7 @@ class Agent
protected:
const std::string colour; // colour of the agent; do not change it
const Piece::Colour colour; // colour of the agent; do not change it
Board board; // board, see qchess.h
Piece * selected; // last piece chosen by Agent::Select, see qchess.h
......
......@@ -22,8 +22,17 @@ int main(int argc, char ** argv)
srand(time(NULL)); // seed random number generator
string colour; cin >> colour; // first read the colour of the agent
Agent agent(colour); // create an agent using the colour
agent.Run(cin, cout); // run the agent (it will read from cin and output to cout)
try
{
Agent agent(colour); // create an agent using the colour
agent.Run(cin, cout); // run the agent (it will read from cin and output to cout)
}
catch (const Exception & e)
{
return 1;
}
return 0; // Don't use exit(3), because it causes memory leaks in the C++ stdlib
}
......@@ -16,13 +16,13 @@ using namespace std;
* @param type1, type2 - Types of piece
* @param index - Index for initial type of piece
*/
Piece::Piece(int new_x, int new_y, const string & new_colour, const string & type1, const string & type2, int index)
Piece::Piece(int new_x, int new_y, const Piece::Colour & new_colour, const Piece::Type & type1, const Piece::Type & type2, int index)
: x(new_x), y(new_y), colour(new_colour), type_index(index), types(), current_type()
{
types[0] = type1; types[1] = type2;
if (index < 0 || index >= 2)
{
current_type = "unknown";
current_type = Piece::UNKNOWN;
}
else
{
......@@ -58,16 +58,16 @@ Board::Board(bool choose_types)
}
// const arrays simplify below code
string colours[] = {"black", "white"};
string types[] = {"rook", "bishop", "knight", "queen", "pawn"};
Piece::Colour colours[] = {Piece::BLACK, Piece::WHITE};
Piece::Type types[] = {Piece::PAWN, Piece::BISHOP, Piece::KNIGHT, Piece::ROOK, Piece::QUEEN};
// frequency of each type of piece
map<string, int> freq;
freq["rook"] = 2;
freq["bishop"] = 2;
freq["knight"] = 2;
freq["queen"] = 1;
freq["pawn"] = 8;
map<Piece::Type, int> freq;
freq[Piece::ROOK] = 2;
freq[Piece::BISHOP] = 2;
freq[Piece::KNIGHT] = 2;
freq[Piece::QUEEN] = 1;
freq[Piece::PAWN] = 8;
// for white and black...
for (int i = 0; i < 2; ++i)
......@@ -80,21 +80,21 @@ Board::Board(bool choose_types)
int y = (i == 0) ? 1 : BOARD_HEIGHT-2;
for (int x = 0; x < BOARD_WIDTH; ++x)
{
Piece * p = new Piece(x, y, colours[i], "pawn", "unknown");
Piece * p = new Piece(x, y, colours[i], Piece::PAWN, Piece::UNKNOWN);
v.push_back(p);
}
// add other pieces
y = (i == 0) ? 0 : BOARD_HEIGHT-1;
v.push_back(new Piece(0, y, colours[i], "rook", "unknown"));
v.push_back(new Piece(BOARD_WIDTH-1, y, colours[i], "rook", "unknown"));
v.push_back(new Piece(1, y, colours[i], "knight", "unknown"));
v.push_back(new Piece(BOARD_WIDTH-2, y, colours[i], "knight", "unknown"));
v.push_back(new Piece(2, y, colours[i], "bishop", "unknown"));
v.push_back(new Piece(BOARD_WIDTH-3, y, colours[i], "bishop", "unknown"));
v.push_back(new Piece(3, y, colours[i], "queen", "unknown"));
Piece * k = new Piece(4, y, colours[i], "king", "king", 1);
v.push_back(new Piece(0, y, colours[i], Piece::ROOK, Piece::UNKNOWN));
v.push_back(new Piece(BOARD_WIDTH-1, y, colours[i], Piece::ROOK, Piece::UNKNOWN));
v.push_back(new Piece(1, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN));
v.push_back(new Piece(BOARD_WIDTH-2, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN));
v.push_back(new Piece(2, y, colours[i], Piece::BISHOP, Piece::UNKNOWN));
v.push_back(new Piece(BOARD_WIDTH-3, y, colours[i], Piece::BISHOP, Piece::UNKNOWN));
v.push_back(new Piece(3, y, colours[i], Piece::QUEEN, Piece::UNKNOWN));
Piece * k = new Piece(4, y, colours[i], Piece::KING, Piece::KING, 1);
if (i == 0)
white_king = k;
else
......@@ -102,7 +102,7 @@ Board::Board(bool choose_types)
v.push_back(k);
// add to board and choose second types if required
map<string, int> f(freq);
map<Piece::Type, int> f(freq);
int type2;
for (unsigned j = 0; j < v.size(); ++j)
{
......@@ -110,7 +110,7 @@ Board::Board(bool choose_types)
grid[p->x][p->y].piece = p;
if (choose_types)
{
if (p->types[1] != "unknown")
if (p->types[1] != Piece::UNKNOWN)
continue;
do
......@@ -185,8 +185,8 @@ void Board::Update_select(int x, int y, int index, const string & type)
assert(s.piece != NULL);
assert(index >= 0 && index < 2);
s.piece->type_index = index;
s.piece->types[index] = type;
s.piece->current_type = type;
s.piece->types[index] = Piece::str2type(type);
s.piece->current_type = s.piece->types[index];
}
/**
......@@ -217,7 +217,7 @@ void Board::Update_move(int x1, int y1, int x2, int y2)
Piece * k = king(s2.piece->colour);
if (k == s2.piece)
{
if (k->colour == "white")
if (k->colour == Piece::WHITE)
white_king = NULL;
else
black_king = NULL;
......@@ -241,9 +241,9 @@ void Board::Update_move(int x1, int y1, int x2, int y2)
*/
void Board::Get_moves(Piece * p, vector<Square*> & v)
{
assert(p->current_type != "unknown");
assert(p->current_type != Piece::UNKNOWN);
int x = p->x; int y = p->y;
if (p->current_type == "king")
if (p->current_type == Piece::KING)
{
Move(p, x+1, y, v);
Move(p, x-1, y, v);
......@@ -254,7 +254,7 @@ void Board::Get_moves(Piece * p, vector<Square*> & v)
Move(p, x-1, y+1, v);
Move(p, x-1, y-1, v);
}
else if (p->current_type == "knight")
else if (p->current_type == Piece::KNIGHT)
{
Move(p, x+2, y+1, v);
Move(p, x+2, y-1, v);
......@@ -265,16 +265,16 @@ void Board::Get_moves(Piece * p, vector<Square*> & v)
Move(p, x+1, y-2, v);
Move(p, x-1, y-2, v);
}
else if (p->current_type == "pawn")
else if (p->current_type == Piece::PAWN)
{
int y1 = (p->colour == "white") ? BOARD_HEIGHT-2 : 1;
int y2 = (p->colour == "white") ? y1 - 2 : y1 + 2;
if (p->types[0] == "pawn" && p->y == y1)
int y1 = (p->colour == Piece::WHITE) ? BOARD_HEIGHT-2 : 1;
int y2 = (p->colour == Piece::WHITE) ? y1 - 2 : y1 + 2;
if (p->types[0] == Piece::PAWN && p->y == y1)
{
Move(p, x, y2, v);
}
y2 = (p->colour == "white") ? y - 1 : y + 1;
y2 = (p->colour == Piece::WHITE) ? y - 1 : y + 1;
Move(p, x, y2, v);
if (Valid_position(x-1, y2) && grid[x-1][y2].piece != NULL)
......@@ -282,21 +282,21 @@ void Board::Get_moves(Piece * p, vector<Square*> & v)
if (Valid_position(x+1, y2) && grid[x+1][y2].piece != NULL)
Move(p, x+1, y2, v);
}
else if (p->current_type == "bishop")
else if (p->current_type == Piece::BISHOP)
{
Scan(p, 1, 1, v);
Scan(p, 1, -1, v);
Scan(p, -1, 1, v);
Scan(p, -1, -1, v);
}
else if (p->current_type == "rook")
else if (p->current_type == Piece::ROOK)
{
Scan(p, 1, 0, v);
Scan(p, -1, 0, v);
Scan(p, 0, 1, v);
Scan(p, 0, -1, v);
}
else if (p->current_type == "queen")
else if (p->current_type == Piece::QUEEN)
{
Scan(p, 1, 1, v);
Scan(p, 1, -1, v);
......@@ -341,7 +341,55 @@ void Board::Scan(Piece * p, int vx, int vy, vector<Square*> & v)
while (Valid_position(x, y) && (grid[x][y].piece == NULL || grid[x][y].piece->colour != p->colour))
{
v.push_back(&(grid[x][y]));
if (grid[x][y].piece != NULL)
break;
x += vx;
y += vy;
}
}
/**
* @funct str2type
* @purpose Convert string to Piece::Type
* @param str - The string
* @returns A Piece::Type
*/
Piece::Type Piece::str2type(const string & str)
{
if (str == "king")
return Piece::KING;
else if (str == "queen")
return Piece::QUEEN;
else if (str == "rook")
return Piece::ROOK;
else if (str == "bishop")
return Piece::BISHOP;
else if (str == "knight")
return Piece::KNIGHT;
else if (str == "pawn")
return Piece::PAWN;
else if (str == "unknown")
return Piece::UNKNOWN;
throw Exception("Piece::str2type", "String \"%s\" doesn't represent a type", str.c_str());
return Piece::UNKNOWN;
}
/**
* @funct str2colour
* @purpose Convert string to Piece::Colour
* @param str - The string
* @returns A Piece::Colour
*/
Piece::Colour Piece::str2colour(const string & str)
{
if (str == "white")
return Piece::WHITE;
else if (str == "black")
return Piece::BLACK;
throw Exception("Piece::str2colour", "string \"%s\" is not white|black", str.c_str());
return Piece::BLACK; // should never get here
}
......@@ -18,6 +18,9 @@
#include <cstdlib>
#include <iostream>
#include <stdarg.h>
#include <cstdio> // for vfprintf... for the Exception
/**
* @class Piece
* @purpose Represent a quantum chess piece
......@@ -25,16 +28,22 @@
class Piece
{
public:
Piece(int x, int y, const std::string & new_colour, const std::string & type1 = "unknown", const std::string & type2 = "unknown", int new_type_index = -1); // constructor
typedef enum {PAWN, BISHOP, KNIGHT, ROOK, QUEEN, KING, UNKNOWN} Type;
typedef enum {WHITE=0, BLACK=1} Colour;
Piece(int x, int y, const Colour & colour, const Type & type1, const Type & type2=UNKNOWN, int type_index = -1); // constructor
Piece(const Piece & cpy); // copy constructor
virtual ~Piece() {} // destructor
int x; int y; // position of the piece
std::string colour; // colour of the piece
Colour colour; // colour of the piece
int type_index; // indicates state the piece is in; 0, 1, or -1 (unknown)
std::string types[2]; // states of the piece
std::string current_type; // current state of the piece
Type types[2]; // states of the piece
Type current_type; // current state of the piece
static Type str2type(const std::string & str);
static Colour str2colour(const std::string & str);
};
......@@ -66,9 +75,9 @@ class Board
// helper; return vector of pieces given player colour
std::vector<Piece*> & pieces(const std::string & colour) {return ((colour == "white") ? white : black);}
std::vector<Piece*> & pieces(const Piece::Colour & colour) {return ((colour == Piece::WHITE) ? white : black);}
// helper; return king given player colour
Piece * king(const std::string & colour) {return ((colour == "white") ? white_king : black_king);}
Piece * king(const Piece::Colour & colour) {return ((colour == Piece::WHITE) ? white_king : black_king);}
void Update_move(int x, int y, int x2, int y2); // move a piece
void Update_select(int x, int y, int index, const std::string & type); // update a selected piece
......@@ -96,6 +105,25 @@ class Board
void Scan(Piece * p, int vx, int vy, std::vector<Square*> & v);
};
/**
* @class Exception
* @purpose The only exception.
*/
class Exception
{
public:
Exception(const char * funct, const char * fmt, ...)
{
fprintf(stderr, "Exception in %s - ", funct);
va_list va;
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
fprintf(stderr, "\n");
}
};
#endif //_QCHESS_H
//EOF
/**
* @class Agent
* @purpose Class that represents an agent which will play qchess
*/
import java.util.Random;
import java.util.Vector;
class Agent
{
public Agent(String colour) throws Exception
{
this.colour = Piece.str2colour(colour);
this.board = new Board();
this.selected = null;
this.rand = new Random();
}
public static void main(String [] args)
{
String colour = Reader.readLine();
try
{
Agent agent = new Agent(colour);
agent.Run();
}
catch (Exception e)
{
//System.err.println("EXCEPTION: agent.Run - "+e);
e.printStackTrace();
}
}
public void Run() throws Exception
{
while (true)
{
Vector<String> v = Reader.readTokens();
String cmd = v.get(0);
if (cmd.compareTo("QUIT") == 0)
break;
else if (cmd.compareTo("SELECTION?") == 0)
{
Square s = select();
System.out.println(Integer.toString(s.x) + " " + Integer.toString(s.y));
}
else if (cmd.compareTo("MOVE?") == 0)
{
Square s = move();
System.out.println(Integer.toString(s.x) + " " + Integer.toString(s.y));
}
else
{
int x = Integer.parseInt(v.get(0));
int y = Integer.parseInt(v.get(1));
if (v.get(2).compareTo("->") == 0)
{
int x2 = Integer.parseInt(v.get(3));
int y2 = Integer.parseInt(v.get(4));
board.Update_move(x, y, x2, y2);
}
else
{
int index = Integer.parseInt(v.get(2));
String type = v.get(3);
board.Update_select(x, y, index, type);
}
}
}
}
public Square select() throws Exception
{
Vector<Piece> p = board.pieces(colour);
int choice = rand.nextInt(p.size());
Square s = board.Get_square(p.get(choice).x, p.get(choice).y);
if (s.piece == null)
throw new Exception("ARGH");
selected = s.piece;
return s;
}
public Square move()
{
Vector<Square> v = new Vector<Square>();
board.Get_moves(selected, v);
return v.get(rand.nextInt(v.size()));
}
private final Piece.Colour colour; // colour of the agent; do not change it
private Board board;
private Piece selected;
private Random rand;
};
/**
* @class Board
* @purpose Represent a quantum chess board
*/
import java.util.Vector;
class Board
{
public static final int WIDTH = 8;
public static final int HEIGHT = 8;
public Board()
{
this.grid = new Square[Board.WIDTH][Board.HEIGHT];
for (int x = 0; x < Board.WIDTH; ++x)
{
for (int y = 0; y < Board.HEIGHT; ++y)
{
this.grid[x][y] = new Square(x, y, null);
this.grid[x][y].x = x;
this.grid[x][y].y = y;
}
}
Piece.Colour[] colours = {Piece.Colour.BLACK, Piece.Colour.WHITE};
this.white = new Vector<Piece>();
this.black = new Vector<Piece>();
for (int i = 0; i < colours.length; ++i)
{
Vector<Piece> p = pieces(colours[i]);
// add pawns
int y = (i == 0) ? 1 : Board.HEIGHT-2;
for (int x = 0; x < Board.WIDTH; ++x)
{
p.add(new Piece(x, y, colours[i], Piece.Type.PAWN, Piece.Type.UNKNOWN));
}
// add major pieces
y = (i == 0) ? 1 : Board.HEIGHT-1;
p.add(new Piece(0, y, colours[i], Piece.Type.ROOK, Piece.Type.UNKNOWN));
p.add(new Piece(1, y, colours[i], Piece.Type.KNIGHT, Piece.Type.UNKNOWN));
p.add(new Piece(2, y, colours[i], Piece.Type.BISHOP, Piece.Type.UNKNOWN));
Piece k = new Piece(3, y, colours[i], Piece.Type.KING, Piece.Type.KING);
p.add(k);
if (i == 0)
white_king = k;
else
black_king = k;
p.add(new Piece(4, y, colours[i], Piece.Type.QUEEN, Piece.Type.UNKNOWN));
p.add(new Piece(5, y, colours[i], Piece.Type.BISHOP, Piece.Type.UNKNOWN));
p.add(new Piece(6, y, colours[i], Piece.Type.KNIGHT, Piece.Type.UNKNOWN));
p.add(new Piece(7, y, colours[i], Piece.Type.ROOK, Piece.Type.UNKNOWN));
for (int j = 0; j < p.size(); ++j)
{
Piece pp = p.get(j);
grid[pp.x][pp.y].piece = pp;
}
}
}
public Vector<Piece> pieces(Piece.Colour colour)
{
return ((colour == Piece.Colour.WHITE) ? white : black);
}
public Piece king(Piece.Colour colour)
{
return ((colour == Piece.Colour.WHITE) ? white_king : black_king);
}
public void Update_move(int x, int y, int x2, int y2)
{
Square s1 = grid[x][y];
Square s2 = grid[x2][y2];
if (s2.piece != null)
{
Vector<Piece> v = pieces(s2.piece.colour);
v.remove(s2.piece);
if (s2.piece == king(s2.piece.colour))
{
if (s2.piece.colour == Piece.Colour.WHITE)
white_king = null;
else
black_king = null;
}
}
s1.piece.x = x2;
s1.piece.y = y2;
s2.piece = s1.piece;
s1.piece = null;
}
public void Update_select(int x, int y, int index, String type) throws Exception
{
Square s = grid[x][y];
s.piece.type_index = index;
s.piece.types[index] = Piece.str2type(type);
s.piece.current_type = s.piece.types[index];
}
public Square Get_square(int x, int y)
{
return grid[x][y]; // get square on board
}
public void Get_moves(Piece p, Vector<Square> v)
{
int x = p.x;
int y = p.y;
if (p.current_type == Piece.Type.KING)