Added AI by Ricardo Cruz. This also adds mouse controls.
[crow/jumpnbump.git] / main.c
1 /*
2  * main.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 "globals.h"
27 #include <fcntl.h>
28 #ifndef _MSC_VER
29 #include <unistd.h>
30 #endif
31
32 #ifdef BZLIB_SUPPORT
33 #include "bzlib.h"
34 #endif
35
36 #ifdef ZLIB_SUPPORT
37 #include "zlib.h"
38 #endif
39
40 #ifdef USE_NET
41 #include "SDL_net.h"
42 #endif /* USE_NET */
43
44 #ifndef M_PI
45 #define M_PI            3.14159265358979323846
46 #endif
47
48 gob_t rabbit_gobs = { 0 };
49 gob_t font_gobs = { 0 };
50 gob_t object_gobs = { 0 };
51 gob_t number_gobs = { 0 };
52
53 main_info_t main_info;
54 player_t player[JNB_MAX_PLAYERS];
55 player_anim_t player_anims[7];
56 object_t objects[NUM_OBJECTS];
57 joy_t joy;
58 mouse_t mouse;
59
60 char datfile_name[2048];
61
62 char *background_pic;
63 char *mask_pic;
64 int flip = 0;
65 char pal[768];
66 char cur_pal[768];
67
68 int ai[JNB_MAX_PLAYERS];
69
70 unsigned int ban_map[17][22] = {
71         {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
72         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},
73         {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
74         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
75         {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
76         {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
77         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
78         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
79         {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
80         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1},
81         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
82         {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1},
83         {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
84         {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
85         {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1},
86         {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
87         {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
88 };
89
90 #define GET_BAN_MAP_XY(x,y) ban_map[(y) >> 4][(x) >> 4]
91
92 struct {
93         int num_frames;
94         int restart_frame;
95         struct {
96                 int image;
97                 int ticks;
98         } frame[10];
99 } object_anims[8] = {
100         {
101                 6, 0, {
102                         {
103                         0, 3}, {
104                         1, 3}, {
105                         2, 3}, {
106                         3, 3}, {
107                         4, 3}, {
108                         5, 3}, {
109                         0, 0}, {
110                         0, 0}, {
111                         0, 0}, {
112                         0, 0}
113                 }
114         }, {
115                 9, 0, {
116                         {
117                         6, 2}, {
118                         7, 2}, {
119                         8, 2}, {
120                         9, 2}, {
121                         10, 2}, {
122                         11, 2}, {
123                         12, 2}, {
124                         13, 2}, {
125                         14, 2}, {
126                         0, 0}
127                 }
128         }, {
129                 5, 0, {
130                         {
131                         15, 3}, {
132                         16, 3}, {
133                         16, 3}, {
134                         17, 3}, {
135                         18, 3}, {
136                         19, 3}, {
137                         0, 0}, {
138                         0, 0}, {
139                         0, 0}, {
140                         0, 0}
141                 }
142         }, {
143                 10, 0, {
144                         {
145                         20, 2}, {
146                         21, 2}, {
147                         22, 2}, {
148                         23, 2}, {
149                         24, 2}, {
150                         25, 2}, {
151                         24, 2}, {
152                         23, 2}, {
153                         22, 2}, {
154                         21, 2}
155                 }
156         }, {
157                 10, 0, {
158                         {
159                         26, 2}, {
160                         27, 2}, {
161                         28, 2}, {
162                         29, 2}, {
163                         30, 2}, {
164                         31, 2}, {
165                         30, 2}, {
166                         29, 2}, {
167                         28, 2}, {
168                         27, 2}
169                 }
170         }, {
171                 10, 0, {
172                         {
173                         32, 2}, {
174                         33, 2}, {
175                         34, 2}, {
176                         35, 2}, {
177                         36, 2}, {
178                         37, 2}, {
179                         36, 2}, {
180                         35, 2}, {
181                         34, 2}, {
182                         33, 2}
183                 }
184         }, {
185                 10, 0, {
186                         {
187                         38, 2}, {
188                         39, 2}, {
189                         40, 2}, {
190                         41, 2}, {
191                         42, 2}, {
192                         43, 2}, {
193                         42, 2}, {
194                         41, 2}, {
195                         40, 2}, {
196                         39, 2}
197                 }
198         }, {
199                 4, 0, {
200                         {
201                         76, 4}, {
202                         77, 4}, {
203                         78, 4}, {
204                         79, 4}, {
205                         0, 0}, {
206                         0, 0}, {
207                         0, 0}, {
208                         0, 0}, {
209                         0, 0}, {
210                         0, 0}
211                 }
212         }
213 };
214
215 int flies_enabled = 1;
216
217 struct {
218         int x, y;
219         int old_x, old_y;
220         int old_draw_x, old_draw_y;
221         int back[2];
222         int back_defined[2];
223 } flies[NUM_FLIES];
224
225 struct {
226         struct {
227                 short num_pobs;
228                 struct {
229                         int x, y;
230                         int image;
231                         gob_t *pob_data;
232                 } pobs[NUM_LEFTOVERS];
233         } page[2];
234 } leftovers;
235
236 int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water;
237
238
239 #ifndef _MSC_VER
240 int filelength(int handle)
241 {
242         struct stat buf;
243
244         if (fstat(handle, &buf) == -1) {
245                 perror("filelength");
246                 exit(EXIT_FAILURE);
247         }
248
249         return buf.st_size;
250 }
251 #endif
252
253
254 /* networking shite. */
255
256 int client_player_num = -1;
257 int is_server = 1;
258 int is_net = 0;
259
260 #ifdef USE_NET
261 TCPsocket sock = NULL;
262 SDLNet_SocketSet socketset = NULL;
263
264 typedef struct
265 {
266         TCPsocket sock;
267         IPaddress addr;
268         SDLNet_SocketSet socketset;
269 } NetInfo;
270
271 NetInfo net_info[JNB_MAX_PLAYERS];
272 #endif
273
274 typedef struct
275 {
276         unsigned long cmd;
277         long arg;
278         long arg2;
279         long arg3;
280         long arg4;
281 } NetPacket;
282
283 #define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4)
284
285 #define NETCMD_NACK         (0xF00DF00D + 0)
286 #define NETCMD_ACK          (0xF00DF00D + 1)
287 #define NETCMD_HELLO        (0xF00DF00D + 2)
288 #define NETCMD_GREENLIGHT   (0xF00DF00D + 3)
289 #define NETCMD_MOVE         (0xF00DF00D + 4)
290 #define NETCMD_BYE          (0xF00DF00D + 5)
291 #define NETCMD_POSITION     (0xF00DF00D + 6)
292 #define NETCMD_ALIVE        (0xF00DF00D + 7)
293 #define NETCMD_KILL         (0xF00DF00D + 8)
294
295
296 #ifdef USE_NET
297 void bufToPacket(const char *buf, NetPacket *pkt)
298 {
299         SDLNet_Write32(*((Uint32*) (buf +  0)), &pkt->cmd);
300         SDLNet_Write32(*((Uint32*) (buf +  4)), &pkt->arg);
301         SDLNet_Write32(*((Uint32*) (buf +  8)), &pkt->arg2);
302         SDLNet_Write32(*((Uint32*) (buf + 12)), &pkt->arg3);
303         SDLNet_Write32(*((Uint32*) (buf + 16)), &pkt->arg4);
304 /*
305         pkt->cmd               =        ntohl(*((unsigned long *) (buf +  0)));
306         pkt->arg               = (long) ntohl(*((unsigned long *) (buf +  4)));
307         pkt->arg2              = (long) ntohl(*((unsigned long *) (buf +  8)));
308         pkt->arg3              = (long) ntohl(*((unsigned long *) (buf + 12)));
309         pkt->arg4              = (long) ntohl(*((unsigned long *) (buf + 16)));
310 */
311 }
312
313
314 void packetToBuf(const NetPacket *pkt, char *buf)
315 {
316         *((Uint32*) (buf +  0)) = SDLNet_Read32(&pkt->cmd);
317         *((Uint32*) (buf +  4)) = SDLNet_Read32(&pkt->arg);
318         *((Uint32*) (buf +  8)) = SDLNet_Read32(&pkt->arg2);
319         *((Uint32*) (buf + 12)) = SDLNet_Read32(&pkt->arg3);
320         *((Uint32*) (buf + 16)) = SDLNet_Read32(&pkt->arg4);
321 /*
322         *((unsigned long *) (buf +  0)) = htonl(pkt->cmd);
323         *((unsigned long *) (buf +  4)) = htonl((unsigned long) pkt->arg);
324         *((unsigned long *) (buf +  8)) = htonl((unsigned long) pkt->arg2);
325         *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3);
326         *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4);
327 */
328 }
329
330
331 void sendPacketToSock(TCPsocket s, NetPacket *pkt)
332 {
333         int bytes_left = NETPKTBUFSIZE;
334         int bw;
335         char buf[NETPKTBUFSIZE];
336         char *ptr = buf;
337
338         packetToBuf(pkt, buf);
339         while (bytes_left > 0) {
340                 bw = SDLNet_TCP_Send(s, ptr, bytes_left);
341                 if (bw < 0) {
342                         fprintf(stderr, "SERVER: SDLNet_TCP_Send(): %s\n", SDLNet_GetError());
343                         SDLNet_TCP_Close(s);
344                         exit(42);
345                 } else if (bw == 0) {
346                         SDL_Delay(1);
347                 } else {
348                         bytes_left -= bw;
349                         ptr += bw;
350                 }
351         }
352 }
353
354
355 void sendPacket(int playerid, NetPacket *pkt)
356 {
357         if ( (playerid < JNB_MAX_PLAYERS) && (playerid >= 0)) {
358                 if ((player[playerid].enabled) && (playerid != client_player_num)) {
359                         sendPacketToSock(net_info[playerid].sock, pkt);
360                 }
361         }
362 }
363
364
365 void sendPacketToAll(NetPacket *pkt)
366 {
367         int i;
368
369         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
370                 sendPacket(i, pkt);
371         }
372 }
373
374 /** read a packet from the given TCPsocket
375 Returns -1 if some error occured, 0 if there was no data available and 1 if a
376 packet was successfully read.
377 Note: the socket has to be in the supplied socketset.
378 TODO: this function will bomb if a packet arrives in pieces, there is no
379 inherent guarantee that the next call will be made on the same socket. */
380 int grabPacket(TCPsocket s, SDLNet_SocketSet ss, NetPacket *pkt)
381 {
382         static char buf[NETPKTBUFSIZE];
383         static int buf_count = 0;
384         int rc;
385
386         if (SDLNet_CheckSockets(ss, 0) <= 0)
387                 return 0;
388
389         if(!SDLNet_SocketReady(s))
390                 return 0;
391
392         rc = SDLNet_TCP_Recv(s, &buf[buf_count], NETPKTBUFSIZE - buf_count);
393         if (rc <= 0) {
394                 /* closed connection? */
395                 return -1;
396         } else if (rc != NETPKTBUFSIZE) {
397                 /* we got a partial packet. Store what we got in the static buffer and
398                 return so that the next call can read the rest. Hopefully. */
399                 buf_count = rc;
400                 return 0;
401         } else {
402                 buf_count = 0;
403                 bufToPacket(buf, pkt);
404                 return 1;
405         }
406 }
407
408
409 int serverRecvPacket(NetPacket *pkt)
410 {
411         int rc;
412         int i;
413
414         assert(is_server);
415
416         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
417                 TCPsocket s = net_info[i].sock;
418
419                 if ((i == client_player_num) || (!player[i].enabled))
420                         continue;
421
422                 rc = grabPacket(s, net_info[i].socketset, pkt);
423                 if (rc < 0) {
424                         NetPacket pkt;
425
426                         player[i].enabled = 0;
427                         SDLNet_TCP_Close(s);
428                         pkt.cmd = NETCMD_BYE;
429                         pkt.arg = i;
430                         pkt.arg2 = 0;
431                         pkt.arg3 = 0;
432                         pkt.arg4 = 0;
433                         sendPacketToAll(&pkt);
434                 } else if (rc > 0) {
435                         return(i);  /* it's all good. */
436                 }
437         }
438
439         return(-1);  /* no packets available currently. */
440 }
441
442
443 void wait_for_greenlight(void)
444 {
445         NetPacket pkt;
446         int i;
447
448         printf("CLIENT: Waiting for greenlight...\n");
449
450         do {
451                 int rc;
452                 while ((rc = grabPacket(sock, socketset, &pkt)) == 0) {
453                         SDL_Delay(100);  /* nap and then try again. */
454                 }
455
456                 if (rc < 0) {
457                         printf("CLIENT: Lost connection.\n");
458                         SDLNet_TCP_Close(sock);
459                         exit(42);
460                 }
461         } while (pkt.cmd != NETCMD_GREENLIGHT);
462
463         printf("CLIENT: Got greenlight.\n");
464
465         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
466                 if (pkt.arg & (1 << i)) {
467                         printf("CLIENT: There is a player #%d.\n", i);
468                         player[i].enabled = 1;
469                 }
470         }
471 }
472
473
474 static int buggered_off = 0;
475
476
477 void tellServerGoodbye(void)
478 {
479         NetPacket pkt;
480
481         if (!buggered_off) {
482                 buggered_off = 1;
483                 pkt.cmd = NETCMD_BYE;
484                 pkt.arg = client_player_num;
485                 pkt.arg2 = 0;
486                 pkt.arg3 = 0;
487                 pkt.arg4 = 0;
488                 sendPacketToSock(sock, &pkt);
489         }
490 }
491 #endif /* USE_NET */
492
493
494 void processMovePacket(NetPacket *pkt)
495 {
496         int playerid = pkt->arg;
497         int movetype = ((pkt->arg2 >> 16) & 0xFF);
498         int newval   = ((pkt->arg2 >>  0) & 0xFF);
499
500         if (movetype == MOVEMENT_LEFT) {
501                 player[playerid].action_left = newval;
502         } else if (movetype == MOVEMENT_RIGHT) {
503                 player[playerid].action_right = newval;
504         } else if (movetype == MOVEMENT_UP) {
505                 player[playerid].action_up = newval;
506         } else {
507                 printf("bogus MOVE packet!\n");
508         }
509
510         player[playerid].x = pkt->arg3;
511         player[playerid].y = pkt->arg4;
512 }
513
514
515 void tellServerPlayerMoved(int playerid, int movement_type, int newval)
516 {
517         NetPacket pkt;
518
519         pkt.cmd = NETCMD_MOVE;
520         pkt.arg = playerid;
521         pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) );
522         pkt.arg3 = player[playerid].x;
523         pkt.arg4 = player[playerid].y;
524
525         if (is_server) {
526                 processMovePacket(&pkt);
527 #ifdef USE_NET
528                 if (is_net)
529                         sendPacketToAll(&pkt);
530         } else {
531                 sendPacketToSock(sock, &pkt);
532 #endif
533         }
534 }
535
536
537 #ifdef USE_NET
538 void tellServerNewPosition(void)
539 {
540         NetPacket pkt;
541         pkt.cmd = NETCMD_POSITION;
542         pkt.arg = client_player_num;
543         pkt.arg2 = player[client_player_num].x;
544         pkt.arg3 = player[client_player_num].y;
545
546         if (is_server) {
547                 sendPacketToAll(&pkt);
548         } else {
549                 sendPacketToSock(sock, &pkt);
550         }
551 }
552 #endif /* USE_NET */
553
554
555 void processKillPacket(NetPacket *pkt)
556 {
557         int c1 = pkt->arg;
558         int c2 = pkt->arg2;
559         int x = pkt->arg3;
560         int y = pkt->arg4;
561         int c4 = 0;
562         int s1 = 0;
563
564         player[c1].y_add = -player[c1].y_add;
565         if (player[c1].y_add > -262144L)
566                 player[c1].y_add = -262144L;
567         player[c1].jump_abort = 1;
568         player[c2].dead_flag = 1;
569         if (player[c2].anim != 6) {
570                 player[c2].anim = 6;
571                 player[c2].frame = 0;
572                 player[c2].frame_tick = 0;
573                 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
574                 if (main_info.no_gore == 0) {
575                         for (c4 = 0; c4 < 6; c4++)
576                                 add_object(OBJ_FUR, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 44 + c2 * 8);
577                         for (c4 = 0; c4 < 6; c4++)
578                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76);
579                         for (c4 = 0; c4 < 6; c4++)
580                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77);
581                         for (c4 = 0; c4 < 8; c4++)
582                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78);
583                         for (c4 = 0; c4 < 10; c4++)
584                                 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
585                 }
586                 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
587                 player[c1].bumps++;
588                 player[c1].bumped[c2]++;
589                 s1 = player[c1].bumps % 100;
590                 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
591                 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
592                 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
593                 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
594         }
595 }
596
597
598 #ifdef USE_NET
599 void processPositionPacket(NetPacket *pkt)
600 {
601         int playerid = pkt->arg;
602
603         player[playerid].x = pkt->arg2;
604         player[playerid].y = pkt->arg3;
605 }
606
607
608 void processAlivePacket(NetPacket *pkt)
609 {
610         int playerid = pkt->arg;
611
612         player[playerid].dead_flag = 0;
613         player[playerid].x = pkt->arg2;
614         player[playerid].y = pkt->arg3;
615 }
616
617
618 void serverTellEveryoneGoodbye(void)
619 {
620         int i;
621
622         if (!buggered_off) {
623                 buggered_off = 1;
624                 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
625                         if (player[i].enabled) {
626                                 NetPacket pkt;
627
628                                 pkt.cmd = NETCMD_BYE;
629                                 pkt.arg = i;
630                                 pkt.arg2 = 0;
631                                 pkt.arg3 = 0;
632                                 pkt.arg4 = 0;
633                                 sendPacketToAll(&pkt);
634                         }
635                 }
636         }
637 }
638
639
640 int server_said_bye = 0;
641
642
643 int update_players_from_server(void)
644 {
645         NetPacket pkt;
646         int rc;
647
648         assert(!is_server);
649
650         while ((rc = grabPacket(sock, socketset, &pkt)) != 0) {
651                 if (rc < 0) {
652                         printf("CLIENT: Lost connection.\n");
653                         pkt.cmd = NETCMD_BYE;
654                         pkt.arg = client_player_num;
655                 }
656
657                 if (pkt.cmd == NETCMD_BYE) {
658                         if (pkt.arg == client_player_num) {
659                                 SDLNet_FreeSocketSet(socketset);
660                                 SDLNet_TCP_Close(sock);
661                                 sock = NULL;
662                                 server_said_bye = 1;
663                                 return(0);
664                         } else {
665                                 player[pkt.arg].enabled = 0;
666                         }
667                 } else if (pkt.cmd == NETCMD_MOVE) {
668                         processMovePacket(&pkt);
669                 } else if (pkt.cmd == NETCMD_ALIVE) {
670                         processAlivePacket(&pkt);
671                 } else if (pkt.cmd == NETCMD_POSITION) {
672                         processPositionPacket(&pkt);
673                 } else if (pkt.cmd == NETCMD_KILL) {
674                         processKillPacket(&pkt);
675                 } else {
676                         printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
677                 }
678         }
679
680         return(1);
681 }
682
683
684 void serverSendAlive(int playerid)
685 {
686         NetPacket pkt;
687
688         assert(is_server);
689         pkt.cmd = NETCMD_ALIVE;
690         pkt.arg = playerid;
691         pkt.arg2 = player[playerid].x;
692         pkt.arg3 = player[playerid].y;
693         sendPacketToAll(&pkt);
694 }
695 #endif /* USE_NET */
696
697
698 void serverSendKillPacket(int killer, int victim)
699 {
700         NetPacket pkt;
701
702         assert(is_server);
703         pkt.cmd = NETCMD_KILL;
704         pkt.arg = killer;
705         pkt.arg2 = victim;
706         pkt.arg3 = player[victim].x;
707         pkt.arg4 = player[victim].y;
708         processKillPacket(&pkt);
709 #ifdef USE_NET
710         if (is_net)
711                 sendPacketToAll(&pkt);
712 #endif
713 }
714
715
716 #ifdef USE_NET
717 void update_players_from_clients(void)
718 {
719         int i;
720         NetPacket pkt;
721         int playerid;
722
723         assert(is_server);
724
725         while ((playerid = serverRecvPacket(&pkt)) >= 0) {
726                 if (pkt.cmd == NETCMD_BYE) {
727                         pkt.arg = playerid;  /* just in case. */
728                         sendPacketToAll(&pkt);
729                         player[playerid].enabled = 0;
730                         SDLNet_FreeSocketSet(net_info[playerid].socketset);
731                         SDLNet_TCP_Close(net_info[playerid].sock);
732                 } else if (pkt.cmd == NETCMD_POSITION) {
733                         pkt.arg = playerid;  /* just in case. */
734                         processPositionPacket(&pkt);
735                         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
736                                 if (i != playerid) {
737                                         sendPacket(i, &pkt);
738                                 }
739                         }
740                 } else if (pkt.cmd == NETCMD_MOVE) {
741                         pkt.arg = playerid;  /* just in case. */
742                         /*
743                         pkt.arg3 = player[playerid].x;
744                         pkt.arg4 = player[playerid].y;
745                         */
746                         processMovePacket(&pkt);
747                         sendPacketToAll(&pkt);
748                 } else {
749                         printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
750                 }
751         }
752 }
753
754
755 void init_server(const char *netarg)
756 {
757         NetPacket pkt;
758         IPaddress addr;
759         int i;
760         int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
761         char *ipstr;
762
763         /** assign player number zero as default for the server */
764         if(-1 == client_player_num)
765                 client_player_num = 0;
766
767         if ((wait_for_clients >= JNB_MAX_PLAYERS) || (wait_for_clients < 0)) {
768                 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
769                 exit(42);
770         }
771
772         if (SDLNet_Init() < 0) {
773                 exit(42);
774         }
775         atexit(SDLNet_Quit);
776
777         SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
778         ipstr = SDLNet_ResolveIP(&addr);
779         SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
780         printf("SERVER: we are %s (%i.%i.%i.%i:%i).\n", ipstr, (addr.host >> 0) & 0xff, (addr.host >> 8) & 0xff, (addr.host >> 16) & 0xff, (addr.host >> 24) & 0xff, addr.port);
781         net_info[client_player_num].addr = addr;
782
783         addr.host = INADDR_ANY;
784         sock = SDLNet_TCP_Open(&addr);
785         if (sock == NULL) {
786                 fprintf(stderr, "SERVER: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
787                 exit(42);
788         }
789
790         player[client_player_num].enabled = 1;
791
792         printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
793
794         socketset = SDLNet_AllocSocketSet(JNB_MAX_PLAYERS + 1);
795         SDLNet_TCP_AddSocket(socketset, sock);
796
797         while (wait_for_clients > 0)
798         {
799                 char buf[NETPKTBUFSIZE];
800                 IPaddress *from;
801                 int negatory = 1;
802                 int br;
803                 TCPsocket s;
804
805                 /* Wait for events */
806                 SDLNet_CheckSockets(socketset, ~0);
807                 if ( SDLNet_SocketReady(sock) ) {
808                         s = SDLNet_TCP_Accept(sock);
809
810                         if (s == NULL)
811                         {
812                                 fprintf(stderr, "SERVER: SDLNet_TCP_Accept(): %s", SDLNet_GetError());
813                                 SDLNet_TCP_Close(sock);
814                                 exit(42);
815                         }
816                 } else
817                         continue;
818
819                 br = SDLNet_TCP_Recv(s, buf, NETPKTBUFSIZE);
820                 if (br < 0) {
821                         fprintf(stderr, "SERVER: SDLNet_TCP_Recv(): %s\n", SDLNet_GetError());
822                         SDLNet_TCP_Close(s);
823                         SDLNet_TCP_Close(sock);
824                         exit(42);
825                 }
826
827                 from = SDLNet_TCP_GetPeerAddress(s);
828                 ipstr = SDLNet_ResolveIP(from);
829                 printf("SERVER: Got data from %s (%i.%i.%i.%i:%i).\n", ipstr, (from->host >> 0) & 0xff, (from->host >> 8) & 0xff, (from->host >> 16) & 0xff, (from->host >> 24) & 0xff, from->port);
830
831                 if (br != NETPKTBUFSIZE) {
832                         printf("SERVER: Bogus packet.\n");
833                         continue;
834                 }
835
836                 bufToPacket(buf, &pkt);
837                 if (pkt.cmd != NETCMD_HELLO) {
838                         printf("SERVER: Bogus packet.\n");
839                         continue;
840                 }
841
842                 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
843
844                 if (-1 == pkt.arg) {
845                         int i;
846                         for(i=0; i!=JNB_MAX_PLAYERS; ++i) {
847                                 if(!player[i].enabled) {
848                                         printf("SERVER: assigning %d as player number\n", i);
849                                         pkt.arg = i;
850                                         break;
851                                 }
852                         }
853                 }
854
855                 if ((pkt.arg>=JNB_MAX_PLAYERS)||(pkt.arg<0)) {
856                         printf("SERVER:  (that's an invalid player number.)\n");
857                 } else if (player[pkt.arg].enabled) {
858                         printf("SERVER:  (that player number is already taken.)\n");
859                 } else {
860                         negatory = 0;
861                 }
862
863                 if (negatory) {
864                         printf("SERVER: Forbidding connection.\n");
865                         pkt.cmd = NETCMD_NACK;
866                         sendPacketToSock(s, &pkt);
867                         SDLNet_TCP_Close(s);
868                 } else {
869                         player[pkt.arg].enabled = 1;
870                         net_info[pkt.arg].sock = s;
871                         net_info[pkt.arg].addr = *from;
872                         net_info[pkt.arg].socketset = SDLNet_AllocSocketSet(1);
873                         SDLNet_TCP_AddSocket(net_info[pkt.arg].socketset, net_info[pkt.arg].sock);
874                         wait_for_clients--;
875                         printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
876                         pkt.cmd = NETCMD_ACK;
877                         sendPacket(pkt.arg, &pkt);
878                 }
879         }
880
881         SDLNet_TCP_Close(sock);  /* done with the listen socket. */
882         SDLNet_FreeSocketSet(socketset);
883         sock = NULL;
884         socketset = NULL;
885
886         printf("SERVER: Got all our connections. Greenlighting clients...\n");
887
888         pkt.cmd = NETCMD_GREENLIGHT;
889         pkt.arg = 0;
890         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
891                 if (player[i].enabled) {
892                         pkt.arg |= (1 << i);
893                 }
894         }
895         sendPacketToAll(&pkt);
896 }
897
898
899 void connect_to_server(char *netarg)
900 {
901         NetPacket pkt;
902         char buf[NETPKTBUFSIZE];
903         char *ipstr;
904         IPaddress hent;
905         IPaddress addr;
906         int br;
907
908         if (netarg == NULL) {
909                 printf("CLIENT: Need to specify host to connect to.\n");
910                 exit(42);
911         }
912
913         if (SDLNet_Init() < 0) {
914                 exit(42);
915         }
916         atexit(SDLNet_Quit);
917
918         SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
919         ipstr = SDLNet_ResolveIP(&addr);
920         SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
921         printf("CLIENT: we are %s (%i.%i.%i.%i:%i).\n", ipstr, (addr.host >> 0) & 0xff, (addr.host >> 8) & 0xff, (addr.host >> 16) & 0xff, (addr.host >> 24) & 0xff, addr.port);
922
923         if (SDLNet_ResolveHost(&hent, netarg, JNB_INETPORT) < 0) {
924                 fprintf(stderr, "CLIENT: couldn't find host: %s\n", SDLNet_GetError());
925                 exit(42);
926         }
927
928         sock = SDLNet_TCP_Open(&hent);
929         if (sock == NULL) {
930                 fprintf(stderr, "CLIENT: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
931                 exit(42);
932         }
933
934         socketset = SDLNet_AllocSocketSet(1);
935         SDLNet_TCP_AddSocket(socketset, sock);
936
937         printf("CLIENT: connected to %s...\n", SDLNet_ResolveIP(&hent));
938
939         printf("CLIENT: Sending HELLO packet...\n");
940         pkt.cmd = NETCMD_HELLO;
941         pkt.arg = client_player_num;
942         sendPacketToSock(sock, &pkt);
943
944         printf("CLIENT: Waiting for ACK from server...\n");
945
946         br = SDLNet_TCP_Recv(sock, buf, NETPKTBUFSIZE);
947         if (br < 0) {
948                 fprintf(stderr, "CLIENT: recv(): %s\n", SDLNet_GetError());
949                 SDLNet_FreeSocketSet(socketset);
950                 SDLNet_TCP_Close(sock);
951                 exit(42);
952         }
953
954         if (br != NETPKTBUFSIZE) {
955                 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n", br, NETPKTBUFSIZE);
956                 SDLNet_FreeSocketSet(socketset);
957                 SDLNet_TCP_Close(sock);
958                 exit(42);
959         }
960
961         bufToPacket(buf, &pkt);
962
963         if (pkt.cmd == NETCMD_NACK) {
964                 printf("CLIENT: Server forbid us from playing.\n");
965                 SDLNet_FreeSocketSet(socketset);
966                 SDLNet_TCP_Close(sock);
967                 exit(42);
968         }
969
970         if (pkt.cmd != NETCMD_ACK) {
971                 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
972                 SDLNet_FreeSocketSet(socketset);
973                 SDLNet_TCP_Close(sock);
974                 exit(42);
975         }
976
977         client_player_num = pkt.arg;
978         player[client_player_num].enabled = 1;
979         net_info[client_player_num].addr = addr;
980         printf("CLIENT: Server accepted our connection.\n");
981
982         wait_for_greenlight();
983 }
984 #endif /* USE_NET */
985
986
987 static void flip_pixels(unsigned char *pixels)
988 {
989         int x,y;
990         unsigned char temp;
991
992         assert(pixels);
993         for (y = 0; y < JNB_HEIGHT; y++) {
994                 for (x = 0; x < (352/2); x++) {
995                         temp = pixels[y*JNB_WIDTH+x];
996                         pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
997                         pixels[y*JNB_WIDTH+(352-x)-1] = temp;
998                 }
999         }
1000 }
1001
1002
1003 void get_closest_player_to_point(int x,int y,int *dist,int *closest_player)
1004 {
1005         int c1;
1006         int cur_dist = 0;
1007
1008         *dist = 0x7fff;
1009         for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1010                 if (player[c1].enabled == 1) {
1011                         cur_dist = (int)sqrt((x - ((player[c1].x >> 16) + 8)) * (x - ((player[c1].x >> 16) + 8)) + (y - ((player[c1].y >> 16) + 8)) * (y - ((player[c1].y >> 16) + 8)));
1012                         if (cur_dist < *dist) {
1013                                 *closest_player = c1;
1014                                 *dist = cur_dist;
1015                         }
1016                 }
1017         }
1018 }
1019
1020
1021 static void update_flies(int update_count)
1022 {
1023         int c1;
1024         int closest_player = 0, dist;
1025         int s1, s2, s3, s4;
1026
1027         /* get center of fly swarm */
1028         s1 = s2 = 0;
1029         for (c1 = 0; c1 < NUM_FLIES; c1++) {
1030                 s1 += flies[c1].x;
1031                 s2 += flies[c1].y;
1032         }
1033         s1 /= NUM_FLIES;
1034         s2 /= NUM_FLIES;
1035
1036         if (update_count == 1) {
1037                 /* get closest player to fly swarm */
1038                 get_closest_player_to_point(s1, s2, &dist, &closest_player);
1039                 /* update fly swarm sound */
1040                 s3 = 32 - dist / 3;
1041                 if (s3 < 0)
1042                         s3 = 0;
1043                 dj_set_sfx_channel_volume(4, (char)(s3));
1044         }
1045
1046         for (c1 = 0; c1 < NUM_FLIES; c1++) {
1047                 /* get closest player to fly */
1048                 get_closest_player_to_point(flies[c1].x, flies[c1].y, &dist, &closest_player);
1049                 flies[c1].old_x = flies[c1].x;
1050                 flies[c1].old_y = flies[c1].y;
1051                 s3 = 0;
1052                 if ((s1 - flies[c1].x) > 30)
1053                         s3 += 1;
1054                 else if ((s1 - flies[c1].x) < -30)
1055                         s3 -= 1;
1056                 if (dist < 30) {
1057                         if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1058                                 if (lord_of_the_flies == 0)
1059                                         s3 -= 1;
1060                                 else
1061                                         s3 += 1;
1062                         } else {
1063                                 if (lord_of_the_flies == 0)
1064                                         s3 += 1;
1065                                 else
1066                                         s3 -= 1;
1067                         }
1068                 }
1069                 s4 = rnd(3) - 1 + s3;
1070                 if ((flies[c1].x + s4) < 16)
1071                         s4 = 0;
1072                 if ((flies[c1].x + s4) > 351)
1073                         s4 = 0;
1074                 if (GET_BAN_MAP_XY(flies[c1].x + s4, flies[c1].y) != BAN_VOID)
1075                         s4 = 0;
1076                 flies[c1].x += s4;
1077                 s3 = 0;
1078                 if ((s2 - flies[c1].y) > 30)
1079                         s3 += 1;
1080                 else if ((s2 - flies[c1].y) < -30)
1081                         s3 -= 1;
1082                 if (dist < 30) {
1083                         if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1084                                 if (lord_of_the_flies == 0)
1085                                         s3 -= 1;
1086                                 else
1087                                         s3 += 1;
1088                         } else {
1089                                 if (lord_of_the_flies == 0)
1090                                         s3 += 1;
1091                                 else
1092                                         s3 -= 1;
1093                         }
1094                 }
1095                 s4 = rnd(3) - 1 + s3;
1096                 if ((flies[c1].y + s4) < 0)
1097                         s4 = 0;
1098                 if ((flies[c1].y + s4) > 239)
1099                         s4 = 0;
1100                 if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y + s4) != BAN_VOID)
1101                         s4 = 0;
1102                 flies[c1].y += s4;
1103         }
1104 }
1105
1106
1107 static void player_kill(int c1, int c2)
1108 {
1109         if (player[c1].y_add >= 0) {
1110                 if (is_server)
1111                         serverSendKillPacket(c1, c2);
1112         } else {
1113                 if (player[c2].y_add < 0)
1114                         player[c2].y_add = 0;
1115         }
1116 }
1117
1118
1119 static void check_cheats(void)
1120 {
1121         if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1122                 pogostick ^= 1;
1123                 last_keys[0] = 0;
1124         }
1125         if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1126                 bunnies_in_space ^= 1;
1127                 last_keys[0] = 0;
1128         }
1129         if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1130                 jetpack ^= 1;
1131                 last_keys[0] = 0;
1132         }
1133         if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1134                 lord_of_the_flies ^= 1;
1135                 last_keys[0] = 0;
1136         }
1137         if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1138                 char blood[32] = {
1139                         63,32,32,53,17,17,42, 7,
1140                          7,28, 0, 0,24, 0, 0,19,
1141                          0, 0,12, 0, 0, 7, 0, 0
1142                 };
1143                 char water[32] = {
1144                         63,63,63,40,53,62,19,42,
1145                         60, 0,33,60, 3,32,46, 3,
1146                         26,33, 3,19,21, 1, 8, 8
1147                 };
1148                 int i;
1149
1150                 blood_is_thicker_than_water ^= 1;
1151                 if (blood_is_thicker_than_water == 1) {
1152                         for (i=0; i<32; i++)
1153                                 pal[432+i] = blood[i];
1154                 } else {
1155                         for (i=0; i<32; i++)
1156                                 pal[432+i] = water[i];
1157                 }
1158                 register_background(background_pic, pal);
1159                 recalculate_gob(&object_gobs, pal);
1160                 last_keys[0] = 0;
1161         }
1162 }
1163
1164
1165 static void collision_check(void)
1166 {
1167         int c1 = 0, c2 = 0, c3 = 0;
1168         int l1;
1169
1170         /* collision check */
1171         for (c3 = 0; c3 < 6; c3++) {
1172                 if (c3 == 0) {
1173                         c1 = 0;
1174                         c2 = 1;
1175                 } else if (c3 == 1) {
1176                         c1 = 0;
1177                         c2 = 2;
1178                 } else if (c3 == 2) {
1179                         c1 = 0;
1180                         c2 = 3;
1181                 } else if (c3 == 3) {
1182                         c1 = 1;
1183                         c2 = 2;
1184                 } else if (c3 == 4) {
1185                         c1 = 1;
1186                         c2 = 3;
1187                 } else if (c3 == 5) {
1188                         c1 = 2;
1189                         c2 = 3;
1190                 }
1191                 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1192                         if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1193                                 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1194                                         if (player[c1].y < player[c2].y) {
1195                                                 player_kill(c1,c2);
1196                                         } else {
1197                                                 player_kill(c2,c1);
1198                                         }
1199                                 } else {
1200                                         if (player[c1].x < player[c2].x) {
1201                                                 if (player[c1].x_add > 0)
1202                                                         player[c1].x = player[c2].x - (12L << 16);
1203                                                 else if (player[c2].x_add < 0)
1204                                                         player[c2].x = player[c1].x + (12L << 16);
1205                                                 else {
1206                                                         player[c1].x -= player[c1].x_add;
1207                                                         player[c2].x -= player[c2].x_add;
1208                                                 }
1209                                                 l1 = player[c2].x_add;
1210                                                 player[c2].x_add = player[c1].x_add;
1211                                                 player[c1].x_add = l1;
1212                                                 if (player[c1].x_add > 0)
1213                                                         player[c1].x_add = -player[c1].x_add;
1214                                                 if (player[c2].x_add < 0)
1215                                                         player[c2].x_add = -player[c2].x_add;
1216                                         } else {
1217                                                 if (player[c1].x_add > 0)
1218                                                         player[c2].x = player[c1].x - (12L << 16);
1219                                                 else if (player[c2].x_add < 0)
1220                                                         player[c1].x = player[c2].x + (12L << 16);
1221                                                 else {
1222                                                         player[c1].x -= player[c1].x_add;
1223                                                         player[c2].x -= player[c2].x_add;
1224                                                 }
1225                                                 l1 = player[c2].x_add;
1226                                                 player[c2].x_add = player[c1].x_add;
1227                                                 player[c1].x_add = l1;
1228                                                 if (player[c1].x_add < 0)
1229                                                         player[c1].x_add = -player[c1].x_add;
1230                                                 if (player[c2].x_add > 0)
1231                                                         player[c2].x_add = -player[c2].x_add;
1232                                         }
1233                                 }
1234                         }
1235                 }
1236         }
1237 }
1238
1239 static void game_loop(void) {
1240         int mod_vol, sfx_vol;
1241         int update_count = 1;
1242         int end_loop_flag = 0;
1243         int fade_flag = 0;
1244         int update_palette = 0;
1245         int mod_fade_direction;
1246         int i;
1247
1248         mod_vol = sfx_vol = 0;
1249         mod_fade_direction = 1;
1250         dj_ready_mod(MOD_GAME);
1251         dj_set_mod_volume((char)mod_vol);
1252         dj_set_sfx_volume((char)mod_vol);
1253         dj_start_mod();
1254
1255         intr_sysupdate();
1256
1257         while (1) {
1258                 while (update_count) {
1259
1260                         if (key_pressed(1) == 1) {
1261 #ifdef USE_NET
1262                                 if (is_net) {
1263                                         if (is_server) {
1264                                                 serverTellEveryoneGoodbye();
1265                                         } else {
1266                                                 tellServerGoodbye();
1267                                         }
1268                                 }
1269 #endif
1270                                 end_loop_flag = 1;
1271                                 memset(pal, 0, 768);
1272                                 mod_fade_direction = 0;
1273                         }
1274
1275                         check_cheats();
1276
1277 #ifdef USE_NET
1278                         if (is_net) {
1279                                 if (is_server) {
1280                                         update_players_from_clients();
1281                                 } else {
1282                                         if (!update_players_from_server()) {
1283                                                 break;  /* got a BYE packet */
1284                                         }
1285                                 }
1286                         }
1287 #endif
1288
1289                         steer_players();
1290
1291                         dj_mix();
1292
1293                         collision_check();
1294
1295                         dj_mix();
1296
1297                         main_info.page_info[main_info.draw_page].num_pobs = 0;
1298                         for (i = 0; i < JNB_MAX_PLAYERS; i++) {
1299                                 if (player[i].enabled == 1)
1300                                         main_info.page_info[main_info.draw_page].num_pobs++;
1301                         }
1302
1303                         update_objects();
1304
1305                         dj_mix();
1306
1307                         if (flies_enabled) {
1308                                 update_flies(update_count);
1309                         }
1310
1311                         dj_mix();
1312
1313                         if (update_count == 1) {
1314                                 int c2;
1315
1316                                 for (i = 0, c2 = 0; i < JNB_MAX_PLAYERS; i++) {
1317                                         if (player[i].enabled == 1) {
1318                                                 main_info.page_info[main_info.draw_page].pobs[c2].x = player[i].x >> 16;
1319                                                 main_info.page_info[main_info.draw_page].pobs[c2].y = player[i].y >> 16;
1320                                                 main_info.page_info[main_info.draw_page].pobs[c2].image = player[i].image + i * 18;
1321                                                 main_info.page_info[main_info.draw_page].pobs[c2].pob_data = &rabbit_gobs;
1322                                                 c2++;
1323                                         }
1324                                 }
1325
1326                                 draw_begin();
1327
1328                                 draw_pobs(main_info.draw_page);
1329
1330                                 dj_mix();
1331
1332                                 if (flies_enabled)
1333                                         draw_flies(main_info.draw_page);
1334
1335                                 draw_end();
1336                         }
1337
1338                         if (mod_fade_direction == 1) {
1339                                 if (mod_vol < 30) {
1340                                         mod_vol++;
1341                                         dj_set_mod_volume((char)mod_vol);
1342                                 }
1343                                 if (sfx_vol < 64) {
1344                                         sfx_vol++;
1345                                         dj_set_sfx_volume((char)sfx_vol);
1346                                 }
1347                         } else {
1348                                 if (mod_vol > 0) {
1349                                         mod_vol--;
1350                                         dj_set_mod_volume((char)mod_vol);
1351                                 }
1352                                 if (sfx_vol > 0) {
1353                                         sfx_vol--;
1354                                         dj_set_sfx_volume((char)sfx_vol);
1355                                 }
1356                         }
1357
1358                         fade_flag = 0;
1359                         for (i = 0; i < 768; i++) {
1360                                 if (cur_pal[i] < pal[i]) {
1361                                         cur_pal[i]++;
1362                                         fade_flag = 1;
1363                                 } else if (cur_pal[i] > pal[i]) {
1364                                         cur_pal[i]--;
1365                                         fade_flag = 1;
1366                                 }
1367                         }
1368                         if (fade_flag == 1)
1369                                 update_palette = 1;
1370                         if (fade_flag == 0 && end_loop_flag == 1)
1371                                 break;
1372
1373                         if (update_count == 1) {
1374                                 if (update_palette == 1) {
1375                                         setpalette(0, 256, cur_pal);
1376                                         update_palette = 0;
1377                                 }
1378
1379                                 main_info.draw_page ^= 1;
1380                                 main_info.view_page ^= 1;
1381
1382                                 flippage(main_info.view_page);
1383
1384                                 wait_vrt(1);
1385
1386                                 draw_begin();
1387
1388                                 if (flies_enabled)
1389                                         redraw_flies_background(main_info.draw_page);
1390
1391                                 redraw_pob_backgrounds(main_info.draw_page);
1392
1393                                 draw_leftovers(main_info.draw_page);
1394
1395                                 draw_end();
1396                         }
1397
1398                         update_count--;
1399                 }
1400
1401 #ifdef USE_NET
1402                 if (is_net) {
1403                         if ( (player[client_player_num].dead_flag == 0) &&
1404                                 (
1405                                  (player[client_player_num].action_left) ||
1406                                  (player[client_player_num].action_right) ||
1407                                  (player[client_player_num].action_up) ||
1408                                  (player[client_player_num].jump_ready == 0)
1409                                 )
1410                            ) {
1411                                 tellServerNewPosition();
1412                         }
1413                 }
1414 #endif
1415
1416                 update_count = intr_sysupdate();
1417
1418 #ifdef USE_NET
1419                 if (is_net) {
1420                         if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1421                                 break;
1422                 } else
1423 #endif
1424                 if ((fade_flag == 0) && (end_loop_flag == 1))
1425                         break;
1426         }
1427 }
1428
1429
1430 static int menu_loop(void)
1431 {
1432         unsigned char *handle;
1433         int mod_vol;
1434         int c1, c2;
1435         int s1, s2;
1436
1437         for(c1 = 0; c1 < JNB_MAX_PLAYERS; c1++)         // reset player values
1438         {
1439                 ai[c1] = 0;
1440         }
1441
1442         while (1) {
1443
1444                 if (!is_net)
1445                         if (menu() != 0)
1446                                 deinit_program();
1447
1448                 if (key_pressed(1) == 1) {
1449                         return 0;
1450                 }
1451                 if (init_level(0, pal) != 0) {
1452                         deinit_level();
1453                         deinit_program();
1454                 }
1455
1456                 memset(cur_pal, 0, 768);
1457                 setpalette(0, 256, cur_pal);
1458
1459                 recalculate_gob(&rabbit_gobs, pal);
1460                 recalculate_gob(&object_gobs, pal);
1461                 recalculate_gob(&number_gobs, pal);
1462
1463                 flippage(1);
1464                 register_background(background_pic, pal);
1465                 flippage(0);
1466
1467                 if (flies_enabled) {
1468                         s1 = rnd(250) + 50;
1469                         s2 = rnd(150) + 50;
1470
1471                         for (c1 = 0; c1 < NUM_FLIES; c1++) {
1472                                 while (1) {
1473                                         flies[c1].x = s1 + rnd(101) - 50;
1474                                         flies[c1].y = s2 + rnd(101) - 50;
1475                                         if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y) == BAN_VOID)
1476                                                 break;
1477                                 }
1478                                 flies[c1].back_defined[0] = 0;
1479                                 flies[c1].back_defined[1] = 0;
1480                         }
1481                 }
1482
1483                 if (flies_enabled)
1484                         dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1485
1486                 dj_set_nosound(0);
1487
1488                 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1489                 main_info.page_info[0].num_pobs = 0;
1490                 main_info.page_info[1].num_pobs = 0;
1491                 main_info.view_page = 0;
1492                 main_info.draw_page = 1;
1493
1494                 game_loop();
1495
1496 #ifdef USE_NET
1497                 if (is_net) {
1498                         if (is_server) {
1499                                 serverTellEveryoneGoodbye();
1500                                 SDLNet_TCP_Close(sock);
1501                                 sock = NULL;
1502                         } else {
1503                                 if (!server_said_bye) {
1504                                         tellServerGoodbye();
1505                                 }
1506
1507                                 SDLNet_TCP_Close(sock);
1508                                 sock = NULL;
1509                         }
1510                 }
1511 #endif
1512
1513                 main_info.view_page = 0;
1514                 main_info.draw_page = 1;
1515
1516                 dj_stop_sfx_channel(4);
1517
1518                 deinit_level();
1519
1520                 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1521                 register_mask(mask_pic);
1522
1523                 register_background(NULL, NULL);
1524
1525                 draw_begin();
1526
1527                 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1528                 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1529                 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1530                 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1531                 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1532                 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1533                 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1534                 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1535
1536                 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1537                         char str1[100];
1538
1539                         for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1540                                 if (c2 != c1) {
1541                                         sprintf(str1, "%d", player[c1].bumped[c2]);
1542                                         put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1543                                 } else
1544                                         put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1545                         }
1546                         sprintf(str1, "%d", player[c1].bumps);
1547                         put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1548                 }
1549
1550                 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1551
1552                 draw_end();
1553
1554                 flippage(main_info.view_page);
1555
1556                 if ((handle = dat_open("menu.pcx")) == 0) {
1557                         strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1558                         return 1;
1559                 }
1560                 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1561                         strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1562                         return 1;
1563                 }
1564
1565                 /* fix dark font */
1566                 for (c1 = 0; c1 < 16; c1++) {
1567                         pal[(240 + c1) * 3 + 0] = c1 << 2;
1568                         pal[(240 + c1) * 3 + 1] = c1 << 2;
1569                         pal[(240 + c1) * 3 + 2] = c1 << 2;
1570                 }
1571
1572                 memset(cur_pal, 0, 768);
1573
1574                 setpalette(0, 256, cur_pal);
1575
1576                 mod_vol = 0;
1577                 dj_ready_mod(MOD_SCORES);
1578                 dj_set_mod_volume((char)mod_vol);
1579                 dj_start_mod();
1580                 dj_set_nosound(0);
1581
1582                 while (key_pressed(1) == 0) {
1583                         if (mod_vol < 35)
1584                                 mod_vol++;
1585                         dj_set_mod_volume((char)mod_vol);
1586                         for (c1 = 0; c1 < 768; c1++) {
1587                                 if (cur_pal[c1] < pal[c1])
1588                                         cur_pal[c1]++;
1589                         }
1590                         dj_mix();
1591                         intr_sysupdate();
1592                         wait_vrt(0);
1593                         setpalette(0, 256, cur_pal);
1594                         flippage(main_info.view_page);
1595                 }
1596                 while (key_pressed(1) == 1) {
1597                         dj_mix();
1598                         intr_sysupdate();
1599                 }
1600
1601                 memset(pal, 0, 768);
1602
1603                 while (mod_vol > 0) {
1604                         mod_vol--;
1605                         dj_set_mod_volume((char)mod_vol);
1606                         for (c1 = 0; c1 < 768; c1++) {
1607                                 if (cur_pal[c1] > pal[c1])
1608                                         cur_pal[c1]--;
1609                         }
1610                         dj_mix();
1611                         wait_vrt(0);
1612                         setpalette(0, 256, cur_pal);
1613                         flippage(main_info.view_page);
1614                 }
1615
1616                 fillpalette(0, 0, 0);
1617
1618                 dj_set_nosound(1);
1619                 dj_stop_mod();
1620
1621                 if (is_net)
1622                         return 0; /* don't go back to menu if in net game. */
1623         }
1624 }
1625
1626
1627 int main(int argc, char *argv[])
1628 {
1629         int result;
1630
1631         if (init_program(argc, argv, pal) != 0)
1632                 deinit_program();
1633
1634         if (main_info.fireworks == 1) {
1635                 fireworks();
1636                 deinit_program();
1637         }
1638
1639         result = menu_loop();
1640
1641         deinit_program();
1642
1643         return result;
1644 }
1645
1646
1647 static void player_action_left(int c1)
1648 {
1649         int s1 = 0, s2 = 0;
1650         int below_left, below, below_right;
1651
1652     s1 = (player[c1].x >> 16);
1653     s2 = (player[c1].y >> 16);
1654         below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1655         below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1656         below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1657
1658     if (below == BAN_ICE) {
1659         if (player[c1].x_add > 0)
1660             player[c1].x_add -= 1024;
1661         else
1662             player[c1].x_add -= 768;
1663     } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1664         if (player[c1].x_add > 0)
1665             player[c1].x_add -= 1024;
1666         else
1667             player[c1].x_add -= 768;
1668     } else {
1669         if (player[c1].x_add > 0) {
1670             player[c1].x_add -= 16384;
1671             if (player[c1].x_add > -98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1672                 add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0);
1673         } else
1674             player[c1].x_add -= 12288;
1675     }
1676     if (player[c1].x_add < -98304L)
1677         player[c1].x_add = -98304L;
1678     player[c1].direction = 1;
1679     if (player[c1].anim == 0) {
1680         player[c1].anim = 1;
1681         player[c1].frame = 0;
1682         player[c1].frame_tick = 0;
1683         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1684     }
1685 }
1686
1687
1688 static void player_action_right(int c1)
1689 {
1690         int s1 = 0, s2 = 0;
1691         int below_left, below, below_right;
1692
1693     s1 = (player[c1].x >> 16);
1694     s2 = (player[c1].y >> 16);
1695         below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1696         below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1697         below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1698
1699     if (below == BAN_ICE) {
1700         if (player[c1].x_add < 0)
1701             player[c1].x_add += 1024;
1702         else
1703             player[c1].x_add += 768;
1704     } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1705         if (player[c1].x_add > 0)
1706             player[c1].x_add += 1024;
1707         else
1708             player[c1].x_add += 768;
1709     } else {
1710         if (player[c1].x_add < 0) {
1711             player[c1].x_add += 16384;
1712             if (player[c1].x_add < 98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1713                 add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0);
1714         } else
1715             player[c1].x_add += 12288;
1716     }
1717     if (player[c1].x_add > 98304L)
1718         player[c1].x_add = 98304L;
1719     player[c1].direction = 0;
1720     if (player[c1].anim == 0) {
1721         player[c1].anim = 1;
1722         player[c1].frame = 0;
1723         player[c1].frame_tick = 0;
1724         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1725     }
1726 }
1727
1728 int map_tile(int pos_x, int pos_y)
1729 {
1730 int tile;
1731
1732 pos_x = pos_x >> 4;
1733 pos_y = pos_y >> 4;
1734
1735 if(pos_x < 0 || pos_x >= 17 || pos_y < 0 || pos_y >= 22)
1736   return BAN_VOID;
1737
1738 tile = ban_map[pos_y][pos_x];
1739 return tile;
1740 }
1741
1742 void cpu_move(void)
1743 {
1744         int lm, rm, jm;
1745         int i, j;
1746         int cur_posx, cur_posy, tar_posx, tar_posy;
1747         int players_distance;
1748         player_t* target = NULL;
1749         int nearest_distance = -1;
1750
1751         for (i = 0; i < JNB_MAX_PLAYERS; i++)
1752                 {
1753           nearest_distance = -1;
1754                 if(ai[i] && player[i].enabled)          // this player is a computer
1755                         {               // get nearest target
1756                         for (j = 0; j < JNB_MAX_PLAYERS; j++)
1757                                 {
1758                                 int deltax, deltay;
1759
1760                                 if(i == j || !player[j].enabled)
1761                                         continue;
1762
1763                                 deltax = player[j].x - player[i].x;
1764                                 deltay = player[j].y - player[i].y;
1765                                 players_distance = deltax*deltax + deltay*deltay;
1766
1767                                 if (players_distance < nearest_distance || nearest_distance == -1)
1768                                         {
1769                                         target = &player[j];
1770                                         nearest_distance = players_distance;
1771                                         }
1772                                 }
1773
1774                         if(target == NULL)
1775                                 continue;
1776
1777                         cur_posx = player[i].x >> 16;
1778                         cur_posy = player[i].y >> 16;
1779                         tar_posx = target->x >> 16;
1780                         tar_posy = target->y >> 16;
1781
1782                         /** nearest player found, get him */
1783                         /* here goes the artificial intelligence code */
1784
1785                         /* X-axis movement */
1786                         if(tar_posx > cur_posx)       // if true target is on the right side
1787                                 {    // go after him
1788                                 lm=0;
1789                                 rm=1;
1790                                 }
1791                         else    // target on the left side
1792                                 {
1793                                 lm=1;
1794                                 rm=0;
1795                                 }
1796
1797                         if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 &&
1798               tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32)
1799                                 {
1800                                 lm = !lm;
1801                                 rm = !rm;
1802                                 }
1803                         else if(tar_posx - cur_posx < 4+8 && tar_posx - cur_posx > -4)
1804                                 {      // makes the bunnies less "nervous"
1805                                 lm=0;
1806                                 lm=0;
1807                                 }
1808
1809                         /* Y-axis movement */
1810                         if(map_tile(cur_posx, cur_posy+16) != BAN_VOID &&
1811                                 ((i == 0 && key_pressed(KEY_PL1_JUMP)) ||
1812                                 (i == 1 && key_pressed(KEY_PL2_JUMP)) ||
1813                                 (i == 2 && key_pressed(KEY_PL3_JUMP)) ||
1814                                 (i == 3 && key_pressed(KEY_PL4_JUMP))))
1815                                         jm=0;   // if we are on ground and jump key is being pressed,
1816                                                                         //first we have to release it or else we won't be able to jump more than once
1817
1818                         else if(map_tile(cur_posx, cur_posy-8) != BAN_VOID &&
1819                                 map_tile(cur_posx, cur_posy-8) != BAN_WATER)
1820                                         jm=0;   // don't jump if there is something over it
1821
1822                         else if(map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_VOID &&
1823                                 map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_WATER &&
1824                                 cur_posx > 16 && cur_posx < 352-16-8)  // obstacle, jump
1825                                         jm=1;   // if there is something on the way, jump over it
1826
1827                         else if(((i == 0 && key_pressed(KEY_PL1_JUMP)) ||
1828                                                         (i == 1 && key_pressed(KEY_PL2_JUMP)) ||
1829                                                         (i == 2 && key_pressed(KEY_PL3_JUMP)) ||
1830                                                         (i == 3 && key_pressed(KEY_PL4_JUMP))) &&
1831                                                         (map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_VOID &&
1832                                                         map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_WATER))
1833                                         jm=1;   // this makes it possible to jump over 2 tiles
1834
1835                         else if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 &&
1836               tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32)  // don't jump - running away
1837                                 jm=0;
1838
1839                         else if(tar_posy <= cur_posy)   // target on the upper side
1840                                 jm=1;
1841                         else   // target below
1842                                 jm=0;
1843
1844                         /** Artificial intelligence done, now apply movements */
1845                         if(lm)
1846                                 {
1847                                 SDLKey key;
1848                                 if(i == 0)
1849                                         key = KEY_PL1_LEFT;
1850                                 else if(i == 1)
1851                                         key = KEY_PL2_LEFT;
1852                                 else if(i == 2)
1853                                         key = KEY_PL3_LEFT;
1854                                 else
1855                                         key = KEY_PL4_LEFT;
1856
1857                                 key &= 0x7f;
1858                                 addkey(key);
1859                                 }
1860                         else
1861                                 {
1862                                 SDLKey key;
1863                                 if(i == 0)
1864                                         key = KEY_PL1_LEFT;
1865                                 else if(i == 1)
1866                                         key = KEY_PL2_LEFT;
1867                                 else if(i == 2)
1868                                         key = KEY_PL3_LEFT;
1869                                 else
1870                                         key = KEY_PL4_LEFT;
1871
1872                                 key &= 0x7f;
1873                                 addkey(key | 0x8000);
1874                                 }
1875
1876                         if(rm)
1877                                 {
1878                                 SDLKey key;
1879                                 if(i == 0)
1880                                         key = KEY_PL1_RIGHT;
1881                                 else if(i == 1)
1882                                         key = KEY_PL2_RIGHT;
1883                                 else if(i == 2)
1884                                         key = KEY_PL3_RIGHT;
1885                                 else
1886                                         key = KEY_PL4_RIGHT;
1887
1888                                 key &= 0x7f;
1889                                 addkey(key);
1890                                 }
1891                         else
1892                                 {
1893                                 SDLKey key;
1894                                 if(i == 0)
1895                                         key = KEY_PL1_RIGHT;
1896                                 else if(i == 1)
1897                                         key = KEY_PL2_RIGHT;
1898                                 else if(i == 2)
1899                                         key = KEY_PL3_RIGHT;
1900                                 else
1901                                         key = KEY_PL4_RIGHT;
1902
1903                                 key &= 0x7f;
1904                                 addkey(key | 0x8000);
1905                                 }
1906
1907                         if(jm)
1908                                 {
1909                                 SDLKey key;
1910                                 if(i == 0)
1911                                         key = KEY_PL1_JUMP;
1912                                 else if(i == 1)
1913                                         key = KEY_PL2_JUMP;
1914                                 else if(i == 2)
1915                                         key = KEY_PL3_JUMP;
1916                                 else
1917                                         key = KEY_PL4_JUMP;
1918
1919                                 key &= 0x7f;
1920                                 addkey(key);
1921                                 }
1922                         else
1923                                 {
1924                                 SDLKey key;
1925                                 if(i == 0)
1926                                         key = KEY_PL1_JUMP;
1927                                 else if(i == 1)
1928                                         key = KEY_PL2_JUMP;
1929                                 else if(i == 2)
1930                                         key = KEY_PL3_JUMP;
1931                                 else
1932                                         key = KEY_PL4_JUMP;
1933
1934                                 key &= 0x7f;
1935                                 addkey(key | 0x8000);
1936                                 }
1937                         }
1938                 }
1939 }
1940
1941
1942 #define GET_BAN_MAP_IN_WATER(s1, s2) (GET_BAN_MAP_XY((s1), ((s2) + 7)) == BAN_VOID || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 7)) == BAN_VOID) && (GET_BAN_MAP_XY((s1), ((s2) + 8)) == BAN_WATER || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 8)) == BAN_WATER)
1943
1944
1945 void steer_players(void)
1946 {
1947         int c1, c2;
1948         int s1 = 0, s2 = 0;
1949
1950         cpu_move();
1951         update_player_actions();
1952
1953         for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1954
1955                 if (player[c1].enabled == 1) {
1956
1957                         if (player[c1].dead_flag == 0) {
1958
1959                                 if (player[c1].action_left && player[c1].action_right) {
1960                                         if (player[c1].direction == 0) {
1961                                                 if (player[c1].action_right) {
1962                                                         player_action_right(c1);
1963                                                 }
1964                                         } else {
1965                                                 if (player[c1].action_left) {
1966                                                         player_action_left(c1);
1967                                                 }
1968                                         }
1969                                 } else if (player[c1].action_left) {
1970                                         player_action_left(c1);
1971                                 } else if (player[c1].action_right) {
1972                                         player_action_right(c1);
1973                                 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1974                                         int below_left, below, below_right;
1975
1976                                         s1 = (player[c1].x >> 16);
1977                                         s2 = (player[c1].y >> 16);
1978                                         below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1979                                         below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1980                                         below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1981                                         if (below == BAN_SOLID || below == BAN_SPRING || (((below_left == BAN_SOLID || below_left == BAN_SPRING) && below_right != BAN_ICE) || (below_left != BAN_ICE && (below_right == BAN_SOLID || below_right == BAN_SPRING)))) {
1982                                                 if (player[c1].x_add < 0) {
1983                                                         player[c1].x_add += 16384;
1984                                                         if (player[c1].x_add > 0)
1985                                                                 player[c1].x_add = 0;
1986                                                 } else {
1987                                                         player[c1].x_add -= 16384;
1988                                                         if (player[c1].x_add < 0)
1989                                                                 player[c1].x_add = 0;
1990                                                 }
1991                                                 if (player[c1].x_add != 0 && GET_BAN_MAP_XY((s1 + 8), (s2 + 16)) == BAN_SOLID)
1992                                                         add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0);
1993                                         }
1994                                         if (player[c1].anim == 1) {
1995                                                 player[c1].anim = 0;
1996                                                 player[c1].frame = 0;
1997                                                 player[c1].frame_tick = 0;
1998                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1999                                         }
2000                                 }
2001                                 if (jetpack == 0) {
2002                                         /* no jetpack */
2003                                         if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
2004                                                 s1 = (player[c1].x >> 16);
2005                                                 s2 = (player[c1].y >> 16);
2006                                                 if (s2 < -16)
2007                                                         s2 = -16;
2008                                                 /* jump */
2009                                                 if (GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_ICE) {
2010                                                         player[c1].y_add = -280000L;
2011                                                         player[c1].anim = 2;
2012                                                         player[c1].frame = 0;
2013                                                         player[c1].frame_tick = 0;
2014                                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2015                                                         player[c1].jump_ready = 0;
2016                                                         player[c1].jump_abort = 1;
2017                                                         if (pogostick == 0)
2018                                                                 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2019                                                         else
2020                                                                 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2021                                                 }
2022                                                 /* jump out of water */
2023                                                 if (GET_BAN_MAP_IN_WATER(s1, s2)) {
2024                                                         player[c1].y_add = -196608L;
2025                                                         player[c1].in_water = 0;
2026                                                         player[c1].anim = 2;
2027                                                         player[c1].frame = 0;
2028                                                         player[c1].frame_tick = 0;
2029                                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2030                                                         player[c1].jump_ready = 0;
2031                                                         player[c1].jump_abort = 1;
2032                                                         if (pogostick == 0)
2033                                                                 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2034                                                         else
2035                                                                 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2036                                                 }
2037                                         }
2038                                         /* fall down by gravity */
2039                                         if (pogostick == 0 && (!player[c1].action_up)) {
2040                                                 player[c1].jump_ready = 1;
2041                                                 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
2042                                                         if (bunnies_in_space == 0)
2043                                                                 /* normal gravity */
2044                                                                 player[c1].y_add += 32768;
2045                                                         else
2046                                                                 /* light gravity */
2047                                                                 player[c1].y_add += 16384;
2048                                                         if (player[c1].y_add > 0)
2049                                                                 player[c1].y_add = 0;
2050                                                 }
2051                                         }
2052                                 } else {
2053                                         /* with jetpack */
2054                                         if (player[c1].action_up) {
2055                                                 player[c1].y_add -= 16384;
2056                                                 if (player[c1].y_add < -400000L)
2057                                                         player[c1].y_add = -400000L;
2058                                                 if (GET_BAN_MAP_IN_WATER(s1, s2))
2059                                                         player[c1].in_water = 0;
2060                                                 if (rnd(100) < 50)
2061                                                         add_object(OBJ_SMOKE, (player[c1].x >> 16) + 6 + rnd(5), (player[c1].y >> 16) + 10 + rnd(5), 0, 16384 + rnd(8192), OBJ_ANIM_SMOKE, 0);
2062                                         }
2063                                 }
2064
2065                                 player[c1].x += player[c1].x_add;
2066                                 if ((player[c1].x >> 16) < 0) {
2067                                         player[c1].x = 0;
2068                                         player[c1].x_add = 0;
2069                                 }
2070                                 if ((player[c1].x >> 16) + 15 > 351) {
2071                                         player[c1].x = 336L << 16;
2072                                         player[c1].x_add = 0;
2073                                 }
2074                                 {
2075                                         if (player[c1].y > 0) {
2076                                                 s2 = (player[c1].y >> 16);
2077                                         } else {
2078                                                 /* check top line only */
2079                                                 s2 = 0;
2080                                         }
2081
2082                                         s1 = (player[c1].x >> 16);
2083                                         if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) {
2084                                                 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
2085                                                 player[c1].x_add = 0;
2086                                         }
2087
2088                                         s1 = (player[c1].x >> 16);
2089                                         if (GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
2090                                                 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
2091                                                 player[c1].x_add = 0;
2092                                         }
2093                                 }
2094
2095                                 player[c1].y += player[c1].y_add;
2096
2097                                 s1 = (player[c1].x >> 16);
2098                                 s2 = (player[c1].y >> 16);
2099                                 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING || ((GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) != BAN_SOLID) || (GET_BAN_MAP_XY(s1, (s2 + 15)) != BAN_SOLID && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING))) {
2100                                         player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
2101                                         player[c1].y_add = -400000L;
2102                                         player[c1].anim = 2;
2103                                         player[c1].frame = 0;
2104                                         player[c1].frame_tick = 0;
2105                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2106                                         player[c1].jump_ready = 0;
2107                                         player[c1].jump_abort = 0;
2108                                         for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
2109                                                 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
2110                                                         if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING) {
2111                                                                 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2112                                                                         objects[c2].frame = 0;
2113                                                                         objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2114                                                                         objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2115                                                                         break;
2116                                                                 }
2117                                                         } else {
2118                                                                 if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) {
2119                                                                         if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2120                                                                                 objects[c2].frame = 0;
2121                                                                                 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2122                                                                                 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2123                                                                                 break;
2124                                                                         }
2125                                                                 } else if (GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
2126                                                                         if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2127                                                                                 objects[c2].frame = 0;
2128                                                                                 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2129                                                                                 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2130                                                                                 break;
2131                                                                         }
2132                                                                 }
2133                                                         }
2134                                                 }
2135                                         }
2136                                         dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2137                                 }
2138                                 s1 = (player[c1].x >> 16);
2139                                 s2 = (player[c1].y >> 16);
2140                                 if (s2 < 0)
2141                                         s2 = 0;
2142                                 if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING) {
2143                                         player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
2144                                         player[c1].y_add = 0;
2145                                         player[c1].anim = 0;
2146                                         player[c1].frame = 0;
2147                                         player[c1].frame_tick = 0;
2148                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2149                                 }
2150                                 s1 = (player[c1].x >> 16);
2151                                 s2 = (player[c1].y >> 16);
2152                                 if (s2 < 0)
2153                                         s2 = 0;
2154                                 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 8)) == BAN_WATER) {
2155                                         if (player[c1].in_water == 0) {
2156                                                 /* falling into water */
2157                                                 player[c1].in_water = 1;
2158                                                 player[c1].anim = 4;
2159                                                 player[c1].frame = 0;
2160                                                 player[c1].frame_tick = 0;
2161                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2162                                                 if (player[c1].y_add >= 32768) {
2163                                                         add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
2164                                                         if (blood_is_thicker_than_water == 0)
2165                                                                 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2166                                                         else
2167                                                                 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
2168                                                 }
2169                                         }
2170                                         /* slowly move up to water surface */
2171                                         player[c1].y_add -= 1536;
2172                                         if (player[c1].y_add < 0 && player[c1].anim != 5) {
2173                                                 player[c1].anim = 5;
2174                                                 player[c1].frame = 0;
2175                                                 player[c1].frame_tick = 0;
2176                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2177                                         }
2178                                         if (player[c1].y_add < -65536L)
2179                                                 player[c1].y_add = -65536L;
2180                                         if (player[c1].y_add > 65535L)
2181                                                 player[c1].y_add = 65535L;
2182                                         if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE) {
2183                                                 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2184                                                 player[c1].y_add = 0;
2185                                         }
2186                                 } else if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
2187                                         player[c1].in_water = 0;
2188                                         player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2189                                         player[c1].y_add = 0;
2190                                         if (player[c1].anim != 0 && player[c1].anim != 1) {
2191                                                 player[c1].anim = 0;
2192                                                 player[c1].frame = 0;
2193                                                 player[c1].frame_tick = 0;
2194                                                 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2195                                         }
2196                                 } else {
2197                                         if (player[c1].in_water == 0) {
2198                                                 if (bunnies_in_space == 0)
2199                                                         player[c1].y_add += 12288;
2200                                                 else
2201                                                         player[c1].y_add += 6144;
2202                                                 if (player[c1].y_add > 327680L)
2203                                                         player[c1].y_add = 327680L;
2204                                         } else {
2205                                                 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
2206                                                 player[c1].y_add = 0;
2207                                         }
2208                                         player[c1].in_water = 0;
2209                                 }
2210                                 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
2211                                         player[c1].anim = 3;
2212                                         player[c1].frame = 0;
2213                                         player[c1].frame_tick = 0;
2214                                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2215                                 }
2216
2217                         }
2218
2219                         player[c1].frame_tick++;
2220                         if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2221                                 player[c1].frame++;
2222                                 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2223                                         if (player[c1].anim != 6)
2224                                                 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2225                                         else
2226                                                 position_player(c1);
2227                                 }
2228                                 player[c1].frame_tick = 0;
2229                         }
2230                         player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2231
2232                 }
2233
2234         }
2235
2236 }
2237
2238
2239 void position_player(int player_num)
2240 {
2241         int c1;
2242         int s1, s2;
2243
2244         while (1) {
2245                 while (1) {
2246                         s1 = rnd(22);
2247                         s2 = rnd(16);
2248                         if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2249                                 break;
2250                 }
2251                 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2252                         if (c1 != player_num && player[c1].enabled == 1) {
2253                                 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2254                                         break;
2255                         }
2256                 }
2257                 if (c1 == JNB_MAX_PLAYERS) {
2258                         player[player_num].x = (long) s1 << 20;
2259                         player[player_num].y = (long) s2 << 20;
2260                         player[player_num].x_add = player[player_num].y_add = 0;
2261                         player[player_num].direction = 0;
2262                         player[player_num].jump_ready = 1;
2263                         player[player_num].in_water = 0;
2264                         player[player_num].anim = 0;
2265                         player[player_num].frame = 0;
2266                         player[player_num].frame_tick = 0;
2267                         player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2268
2269                         if (is_server) {
2270 #ifdef USE_NET
2271                                 if (is_net)
2272                                         serverSendAlive(player_num);
2273 #endif
2274                                 player[player_num].dead_flag = 0;
2275                         }
2276
2277                         break;
2278                 }
2279         }
2280
2281 }
2282
2283
2284 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2285 {
2286         int c1;
2287
2288         for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2289                 if (objects[c1].used == 0) {
2290                         objects[c1].used = 1;
2291                         objects[c1].type = type;
2292                         objects[c1].x = (long) x << 16;
2293                         objects[c1].y = (long) y << 16;
2294                         objects[c1].x_add = x_add;
2295                         objects[c1].y_add = y_add;
2296                         objects[c1].x_acc = 0;
2297                         objects[c1].y_acc = 0;
2298                         objects[c1].anim = anim;
2299                         objects[c1].frame = frame;
2300                         objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2301                         objects[c1].image = object_anims[anim].frame[frame].image;
2302                         break;
2303                 }
2304         }
2305
2306 }
2307
2308
2309 void update_objects(void)
2310 {
2311         int c1;
2312         int s1 = 0;
2313
2314         for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2315                 if (objects[c1].used == 1) {
2316                         switch (objects[c1].type) {
2317                         case OBJ_SPRING:
2318                                 objects[c1].ticks--;
2319                                 if (objects[c1].ticks <= 0) {
2320                                         objects[c1].frame++;
2321                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2322                                                 objects[c1].frame--;
2323                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2324                                         } else {
2325                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2326                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2327                                         }
2328                                 }
2329                                 if (objects[c1].used == 1)
2330                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2331                                 break;
2332                         case OBJ_SPLASH:
2333                                 objects[c1].ticks--;
2334                                 if (objects[c1].ticks <= 0) {
2335                                         objects[c1].frame++;
2336                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2337                                                 objects[c1].used = 0;
2338                                         else {
2339                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2340                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2341                                         }
2342                                 }
2343                                 if (objects[c1].used == 1)
2344                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2345                                 break;
2346                         case OBJ_SMOKE:
2347                                 objects[c1].x += objects[c1].x_add;
2348                                 objects[c1].y += objects[c1].y_add;
2349                                 objects[c1].ticks--;
2350                                 if (objects[c1].ticks <= 0) {
2351                                         objects[c1].frame++;
2352                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2353                                                 objects[c1].used = 0;
2354                                         else {
2355                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2356                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2357                                         }
2358                                 }
2359                                 if (objects[c1].used == 1)
2360                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2361                                 break;
2362                         case OBJ_YEL_BUTFLY:
2363                         case OBJ_PINK_BUTFLY:
2364                                 objects[c1].x_acc += rnd(128) - 64;
2365                                 if (objects[c1].x_acc < -1024)
2366                                         objects[c1].x_acc = -1024;
2367                                 if (objects[c1].x_acc > 1024)
2368                                         objects[c1].x_acc = 1024;
2369                                 objects[c1].x_add += objects[c1].x_acc;
2370                                 if (objects[c1].x_add < -32768)
2371                                         objects[c1].x_add = -32768;
2372                                 if (objects[c1].x_add > 32768)
2373                                         objects[c1].x_add = 32768;
2374                                 objects[c1].x += objects[c1].x_add;
2375                                 if ((objects[c1].x >> 16) < 16) {
2376                                         objects[c1].x = 16 << 16;
2377                                         objects[c1].x_add = -objects[c1].x_add >> 2;
2378                                         objects[c1].x_acc = 0;
2379                                 } else if ((objects[c1].x >> 16) > 350) {
2380                                         objects[c1].x = 350 << 16;
2381                                         objects[c1].x_add = -objects[c1].x_add >> 2;
2382                                         objects[c1].x_acc = 0;
2383                                 }
2384                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2385                                         if (objects[c1].x_add < 0) {
2386                                                 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2387                                         } else {
2388                                                 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2389                                         }
2390                                         objects[c1].x_add = -objects[c1].x_add >> 2;
2391                                         objects[c1].x_acc = 0;
2392                                 }
2393                                 objects[c1].y_acc += rnd(64) - 32;
2394                                 if (objects[c1].y_acc < -1024)
2395                                         objects[c1].y_acc = -1024;
2396                                 if (objects[c1].y_acc > 1024)
2397                                         objects[c1].y_acc = 1024;
2398                                 objects[c1].y_add += objects[c1].y_acc;
2399                                 if (objects[c1].y_add < -32768)
2400                                         objects[c1].y_add = -32768;
2401                                 if (objects[c1].y_add > 32768)
2402                                         objects[c1].y_add = 32768;
2403                                 objects[c1].y += objects[c1].y_add;
2404                                 if ((objects[c1].y >> 16) < 0) {
2405                                         objects[c1].y = 0;
2406                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2407                                         objects[c1].y_acc = 0;
2408                                 } else if ((objects[c1].y >> 16) > 255) {
2409                                         objects[c1].y = 255 << 16;
2410                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2411                                         objects[c1].y_acc = 0;
2412                                 }
2413                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2414                                         if (objects[c1].y_add < 0) {
2415                                                 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2416                                         } else {
2417                                                 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2418                                         }
2419                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2420                                         objects[c1].y_acc = 0;
2421                                 }
2422                                 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2423                                         if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2424                                                 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2425                                                 objects[c1].frame = 0;
2426                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2427                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2428                                         } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2429                                                 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2430                                                 objects[c1].frame = 0;
2431                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2432                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2433                                         }
2434                                 } else {
2435                                         if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2436                                                 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT;
2437                                                 objects[c1].frame = 0;
2438                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2439                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2440                                         } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) {
2441                                                 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT;
2442                                                 objects[c1].frame = 0;
2443                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2444                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2445                                         }
2446                                 }
2447                                 objects[c1].ticks--;
2448                                 if (objects[c1].ticks <= 0) {
2449                                         objects[c1].frame++;
2450                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2451                                                 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2452                                         else {
2453                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2454                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2455                                         }
2456                                 }
2457                                 if (objects[c1].used == 1)
2458                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2459                                 break;
2460                         case OBJ_FUR:
2461                                 if (rnd(100) < 30)
2462                                         add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2463                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2464                                         objects[c1].y_add += 3072;
2465                                         if (objects[c1].y_add > 196608L)
2466                                                 objects[c1].y_add = 196608L;
2467                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2468                                         if (objects[c1].x_add < 0) {
2469                                                 if (objects[c1].x_add < -65536L)
2470                                                         objects[c1].x_add = -65536L;
2471                                                 objects[c1].x_add += 1024;
2472                                                 if (objects[c1].x_add > 0)
2473                                                         objects[c1].x_add = 0;
2474                                         } else {
2475                                                 if (objects[c1].x_add > 65536L)
2476                                                         objects[c1].x_add = 65536L;
2477                                                 objects[c1].x_add -= 1024;
2478                                                 if (objects[c1].x_add < 0)
2479                                                         objects[c1].x_add = 0;
2480                                         }
2481                                         objects[c1].y_add += 1024;
2482                                         if (objects[c1].y_add < -65536L)
2483                                                 objects[c1].y_add = -65536L;
2484                                         if (objects[c1].y_add > 65536L)
2485                                                 objects[c1].y_add = 65536L;
2486                                 }
2487                                 objects[c1].x += objects[c1].x_add;
2488                                 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1 || ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3)) {
2489                                         if (objects[c1].x_add < 0) {
2490                                                 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2491                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2492                                         } else {
2493                                                 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2494                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2495                                         }
2496                                 }
2497                                 objects[c1].y += objects[c1].y_add;
2498                                 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2499                                         objects[c1].used = 0;
2500                                 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2501                                         if (objects[c1].y_add < 0) {
2502                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2503                                                         objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2504                                                         objects[c1].x_add >>= 2;
2505                                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2506                                                 }
2507                                         } else {
2508                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2509                                                         if (objects[c1].y_add > 131072L) {
2510                                                                 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2511                                                                 objects[c1].x_add >>= 2;
2512                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2513                                                         } else
2514                                                                 objects[c1].used = 0;
2515                                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2516                                                         objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2517                                                         if (objects[c1].y_add > 131072L)
2518                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2519                                                         else
2520                                                                 objects[c1].y_add = 0;
2521                                                 }
2522                                         }
2523                                 }
2524                                 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2525                                         objects[c1].x_add = -16384;
2526                                 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2527                                         objects[c1].x_add = 16384;
2528                                 if (objects[c1].used == 1) {
2529                                         s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2530                                         if (s1 < 0)
2531                                                 s1 += 8;
2532                                         if (s1 < 0)
2533                                                 s1 = 0;
2534                                         if (s1 > 7)
2535                                                 s1 = 7;
2536                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2537                                 }
2538                                 break;
2539                         case OBJ_FLESH:
2540                                 if (rnd(100) < 30) {
2541                                         if (objects[c1].frame == 76)
2542                                                 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2543                                         else if (objects[c1].frame == 77)
2544                                                 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2545                                         else if (objects[c1].frame == 78)
2546                                                 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2547                                 }
2548                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2549                                         objects[c1].y_add += 3072;
2550                                         if (objects[c1].y_add > 196608L)
2551                                                 objects[c1].y_add = 196608L;
2552                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2553                                         if (objects[c1].x_add < 0) {
2554                                                 if (objects[c1].x_add < -65536L)
2555                                                         objects[c1].x_add = -65536L;
2556                                                 objects[c1].x_add += 1024;
2557                                                 if (objects[c1].x_add > 0)
2558                                                         objects[c1].x_add = 0;
2559                                         } else {
2560                                                 if (objects[c1].x_add > 65536L)
2561                                                         objects[c1].x_add = 65536L;
2562                                                 objects[c1].x_add -= 1024;
2563                                                 if (objects[c1].x_add < 0)
2564                                                         objects[c1].x_add = 0;
2565                                         }
2566                                         objects[c1].y_add += 1024;
2567                                         if (objects[c1].y_add < -65536L)
2568                                                 objects[c1].y_add = -65536L;
2569                                         if (objects[c1].y_add > 65536L)
2570                                                 objects[c1].y_add = 65536L;
2571                                 }
2572                                 objects[c1].x += objects[c1].x_add;
2573                                 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1 || ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3)) {
2574                                         if (objects[c1].x_add < 0) {
2575                                                 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2576                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2577                                         } else {
2578                                                 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2579                                                 objects[c1].x_add = -objects[c1].x_add >> 2;
2580                                         }
2581                                 }
2582                                 objects[c1].y += objects[c1].y_add;
2583                                 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2584                                         objects[c1].used = 0;
2585                                 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2586                                         if (objects[c1].y_add < 0) {
2587                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2588                                                         objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2589                                                         objects[c1].x_add >>= 2;
2590                                                         objects[c1].y_add = -objects[c1].y_add >> 2;
2591                                                 }
2592                                         } else {
2593                                                 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2594                                                         if (objects[c1].y_add > 131072L) {
2595                                                                 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2596                                                                 objects[c1].x_add >>= 2;
2597                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2598                                                         } else {
2599                                                                 if (rnd(100) < 10) {
2600                                                                         s1 = rnd(4) - 2;
2601                                                                         add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2602                                                                         add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2603                                                                 }
2604                                                                 objects[c1].used = 0;
2605                                                         }
2606                                                 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2607                                                         objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2608                                                         if (objects[c1].y_add > 131072L)
2609                                                                 objects[c1].y_add = -objects[c1].y_add >> 2;
2610                                                         else
2611                                                                 objects[c1].y_add = 0;
2612                                                 }
2613                                         }
2614                                 }
2615                                 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2616                                         objects[c1].x_add = -16384;
2617                                 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2618                                         objects[c1].x_add = 16384;
2619                                 if (objects[c1].used == 1)
2620                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2621                                 break;
2622                         case OBJ_FLESH_TRACE:
2623                                 objects[c1].ticks--;
2624                                 if (objects[c1].ticks <= 0) {
2625                                         objects[c1].frame++;
2626                                         if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2627                                                 objects[c1].used = 0;
2628                                         else {
2629                                                 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2630                                                 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2631                                         }
2632                                 }
2633                                 if (objects[c1].used == 1)
2634                                         add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2635                                 break;
2636                         }
2637                 }
2638         }
2639
2640 }
2641
2642
2643 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2644 {
2645
2646         if (main_info.page_info[page].num_pobs >= NUM_POBS)
2647                 return 1;
2648
2649         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2650         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2651         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2652         main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2653         main_info.page_info[page].num_pobs++;
2654
2655         return 0;
2656
2657 }
2658
2659
2660 void draw_flies(int page)
2661 {
2662         int c2;
2663
2664         for (c2 = 0; c2 < NUM_FLIES; c2++) {
2665                 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2666                 flies[c2].back_defined[main_info.draw_page] = 1;
2667                 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2668                         set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2669         }
2670 }
2671
2672 void draw_pobs(int page)
2673 {
2674         int c1;
2675         int back_buf_ofs;
2676
2677         back_buf_ofs = 0;
2678
2679         for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2680                 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2681                 get_block(page, main_info.page_info[page].pobs[c1].x - pob_hs_x(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), main_info.page_info[page].pobs[c1].y - pob_hs_y(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), (unsigned char *)main_info.pob_backbuf[page] + back_buf_ofs);
2682                 if (scale_up)
2683                         back_buf_ofs += pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * 4;
2684                 else
2685                         back_buf_ofs += pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data);
2686                 put_pob(page, main_info.page_info[page].pobs[c1].x, main_info.page_info[page].pobs[c1].y, main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data, 1, mask_pic);
2687         }
2688
2689 }
2690
2691
2692 void redraw_flies_background(int page)
2693 {
2694         int c2;
2695
2696         for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2697                 if (flies[c2].back_defined[page] == 1)
2698                         set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2699                 flies[c2].old_draw_x = flies[c2].x;
2700                 flies[c2].old_draw_y = flies[c2].y;
2701         }
2702 }
2703
2704
2705 void redraw_pob_backgrounds(int page)
2706 {
2707         int c1;
2708
2709         for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2710                 put_block(page, main_info.page_info[page].pobs[c1].x - pob_hs_x(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), main_info.page_info[page].pobs[c1].y - pob_hs_y(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), (unsigned char *)main_info.pob_backbuf[page] + main_info.page_info[page].pobs[c1].back_buf_ofs);
2711
2712 }
2713
2714
2715 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2716 {
2717
2718         if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2719                 return 1;
2720
2721         leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2722         leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2723         leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2724         leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2725         leftovers.page[page].num_pobs++;
2726
2727         return 0;
2728
2729 }
2730
2731
2732 void draw_leftovers(int page)
2733 {
2734         int c1;
2735
2736         for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2737                 put_pob(page, leftovers.page[page].pobs[c1].x, leftovers.page[page].pobs[c1].y, leftovers.page[page].pobs[c1].image, leftovers.page[page].pobs[c1].pob_data, 1, mask_pic);
2738
2739         leftovers.page[page].num_pobs = 0;
2740
2741 }
2742
2743
2744 int init_level(int level, char *pal)
2745 {
2746         unsigned char *handle;
2747         int c1, c2;
2748         int s1, s2;
2749
2750         if ((handle = dat_open("level.pcx")) == 0) {
2751                 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2752                 return 1;
2753         }
2754         if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2755                 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2756                 return 1;
2757         }
2758         if (flip)
2759                 flip_pixels(background_pic);
2760         if ((handle = dat_open("mask.pcx")) == 0) {
2761                 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2762                 return 1;
2763         }
2764         if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2765                 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2766                 return 1;
2767         }
2768         if (flip)
2769                 flip_pixels(mask_pic);
2770         register_mask(mask_pic);
2771
2772         for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2773                 if (player[c1].enabled == 1) {
2774                         player[c1].bumps = 0;
2775                         for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2776                                 player[c1].bumped[c2] = 0;
2777                         position_player(c1);
2778                 }
2779         }
2780
2781         for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2782                 objects[c1].used = 0;
2783
2784         for (c1 = 0; c1 < 16; c1++) {
2785                 for (c2 = 0; c2 < 22; c2++) {
2786                         if (ban_map[c1][c2] == BAN_SPRING)
2787                                 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2788                 }
2789         }
2790
2791         while (1) {
2792                 s1 = rnd(22);
2793                 s2 = rnd(16);
2794                 if (ban_map[s2][s1] == BAN_VOID) {
2795                         add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2796                         break;
2797                 }
2798         }
2799         while (1) {
2800                 s1 = rnd(22);
2801                 s2 = rnd(16);
2802                 if (ban_map[s2][s1] == BAN_VOID) {
2803                         add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2804                         break;
2805                 }
2806         }
2807         while (1) {
2808                 s1 = rnd(22);
2809                 s2 = rnd(16);
2810                 if (ban_map[s2][s1] == BAN_VOID) {
2811                         add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2812                         break;
2813                 }
2814         }
2815         while (1) {
2816                 s1 = rnd(22);
2817                 s2 = rnd(16);
2818                 if (ban_map[s2][s1] == BAN_VOID) {
2819                         add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2820                         break;
2821                 }
2822         }
2823
2824         return 0;
2825
2826 }
2827
2828
2829 void deinit_level(void)
2830 {
2831         dj_set_nosound(1);
2832         dj_stop_mod();
2833 }
2834
2835
2836 #ifndef PATH_MAX
2837 #define PATH_MAX 1024
2838 #endif
2839 #ifndef O_BINARY
2840 #define O_BINARY 0
2841 #endif
2842
2843 unsigned char *datafile_buffer = NULL;
2844
2845 static void preread_datafile(const char *fname)
2846 {
2847     int fd = 0;
2848     int len;
2849
2850 #ifdef ZLIB_SUPPORT
2851     char *gzfilename;
2852     gzFile gzf;
2853 #endif
2854
2855 #ifdef BZLIB_SUPPORT
2856     char *bzfilename;
2857     BZFILE *bzf;
2858 #endif
2859
2860 #ifdef BZLIB_SUPPORT
2861     bzfilename = malloc(strlen(fname) + 5);
2862     strcpy(bzfilename, fname);
2863     strcat(bzfilename, ".bz2");
2864     bzf = BZ2_bzopen(bzfilename, "rb");
2865     free(bzfilename);
2866     bzfilename = NULL;
2867
2868     if (bzf != NULL) {
2869         int bufsize = 0;
2870         int bufpos = 0;
2871         int br;
2872         unsigned char *ptr;
2873         do {
2874             if (bufpos >= bufsize) {
2875                 bufsize += 1024 * 1024;
2876                 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2877                 if (datafile_buffer == NULL) {
2878                     perror("realloc()");
2879                     exit(42);
2880                 }
2881             }
2882
2883             br = BZ2_bzread(bzf, datafile_buffer + bufpos, bufsize - bufpos);
2884             if (br == -1) {
2885                 fprintf(stderr, "gzread failed.\n");
2886                 exit(42);
2887             }
2888
2889             bufpos += br;
2890         } while (br>0);
2891
2892         /* try to shrink buffer... */
2893         ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2894         if (ptr != NULL)
2895             datafile_buffer = ptr;
2896
2897         BZ2_bzclose(bzf);
2898         return;
2899     }
2900
2901     /* drop through and try for an gzip compressed or uncompressed datafile... */
2902 #endif
2903
2904 #ifdef ZLIB_SUPPORT
2905     gzfilename = malloc(strlen(fname) + 4);
2906     strcpy(gzfilename, fname);
2907     strcat(gzfilename, ".gz");
2908     gzf = gzopen(gzfilename, "rb");
2909     free(gzfilename);
2910     gzfilename = NULL;
2911
2912     if (gzf != NULL) {
2913         int bufsize = 0;
2914         int bufpos = 0;
2915         unsigned char *ptr;
2916         do {
2917             int br;
2918             if (bufpos >= bufsize) {
2919                 bufsize += 1024 * 1024;
2920                 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2921                 if (datafile_buffer == NULL) {
2922                     perror("realloc()");
2923                     exit(42);
2924                 }
2925             }
2926
2927             br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2928             if (br == -1) {
2929                 fprintf(stderr, "gzread failed.\n");
2930                 exit(42);
2931             }
2932
2933             bufpos += br;
2934         } while (!gzeof(gzf));
2935
2936         /* try to shrink buffer... */
2937         ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2938         if (ptr != NULL)
2939             datafile_buffer = ptr;
2940
2941         gzclose(gzf);
2942         return;
2943     }
2944
2945     /* drop through and try for an uncompressed datafile... */
2946 #endif
2947
2948     fd = open(fname, O_RDONLY | O_BINARY);
2949     if (fd == -1) {
2950         fprintf(stderr, "can't open %s:", fname);
2951         perror("");
2952         exit(42);
2953     }
2954
2955     len = filelength(fd);
2956     datafile_buffer = (unsigned char *) malloc(len);
2957     if (datafile_buffer == NULL) {
2958         perror("malloc()");
2959         close(fd);
2960         exit(42);
2961     }
2962
2963     if (read(fd, datafile_buffer, len) != len) {
2964         perror("read()");
2965         close(fd);
2966         exit(42);
2967     }
2968
2969     close(fd);
2970 }
2971
2972
2973 int init_program(int argc, char *argv[], char *pal)
2974 {
2975         char *netarg = NULL;
2976         unsigned char *handle = (unsigned char *) NULL;
2977         int c1 = 0, c2 = 0;
2978         int load_flag = 0;
2979         int force2, force3;
2980         sfx_data fly;
2981         int player_anim_data[] = {
2982                 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2983                 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2984                 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2985                 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2986                 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2987                 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2988                 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2989         };
2990
2991 #ifdef USE_NET
2992         memset(&net_info, 0, sizeof(net_info));
2993 #endif
2994
2995 #ifdef DOS
2996         if (__djgpp_nearptr_enable() == 0)
2997                 return 1;
2998 #endif
2999
3000         srand(time(NULL));
3001
3002         if (hook_keyb_handler() != 0)
3003                 return 1;
3004
3005         memset(&main_info, 0, sizeof(main_info));
3006
3007         strcpy(datfile_name, DATA_PATH);
3008
3009         force2 = force3 = 0;
3010
3011         if (argc > 1) {
3012                 for (c1 = 1; c1 < argc; c1++) {
3013                         if (stricmp(argv[c1], "-nosound") == 0)
3014                                 main_info.no_sound = 1;
3015                         else if (stricmp(argv[c1], "-musicnosound") == 0)
3016                                 main_info.music_no_sound = 1;
3017                         else if (stricmp(argv[c1], "-nogore") == 0)
3018                                 main_info.no_gore = 1;
3019                         else if (stricmp(argv[c1], "-noflies") == 0)
3020                                 flies_enabled = 0;
3021                         else if (stricmp(argv[c1], "-nojoy") == 0)
3022                                 main_info.joy_enabled = 0;
3023                         else if (stricmp(argv[c1], "-fireworks") == 0)
3024                                 main_info.fireworks = 1;
3025 #ifdef USE_SDL
3026                         else if (stricmp(argv[c1], "-fullscreen") == 0)
3027                                 fs_toggle();
3028 #endif
3029                         else if (stricmp(argv[c1], "-scaleup") == 0)
3030                                 set_scaling(1);
3031                         else if (stricmp(argv[c1], "-mirror") == 0)
3032                                 flip = 1;
3033                         else if (stricmp(argv[c1], "-dat") == 0) {
3034                                 if (c1 < (argc - 1)) {
3035                                         FILE *f;
3036
3037                                         if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
3038                                                 fclose(f);
3039                                                 strcpy(datfile_name, argv[c1 + 1]);
3040                                         }
3041                                 }
3042                         } else if (stricmp(argv[c1], "-player") == 0) {
3043                                 if (c1 < (argc - 1)) {
3044                                         if (client_player_num < 0)
3045                                                 client_player_num = atoi(argv[c1 + 1]);
3046                                 }
3047 #ifdef USE_NET
3048                         } else if (stricmp(argv[c1], "-server") == 0) {
3049                                 if (c1 < (argc - 1)) {
3050                                         is_server = 1;
3051                                         is_net = 1;
3052                                         netarg = argv[c1 + 1];
3053                                 }
3054                         } else if (stricmp(argv[c1], "-connect") == 0) {
3055                                 if (c1 < (argc - 1)) {
3056                                         is_server = 0;
3057                                         is_net = 1;
3058                                         netarg = argv[c1 + 1];
3059                                 }
3060 #endif
3061                         } else if (stricmp(argv[c1], "-mouse") == 0) {
3062                                 if (c1 < (argc - 1)) {
3063                                         if (stricmp(argv[c1 + 1], "2") == 0)
3064                                                 force2 = 1;
3065                                         if (stricmp(argv[c1 + 1], "3") == 0)
3066                                                 force3 = 1;
3067                                 }
3068                         }
3069                         else if (strstr(argv[1],"-v")) {
3070                                 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
3071 #ifndef USE_NET
3072                                 printf("out");
3073 #endif
3074                                 printf(" network support.\n");
3075                                 return 1;
3076                         }
3077                         else if (strstr(argv[1],"-h")) {
3078                                 printf("Usage: jumpnbump [OPTION]...\n");
3079                                 printf("\n");
3080                                 printf("  -h                       this help\n");
3081                                 printf("  -v                       print version\n");
3082                                 printf("  -dat level.dat           play a different level\n");
3083 #ifdef USE_NET
3084                                 printf("  -server playercount      start as server waiting for players\n");
3085                                 printf("  -connect host            connect to server\n");
3086 #endif
3087                                 printf("  -player num              set main player to num (0-3). Needed for networking\n");
3088                                 printf("  -fireworks               screensaver mode\n");
3089                                 printf("  -fullscreen              run in fullscreen mode\n");
3090                                 printf("  -nosound                 play without sound\n");
3091                                 printf("  -nogore                  play without blood\n");
3092                                 printf("  -noflies                 disable flies\n");
3093                                 printf("  -mirror                  play with mirrored level\n");
3094                                 printf("  -scaleup                 play with doubled resolution (800x512)\n");
3095                                 printf("  -musicnosound            play with music but without sound\n");
3096                                 printf("\n");
3097                                 return 1;
3098                         }
3099                 }
3100         }
3101
3102         preread_datafile(datfile_name);
3103
3104 #if 0
3105 /** It should not be necessary to assign a default player number here. The
3106 server assigns one in init_server, the client gets one assigned by the server,
3107 all provided the user didn't choose one on the commandline. */
3108         if (is_net) {
3109                 if (client_player_num < 0)
3110                         client_player_num = 0;
3111                 player[client_player_num].enabled = 1;
3112         }
3113 #endif
3114
3115         main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height);
3116         main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height);
3117
3118         for (c1 = 0; c1 < 7; c1++) {
3119                 player_anims[c1].num_frames = player_anim_data[c1 * 10];
3120                 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
3121                 for (c2 = 0; c2 < 4; c2++) {
3122                         player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
3123                         player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
3124                 }
3125         }
3126
3127         if ((handle = dat_open("menu.pcx")) == 0) {
3128                 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
3129                 return 1;
3130         }
3131         if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
3132                 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
3133                 return 1;
3134         }
3135
3136         if ((handle = dat_open("rabbit.gob")) == 0) {
3137                 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
3138                 return 1;
3139         }
3140         if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob"))) {
3141                 /* error */
3142                 return 1;
3143         }
3144
3145         if ((handle = dat_open("objects.gob")) == 0) {
3146                 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
3147                 return 1;
3148         }
3149         if (register_gob(handle, &object_gobs, dat_filelen("objects.gob"))) {
3150                 /* error */
3151                 return 1;
3152         }
3153
3154         if ((handle = dat_open("font.gob")) == 0) {
3155                 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
3156                 return 1;
3157         }
3158         if (register_gob(handle, &font_gobs, dat_filelen("font.gob"))) {
3159                 /* error */
3160                 return 1;
3161         }
3162
3163         if ((handle = dat_open("numbers.gob")) == 0) {
3164                 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
3165                 return 1;
3166         }
3167         if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob"))) {
3168                 /* error */
3169                 return 1;
3170         }
3171
3172         if (read_level() != 0) {
3173                 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3174                 return 1;
3175         }
3176
3177         dj_init();
3178
3179         if (main_info.no_sound == 0) {
3180                 dj_autodetect_sd();
3181                 dj_set_mixing_freq(20000);
3182                 dj_set_stereo(0);
3183                 dj_set_auto_mix(0);
3184                 dj_set_dma_time(8);
3185                 dj_set_num_sfx_channels(5);
3186                 dj_set_sfx_volume(64);
3187                 dj_set_nosound(1);
3188                 dj_start();
3189
3190                 if ((handle = dat_open("jump.mod")) == 0) {
3191                         strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
3192                         return 1;
3193                 }
3194                 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
3195                         strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
3196                         return 1;
3197                 }
3198
3199                 if ((handle = dat_open("bump.mod")) == 0) {
3200                         strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
3201                         return 1;
3202                 }
3203                 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
3204                         strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
3205                         return 1;
3206                 }
3207
3208                 if ((handle = dat_open("scores.mod")) == 0) {
3209                         strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3210                         return 1;
3211                 }
3212                 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
3213                         strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3214                         return 1;
3215                 }
3216
3217                 if ((handle = dat_open("jump.smp")) == 0) {
3218                         strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3219                         return 1;
3220                 }
3221                 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp"), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
3222                         strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3223                         return 1;
3224                 }
3225
3226                 if ((handle = dat_open("death.smp")) == 0) {
3227                         strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3228                         return 1;
3229                 }
3230                 if (dj_load_sfx(handle, 0, dat_filelen("death.smp"), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
3231                         strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3232                         return 1;
3233                 }
3234
3235                 if ((handle = dat_open("spring.smp")) == 0) {
3236                         strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3237                         return 1;
3238                 }
3239                 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp"), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
3240                         strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3241                         return 1;
3242                 }
3243
3244                 if ((handle = dat_open("splash.smp")) == 0) {
3245                         strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3246                         return 1;
3247                 }
3248                 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp"), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
3249                         strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3250                         return 1;
3251                 }
3252
3253                 if ((handle = dat_open("fly.smp")) == 0) {
3254                         strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3255                         return 1;
3256                 }
3257                 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp"), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
3258                         strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3259                         return 1;
3260                 }
3261
3262                 dj_get_sfx_settings(SFX_FLY, &fly);
3263                 fly.priority = 10;
3264                 fly.default_freq = SFX_FLY_FREQ;
3265                 fly.loop = 1;
3266                 fly.loop_start = 0;
3267                 fly.loop_length = fly.length;
3268 &nbs