cd src && chmod +x version.sh && ./version.sh && cd ..
noinst_PROGRAMS = neonserv
-noinst_LTLIBRARIES = libDummyServ.la libfuncmds.la libglobalcmd.la libNeonHelp.la libNeonServ.la libNeonSpam.la libstats.la
+noinst_LTLIBRARIES = libDummyServ.la libfuncmds.la libglobalcmd.la libNeonHelp.la libNeonServ.la libNeonSpam.la libstats.la libNeonFun.la
libDummyServ_la_SOURCES = src/modules/DummyServ.mod/bot_DummyServ.c \
src/modules/DummyServ.mod/module.c
libstats_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined
libstats_la_LIBADD = $(MYSQL_LIBS)
+libNeonFun_la_SOURCES = src/modules/NeonFun.mod/bot_NeonFun.c \
+ src/modules/NeonFun.mod/cmd_neonfun.c \
+ src/modules/NeonFun.mod/cmd_neonfun_uno.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/module.c
+libNeonFun_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined
+libNeonFun_la_LIBADD = $(MYSQL_LIBS)
+
neonserv_SOURCES = src/version.c \
src/EventLogger.c \
src/IRCEvents.c \
--- /dev/null
+/* bot_NeonFun.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 <http://www.gnu.org/licenses/>.
+ */
+#include "../module.h"
+#include "../botid.h"
+
+#include "bot_NeonFun.h"
+#include "../../modcmd.h"
+#include "../../IRCParser.h"
+#include "../../IRCEvents.h"
+#include "../../UserNode.h"
+#include "../../ChanNode.h"
+#include "../../ChanUser.h"
+#include "../../ModeNode.h"
+#include "../../BanNode.h"
+#include "../../ClientSocket.h"
+#include "../../mysqlConn.h"
+#include "../../lang.h"
+#include "../../HandleInfoHandler.h"
+#include "../../WHOHandler.h"
+#include "../../DBHelper.h"
+#include "../../tools.h"
+#include "../../timeq.h"
+#include "../../version.h"
+#include "../../EventLogger.h"
+#include "../../bots.h"
+#include "game_uno.h"
+
+#define BOTID NEONFUN_BOTID
+#define BOTALIAS "NeonFun"
+
+static void neonfun_bot_ready(struct ClientSocket *client) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ putsock(client, "MODE %s +%s", client->user->nick, row[0]);
+ }
+
+ printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid);
+ res = mysql_use();
+
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ putsock(client, "JOIN %s %s", row[0], row[1]);
+ }
+}
+
+static void neonfun_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
+ strcpy(trigger, "+");
+ return;
+ }
+ printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID);
+ res = mysql_use();
+ if(!(row = mysql_fetch_row(res))) {
+ strcpy(trigger, "+");
+ return;
+ }
+ if(row[0] && *row[0])
+ strcpy(trigger, row[0]);
+ else
+ strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "~"));
+}
+
+static void start_bots(int type) {
+ struct ClientSocket *client;
+ MYSQL_RES *res, *res2;
+ MYSQL_ROW row;
+
+ if(type == MODSTATE_STARTSTOP) {
+ printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID);
+ res = mysql_use();
+
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]);
+ client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0);
+ client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0);
+ client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0);
+ client->flags |= SOCKET_FLAG_SILENT;
+ client->botid = BOTID;
+ client->clientid = atoi(row[7]);
+ connect_socket(client);
+ }
+ }
+
+ printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID);
+ res2 = mysql_use();
+ while ((row = mysql_fetch_row(res2)) != NULL) {
+ if(bind_cmd_to_command(BOTID, row[0], row[1])) {
+ if(row[2] && strcmp(row[2], "")) {
+ bind_set_parameters(BOTID, row[0], row[2]);
+ }
+ if(row[3]) {
+ bind_set_global_access(BOTID, row[0], atoi(row[3]));
+ }
+ if(row[4]) {
+ bind_set_channel_access(BOTID, row[0], row[4]);
+ }
+ if(strcmp(row[5], "0"))
+ bind_set_bind_flags(BOTID, row[0], atoi(row[5]));
+ }
+ }
+ bind_unbound_required_functions(BOTID);
+}
+
+static void neonfun_parted(struct ChanUser *chanuser, char *reason) {
+ uno_event_part(chanuser);
+}
+
+static void neonfun_quitted(struct UserNode *user, char *reason) {
+ uno_event_quit(user);
+}
+
+static int neonfun_freechan(struct ChanNode *chan) {
+ uno_event_freechan(chan);
+ return 0;
+}
+
+void init_NeonFun(int type) {
+ set_bot_alias(BOTID, BOTALIAS);
+ start_bots(type);
+
+ if(type == MODSTATE_REBIND) return;
+
+ //register events
+ bind_bot_ready(neonfun_bot_ready, module_id);
+ bind_part(neonfun_parted, module_id);
+ bind_quit(neonfun_quitted, module_id);
+ bind_freechan(neonfun_freechan, module_id);
+
+ set_trigger_callback(BOTID, module_id, neonfun_trigger_callback);
+}
+
+void loop_NeonFun() {
+
+}
+
+void free_NeonFun(int type) {
+ unbind_allcmd(BOTID);
+ if(type == MODSTATE_STARTSTOP) {
+ //disconnect all our bots
+ struct ClientSocket *client;
+ for(client = getBots(0, NULL); client; client = getBots(0, client)) {
+ if(client->botid == BOTID) {
+ unbind_botwise_allcmd(0, client->clientid);
+ close_socket(client);
+ break;
+ }
+ }
+ }
+}
+
+char* getSetting(struct UserNode *user, struct ChanNode *chan, const char *setting) {
+ char *uname = "";
+ int cid = 0;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ if(user) {
+ uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*");
+ }
+ if(chan) {
+ loadChannelSettings(chan);
+ if(chan->flags & CHANFLAG_CHAN_REGISTERED)
+ cid = chan->channel_id;
+ }
+ printf_mysql_query("SELECT `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ return row[0];
+ } else
+ return NULL;
+}
+
+void setSetting(struct UserNode *user, struct ChanNode *chan, const char *setting, const char *value) {
+ char *uname = "";
+ int cid = 0;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ if(user) {
+ uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*");
+ }
+ if(chan) {
+ loadChannelSettings(chan);
+ if(chan->flags & CHANFLAG_CHAN_REGISTERED)
+ cid = chan->channel_id;
+ }
+ printf_mysql_query("SELECT `id`, `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ if(strcmp(row[1], value))
+ printf_mysql_query("UPDATE `fundata` SET `value` = '%s' WHERE `id` = '%s'", escape_string(value), row[0]);
+ } else
+ printf_mysql_query("INSERT INTO `fundata` (`user`, `cid`, `name`, `value`) VALUES ('%s', '%d', '%s', '%s')", escape_string(uname), cid, escape_string(setting), escape_string(value));
+}
+
+void uno_reply(struct uno_game *game, struct UserNode *user, const char *text, ...) {
+ struct ClientSocket *client = game->textbot;
+ const char *reply_format = get_language_string(user, text);
+ if(reply_format == NULL)
+ reply_format = text;
+ char formatBuf[MAXLEN];
+ sprintf(formatBuf, "PRIVMSG %s :[UNO] %s", game->channel->name, 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
--- /dev/null
+/* bot_NeonFun.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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef _bot_NeonFun_h
+#define _bot_NeonFun_h
+
+#include "../../main.h"
+
+void init_NeonFun(int type);
+void loop_NeonFun();
+void free_NeonFun(int type);
+
+struct uno_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, ...);
+
+#endif
\ No newline at end of file
--- /dev/null
+/* cmd_neonfun.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 <http://www.gnu.org/licenses/>.
+ */
+#include "../module.h"
+
+#include "cmd_neonfun.h"
+#include "../../modcmd.h"
+#include "../../lang.h"
+#include "../../ConfigParser.h"
+
+static const struct default_language_entry msgtab[] = {
+ {"NF_UNO_ALREADY_RUNNING", "There is already a UNO game running in %s."}, /* {ARGS: "#channel"} */
+ {"NF_UNO_ALREADY_JOINED", "You have already joined this UNO game."},
+ {"NF_UNO_USER_JOINED", "$b%s$b has joined the game."}, /* {ARGS: "TestUser"} */
+ {"NF_UNO_CREATED", "$b%s$b started an UNO game. Type $b+uno$b to join the game."}, /* {ARGS: "TestUser"} */
+ {"NF_UNO_ERROR", "UNO program error. Please contact a bot administrator. (ErrCode: %d)"}, /* {ARGS: 0} */
+ {"NF_UNO_START", "GAME START"},
+ {"NF_UNO_USER_HURRY_UP", "$b%s$b, it's your turn!"}, /* {ARGS: "TestUser"} */
+ {"NF_UNO_USER_TOOK_CARD", "$b%s$b took another card."}, /* {ARGS: "TestUser"} */
+ {"NF_UNO_USER_TOOK_CARDS", "$b%s$b took $b%d$b cards."}, /* {ARGS: "TestUser", 4} */
+ {"NF_UNO_YOUR_CARDS", "Your cards: %s"}, /* {ARGS: "[+2] [+4] [R5] ..."} */
+ {"NF_UNO_TOP_CARD", "upper card: %s"}, /* {ARGS: "[+4]"} */
+ {"NF_UNO_NOT_YOUR_TURN", "Wait your turn!"},
+ {"NF_UNO_UNKNOWN_CARD", "Unknown card [%s]."}, /* {ARGS: "xy"} */
+ {"NF_UNO_CARD_NOT_IN_DECK", "You don't have this card."},
+ {"NF_UNO_CARD_YELLOW", "yellow"},
+ {"NF_UNO_CARD_BLUE", "blue"},
+ {"NF_UNO_CARD_RED", "red"},
+ {"NF_UNO_CARD_GREEN", "green"},
+ {"NF_UNO_DEFINE_COLOR", "Please define the color you want to set as a parameter to the command (eg. $b+unoplay +4 RED$b)"},
+ {"NF_UNO_CARD_NOT_POSSIBLE", "You can't play this card."},
+ {"NF_UNO_ONE_CARD", "$b%s$b has only one card! $k4U$k$k9N$k$k12O$k"}, /* {ARGS: "TestUser"} */
+ {"NF_UNO_USER_WIN", "$b%s$b has 0 cards! $k4U$k$k9N$k$k12O$k $k4U$k$k9N$k$k12O$k!!!"}, /* {ARGS: "TestUser"} */
+ {"NF_UNO_TIMEOUT", "game stopped (no more active players)."},
+ {"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...?"},
+ {NULL, NULL}
+};
+
+void register_commands() {
+ //NeonFun Commands
+ register_default_language_table(msgtab);
+ register_command_alias(5, "NeonFun");
+
+ #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(5, NAME, module_id, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS)
+ // NAME FUNCTION PARAMS PRIVS FLAGS
+ USER_COMMAND("uno", neonfun_cmd_uno, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN);
+ 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);
+
+ #undef USER_COMMAND
+
+}
+
+
--- /dev/null
+/* cmd_neonfun.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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef _cmd_neonfun_h
+#define _cmd_neonfun_h
+#include "../module.h"
+#include "../../main.h"
+#include "../../modcmd.h"
+#include "../../IRCParser.h"
+#include "../../IRCEvents.h"
+#include "../../UserNode.h"
+#include "../../ChanNode.h"
+#include "../../ChanUser.h"
+#include "../../ModeNode.h"
+#include "../../BanNode.h"
+#include "../../ClientSocket.h"
+#include "../../mysqlConn.h"
+#include "../../lang.h"
+#include "../../HandleInfoHandler.h"
+#include "../../WHOHandler.h"
+#include "../../DBHelper.h"
+#include "../../tools.h"
+#include "../../timeq.h"
+#include "../../version.h"
+#include "../../EventLogger.h"
+#include "../../bots.h"
+#include "../../ConfigParser.h"
+#include "bot_NeonFun.h"
+
+void register_commands();
+
+CMD_BIND(neonfun_cmd_uno);
+CMD_BIND(neonfun_cmd_unotake);
+CMD_BIND(neonfun_cmd_unoplay);
+
+#endif
--- /dev/null
+/* cmd_neonfun_uno.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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "cmd_neonfun.h"
+#include "game_uno.h"
+
+CMD_BIND(neonfun_cmd_uno) {
+ struct ChanUser *chanuser = getChanUser(user, chan);
+ if(!chanuser) return;
+ struct uno_game *game;
+ for(game = uno_active_games; game; game = game->next) {
+ if(chan == game->channel) {
+ if(game->state == UNO_STATE_WAITING)
+ break;
+ else {
+ reply(getTextBot(), user, "NF_UNO_ALREADY_RUNNING", chan->name);
+ return;
+ }
+ }
+ }
+ if(game) {
+ //check if player has already joined
+ struct uno_player *player, *last_player = NULL;
+ for(player = game->player; player; player = player->next) {
+ if(player->chanuser == chanuser) {
+ reply(getTextBot(), user, "NF_UNO_ALREADY_JOINED");
+ return;
+ } else
+ last_player = player;
+ }
+ if(!last_player) return; //error (game without players?)
+ player = malloc(sizeof(*player));
+ player->chanuser = chanuser;
+ player->count = 0;
+ player->cards = NULL;
+ player->prev = last_player;
+ player->next = NULL;
+ last_player->next = player;
+ game->players++;
+ uno_reply(game, user, "NF_UNO_USER_JOINED", user->nick);
+ } else {
+ game = malloc(sizeof(*game));
+ game->channel = chan;
+ game->textbot = getTextBot();
+ game->state = UNO_STATE_WAITING;
+ game->reverse_direction = 0;
+ game->take_cards_pending = 0;
+ game->deck = NULL;
+ game->top_card = NULL;
+ struct uno_player *player = malloc(sizeof(*player));
+ player->chanuser = chanuser;
+ player->count = 0;
+ player->cards = NULL;
+ player->prev = NULL;
+ player->next = NULL;
+ game->player = player;
+ game->winner = NULL;
+ game->active_player = NULL;
+ game->players = 1;
+ game->active_player = 0;
+ game->timer = timeq_add(30, module_id, uno_game_wait_timeout, game);
+ game->next = uno_active_games;
+ uno_active_games = game;
+ uno_reply(game, user, "NF_UNO_CREATED", user->nick);
+ }
+}
--- /dev/null
+/* cmd_neonfun_unoplay.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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "cmd_neonfun.h"
+#include "game_uno.h"
+
+CMD_BIND(neonfun_cmd_unoplay) {
+ struct ChanUser *chanuser = getChanUser(user, chan);
+ if(!chanuser) return;
+ struct uno_game *game;
+ for(game = uno_active_games; game; game = game->next) {
+ if(chan == game->channel) {
+ if(game->state == UNO_STATE_WAITING)
+ return;
+ else
+ break;
+ }
+ }
+ if(game) {
+ //check if it's the player's turn
+ if(game->active_player->chanuser != chanuser) {
+ reply(getTextBot(), user, "NF_UNO_NOT_YOUR_TURN");
+ return;
+ }
+ game->active_player->timeout = 0;
+ struct uno_card *card = uno_parse_card(game, game->active_player, argv[0]);
+ if(!card) return;
+ unsigned char new_color = card->color;
+ if(card->card == UNO_CARD_ADD_4 || card->card == UNO_CARD_COLOR) {
+ if(argc < 2) {
+ reply(game->textbot, user, "NF_UNO_DEFINE_COLOR");
+ return;
+ }
+ if(!stricmp(argv[1], "RED") || !stricmp(argv[1], "R") || !stricmp(argv[1], get_language_string(user, "NF_UNO_CARD_RED"))) {
+ new_color = UNO_COLOR_RED;
+ } else if(!stricmp(argv[1], "BLUE") || !stricmp(argv[1], "B") || !stricmp(argv[1], get_language_string(user, "NF_UNO_CARD_BLUE"))) {
+ new_color = UNO_COLOR_BLUE;
+ } else if(!stricmp(argv[1], "GREEN") || !stricmp(argv[1], "G") || !stricmp(argv[1], get_language_string(user, "NF_UNO_CARD_GREEN"))) {
+ new_color = UNO_COLOR_GREEN;
+ } else if(!stricmp(argv[1], "YELLOW") || !stricmp(argv[1], "Y") || !stricmp(argv[1], get_language_string(user, "NF_UNO_CARD_YELLOW"))) {
+ new_color = UNO_COLOR_YELLOW;
+ } else {
+ reply(game->textbot, user, "NF_UNO_DEFINE_COLOR");
+ return;
+ }
+ }
+ if(uno_check_card_valid(game, card)) {
+ reply(game->textbot, user, "NF_UNO_CARD_NOT_POSSIBLE");
+ return;
+ }
+ card->color = new_color;
+ uno_play_card(game, game->active_player, card);
+ }
+}
--- /dev/null
+/* cmd_neonfun_unotake.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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "cmd_neonfun.h"
+#include "game_uno.h"
+
+CMD_BIND(neonfun_cmd_unotake) {
+ struct ChanUser *chanuser = getChanUser(user, chan);
+ if(!chanuser) return;
+ struct uno_game *game;
+ for(game = uno_active_games; game; game = game->next) {
+ if(chan == game->channel) {
+ if(game->state == UNO_STATE_WAITING)
+ return;
+ else
+ break;
+ }
+ }
+ if(game) {
+ //check if it's the player's turn
+ if(game->active_player->chanuser != chanuser) {
+ reply(getTextBot(), user, "NF_UNO_NOT_YOUR_TURN");
+ return;
+ }
+ game->active_player->timeout = 0;
+ uno_action_take_card(game, game->active_player);
+ }
+}
--- /dev/null
+/* game_uno.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 <http://www.gnu.org/licenses/>.
+ */
+#include "../module.h"
+#include "game_uno.h"
+#include "bot_NeonFun.h"
+#include "../../IRCParser.h"
+#include "../../bots.h"
+#include "../../UserNode.h"
+#include "../../ChanUser.h"
+#include "../../tools.h"
+#include "../botid.h"
+
+struct uno_game *uno_active_games = NULL;
+
+#define UNO_COLOR_COUNT 4
+static int uno_colors[] = {UNO_COLOR_RED, UNO_COLOR_BLUE, UNO_COLOR_GREEN, UNO_COLOR_YELLOW};
+static int uno_irc_colors[] = {4, 12, 3, 7};
+static char *uno_color_chars[] = {"R", "B", "G", "Y"};
+
+static const struct {
+ const char *name;
+ unsigned char type;
+} uno_card_types[] = {
+ {"0", UNO_CARD_NUMBER_0},
+ {"1", UNO_CARD_NUMBER_1},
+ {"2", UNO_CARD_NUMBER_2},
+ {"3", UNO_CARD_NUMBER_3},
+ {"4", UNO_CARD_NUMBER_4},
+ {"5", UNO_CARD_NUMBER_5},
+ {"6", UNO_CARD_NUMBER_6},
+ {"7", UNO_CARD_NUMBER_7},
+ {"8", UNO_CARD_NUMBER_8},
+ {"9", UNO_CARD_NUMBER_9},
+ {"X", UNO_CARD_SKIP},
+ {"><", UNO_CARD_DIRECTION},
+ {"+2", UNO_CARD_ADD_2},
+ {"+4", UNO_CARD_ADD_4},
+ {"COLOR", UNO_CARD_COLOR},
+ {NULL, 0}
+};
+
+struct uno_card_deck *uno_shuffle_deck() {
+ struct uno_card *card, *last_card = NULL;
+ int card_count = 0;
+ #define ADD_CARD(ccolor,ctype) \
+ card = malloc(sizeof(*card)); \
+ card->color = ccolor; \
+ card->card = ctype; \
+ card->prev = NULL; \
+ card->next = last_card; \
+ if(last_card) \
+ last_card->prev = card; \
+ last_card = card; \
+ card_count++;
+ int colorcount = UNO_COLOR_COUNT;
+ for(colorcount--; colorcount >= 0; colorcount--) {
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_0);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_0);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_1);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_1);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_2);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_2);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_3);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_3);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_4);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_4);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_5);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_5);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_6);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_6);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_7);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_7);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_8);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_8);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_9);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_9);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_SKIP);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_SKIP);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_DIRECTION);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_DIRECTION);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_ADD_2);
+ ADD_CARD(uno_colors[colorcount], UNO_CARD_ADD_2);
+ }
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
+ ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
+ #undef ADD_CARD
+ struct uno_card_deck *deck = malloc(sizeof(*deck));
+ deck->cards = last_card;
+ deck->count = card_count;
+ return deck;
+}
+
+struct uno_card *uno_get_card(struct uno_card_deck *deck) {
+ if(!deck->count) return NULL;
+ int card_id = (rand() % deck->count);
+ int i = 0;
+ struct uno_card *card;
+ for(card = deck->cards; card; card = card->next) {
+ if(i == card_id) {
+ if(card->prev)
+ card->prev->next = card->next;
+ else
+ deck->cards = card->next;
+ if(card->next)
+ card->next->prev = card->prev;
+ deck->count--;
+ card->next = NULL;
+ card->prev = NULL;
+ return card;
+ }
+ i++;
+ }
+ return NULL;
+}
+
+void uno_free_deck(struct uno_card_deck *deck) {
+ struct uno_card *card, *next_card;
+ if(deck->count) {
+ for(card = deck->cards; card; card = next_card) {
+ next_card = card->next;
+ free(card);
+ }
+ }
+}
+
+void uno_free_player(struct uno_player *player, struct uno_card_deck *deck) {
+ if(player->count) {
+ struct uno_card *card, *next_card;
+ for(card = player->cards; card; card = next_card) {
+ next_card = card->next;
+ if(deck) {
+ card->next = deck->cards;
+ deck->cards->prev = card;
+ deck->cards = card;
+ deck->count++;
+ } else
+ free(card);
+ }
+ }
+ if(player->prev)
+ player->prev->next = player->next;
+ if(player->next)
+ player->next->prev = player->prev;
+ free(player);
+}
+
+void uno_free_topcard(struct uno_card *card) {
+ struct uno_card *next_card;
+ for(; card; card = next_card) {
+ next_card = card->prev;
+ free(card);
+ }
+}
+
+void uno_free_game(struct uno_game *game) {
+ struct uno_player *player, *next_player;
+ for(player = game->player; player; player = next_player) {
+ next_player = player->next;
+ uno_free_player(player, NULL);
+ }
+ for(player = game->winner; player; player = next_player) {
+ next_player = player->next;
+ uno_free_player(player, NULL);
+ }
+ if(game->deck)
+ uno_free_deck(game->deck);
+ if(game->top_card)
+ uno_free_topcard(game->top_card);
+ if(game->timer)
+ timeq_del(game->timer);
+ struct uno_game *cgame, *pgame = NULL;
+ for(cgame = uno_active_games; cgame; cgame = cgame->next) {
+ if(cgame == game) {
+ if(pgame)
+ pgame->next = game->next;
+ else
+ uno_active_games = game->next;
+ break;
+ } else
+ pgame = cgame;
+ }
+ free(game);
+}
+
+struct uno_player *uno_get_next_player(struct uno_game *game) {
+ struct uno_player *player = game->active_player;
+ if(!game->reverse_direction) {
+ player = player->next;
+ if(!player)
+ player = game->player;
+ } else {
+ player = player->prev;
+ if(!player) {
+ for(player = game->player; player->next; player = player->next) {
+ //loop to the last player
+ }
+ }
+ }
+ return player;
+}
+
+void uno_show_player_cards(struct uno_game *game, struct uno_player *player) {
+ struct uno_card *card;
+ char cards_buf[MAXLEN];
+ int cards_bufpos = 0;
+ for(card = player->cards; card; card = card->next) {
+ int cardcolor = 1;
+ char *cardchar = "";
+ int i;
+ for(i = 0; i < UNO_COLOR_COUNT; i++) {
+ if(uno_colors[i] == card->color) {
+ cardcolor = uno_irc_colors[i];
+ cardchar = uno_color_chars[i];
+ break;
+ }
+ }
+ i = 0;
+ while(uno_card_types[i].name) {
+ if(uno_card_types[i].type == card->card) {
+ cards_bufpos += sprintf(cards_buf + cards_bufpos, "%s[\003%d%s%s\003]", (cards_bufpos ? " " : ""), cardcolor, cardchar, uno_card_types[i].name);
+ break;
+ }
+ i++;
+ }
+ }
+ reply(game->textbot, player->chanuser->user, "NF_UNO_YOUR_CARDS", cards_buf);
+}
+
+void uno_show_top_card(struct uno_game *game) {
+ struct uno_card *card = game->top_card;
+ char card_buf[50];
+ int cardcolor = 1;
+ char *cardchar = "";
+ int i;
+ for(i = 0; i < UNO_COLOR_COUNT; i++) {
+ if(uno_colors[i] == card->color) {
+ cardcolor = uno_irc_colors[i];
+ cardchar = uno_color_chars[i];
+ break;
+ }
+ }
+ i = 0;
+ while(uno_card_types[i].name) {
+ if(uno_card_types[i].type == card->card) {
+ if(card->card == UNO_CARD_ADD_4 || card->card == UNO_CARD_COLOR)
+ cardchar = "";
+ sprintf(card_buf, "[\003%d%s%s\003]", cardcolor, cardchar, uno_card_types[i].name);
+ break;
+ }
+ i++;
+ }
+ uno_reply(game, NULL, "NF_UNO_TOP_CARD", card_buf);
+}
+
+TIMEQ_CALLBACK(uno_game_wait_timeout) {
+ struct uno_game *game = data;
+ game->timer = NULL;
+ if(game->players == 1) {
+ //TEXT: too less users
+ uno_free_game(game);
+ return;
+ }
+ game->deck = uno_shuffle_deck();
+ uno_reply(game, NULL, "NF_UNO_START");
+ struct uno_player *player;
+ for(player = game->player; player; player = player->next) {
+ //give 7 cards
+ int i;
+ for(i = 0; i < 7; i++) {
+ if(!game->deck->count)
+ game->deck = uno_shuffle_deck();
+ struct uno_card *card = uno_get_card(game->deck);
+ if(!card) {
+ uno_reply(game, NULL, "NF_UNO_ERROR", 1);
+ uno_free_game(game);
+ return;
+ }
+ card->next = player->cards;
+ if(player->cards)
+ player->cards->prev = card;
+ player->cards = card;
+ player->count++;
+ }
+ uno_show_player_cards(game, player);
+ if((player->chanuser->user->flags & USERFLAG_ISAUTHED)) {
+ char *tmp;
+ int game_count = ((tmp = getSetting(player->chanuser->user, game->channel, "uno_games")) ? atoi(tmp) : 0);
+ int total_game_count = ((tmp = getSetting(player->chanuser->user, NULL, "uno_games")) ? atoi(tmp) : 0);
+ game_count++;
+ total_game_count++;
+ char buf[10];
+ sprintf(buf, "%d", game_count);
+ setSetting(player->chanuser->user, game->channel, "uno_games", buf);
+ sprintf(buf, "%d", total_game_count);
+ setSetting(player->chanuser->user, NULL, "uno_games", buf);
+ }
+ }
+ if(!game->deck->count)
+ game->deck = uno_shuffle_deck();
+ struct uno_card *card = uno_get_card(game->deck);
+ if(!card) {
+ uno_reply(game, NULL, "NF_UNO_ERROR", 1);
+ uno_free_game(game);
+ return;
+ }
+ game->top_card = card;
+ game->state = UNO_STATE_RUNNING;
+ uno_show_top_card(game);
+ game->active_player = game->player; //active player
+ uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
+ game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+}
+
+TIMEQ_CALLBACK(uno_player_timeout) {
+ struct uno_game *game = data;
+ game->timer = NULL;
+ //player timeout (take another card)
+ struct uno_player *player = game->active_player, *next_player = uno_get_next_player(game);
+ //add a card to the players deck
+ if(!game->deck->count)
+ game->deck = uno_shuffle_deck();
+ struct uno_card *card = uno_get_card(game->deck);
+ if(!card) {
+ uno_reply(game, NULL, "NF_UNO_ERROR", 2);
+ uno_free_game(game);
+ return;
+ }
+ card->next = player->cards;
+ if(player->cards)
+ player->cards->prev = card;
+ player->cards = card;
+ player->count++;
+ player->timeout = 1;
+ game->active_player = next_player;
+ uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
+ struct uno_player *cplayer;
+ for(cplayer = game->player; cplayer; cplayer = cplayer->next) {
+ if(!cplayer->timeout)
+ break;
+ }
+ if(!cplayer) {
+ uno_reply(game, NULL, "NF_UNO_TIMEOUT");
+ uno_free_game(game);
+ return;
+ }
+ uno_show_player_cards(game, player);
+ uno_show_top_card(game);
+ uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
+ uno_show_player_cards(game, game->active_player);
+ game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+}
+
+void uno_action_take_card(struct uno_game *game, struct uno_player *player) {
+ timeq_del(game->timer);
+ game->timer = NULL;
+ struct uno_player *next_player = uno_get_next_player(game);
+ //add a card to the players deck
+ int ccount;
+ if(game->take_cards_pending) {
+ //count cards to take
+ struct uno_card *card;
+ ccount = 0;
+ for(card = game->top_card; card; card = card->prev) {
+ if(card->card == UNO_CARD_ADD_2)
+ ccount += 2;
+ else if(card->card == UNO_CARD_ADD_4)
+ ccount += 4;
+ }
+ } else
+ ccount = 1;
+ int i;
+ for(i = 0; i < ccount; i++) {
+ if(!game->deck->count)
+ game->deck = uno_shuffle_deck(game->deck);
+ struct uno_card *card = uno_get_card(game->deck);
+ if(!card) {
+ uno_reply(game, NULL, "NF_UNO_ERROR", 2);
+ uno_free_game(game);
+ return;
+ }
+ card->next = player->cards;
+ if(player->cards)
+ player->cards->prev = card;
+ player->cards = card;
+ player->count++;
+ }
+ game->active_player = next_player;
+ if(game->take_cards_pending) {
+ game->take_cards_pending = 0;
+ uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARDS", player->chanuser->user->nick, ccount);
+ } else
+ uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
+ uno_show_player_cards(game, player);
+ uno_show_top_card(game);
+ uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
+ uno_show_player_cards(game, game->active_player);
+ game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+}
+
+
+
+struct uno_card *uno_parse_card(struct uno_game *game, struct uno_player *player, char *arg1) {
+ char *b = arg1;
+ int a = 0;
+ while(*b) {
+ switch (*b) {
+ case '\003':
+ if(isdigit(b[1]))
+ b[1] = '\002';
+ if(isdigit(b[2]))
+ b[2] = '\002';
+ case '[':
+ case '\002':
+ case ']':
+ *b = '\0';
+ break;
+ default:
+ if(!a) {
+ a = 1;
+ arg1 = b;
+ }
+ }
+ b++;
+ }
+ unsigned char ctype = 255, ccolor = 0;
+ int i = 0, j;
+ char tmpbuf[50];
+ while(uno_card_types[i].name) {
+ if(!stricmp(uno_card_types[i].name, arg1)) {
+ ctype = uno_card_types[i].type;
+ break;
+ }
+ for(j = 0; j < UNO_COLOR_COUNT; j++) {
+ sprintf(tmpbuf, "%s%s", uno_color_chars[j], uno_card_types[i].name);
+ if(!stricmp(tmpbuf, arg1)) {
+ ccolor = uno_colors[j];
+ ctype = uno_card_types[i].type;
+ break;
+ }
+ }
+ i++;
+ }
+ if(ctype == 255) {
+ reply(game->textbot, player->chanuser->user, "NF_UNO_UNKNOWN_CARD", arg1);
+ return NULL;
+ }
+ struct uno_card *card;
+ for(card = player->cards; card; card = card->next) {
+ if(card->card == ctype && card->color == ccolor)
+ break;
+ }
+ if(!card) {
+ reply(game->textbot, player->chanuser->user, "NF_UNO_CARD_NOT_IN_DECK");
+ return NULL;
+ }
+ return card;
+}
+
+int uno_check_card_valid(struct uno_game *game, struct uno_card *card) {
+ if(game->take_cards_pending && card->card != game->top_card->card)
+ return 1;
+ if(card->color == UNO_COLOR_BLACK)
+ return 0;
+ if(card->color != game->top_card->color && card->card != game->top_card->card)
+ return 1;
+ return 0;
+}
+
+void uno_play_card(struct uno_game *game, struct uno_player *player, struct uno_card *card) {
+ timeq_del(game->timer);
+ game->timer = NULL;
+ if(card->prev)
+ card->prev->next = card->next;
+ else
+ player->cards = card->next;
+ if(card->next)
+ card->next->prev = card->prev;
+ player->count--;
+ if(!game->take_cards_pending) {
+ uno_free_topcard(game->top_card);
+ card->prev = NULL;
+ } else
+ card->prev = game->top_card;
+ card->next = NULL;
+ game->top_card = card;
+ uno_show_top_card(game);
+ if(player->count == 1) {
+ uno_reply(game, NULL, "NF_UNO_ONE_CARD", game->active_player->chanuser->user->nick);
+ } else if(player->count == 0) {
+ uno_reply(game, NULL, "NF_UNO_USER_WIN", game->active_player->chanuser->user->nick);
+ if(player->prev)
+ player->prev->next = player->next;
+ if(player->next)
+ player->next->prev = player->prev;
+ player->next = NULL;
+ player->prev = NULL;
+ struct uno_player *cplayer;
+ int winner_count = 0;
+ if(game->winner) {
+ for(cplayer = game->winner; cplayer->next; cplayer = cplayer->next) {
+ winner_count++;
+ }
+ } else
+ cplayer = NULL;
+ if(cplayer) {
+ cplayer->next = player;
+ } else {
+ game->winner = player;
+ if((player->chanuser->user->flags & USERFLAG_ISAUTHED)) {
+ char *tmp;
+ int win_count = ((tmp = getSetting(player->chanuser->user, game->channel, "uno_win")) ? atoi(tmp) : 0);
+ int total_win_count = ((tmp = getSetting(player->chanuser->user, NULL, "uno_win")) ? atoi(tmp) : 0);
+ win_count++;
+ total_win_count++;
+ char buf[10];
+ sprintf(buf, "%d", win_count);
+ setSetting(player->chanuser->user, game->channel, "uno_win", buf);
+ sprintf(buf, "%d", total_win_count);
+ setSetting(player->chanuser->user, NULL, "uno_win", buf);
+ }
+ }
+ player->prev = cplayer;
+ game->players--;
+ if(game->players <= 1) {
+ //game finished
+ uno_reply(game, NULL, "NF_UNO_GAME_FINISHED");
+ struct Table *table;
+ table = table_init(4, winner_count + 3, 0);
+ char *content[4];
+ content[0] = get_language_string(NULL, "NF_UNO_RANK");
+ content[1] = get_language_string(NULL, "NF_UNO_NAME");
+ content[2] = get_language_string(NULL, "NF_UNO_WON_GAMES");
+ content[3] = get_language_string(NULL, "NF_UNO_TOTAL_WON_GAMES");
+ table_add(table, content);
+ winner_count = 1;
+ char rank_buf[20], won_buf[50], total_won_buf[50];
+ char *tmp, *tmp2;
+ for(cplayer = game->winner; cplayer->next; cplayer = cplayer->next) {
+ sprintf(rank_buf, "%d", winner_count++);
+ content[0] = rank_buf;
+ content[1] = cplayer->chanuser->user->nick;
+ if((cplayer->chanuser->user->flags & USERFLAG_ISAUTHED)) {
+ sprintf(won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, game->channel, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, game->channel, "uno_games")) ? atoi(tmp2) : 0));
+ content[2] = won_buf;
+ sprintf(total_won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, NULL, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, NULL, "uno_games")) ? atoi(tmp2) : 0));
+ content[3] = total_won_buf;
+ } else {
+ content[2] = "?";
+ content[3] = "?";
+ }
+ table_add(table, content);
+ }
+ cplayer = game->player;
+ sprintf(rank_buf, "%d", winner_count++);
+ content[0] = rank_buf;
+ content[1] = cplayer->chanuser->user->nick;
+ if((cplayer->chanuser->user->flags & USERFLAG_ISAUTHED)) {
+ sprintf(won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, game->channel, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, game->channel, "uno_games")) ? atoi(tmp2) : 0));
+ content[2] = won_buf;
+ sprintf(total_won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, NULL, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, NULL, "uno_games")) ? atoi(tmp2) : 0));
+ content[3] = total_won_buf;
+ } else {
+ content[2] = "?";
+ content[3] = "?";
+ }
+ table_add(table, content);
+ char **table_lines = table_end(table);
+ int i;
+ for(i = 0; i < table->entrys; i++) {
+ uno_reply(game, NULL, table_lines[i]);
+ }
+ table_free(table);
+ uno_free_game(game);
+ return;
+ }
+ }
+ if(card->card == UNO_CARD_DIRECTION)
+ game->reverse_direction = (game->reverse_direction ? 0 : 1);
+ struct uno_player *next_player = uno_get_next_player(game);
+ game->active_player = next_player;
+ if(card->card == UNO_CARD_SKIP) {
+ uno_reply(game, NULL, "NF_UNO_USER_SKIP", game->active_player->chanuser->user->nick);
+ next_player = uno_get_next_player(game);
+ game->active_player = next_player;
+ }
+ if(card->card == UNO_CARD_ADD_2 || card->card == UNO_CARD_ADD_4) {
+ int ccount = 0;
+ for(card = game->top_card; card; card = card->prev) {
+ if(card->card == UNO_CARD_ADD_2)
+ ccount += 2;
+ else if(card->card == UNO_CARD_ADD_4)
+ ccount += 4;
+ }
+ uno_reply(game, NULL, "NF_UNO_ADD_CARD", game->active_player->chanuser->user->nick, ccount);
+ game->take_cards_pending = 1;
+ }
+ uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
+ uno_show_player_cards(game, game->active_player);
+ game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+}
+
+void uno_event_part(struct ChanUser *chanuser) {
+ struct uno_game *game;
+ for(game = uno_active_games; game; game = game->next) {
+ if(chanuser->chan == game->channel) {
+ struct uno_player *player;
+ for(player = game->player; player; player = player->next) {
+ if(player->chanuser == chanuser) {
+ uno_free_player(player, game->deck);
+ return;
+ }
+ }
+ }
+ }
+}
+
+void uno_event_quit(struct UserNode *user) {
+ struct uno_game *game;
+ for(game = uno_active_games; game; game = game->next) {
+ struct uno_player *player;
+ for(player = game->player; player; player = player->next) {
+ if(player->chanuser->user == user) {
+ uno_free_player(player, game->deck);
+ break;
+ }
+ }
+ }
+}
+
+void uno_event_freechan(struct ChanNode *chan) {
+ struct uno_game *game;
+ for(game = uno_active_games; game; game = game->next) {
+ if(game->channel == chan) {
+ uno_free_game(game);
+ }
+ }
+}
--- /dev/null
+/* game_uno.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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef _game_uno_h
+#define _game_uno_h
+#include "../../timeq.h"
+
+#define UNO_STATE_WAITING 1
+#define UNO_STATE_RUNNING 2
+
+#define UNO_COLOR_BLACK 0
+#define UNO_COLOR_RED 1
+#define UNO_COLOR_BLUE 2
+#define UNO_COLOR_GREEN 3
+#define UNO_COLOR_YELLOW 4
+
+#define UNO_CARD_NUMBER_0 0
+#define UNO_CARD_NUMBER_1 1
+#define UNO_CARD_NUMBER_2 2
+#define UNO_CARD_NUMBER_3 3
+#define UNO_CARD_NUMBER_4 4
+#define UNO_CARD_NUMBER_5 5
+#define UNO_CARD_NUMBER_6 6
+#define UNO_CARD_NUMBER_7 7
+#define UNO_CARD_NUMBER_8 8
+#define UNO_CARD_NUMBER_9 9
+#define UNO_CARD_SKIP 10
+#define UNO_CARD_DIRECTION 11
+#define UNO_CARD_ADD_2 12
+#define UNO_CARD_ADD_4 13
+#define UNO_CARD_COLOR 14
+
+#define UNO_IS_NUMBER_CARD(ccard) (ccard->card <= 9)
+
+struct UserNode;
+struct ChanNode;
+struct ChanUser;
+struct ClientSocket;
+extern struct uno_game *uno_active_games;
+
+struct uno_card {
+ unsigned char color;
+ unsigned char card;
+ struct uno_card *prev, *next;
+};
+
+struct uno_card_deck {
+ struct uno_card *cards;
+ int count;
+};
+
+struct uno_player {
+ struct ChanUser *chanuser;
+ struct uno_card *cards;
+ int count;
+ int timeout;
+ struct uno_player *prev, *next;
+};
+
+struct uno_game {
+ struct ChanNode *channel;
+ struct ClientSocket *textbot;
+ int state : 3;
+ int reverse_direction : 1;
+ int take_cards_pending : 1;
+ struct uno_card_deck *deck;
+ struct uno_card *top_card;
+ struct uno_player *player;
+ struct uno_player *winner;
+ struct uno_player *active_player;
+ int players;
+
+ struct timeq_entry *timer;
+ struct uno_game *next;
+};
+
+struct uno_card_deck *uno_shuffle_deck();
+struct uno_card *uno_get_card(struct uno_card_deck *deck);
+void uno_free_deck(struct uno_card_deck *deck);
+void uno_free_player(struct uno_player *player, struct uno_card_deck *deck);
+void uno_free_topcard(struct uno_card *card);
+void uno_free_game(struct uno_game *game);
+struct uno_player *uno_get_next_player(struct uno_game *game);
+void uno_show_player_cards(struct uno_game *game, struct uno_player *player);
+void uno_show_top_card(struct uno_game *game);
+
+TIMEQ_CALLBACK(uno_game_wait_timeout);
+TIMEQ_CALLBACK(uno_player_timeout);
+
+void uno_action_take_card(struct uno_game *game, struct uno_player *player);
+struct uno_card *uno_parse_card(struct uno_game *game, struct uno_player *player, char *arg1);
+int uno_check_card_valid(struct uno_game *game, struct uno_card *card);
+void uno_play_card(struct uno_game *game, struct uno_player *player, struct uno_card *card);
+
+void uno_event_part(struct ChanUser *chanuser);
+void uno_event_quit(struct UserNode *user);
+void uno_event_freechan(struct ChanNode *chan);
+
+#endif
--- /dev/null
+/* module.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 <http://www.gnu.org/licenses/>.
+ */
+#include "../module.h"
+#include "bot_NeonFun.h"
+#include "cmd_neonfun.h"
+
+static int module_initialize() {
+ register_commands();
+ return 0;
+}
+
+static void module_start(int type) {
+ init_NeonFun(type);
+ srand(time(NULL));
+}
+
+static void module_loop() {
+ loop_NeonFun();
+}
+
+static void module_stop(int type) {
+ free_NeonFun(type);
+}
+
+MODULE_HEADER(module_initialize, module_start, module_loop, module_stop);
#define NEONSPAM_BOTID 2
#define DUMMYSERV_BOTID 3
#define NEONHELP_BOTID 4
+#define NEONFUN_BOTID 5
#endif
\ No newline at end of file
break;
}
}
- printf_mysql_query("UPDATE `bots` SET `prefered` = '%d' WHERE `id` = '%s'", val, bot[15]);
+ printf_mysql_query("UPDATE `bots` SET `textbot` = '%d' WHERE `id` = '%s'", val, bot[15]);
ret = 1;
}
reply(getTextBot(), user, "\002PREFERED \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF")));