Added AI by Ricardo Cruz. This also adds mouse controls.
[crow/jumpnbump.git] / sdl / interrpt.c
1 /*
2  * interrpt.c
3  * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
4  * 
5  * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
6  *
7  * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
8  *
9  * This file is part of Jump'n'Bump.
10  *
11  * Jump'n'Bump is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * Jump'n'Bump is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #ifndef _MSC_VER
30 #include <unistd.h>
31 #endif
32 #include "globals.h"
33
34 #ifdef USE_KAILLERA
35 #include "SDL_thread.h"
36 #include "SDL_mutex.h"
37 #include <kailleraclient.h>
38
39 char local_keyb[256];
40 #endif /* USE_KAILLERA */
41
42 char keyb[256];
43 char last_keys[50];
44
45 #ifdef USE_KAILLERA
46
47 /* information about the party in this session */
48 static int my_player = -1;
49 static int my_numplayers = -1;
50
51 /* semaphore for controlling kaillera thread */
52 static SDL_sem *game_start_sem = NULL;
53
54 /* keys supported on my end */
55 static int my_player_up = -1;
56 static int my_player_left = -1;
57 static int my_player_right = 1;
58
59 /* values for the kaillera client interface */
60 static char kaillera_app_name[] = "Jump 'n Bump";
61 static char kaillera_game_name[] = "Jump 'n Bump\0\0";
62
63 static int player_keys[4][3] = {
64         {
65                 KEY_PL1_LEFT,
66                 KEY_PL1_RIGHT,
67                 KEY_PL1_JUMP
68         },                        
69         {
70                 KEY_PL2_LEFT,
71                 KEY_PL2_RIGHT,
72                 KEY_PL2_JUMP
73         },
74         {
75                 KEY_PL3_LEFT,
76                 KEY_PL3_RIGHT,
77                 KEY_PL3_JUMP
78         },
79         {
80                 KEY_PL4_LEFT,
81                 KEY_PL4_RIGHT,
82                 KEY_PL4_JUMP
83         }
84 };
85
86 static int WINAPI kaillera_game_callback(char *game, int player, int numplayers)
87 {
88         int length;
89         int urand;
90         unsigned char random[8];
91
92         if (strcmp(game, kaillera_game_name) != 0) {
93                 printf("unknown game selected: %s\n", game);
94
95                 my_player = -1;
96                 goto release;
97         }
98
99         printf("start network game with %d players\n", numplayers);
100         printf("I am player %d\n", player);
101
102         my_player = player;
103         my_numplayers = numplayers;
104
105         my_player_up = player_keys[player-1][0] & 0xff;
106         my_player_left = player_keys[player-1][1] & 0xff;
107         my_player_right = player_keys[player-1][2] & 0xff;
108
109         /* initialize randomizer agreed by all players */
110         random[0] = time(0) & 0xff;
111         random[1] = random[2] = random[3] = 0x00;
112         length = kailleraModifyPlayValues(&random, sizeof(random[0]));
113         if (length < 0) {
114                 goto release;
115         }
116
117         urand = random[3] << 24 | random[2] << 16 | random[1] << 8 | random[0];
118         srand(urand);
119
120 release:
121
122         SDL_SemPost(game_start_sem);
123         return 0;
124 }
125
126 static kailleraInfos kaillera_data = {
127         kaillera_app_name,
128         kaillera_game_name,
129         kaillera_game_callback,
130         NULL,
131         NULL,
132         NULL
133 };
134
135 static void print_version()
136 {
137         char version[16];
138
139         kailleraGetVersion(version);
140         printf("using kaillera version %s\n", version);
141 }
142
143 static int kaillera_thread(void *arg)
144 {
145         kailleraInit();
146         
147         /* print_version(); */
148
149         kailleraSetInfos(&kaillera_data);
150
151         kailleraSelectServerDialog(0);
152         if (SDL_SemValue(game_start_sem) == 0) {
153                 /* server dialog returned and game didnt start */
154                 
155                 /* release blocking thread */
156                 my_player = -1;
157                 SDL_SemPost(game_start_sem);
158         }
159
160         return 0;
161 }
162
163 static int start_kaillera_thread(void)
164 {
165         SDL_Thread *thread;
166
167         game_start_sem = SDL_CreateSemaphore(0);
168
169         thread = SDL_CreateThread(kaillera_thread, NULL);
170         if (!thread) {
171                 printf("SDL_CreateThread failed\n");
172                 return -1;
173         }
174         
175         return 0;
176 }       
177
178 int addkey(unsigned int key)
179 {
180         /* it doesnt matter if a player presses keys
181          * that control other bunnies. whatever is sent 
182          * is packed by pack_keys()
183          */
184         if (!(key & 0x8000)) {
185                 local_keyb[key & 0x7fff] = 1;
186         } else
187                 local_keyb[key & 0x7fff] = 0;
188         return 0;
189 }
190
191 void remove_keyb_handler(void)
192 {
193         kailleraShutdown();
194 }
195
196 int pack_keys(void)
197 {
198         int rv;
199
200         rv = local_keyb[my_player_up];
201         rv |= local_keyb[my_player_left] << 1;
202         rv |= local_keyb[my_player_right] << 2;
203         rv |= local_keyb[1] << 3;
204         return rv;
205 }
206
207 void unpack_keys(int player, char value)
208 {
209         keyb[player_keys[player][0] & 0xff] = (value >> 0) & 1;
210         keyb[player_keys[player][1] & 0xff] = (value >> 1) & 1;
211         keyb[player_keys[player][2] & 0xff] = (value >> 2) & 1;
212
213         /* escape key is shared among all users */
214         keyb[1] |= (value >> 3) & 1;
215 }
216
217 int update_kaillera_keys(void)
218 {
219         char keys[8];
220         int length;
221         int player;
222
223         keys[0] = pack_keys();
224         length = kailleraModifyPlayValues(&keys, sizeof(keys[0]));
225
226         if (length < 0) {
227                 /* terminate session */
228                 printf("** LOST CONNECTION **\n");
229                 kailleraEndGame();
230                 my_player = -1;
231                 return -1;
232         }
233
234         for (player=0; player<length; player++) {
235                 unpack_keys(player, keys[player]);
236         }
237
238         return 0;
239 }
240
241 int hook_keyb_handler(void)
242 {
243         SDL_EnableUNICODE(1);
244         memset((void *) last_keys, 0, sizeof(last_keys));
245
246         start_kaillera_thread();
247         SDL_SemWait(game_start_sem);
248         if (my_player < 0) {
249                 printf("GAME ABORTED!\n");
250                 return -1;
251         }
252
253         printf("GAME STARTS!\n");
254         return 0;
255 }
256
257 int key_pressed(int key)
258 {
259         if (key == 1 && my_player < 0) {
260                 /* if game completed or aborted, post ESC */
261                 return 1;
262         }
263
264         return keyb[(unsigned char) key];
265 }
266
267 #else /* USE_KAILLERA */
268
269 int addkey(unsigned int key)
270 {
271         int c1;
272
273         if (!(key & 0x8000)) {
274                 keyb[key & 0x7fff] = 1;
275                 for (c1 = 48; c1 > 0; c1--)
276                         last_keys[c1] = last_keys[c1 - 1];
277                 last_keys[0] = key & 0x7fff;
278         } else
279                 keyb[key & 0x7fff] = 0;
280         return 0;
281 }
282
283 void remove_keyb_handler(void)
284 {
285 }
286
287 int hook_keyb_handler(void)
288 {
289         SDL_EnableUNICODE(1);
290         memset((void *) last_keys, 0, sizeof(last_keys));
291
292         return 0;
293 }
294
295 int key_pressed(int key)
296 {
297         return keyb[(unsigned char) key];
298 }
299
300
301 #endif /* USE_KAILLERA */
302
303 int intr_sysupdate()
304 {
305         SDL_Event e;
306         int i = 0;
307         static int last_time = 0;
308         int now, time_diff;
309
310         while (SDL_PollEvent(&e)) {
311                 switch (e.type) {
312                 case SDL_MOUSEBUTTONDOWN:
313                 case SDL_MOUSEBUTTONUP:
314                         if(e.button.state == SDL_PRESSED &&
315                                         ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) ||
316                                         (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) ||
317                                         (e.button.button == SDL_BUTTON_LEFT && e.button.button == SDL_BUTTON_RIGHT) ||
318           e.button.button == SDL_BUTTON_MIDDLE))
319                                 {
320                                 addkey(KEY_PL3_JUMP & 0x7f);
321                                 }
322                         else if(e.button.state == SDL_RELEASED &&
323                                         ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) ||
324                                         (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) ||
325           e.button.button == SDL_BUTTON_MIDDLE))
326                                 {
327                                 addkey((KEY_PL3_JUMP & 0x7f) | 0x8000);
328                                 }
329
330                         if(e.button.button == SDL_BUTTON_LEFT)
331                                 {
332                                 SDLKey sym = KEY_PL3_LEFT;
333                                 sym &= 0x7f;
334                                 if(e.button.state == SDL_RELEASED)
335                                         {
336                                         if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)))
337                                                 addkey(KEY_PL3_RIGHT & 0x7f);
338                                         else
339                                                 sym |= 0x8000;
340                                         }
341                                 addkey(sym);
342                                 }
343                         else if(e.button.button == SDL_BUTTON_RIGHT)
344                                 {
345                                 SDLKey sym = KEY_PL3_RIGHT;
346                                 sym &= 0x7f;
347                                 if (e.button.state == SDL_RELEASED)
348                                         {
349                                         if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_LEFT)))
350                                                 addkey(KEY_PL3_LEFT & 0x7f);
351                                         else
352                                                 sym |= 0x8000;
353                                         }
354                                 addkey(sym);
355                                 }
356                         break;
357                 case SDL_KEYDOWN:
358                 case SDL_KEYUP:
359                         switch (e.key.keysym.sym) {
360                         case SDLK_F12:
361                                 if (e.type == SDL_KEYDOWN) {
362                                         SDL_Quit();
363                                         exit(1);
364                                 }
365                                 break;
366                         case SDLK_F10:
367                                 if (e.type == SDL_KEYDOWN) {
368                                         fs_toggle();
369                                 }
370                                 break;
371                         case SDLK_1:
372                                 if (e.type == SDL_KEYUP)
373                                         ai[0] = !ai[0];
374
375                                 /* Release keys, otherwise it will continue moving that way */
376                                 addkey((KEY_PL1_LEFT & 0x7f) | 0x8000);
377                                 addkey((KEY_PL1_RIGHT & 0x7f) | 0x8000);
378                                 addkey((KEY_PL1_JUMP & 0x7f) | 0x8000);
379                                 break;
380                         case SDLK_2:
381                                 if (e.type == SDL_KEYUP)
382                                         ai[1] = !ai[1];
383
384                                 /* Release keys, otherwise it will continue moving that way */
385                                 addkey((KEY_PL2_LEFT & 0x7f) | 0x8000);
386                                 addkey((KEY_PL2_RIGHT & 0x7f) | 0x8000);
387                                 addkey((KEY_PL2_JUMP & 0x7f) | 0x8000);
388                                 break;
389                         case SDLK_3:
390                                 if (e.type == SDL_KEYUP)
391                                         ai[2] = !ai[2];
392
393                                 /* Release keys, otherwise it will continue moving that way */
394                                 addkey((KEY_PL3_LEFT & 0x7f) | 0x8000);
395                                 addkey((KEY_PL3_RIGHT & 0x7f) | 0x8000);
396                                 addkey((KEY_PL3_JUMP & 0x7f) | 0x8000);
397                                 break;
398                         case SDLK_4:
399                                 if (e.type == SDL_KEYUP)
400                                         ai[3] = !ai[3];
401
402                                 /* Release keys, otherwise it will continue moving that way */
403                                 addkey((KEY_PL4_LEFT & 0x7f) | 0x8000);
404                                 addkey((KEY_PL4_RIGHT & 0x7f) | 0x8000);
405                                 addkey((KEY_PL4_JUMP & 0x7f) | 0x8000);
406                                 break;
407                         case SDLK_ESCAPE:
408                                 if (e.type == SDL_KEYUP)
409                                         addkey(1 | 0x8000);
410                                 else
411                                         addkey(1 & 0x7f);
412                                 break;
413                         default:
414                                 e.key.keysym.sym &= 0x7f;
415                                 if (e.type == SDL_KEYUP)
416                                         e.key.keysym.sym |= 0x8000;
417                                 addkey(e.key.keysym.sym);
418
419                                 break;
420                         }
421                         break;
422                 default:
423                         break;
424                 }
425                 i++;
426         }
427
428         SDL_Delay(1);
429         now = SDL_GetTicks();
430         time_diff = now - last_time;
431         if (time_diff>0) {
432                 i = time_diff / (1000 / 60);
433                 if (i) {
434                         last_time = now;
435                 } else {
436                         int tmp;
437
438                         tmp = (1000/60) - i - 10;
439                         if (tmp>0)
440                                 SDL_Delay(tmp);
441                 }
442         }
443 /*
444         if (!then)
445                 SDL_Delay(1);
446         else {
447                 then = (1000 / 60) - (now - then);
448                 if (then > 0 && then < 1000)
449                         SDL_Delay(then);
450         }
451         then = now;
452 */
453
454 #ifdef USE_KAILLERA
455         if (my_player >= 0) {
456                 update_kaillera_keys();
457                 i=1;
458         }
459 #endif /* USE_KAILLERA */
460
461         return i;
462 }