bot: make most declarations static
[0verkill.git] / bot.c
blobd85823d8cc898acc353d274189e39dc2c5c5a486
1 #ifndef WIN32
2 #include "config.h"
3 #endif
5 #include <stdio.h>
6 #include <signal.h>
7 #include <math.h>
9 #ifdef HAVE_FLOAT_H
10 #include <float.h>
11 #endif
13 #ifdef HAVE_SIGINFO_H
14 #include <siginfo.h>
15 #endif
17 #ifdef HAVE_SYS_SELECT_H
18 #include <sys/select.h>
19 #endif
21 #include <ctype.h>
23 #if (!defined(WIN32))
24 #ifdef TIME_WITH_SYS_TIME
25 #include <sys/time.h>
26 #include <time.h>
27 #else
28 #ifdef TM_IN_SYS_TIME
29 #include <sys/time.h>
30 #else
31 #include <time.h>
32 #endif
33 #endif
34 #else
35 #include <time.h>
36 #endif
38 #include <errno.h>
39 #include <stdlib.h>
40 #ifndef WIN32
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <netdb.h>
45 #ifndef __USE_GNU
46 #define __USE_GNU
47 #endif
48 #else
49 #include <winsock.h>
50 #endif
52 #include <string.h>
54 #include "sprite.h"
55 #include "data.h"
56 #include "cfg.h"
57 #include "net.h"
58 #include "hash.h"
59 #include "time.h"
60 #include "math.h"
61 #include "getopt.h"
62 #include "error.h"
65 #ifdef WIN32
66 int consoleApp=1;
67 #endif
69 #define N_NAMES 18
70 #define CAN_SEE_X 60
71 #define CAN_SEE_Y 10
73 /* some empty functions and variables */
74 void c_shutdown(void){}
75 void init_blit(void){}
76 void shutdown_blit(void){}
77 int SCREEN_X=1,SCREEN_Y=1;
78 unsigned char *screen,*screen_a;
79 #ifdef TRI_D
80 unsigned char *screen2,*screen2_a;
81 #endif
84 static int in_signal_handler=0;
85 static int level_sprites_start;
86 static int level_number=-1;
88 /* my health, armor, frags, deaths, ammo, ... and ID */
89 static unsigned char health,armor;
90 static unsigned int frags,deaths;
91 static unsigned short ammo[ARMS];
92 static unsigned char current_weapon;
93 static unsigned char weapons;
94 static int my_id;
96 /* connection with server */
97 static int connected=0;
99 int console_ok=1;
101 /* networking */
102 int fd; /* socket */
103 static struct sockaddr_in server; /* server address */
105 /* objects */
106 static struct object_list objects;
107 struct object_list *last_obj;
108 static struct it* hero;
110 static unsigned long_long game_start_offset; /* time difference between game start on this machine and on server */
113 static struct /* keyboard status */
115 unsigned char right,left,jump,creep,speed,fire,weapon,down_ladder;
116 }keyboard_status;
119 static char *names[N_NAMES]={
120 "Terminator",
121 "Jack The Ripper",
122 "Rambo",
123 "Exhumator",
124 "Assassin",
125 "Arnold",
126 "Necromancer",
127 "Predator",
128 "Rocky",
129 "Harvester",
130 "Lamer",
131 "Killme",
132 "Looser",
133 "Krueger",
134 "I'll kill you",
135 "Zombieman",
136 "Hellraiser",
137 "Eraser"
140 static int direction=0; /* 0=stop, 1=left, 2=right */
141 static int const1,const2,const3,const4;
142 static unsigned short port=DEFAULT_PORT;
143 static char *host;
144 static int priority;
145 /* 0=nothing
146 * 1=kill player
147 * 2=find rifle
148 * 3=find shotgun
149 * 4=find UZI
150 * 5=find grenades
151 * 6=find gun ammo
152 * 7=find shotgun ammo
153 * 8=find rifle ammo
154 * 9=find uzi ammo
155 * 10=find medikit
158 /*-----------------------------------------------------------------------*/
161 #define can_see(a,b) (a<add_int(hero->x,CAN_SEE_X)&&a>sub_int(hero->x,CAN_SEE_X)&&b>sub_int(hero->y,CAN_SEE_Y)&&b<add_int(hero->y,CAN_SEE_Y))
164 static int odds(int p)
166 return (random()%1000)<p;
170 /* free all before exit */
171 static void clear_memory(void)
173 struct object_list *o;
175 for (o=&objects;o->next;)
176 delete_obj(o->next->member.id);
177 free_area();
178 shutdown_sprites();
179 free_sprites(0);
183 /* shut down the client */
184 static void shut_down(int a)
186 if (a)
188 clear_memory();
189 free_packet_buffer();
190 check_memory_leaks();
191 EXIT(0);
196 /* find address of server and fill the server address structure */
197 static char * find_server(char *name,unsigned short port)
199 struct hostent *h;
201 h=gethostbyname(name);
202 if (!h)return "Error: Can't resolve server address.\n";
204 server.sin_family=AF_INET;
205 server.sin_port=htons(port);
206 server.sin_addr=*((struct in_addr*)(h->h_addr_list[0]));
207 return 0;
211 /* initialize socket */
212 static char * init_socket(void)
214 fd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
215 if(fd<0)return "Can't get socket.\n";
216 return 0;
220 #define MAX_COUNT 32
222 /* send quit request to server */
223 static void send_quit(void)
225 char p;
226 fd_set rfds;
227 struct timeval tv;
228 int a=sizeof(server);
229 int count=0;
231 tv.tv_sec=2;
232 tv.tv_usec=0;
233 FD_ZERO(&rfds);
234 FD_SET(fd,&rfds);
236 send_again:
237 p=P_QUIT_REQUEST;
238 count ++;
239 send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
240 if (!select(fd+1,&rfds,0,0,&tv)&&count<=MAX_COUNT)goto send_again;
241 recv_packet(&p,1,(struct sockaddr*)(&server),&a,1,my_id,0);
242 if (p!=P_PLAYER_DELETED&&count<=MAX_COUNT)goto send_again;
245 #undef MAX_COUNT
248 /* initiate connection with server */
249 static char * contact_server(int color, char *name)
251 static char packet[256];
252 int l=strlen(name)+1;
253 int a,r;
254 int min,maj;
256 fd_set fds;
257 struct timeval tv;
258 tv.tv_sec=4;
259 tv.tv_usec=0;
260 FD_ZERO(&fds);
261 FD_SET(fd,&fds);
263 packet[0]=P_NEW_PLAYER;
264 packet[1]=0;
265 packet[2]=VERSION_MAJOR;
266 packet[3]=VERSION_MINOR;
267 packet[4]=color;
268 memcpy(packet+5,name,l);
270 send_packet(packet,l+5,(struct sockaddr*)(&server),my_id,0);
273 if (!select(fd+1,&fds,NULL,NULL,&tv))return "No reply within 4 seconds.\n";
275 if ((r=recv_packet(packet,256,0,0,1,0,0))<0)
277 if (errno==EINTR)return "Server hung up.\n";
278 else return "Connection error.\n";
281 switch(*packet)
283 case P_PLAYER_REFUSED:
284 switch(packet[1])
286 case E_INCOMPATIBLE_VERSION:
287 return "Incompatible client version. Connection refused.\n";
289 case E_NAME_IN_USE:
290 return "This name is already in use. Connection refused.\n";
292 default:
293 return "Connection refused.\n";
296 case P_PLAYER_ACCEPTED:
297 my_id=get_int(packet+35);
298 if (r<41){send_quit();return "Incompatible server version. Givin' up.\n";}
299 maj=packet[39];
300 min=packet[40];
301 if (maj!=VERSION_MAJOR||min<MIN_SERVER_VERSION_MINOR)
302 {send_quit();return "Incompatible server version. Givin' up.\n";}
303 game_start_offset=get_time();
304 game_start_offset-=get_long_long(packet+27);
305 health=100;
306 armor=0;
307 for(a=0;a<ARMS;a++)
308 ammo[a]=0;
309 ammo[0]=weapon[0].basic_ammo;
310 current_weapon=0;
311 weapons = WEAPON_MASK_GUN |
312 WEAPON_MASK_GRENADE |
313 WEAPON_MASK_CHAINSAW |
314 WEAPON_MASK_BLOODRAIN; /* gun, grenades, chainsaw
315 and bloodrain */
316 hero=new_obj(
317 get_int(packet+1), /* ID */
318 T_PLAYER, /* type */
319 0, /* time to live */
320 get_int16(packet+5), /* sprite */
321 0, /* position */
322 get_int(packet+23), /* status */
323 get_int(packet+7), /* X */
324 get_int(packet+11), /* Y */
325 get_int(packet+15), /* XSPEED */
326 get_int(packet+19), /* YSPEED */
329 break;
331 default:
332 return "Connection error.\n";
334 return 0;
338 /* I want to be born again */
339 static void send_reenter_game(void)
341 char packet;
342 packet=P_REENTER_GAME;
343 send_packet(&packet,1,(struct sockaddr*)(&server),my_id,0);
347 /* send chat message */
348 static void send_message(char *msg)
350 static char packet[MAX_MESSAGE_LENGTH + 2];
351 int len;
353 len = strlen(msg) + 1;
354 packet[0] = P_MESSAGE;
355 packet[1] = 0x00;
356 memcpy(packet + 2, msg, len);
357 send_packet(packet, len + 2, (struct sockaddr *)(&server), my_id, 0);
361 /* send end of game to server */
362 static void send_keyboard(void)
364 char packet[3];
365 packet[0]=P_KEYBOARD;
366 packet[1]= keyboard_status.right|
367 (keyboard_status.left<<1)|
368 (keyboard_status.jump<<2)|
369 (keyboard_status.creep<<3)|
370 (keyboard_status.speed<<4)|
371 (keyboard_status.fire<<5)|
372 (keyboard_status.down_ladder<<6);
373 packet[2]= keyboard_status.weapon;
374 send_packet(packet,3,(struct sockaddr*)(&server),my_id,0);
378 static void reset_keyboard(void)
380 keyboard_status.left=0;
381 keyboard_status.right=0;
382 keyboard_status.speed=1;
383 keyboard_status.jump=0;
384 keyboard_status.creep=0;
385 keyboard_status.fire=0;
386 keyboard_status.weapon=0;
387 keyboard_status.down_ladder=0;
391 static void test_object(struct it *obj)
393 if (obj==hero)return;
394 if (!can_see(obj->x,obj->y))return;
395 switch(obj->type)
397 case T_PLAYER:
398 if (obj->status&S_INVISIBLE)
399 break;
400 if (priority>1)
401 break;
402 priority=1;
403 keyboard_status.fire=1;
404 if (obj->x>hero->x)direction=2;
405 else direction=1;
406 if (my_abs(obj->x-hero->x)<int2double(30))direction=0;
407 break;
409 case T_BULLET:
410 case T_SHRAPNEL:
411 case T_BFGCELL:
412 case T_CHAIN:
413 if ((my_sgn(hero->x-obj->x)==my_sgn(obj->xspeed)||my_abs(hero->x-obj->x)<int2double(20))&&obj->y>=hero->y&&obj->y<hero->y+int2double(PLAYER_HEIGHT))
414 keyboard_status.creep=1;
415 break;
417 case T_RIFLE:
418 if (priority>2)break;
419 if ((weapons&(1<<WEAPON_RIFLE))&&ammo[WEAPON_RIFLE])break;
420 priority=2;
421 if (obj->x>hero->x)direction=2;
422 else direction=1;
423 break;
425 case T_SHOTGUN:
426 if (priority>3)break;
427 if ((weapons&(1<<WEAPON_SHOTGUN))&&ammo[WEAPON_SHOTGUN])break;
428 priority=3;
429 if (obj->x>hero->x)direction=2;
430 else direction=1;
431 break;
433 case T_UZI:
434 if (priority>4)break;
435 if ((weapons&(1<<WEAPON_UZI))&&ammo[WEAPON_UZI])break;
436 priority=4;
437 if (obj->x>hero->x)direction=2;
438 else direction=1;
439 break;
441 case T_AMMO_GRENADE:
442 if (priority>5)break;
443 if (!(weapons&(1<<WEAPON_GRENADE))||ammo[WEAPON_GRENADE])break;
444 priority=5;
445 if (obj->x>hero->x)direction=2;
446 else direction=1;
447 break;
449 case T_AMMO_GUN:
450 if (priority>6)break;
451 if (!(weapons&(1<<WEAPON_GUN))||ammo[WEAPON_GUN])break;
452 priority=6;
453 if (obj->x>hero->x)direction=2;
454 else direction=1;
455 break;
457 case T_AMMO_SHOTGUN:
458 if (priority>7)break;
459 if (!(weapons&(1<<WEAPON_SHOTGUN))||ammo[WEAPON_SHOTGUN])break;
460 priority=7;
461 if (obj->x>hero->x)direction=2;
462 else direction=1;
463 break;
465 case T_AMMO_RIFLE:
466 if (priority>8)break;
467 if (!(weapons&(1<<WEAPON_RIFLE))||ammo[WEAPON_RIFLE])break;
468 priority=8;
469 if (obj->x>hero->x)direction=2;
470 else direction=1;
471 break;
473 case T_AMMO_UZI:
474 if (priority>9)break;
475 if (!(weapons&(1<<WEAPON_UZI))||ammo[WEAPON_UZI])break;
476 priority=9;
477 if (obj->x>hero->x)direction=2;
478 else direction=1;
479 break;
481 case T_MEDIKIT:
482 if (priority>10)break;
483 if (health>70)break;
484 priority=10;
485 if (obj->x>hero->x)direction=2;
486 else direction=1;
487 break;
493 /* destroys all objects except hero (before level change) */
494 static void clean_memory(void)
496 struct object_list *o;
498 /* delete all objects except hero */
499 for (o=&objects;o->next;)
500 if ((hero->id)!=(o->next->member.id))delete_obj(o->next->member.id);
501 else o=o->next;
505 static void change_level(void)
507 char *LEVEL;
508 char txt[256];
510 clean_memory();
511 free_sprites(level_sprites_start);
512 reinit_area();
514 LEVEL=load_level(level_number);
515 snprintf(txt,256,"Loading level \"%s\".\n",LEVEL);
516 ERROR(txt);
517 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,LEVEL_SPRITES_SUFFIX);
518 load_sprites(txt);
519 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,STATIC_DATA_SUFFIX);
520 load_data(txt);
521 mem_free(LEVEL);
525 /* recompute object positions */
526 static void update_game(void)
528 struct object_list *p;
529 int w,h;
530 unsigned char stop_x,stop_y,sy;
531 unsigned long_long t;
532 int x,y,x1,y1,DELTA_TIME;
534 for(p=&objects;p->next;p=p->next)
536 if (p->next->member.type == T_NOTHING)
537 continue;
538 if (p->next->member.status & S_DEAD)
539 continue; /* dead player */
540 /* decrement time to live */
541 if (p->next->member.ttl>0)
543 p->next->member.ttl--;
544 if (!p->next->member.ttl)
546 if ((p->next->member.type)==T_PLAYER)
547 p->next->member.status &= ~S_SHOOTING;
548 else
550 if (p->next->member.type!=T_GRENADE){ /* client's waiting for P_EXPLODE_GRENADE and doesn't delete the grenade yet */
551 p=p->prev;
552 delete_obj(p->next->next->member.id);
553 continue;}
557 test_object(&(p->next->member));
558 /* maintain only objects that you are allowed to maintain */
559 if (!(obj_attr[p->next->member.type].maintainer&1))continue;
562 /* if not falling slow down x motion */
563 if (!(p->next->member.status & S_FALLING))
564 p->next->member.xspeed=mul(p->next->member.xspeed,obj_attr[p->next->member.type].slow_down_x);
566 /* fall */
567 if (obj_attr[p->next->member.type].fall)
569 p->next->member.status |= S_FALLING;
570 p->next->member.yspeed+=FALL_ACCEL;
571 /* but not too fast */
572 if (p->next->member.yspeed>MAX_Y_SPEED)p->next->member.yspeed=MAX_Y_SPEED;
575 get_dimensions(p->next->member.type,p->next->member.status,sprites[p->next->member.sprite].positions,&w,&h);
576 x=p->next->member.x;
577 y=p->next->member.y;
578 t=get_time();
579 DELTA_TIME=float2double(((double)(long_long)(t-p->next->member.last_updated))/MICROSECONDS);
580 update_position(
581 &(p->next->member),
582 p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
583 p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
584 w,h,&stop_x,&stop_y);
585 p->next->member.last_updated=t;
587 /* walk up the stairs */
588 if (stop_x&&p->next->member.type==T_PLAYER&&!(p->next->member.status & S_CREEP))
590 x1=p->next->member.x;
591 y1=p->next->member.y;
592 p->next->member.x=x;
593 p->next->member.y=y-int2double(1);
594 update_position(
595 &(p->next->member),
596 p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
597 p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
598 w,h,0,&sy);
599 if ((p->next->member.xspeed>0&&p->next->member.x<=x1)||(p->next->member.xspeed<0&&p->next->member.x>=x1)) /* restore original values */
601 p->next->member.x=x1;
602 p->next->member.y=y1;
604 else
606 stop_y=sy;
607 stop_x=0;
611 if (stop_x)p->next->member.xspeed=-mul(p->next->member.xspeed,obj_attr[p->next->member.type].bounce_x);
612 if (my_abs(p->next->member.xspeed)<MIN_X_SPEED)
614 p->next->member.xspeed=0;
615 p->next->member.status &= ~S_WALKING;
619 if (stop_y)
621 p->next->member.yspeed=mul(p->next->member.yspeed,obj_attr[p->next->member.type].bounce_y);
622 p->next->member.yspeed=-p->next->member.yspeed;
623 if (my_abs(p->next->member.yspeed)<MIN_Y_SPEED)
625 p->next->member.yspeed=0;
626 if (stop_y==1)p->next->member.status &= ~S_FALLING;
630 if ((p->next->member.type == T_SHRAPNEL || p->next->member.type == T_BULLET ||
631 p->next->member.type == T_BFGCELL || p->next->member.type == T_CHAIN) &&
632 (stop_x || stop_y)) { /* bullet and shrapnel die crashing into wall */
633 p=p->prev; /* deleting object makes a great mess in for cycle, so we must cheat the cycle */
634 delete_obj(p->next->next->member.id);
635 continue;
642 /* returns number of read bytes */
643 static int process_packet(char *packet,int l)
645 int a,n=l;
647 switch(*packet)
649 case P_CHUNK:
650 for (a=1;a<l&&a<MAX_PACKET_LENGTH;a+=n)
651 n=process_packet(packet+a,l-a);
652 break;
654 case P_NEW_OBJ:
655 if (l < (n=30))break; /* invalid packet */
656 new_obj(
657 get_int(packet+1), /* ID */
658 packet[27], /* type */
659 get_int16(packet+28), /* time to live */
660 get_int16(packet+5), /* sprite */
661 0, /* anim position */
662 get_int(packet+23), /* status */
663 get_int(packet+7), /* x */
664 get_int(packet+11), /* y */
665 get_int(packet+15), /* xspeed */
666 get_int(packet+19), /* yspeed */
667 0 /* data */
669 break;
671 case P_PLAYER_DELETED:
672 n=1;
673 shut_down(1);
674 break;
676 case P_DELETE_OBJECT:
677 if (l<5)break; /* invalid packet */
678 delete_obj(get_int(packet+1));
679 n=5;
680 break;
682 case P_UPDATE_OBJECT:
683 if (l < (n=28))break; /* invalid packet */
685 struct object_list *p;
687 p=find_in_table(get_int(packet+1));
688 if (!p)break;
689 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
690 p->member.update_counter=packet[5];
691 p->member.x=get_int(packet+6);
692 p->member.y=get_int(packet+10);
693 p->member.xspeed=get_int(packet+14);
694 p->member.yspeed=get_int(packet+18);
695 p->member.status=get_int(packet+22);
696 p->member.data=0;
697 p->member.ttl=get_int16(packet+26);
698 /* kdyz tasi, tak se nahodi ttl */
699 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
700 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
702 break;
704 case P_UPDATE_OBJECT_POS:
705 if (l<22)break; /* invalid packet */
707 struct object_list *p;
709 n=22;
710 p=find_in_table(get_int(packet+1));
711 if (!p)break;
712 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
713 p->member.update_counter=packet[5];
714 p->member.x=get_int(packet+6);
715 p->member.y=get_int(packet+10);
716 p->member.xspeed=get_int(packet+14);
717 p->member.yspeed=get_int(packet+18);
719 break;
721 case P_UPDATE_OBJECT_SPEED:
722 if (l<14)break; /* invalid packet */
724 struct object_list *p;
726 n=14;
727 p=find_in_table(get_int(packet+1));
728 if (!p)break;
729 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
730 p->member.update_counter=packet[5];
731 p->member.xspeed=get_int(packet+6);
732 p->member.yspeed=get_int(packet+10);
734 break;
736 case P_UPDATE_OBJECT_COORDS:
737 if (l<14)break; /* invalid packet */
739 struct object_list *p;
741 n=14;
742 p=find_in_table(get_int(packet+1));
743 if (!p)break;
744 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
745 p->member.update_counter=packet[5];
746 p->member.x=get_int(packet+6);
747 p->member.y=get_int(packet+10);
749 break;
751 case P_UPDATE_OBJECT_SPEED_STATUS:
752 if (l < (n=18))break; /* invalid packet */
754 struct object_list *p;
756 p=find_in_table(get_int(packet+1));
757 if (!p)break;
758 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
759 p->member.update_counter=packet[5];
760 p->member.xspeed=get_int(packet+6);
761 p->member.yspeed=get_int(packet+10);
762 p->member.status=get_int(packet+14);
763 /* kdyz tasi, tak se nahodi ttl */
764 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
765 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
767 break;
769 case P_UPDATE_OBJECT_COORDS_STATUS:
770 if (l < (n=18))break; /* invalid packet */
772 struct object_list *p;
774 p=find_in_table(get_int(packet+1));
775 if (!p)break;
776 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
777 p->member.update_counter=packet[5];
778 p->member.x=get_int(packet+6);
779 p->member.y=get_int(packet+10);
780 p->member.status=get_int(packet+14);
781 /* kdyz tasi, tak se nahodi ttl */
782 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
783 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
785 break;
787 case P_UPDATE_OBJECT_SPEED_STATUS_TTL:
788 if (l < (n=20))break; /* invalid packet */
790 struct object_list *p;
792 p=find_in_table(get_int(packet+1));
793 if (!p)break;
794 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
795 p->member.update_counter=packet[5];
796 p->member.xspeed=get_int(packet+6);
797 p->member.yspeed=get_int(packet+10);
798 p->member.status=get_int(packet+14);
799 p->member.ttl=get_int16(packet+18);
800 /* kdyz tasi, tak se nahodi ttl */
801 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
802 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
804 break;
806 case P_UPDATE_OBJECT_COORDS_STATUS_TTL:
807 if (l < (n=20))break; /* invalid packet */
809 struct object_list *p;
811 p=find_in_table(get_int(packet+1));
812 if (!p)break;
813 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
814 p->member.update_counter=packet[5];
815 p->member.x=get_int(packet+6);
816 p->member.y=get_int(packet+10);
817 p->member.status=get_int(packet+14);
818 p->member.ttl=get_int16(packet+18);
819 /* kdyz tasi, tak se nahodi ttl */
820 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
821 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
823 break;
825 case P_UPDATE_STATUS:
826 if (l < (n=9))break; /* invalid packet */
828 struct object_list *p;
830 p=find_in_table(get_int(packet+1));
831 if (!p)break; /* ignore objects we don't have */
832 p->member.status=get_int(packet+5);
833 /* kdyz tasi, tak se nahodi ttl */
834 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
835 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
837 break;
839 case P_HIT:
840 if (l<8)break; /* invalid packet */
842 struct object_list *p;
844 n=8;
845 p=find_in_table(get_int(packet+1));
846 if (!p)break; /* ignore objects we don't have */
847 p->member.status |= S_HIT;
848 p->member.data=(void*)(long)((packet[5]<<16)+(packet[7]<<8)+(packet[6]));
849 /* kdyz tasi, tak se nahodi ttl */
850 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
851 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
853 break;
855 case P_UPDATE_PLAYER:
856 if (l<15+2*ARMS)break; /* invalid packet */
857 health=packet[1];
858 armor=packet[2];
859 for (a=0;a<ARMS;a++)
860 ammo[a]=get_int16(packet+3+(a<<1));
861 frags=get_int(packet+3+ARMS*2);
862 deaths=get_int(packet+7+ARMS*2);
863 current_weapon=get_int16(packet+11+2*ARMS);
864 weapons=get_int16(packet+13+2*ARMS);
865 n=15+2*ARMS;
866 break;
868 case P_MESSAGE:
869 if (l < 3)
870 break; /* invalid packet */
871 n = 3 + strlen(packet + 2);
872 break;
874 case P_END:
875 if (l<2)printf("Game terminated.\n");
876 else printf("Game terminated by %s.\n",packet+1);
877 n=2+strlen(packet+1);
878 shut_down(1);
880 case P_INFO:
881 if (l<=5)break;
882 l=6;
883 for (a=0;a<packet[5]&&a<TOP_PLAYERS_N;a++)
885 int x;
886 x=strlen(packet+l+9)+1;
887 l+=x+9;
889 n=l;
890 break;
892 case P_EXPLODE_GRENADE:
893 case P_EXPLODE_BFG:
895 unsigned int i,j;
896 struct object_list *p;
897 int b;
899 if (l<9)break;
900 n=9;
901 i=get_int(packet+1);
902 j=get_int(packet+5);
903 p=find_in_table(j);
904 if (!p)break;
906 for (b=0;b<N_SHRAPNELS_EXPLODE;b++)
908 double angle=(double)b*2*M_PI/N_SHRAPNELS_EXPLODE;
909 int spd=add_int(mul_int(my_and(mul_int(weapon[WEAPON_GRENADE].speed,b+1),15),16),100);
911 new_obj(
913 T_SHRAPNEL,
914 SHRAPNEL_TTL,
917 WEAPON_GRENADE,
918 p->member.x,
919 p->member.y,
920 p->member.xspeed+mul(spd,float2double(cos(angle))),
921 p->member.yspeed+mul(spd,float2double(sin(angle))),
922 0);
923 i++;
925 delete_obj(j);
928 break;
930 case P_CHANGE_LEVEL:
932 char *md5;
933 int a;
934 char p;
936 if (l<38)break; /* invalid packet */
937 a=get_int(packet+1);
938 if (level_number==a)goto level_changed;
939 level_number=a;
941 md5=md5_level(level_number);
942 if (strcmp((char *)md5,packet+5)) /* MD5s differ */
944 mem_free(md5);
945 ERROR("Invalid MD5 sum. Can't change level. Exiting...");
946 send_quit();
947 shut_down(1);
949 mem_free(md5);
951 /* OK we can change it */
952 change_level();
953 level_changed:
955 p=P_LEVEL_ACCEPTED;
956 send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
957 n=38;
959 break;
962 return n;
966 /* read packet from socket */
967 static void read_data(void)
969 fd_set rfds;
970 struct timeval tv;
971 struct sockaddr_in client;
972 static char packet[MAX_PACKET_LENGTH];
973 int a=sizeof(client);
974 int l;
976 tv.tv_sec=0;
977 tv.tv_usec=0;
978 FD_ZERO(&rfds);
979 FD_SET(fd,&rfds);
980 while(select(fd+1,&rfds,0,0,&tv))
982 if ((l=recv_packet(packet,MAX_PACKET_LENGTH,(struct sockaddr*)(&client),&a,1,my_id,0))<0)
983 return; /* something's strange */
984 process_packet(packet,l);
990 /* handle fatal signal (sigabrt, sigsegv, ...) */
991 static void signal_handler(int signum)
994 if (connected)send_quit();
995 shut_down(0);
996 clear_memory();
997 if (fd) close(fd);
998 #ifdef HAVE_PSIGNAL
999 psignal(signum,"Exiting on signal");
1000 #else
1001 fprintf(stderr, "Exiting on signal: %d\n", signum);
1002 #endif
1003 if (!in_signal_handler){in_signal_handler=1;check_memory_leaks();}
1004 free_packet_buffer();
1005 EXIT(1);
1009 /* print command line help */
1010 static void print_help(void)
1012 printf(
1013 "0verkill bot"
1014 ".\n"
1015 "(c)2000 Brainsoft\n"
1016 "Usage: bot [-h] -a <server address> [-p <port>]"
1017 "\n"
1022 static void parse_command_line(int argc,char **argv)
1024 int a;
1025 char *e;
1027 while(1)
1029 a=getopt(argc,argv,"hp:a:");
1030 switch(a)
1032 case EOF:
1033 return;
1035 case '?':
1036 case ':':
1037 EXIT(1);
1039 case 'h':
1040 print_help();
1041 EXIT(0);
1043 case 'a':
1044 host=optarg;
1045 break;
1047 case 'p':
1048 port=(unsigned short)strtoul(optarg,&e,10);
1049 if (*e){ERROR("Error: Decimal number expected.\n");EXIT(1);}
1050 break;
1056 static char * select_name(void)
1058 return names[(random())%N_NAMES];
1062 static void where2go(void)
1064 if (!direction)
1066 if (odds(20+const2))direction=2;
1067 if (odds(20+const2))direction=1;
1069 if(direction==1)keyboard_status.left=1;
1070 if(direction==2)keyboard_status.right=1;
1072 if (odds(40+const1))keyboard_status.jump=1;
1073 if (odds(100+const4))keyboard_status.down_ladder=1;
1074 if (odds(3)+const3)keyboard_status.fire=1;
1079 static void action(void)
1081 if (hero->status & S_DEAD)
1082 send_reenter_game(); /* respawn */
1083 where2go();
1086 /*----------------------------------------------------------------------------*/
1087 int main(int argc,char **argv)
1089 int color;
1090 unsigned long_long last_time;
1091 char *m;
1094 #ifdef WIN32
1095 WSADATA wd;
1097 WSAStartup(0x101, &wd);
1098 printf("Started WinSock version %X.%02X\n", wd.wVersion/0x100, wd.wVersion&0xFF);
1099 #endif
1101 chdir_to_data_files();
1102 ERROR("Initialization...\n");
1104 last_obj=&objects;
1105 srandom(get_time());
1107 const1=random()%50;
1108 const2=random()%20;
1109 const3=random()%5;
1110 const4=random()%20;
1112 host=NULL;
1113 parse_command_line(argc,argv);
1114 if (!host){ERROR("No server address specified.\n");EXIT(1);}
1115 hash_table_init();
1116 init_sprites();
1117 init_area();
1118 ERROR("Loading graphics...\n");
1119 load_sprites(DATA_PATH GAME_SPRITES_FILE);
1120 level_sprites_start=n_sprites;
1122 signal(SIGINT,signal_handler);
1123 signal(SIGTERM,signal_handler);
1124 signal(SIGILL,signal_handler);
1125 signal(SIGABRT,signal_handler);
1126 signal(SIGFPE,signal_handler);
1127 signal(SIGSEGV,signal_handler);
1128 #ifndef WIN32
1129 signal(SIGQUIT,signal_handler);
1130 signal(SIGBUS,signal_handler);
1131 #endif
1133 ERROR("Resolving server address ...\n");
1134 if ((m=find_server(host,port))){ERROR(m);EXIT(1);}
1135 ERROR("Initializing socket ...\n");
1136 if ((m=init_socket())){ERROR(m);EXIT(1);}
1137 ERROR("Contacting server ...\n");
1138 color=(random()%15)+1;
1139 if ((m=contact_server(color,select_name()))){ERROR(m);EXIT(1);}
1141 connected=1;
1142 ERROR("OK, connected.\nPlaying...\n");
1144 last_time=get_time();
1145 again:
1146 last_time+=CLIENT_PERIOD_USEC;
1147 if (get_time()-last_time>PERIOD_USEC*100)last_time=get_time();
1148 read_data();
1149 reset_keyboard();
1150 priority=0;
1151 update_game();
1152 action();
1153 send_keyboard();
1154 sleep_until(last_time+CLIENT_PERIOD_USEC);
1155 goto again;
1156 if (fd) close(fd);