From eb2aab55a1f97b329c0409d32d35d1f112facedb Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 22 Mar 2012 17:11:25 +0100 Subject: [PATCH] added 4wins game --- Makefile.am | 4 + src/modules/NeonFun.mod/bot_NeonFun.c | 41 ++++ src/modules/NeonFun.mod/bot_NeonFun.h | 2 + src/modules/NeonFun.mod/cmd_neonfun.c | 26 +++ src/modules/NeonFun.mod/cmd_neonfun.h | 4 + src/modules/NeonFun.mod/cmd_neonfun_4stone.c | 107 ++++++++++ src/modules/NeonFun.mod/cmd_neonfun_4view.c | 57 +++++ src/modules/NeonFun.mod/cmd_neonfun_4wins.c | 93 ++++++++ src/modules/NeonFun.mod/game_4wins.c | 212 +++++++++++++++++++ src/modules/NeonFun.mod/game_4wins.h | 63 ++++++ src/modules/NeonFun.mod/game_uno.c | 1 + 11 files changed, 610 insertions(+) create mode 100644 src/modules/NeonFun.mod/cmd_neonfun_4stone.c create mode 100644 src/modules/NeonFun.mod/cmd_neonfun_4view.c create mode 100644 src/modules/NeonFun.mod/cmd_neonfun_4wins.c create mode 100644 src/modules/NeonFun.mod/game_4wins.c create mode 100644 src/modules/NeonFun.mod/game_4wins.h diff --git a/Makefile.am b/Makefile.am index aba1bf4..6daebad 100644 --- a/Makefile.am +++ b/Makefile.am @@ -155,6 +155,10 @@ libNeonFun_la_SOURCES = src/modules/NeonFun.mod/bot_NeonFun.c \ src/modules/NeonFun.mod/cmd_neonfun_unoplay.c \ src/modules/NeonFun.mod/cmd_neonfun_unotake.c \ src/modules/NeonFun.mod/game_uno.c \ + src/modules/NeonFun.mod/cmd_neonfun_4wins.c \ + src/modules/NeonFun.mod/cmd_neonfun_4stone.c \ + src/modules/NeonFun.mod/cmd_neonfun_4view.c \ + src/modules/NeonFun.mod/game_4wins.c \ src/modules/NeonFun.mod/module.c libNeonFun_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined libNeonFun_la_LIBADD = $(MYSQL_LIBS) diff --git a/src/modules/NeonFun.mod/bot_NeonFun.c b/src/modules/NeonFun.mod/bot_NeonFun.c index f203f91..ebb0cc5 100644 --- a/src/modules/NeonFun.mod/bot_NeonFun.c +++ b/src/modules/NeonFun.mod/bot_NeonFun.c @@ -38,6 +38,7 @@ #include "../../EventLogger.h" #include "../../bots.h" #include "game_uno.h" +#include "game_4wins.h" #define BOTID NEONFUN_BOTID #define BOTALIAS "NeonFun" @@ -123,14 +124,17 @@ static void start_bots(int type) { static void neonfun_parted(struct ChanUser *chanuser, char *reason) { uno_event_part(chanuser); + fourwins_event_part(chanuser); } static void neonfun_quitted(struct UserNode *user, char *reason) { uno_event_quit(user); + fourwins_event_quit(user); } static int neonfun_freechan(struct ChanNode *chan) { uno_event_freechan(chan); + fourwins_event_freechan(chan); return 0; } @@ -232,5 +236,42 @@ void uno_reply(struct uno_game *game, struct UserNode *user, const char *text, . write_socket(client, sendBuf, pos+1); } +void fourwins_reply(struct fourwins_game *game, const char *text, ...) { + struct ClientSocket *client = game->textbot; + struct fourwins_guest *guest; + int guest_count = 0; + for(guest = game->guests; guest; guest = guest->next) { + guest_count++; + } + struct ChanUser *chanusers[guest_count + 2]; + chanusers[0] = game->player[0]; + chanusers[1] = game->player[1]; + guest_count = 0; + for(guest = game->guests; guest; guest = guest->next) { + chanusers[2 + (guest_count++)] = guest->chanuser; + } + int i; + guest_count += 2; + for(i = 0; i < guest_count; i++) { + const char *reply_format = get_language_string(chanusers[i]->user, text); + if(reply_format == NULL) + reply_format = text; + char formatBuf[MAXLEN]; + sprintf(formatBuf, "NOTICE %s :[4WINS] %s", chanusers[i]->user->nick, reply_format); + va_list arg_list; + char sendBuf[MAXLEN]; + int pos; + if (!(client->flags & SOCKET_FLAG_CONNECTED)) return; + sendBuf[0] = '\0'; + va_start(arg_list, text); + pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list); + va_end(arg_list); + if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2; + sendBuf[pos] = '\n'; + sendBuf[pos+1] = '\0'; + write_socket(client, sendBuf, pos+1); + } +} + #undef BOTID #undef BOTALIAS diff --git a/src/modules/NeonFun.mod/bot_NeonFun.h b/src/modules/NeonFun.mod/bot_NeonFun.h index 6e0e0f6..c2102e7 100644 --- a/src/modules/NeonFun.mod/bot_NeonFun.h +++ b/src/modules/NeonFun.mod/bot_NeonFun.h @@ -24,11 +24,13 @@ void loop_NeonFun(); void free_NeonFun(int type); struct uno_game; +struct fourwins_game; struct ChanNode; struct UserNode; char* getSetting(struct UserNode *user, struct ChanNode *chan, const char *setting); void setSetting(struct UserNode *user, struct ChanNode *chan, const char *setting, const char *value); void uno_reply(struct uno_game *game, struct UserNode *user, const char *text, ...); +void fourwins_reply(struct fourwins_game *game, const char *text, ...); #endif \ No newline at end of file diff --git a/src/modules/NeonFun.mod/cmd_neonfun.c b/src/modules/NeonFun.mod/cmd_neonfun.c index 4f659c9..1957498 100644 --- a/src/modules/NeonFun.mod/cmd_neonfun.c +++ b/src/modules/NeonFun.mod/cmd_neonfun.c @@ -48,6 +48,28 @@ static const struct default_language_entry msgtab[] = { {"NF_UNO_USER_SKIP", "skipped $b%s$b."}, /* {ARGS: "TestUser"} */ {"NF_UNO_GAME_FINISHED", "The UNO Game has been finished!"}, {"NF_UNO_ADD_CARD", "$b%s$b has to take up %d cards. There is still the possibility that he/she has another card of this type...?"}, + {"NF_UNO_RANK", "Rank"}, + {"NF_UNO_NAME", "Name"}, + {"NF_UNO_WON_GAMES", "Won Games"}, + {"NF_UNO_TOTAL_WON_GAMES", "Total won Games"}, + + {"NF_4WINS_NOT_YOUR_TURN", "Wait your turn!"}, + {"NF_4WINS_INVALID_COLUMN", "invalid column!"}, + {"NF_4WINS_COLUMN_FULL", "This column is full!"}, + {"NF_4WINS_USER_HURRY_UP", "$b%s$b, it's your turn! To put a stone into a column use: 4stone "}, /* {ARGS: "TestUser"} */ + {"NF_4WINS_USER_WON", "$b%s$b won the game!"}, /* {ARGS: "TestUser"} */ + {"NF_4WINS_ENTER_OPPONENT", "Please enter the nick of the opponent you want to play against as a parameter of 4wins (eg. $b4wins TestUser$b)"}, + {"NF_4WINS_OPPONENT_NOT_IN_CHAN", "$b%s$b needs to be in this channel to start a game against him/her."}, /* {ARGS: "TestUser"} */ + {"NF_4WINS_DRAW", "Noone has won this game."}, + {"NF_4WINS_REQUEST", "$b%s$b wants to play a game against you. use $b4wins$b to start the game."}, /* {ARGS: "TestUser"} */ + {"NF_4WINS_REQUESTED", "waiting for $b%s$b accepting the game..."}, /* {ARGS: "TestUser"} */ + {"NF_4WINS_START", "%s accepted the challenge! game starts:"}, /* {ARGS: "TestUser"} */ + {"NF_4WINS_APPEND_PLAYER", "Please append the nick of a player playing the game you want to view. (eg. $b4view TestUser$b)"}, + {"NF_4WINS_NO_GAME_FOUND", "Couldn't find a game with this user in this channel."}, + {"NF_4WINS_VIEWING_ANOTHER_GAME", "You are already viewing another game."}, + {"NF_4WINS_VIEWING_GAME", "You are now viewing the game."}, + {"NF_4WINS_GAME_CLOSED", "Game aborted."}, + {"NF_4WINS_TIMEOUT", "Game aborted (timeout)."}, {NULL, NULL} }; @@ -62,6 +84,10 @@ void register_commands() { USER_COMMAND("unotake", neonfun_cmd_unotake, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN); USER_COMMAND("unoplay", neonfun_cmd_unoplay, 1, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN); + USER_COMMAND("4wins", neonfun_cmd_4wins, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN); + USER_COMMAND("4stone", neonfun_cmd_4stone, 1, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN); + USER_COMMAND("4view", neonfun_cmd_4view, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN); + #undef USER_COMMAND } diff --git a/src/modules/NeonFun.mod/cmd_neonfun.h b/src/modules/NeonFun.mod/cmd_neonfun.h index a97da59..93963da 100644 --- a/src/modules/NeonFun.mod/cmd_neonfun.h +++ b/src/modules/NeonFun.mod/cmd_neonfun.h @@ -46,4 +46,8 @@ CMD_BIND(neonfun_cmd_uno); CMD_BIND(neonfun_cmd_unotake); CMD_BIND(neonfun_cmd_unoplay); +CMD_BIND(neonfun_cmd_4wins); +CMD_BIND(neonfun_cmd_4stone); +CMD_BIND(neonfun_cmd_4view); + #endif diff --git a/src/modules/NeonFun.mod/cmd_neonfun_4stone.c b/src/modules/NeonFun.mod/cmd_neonfun_4stone.c new file mode 100644 index 0000000..96fa091 --- /dev/null +++ b/src/modules/NeonFun.mod/cmd_neonfun_4stone.c @@ -0,0 +1,107 @@ +/* cmd_neonfun_4stone.c - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 3 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, see . + */ + +#include "cmd_neonfun.h" +#include "game_4wins.h" + +CMD_BIND(neonfun_cmd_4stone) { + struct ChanUser *chanuser = getChanUser(user, chan); + if(!chanuser) return; + struct fourwins_game *game; + for(game = fourwins_active_games; game; game = game->next) { + if(chanuser == game->player[0] || chanuser == game->player[1]) { + if(game->state == FOURWINS_STATE_WAITING) + return; + else + break; + } + } + if(game) { + //check if it's the player's turn + if(game->player[game->active_player] != chanuser) { + reply(getTextBot(), user, "NF_4WINS_NOT_YOUR_TURN"); + return; + } + int x = atoi(argv[0])-1; + if(x < 0 || x >= FOURWINS_MATRIX_WIDTH) { + reply(getTextBot(), user, "NF_4WINS_INVALID_COLUMN"); + return; + } + int y = fourwins_next_free_y(game, x); + if(y < 0) { + reply(getTextBot(), user, "NF_4WINS_COLUMN_FULL"); + return; + } + timeq_del(game->timer); + game->timer = NULL; + game->matrix[x][y].field = game->active_player+1; + fourwins_show_matrix(game); + if(fourwins_check_win(game, x, y)) { + fourwins_reply(game, "NF_4WINS_USER_WON", game->player[game->active_player]->user->nick); + if((game->player[game->active_player]->user->flags & USERFLAG_ISAUTHED)) { + char *tmp; + int win_count = ((tmp = getSetting(game->player[game->active_player]->user, chan, "4wins_win")) ? atoi(tmp) : 0); + int total_win_count = ((tmp = getSetting(game->player[game->active_player]->user, NULL, "4wins_win")) ? atoi(tmp) : 0); + win_count++; + total_win_count++; + char buf[10]; + sprintf(buf, "%d", win_count); + setSetting(game->player[game->active_player]->user, chan, "4wins_win", buf); + sprintf(buf, "%d", total_win_count); + setSetting(game->player[game->active_player]->user, NULL, "4wins_win", buf); + } + fourwins_free_game(game); + } else { + game->total_stones++; + if(game->total_stones == FOURWINS_MAX_STONES) { + fourwins_reply(game, "NF_4WINS_DRAW"); + if((game->player[0]->user->flags & USERFLAG_ISAUTHED)) { + char *tmp; + int win_count = ((tmp = getSetting(game->player[0]->user, chan, "4wins_draw")) ? atoi(tmp) : 0); + int total_win_count = ((tmp = getSetting(game->player[0]->user, NULL, "4wins_draw")) ? atoi(tmp) : 0); + win_count++; + total_win_count++; + char buf[10]; + sprintf(buf, "%d", win_count); + setSetting(game->player[0]->user, chan, "4wins_draw", buf); + sprintf(buf, "%d", total_win_count); + setSetting(game->player[0]->user, NULL, "4wins_draw", buf); + } + if((game->player[1]->user->flags & USERFLAG_ISAUTHED)) { + char *tmp; + int win_count = ((tmp = getSetting(game->player[1]->user, chan, "4wins_draw")) ? atoi(tmp) : 0); + int total_win_count = ((tmp = getSetting(game->player[1]->user, NULL, "4wins_draw")) ? atoi(tmp) : 0); + win_count++; + total_win_count++; + char buf[10]; + sprintf(buf, "%d", win_count); + setSetting(game->player[1]->user, chan, "4wins_draw", buf); + sprintf(buf, "%d", total_win_count); + setSetting(game->player[1]->user, NULL, "4wins_draw", buf); + } + fourwins_free_game(game); + return; + } + if(game->active_player) + game->active_player = 0; + else + game->active_player = 1; + fourwins_reply(game, "NF_4WINS_USER_HURRY_UP", game->player[game->active_player]->user->nick); + game->timer = timeq_add(120, module_id, fourwins_timeout, game); + } + } +} diff --git a/src/modules/NeonFun.mod/cmd_neonfun_4view.c b/src/modules/NeonFun.mod/cmd_neonfun_4view.c new file mode 100644 index 0000000..22aef65 --- /dev/null +++ b/src/modules/NeonFun.mod/cmd_neonfun_4view.c @@ -0,0 +1,57 @@ +/* cmd_neonfun_4view.c - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 3 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, see . + */ + +#include "cmd_neonfun.h" +#include "game_4wins.h" + +CMD_BIND(neonfun_cmd_4view) { + struct UserNode *gameuser; + struct ChanUser *chanuser; + if(!argc || !(gameuser = getUserByNick(argv[0])) || !(chanuser = getChanUser(gameuser, chan))) { + reply(getTextBot(), user, "NF_4WINS_APPEND_PLAYER"); + return; + } + struct fourwins_game *game, *fgame = NULL; + struct fourwins_guest *guest; + for(game = fourwins_active_games; game; game = game->next) { + for(guest = game->guests; guest; guest = guest->next) { + if(guest->chanuser->user == user) { + reply(getTextBot(), user, "NF_4WINS_VIEWING_ANOTHER_GAME"); + return; + } + } + if(game->player[0]->user == user || game->player[1]->user == user) { + reply(getTextBot(), user, "NF_4WINS_VIEWING_ANOTHER_GAME"); + return; + } + if(chanuser == game->player[0] || chanuser == game->player[1]) { + fgame = game; + } + } + game = fgame; + if(game) { + guest = malloc(sizeof(*guest)); + chanuser = getChanUser(user, chan); + if(!chanuser) return; + guest->chanuser = chanuser; + guest->next = game->guests; + game->guests = guest; + reply(getTextBot(), user, "NF_4WINS_VIEWING_GAME"); + } else { + reply(getTextBot(), user, "NF_4WINS_NO_GAME_FOUND"); + } +} diff --git a/src/modules/NeonFun.mod/cmd_neonfun_4wins.c b/src/modules/NeonFun.mod/cmd_neonfun_4wins.c new file mode 100644 index 0000000..a282a14 --- /dev/null +++ b/src/modules/NeonFun.mod/cmd_neonfun_4wins.c @@ -0,0 +1,93 @@ +/* cmd_neonfun_4wins.c - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 3 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, see . + */ + +#include "cmd_neonfun.h" +#include "game_4wins.h" + +CMD_BIND(neonfun_cmd_4wins) { + struct ChanUser *chanuser = getChanUser(user, chan); + if(!chanuser) return; + struct fourwins_game *game; + for(game = fourwins_active_games; game; game = game->next) { + if(chanuser == game->player[0]) { + return; + } else if(chanuser == game->player[1]) { + if(game->state == FOURWINS_STATE_WAITING) + break; + else + return; + } + } + if(game) { + timeq_del(game->timer); + game->timer = NULL; + game->state = FOURWINS_STATE_RUNNING; + fourwins_reply(game, "NF_4WINS_START", user->nick); + if((game->player[0]->user->flags & USERFLAG_ISAUTHED)) { + char *tmp; + int win_count = ((tmp = getSetting(game->player[0]->user, chan, "4wins_games")) ? atoi(tmp) : 0); + int total_win_count = ((tmp = getSetting(game->player[0]->user, NULL, "4wins_games")) ? atoi(tmp) : 0); + win_count++; + total_win_count++; + char buf[10]; + sprintf(buf, "%d", win_count); + setSetting(game->player[0]->user, chan, "4wins_games", buf); + sprintf(buf, "%d", total_win_count); + setSetting(game->player[0]->user, NULL, "4wins_games", buf); + } + if((game->player[1]->user->flags & USERFLAG_ISAUTHED)) { + char *tmp; + int win_count = ((tmp = getSetting(game->player[1]->user, chan, "4wins_games")) ? atoi(tmp) : 0); + int total_win_count = ((tmp = getSetting(game->player[1]->user, NULL, "4wins_games")) ? atoi(tmp) : 0); + win_count++; + total_win_count++; + char buf[10]; + sprintf(buf, "%d", win_count); + setSetting(game->player[1]->user, chan, "4wins_games", buf); + sprintf(buf, "%d", total_win_count); + setSetting(game->player[1]->user, NULL, "4wins_games", buf); + } + fourwins_show_matrix(game); + fourwins_reply(game, "NF_4WINS_USER_HURRY_UP", game->player[game->active_player]->user->nick); + game->timer = timeq_add(120, module_id, fourwins_timeout, game); + } else { + if(!argc) { + reply(getTextBot(), user, "NF_4WINS_ENTER_OPPONENT"); + return; + } + struct UserNode *opp_user = getUserByNick(argv[0]); + if(!opp_user) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + struct ChanUser *opponent = getChanUser(opp_user, chan); + if(!opponent) { + reply(getTextBot(), user, "NF_4WINS_OPPONENT_NOT_IN_CHAN", opp_user->nick); + return; + } + game = calloc(1,sizeof(*game)); + game->player[0] = chanuser; + game->player[1] = opponent; + game->textbot = getTextBot(); + game->state = FOURWINS_STATE_WAITING; + game->timer = timeq_add(120, module_id, fourwins_timeout, game); + game->next = fourwins_active_games; + fourwins_active_games = game; + reply(getTextBot(), user, "NF_4WINS_REQUESTED", opp_user->nick); + reply(getTextBot(), opp_user, "NF_4WINS_REQUEST", user->nick); + } +} diff --git a/src/modules/NeonFun.mod/game_4wins.c b/src/modules/NeonFun.mod/game_4wins.c new file mode 100644 index 0000000..88503a1 --- /dev/null +++ b/src/modules/NeonFun.mod/game_4wins.c @@ -0,0 +1,212 @@ +/* game_4wins.c - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 3 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, see . + */ +#include "../module.h" +#include "game_4wins.h" +#include "bot_NeonFun.h" +#include "../../IRCParser.h" +#include "../../bots.h" +#include "../../UserNode.h" +#include "../../ChanUser.h" +#include "../../tools.h" +#include "../botid.h" + +struct fourwins_game *fourwins_active_games = NULL; + +int fourwins_next_free_y(struct fourwins_game *game, int x) { + int y; + for(y = 0; y < FOURWINS_MATRIX_HEIGHT; y++) { + if(!game->matrix[x][y].field) + return y; + } + return -1; +} + +int fourwins_check_win(struct fourwins_game *game, int x, int y) { + int field = game->matrix[x][y].field; + if(!field) return 0; + //horizontal + { + int fc = 0; + int i; + for(i = x; i < FOURWINS_MATRIX_WIDTH; i++) { + if(game->matrix[i][y].field == field) + fc++; + else + break; + } + for(i = x-1; i >= 0; i--) { + if(game->matrix[i][y].field == field) + fc++; + else + break; + } + if(fc >= 4) return 1; + } + //senkrecht + if(y >= 3) { + int fc = 0; + int i; + for(i = y; i >= 0; i--) { + if(game->matrix[i][y].field == field) + fc++; + else + break; + } + if(fc >= 4) return 1; + } + //diagonal 1 + { + int fc = 0; + int ix, iy; + for(ix = x, iy = y; ix < FOURWINS_MATRIX_WIDTH && iy < FOURWINS_MATRIX_HEIGHT; ix++, iy++) { + if(game->matrix[ix][iy].field == field) + fc++; + else + break; + } + for(ix = x, iy = y; ix >= 0 && iy >= 0; ix--, iy--) { + if(game->matrix[ix][iy].field == field) + fc++; + else + break; + } + if(fc >= 4) return 1; + } + //diagonal 2 + { + int fc = 0; + int ix, iy; + for(ix = x, iy = y; ix < FOURWINS_MATRIX_WIDTH && iy >= 0; ix++, iy--) { + if(game->matrix[ix][iy].field == field) + fc++; + else + break; + } + for(ix = x, iy = y; ix >= 0 && iy < FOURWINS_MATRIX_HEIGHT; ix--, iy++) { + if(game->matrix[ix][iy].field == field) + fc++; + else + break; + } + if(fc >= 4) return 1; + } + return 0; +} + +void fourwins_show_matrix(struct fourwins_game *game) { + int x,y; + char lineBuf[MAXLEN]; + int linePos = 0; + for(x = 0; x < FOURWINS_MATRIX_WIDTH; x++) { + linePos += sprintf(lineBuf+linePos, (x ? "| %d " : " %d "), x+1); + } + fourwins_reply(game, lineBuf); + for(y = FOURWINS_MATRIX_HEIGHT-1; y >= 0; y--) { + linePos = 0; + for(x = 0; x < FOURWINS_MATRIX_WIDTH; x++) { + char *field = " "; + if(game->matrix[x][y].field == 1) + field = "\0034o\003"; + if(game->matrix[x][y].field == 2) + field = "\00312o\003"; + linePos += sprintf(lineBuf+linePos, (x ? " (%s)" : "(%s)"), field); + } + fourwins_reply(game, lineBuf); + } +} + +TIMEQ_CALLBACK(fourwins_timeout) { + struct fourwins_game *game = data; + game->timer = NULL; + fourwins_reply(game, "NF_4WINS_TIMEOUT"); + fourwins_free_game(game); +} + +void fourwins_free_game(struct fourwins_game *game) { + struct fourwins_guest *guest, *next_guest; + for(guest = game->guests; guest; guest = next_guest) { + next_guest = guest->next; + free(guest); + } + struct fourwins_game *cgame, *prev = NULL; + for(cgame = fourwins_active_games; cgame; cgame = cgame->next) { + if(cgame == game) { + if(prev) + prev->next = game->next; + else + fourwins_active_games->next = game->next; + } else + prev = cgame; + } + free(game); +} + +void fourwins_event_part(struct ChanUser *chanuser) { + struct fourwins_game *game; + for(game = fourwins_active_games; game; game = game->next) { + if(game->player[0] == chanuser || game->player[1] == chanuser) { + fourwins_reply(game, "NF_4WINS_GAME_CLOSED"); + fourwins_free_game(game); + return; + } + struct fourwins_guest *guest, *prev_guest = NULL; + for(guest = game->guests; guest; guest = guest->next) { + if(guest->chanuser == chanuser) { + if(prev_guest) + prev_guest->next = guest->next; + else + game->guests = guest->next; + free(guest); + break; + } else + prev_guest = guest; + } + } +} + +void fourwins_event_quit(struct UserNode *user) { + struct fourwins_game *game; + for(game = fourwins_active_games; game; game = game->next) { + if(game->player[0]->user == user || game->player[1]->user == user) { + fourwins_reply(game, "NF_4WINS_GAME_CLOSED"); + fourwins_free_game(game); + return; + } + struct fourwins_guest *guest, *prev_guest = NULL; + for(guest = game->guests; guest; guest = guest->next) { + if(guest->chanuser->user == user) { + if(prev_guest) + prev_guest->next = guest->next; + else + game->guests = guest->next; + free(guest); + break; + } else + prev_guest = guest; + } + } +} + +void fourwins_event_freechan(struct ChanNode *chan) { + struct fourwins_game *game; + for(game = fourwins_active_games; game; game = game->next) { + if(game->player[0]->chan == chan) { + fourwins_free_game(game); + return; + } + } +} diff --git a/src/modules/NeonFun.mod/game_4wins.h b/src/modules/NeonFun.mod/game_4wins.h new file mode 100644 index 0000000..7e404b6 --- /dev/null +++ b/src/modules/NeonFun.mod/game_4wins.h @@ -0,0 +1,63 @@ +/* game_4wins.h - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 3 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, see . + */ +#ifndef _game_4wins_h +#define _game_4wins_h +#include "../../timeq.h" + +#define FOURWINS_STATE_WAITING 1 +#define FOURWINS_STATE_RUNNING 2 + +#define FOURWINS_MATRIX_WIDTH 7 +#define FOURWINS_MATRIX_HEIGHT 6 + +#define FOURWINS_MAX_STONES (FOURWINS_MATRIX_WIDTH * FOURWINS_MATRIX_HEIGHT) + +struct UserNode; +struct ChanNode; +struct ChanUser; +struct ClientSocket; +extern struct fourwins_game *fourwins_active_games; + +struct fourwins_guest { + struct ChanUser *chanuser; + struct fourwins_guest *next; +}; + +struct fourwins_game { + struct ChanUser *player[2]; + int active_player; + struct fourwins_guest *guests; + struct ClientSocket *textbot; + int state : 3; + struct { + unsigned int field:2; /* 0,1,2 */ + } matrix[FOURWINS_MATRIX_WIDTH][FOURWINS_MATRIX_HEIGHT]; + int total_stones; + struct timeq_entry *timer; + struct fourwins_game *next; +}; + +int fourwins_next_free_y(struct fourwins_game *game, int x); +int fourwins_check_win(struct fourwins_game *game, int x, int y); +void fourwins_show_matrix(struct fourwins_game *game); +TIMEQ_CALLBACK(fourwins_timeout); +void fourwins_free_game(struct fourwins_game *game); +void fourwins_event_part(struct ChanUser *chanuser); +void fourwins_event_quit(struct UserNode *user); +void fourwins_event_freechan(struct ChanNode *chan); + +#endif diff --git a/src/modules/NeonFun.mod/game_uno.c b/src/modules/NeonFun.mod/game_uno.c index 8ddd9c9..4f17aeb 100644 --- a/src/modules/NeonFun.mod/game_uno.c +++ b/src/modules/NeonFun.mod/game_uno.c @@ -652,6 +652,7 @@ void uno_event_freechan(struct ChanNode *chan) { for(game = uno_active_games; game; game = game->next) { if(game->channel == chan) { uno_free_game(game); + return; } } } -- 2.20.1