+/* 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 <http://www.gnu.org/licenses/>.
+ */
+#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;
+ }
+ }
+}