Commit f91a915d authored by Sam Moore's avatar Sam Moore

First actual commit

More details to follow :P
parent b41b9981
This is a test
SPAM
#Makefile for Stratego
CPP = g++ -Wall -pedantic -lSDL -lGL -g
OBJ = main.o controller.o program.o thread_util.o stratego.o graphics.o
BIN = stratego
$(BIN) : $(OBJ)
$(CPP) -o $(BIN) $(OBJ)
%.o : %.cpp %.h
$(CPP) -c $<
clean :
$(RM) $(BIN) $(OBJ) $(LINKOBJ)
clean_full: #cleans up all backup files
$(RM) $(BIN) $(OBJ) $(LINKOBJ)
$(RM) *.*~
$(RM) *~
#ifndef ARRAY_H
#define ARRAY_H
typedef long unsigned int LUint;
#include <cassert>
template <class T>
class Array
{
public:
Array() : start(NULL), size(0), reserved(0) {}
Array(LUint newSize) : start(new T[newSize]), size(newSize), reserved(newSize) {}
~Array() {delete [] start;}
void Empty() {size = 0;}
void Add(const T & add);
void Reserve(LUint reserve);
void Resize(LUint newSize);
void RemoveBack();
LUint Size() const {return size;}
LUint Capacity() const {return reserved;}
void operator=(const Array & equ);
bool operator==(const Array & equ) const;
bool operator!=(const Array & equ) const {return !operator==(equ);}
class Iterator
{
public:
Iterator(const Array & from) : parent(from), index(0) {}
Iterator(const Iterator & cpy) : parent(cpy.parent), index(cpy.index) {}
~Iterator() {}
bool Good() const {return index < parent.Size();}
T & operator*() const {return parent.start[index];}
void operator++() {++index;}
void operator--() {--index;}
void operator++(int) {operator++();}
void operator--(int) {operator--();}
Iterator & operator+=(int amount) {index += amount;}
Iterator & operator-=(int amount) {index -= amount;}
Iterator operator+(int amount) {return Iterator(*this) += amount;}
Iterator operator-(int amount) {return Iterator(*this) -= amount;}
void operator=(const Iterator & set) {index = set.index;}
bool operator==(const Iterator & set) {return (&parent == &(set.parent) && index == set.index);}
private:
const Array & parent;
LUint index;
};
Iterator First() const {return Iterator(*this);}
Iterator Last() const {return Iterator(*this) -= (size-1);}
T & operator[](LUint at) const
{
#ifdef DEBUGALL
printf(" Array<T>::operator[] - called for index %lu/%lu (reserved %lu)\n", at, size, reserved);
#endif //DEBUG
assert(at < size); return start[at];
}
int Find(const T & find)
{
LUint result;
for (result = 0; result < size; result++)
{
//printf("%p %lu/%lu\n", (void*)(start), result, size);
if (start[result] == find)
return (int)(result);
}
return -1;
}
private:
T * start;
LUint size; LUint reserved;
};
template <class T> void Array<T>::Add(const T & add)
{
if (size >= reserved)
{
T * old = start;
reserved *= 2; ++reserved;
start = new T[reserved];
for (LUint ii=0; ii < size; ++ii)
start[ii] = old[ii];
delete [] old;
}
start[size++] = add;
}
template <class T> void Array<T>::RemoveBack()
{
if (size > 0)
--size;
}
template <class T> void Array<T>::Resize(LUint newSize)
{
T * old = start;
start = new T[newSize];
for (LUint ii=0; ii < size; ++ii)
start[ii] = old[ii];
size = newSize; reserved = newSize;
delete [] old;
}
template <class T> void Array<T>::Reserve(LUint newReserve)
{
if (newReserve > reserved)
{
T * old = start;
start = new T[newReserve];
for (LUint ii=0; ii < size; ++ii)
start[ii] = old[ii];
reserved = newReserve;
}
}
#endif //ARRAY_H
#ifndef COMMON_H
#define COMMON_H
#define GRAPHICS
#endif //COMMON_H
//EOF
#include <sstream>
#include "stratego.h"
#include "controller.h"
using namespace std;
/**
* Queries the AI program to setup its pieces
* @returns the result of the response
*/
Board::MovementResult Controller::Setup(const char * opponentName)
{
int y;
switch (colour)
{
case Piece::RED:
assert(SendMessage("RED %s %d %d", opponentName, Board::theBoard.Width(), Board::theBoard.Height()));
y = 0;
break;
case Piece::BLUE:
assert(SendMessage("BLUE %s %d %d", opponentName, Board::theBoard.Width(), Board::theBoard.Height()));
y = Board::theBoard.Height()-4;
break;
case Piece::NONE:
case Piece::BOTH:
//Should never see this;
assert(false);
break;
}
int usedUnits[(int)(Piece::BOMB)];
for (int ii = 0; ii <= (int)(Piece::BOMB); ++ii)
usedUnits[ii] = 0;
//The setup is spread across 4 lines of the board - blue at the top, red at the bottom. AI has 2.5s for each line.
for (int ii=0; ii < 4; ++ii)
{
string line="";
if (!GetMessage(line, 2.5))
{
fprintf(stderr, "Timeout on setup\n");
return Board::BAD_RESPONSE;
}
if ((int)(line.size()) != Board::theBoard.Width())
{
fprintf(stderr, "Bad length of \"%s\" on setup\n", line.c_str());
return Board::BAD_RESPONSE;
}
for (int x = 0; x < (int)(line.size()); ++x)
{
Piece::Type type = Piece::GetType(line[x]);
if (type != Piece::NOTHING)
{
//fprintf(stderr, "x y %d %d\n", x, y+ii);
// fprintf(stderr, "Found unit of type '%c' (%d '%c') %d vs %d\n", line[x], (int)(type), Piece::tokens[(int)(type)], usedUnits[(int)(type)], Piece::maxUnits[(int)type]);
/// fprintf(stderr, "Marshal is %d '%c', flag is %d '%c'\n", (int)Piece::MARSHAL, Piece::tokens[(int)(Piece::MARSHAL)], (int)Piece::FLAG, Piece::tokens[(int)(Piece::FLAG)]);
usedUnits[(int)(type)] += 1;
if (usedUnits[type] > Piece::maxUnits[(int)type])
{
fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
return Board::BAD_RESPONSE;
}
Board::theBoard.AddPiece(x, y+ii, type, colour);
}
}
}
if (usedUnits[(int)Piece::FLAG] <= 0)
{
return Board::BAD_RESPONSE; //You need to include a flag!
}
return Board::OK;
}
/**
* Queries the AI program to respond to a state of Board::theBoard
* @returns The result of the response and/or move if made
*/
Board::MovementResult Controller::MakeMove(string & buffer)
{
if (!Running())
return Board::NO_MOVE; //AI has quit
Board::theBoard.Print(output, colour);
buffer.clear();
if (!GetMessage(buffer,2))
{
return Board::NO_MOVE; //AI did not respond. It will lose by default.
}
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
{
fprintf(stderr, "BAD_RESPONSE \"%s\"\n", buffer.c_str());
return Board::BAD_RESPONSE; //AI gave bogus direction - it will lose by default.
}
int multiplier = 1;
if (s.peek() != EOF)
s >> multiplier;
Board::MovementResult moveResult = Board::theBoard.MovePiece(x, y, dir, multiplier, colour);
switch (moveResult)
{
case Board::OK:
buffer += " OK";
break;
case Board::VICTORY:
buffer += " FLAG";
break;
case Board::KILLS:
buffer += " KILLS";
break;
case Board::DIES:
buffer += " DIES";
break;
case Board::BOTH_DIE:
buffer += " BOTHDIE";
break;
default:
buffer += " ILLEGAL";
break;
}
if (!Board::LegalResult(moveResult))
return Board::OK; //HACK - Legal results returned!
else
return moveResult;
}
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "stratego.h"
#include "program.h"
/**
* Class to control an AI program for a game of Stratego
* Inherits most features from the Program class
*/
class Controller : public Program
{
public:
Controller(const Piece::Colour & newColour, const char * executablePath) : Program(executablePath), colour(newColour) {}
virtual ~Controller() {}
Board::MovementResult Setup(const char * opponentName); //Requests the AI program for the initial positioning of its pieces.
Board::MovementResult MakeMove(std::string & buffer); //Queries the AI program for a response to the state of Board::theBoard
const Piece::Colour colour; //Colour identifying the side of the AI program.
};
#endif //CONTROLLER_H
../samples/dummy
\ No newline at end of file
#include "graphics.h"
#include <cmath>
#include <cassert>
#include <iostream>
#undef DEBUG
//#define DEBUG
std::list<SDL_Surface*> Graphics::allTextures = std::list<SDL_Surface*>();
Screen * Graphics::screen = NULL;
int Graphics::screenWidth = 0;
int Graphics::screenHeight = 0;
bool Graphics::initialised = false;
using namespace std;
Texture::Texture(const char * filename, bool newDrawCentred) : surface(NULL), texture(0), drawCentred(newDrawCentred)
{
#ifdef DEBUG
printf("Texture::Texture - loading \"%s\".\n", filename);
#endif //DEBUG
surface = Graphics::LoadTextureBMP(filename);
if (surface == NULL)
{
fprintf(stderr, "Texture::Texture - Could not open texture from file \"%s\"! ABORT\n", filename);
exit(EXIT_FAILURE);
}
GLenum texture_format;
GLint nOfColours = surface->format->BytesPerPixel;
switch (nOfColours)
{
case 4: //contains alpha
texture_format = (surface->format->Rmask == 0x000000FF) ? GL_RGBA : GL_BGRA;
break;
case 3: //does not contain alpha
texture_format = (surface->format->Rmask == 0x000000FF) ? GL_RGB : GL_BGR;
break;
default:
fprintf(stderr,"Texture::Texture - Could not understand SDL_Surface format (%d colours)! ABORT\n", nOfColours);
exit(EXIT_FAILURE);
break;
}
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D(GL_TEXTURE_2D, 0, nOfColours, surface->w, surface->h,0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
}
Texture::~Texture()
{
#ifdef DEBUG
printf("Texture::~Texture - %p has been deleted. glDeleteTexture and SDL_FreeSurface here.\n", (void*)(this));
#endif //DEBUG
glDeleteTextures(1, &texture);
//SDL_FreeSurface(surface);
}
void Texture::DrawColour(int x, int y, double angle, double scale, Colour colour)
{
if (scale > surface->w || scale > surface->h)
{
Graphics::DrawPixel(x/scale,y/scale,colour);
}
else
{
glColor3f(colour.r,colour.g,colour.b);
Draw(x,y,angle,scale);
glColor3f(1,1,1);
}
}
void Texture::Draw(int x, int y, double angle , double scale )
{
//Draws the CENTRE of the texture at x, y, rotated by angle
#ifdef DEBUG
printf(" Texture::Draw - Drawing %p at (%d, %d) ; angle %2f ; scale % 2f\n", (void*)(this), x, y, angle, scale);
#endif //DEBUG
//if (x/scale < 0 || x/scale > Graphics::ScreenWidth() || y/scale < 0 || y/scale > Graphics::ScreenHeight() )
// return;
glPushMatrix(); //NOT deprecated
glTranslatef(x/scale, y/scale,0);
if (scale > surface->w || scale > surface->h)
{
Graphics::DrawPixel(0,0, Colour(255,255,255));
}
else
{
glRotated(angle, 0, 0, 1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
//scale /= 2;
if (drawCentred)
{
glTexCoord2i(0,0); glVertex3f(-0.5f/scale*surface->w ,-0.5f/scale*surface->h,0); //bottom left
glTexCoord2i(1,0); glVertex3f(0.5f/scale*surface->w,-0.5f/scale*surface->h,0); //bottom right
glTexCoord2i(1,1); glVertex3f(0.5f/scale*surface->w,0.5f/scale*surface->h,0); //top right
glTexCoord2i(0,1); glVertex3f(-0.5f/scale*surface->w,0.5f/scale*surface->h,0); //top left
}
else
{
glTexCoord2i(0,0); glVertex3f(0 ,0,0); //bottom left
glTexCoord2i(1,0); glVertex3f(1.0f/scale*surface->w,0,0); //bottom right
glTexCoord2i(1,1); glVertex3f(1.0f/scale*surface->w,1.0f/scale*surface->h,0); //top right
glTexCoord2i(0,1); glVertex3f(0,1.0f/scale*surface->h,0); //top left
}
glEnd();
glDisable(GL_TEXTURE_2D);
}
glPopMatrix();
}
Font::Font(const char * filename, int newWidth, int newHeight) : Texture(filename), width(newWidth), height(newHeight)
{
}
Font::~Font()
{
}
void Font::DrawText(const char * string, int x, int y, double angle, double scale)
{
#ifdef DEBUG
printf("Font::DrawText - drawing \"%s\"\n", string);
#endif //DEBUG
glPushMatrix(); //NOT deprecated
glTranslatef(x, y,0);
glRotated(angle, 0, 0, 1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
for (int ii=0; string[ii] != '\0'; ++ii)
{
if (string[ii] != ' ')
{
glPushMatrix();
glTranslatef(ii*(float)(width)/(float)(scale),0,0);
int index = (int)(string[ii]) - (int)('!');
if (index < 0 || index > (int)('~') - (int)('!'))
index = (int)('~') - (int)('!') + 1;
float start = (float)(((((float)(index))*((float)(width)))-3.0f)/((float)surface->w));
float end = (float)(((((float)(index+1))*((float)(width)))-4.0f)/((float)surface->w));
if (start < 0) {start = 0;} if (end > 1) {end = 1;}
glBegin(GL_QUADS);
glTexCoord2f(start,0); glVertex3f(-0.5f/scale*width ,-0.5f/scale*height,0); //bottom left
glTexCoord2f(end,0); glVertex3f(0.5f/scale*width,-0.5f/scale*height,0); //bottom right
glTexCoord2f(end,1); glVertex3f(0.5f/scale*width,0.5f/scale*height,0); //top right
glTexCoord2f(start,1); glVertex3f(-0.5f/scale*width,0.5f/scale*height,0); //top left
//printf("Index %d - Drawing %c - maps to %f->%f\n", index,string[ii],start,end);
glEnd();
glPopMatrix();
}
}
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
void Graphics::Initialise(const char * caption, int newWidth, int newHeight)
{
if (Initialised())
{
std::cerr << "Graphics have already been initialised! Fatal Error\n";
exit(EXIT_FAILURE);
}
screenWidth = newWidth; screenHeight = newHeight;
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
std::cerr << "Couldn't init SDL!\n";
exit(EXIT_FAILURE);
}
// atexit(Graphics::Destroy); BREAKS THINGS
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); //According to sulix does not matter. (much)
screen = SDL_SetVideoMode(screenWidth,screenHeight, 32, SDL_OPENGL);
if ( screen == NULL )
{
std::cerr << "Couldn't set " << screenWidth << "x" << screenHeight << "x32 video mode: " << SDL_GetError() << "\n";
exit(EXIT_FAILURE);
}
//COMES AFTER SETVIDEO MODE
glEnable(GL_TEXTURE_2D);
glClearColor(1,1,1,0); //Set clear colour (white) here
glViewport(0,0,screenWidth,screenHeight); //DOES matter
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,screenWidth,screenHeight,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
SDL_WM_SetCaption( caption, NULL);
Graphics::initialised = true;