This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats-gameserv/ttt.c
2006-01-26 15:33:00 +00:00

219 lines
5.6 KiB
C

/* GamesServ - Small Games Service - NeoStats Addon Module
** Copyright (c) 2006 Justin Hammond, Mark Hetherington, DeadNotBuried
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
** USA
**
** GamesServ CVS Identification
** $Id$
*/
#include "neostats.h" /* Required for bot support */
#include "gamesserv.h"
static int CheckTTTWinner(Client *u, UserGameData *ugd, TicTacToe *tttd);
static void gsturn(Client *u, UserGameData *ugd, TicTacToe *tttd);
/*
* Start Tic Tac Toe Game
*/
int startttt(const CmdParams *cmdparams) {
UserGameData *ugd;
TicTacToe *tttd;
int x, y;
if (CheckUserGameStart(cmdparams->source) != NS_SUCCESS) {
return NS_SUCCESS;
}
ugd = ns_calloc(sizeof(UserGameData));
tttd = ns_calloc(sizeof(TicTacToe));
ugd->gametype = GS_GAME_USER_TICTACTOE;
ugd->gamedata = (char *)tttd;
tttd->turnnum = 0;
for ( x = 0 ; x < 3 ; x++ ) {
for ( y = 0 ; y < 3 ; y++ ) {
tttd->grid[x][y] = '?';
}
}
SetUserModValue(cmdparams->source, ugd);
irc_prefmsg (gs_bot, cmdparams->source, "Tic Tac Toe has started.");
switch (rand()%2) {
case 1:
irc_prefmsg (gs_bot, cmdparams->source, "You get the first turn.");
break;
default:
gsturn(cmdparams->source, ugd, tttd);
break;
}
return NS_SUCCESS;
}
/*
* mark position
*/
int playttt(const CmdParams *cmdparams) {
UserGameData *ugd;
TicTacToe *tttd;
int x, y;
ugd = (UserGameData *)GetUserModValue(cmdparams->source);
if (!ugd) {
return NS_SUCCESS;
}
if (ugd->gametype != GS_GAME_USER_TICTACTOE) {
return NS_SUCCESS;
}
tttd = (TicTacToe *)ugd->gamedata;
if (!tttd) {
return NS_SUCCESS;
}
if (cmdparams->ac != 2) {
irc_prefmsg (gs_bot, cmdparams->source, "Invalid Position.");
return NS_SUCCESS;
}
x = atoi(cmdparams->av[0]);
y = atoi(cmdparams->av[1]);
if ( x < 1 || x > 3 || y < 1 || y > 3 ) {
irc_prefmsg (gs_bot, cmdparams->source, "Invalid Position.");
return NS_SUCCESS;
}
if (tttd->grid[(x-1)][(y-1)] != '?') {
if (tttd->grid[(x-1)][(y-1)] == 'O') {
irc_prefmsg (gs_bot, cmdparams->source, "I have already marked that position.");
} else if (tttd->grid[(x-1)][(y-1)] == 'X') {
irc_prefmsg (gs_bot, cmdparams->source, "You have already marked that position.");
}
return NS_SUCCESS;
}
tttd->grid[(x-1)][(y-1)] = 'X';
tttd->turnnum++;
if (CheckTTTWinner(cmdparams->source, ugd, tttd) != NS_SUCCESS) {
gsturn(cmdparams->source, ugd, tttd);
}
return NS_SUCCESS;
}
/*
* GamesServ Turn
*/
static void gsturn(Client *u, UserGameData *ugd, TicTacToe *tttd) {
int i, i2, x, y;
if (!ugd || ! tttd) {
return;
}
if (ugd->gametype != GS_GAME_USER_TICTACTOE) {
return;
}
/*
* TODO: Get a decent system for picking pseudo clients turn
* currently just selects a random position
*/
i = ((rand() % (9 - tttd->turnnum)) + 1);
i2 = 0;
for ( x = 0 ; x < 3 ; x++ ) {
for ( y = 0 ; y < 3 ; y++ ) {
if (tttd->grid[x][y] == '?') {
i2++;
}
if (i == i2) {
break;
}
}
if (i == i2) {
break;
}
}
tttd->grid[x][y] = 'O';
irc_prefmsg (gs_bot, u, "Game Board:");
for ( i = 0 ; i < 3 ; i++ ) {
irc_prefmsg (gs_bot, u, " %s | %s | %s", ( tttd->grid[0][i] == 'X' ) ? "X" : ( tttd->grid[0][i] == 'O' ) ? "O" : "-", ( tttd->grid[1][i] == 'X' ) ? "X" : ( tttd->grid[1][i] == 'O' ) ? "O" : "-", ( tttd->grid[2][i] == 'X' ) ? "X" : ( tttd->grid[2][i] == 'O' ) ? "O" : "-");
if (i < 2) {
irc_prefmsg (gs_bot, u, " ---|---|---");
}
}
tttd->turnnum++;
CheckTTTWinner(u, ugd, tttd);
return;
}
/*
* Check for Tic Tac Toe Winner
*
* returns NS_SUCCESS for game over, else NS_FAILURE
*/
static int CheckTTTWinner(Client *u, UserGameData *ugd, TicTacToe *tttd) {
int i, w;
if (!ugd || !tttd) {
return NS_FAILURE;
}
if (ugd->gametype != GS_GAME_USER_TICTACTOE) {
return NS_FAILURE;
}
w = 0;
for ( i = 0 ; i < 3 ; i++ ) {
if (!w && tttd->grid[i][0] == tttd->grid[i][1] && tttd->grid[i][0] == tttd->grid[i][2]) {
if (tttd->grid[i][0] == 'O') {
w = 1;
} else if (tttd->grid[i][0] == 'X') {
w = 2;
}
}
}
if (!w) {
for ( i = 0 ; i < 3 ; i++ ) {
if (!w && tttd->grid[0][i] == tttd->grid[1][i] && tttd->grid[0][i] == tttd->grid[2][i]) {
if (tttd->grid[i][0] == 'O') {
w = 1;
} else if (tttd->grid[i][0] == 'X') {
w = 2;
}
}
}
}
if (!w && tttd->grid[0][0] == tttd->grid[1][1] && tttd->grid[0][0] == tttd->grid[2][2]) {
if (tttd->grid[0][0] == 'O') {
w = 1;
} else if (tttd->grid[0][0] == 'X') {
w = 2;
}
}
if (!w && tttd->grid[2][0] == tttd->grid[1][1] && tttd->grid[2][0] == tttd->grid[0][2]) {
if (tttd->grid[2][0] == 'O') {
w = 1;
} else if (tttd->grid[2][0] == 'X') {
w = 2;
}
}
switch (w) {
case 1:
irc_prefmsg (gs_bot, u, "Looks like I win yet again :)");
stopug(u);
return NS_SUCCESS;
case 2:
irc_prefmsg (gs_bot, u, "You only won because I am having a bad day.");
stopug(u);
return NS_SUCCESS;
default:
break;
}
if (tttd->turnnum >= 8) {
irc_prefmsg (gs_bot, u, "Looks like another Draw (Game Over)");
stopug(u);
return NS_SUCCESS;
}
return NS_FAILURE;
}