rewrote IRC cache parser to be (hopefully) more stable
[NeonServV5.git] / src / modules / NeonFun.mod / game_4wins.c
1 /* game_4wins.c - NeonServ v5.4
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "../module.h"
18 #include "game_4wins.h"
19 #include "bot_NeonFun.h"
20 #include "../../IRCParser.h"
21 #include "../../bots.h"
22 #include "../../UserNode.h"
23 #include "../../ChanUser.h"
24 #include "../../tools.h"
25 #include "../botid.h"
26
27 struct fourwins_game *fourwins_active_games = NULL;
28
29 int fourwins_next_free_y(struct fourwins_game *game, int x) {
30     int y;
31     for(y = 0; y < FOURWINS_MATRIX_HEIGHT; y++) {
32         if(!game->matrix[x][y].field)
33             return y;
34     }
35     return -1;
36 }
37
38 int fourwins_check_win(struct fourwins_game *game, int x, int y) {
39     int field = game->matrix[x][y].field;
40     if(!field) return 0;
41     //horizontal
42     {
43         int fc = 0;
44         int i;
45         for(i = x; i < FOURWINS_MATRIX_WIDTH; i++) {
46             if(game->matrix[i][y].field == field)
47                 fc++;
48             else
49                 break;
50         }
51         for(i = x-1; i >= 0; i--) {
52             if(game->matrix[i][y].field == field)
53                 fc++;
54             else
55                 break;
56         }
57         if(fc >= 4) return 1;
58     }
59     //senkrecht
60     if(y >= 3) {
61         int fc = 0;
62         int i;
63         for(i = y; i >= 0; i--) {
64             if(game->matrix[i][y].field == field)
65                 fc++;
66             else
67                 break;
68         }
69         if(fc >= 4) return 1;
70     }
71     //diagonal 1
72     {
73         int fc = 0;
74         int ix, iy;
75         for(ix = x, iy = y; ix < FOURWINS_MATRIX_WIDTH && iy < FOURWINS_MATRIX_HEIGHT; ix++, iy++) {
76             if(game->matrix[ix][iy].field == field)
77                 fc++;
78             else
79                 break;
80         }
81         for(ix = x-1, iy = y-1; ix >= 0 && iy >= 0; ix--, iy--) {
82             if(game->matrix[ix][iy].field == field)
83                 fc++;
84             else
85                 break;
86         }
87         if(fc >= 4) return 1;
88     }
89     //diagonal 2
90     {
91         int fc = 0;
92         int ix, iy;
93         for(ix = x, iy = y; ix < FOURWINS_MATRIX_WIDTH && iy >= 0; ix++, iy--) {
94             if(game->matrix[ix][iy].field == field)
95                 fc++;
96             else
97                 break;
98         }
99         for(ix = x-1, iy = y+1; ix >= 0 && iy < FOURWINS_MATRIX_HEIGHT; ix--, iy++) {
100             if(game->matrix[ix][iy].field == field)
101                 fc++;
102             else
103                 break;
104         }
105         if(fc >= 4) return 1;
106     }
107     return 0;
108 }
109
110 void fourwins_show_matrix(struct fourwins_game *game) {
111     int x,y;
112     char lineBuf[MAXLEN];
113     int linePos = 0;
114     for(x = 0; x < FOURWINS_MATRIX_WIDTH; x++) {
115         linePos += sprintf(lineBuf+linePos, (x ? "| %d " : " %d "), x+1);
116     }
117     fourwins_reply(game, lineBuf);
118     for(y = FOURWINS_MATRIX_HEIGHT-1; y >= 0; y--) {
119         linePos = 0;
120         for(x = 0; x < FOURWINS_MATRIX_WIDTH; x++) {
121             char *field = " ";
122             if(game->matrix[x][y].field == 1)
123                 field = "\0034o\003";
124             if(game->matrix[x][y].field == 2)
125                 field = "\00312o\003";
126             linePos += sprintf(lineBuf+linePos, (x ? " (%s)" : "(%s)"), field);
127         }
128         fourwins_reply(game, lineBuf);
129     }
130 }
131
132 TIMEQ_CALLBACK(fourwins_timeout) {
133     struct fourwins_game *game = data;
134     game->timer = NULL;
135     fourwins_reply(game, "NF_4WINS_TIMEOUT");
136     fourwins_free_game(game);
137 }
138
139 void fourwins_free_game(struct fourwins_game *game) {
140     struct fourwins_guest *guest, *next_guest;
141     for(guest = game->guests; guest; guest = next_guest) {
142         next_guest = guest->next;
143         free(guest);
144     }
145     struct fourwins_game *cgame, *prev = NULL;
146     for(cgame = fourwins_active_games; cgame; cgame = cgame->next) {
147         if(cgame == game) {
148             if(prev)
149                 prev->next = game->next;
150             else
151                 fourwins_active_games = game->next;
152             break;
153         } else
154             prev = cgame;
155     }
156     free(game);
157 }
158
159 void fourwins_event_part(struct ChanUser *chanuser) {
160     struct fourwins_game *game;
161     for(game = fourwins_active_games; game; game = game->next) {
162         if(game->player[0] == chanuser || game->player[1] == chanuser) {
163             fourwins_reply(game, "NF_4WINS_GAME_CLOSED");
164             fourwins_free_game(game);
165             return;
166         }
167         struct fourwins_guest *guest, *prev_guest = NULL;
168         for(guest = game->guests; guest; guest = guest->next) {
169             if(guest->chanuser == chanuser) {
170                 if(prev_guest)
171                     prev_guest->next = guest->next;
172                 else
173                     game->guests = guest->next;
174                 free(guest);
175                 break;
176             } else
177                 prev_guest = guest;
178         }
179     }
180 }
181
182 void fourwins_event_freechan(struct ChanNode *chan) {
183     struct fourwins_game *game;
184     for(game = fourwins_active_games; game; game = game->next) {
185         if(game->player[0]->chan == chan) {
186             fourwins_free_game(game);
187             return;
188         }
189     }
190 }