Commit b9a34f65 authored by Matt Williams's avatar Matt Williams
Browse files

Make code more elegant

Add helper functions to be used by the AI

svn path=/trunk/playground/games/ksquares/; revision=617293
parent 48261104
PROJECT(ksquares)
#find_package(KDE4 REQUIRED)
#include (KDE4Defaults)
#include (MacroLibrary)
#find_library(KDEGAMES_LIB kdegames ${KDE4_LIB_DIR})
#link_directories (${KDE4_LIB_DIR})
#if (KDEGAMES_LIB)
# add_subdirectory(src)
#endif (KDEGAMES_LIB)
add_subdirectory(src)
add_subdirectory(doc)
\ No newline at end of file
#! /bin/sh
$XGETTEXT *.cpp -o $podir/ksquares.pot
\ No newline at end of file
$EXTRACTRC `find . -name \*.ui -o -name \*.rc` >> rc.cpp || exit 11
$XGETTEXT *.cpp -o $podir/ksquares.pot
\ No newline at end of file
......@@ -12,30 +12,16 @@
#include <ctime>
#include <kdebug.h>
aiController::aiController(int newPlayerId)
aiController::aiController(int newPlayerId, QVector<bool> newLines, QVector<int> newSquareOwners, int newWidth, int newHeight) : squareOwners(newSquareOwners), lines(newLines), playerId(newPlayerId), width(newWidth), height(newHeight)
{
kDebug() << "AI: Starting AI..." << endl;
playerId = newPlayerId;
}
void aiController::setLines(QVector<bool> newLines)
{
kDebug() << "AI: Reading lines" << endl;
lines = newLines;
//kdDebug() << "AI: - lines.size(): " << lines.size() << endl;
}
void aiController::setSquareOwners(QVector<int> newSquareOwners)
{
kDebug() << "AI: Reading square ownerships" << endl;
squareOwners = newSquareOwners;
//kdDebug() << "AI: - newSquareOwners.size(): " << newSquareOwners.size() << endl;
}
int aiController::drawLine()
{
int indexChoice;
srand( (unsigned)time( NULL ) );
//kDebug() << "int aiController::drawLine()" << endl;
do
{
float randomFloat = ((float) rand()/(RAND_MAX + 1.0))*(lines.size()-1);
......@@ -46,4 +32,69 @@ int aiController::drawLine()
return indexChoice;
}
int aiController::countBorderLines(int squareIndex)
{
int count = 0;
QVector<int> lineList = linesFromSquare(squareIndex);
if(lines.at(lineList.at(0)) == true)
count++;
if(lines.at(lineList.at(1)) == true)
count++;
if(lines.at(lineList.at(2)) == true)
count++;
if(lines.at(lineList.at(3)) == true)
count++;
return count;
}
QVector<int> aiController::squaresFromLine(int lineIndex)
{
QVector<int> squareList;
if (lineDirection(lineIndex) == KS::HORIZONTAL)
{
squareList.append(lineIndex - ( (width+1) * (lineIndex/((width*2)+1)) ));
squareList.append(squareList.at(0) - width);
if(squareList.at(0) < 0)
squareList.remove(0);
if(squareList.at(1) >= (width*height))
squareList.remove(1);
}
else if (lineDirection(lineIndex) == KS::VERTICAL) //TODO: fix wrap-around
{
squareList.append(lineIndex - ( (lineIndex/((width*2)+1))*width + (lineIndex/((width*2)+1)) + width ));
squareList.append(squareList.at(0) - 1);
}
return squareList;
}
QVector<int> aiController::linesFromSquare(int squareIndex)
{
QVector<int> lineList;
int index1 = (squareIndex/width) * ((2*width) + 1) + (squareIndex%width);
int index2 = index1 + width;
int index3 = index2 + 1;
int index4 = index3 + width;
lineList.append(index1);
lineList.append(index2);
lineList.append(index3);
lineList.append(index4);
return lineList;
}
KS::Direction aiController::lineDirection(int lineIndex)
{
int index2 = lineIndex % ((2*width) + 1);
KS::Direction dir;
if(index2 < width)
dir = KS::HORIZONTAL;
else
dir = KS::VERTICAL;
return dir;
}
#include "aicontroller.moc"
......@@ -13,6 +13,11 @@
#include <QObject>
#include <QVector>
namespace KS
{
enum Direction {HORIZONTAL, VERTICAL};
}
/**
* @short AI Controller for KSquares
*
......@@ -31,9 +36,7 @@ class aiController : public QObject
Q_OBJECT
public:
aiController(int newPlayerId);
void setLines(QVector<bool> newLines);
void setSquareOwners(QVector<int> newSquareOwners);
aiController(int newPlayerId, QVector<bool> newLines, QVector<int> newSquareOwners, int newWidth, int newHeight);
/**
* Choses where to draw the line
* Currently only choses randomly :S
......@@ -45,9 +48,21 @@ class aiController : public QObject
public slots:
protected:
/**
* @param squareIndex the index of the square (relates to @ref squareOwners )
*
* @return The number of lines currently drawn around a specific square
*/
int countBorderLines(int squareIndex);
QVector<int> squaresFromLine(int lineIndex);
QVector<int> linesFromSquare(int squareIndex);
KS::Direction lineDirection(int lineIndex);
QVector<int> squareOwners;
QVector<bool> lines;
int playerId;
int width;
int height;
signals:
......
......@@ -65,7 +65,7 @@ bool GameBoardScene::isLineAlready(QList<QGraphicsEllipseItem*> pointPair)
qreal refX; // these two will be the grid-coord of the
qreal refY; // to and left most point of the two
enum{HORZONTAL, VERTICAL} dir;
enum{HORIZONTAL, VERTICAL} dir;
if (pointOneX == pointTwoX)
{
dir = VERTICAL;
......@@ -77,7 +77,7 @@ bool GameBoardScene::isLineAlready(QList<QGraphicsEllipseItem*> pointPair)
}
else if (pointOneY == pointTwoY)
{
dir = HORZONTAL;
dir = HORIZONTAL;
refY = pointOneY;
if (pointOneX < pointTwoX) //want the leftmost point as reference
refX = pointOneX;
......@@ -85,7 +85,7 @@ bool GameBoardScene::isLineAlready(QList<QGraphicsEllipseItem*> pointPair)
refX = pointTwoX;
}
if (dir == HORZONTAL)
if (dir == HORIZONTAL)
{
index = refY * ((2*width)+1) + refX;
}
......@@ -114,7 +114,7 @@ bool GameBoardScene::addLineToIndex(QList<QGraphicsEllipseItem*> pointPair)
qreal refX; // these two will be the grid-coord of the
qreal refY; // to and left most point of the two
enum{HORZONTAL, VERTICAL} dir;
enum{HORIZONTAL, VERTICAL} dir;
if (pointOneX == pointTwoX)
{
dir = VERTICAL;
......@@ -126,7 +126,7 @@ bool GameBoardScene::addLineToIndex(QList<QGraphicsEllipseItem*> pointPair)
}
else if (pointOneY == pointTwoY)
{
dir = HORZONTAL;
dir = HORIZONTAL;
refY = pointOneY;
if (pointOneX < pointTwoX) //want the leftmost point as reference
refX = pointOneX;
......@@ -134,7 +134,7 @@ bool GameBoardScene::addLineToIndex(QList<QGraphicsEllipseItem*> pointPair)
refX = pointTwoX;
}
if (dir == HORZONTAL)
if (dir == HORIZONTAL)
{
index = refY * ((2*width)+1) + refX;
}
......@@ -151,6 +151,7 @@ bool GameBoardScene::addLineToIndex(QList<QGraphicsEllipseItem*> pointPair)
bool GameBoardScene::addLineToIndex(int index)
{
//kDebug() << "bool GameBoardScene::addLineToIndex(int index)" << endl;
//kDebug() << "Adding line at index " << index << endl;
if (lineDrawn[index] == false) //if there's not a line there yet, do checks
{
......@@ -172,9 +173,9 @@ bool GameBoardScene::addLineToIndex(int index)
QGraphicsLineItem* GameBoardScene::lineFromIndex(int index)
{
int index2 = index % ((2*width) + 1);
enum{HORZONTAL, VERTICAL} dir;
enum{HORIZONTAL, VERTICAL} dir;
if(index2 < width)
dir = HORZONTAL;
dir = HORIZONTAL;
else
dir = VERTICAL;
......@@ -184,7 +185,7 @@ QGraphicsLineItem* GameBoardScene::lineFromIndex(int index)
int xCoordEnd = 0;
switch(dir)
{
case HORZONTAL:
case HORIZONTAL:
xCoordStart = index2 * spacing;
yCoordEnd = yCoordStart;
xCoordEnd = xCoordStart + spacing;
......@@ -200,6 +201,7 @@ QGraphicsLineItem* GameBoardScene::lineFromIndex(int index)
void GameBoardScene::checkForNewSquares()
{
//kDebug() << "void GameBoardScene::checkForNewSquares()" << endl;
for(int i=0; i < (width*height); i++) //cycle through every box..
{
if (squareOwnerTable.at(i) == -1) //..checking it if there is no current owner
......
......@@ -24,6 +24,9 @@ class GameBoardScene : public QGraphicsScene
QVector<int> squareOwners() const {return squareOwnerTable;}
QVector<bool> lines() const {return lineDrawn;}
bool addLineToIndex(int index);
int boardWidth() const {return width;}
int boardHeight() const {return height;}
public slots:
void setSquareOwner(int squareIndex, int owner);
void drawSquare(int index);
......
......@@ -20,6 +20,7 @@
#include <kstandardaction.h>
#include <kstandardgameaction.h>
#include <kdebug.h>
#include <klocale.h>
//generated
#include "settings.h"
......@@ -36,7 +37,7 @@ KSquares::KSquares() : KMainWindow(), m_view(new GameBoardView(this))
{
sGame = new KSquaresGame();
//connect(m_view, SIGNAL(gameStarted()), sGame, SLOT(startGame()));
connect(sGame, SIGNAL(playerChangedSig(KSquaresPlayer*)), this, SLOT(playerChanged(KSquaresPlayer*)));
connect(sGame, SIGNAL(takeTurnSig(KSquaresPlayer*)), this, SLOT(playerTakeTurn(KSquaresPlayer*)));
setCentralWidget(m_view);
setupActions();
statusBar()->insertPermanentItem(i18n("Current Player"), 0);
......@@ -68,19 +69,34 @@ void KSquares::gameNew()
{
//load settings
NewGameDialog dialog(this);
//create indexed arrays of the widgets
QList<QLineEdit*> nameLineEditList;
nameLineEditList.append(dialog.playerOneName);
nameLineEditList.append(dialog.playerTwoName);
nameLineEditList.append(dialog.playerThreeName);
nameLineEditList.append(dialog.playerFourName);
QList<QCheckBox*> humanCheckBoxList;
humanCheckBoxList.append(dialog.playerOneHuman);
humanCheckBoxList.append(dialog.playerTwoHuman);
humanCheckBoxList.append(dialog.playerThreeHuman);
humanCheckBoxList.append(dialog.playerFourHuman);
//get settings from file
for(int i=0; i<=3; i++)
{
nameLineEditList.at(i)->setText(Settings::playerNames().at(i));
}
for(int i=0; i<=3; i++)
{
if (Settings::humanList().at(i) == 2)
humanCheckBoxList.at(i)->setCheckState(Qt::Checked);
else
humanCheckBoxList.at(i)->setCheckState(Qt::Unchecked);
}
dialog.spinNumOfPlayers->setValue(Settings::numOfPlayers());
dialog.playerOneName->setText(Settings::playerNames().at(0));
dialog.playerTwoName->setText(Settings::playerNames().at(1));
dialog.spinHeight->setValue(Settings::boardHeight());
dialog.spinWidth->setValue(Settings::boardWidth());
if (Settings::humanList().at(0) == 2)
dialog.playerOneHuman->setCheckState(Qt::Checked);
else
dialog.playerOneHuman->setCheckState(Qt::Unchecked);
if (Settings::humanList().at(1) == 2)
dialog.playerTwoHuman->setCheckState(Qt::Checked);
else
dialog.playerTwoHuman->setCheckState(Qt::Unchecked);
//run dialog
dialog.exec();
......@@ -91,13 +107,17 @@ void KSquares::gameNew()
Settings::setNumOfPlayers(dialog.spinNumOfPlayers->value());
QStringList tempNames;
tempNames.append(dialog.playerOneName->text());
tempNames.append(dialog.playerTwoName->text());
for(int i=0; i<=3; i++)
{
tempNames.append(nameLineEditList.at(i)->text());
}
Settings::setPlayerNames(tempNames);
QList<int> tempHuman;
tempHuman.append(dialog.playerOneHuman->checkState());
tempHuman.append(dialog.playerTwoHuman->checkState());
for(int i=0; i<=3; i++)
{
tempHuman.append(humanCheckBoxList.at(i)->checkState());
}
Settings::setHumanList(tempHuman);
Settings::setBoardHeight(dialog.spinHeight->value());
......@@ -106,27 +126,9 @@ void KSquares::gameNew()
//create players
QVector<KSquaresPlayer> playerList;
switch(dialog.playerOneHuman->checkState())
{
case 0:
playerList.append(KSquaresPlayer(dialog.playerOneName->text(), false));
break;
case 2:
playerList.append(KSquaresPlayer(dialog.playerOneName->text(), true));
break;
default:
break;
}
switch(dialog.playerTwoHuman->checkState())
for(int i=0; i<dialog.spinNumOfPlayers->value(); i++)
{
case 0:
playerList.append(KSquaresPlayer(dialog.playerTwoName->text(), false));
break;
case 2:
playerList.append(KSquaresPlayer(dialog.playerTwoName->text(), true));
break;
default:
break;
playerList.append(KSquaresPlayer(nameLineEditList.at(i)->text(), humanCheckBoxList.at(i)->isChecked()));
}
//create physical board
......@@ -152,8 +154,8 @@ void KSquares::gameOver(QVector<KSquaresPlayer> playerList)
QStandardItemModel* scoreTableModel = new QStandardItemModel();
scoreTableModel->setRowCount(playerList.size());
scoreTableModel->setColumnCount(2);
scoreTableModel->setHeaderData(0, Qt::Horizontal, "Player Name");
scoreTableModel->setHeaderData(1, Qt::Horizontal, "Score");
scoreTableModel->setHeaderData(0, Qt::Horizontal, i18n("Player Name"));
scoreTableModel->setHeaderData(1, Qt::Horizontal, i18n("Score"));
for(int i = 0; i < playerList.size(); i++)
{
......@@ -185,8 +187,9 @@ void KSquares::optionsPreferences()
dialog->show();
}
void KSquares::playerChanged(KSquaresPlayer* currentPlayer)
void KSquares::playerTakeTurn(KSquaresPlayer* currentPlayer)
{
//kDebug() << "void KSquares::playerTakeTurn(KSquaresPlayer* currentPlayer)" << endl;
statusBar()->changeItem(currentPlayer->name(), 0);
if(currentPlayer->isHuman())
{
......@@ -202,9 +205,9 @@ void KSquares::playerChanged(KSquaresPlayer* currentPlayer)
if(m_view->isEnabled())
m_view->setEnabled(false);
aiController ai(sGame->currentPlayerId());
ai.setLines(m_view->scene()->lines());
ai.setSquareOwners(m_view->scene()->squareOwners());
aiController ai(sGame->currentPlayerId(), m_view->scene()->lines(), m_view->scene()->squareOwners(), m_view->scene()->boardWidth(), m_view->scene()->boardHeight());
/*ai.setLines(m_view->scene()->lines());
ai.setSquareOwners(m_view->scene()->squareOwners());*/
m_view->scene()->addLineToIndex(ai.drawLine());
}
}
......
......@@ -34,7 +34,7 @@ class KSquares : public KMainWindow
private slots:
void gameNew();
void optionsPreferences();
void playerChanged(KSquaresPlayer* currentPlayer);
void playerTakeTurn(KSquaresPlayer* currentPlayer);
void gameOver(QVector<KSquaresPlayer> playerList); //when KSquaresGame says the game is over. Display score board
private:
......
......@@ -12,11 +12,11 @@ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
</entry>
<entry name="PlayerNames" type="StringList">
<label>Player Names</label>
<default>Player 1,Player 2</default>
<default>Player 1,Player 2,Player 3,Player 4</default>
</entry>
<entry name="HumanList" type="IntList">
<label>Human or AI</label>
<default>1,1</default>
<default>2,2,2,2</default>
</entry>
<entry name="BoardWidth" type="Int">
<label>Width of board</label>
......
......@@ -14,11 +14,13 @@
KSquaresGame::KSquaresGame()
{
kDebug() << "Constructing Game" << endl;
gameInProgress = false;
}
KSquaresGame::~KSquaresGame()
{
kDebug() << "Destroying game" << endl;
gameInProgress = false;
}
void KSquaresGame::createGame(QVector<KSquaresPlayer> startPlayers, int startWidth, int startHeight)
......@@ -32,6 +34,7 @@ void KSquaresGame::createGame(QVector<KSquaresPlayer> startPlayers, int startWid
{
players.append(startPlayers[i]); //???
}
gameInProgress = false;
//points.resize(0);
//points.fill(0, players.size());
}
......@@ -39,6 +42,7 @@ void KSquaresGame::createGame(QVector<KSquaresPlayer> startPlayers, int startWid
void KSquaresGame::startGame()
{
kDebug() << "Game Starting" << endl;
gameInProgress = true;
nextPlayer();
}
......@@ -46,15 +50,15 @@ int KSquaresGame::nextPlayer()
{
anotherGo = false; //just to reset the variable
currentPlayerId() >= (players.size()-1) ? i_currentPlayerId = 0 : i_currentPlayerId++;
kDebug() << "- Moving to next player: " << currentPlayer()->name() << "(" << currentPlayerId() << ")" << endl;
emit playerChangedSig(currentPlayer());
kDebug() << endl << "- Moving to next player: " << currentPlayer()->name() << "(" << currentPlayerId() << ")" << endl;
emit takeTurnSig(currentPlayer());
return currentPlayerId();
}
void KSquaresGame::playerSquareComplete(int index)
{
kDebug() << "- - " << currentPlayer()->name() << "(" << currentPlayerId() << ") has completed a square" << endl;
//kDebug() << "- - " << currentPlayer()->name() << "(" << currentPlayerId() << ") has completed a square" << endl;
anotherGo = true;
emit setSquareOwnerSig(index, currentPlayerId());
//points[currentPlayer()-1]++;
......@@ -70,6 +74,7 @@ void KSquaresGame::playerSquareComplete(int index)
if (totalPoints >= width*height) //if the board is full
{
kDebug() << "Game Over" << endl;
gameInProgress = false;
emit gameOverSig(players);
//endGame();
}
......@@ -78,16 +83,19 @@ void KSquaresGame::playerSquareComplete(int index)
void KSquaresGame::tryEndGo()
{
kDebug() << "- - Line placed, trying to end go" << endl;
if (not anotherGo)
if (anotherGo)
{
kDebug() << "- - - Go ending" << endl;
nextPlayer();
return;
if(gameInProgress)
{
kDebug() << "- - - Having another go" << endl;
anotherGo = false;
emit takeTurnSig(currentPlayer());
}
}
else
{
kDebug() << "- - - Having another go" << endl;
anotherGo = false;
kDebug() << "- - - Go ending" << endl;
nextPlayer();
}
}
......@@ -100,6 +108,7 @@ void KSquaresGame::endGame()
height = 0;
i_currentPlayerId = -1;
anotherGo = false;
gameInProgress = false;
}
#include "ksquaresgame.moc"
......@@ -44,10 +44,11 @@ class KSquaresGame : public QObject
int width;
int height;
QVector<KSquaresPlayer> players;
bool gameInProgress;
signals:
void setSquareOwnerSig(int,int);
void playerChangedSig(KSquaresPlayer*); //emit the new curent player
void takeTurnSig(KSquaresPlayer*); //emit the new curent player
void gameOverSig(QVector<KSquaresPlayer>);
void aiStartGo(int); //int = player ID
void aiEndGo(int);
......
......@@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>368</width>
<height>273</height>
<height>333</height>
</rect>
</property>
<property name="windowTitle" >
......@@ -22,6 +22,19 @@
<property name="spacing" >
<number>6</number>
</property>
<item row="2" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>350</width>
<height>51</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" >
<widget class="QGroupBox" name="groupBox_2" >
<property name="whatsThis" >
......@@ -129,8 +142,37 @@ p, li { white-space: pre-wrap; }
<property name="spacing" >
<number>6</number>
</property>
<item row="2" column="2" >
<widget class="QCheckBox" name="playerTwoHuman" >
<item row="4" column="0" >
<widget class="QLabel" name="labelPlayer4Name" >
<property name="whatsThis" >
<string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
p, li { white-space: pre-wrap; }
&lt;/style>&lt;/head>&lt;body style=" font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:Sans;">The name of the second player&lt;/p>&lt;/body>&lt;/html></string>
</property>
<property name="text" >
<string>Player 4:</string>
</property>
<property name="buddy" >
<cstring>playerFourName</cstring>
</property>
</widget>
</item>
<item row="4" column="2" >
<widget class="QCheckBox" name="playerFourHuman" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="text" >
<string>Human?</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2" >
<widget class="QCheckBox" name="playerThreeHuman" >
<property name="enabled" >
<bool>true</bool>
</property>
......@@ -142,27 +184,80 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="3" column="0" >
<widget class="QLabel" name="labelPlayer3Name" >
<property name="whatsThis" >
<string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
p, li { white-space: pre-wrap; }
&lt;/style>&lt;/head>&lt;body style=" font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The name of the first player&lt;/p>&lt;/body>&lt;/html></string>
</property>
<property name="text" >
<string>Player 3:</string>
</property>
<property name="buddy" >
<cstring>playerThreeName</cstring>