/***** All content © 2010 DigiPen (USA) Corporation, all rights reserved. ****/
/*! \file TicTacToe.c
** \author Nathan Williams
** \par email: nwilliam\@digipen.edu
** \date 04/10/2010
** \brief Implementation of Tic-Tac-Toe.
*
* Game Rules: Standard gameplay, 3x3 board with Xs and Os.
*
* Board: 0 | 1 | 2
* -------------
* 3 | 4 | 5
* -------------
* 6 | 7 | 8
*
* Move String: [int]
* Represents board position being played.
*******************************************************************************/
#include <string.h> /* strlen */
#include <stdlib.h> /* calloc, free */
#include "PluginCommon.h"
#include "PluginInterface.h"
#include "TicTacToe.h"
int Init(void)
{
/* Nothing to do */
return 0;
}
void Shutdown(void)
{
}
const char* Name(void)
{
return "Tic-Tac-Toe";
}
const char* Author(void)
{
return "nlw";
}
const char* Type(void)
{
return "TicTacToe";
}
const char* Version(void)
{
return "0.1";
}
const char* APIVersion(void)
{
return "0.1";
}
int NumberOfPlayers(void)
{
return 2;
}
void* CreateGame(void)
{
struct Game* newGame = (struct Game *)calloc(1, sizeof(struct Game));
if(newGame)
newGame->status = PLUGIN_GAME_STATUS_CREATED;
return newGame;
}
int SetGameOption(void* igame, const char* option)
{
/* No options for this game */
(void)igame;
(void)option;
return 1;
}
int AddPlayer(void* igame, void* player)
{
struct Game* game = (struct Game *)igame;
if(game->players[0] == NULL)
game->players[0] = player;
else if(game->players[1] == NULL)
game->players[1] = player;
else
return 1;
return 0;
}
int RemovePlayer(void* igame, void* player)
{
struct Game* game = (struct Game *)igame;
if(game->players[0] == player)
game->players[0] = NULL;
else if(game->players[1] == player)
game->players[1] = NULL;
else
return 1;
if(game->status == PLUGIN_GAME_STATUS_PLAYING)
game->status = PLUGIN_GAME_STATUS_PAUSED;
return 0;
}
int PlayerCount(void* igame)
{
struct Game* game = (struct Game *)igame;
return (game->players[0] != 0) + (game->players[1] != 0);
}
void* GetPlayer(void* igame, int playerNumber)
{
struct Game* game = (struct Game *)igame;
if(playerNumber == 1 || playerNumber == 2)
return game->players[playerNumber-1];
return NULL;
}
int GetPlayerNumber(void* igame, void* player)
{
struct Game* game = (struct Game *)igame;
if(game->players[0] == player)
return 1;
if(game->players[1] == player)
return 2;
return 0;
}
int StartGame(void* igame)
{
struct Game* game = (struct Game *)igame;
if(PlayerCount(game) != 2)
return 1;
game->nextPlayer = 1;
game->status = PLUGIN_GAME_STATUS_PLAYING;
return 0;
}
void* GetNextPlayer(void* igame)
{
struct Game* game = (struct Game *)igame;
if(game->nextPlayer > 0)
return game->players[game->nextPlayer-1];
return NULL;
}
int ValidateMove(void* igame, void* player, const char* move)
{
struct Game* game = (struct Game *)igame;
char* board = game->board;
int i, movePos;
int wins[8][3] = { {0,1,2}, {3,4,5}, {6,7,8}, /* Horizontal */
{0,3,6}, {1,4,7}, {2,5,8}, /* Vertical */
{0,4,8}, {2,4,6} }; /* Diagonal */
/* Sanity check */
if(move == NULL || strlen(move) != 1 || game->status != PLUGIN_GAME_STATUS_PLAYING)
return -1;
movePos = move[0] - '0';
/* Check out of range or already played */
if(movePos < 0 || movePos > 8 || board[movePos] != 0)
return -1;
if(game->players[0] == player)
{
board[movePos] = 'X';
game->nextPlayer = 2;
}
else
{
board[movePos] = 'O';
game->nextPlayer = 1;
}
/* Check for winner or draw */
for(i = 0; i < 8; ++i)
{
if(board[wins[i][0]] == board[wins[i][1]] &&
board[wins[i][0]] == board[wins[i][2]] &&
board[wins[i][0]] != 0)
{
game->nextPlayer = GetPlayerNumber(igame, player);
game->status = PLUGIN_GAME_STATUS_OVER_WINNER;
return 0;
}
}
/* Check for draw */
if(board[0] && board[1] && board[2] && board[3] && board[4] &&
board[5] && board[6] && board[7] && board[8])
{
game->nextPlayer = 0;
game->status = PLUGIN_GAME_STATUS_OVER_DRAW;
}
return 0;
}
int GetGameStatus(void* igame)
{
struct Game* game = (struct Game *)igame;
return game->status;
}
void DestroyGame(void* igame)
{
free(igame);
}