Merge branch 'feature/handle-quit-event'
[jumpnbump.git] / main.c
blob2db1f1820ea689a02b0d9477f7eaca217ab4d717
1 /*
2 * main.c
3 * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
4 *
5 * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
7 * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
9 * This file is part of Jump'n'Bump.
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.
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.
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
26 #include "globals.h"
27 #include <fcntl.h>
28 #ifndef _MSC_VER
29 #include <unistd.h>
30 #endif
32 #ifdef USE_NET
33 #include "SDL_net.h"
34 #endif /* USE_NET */
36 #ifndef M_PI
37 #define M_PI 3.14159265358979323846
38 #endif
40 gob_t rabbit_gobs = { 0 };
41 gob_t font_gobs = { 0 };
42 gob_t object_gobs = { 0 };
43 gob_t number_gobs = { 0 };
45 main_info_t main_info;
46 player_t player[JNB_MAX_PLAYERS];
47 player_anim_t player_anims[7];
48 object_t objects[NUM_OBJECTS];
49 joy_t joy;
50 mouse_t mouse;
52 char datfile_name[2048];
54 char *background_pic;
55 char *mask_pic;
56 int flip = 0;
58 int ai[JNB_MAX_PLAYERS];
60 unsigned int ban_map[17][22] = {
61 {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
62 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},
63 {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
64 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
65 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
66 {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
67 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
68 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
69 {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
70 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1},
71 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
72 {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1},
73 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
74 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
75 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1},
76 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
77 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
80 struct {
81 int num_frames;
82 int restart_frame;
83 struct {
84 int image;
85 int ticks;
86 } frame[10];
87 } object_anims[8] = {
89 6, 0, {
91 0, 3}, {
92 1, 3}, {
93 2, 3}, {
94 3, 3}, {
95 4, 3}, {
96 5, 3}, {
97 0, 0}, {
98 0, 0}, {
99 0, 0}, {
100 0, 0}
102 }, {
103 9, 0, {
105 6, 2}, {
106 7, 2}, {
107 8, 2}, {
108 9, 2}, {
109 10, 2}, {
110 11, 2}, {
111 12, 2}, {
112 13, 2}, {
113 14, 2}, {
114 0, 0}
116 }, {
117 5, 0, {
119 15, 3}, {
120 16, 3}, {
121 16, 3}, {
122 17, 3}, {
123 18, 3}, {
124 19, 3}, {
125 0, 0}, {
126 0, 0}, {
127 0, 0}, {
128 0, 0}
130 }, {
131 10, 0, {
133 20, 2}, {
134 21, 2}, {
135 22, 2}, {
136 23, 2}, {
137 24, 2}, {
138 25, 2}, {
139 24, 2}, {
140 23, 2}, {
141 22, 2}, {
142 21, 2}
144 }, {
145 10, 0, {
147 26, 2}, {
148 27, 2}, {
149 28, 2}, {
150 29, 2}, {
151 30, 2}, {
152 31, 2}, {
153 30, 2}, {
154 29, 2}, {
155 28, 2}, {
156 27, 2}
158 }, {
159 10, 0, {
161 32, 2}, {
162 33, 2}, {
163 34, 2}, {
164 35, 2}, {
165 36, 2}, {
166 37, 2}, {
167 36, 2}, {
168 35, 2}, {
169 34, 2}, {
170 33, 2}
172 }, {
173 10, 0, {
175 38, 2}, {
176 39, 2}, {
177 40, 2}, {
178 41, 2}, {
179 42, 2}, {
180 43, 2}, {
181 42, 2}, {
182 41, 2}, {
183 40, 2}, {
184 39, 2}
186 }, {
187 4, 0, {
189 76, 4}, {
190 77, 4}, {
191 78, 4}, {
192 79, 4}, {
193 0, 0}, {
194 0, 0}, {
195 0, 0}, {
196 0, 0}, {
197 0, 0}, {
198 0, 0}
203 int flies_enabled = 1;
205 struct {
206 int x, y;
207 int old_x, old_y;
208 int old_draw_x, old_draw_y;
209 int back[2];
210 int back_defined[2];
211 } flies[NUM_FLIES];
213 struct {
214 struct {
215 short num_pobs;
216 struct {
217 int x, y;
218 int image;
219 gob_t *pob_data;
220 } pobs[NUM_LEFTOVERS];
221 } page[2];
222 } leftovers;
224 int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water;
227 #ifndef _MSC_VER
228 int filelength(int handle)
230 struct stat buf;
232 if (fstat(handle, &buf) == -1) {
233 perror("filelength");
234 exit(EXIT_FAILURE);
237 return buf.st_size;
239 #endif
242 /* networking shite. */
244 int client_player_num = -1;
245 int is_server = 1;
246 int is_net = 0;
248 #ifdef USE_NET
249 TCPsocket sock = NULL;
250 SDLNet_SocketSet socketset = NULL;
252 typedef struct
254 TCPsocket sock;
255 IPaddress addr;
256 SDLNet_SocketSet socketset;
257 } NetInfo;
259 NetInfo net_info[JNB_MAX_PLAYERS];
260 #endif
262 typedef struct
264 unsigned long cmd;
265 long arg;
266 long arg2;
267 long arg3;
268 long arg4;
269 } NetPacket;
271 #define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4)
273 #define NETCMD_NACK (0xF00DF00D + 0)
274 #define NETCMD_ACK (0xF00DF00D + 1)
275 #define NETCMD_HELLO (0xF00DF00D + 2)
276 #define NETCMD_GREENLIGHT (0xF00DF00D + 3)
277 #define NETCMD_MOVE (0xF00DF00D + 4)
278 #define NETCMD_BYE (0xF00DF00D + 5)
279 #define NETCMD_POSITION (0xF00DF00D + 6)
280 #define NETCMD_ALIVE (0xF00DF00D + 7)
281 #define NETCMD_KILL (0xF00DF00D + 8)
284 #ifdef USE_NET
285 void bufToPacket(const char *buf, NetPacket *pkt)
287 SDLNet_Write32(*((Uint32*) (buf + 0)), &pkt->cmd);
288 SDLNet_Write32(*((Uint32*) (buf + 4)), &pkt->arg);
289 SDLNet_Write32(*((Uint32*) (buf + 8)), &pkt->arg2);
290 SDLNet_Write32(*((Uint32*) (buf + 12)), &pkt->arg3);
291 SDLNet_Write32(*((Uint32*) (buf + 16)), &pkt->arg4);
293 pkt->cmd = ntohl(*((unsigned long *) (buf + 0)));
294 pkt->arg = (long) ntohl(*((unsigned long *) (buf + 4)));
295 pkt->arg2 = (long) ntohl(*((unsigned long *) (buf + 8)));
296 pkt->arg3 = (long) ntohl(*((unsigned long *) (buf + 12)));
297 pkt->arg4 = (long) ntohl(*((unsigned long *) (buf + 16)));
302 void packetToBuf(const NetPacket *pkt, char *buf)
304 *((Uint32*) (buf + 0)) = SDLNet_Read32(&pkt->cmd);
305 *((Uint32*) (buf + 4)) = SDLNet_Read32(&pkt->arg);
306 *((Uint32*) (buf + 8)) = SDLNet_Read32(&pkt->arg2);
307 *((Uint32*) (buf + 12)) = SDLNet_Read32(&pkt->arg3);
308 *((Uint32*) (buf + 16)) = SDLNet_Read32(&pkt->arg4);
310 *((unsigned long *) (buf + 0)) = htonl(pkt->cmd);
311 *((unsigned long *) (buf + 4)) = htonl((unsigned long) pkt->arg);
312 *((unsigned long *) (buf + 8)) = htonl((unsigned long) pkt->arg2);
313 *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3);
314 *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4);
319 void sendPacketToSock(TCPsocket s, NetPacket *pkt)
321 int bytes_left = NETPKTBUFSIZE;
322 int bw;
323 char buf[NETPKTBUFSIZE];
324 char *ptr = buf;
326 packetToBuf(pkt, buf);
327 while (bytes_left > 0) {
328 bw = SDLNet_TCP_Send(s, ptr, bytes_left);
329 if (bw < 0) {
330 fprintf(stderr, "SERVER: SDLNet_TCP_Send(): %s\n", SDLNet_GetError());
331 SDLNet_TCP_Close(s);
332 exit(42);
333 } else if (bw == 0) {
334 SDL_Delay(1);
335 } else {
336 bytes_left -= bw;
337 ptr += bw;
343 void sendPacket(int playerid, NetPacket *pkt)
345 if ( (playerid < JNB_MAX_PLAYERS) && (playerid >= 0)) {
346 if ((player[playerid].enabled) && (playerid != client_player_num)) {
347 sendPacketToSock(net_info[playerid].sock, pkt);
353 void sendPacketToAll(NetPacket *pkt)
355 int i;
357 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
358 sendPacket(i, pkt);
362 /** read a packet from the given TCPsocket
363 Returns -1 if some error occured, 0 if there was no data available and 1 if a
364 packet was successfully read.
365 Note: the socket has to be in the supplied socketset.
366 TODO: this function will bomb if a packet arrives in pieces, there is no
367 inherent guarantee that the next call will be made on the same socket. */
368 int grabPacket(TCPsocket s, SDLNet_SocketSet ss, NetPacket *pkt)
370 static char buf[NETPKTBUFSIZE];
371 static int buf_count = 0;
372 int rc;
374 if (SDLNet_CheckSockets(ss, 0) <= 0)
375 return 0;
377 if(!SDLNet_SocketReady(s))
378 return 0;
380 rc = SDLNet_TCP_Recv(s, &buf[buf_count], NETPKTBUFSIZE - buf_count);
381 if (rc <= 0) {
382 /* closed connection? */
383 return -1;
384 } else if (rc != NETPKTBUFSIZE) {
385 /* we got a partial packet. Store what we got in the static buffer and
386 return so that the next call can read the rest. Hopefully. */
387 buf_count = rc;
388 return 0;
389 } else {
390 buf_count = 0;
391 bufToPacket(buf, pkt);
392 return 1;
397 int serverRecvPacket(NetPacket *pkt)
399 int rc;
400 int i;
402 assert(is_server);
404 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
405 TCPsocket s = net_info[i].sock;
407 if ((i == client_player_num) || (!player[i].enabled))
408 continue;
410 rc = grabPacket(s, net_info[i].socketset, pkt);
411 if (rc < 0) {
412 NetPacket pkt;
414 player[i].enabled = 0;
415 SDLNet_TCP_Close(s);
416 pkt.cmd = NETCMD_BYE;
417 pkt.arg = i;
418 pkt.arg2 = 0;
419 pkt.arg3 = 0;
420 pkt.arg4 = 0;
421 sendPacketToAll(&pkt);
422 } else if (rc > 0) {
423 return(i); /* it's all good. */
427 return(-1); /* no packets available currently. */
431 void wait_for_greenlight(void)
433 NetPacket pkt;
434 int i;
436 printf("CLIENT: Waiting for greenlight...\n");
438 do {
439 int rc;
440 while ((rc = grabPacket(sock, socketset, &pkt)) == 0) {
441 SDL_Delay(100); /* nap and then try again. */
444 if (rc < 0) {
445 printf("CLIENT: Lost connection.\n");
446 SDLNet_TCP_Close(sock);
447 exit(42);
449 } while (pkt.cmd != NETCMD_GREENLIGHT);
451 printf("CLIENT: Got greenlight.\n");
453 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
454 if (pkt.arg & (1 << i)) {
455 printf("CLIENT: There is a player #%d.\n", i);
456 player[i].enabled = 1;
462 static int buggered_off = 0;
465 void tellServerGoodbye(void)
467 NetPacket pkt;
469 if (!buggered_off) {
470 buggered_off = 1;
471 pkt.cmd = NETCMD_BYE;
472 pkt.arg = client_player_num;
473 pkt.arg2 = 0;
474 pkt.arg3 = 0;
475 pkt.arg4 = 0;
476 sendPacketToSock(sock, &pkt);
479 #endif /* USE_NET */
482 void processMovePacket(NetPacket *pkt)
484 int playerid = pkt->arg;
485 int movetype = ((pkt->arg2 >> 16) & 0xFF);
486 int newval = ((pkt->arg2 >> 0) & 0xFF);
488 if (movetype == MOVEMENT_LEFT) {
489 player[playerid].action_left = newval;
490 } else if (movetype == MOVEMENT_RIGHT) {
491 player[playerid].action_right = newval;
492 } else if (movetype == MOVEMENT_UP) {
493 player[playerid].action_up = newval;
494 } else {
495 printf("bogus MOVE packet!\n");
498 player[playerid].x = pkt->arg3;
499 player[playerid].y = pkt->arg4;
503 void tellServerPlayerMoved(int playerid, int movement_type, int newval)
505 NetPacket pkt;
507 pkt.cmd = NETCMD_MOVE;
508 pkt.arg = playerid;
509 pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) );
510 pkt.arg3 = player[playerid].x;
511 pkt.arg4 = player[playerid].y;
513 if (is_server) {
514 processMovePacket(&pkt);
515 #ifdef USE_NET
516 if (is_net)
517 sendPacketToAll(&pkt);
518 } else {
519 sendPacketToSock(sock, &pkt);
520 #endif
525 #ifdef USE_NET
526 void tellServerNewPosition(void)
528 NetPacket pkt;
529 pkt.cmd = NETCMD_POSITION;
530 pkt.arg = client_player_num;
531 pkt.arg2 = player[client_player_num].x;
532 pkt.arg3 = player[client_player_num].y;
534 if (is_server) {
535 sendPacketToAll(&pkt);
536 } else {
537 sendPacketToSock(sock, &pkt);
540 #endif /* USE_NET */
543 void processKillPacket(NetPacket *pkt)
545 int c1 = pkt->arg;
546 int c2 = pkt->arg2;
547 int x = pkt->arg3;
548 int y = pkt->arg4;
549 int c4 = 0;
550 int s1 = 0;
552 player[c1].y_add = -player[c1].y_add;
553 if (player[c1].y_add > -262144L)
554 player[c1].y_add = -262144L;
555 player[c1].jump_abort = 1;
556 player[c2].dead_flag = 1;
557 if (player[c2].anim != 6) {
558 player[c2].anim = 6;
559 player[c2].frame = 0;
560 player[c2].frame_tick = 0;
561 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
562 if (main_info.no_gore == 0) {
563 for (c4 = 0; c4 < 6; c4++)
564 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);
565 for (c4 = 0; c4 < 6; c4++)
566 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76);
567 for (c4 = 0; c4 < 6; c4++)
568 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77);
569 for (c4 = 0; c4 < 8; c4++)
570 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78);
571 for (c4 = 0; c4 < 10; c4++)
572 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
574 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
575 player[c1].bumps++;
576 player[c1].bumped[c2]++;
577 s1 = player[c1].bumps % 100;
578 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
579 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
580 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
581 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
586 #ifdef USE_NET
587 void processPositionPacket(NetPacket *pkt)
589 int playerid = pkt->arg;
591 player[playerid].x = pkt->arg2;
592 player[playerid].y = pkt->arg3;
596 void processAlivePacket(NetPacket *pkt)
598 int playerid = pkt->arg;
600 player[playerid].dead_flag = 0;
601 player[playerid].x = pkt->arg2;
602 player[playerid].y = pkt->arg3;
606 void serverTellEveryoneGoodbye(void)
608 int i;
610 if (!buggered_off) {
611 buggered_off = 1;
612 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
613 if (player[i].enabled) {
614 NetPacket pkt;
616 pkt.cmd = NETCMD_BYE;
617 pkt.arg = i;
618 pkt.arg2 = 0;
619 pkt.arg3 = 0;
620 pkt.arg4 = 0;
621 sendPacketToAll(&pkt);
628 int server_said_bye = 0;
631 int update_players_from_server(void)
633 NetPacket pkt;
634 int rc;
636 assert(!is_server);
638 while ((rc = grabPacket(sock, socketset, &pkt)) != 0) {
639 if (rc < 0) {
640 printf("CLIENT: Lost connection.\n");
641 pkt.cmd = NETCMD_BYE;
642 pkt.arg = client_player_num;
645 if (pkt.cmd == NETCMD_BYE) {
646 if (pkt.arg == client_player_num) {
647 SDLNet_FreeSocketSet(socketset);
648 SDLNet_TCP_Close(sock);
649 sock = NULL;
650 server_said_bye = 1;
651 return(0);
652 } else {
653 player[pkt.arg].enabled = 0;
655 } else if (pkt.cmd == NETCMD_MOVE) {
656 processMovePacket(&pkt);
657 } else if (pkt.cmd == NETCMD_ALIVE) {
658 processAlivePacket(&pkt);
659 } else if (pkt.cmd == NETCMD_POSITION) {
660 processPositionPacket(&pkt);
661 } else if (pkt.cmd == NETCMD_KILL) {
662 processKillPacket(&pkt);
663 } else {
664 printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
668 return(1);
672 void serverSendAlive(int playerid)
674 NetPacket pkt;
676 assert(is_server);
677 pkt.cmd = NETCMD_ALIVE;
678 pkt.arg = playerid;
679 pkt.arg2 = player[playerid].x;
680 pkt.arg3 = player[playerid].y;
681 sendPacketToAll(&pkt);
683 #endif /* USE_NET */
686 void serverSendKillPacket(int killer, int victim)
688 NetPacket pkt;
690 assert(is_server);
691 pkt.cmd = NETCMD_KILL;
692 pkt.arg = killer;
693 pkt.arg2 = victim;
694 pkt.arg3 = player[victim].x;
695 pkt.arg4 = player[victim].y;
696 processKillPacket(&pkt);
697 #ifdef USE_NET
698 if (is_net)
699 sendPacketToAll(&pkt);
700 #endif
704 #ifdef USE_NET
705 void update_players_from_clients(void)
707 int i;
708 NetPacket pkt;
709 int playerid;
711 assert(is_server);
713 while ((playerid = serverRecvPacket(&pkt)) >= 0) {
714 if (pkt.cmd == NETCMD_BYE) {
715 pkt.arg = playerid; /* just in case. */
716 sendPacketToAll(&pkt);
717 player[playerid].enabled = 0;
718 SDLNet_FreeSocketSet(net_info[playerid].socketset);
719 SDLNet_TCP_Close(net_info[playerid].sock);
720 } else if (pkt.cmd == NETCMD_POSITION) {
721 pkt.arg = playerid; /* just in case. */
722 processPositionPacket(&pkt);
723 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
724 if (i != playerid) {
725 sendPacket(i, &pkt);
728 } else if (pkt.cmd == NETCMD_MOVE) {
729 pkt.arg = playerid; /* just in case. */
731 pkt.arg3 = player[playerid].x;
732 pkt.arg4 = player[playerid].y;
734 processMovePacket(&pkt);
735 sendPacketToAll(&pkt);
736 } else {
737 printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
743 void init_server(const char *netarg)
745 NetPacket pkt;
746 IPaddress addr;
747 int i;
748 int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
749 char *ipstr;
751 /** assign player number zero as default for the server */
752 if(-1 == client_player_num)
753 client_player_num = 0;
755 if ((wait_for_clients >= JNB_MAX_PLAYERS) || (wait_for_clients < 0)) {
756 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
757 exit(42);
760 if (SDLNet_Init() < 0) {
761 exit(42);
763 atexit(SDLNet_Quit);
765 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
766 ipstr = SDLNet_ResolveIP(&addr);
767 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
768 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);
769 net_info[client_player_num].addr = addr;
771 addr.host = INADDR_ANY;
772 sock = SDLNet_TCP_Open(&addr);
773 if (sock == NULL) {
774 fprintf(stderr, "SERVER: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
775 exit(42);
778 player[client_player_num].enabled = 1;
780 printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
782 socketset = SDLNet_AllocSocketSet(JNB_MAX_PLAYERS + 1);
783 SDLNet_TCP_AddSocket(socketset, sock);
785 while (wait_for_clients > 0)
787 char buf[NETPKTBUFSIZE];
788 IPaddress *from;
789 int negatory = 1;
790 int br;
791 TCPsocket s;
793 /* Wait for events */
794 SDLNet_CheckSockets(socketset, ~0);
795 if ( SDLNet_SocketReady(sock) ) {
796 s = SDLNet_TCP_Accept(sock);
798 if (s == NULL)
800 fprintf(stderr, "SERVER: SDLNet_TCP_Accept(): %s", SDLNet_GetError());
801 SDLNet_TCP_Close(sock);
802 exit(42);
804 } else
805 continue;
807 br = SDLNet_TCP_Recv(s, buf, NETPKTBUFSIZE);
808 if (br < 0) {
809 fprintf(stderr, "SERVER: SDLNet_TCP_Recv(): %s\n", SDLNet_GetError());
810 SDLNet_TCP_Close(s);
811 SDLNet_TCP_Close(sock);
812 exit(42);
815 from = SDLNet_TCP_GetPeerAddress(s);
816 ipstr = SDLNet_ResolveIP(from);
817 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);
819 if (br != NETPKTBUFSIZE) {
820 printf("SERVER: Bogus packet.\n");
821 continue;
824 bufToPacket(buf, &pkt);
825 if (pkt.cmd != NETCMD_HELLO) {
826 printf("SERVER: Bogus packet.\n");
827 continue;
830 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
832 if (-1 == pkt.arg) {
833 int i;
834 for(i=0; i!=JNB_MAX_PLAYERS; ++i) {
835 if(!player[i].enabled) {
836 printf("SERVER: assigning %d as player number\n", i);
837 pkt.arg = i;
838 break;
843 if ((pkt.arg>=JNB_MAX_PLAYERS)||(pkt.arg<0)) {
844 printf("SERVER: (that's an invalid player number.)\n");
845 } else if (player[pkt.arg].enabled) {
846 printf("SERVER: (that player number is already taken.)\n");
847 } else {
848 negatory = 0;
851 if (negatory) {
852 printf("SERVER: Forbidding connection.\n");
853 pkt.cmd = NETCMD_NACK;
854 sendPacketToSock(s, &pkt);
855 SDLNet_TCP_Close(s);
856 } else {
857 player[pkt.arg].enabled = 1;
858 net_info[pkt.arg].sock = s;
859 net_info[pkt.arg].addr = *from;
860 net_info[pkt.arg].socketset = SDLNet_AllocSocketSet(1);
861 SDLNet_TCP_AddSocket(net_info[pkt.arg].socketset, net_info[pkt.arg].sock);
862 wait_for_clients--;
863 printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
864 pkt.cmd = NETCMD_ACK;
865 sendPacket(pkt.arg, &pkt);
869 SDLNet_TCP_Close(sock); /* done with the listen socket. */
870 SDLNet_FreeSocketSet(socketset);
871 sock = NULL;
872 socketset = NULL;
874 printf("SERVER: Got all our connections. Greenlighting clients...\n");
876 pkt.cmd = NETCMD_GREENLIGHT;
877 pkt.arg = 0;
878 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
879 if (player[i].enabled) {
880 pkt.arg |= (1 << i);
883 sendPacketToAll(&pkt);
887 void connect_to_server(char *netarg)
889 NetPacket pkt;
890 char buf[NETPKTBUFSIZE];
891 char *ipstr;
892 IPaddress hent;
893 IPaddress addr;
894 int br;
896 if (netarg == NULL) {
897 printf("CLIENT: Need to specify host to connect to.\n");
898 exit(42);
901 if (SDLNet_Init() < 0) {
902 exit(42);
904 atexit(SDLNet_Quit);
906 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
907 ipstr = SDLNet_ResolveIP(&addr);
908 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
909 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);
911 if (SDLNet_ResolveHost(&hent, netarg, JNB_INETPORT) < 0) {
912 fprintf(stderr, "CLIENT: couldn't find host: %s\n", SDLNet_GetError());
913 exit(42);
916 sock = SDLNet_TCP_Open(&hent);
917 if (sock == NULL) {
918 fprintf(stderr, "CLIENT: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
919 exit(42);
922 socketset = SDLNet_AllocSocketSet(1);
923 SDLNet_TCP_AddSocket(socketset, sock);
925 printf("CLIENT: connected to %s...\n", SDLNet_ResolveIP(&hent));
927 printf("CLIENT: Sending HELLO packet...\n");
928 pkt.cmd = NETCMD_HELLO;
929 pkt.arg = client_player_num;
930 sendPacketToSock(sock, &pkt);
932 printf("CLIENT: Waiting for ACK from server...\n");
934 br = SDLNet_TCP_Recv(sock, buf, NETPKTBUFSIZE);
935 if (br < 0) {
936 fprintf(stderr, "CLIENT: recv(): %s\n", SDLNet_GetError());
937 SDLNet_FreeSocketSet(socketset);
938 SDLNet_TCP_Close(sock);
939 exit(42);
942 if (br != NETPKTBUFSIZE) {
943 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n", br, NETPKTBUFSIZE);
944 SDLNet_FreeSocketSet(socketset);
945 SDLNet_TCP_Close(sock);
946 exit(42);
949 bufToPacket(buf, &pkt);
951 if (pkt.cmd == NETCMD_NACK) {
952 printf("CLIENT: Server forbid us from playing.\n");
953 SDLNet_FreeSocketSet(socketset);
954 SDLNet_TCP_Close(sock);
955 exit(42);
958 if (pkt.cmd != NETCMD_ACK) {
959 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
960 SDLNet_FreeSocketSet(socketset);
961 SDLNet_TCP_Close(sock);
962 exit(42);
965 client_player_num = pkt.arg;
966 player[client_player_num].enabled = 1;
967 net_info[client_player_num].addr = addr;
968 printf("CLIENT: Server accepted our connection.\n");
970 wait_for_greenlight();
972 #endif /* USE_NET */
975 static void flip_pixels(unsigned char *pixels)
977 int x,y;
978 unsigned char temp;
980 assert(pixels);
981 for (y = 0; y < JNB_HEIGHT; y++) {
982 for (x = 0; x < (352/2); x++) {
983 temp = pixels[y*JNB_WIDTH+x];
984 pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
985 pixels[y*JNB_WIDTH+(352-x)-1] = temp;
991 int main(int argc, char *argv[])
993 unsigned char *handle;
994 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
995 int l1;
996 int s1, s2, s3, s4;
997 int closest_player = 0, dist, cur_dist = 0;
998 int end_loop_flag = 0, fade_flag = 0;
999 int mod_vol, sfx_vol, mod_fade_direction;
1000 char str1[100];
1001 char pal[768];
1002 char cur_pal[768];
1003 int update_count;
1004 int i;
1006 if (init_program(argc, argv, pal) != 0)
1007 deinit_program();
1009 if (main_info.fireworks == 1) {
1010 fireworks();
1011 deinit_program();
1014 for(i = 0; i < JNB_MAX_PLAYERS; i++) // reset player values
1016 ai[i] = 0;
1019 while (1) {
1021 if (!is_net)
1022 if (menu() != 0)
1023 deinit_program();
1025 if (key_pressed(1) == 1) {
1026 break;
1028 if (init_level(0, pal) != 0) {
1029 deinit_level();
1030 deinit_program();
1033 memset(cur_pal, 0, 768);
1034 setpalette(0, 256, cur_pal);
1036 recalculate_gob(&rabbit_gobs, pal);
1037 recalculate_gob(&object_gobs, pal);
1038 recalculate_gob(&number_gobs, pal);
1040 flippage(1);
1041 register_background(background_pic, pal);
1042 flippage(0);
1044 if (flies_enabled) {
1045 s1 = rnd(250) + 50;
1046 s2 = rnd(150) + 50;
1048 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1049 while (1) {
1050 flies[c1].x = s1 + rnd(101) - 50;
1051 flies[c1].y = s2 + rnd(101) - 50;
1052 if (ban_map[flies[c1].y >> 4][flies[c1].x >> 4] == BAN_VOID)
1053 break;
1055 flies[c1].back_defined[0] = 0;
1056 flies[c1].back_defined[1] = 0;
1060 mod_vol = sfx_vol = 10;
1061 mod_fade_direction = 1;
1062 dj_ready_mod(MOD_GAME);
1063 dj_set_mod_volume((char)mod_vol);
1064 dj_set_sfx_volume((char)mod_vol);
1065 dj_start_mod();
1067 if (flies_enabled)
1068 dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1070 dj_set_nosound(0);
1072 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1073 end_loop_flag = 0;
1074 main_info.page_info[0].num_pobs = 0;
1075 main_info.page_info[1].num_pobs = 0;
1076 main_info.view_page = 0;
1077 main_info.draw_page = 1;
1079 update_count = 1;
1080 while (1) {
1081 while (update_count) {
1083 if (key_pressed(1) == 1) {
1084 #ifdef USE_NET
1085 if (is_net) {
1086 if (is_server) {
1087 serverTellEveryoneGoodbye();
1088 } else {
1089 tellServerGoodbye();
1092 #endif
1093 end_loop_flag = 1;
1094 memset(pal, 0, 768);
1095 mod_fade_direction = 0;
1098 if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1099 pogostick ^= 1;
1100 last_keys[0] = 0;
1102 if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1103 bunnies_in_space ^= 1;
1104 last_keys[0] = 0;
1106 if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1107 jetpack ^= 1;
1108 last_keys[0] = 0;
1110 if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1111 lord_of_the_flies ^= 1;
1112 last_keys[0] = 0;
1114 if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1115 blood_is_thicker_than_water ^= 1;
1116 if (blood_is_thicker_than_water == 1) {
1117 pal[432] = 63;
1118 pal[433] = 32;
1119 pal[434] = 32;
1120 pal[435] = 53;
1121 pal[436] = 17;
1122 pal[437] = 17;
1123 pal[438] = 42;
1124 pal[439] = 7;
1125 pal[440] = 7;
1126 pal[441] = 28;
1127 pal[442] = 0;
1128 pal[443] = 0;
1129 pal[444] = 24;
1130 pal[445] = 0;
1131 pal[446] = 0;
1132 pal[447] = 19;
1133 pal[448] = 0;
1134 pal[449] = 0;
1135 pal[450] = 12;
1136 pal[451] = 0;
1137 pal[452] = 0;
1138 pal[453] = 7;
1139 pal[454] = 0;
1140 pal[455] = 0;
1141 } else {
1142 pal[432] = 63;
1143 pal[433] = 63;
1144 pal[434] = 63;
1145 pal[435] = 40;
1146 pal[436] = 53;
1147 pal[437] = 62;
1148 pal[438] = 19;
1149 pal[439] = 42;
1150 pal[440] = 60;
1151 pal[441] = 0;
1152 pal[442] = 33;
1153 pal[443] = 60;
1154 pal[444] = 3;
1155 pal[445] = 32;
1156 pal[446] = 46;
1157 pal[447] = 3;
1158 pal[448] = 26;
1159 pal[449] = 33;
1160 pal[450] = 3;
1161 pal[451] = 19;
1162 pal[452] = 21;
1163 pal[453] = 1;
1164 pal[454] = 8;
1165 pal[455] = 8;
1167 register_background(background_pic, pal);
1168 recalculate_gob(&object_gobs, pal);
1169 last_keys[0] = 0;
1172 #ifdef USE_NET
1173 if (is_net) {
1174 if (is_server) {
1175 update_players_from_clients();
1176 } else {
1177 if (!update_players_from_server()) {
1178 break; /* got a BYE packet */
1182 #endif
1184 steer_players();
1186 dj_mix();
1188 for (c3 = 0; c3 < 6; c3++) {
1189 if (c3 == 0) {
1190 c1 = 0;
1191 c2 = 1;
1192 } else if (c3 == 1) {
1193 c1 = 0;
1194 c2 = 2;
1195 } else if (c3 == 2) {
1196 c1 = 0;
1197 c2 = 3;
1198 } else if (c3 == 3) {
1199 c1 = 1;
1200 c2 = 2;
1201 } else if (c3 == 4) {
1202 c1 = 1;
1203 c2 = 3;
1204 } else if (c3 == 5) {
1205 c1 = 2;
1206 c2 = 3;
1208 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1209 if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1210 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1211 if (player[c1].y < player[c2].y) {
1212 if (player[c1].y_add >= 0) {
1213 if (is_server)
1214 serverSendKillPacket(c1, c2);
1215 } else {
1216 if (player[c2].y_add < 0)
1217 player[c2].y_add = 0;
1219 } else {
1220 if (player[c2].y_add >= 0) {
1221 if (is_server)
1222 serverSendKillPacket(c2, c1);
1223 } else {
1224 if (player[c1].y_add < 0)
1225 player[c1].y_add = 0;
1228 } else {
1229 if (player[c1].x < player[c2].x) {
1230 if (player[c1].x_add > 0)
1231 player[c1].x = player[c2].x - (12L << 16);
1232 else if (player[c2].x_add < 0)
1233 player[c2].x = player[c1].x + (12L << 16);
1234 else {
1235 player[c1].x -= player[c1].x_add;
1236 player[c2].x -= player[c2].x_add;
1238 l1 = player[c2].x_add;
1239 player[c2].x_add = player[c1].x_add;
1240 player[c1].x_add = l1;
1241 if (player[c1].x_add > 0)
1242 player[c1].x_add = -player[c1].x_add;
1243 if (player[c2].x_add < 0)
1244 player[c2].x_add = -player[c2].x_add;
1245 } else {
1246 if (player[c1].x_add > 0)
1247 player[c2].x = player[c1].x - (12L << 16);
1248 else if (player[c2].x_add < 0)
1249 player[c1].x = player[c2].x + (12L << 16);
1250 else {
1251 player[c1].x -= player[c1].x_add;
1252 player[c2].x -= player[c2].x_add;
1254 l1 = player[c2].x_add;
1255 player[c2].x_add = player[c1].x_add;
1256 player[c1].x_add = l1;
1257 if (player[c1].x_add < 0)
1258 player[c1].x_add = -player[c1].x_add;
1259 if (player[c2].x_add > 0)
1260 player[c2].x_add = -player[c2].x_add;
1267 dj_mix();
1269 main_info.page_info[main_info.draw_page].num_pobs = 0;
1270 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1271 if (player[c1].enabled == 1)
1272 main_info.page_info[main_info.draw_page].num_pobs++;
1275 update_objects();
1277 dj_mix();
1279 if (flies_enabled) {
1280 /* get center of fly swarm */
1281 s1 = s2 = 0;
1282 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1283 s1 += flies[c1].x;
1284 s2 += flies[c1].y;
1286 s1 /= NUM_FLIES;
1287 s2 /= NUM_FLIES;
1289 if (update_count == 1) {
1290 /* get closest player to fly swarm */
1291 dist = 0x7fff;
1292 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1293 if (player[c1].enabled == 1) {
1294 cur_dist = (int)sqrt((s1 - ((player[c1].x >> 16) + 8)) * (s1 - ((player[c1].x >> 16) + 8)) + (s2 - ((player[c1].y >> 16) + 8)) * (s2 - ((player[c1].y >> 16) + 8)));
1295 if (cur_dist < dist) {
1296 closest_player = c1;
1297 dist = cur_dist;
1301 /* update fly swarm sound */
1302 s3 = 32 - dist / 3;
1303 if (s3 < 0)
1304 s3 = 0;
1305 dj_set_sfx_channel_volume(4, (char)(s3));
1308 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1309 /* get closest player to fly */
1310 dist = 0x7fff;
1311 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1312 if (player[c2].enabled == 1) {
1313 cur_dist = (int)sqrt((flies[c1].x - ((player[c2].x >> 16) + 8)) * (flies[c1].x - ((player[c2].x >> 16) + 8)) + (flies[c1].y - ((player[c2].y >> 16) + 8)) * (flies[c1].y - ((player[c2].y >> 16) + 8)));
1314 if (cur_dist < dist) {
1315 closest_player = c2;
1316 dist = cur_dist;
1320 flies[c1].old_x = flies[c1].x;
1321 flies[c1].old_y = flies[c1].y;
1322 s3 = 0;
1323 if ((s1 - flies[c1].x) > 30)
1324 s3 += 1;
1325 else if ((s1 - flies[c1].x) < -30)
1326 s3 -= 1;
1327 if (dist < 30) {
1328 if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1329 if (lord_of_the_flies == 0)
1330 s3 -= 1;
1331 else
1332 s3 += 1;
1333 } else {
1334 if (lord_of_the_flies == 0)
1335 s3 += 1;
1336 else
1337 s3 -= 1;
1340 s4 = rnd(3) - 1 + s3;
1341 if ((flies[c1].x + s4) < 16)
1342 s4 = 0;
1343 if ((flies[c1].x + s4) > 351)
1344 s4 = 0;
1345 if (ban_map[flies[c1].y >> 4][(flies[c1].x + s4) >> 4] != BAN_VOID)
1346 s4 = 0;
1347 flies[c1].x += s4;
1348 s3 = 0;
1349 if ((s2 - flies[c1].y) > 30)
1350 s3 += 1;
1351 else if ((s2 - flies[c1].y) < -30)
1352 s3 -= 1;
1353 if (dist < 30) {
1354 if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1355 if (lord_of_the_flies == 0)
1356 s3 -= 1;
1357 else
1358 s3 += 1;
1359 } else {
1360 if (lord_of_the_flies == 0)
1361 s3 += 1;
1362 else
1363 s3 -= 1;
1366 s4 = rnd(3) - 1 + s3;
1367 if ((flies[c1].y + s4) < 0)
1368 s4 = 0;
1369 if ((flies[c1].y + s4) > 239)
1370 s4 = 0;
1371 if (ban_map[(flies[c1].y + s4) >> 4][flies[c1].x >> 4] != BAN_VOID)
1372 s4 = 0;
1373 flies[c1].y += s4;
1377 dj_mix();
1379 s1 = 0;
1380 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1381 if (player[c1].enabled == 1) {
1382 main_info.page_info[main_info.draw_page].pobs[s1].x = player[c1].x >> 16;
1383 main_info.page_info[main_info.draw_page].pobs[s1].y = player[c1].y >> 16;
1384 main_info.page_info[main_info.draw_page].pobs[s1].image = player[c1].image + c1 * 18;
1385 main_info.page_info[main_info.draw_page].pobs[s1].pob_data = &rabbit_gobs;
1386 s1++;
1390 if (update_count == 1) {
1391 draw_begin();
1393 draw_pobs(main_info.draw_page);
1395 dj_mix();
1397 if (flies_enabled)
1398 draw_flies(main_info.draw_page);
1400 draw_end();
1403 if (mod_fade_direction == 1) {
1404 if (mod_vol < 30) {
1405 mod_vol++;
1406 dj_set_mod_volume((char)mod_vol);
1408 } else {
1409 if (mod_vol > 0) {
1410 mod_vol--;
1411 dj_set_mod_volume((char)mod_vol);
1415 if (mod_fade_direction == 1) {
1416 if (sfx_vol < 64) {
1417 sfx_vol++;
1418 dj_set_sfx_volume((char)sfx_vol);
1420 } else {
1421 if (sfx_vol > 0) {
1422 sfx_vol--;
1423 dj_set_sfx_volume((char)sfx_vol);
1427 fade_flag = 0;
1428 for (c1 = 0; c1 < 768; c1++) {
1429 if (cur_pal[c1] < pal[c1]) {
1430 cur_pal[c1]++;
1431 fade_flag = 1;
1432 } else if (cur_pal[c1] > pal[c1]) {
1433 cur_pal[c1]--;
1434 fade_flag = 1;
1437 if (fade_flag == 0 && end_loop_flag == 1)
1438 break;
1440 if (update_count == 1) {
1441 main_info.draw_page ^= 1;
1442 main_info.view_page ^= 1;
1444 flippage(main_info.view_page);
1446 wait_vrt(1);
1449 if (fade_flag == 1)
1450 setpalette(0, 256, cur_pal);
1452 if (update_count == 1) {
1453 draw_begin();
1455 if (flies_enabled)
1456 redraw_flies_background(main_info.draw_page);
1458 redraw_pob_backgrounds(main_info.draw_page);
1460 draw_leftovers(main_info.draw_page);
1462 draw_end();
1465 update_count--;
1468 #ifdef USE_NET
1469 if (is_net) {
1470 if ( (player[client_player_num].dead_flag == 0) &&
1472 (player[client_player_num].action_left) ||
1473 (player[client_player_num].action_right) ||
1474 (player[client_player_num].action_up) ||
1475 (player[client_player_num].jump_ready == 0)
1478 tellServerNewPosition();
1481 #endif
1483 update_count = intr_sysupdate();
1485 #ifdef USE_NET
1486 if (is_net) {
1487 if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1488 break;
1489 } else
1490 #endif
1491 if ((fade_flag == 0) && (end_loop_flag == 1))
1492 break;
1495 #ifdef USE_NET
1496 if (is_net) {
1497 if (is_server) {
1498 serverTellEveryoneGoodbye();
1499 SDLNet_TCP_Close(sock);
1500 sock = NULL;
1501 } else {
1502 if (!server_said_bye) {
1503 tellServerGoodbye();
1506 SDLNet_TCP_Close(sock);
1507 sock = NULL;
1510 #endif
1512 main_info.view_page = 0;
1513 main_info.draw_page = 1;
1515 dj_stop_sfx_channel(4);
1517 deinit_level();
1519 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1520 register_mask(mask_pic);
1522 register_background(NULL, NULL);
1524 draw_begin();
1526 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1527 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1528 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1529 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1530 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1531 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1532 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1533 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1535 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1536 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1537 if (c2 != c1) {
1538 sprintf(str1, "%d", player[c1].bumped[c2]);
1539 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1540 } else
1541 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1543 sprintf(str1, "%d", player[c1].bumps);
1544 put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1547 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1549 draw_end();
1551 flippage(main_info.view_page);
1553 if ((handle = dat_open("menu.pcx")) == 0) {
1554 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1555 return 1;
1557 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1558 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1559 return 1;
1562 /* fix dark font */
1563 for (c1 = 0; c1 < 16; c1++) {
1564 pal[(240 + c1) * 3 + 0] = c1 << 2;
1565 pal[(240 + c1) * 3 + 1] = c1 << 2;
1566 pal[(240 + c1) * 3 + 2] = c1 << 2;
1569 memset(cur_pal, 0, 768);
1571 setpalette(0, 256, cur_pal);
1573 mod_vol = 0;
1574 dj_ready_mod(MOD_SCORES);
1575 dj_set_mod_volume((char)mod_vol);
1576 dj_start_mod();
1577 dj_set_nosound(0);
1579 while (key_pressed(1) == 0) {
1580 if (mod_vol < 35)
1581 mod_vol++;
1582 dj_set_mod_volume((char)mod_vol);
1583 for (c1 = 0; c1 < 768; c1++) {
1584 if (cur_pal[c1] < pal[c1])
1585 cur_pal[c1]++;
1587 dj_mix();
1588 intr_sysupdate();
1589 wait_vrt(0);
1590 setpalette(0, 256, cur_pal);
1591 flippage(main_info.view_page);
1593 while (key_pressed(1) == 1) {
1594 dj_mix();
1595 intr_sysupdate();
1598 memset(pal, 0, 768);
1600 while (mod_vol > 0) {
1601 mod_vol--;
1602 dj_set_mod_volume((char)mod_vol);
1603 for (c1 = 0; c1 < 768; c1++) {
1604 if (cur_pal[c1] > pal[c1])
1605 cur_pal[c1]--;
1607 dj_mix();
1608 wait_vrt(0);
1609 setpalette(0, 256, cur_pal);
1610 flippage(main_info.view_page);
1613 fillpalette(0, 0, 0);
1615 dj_set_nosound(1);
1616 dj_stop_mod();
1618 if (is_net)
1619 break; /* don't go back to menu if in net game. */
1622 deinit_program();
1624 return 0;
1627 int map_tile(int pos_x, int pos_y)
1629 int tile;
1631 pos_x = pos_x >> 4;
1632 pos_y = pos_y >> 4;
1634 if(pos_x < 0 || pos_x >= 17 || pos_y < 0 || pos_y >= 22)
1635 return BAN_VOID;
1637 tile = ban_map[pos_y][pos_x];
1638 return tile;
1641 void cpu_move(void)
1643 int lm, rm, jm;
1644 int i, j;
1645 int cur_posx, cur_posy, tar_posx, tar_posy;
1646 int players_distance;
1647 player_t* target = NULL;
1648 int nearest_distance = -1;
1650 for (i = 0; i < JNB_MAX_PLAYERS; i++)
1652 nearest_distance = -1;
1653 if(ai[i] && player[i].enabled) // this player is a computer
1654 { // get nearest target
1655 for (j = 0; j < JNB_MAX_PLAYERS; j++)
1657 int deltax, deltay;
1659 if(i == j || !player[j].enabled)
1660 continue;
1662 deltax = player[j].x - player[i].x;
1663 deltay = player[j].y - player[i].y;
1664 players_distance = deltax*deltax + deltay*deltay;
1666 if (players_distance < nearest_distance || nearest_distance == -1)
1668 target = &player[j];
1669 nearest_distance = players_distance;
1673 if(target == NULL)
1674 continue;
1676 cur_posx = player[i].x >> 16;
1677 cur_posy = player[i].y >> 16;
1678 tar_posx = target->x >> 16;
1679 tar_posy = target->y >> 16;
1681 /** nearest player found, get him */
1682 /* here goes the artificial intelligence code */
1684 /* X-axis movement */
1685 if(tar_posx > cur_posx) // if true target is on the right side
1686 { // go after him
1687 lm=0;
1688 rm=1;
1690 else // target on the left side
1692 lm=1;
1693 rm=0;
1696 if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 &&
1697 tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32)
1699 lm = !lm;
1700 rm = !rm;
1702 else if(tar_posx - cur_posx < 4+8 && tar_posx - cur_posx > -4)
1703 { // makes the bunnies less "nervous"
1704 lm=0;
1705 lm=0;
1708 /* Y-axis movement */
1709 if(map_tile(cur_posx, cur_posy+16) != BAN_VOID &&
1710 ((i == 0 && key_pressed(KEY_PL1_JUMP)) ||
1711 (i == 1 && key_pressed(KEY_PL2_JUMP)) ||
1712 (i == 2 && key_pressed(KEY_PL3_JUMP)) ||
1713 (i == 3 && key_pressed(KEY_PL4_JUMP))))
1714 jm=0; // if we are on ground and jump key is being pressed,
1715 //first we have to release it or else we won't be able to jump more than once
1717 else if(map_tile(cur_posx, cur_posy-8) != BAN_VOID &&
1718 map_tile(cur_posx, cur_posy-8) != BAN_WATER)
1719 jm=0; // don't jump if there is something over it
1721 else if(map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_VOID &&
1722 map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_WATER &&
1723 cur_posx > 16 && cur_posx < 352-16-8) // obstacle, jump
1724 jm=1; // if there is something on the way, jump over it
1726 else if(((i == 0 && key_pressed(KEY_PL1_JUMP)) ||
1727 (i == 1 && key_pressed(KEY_PL2_JUMP)) ||
1728 (i == 2 && key_pressed(KEY_PL3_JUMP)) ||
1729 (i == 3 && key_pressed(KEY_PL4_JUMP))) &&
1730 (map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_VOID &&
1731 map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_WATER))
1732 jm=1; // this makes it possible to jump over 2 tiles
1734 else if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 &&
1735 tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32) // don't jump - running away
1736 jm=0;
1738 else if(tar_posy <= cur_posy) // target on the upper side
1739 jm=1;
1740 else // target below
1741 jm=0;
1743 /** Artificial intelligence done, now apply movements */
1744 if(lm)
1746 SDLKey key;
1747 if(i == 0)
1748 key = KEY_PL1_LEFT;
1749 else if(i == 1)
1750 key = KEY_PL2_LEFT;
1751 else if(i == 2)
1752 key = KEY_PL3_LEFT;
1753 else
1754 key = KEY_PL4_LEFT;
1756 key &= 0x7f;
1757 addkey(key);
1759 else
1761 SDLKey key;
1762 if(i == 0)
1763 key = KEY_PL1_LEFT;
1764 else if(i == 1)
1765 key = KEY_PL2_LEFT;
1766 else if(i == 2)
1767 key = KEY_PL3_LEFT;
1768 else
1769 key = KEY_PL4_LEFT;
1771 key &= 0x7f;
1772 addkey(key | 0x8000);
1775 if(rm)
1777 SDLKey key;
1778 if(i == 0)
1779 key = KEY_PL1_RIGHT;
1780 else if(i == 1)
1781 key = KEY_PL2_RIGHT;
1782 else if(i == 2)
1783 key = KEY_PL3_RIGHT;
1784 else
1785 key = KEY_PL4_RIGHT;
1787 key &= 0x7f;
1788 addkey(key);
1790 else
1792 SDLKey key;
1793 if(i == 0)
1794 key = KEY_PL1_RIGHT;
1795 else if(i == 1)
1796 key = KEY_PL2_RIGHT;
1797 else if(i == 2)
1798 key = KEY_PL3_RIGHT;
1799 else
1800 key = KEY_PL4_RIGHT;
1802 key &= 0x7f;
1803 addkey(key | 0x8000);
1806 if(jm)
1808 SDLKey key;
1809 if(i == 0)
1810 key = KEY_PL1_JUMP;
1811 else if(i == 1)
1812 key = KEY_PL2_JUMP;
1813 else if(i == 2)
1814 key = KEY_PL3_JUMP;
1815 else
1816 key = KEY_PL4_JUMP;
1818 key &= 0x7f;
1819 addkey(key);
1821 else
1823 SDLKey key;
1824 if(i == 0)
1825 key = KEY_PL1_JUMP;
1826 else if(i == 1)
1827 key = KEY_PL2_JUMP;
1828 else if(i == 2)
1829 key = KEY_PL3_JUMP;
1830 else
1831 key = KEY_PL4_JUMP;
1833 key &= 0x7f;
1834 addkey(key | 0x8000);
1841 void steer_players(void)
1843 int c1, c2;
1844 int s1 = 0, s2 = 0;
1846 cpu_move();
1847 update_player_actions();
1849 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1851 if (player[c1].enabled == 1) {
1853 if (player[c1].dead_flag == 0) {
1855 if (player[c1].action_left && player[c1].action_right) {
1856 if (player[c1].direction == 0) {
1857 if (player[c1].action_right) {
1858 s1 = (player[c1].x >> 16);
1859 s2 = (player[c1].y >> 16);
1860 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1861 if (player[c1].x_add < 0)
1862 player[c1].x_add += 1024;
1863 else
1864 player[c1].x_add += 768;
1865 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1866 if (player[c1].x_add > 0)
1867 player[c1].x_add += 1024;
1868 else
1869 player[c1].x_add += 768;
1870 } else {
1871 if (player[c1].x_add < 0) {
1872 player[c1].x_add += 16384;
1873 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1874 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);
1875 } else
1876 player[c1].x_add += 12288;
1878 if (player[c1].x_add > 98304L)
1879 player[c1].x_add = 98304L;
1880 player[c1].direction = 0;
1881 if (player[c1].anim == 0) {
1882 player[c1].anim = 1;
1883 player[c1].frame = 0;
1884 player[c1].frame_tick = 0;
1885 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1888 } else {
1889 if (player[c1].action_left) {
1890 s1 = (player[c1].x >> 16);
1891 s2 = (player[c1].y >> 16);
1892 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1893 if (player[c1].x_add > 0)
1894 player[c1].x_add -= 1024;
1895 else
1896 player[c1].x_add -= 768;
1897 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1898 if (player[c1].x_add > 0)
1899 player[c1].x_add -= 1024;
1900 else
1901 player[c1].x_add -= 768;
1902 } else {
1903 if (player[c1].x_add > 0) {
1904 player[c1].x_add -= 16384;
1905 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1906 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);
1907 } else
1908 player[c1].x_add -= 12288;
1910 if (player[c1].x_add < -98304L)
1911 player[c1].x_add = -98304L;
1912 player[c1].direction = 1;
1913 if (player[c1].anim == 0) {
1914 player[c1].anim = 1;
1915 player[c1].frame = 0;
1916 player[c1].frame_tick = 0;
1917 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1921 } else if (player[c1].action_left) {
1922 s1 = (player[c1].x >> 16);
1923 s2 = (player[c1].y >> 16);
1924 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1925 if (player[c1].x_add > 0)
1926 player[c1].x_add -= 1024;
1927 else
1928 player[c1].x_add -= 768;
1929 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1930 if (player[c1].x_add > 0)
1931 player[c1].x_add -= 1024;
1932 else
1933 player[c1].x_add -= 768;
1934 } else {
1935 if (player[c1].x_add > 0) {
1936 player[c1].x_add -= 16384;
1937 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1938 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);
1939 } else
1940 player[c1].x_add -= 12288;
1942 if (player[c1].x_add < -98304L)
1943 player[c1].x_add = -98304L;
1944 player[c1].direction = 1;
1945 if (player[c1].anim == 0) {
1946 player[c1].anim = 1;
1947 player[c1].frame = 0;
1948 player[c1].frame_tick = 0;
1949 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1951 } else if (player[c1].action_right) {
1952 s1 = (player[c1].x >> 16);
1953 s2 = (player[c1].y >> 16);
1954 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_ICE) {
1955 if (player[c1].x_add < 0)
1956 player[c1].x_add += 1024;
1957 else
1958 player[c1].x_add += 768;
1959 } else if ((ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_SOLID)) {
1960 if (player[c1].x_add > 0)
1961 player[c1].x_add += 1024;
1962 else
1963 player[c1].x_add += 768;
1964 } else {
1965 if (player[c1].x_add < 0) {
1966 player[c1].x_add += 16384;
1967 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1968 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);
1969 } else
1970 player[c1].x_add += 12288;
1972 if (player[c1].x_add > 98304L)
1973 player[c1].x_add = 98304L;
1974 player[c1].direction = 0;
1975 if (player[c1].anim == 0) {
1976 player[c1].anim = 1;
1977 player[c1].frame = 0;
1978 player[c1].frame_tick = 0;
1979 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1981 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1982 s1 = (player[c1].x >> 16);
1983 s2 = (player[c1].y >> 16);
1984 if (ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SPRING || (((ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SPRING) && ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] != BAN_ICE) || (ban_map[(s2 + 16) >> 4][s1 >> 4] != BAN_ICE && (ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SPRING)))) {
1985 if (player[c1].x_add < 0) {
1986 player[c1].x_add += 16384;
1987 if (player[c1].x_add > 0)
1988 player[c1].x_add = 0;
1989 } else {
1990 player[c1].x_add -= 16384;
1991 if (player[c1].x_add < 0)
1992 player[c1].x_add = 0;
1994 if (player[c1].x_add != 0 && ban_map[(s2 + 16) >> 4][(s1 + 8) >> 4] == BAN_SOLID)
1995 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);
1997 if (player[c1].anim == 1) {
1998 player[c1].anim = 0;
1999 player[c1].frame = 0;
2000 player[c1].frame_tick = 0;
2001 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2004 if (jetpack == 0) {
2005 if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
2006 s1 = (player[c1].x >> 16);
2007 s2 = (player[c1].y >> 16);
2008 if (s2 < -16)
2009 s2 = -16;
2010 if (ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 16) >> 4][(s1 + 15) >> 4] == BAN_ICE) {
2011 player[c1].y_add = -280000L;
2012 player[c1].anim = 2;
2013 player[c1].frame = 0;
2014 player[c1].frame_tick = 0;
2015 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2016 player[c1].jump_ready = 0;
2017 player[c1].jump_abort = 1;
2018 if (pogostick == 0)
2019 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2020 else
2021 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2023 if ((ban_map[(s2 + 7) >> 4][s1 >> 4] == BAN_VOID || ban_map[(s2 + 7) >> 4][(s1 + 15) >> 4] == BAN_VOID) && (ban_map[(s2 + 8) >> 4][s1 >> 4] == BAN_WATER || ban_map[(s2 + 8) >> 4][(s1 + 15) >> 4] == BAN_WATER)) {
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);
2038 if (pogostick == 0 && (!player[c1].action_up)) {
2039 player[c1].jump_ready = 1;
2040 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
2041 if (bunnies_in_space == 0)
2042 player[c1].y_add += 32768;
2043 else
2044 player[c1].y_add += 16384;
2045 if (player[c1].y_add > 0)
2046 player[c1].y_add = 0;
2049 } else {
2051 if (player[c1].action_up) {
2052 player[c1].y_add -= 16384;
2053 if (player[c1].y_add < -400000L)
2054 player[c1].y_add = -400000L;
2055 if ((ban_map[(s2 + 7) >> 4][s1 >> 4] == BAN_VOID || ban_map[(s2 + 7) >> 4][(s1 + 15) >> 4] == BAN_VOID) && (ban_map[(s2 + 8) >> 4][s1 >> 4] == BAN_WATER || ban_map[(s2 + 8) >> 4][(s1 + 15) >> 4] == BAN_WATER))
2056 player[c1].in_water = 0;
2057 if (rnd(100) < 50)
2058 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);
2063 player[c1].x += player[c1].x_add;
2064 if ((player[c1].x >> 16) < 0) {
2065 player[c1].x = 0;
2066 player[c1].x_add = 0;
2068 if ((player[c1].x >> 16) + 15 > 351) {
2069 player[c1].x = 336L << 16;
2070 player[c1].x_add = 0;
2072 if (player[c1].y > 0) {
2073 s1 = (player[c1].x >> 16);
2074 s2 = (player[c1].y >> 16);
2075 if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
2076 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
2077 player[c1].x_add = 0;
2079 s1 = (player[c1].x >> 16);
2080 s2 = (player[c1].y >> 16);
2081 if (ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
2082 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
2083 player[c1].x_add = 0;
2085 } else {
2086 s1 = (player[c1].x >> 16);
2087 s2 = 0;
2088 if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
2089 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
2090 player[c1].x_add = 0;
2092 s1 = (player[c1].x >> 16);
2093 s2 = 0;
2094 if (ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
2095 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
2096 player[c1].x_add = 0;
2100 player[c1].y += player[c1].y_add;
2102 s1 = (player[c1].x >> 16);
2103 s2 = (player[c1].y >> 16);
2104 if (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == BAN_SPRING || ((ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING && ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] != BAN_SOLID) || (ban_map[(s2 + 15) >> 4][s1 >> 4] != BAN_SOLID && ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING))) {
2105 player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
2106 player[c1].y_add = -400000L;
2107 player[c1].anim = 2;
2108 player[c1].frame = 0;
2109 player[c1].frame_tick = 0;
2110 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2111 player[c1].jump_ready = 0;
2112 player[c1].jump_abort = 0;
2113 for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
2114 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
2115 if (ban_map[(s2 + 15) >> 4][(s1 + 8) >> 4] == BAN_SPRING) {
2116 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2117 objects[c2].frame = 0;
2118 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2119 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2120 break;
2122 } else {
2123 if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING) {
2124 if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2125 objects[c2].frame = 0;
2126 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2127 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2128 break;
2130 } else if (ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
2131 if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
2132 objects[c2].frame = 0;
2133 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
2134 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
2135 break;
2141 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2143 s1 = (player[c1].x >> 16);
2144 s2 = (player[c1].y >> 16);
2145 if (s2 < 0)
2146 s2 = 0;
2147 if (ban_map[s2 >> 4][s1 >> 4] == BAN_SOLID || ban_map[s2 >> 4][s1 >> 4] == BAN_ICE || ban_map[s2 >> 4][s1 >> 4] == BAN_SPRING || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[s2 >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
2148 player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
2149 player[c1].y_add = 0;
2150 player[c1].anim = 0;
2151 player[c1].frame = 0;
2152 player[c1].frame_tick = 0;
2153 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2155 s1 = (player[c1].x >> 16);
2156 s2 = (player[c1].y >> 16);
2157 if (s2 < 0)
2158 s2 = 0;
2159 if (ban_map[(s2 + 8) >> 4][(s1 + 8) >> 4] == BAN_WATER) {
2160 if (player[c1].in_water == 0) {
2161 player[c1].in_water = 1;
2162 player[c1].anim = 4;
2163 player[c1].frame = 0;
2164 player[c1].frame_tick = 0;
2165 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2166 if (player[c1].y_add >= 32768) {
2167 add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
2168 if (blood_is_thicker_than_water == 0)
2169 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
2170 else
2171 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
2174 player[c1].y_add -= 1536;
2175 if (player[c1].y_add < 0 && player[c1].anim != 5) {
2176 player[c1].anim = 5;
2177 player[c1].frame = 0;
2178 player[c1].frame_tick = 0;
2179 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2181 if (player[c1].y_add < -65536L)
2182 player[c1].y_add = -65536L;
2183 if (player[c1].y_add > 65535L)
2184 player[c1].y_add = 65535L;
2185 if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE) {
2186 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2187 player[c1].y_add = 0;
2189 } else if (ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][s1 >> 4] == BAN_SPRING || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SOLID || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_ICE || ban_map[(s2 + 15) >> 4][(s1 + 15) >> 4] == BAN_SPRING) {
2190 player[c1].in_water = 0;
2191 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
2192 player[c1].y_add = 0;
2193 if (player[c1].anim != 0 && player[c1].anim != 1) {
2194 player[c1].anim = 0;
2195 player[c1].frame = 0;
2196 player[c1].frame_tick = 0;
2197 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2199 } else {
2200 if (player[c1].in_water == 0) {
2201 if (bunnies_in_space == 0)
2202 player[c1].y_add += 12288;
2203 else
2204 player[c1].y_add += 6144;
2205 if (player[c1].y_add > 327680L)
2206 player[c1].y_add = 327680L;
2207 } else {
2208 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
2209 player[c1].y_add = 0;
2211 player[c1].in_water = 0;
2213 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
2214 player[c1].anim = 3;
2215 player[c1].frame = 0;
2216 player[c1].frame_tick = 0;
2217 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2222 player[c1].frame_tick++;
2223 if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2224 player[c1].frame++;
2225 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2226 if (player[c1].anim != 6)
2227 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2228 else
2229 position_player(c1);
2231 player[c1].frame_tick = 0;
2233 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2242 void position_player(int player_num)
2244 int c1;
2245 int s1, s2;
2247 while (1) {
2248 while (1) {
2249 s1 = rnd(22);
2250 s2 = rnd(16);
2251 if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2252 break;
2254 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2255 if (c1 != player_num && player[c1].enabled == 1) {
2256 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2257 break;
2260 if (c1 == JNB_MAX_PLAYERS) {
2261 player[player_num].x = (long) s1 << 20;
2262 player[player_num].y = (long) s2 << 20;
2263 player[player_num].x_add = player[player_num].y_add = 0;
2264 player[player_num].direction = 0;
2265 player[player_num].jump_ready = 1;
2266 player[player_num].in_water = 0;
2267 player[player_num].anim = 0;
2268 player[player_num].frame = 0;
2269 player[player_num].frame_tick = 0;
2270 player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2272 if (is_server) {
2273 #ifdef USE_NET
2274 if (is_net)
2275 serverSendAlive(player_num);
2276 #endif
2277 player[player_num].dead_flag = 0;
2280 break;
2287 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2289 int c1;
2291 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2292 if (objects[c1].used == 0) {
2293 objects[c1].used = 1;
2294 objects[c1].type = type;
2295 objects[c1].x = (long) x << 16;
2296 objects[c1].y = (long) y << 16;
2297 objects[c1].x_add = x_add;
2298 objects[c1].y_add = y_add;
2299 objects[c1].x_acc = 0;
2300 objects[c1].y_acc = 0;
2301 objects[c1].anim = anim;
2302 objects[c1].frame = frame;
2303 objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2304 objects[c1].image = object_anims[anim].frame[frame].image;
2305 break;
2312 void update_objects(void)
2314 int c1;
2315 int s1 = 0;
2317 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2318 if (objects[c1].used == 1) {
2319 switch (objects[c1].type) {
2320 case OBJ_SPRING:
2321 objects[c1].ticks--;
2322 if (objects[c1].ticks <= 0) {
2323 objects[c1].frame++;
2324 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2325 objects[c1].frame--;
2326 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2327 } else {
2328 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2329 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2332 if (objects[c1].used == 1)
2333 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2334 break;
2335 case OBJ_SPLASH:
2336 objects[c1].ticks--;
2337 if (objects[c1].ticks <= 0) {
2338 objects[c1].frame++;
2339 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2340 objects[c1].used = 0;
2341 else {
2342 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2343 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2346 if (objects[c1].used == 1)
2347 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2348 break;
2349 case OBJ_SMOKE:
2350 objects[c1].x += objects[c1].x_add;
2351 objects[c1].y += objects[c1].y_add;
2352 objects[c1].ticks--;
2353 if (objects[c1].ticks <= 0) {
2354 objects[c1].frame++;
2355 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2356 objects[c1].used = 0;
2357 else {
2358 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2359 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2362 if (objects[c1].used == 1)
2363 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2364 break;
2365 case OBJ_YEL_BUTFLY:
2366 case OBJ_PINK_BUTFLY:
2367 objects[c1].x_acc += rnd(128) - 64;
2368 if (objects[c1].x_acc < -1024)
2369 objects[c1].x_acc = -1024;
2370 if (objects[c1].x_acc > 1024)
2371 objects[c1].x_acc = 1024;
2372 objects[c1].x_add += objects[c1].x_acc;
2373 if (objects[c1].x_add < -32768)
2374 objects[c1].x_add = -32768;
2375 if (objects[c1].x_add > 32768)
2376 objects[c1].x_add = 32768;
2377 objects[c1].x += objects[c1].x_add;
2378 if ((objects[c1].x >> 16) < 16) {
2379 objects[c1].x = 16 << 16;
2380 objects[c1].x_add = -objects[c1].x_add >> 2;
2381 objects[c1].x_acc = 0;
2382 } else if ((objects[c1].x >> 16) > 350) {
2383 objects[c1].x = 350 << 16;
2384 objects[c1].x_add = -objects[c1].x_add >> 2;
2385 objects[c1].x_acc = 0;
2387 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2388 if (objects[c1].x_add < 0) {
2389 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2390 } else {
2391 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2393 objects[c1].x_add = -objects[c1].x_add >> 2;
2394 objects[c1].x_acc = 0;
2396 objects[c1].y_acc += rnd(64) - 32;
2397 if (objects[c1].y_acc < -1024)
2398 objects[c1].y_acc = -1024;
2399 if (objects[c1].y_acc > 1024)
2400 objects[c1].y_acc = 1024;
2401 objects[c1].y_add += objects[c1].y_acc;
2402 if (objects[c1].y_add < -32768)
2403 objects[c1].y_add = -32768;
2404 if (objects[c1].y_add > 32768)
2405 objects[c1].y_add = 32768;
2406 objects[c1].y += objects[c1].y_add;
2407 if ((objects[c1].y >> 16) < 0) {
2408 objects[c1].y = 0;
2409 objects[c1].y_add = -objects[c1].y_add >> 2;
2410 objects[c1].y_acc = 0;
2411 } else if ((objects[c1].y >> 16) > 255) {
2412 objects[c1].y = 255 << 16;
2413 objects[c1].y_add = -objects[c1].y_add >> 2;
2414 objects[c1].y_acc = 0;
2416 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2417 if (objects[c1].y_add < 0) {
2418 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2419 } else {
2420 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2422 objects[c1].y_add = -objects[c1].y_add >> 2;
2423 objects[c1].y_acc = 0;
2425 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2426 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2427 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2428 objects[c1].frame = 0;
2429 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2430 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2431 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2432 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2433 objects[c1].frame = 0;
2434 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2435 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2437 } else {
2438 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2439 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT;
2440 objects[c1].frame = 0;
2441 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2442 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2443 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) {
2444 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT;
2445 objects[c1].frame = 0;
2446 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2447 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2450 objects[c1].ticks--;
2451 if (objects[c1].ticks <= 0) {
2452 objects[c1].frame++;
2453 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2454 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2455 else {
2456 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2457 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2460 if (objects[c1].used == 1)
2461 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2462 break;
2463 case OBJ_FUR:
2464 if (rnd(100) < 30)
2465 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2466 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2467 objects[c1].y_add += 3072;
2468 if (objects[c1].y_add > 196608L)
2469 objects[c1].y_add = 196608L;
2470 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2471 if (objects[c1].x_add < 0) {
2472 if (objects[c1].x_add < -65536L)
2473 objects[c1].x_add = -65536L;
2474 objects[c1].x_add += 1024;
2475 if (objects[c1].x_add > 0)
2476 objects[c1].x_add = 0;
2477 } else {
2478 if (objects[c1].x_add > 65536L)
2479 objects[c1].x_add = 65536L;
2480 objects[c1].x_add -= 1024;
2481 if (objects[c1].x_add < 0)
2482 objects[c1].x_add = 0;
2484 objects[c1].y_add += 1024;
2485 if (objects[c1].y_add < -65536L)
2486 objects[c1].y_add = -65536L;
2487 if (objects[c1].y_add > 65536L)
2488 objects[c1].y_add = 65536L;
2490 objects[c1].x += objects[c1].x_add;
2491 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)) {
2492 if (objects[c1].x_add < 0) {
2493 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2494 objects[c1].x_add = -objects[c1].x_add >> 2;
2495 } else {
2496 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2497 objects[c1].x_add = -objects[c1].x_add >> 2;
2500 objects[c1].y += objects[c1].y_add;
2501 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2502 objects[c1].used = 0;
2503 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2504 if (objects[c1].y_add < 0) {
2505 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2506 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2507 objects[c1].x_add >>= 2;
2508 objects[c1].y_add = -objects[c1].y_add >> 2;
2510 } else {
2511 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2512 if (objects[c1].y_add > 131072L) {
2513 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2514 objects[c1].x_add >>= 2;
2515 objects[c1].y_add = -objects[c1].y_add >> 2;
2516 } else
2517 objects[c1].used = 0;
2518 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2519 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2520 if (objects[c1].y_add > 131072L)
2521 objects[c1].y_add = -objects[c1].y_add >> 2;
2522 else
2523 objects[c1].y_add = 0;
2527 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2528 objects[c1].x_add = -16384;
2529 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2530 objects[c1].x_add = 16384;
2531 if (objects[c1].used == 1) {
2532 s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2533 if (s1 < 0)
2534 s1 += 8;
2535 if (s1 < 0)
2536 s1 = 0;
2537 if (s1 > 7)
2538 s1 = 7;
2539 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2541 break;
2542 case OBJ_FLESH:
2543 if (rnd(100) < 30) {
2544 if (objects[c1].frame == 76)
2545 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2546 else if (objects[c1].frame == 77)
2547 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2548 else if (objects[c1].frame == 78)
2549 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2551 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2552 objects[c1].y_add += 3072;
2553 if (objects[c1].y_add > 196608L)
2554 objects[c1].y_add = 196608L;
2555 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2556 if (objects[c1].x_add < 0) {
2557 if (objects[c1].x_add < -65536L)
2558 objects[c1].x_add = -65536L;
2559 objects[c1].x_add += 1024;
2560 if (objects[c1].x_add > 0)
2561 objects[c1].x_add = 0;
2562 } else {
2563 if (objects[c1].x_add > 65536L)
2564 objects[c1].x_add = 65536L;
2565 objects[c1].x_add -= 1024;
2566 if (objects[c1].x_add < 0)
2567 objects[c1].x_add = 0;
2569 objects[c1].y_add += 1024;
2570 if (objects[c1].y_add < -65536L)
2571 objects[c1].y_add = -65536L;
2572 if (objects[c1].y_add > 65536L)
2573 objects[c1].y_add = 65536L;
2575 objects[c1].x += objects[c1].x_add;
2576 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)) {
2577 if (objects[c1].x_add < 0) {
2578 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2579 objects[c1].x_add = -objects[c1].x_add >> 2;
2580 } else {
2581 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2582 objects[c1].x_add = -objects[c1].x_add >> 2;
2585 objects[c1].y += objects[c1].y_add;
2586 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2587 objects[c1].used = 0;
2588 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2589 if (objects[c1].y_add < 0) {
2590 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2591 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2592 objects[c1].x_add >>= 2;
2593 objects[c1].y_add = -objects[c1].y_add >> 2;
2595 } else {
2596 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2597 if (objects[c1].y_add > 131072L) {
2598 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2599 objects[c1].x_add >>= 2;
2600 objects[c1].y_add = -objects[c1].y_add >> 2;
2601 } else {
2602 if (rnd(100) < 10) {
2603 s1 = rnd(4) - 2;
2604 add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2605 add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2607 objects[c1].used = 0;
2609 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2610 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2611 if (objects[c1].y_add > 131072L)
2612 objects[c1].y_add = -objects[c1].y_add >> 2;
2613 else
2614 objects[c1].y_add = 0;
2618 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2619 objects[c1].x_add = -16384;
2620 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2621 objects[c1].x_add = 16384;
2622 if (objects[c1].used == 1)
2623 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2624 break;
2625 case OBJ_FLESH_TRACE:
2626 objects[c1].ticks--;
2627 if (objects[c1].ticks <= 0) {
2628 objects[c1].frame++;
2629 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2630 objects[c1].used = 0;
2631 else {
2632 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2633 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2636 if (objects[c1].used == 1)
2637 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2638 break;
2646 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2649 if (main_info.page_info[page].num_pobs >= NUM_POBS)
2650 return 1;
2652 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2653 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2654 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2655 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2656 main_info.page_info[page].num_pobs++;
2658 return 0;
2663 void draw_flies(int page)
2665 int c2;
2667 for (c2 = 0; c2 < NUM_FLIES; c2++) {
2668 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2669 flies[c2].back_defined[main_info.draw_page] = 1;
2670 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2671 set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2675 void draw_pobs(int page)
2677 int c1;
2678 int back_buf_ofs;
2680 back_buf_ofs = 0;
2682 for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2683 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2684 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);
2685 if (scale_up)
2686 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;
2687 else
2688 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);
2689 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);
2695 void redraw_flies_background(int page)
2697 int c2;
2699 for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2700 if (flies[c2].back_defined[page] == 1)
2701 set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2702 flies[c2].old_draw_x = flies[c2].x;
2703 flies[c2].old_draw_y = flies[c2].y;
2708 void redraw_pob_backgrounds(int page)
2710 int c1;
2712 for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2713 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);
2718 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2721 if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2722 return 1;
2724 leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2725 leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2726 leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2727 leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2728 leftovers.page[page].num_pobs++;
2730 return 0;
2735 void draw_leftovers(int page)
2737 int c1;
2739 for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2740 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);
2742 leftovers.page[page].num_pobs = 0;
2747 int init_level(int level, char *pal)
2749 unsigned char *handle;
2750 int c1, c2;
2751 int s1, s2;
2753 if ((handle = dat_open("level.pcx")) == 0) {
2754 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2755 return 1;
2757 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2758 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2759 return 1;
2761 if (flip)
2762 flip_pixels(background_pic);
2763 if ((handle = dat_open("mask.pcx")) == 0) {
2764 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2765 return 1;
2767 if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2768 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2769 return 1;
2771 if (flip)
2772 flip_pixels(mask_pic);
2773 register_mask(mask_pic);
2775 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2776 if (player[c1].enabled == 1) {
2777 player[c1].bumps = 0;
2778 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2779 player[c1].bumped[c2] = 0;
2780 position_player(c1);
2784 for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2785 objects[c1].used = 0;
2787 for (c1 = 0; c1 < 16; c1++) {
2788 for (c2 = 0; c2 < 22; c2++) {
2789 if (ban_map[c1][c2] == BAN_SPRING)
2790 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2794 while (1) {
2795 s1 = rnd(22);
2796 s2 = rnd(16);
2797 if (ban_map[s2][s1] == BAN_VOID) {
2798 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2799 break;
2802 while (1) {
2803 s1 = rnd(22);
2804 s2 = rnd(16);
2805 if (ban_map[s2][s1] == BAN_VOID) {
2806 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2807 break;
2810 while (1) {
2811 s1 = rnd(22);
2812 s2 = rnd(16);
2813 if (ban_map[s2][s1] == BAN_VOID) {
2814 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2815 break;
2818 while (1) {
2819 s1 = rnd(22);
2820 s2 = rnd(16);
2821 if (ban_map[s2][s1] == BAN_VOID) {
2822 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2823 break;
2827 return 0;
2832 void deinit_level(void)
2834 dj_set_nosound(1);
2835 dj_stop_mod();
2839 #ifndef PATH_MAX
2840 #define PATH_MAX 1024
2841 #endif
2842 #ifndef O_BINARY
2843 #define O_BINARY 0
2844 #endif
2846 unsigned char *datafile_buffer = NULL;
2848 static void preread_datafile(const char *fname)
2850 int fd = 0;
2851 int len;
2853 #ifdef ZLIB_SUPPORT
2854 char *gzfilename = alloca(strlen(fname) + 4);
2855 int bufsize = 0;
2856 int bufpos = 0;
2857 gzFile gzf;
2859 strcpy(gzfilename, fname);
2860 strcat(gzfilename, ".gz");
2862 gzf = gzopen(gzfilename, "rb");
2863 if (gzf != NULL) {
2864 unsigned char *ptr;
2865 do {
2866 int br;
2867 if (bufpos >= bufsize) {
2868 bufsize += 1024 * 1024;
2869 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2870 if (datafile_buffer == NULL) {
2871 perror("realloc()");
2872 exit(42);
2876 br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2877 if (br == -1) {
2878 fprintf(stderr, "gzread failed.\n");
2879 exit(42);
2882 bufpos += br;
2883 } while (!gzeof(gzf));
2885 /* try to shrink buffer... */
2886 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2887 if (ptr != NULL)
2888 datafile_buffer = ptr;
2890 gzclose(gzf);
2891 return;
2894 /* drop through and try for an uncompressed datafile... */
2895 #endif
2897 fd = open(fname, O_RDONLY | O_BINARY);
2898 if (fd == -1) {
2899 fprintf(stderr, "can't open %s:", fname);
2900 perror("");
2901 exit(42);
2904 len = filelength(fd);
2905 datafile_buffer = (unsigned char *) malloc(len);
2906 if (datafile_buffer == NULL) {
2907 perror("malloc()");
2908 close(fd);
2909 exit(42);
2912 if (read(fd, datafile_buffer, len) != len) {
2913 perror("read()");
2914 close(fd);
2915 exit(42);
2918 close(fd);
2922 int init_program(int argc, char *argv[], char *pal)
2924 char *netarg = NULL;
2925 unsigned char *handle = (unsigned char *) NULL;
2926 int c1 = 0, c2 = 0;
2927 int load_flag = 0;
2928 int force2, force3;
2929 sfx_data fly;
2930 int player_anim_data[] = {
2931 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2932 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2933 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2934 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2935 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2936 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2937 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2940 #ifdef USE_NET
2941 memset(&net_info, 0, sizeof(net_info));
2942 #endif
2944 #ifdef DOS
2945 if (__djgpp_nearptr_enable() == 0)
2946 return 1;
2947 #endif
2949 srand(time(NULL));
2951 if (hook_keyb_handler() != 0)
2952 return 1;
2954 memset(&main_info, 0, sizeof(main_info));
2956 strcpy(datfile_name, DATA_PATH);
2958 force2 = force3 = 0;
2960 if (argc > 1) {
2961 for (c1 = 1; c1 < argc; c1++) {
2962 if (stricmp(argv[c1], "-nosound") == 0)
2963 main_info.no_sound = 1;
2964 else if (stricmp(argv[c1], "-musicnosound") == 0)
2965 main_info.music_no_sound = 1;
2966 else if (stricmp(argv[c1], "-nogore") == 0)
2967 main_info.no_gore = 1;
2968 else if (stricmp(argv[c1], "-noflies") == 0)
2969 flies_enabled = 0;
2970 else if (stricmp(argv[c1], "-nojoy") == 0)
2971 main_info.joy_enabled = 0;
2972 else if (stricmp(argv[c1], "-fireworks") == 0)
2973 main_info.fireworks = 1;
2974 #ifdef USE_SDL
2975 else if (stricmp(argv[c1], "-fullscreen") == 0)
2976 fs_toggle();
2977 #endif
2978 else if (stricmp(argv[c1], "-scaleup") == 0)
2979 set_scaling(1);
2980 else if (stricmp(argv[c1], "-mirror") == 0)
2981 flip = 1;
2982 else if (stricmp(argv[c1], "-dat") == 0) {
2983 if (c1 < (argc - 1)) {
2984 FILE *f;
2986 if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
2987 fclose(f);
2988 strcpy(datfile_name, argv[c1 + 1]);
2991 } else if (stricmp(argv[c1], "-player") == 0) {
2992 if (c1 < (argc - 1)) {
2993 if (client_player_num < 0)
2994 client_player_num = atoi(argv[c1 + 1]);
2996 #ifdef USE_NET
2997 } else if (stricmp(argv[c1], "-server") == 0) {
2998 if (c1 < (argc - 1)) {
2999 is_server = 1;
3000 is_net = 1;
3001 netarg = argv[c1 + 1];
3003 } else if (stricmp(argv[c1], "-connect") == 0) {
3004 if (c1 < (argc - 1)) {
3005 is_server = 0;
3006 is_net = 1;
3007 netarg = argv[c1 + 1];
3009 #endif
3010 } else if (stricmp(argv[c1], "-mouse") == 0) {
3011 if (c1 < (argc - 1)) {
3012 if (stricmp(argv[c1 + 1], "2") == 0)
3013 force2 = 1;
3014 if (stricmp(argv[c1 + 1], "3") == 0)
3015 force3 = 1;
3018 else if (strstr(argv[1],"-v")) {
3019 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
3020 #ifndef USE_NET
3021 printf("out");
3022 #endif
3023 printf(" network support.\n");
3024 return 1;
3026 else if (strstr(argv[1],"-h")) {
3027 printf("Usage: jumpnbump [OPTION]...\n");
3028 printf("\n");
3029 printf(" -h this help\n");
3030 printf(" -v print version\n");
3031 printf(" -dat level.dat play a different level\n");
3032 #ifdef USE_NET
3033 printf(" -server playercount start as server waiting for players\n");
3034 printf(" -connect host connect to server\n");
3035 #endif
3036 printf(" -player num set main player to num (0-3). Needed for networking\n");
3037 printf(" -fireworks screensaver mode\n");
3038 printf(" -fullscreen run in fullscreen mode\n");
3039 printf(" -nosound play without sound\n");
3040 printf(" -nogore play without blood\n");
3041 printf(" -noflies disable flies\n");
3042 printf(" -mirror play with mirrored level\n");
3043 printf(" -scaleup play with doubled resolution (800x512)\n");
3044 printf(" -musicnosound play with music but without sound\n");
3045 printf("\n");
3046 return 1;
3051 preread_datafile(datfile_name);
3053 #if 0
3054 /** It should not be necessary to assign a default player number here. The
3055 server assigns one in init_server, the client gets one assigned by the server,
3056 all provided the user didn't choose one on the commandline. */
3057 if (is_net) {
3058 if (client_player_num < 0)
3059 client_player_num = 0;
3060 player[client_player_num].enabled = 1;
3062 #endif
3064 main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height);
3065 main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height);
3067 for (c1 = 0; c1 < 7; c1++) {
3068 player_anims[c1].num_frames = player_anim_data[c1 * 10];
3069 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
3070 for (c2 = 0; c2 < 4; c2++) {
3071 player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
3072 player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
3076 if ((handle = dat_open("menu.pcx")) == 0) {
3077 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
3078 return 1;
3080 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
3081 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
3082 return 1;
3085 if ((handle = dat_open("rabbit.gob")) == 0) {
3086 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
3087 return 1;
3089 if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob"))) {
3090 /* error */
3091 return 1;
3094 if ((handle = dat_open("objects.gob")) == 0) {
3095 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
3096 return 1;
3098 if (register_gob(handle, &object_gobs, dat_filelen("objects.gob"))) {
3099 /* error */
3100 return 1;
3103 if ((handle = dat_open("font.gob")) == 0) {
3104 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
3105 return 1;
3107 if (register_gob(handle, &font_gobs, dat_filelen("font.gob"))) {
3108 /* error */
3109 return 1;
3112 if ((handle = dat_open("numbers.gob")) == 0) {
3113 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
3114 return 1;
3116 if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob"))) {
3117 /* error */
3118 return 1;
3121 if (read_level() != 0) {
3122 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3123 return 1;
3126 dj_init();
3128 if (main_info.no_sound == 0) {
3129 dj_autodetect_sd();
3130 dj_set_mixing_freq(20000);
3131 dj_set_stereo(0);
3132 dj_set_auto_mix(0);
3133 dj_set_dma_time(8);
3134 dj_set_num_sfx_channels(5);
3135 dj_set_sfx_volume(64);
3136 dj_set_nosound(1);
3137 dj_start();
3139 if ((handle = dat_open("jump.mod")) == 0) {
3140 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
3141 return 1;
3143 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
3144 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
3145 return 1;
3148 if ((handle = dat_open("bump.mod")) == 0) {
3149 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
3150 return 1;
3152 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
3153 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
3154 return 1;
3157 if ((handle = dat_open("scores.mod")) == 0) {
3158 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3159 return 1;
3161 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
3162 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
3163 return 1;
3166 if ((handle = dat_open("jump.smp")) == 0) {
3167 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3168 return 1;
3170 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp"), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
3171 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3172 return 1;
3175 if ((handle = dat_open("death.smp")) == 0) {
3176 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3177 return 1;
3179 if (dj_load_sfx(handle, 0, dat_filelen("death.smp"), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
3180 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3181 return 1;
3184 if ((handle = dat_open("spring.smp")) == 0) {
3185 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3186 return 1;
3188 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp"), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
3189 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3190 return 1;
3193 if ((handle = dat_open("splash.smp")) == 0) {
3194 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3195 return 1;
3197 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp"), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
3198 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3199 return 1;
3202 if ((handle = dat_open("fly.smp")) == 0) {
3203 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3204 return 1;
3206 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp"), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
3207 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3208 return 1;
3211 dj_get_sfx_settings(SFX_FLY, &fly);
3212 fly.priority = 10;
3213 fly.default_freq = SFX_FLY_FREQ;
3214 fly.loop = 1;
3215 fly.loop_start = 0;
3216 fly.loop_length = fly.length;
3217 dj_set_sfx_settings(SFX_FLY, &fly);
3220 if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3221 return 1;
3222 if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3223 return 1;
3224 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
3225 register_mask(mask_pic);
3227 /* fix dark font */
3228 for (c1 = 0; c1 < 16; c1++) {
3229 pal[(240 + c1) * 3 + 0] = c1 << 2;
3230 pal[(240 + c1) * 3 + 1] = c1 << 2;
3231 pal[(240 + c1) * 3 + 2] = c1 << 2;
3234 setpalette(0, 256, pal);
3236 init_inputs();
3238 recalculate_gob(&font_gobs, pal);
3240 if (main_info.joy_enabled == 1 && main_info.fireworks == 0) {
3241 load_flag = 0;
3242 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3243 put_text(0, 200, 100, "Move the joystick to the", 2);
3244 put_text(0, 200, 115, "UPPER LEFT", 2);
3245 put_text(0, 200, 130, "and press button A", 2);
3246 put_text(0, 200, 200, "Or press ESC to use", 2);
3247 put_text(0, 200, 215, "previous settings", 2);
3248 if (calib_joy(0) != 0)
3249 load_flag = 1;
3250 else {
3251 register_background(NULL, NULL);
3253 main_info.view_page = 1;
3254 flippage(1);
3256 wait_vrt(0);
3258 put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2);
3259 put_text(1, 200, 100, "Move the joystick to the", 2);
3260 put_text(1, 200, 115, "LOWER RIGHT", 2);
3261 put_text(1, 200, 130, "and press button A", 2);
3262 put_text(1, 200, 200, "Or press ESC to use", 2);
3263 put_text(1, 200, 215, "previous settings", 2);
3264 if (calib_joy(1) != 0)
3265 load_flag = 1;
3266 else {
3267 register_background(NULL, NULL);
3268 flippage(0);
3270 wait_vrt(0);
3272 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3273 put_text(0, 200, 100, "Move the joystick to the", 2);
3274 put_text(0, 200, 115, "CENTER", 2);
3275 put_text(0, 200, 130, "and press button A", 2);
3276 put_text(0, 200, 200, "Or press ESC to use", 2);
3277 put_text(0, 200, 215, "previous settings", 2);
3278 if (calib_joy(2) != 0)
3279 load_flag = 1;
3280 else {
3281 if (joy.calib_data.x1 == joy.calib_data.x2)
3282 joy.calib_data.x1 -= 10;
3283 if (joy.calib_data.x3 == joy.calib_data.x2)
3284 joy.calib_data.x3 += 10;
3285 if (joy.calib_data.y1 == joy.calib_data.y2)
3286 joy.calib_data.y1 -= 10;
3287 if (joy.calib_data.y3 == joy.calib_data.y2)
3288 joy.calib_data.y3 += 10;
3289 write_calib_data();
3293 if (load_flag == 1) {
3294 if ((handle = dat_open("calib.dat")) == 0) {
3295 strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n");
3296 return 1;
3298 joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3299 joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3300 joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3301 joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3302 joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3303 joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3307 #ifdef USE_NET
3308 if (is_net) {
3309 if (is_server) {
3310 init_server(netarg);
3311 } else {
3312 connect_to_server(netarg);
3315 #endif
3317 return 0;
3321 void deinit_program(void)
3323 #ifdef DOS
3324 __dpmi_regs regs;
3325 #endif
3327 exit_fullscreen();
3329 dj_stop();
3330 dj_free_mod(MOD_MENU);
3331 dj_free_mod(MOD_GAME);
3332 dj_free_sfx(SFX_DEATH);
3333 dj_free_sfx(SFX_SPRING);
3334 dj_free_sfx(SFX_SPLASH);
3335 dj_deinit();
3337 if (background_pic != 0)
3338 free(background_pic);
3339 if (mask_pic != 0)
3340 free(mask_pic);
3342 remove_keyb_handler();
3344 #ifdef DOS
3345 regs.x.ax = 0x3;
3346 __dpmi_int(0x10, &regs);
3347 #endif
3349 if (main_info.error_str[0] != 0) {
3350 printf(main_info.error_str);
3351 #ifdef _MSC_VER
3352 MessageBox(0, main_info.error_str, "Jump'n'Bump", 0);
3353 #endif
3354 exit(1);
3355 } else
3356 exit(0);
3361 unsigned short rnd(unsigned short max)
3363 #if (RAND_MAX < 0x7fff)
3364 #error "rand returns too small values"
3365 #elif (RAND_MAX == 0x7fff)
3366 return (unsigned short)((rand()*2) % (int)max);
3367 #else
3368 return (unsigned short)(rand() % (int)max);
3369 #endif
3373 int read_level(void)
3375 unsigned char *handle;
3376 int c1, c2;
3377 int chr;
3379 if ((handle = dat_open("levelmap.txt")) == 0) {
3380 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3381 return 1;
3384 for (c1 = 0; c1 < 16; c1++) {
3385 for (c2 = 0; c2 < 22; c2++) {
3386 while (1) {
3387 chr = (int) *(handle++);
3388 if (chr >= '0' && chr <= '4')
3389 break;
3391 if (flip)
3392 ban_map[c1][21-c2] = chr - '0';
3393 else
3394 ban_map[c1][c2] = chr - '0';
3398 for (c2 = 0; c2 < 22; c2++)
3399 ban_map[16][c2] = BAN_SOLID;
3401 return 0;
3406 unsigned char *dat_open(char *file_name)
3408 int num;
3409 int c1;
3410 char name[21];
3411 int ofs;
3412 unsigned char *ptr;
3414 if (datafile_buffer == NULL)
3415 return 0;
3417 memset(name, 0, sizeof(name));
3419 num = ( (datafile_buffer[0] << 0) +
3420 (datafile_buffer[1] << 8) +
3421 (datafile_buffer[2] << 16) +
3422 (datafile_buffer[3] << 24) );
3424 ptr = datafile_buffer + 4;
3426 for (c1 = 0; c1 < num; c1++) {
3428 memcpy(name, ptr, 12);
3429 ptr += 12;
3431 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3432 ofs = ( (ptr[0] << 0) +
3433 (ptr[1] << 8) +
3434 (ptr[2] << 16) +
3435 (ptr[3] << 24) );
3437 return (datafile_buffer + ofs);
3439 ptr += 8;
3442 return 0;
3446 int dat_filelen(char *file_name)
3448 unsigned char *ptr;
3449 int num;
3450 int c1;
3451 char name[21];
3452 int len;
3454 memset(name, 0, sizeof(name));
3456 num = ( (datafile_buffer[0] << 0) +
3457 (datafile_buffer[1] << 8) +
3458 (datafile_buffer[2] << 16) +
3459 (datafile_buffer[3] << 24) );
3461 ptr = datafile_buffer + 4;
3463 for (c1 = 0; c1 < num; c1++) {
3465 memcpy(name, ptr, 12);
3466 ptr += 12;
3468 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3470 ptr += 4;
3471 len = ( (ptr[0] << 0) +
3472 (ptr[1] << 8) +
3473 (ptr[2] << 16) +
3474 (ptr[3] << 24) );
3476 return len;
3478 ptr += 8;
3481 return 0;
3485 void write_calib_data(void)
3487 FILE *handle;
3488 int c1;
3489 int len, num;
3490 char *mem;
3491 int ofs;
3493 if ((handle = fopen(datfile_name, "rb")) == NULL)
3494 return;
3495 len = filelength(fileno(handle));
3496 if ((mem = malloc(len)) == NULL)
3497 return;
3498 fread(mem, 1, len, handle);
3499 fclose(handle);
3501 ofs = 4;
3502 num = *(int *) (&mem[0]);
3503 for (c1 = 0; c1 < num; c1++) {
3504 if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) {
3505 ofs = *(int *) (&mem[ofs + 12]);
3506 break;
3508 ofs += 20;
3511 mem[ofs] = joy.calib_data.x1 & 0xff;
3512 mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff;
3513 mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff;
3514 mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff;
3515 mem[ofs + 4] = joy.calib_data.x2 & 0xff;
3516 mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff;
3517 mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff;
3518 mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff;
3519 mem[ofs + 8] = joy.calib_data.x3 & 0xff;
3520 mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff;
3521 mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff;
3522 mem[ofs + 11] = (joy.calib_data.x3 >> 24