editor: #undef O after use
[0verkill.git] / bot.c
blob6749c7e24fd4c099c509110b3d4581e607c312a7
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;
95 /* for use with the -n option */
96 static char *static_name=NULL;
98 /* connection with server */
99 static int connected=0;
101 int console_ok=1;
103 /* networking */
104 int fd; /* socket */
105 static struct sockaddr_in server; /* server address */
107 /* objects */
108 static struct object_list objects;
109 struct object_list *last_obj;
110 static struct it* hero;
112 static unsigned long_long game_start_offset; /* time difference between game start on this machine and on server */
115 static struct /* keyboard status */
117 unsigned char right,left,jump,creep,speed,fire,weapon,down_ladder;
118 }keyboard_status;
121 static char *names[N_NAMES]={
122 "Terminator",
123 "Jack The Ripper",
124 "Rambo",
125 "Exhumator",
126 "Assassin",
127 "Arnold",
128 "Necromancer",
129 "Predator",
130 "Rocky",
131 "Harvester",
132 "Lamer",
133 "Killme",
134 "Looser",
135 "Krueger",
136 "I'll kill you",
137 "Zombieman",
138 "Hellraiser",
139 "Eraser"
142 static int direction=0; /* 0=stop, 1=left, 2=right */
143 static int const1,const2,const3,const4;
144 static unsigned short port=DEFAULT_PORT;
145 static char *host;
146 static int priority;
147 /* 0=nothing
148 * 1=kill player
149 * 2=find rifle
150 * 3=find shotgun
151 * 4=find UZI
152 * 5=find grenades
153 * 6=find gun ammo
154 * 7=find shotgun ammo
155 * 8=find rifle ammo
156 * 9=find uzi ammo
157 * 10=find medikit
160 /*-----------------------------------------------------------------------*/
163 #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))
166 static int odds(int p)
168 return (random()%1000)<p;
172 /* free all before exit */
173 static void clear_memory(void)
175 struct object_list *o;
177 for (o=&objects;o->next;)
178 delete_obj(o->next->member.id);
179 free_area();
180 shutdown_sprites();
181 free_sprites(0);
185 /* shut down the client */
186 static void shut_down(int a)
188 if (a)
190 clear_memory();
191 free_packet_buffer();
192 check_memory_leaks();
193 EXIT(0);
198 /* find address of server and fill the server address structure */
199 static char * find_server(char *name,unsigned short port)
201 struct hostent *h;
203 h=gethostbyname(name);
204 if (!h)return "Error: Can't resolve server address.\n";
206 server.sin_family=AF_INET;
207 server.sin_port=htons(port);
208 server.sin_addr=*((struct in_addr*)(h->h_addr_list[0]));
209 return 0;
213 /* initialize socket */
214 static char * init_socket(void)
216 fd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
217 if(fd<0)return "Can't get socket.\n";
218 return 0;
222 #define MAX_COUNT 32
224 /* send quit request to server */
225 static void send_quit(void)
227 char p;
228 fd_set rfds;
229 struct timeval tv;
230 int a=sizeof(server);
231 int count=0;
233 tv.tv_sec=2;
234 tv.tv_usec=0;
235 FD_ZERO(&rfds);
236 FD_SET(fd,&rfds);
238 send_again:
239 p=P_QUIT_REQUEST;
240 count ++;
241 send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
242 if (!select(fd+1,&rfds,0,0,&tv)&&count<=MAX_COUNT)goto send_again;
243 recv_packet(&p,1,(struct sockaddr*)(&server),&a,1,my_id,0);
244 if (p!=P_PLAYER_DELETED&&count<=MAX_COUNT)goto send_again;
247 #undef MAX_COUNT
250 /* initiate connection with server */
251 static char * contact_server(int color, char *name)
253 static char packet[256];
254 int l=strlen(name)+1;
255 int a,r;
256 int min,maj;
258 fd_set fds;
259 struct timeval tv;
260 tv.tv_sec=4;
261 tv.tv_usec=0;
262 FD_ZERO(&fds);
263 FD_SET(fd,&fds);
265 packet[0]=P_NEW_PLAYER;
266 packet[1]=0;
267 packet[2]=VERSION_MAJOR;
268 packet[3]=VERSION_MINOR;
269 packet[4]=color;
270 if (l>MAX_NAME_LEN) {l=MAX_NAME_LEN; packet[5+MAX_NAME_LEN]='\0';}
271 memcpy(packet+5,name,l);
273 printf("Using name \"%s\".\n", packet+5);
275 send_packet(packet,l+5,(struct sockaddr*)(&server),my_id,0);
278 if (!select(fd+1,&fds,NULL,NULL,&tv))return "No reply within 4 seconds.\n";
280 if ((r=recv_packet(packet,256,0,0,1,0,0))<0)
282 if (errno==EINTR)return "Server hung up.\n";
283 else return "Connection error.\n";
286 switch(*packet)
288 case P_PLAYER_REFUSED:
289 switch(packet[1])
291 case E_INCOMPATIBLE_VERSION:
292 return "Incompatible client version. Connection refused.\n";
294 case E_NAME_IN_USE:
295 return "This name is already in use. Connection refused.\n";
297 default:
298 return "Connection refused.\n";
301 case P_PLAYER_ACCEPTED:
302 my_id=get_int(packet+35);
303 if (r<41){send_quit();return "Incompatible server version. Givin' up.\n";}
304 maj=packet[39];
305 min=packet[40];
306 if (maj!=VERSION_MAJOR||min<MIN_SERVER_VERSION_MINOR)
307 {send_quit();return "Incompatible server version. Givin' up.\n";}
308 game_start_offset=get_time();
309 game_start_offset-=get_long_long(packet+27);
310 health=100;
311 armor=0;
312 for(a=0;a<ARMS;a++)
313 ammo[a]=0;
314 ammo[0]=weapon[0].basic_ammo;
315 current_weapon=0;
316 weapons = WEAPON_MASK_GUN |
317 WEAPON_MASK_GRENADE |
318 WEAPON_MASK_CHAINSAW |
319 WEAPON_MASK_BLOODRAIN; /* gun, grenades, chainsaw
320 and bloodrain */
321 hero=new_obj(
322 get_int(packet+1), /* ID */
323 T_PLAYER, /* type */
324 0, /* time to live */
325 get_int16(packet+5), /* sprite */
326 0, /* position */
327 get_int(packet+23), /* status */
328 get_int(packet+7), /* X */
329 get_int(packet+11), /* Y */
330 get_int(packet+15), /* XSPEED */
331 get_int(packet+19), /* YSPEED */
334 break;
336 default:
337 return "Connection error.\n";
339 return 0;
343 /* I want to be born again */
344 static void send_reenter_game(void)
346 char packet;
347 packet=P_REENTER_GAME;
348 send_packet(&packet,1,(struct sockaddr*)(&server),my_id,0);
352 /* send chat message */
353 static void send_message(char *msg)
355 static char packet[MAX_MESSAGE_LENGTH + 2];
356 int len;
358 len = strlen(msg) + 1;
359 packet[0] = P_MESSAGE;
360 packet[1] = 0x00;
361 memcpy(packet + 2, msg, len);
362 send_packet(packet, len + 2, (struct sockaddr *)(&server), my_id, 0);
366 /* send end of game to server */
367 static void send_keyboard(void)
369 char packet[3];
370 packet[0]=P_KEYBOARD;
371 packet[1]= keyboard_status.right|
372 (keyboard_status.left<<1)|
373 (keyboard_status.jump<<2)|
374 (keyboard_status.creep<<3)|
375 (keyboard_status.speed<<4)|
376 (keyboard_status.fire<<5)|
377 (keyboard_status.down_ladder<<6);
378 packet[2]= keyboard_status.weapon;
379 send_packet(packet,3,(struct sockaddr*)(&server),my_id,0);
383 static void reset_keyboard(void)
385 keyboard_status.left=0;
386 keyboard_status.right=0;
387 keyboard_status.speed=1;
388 keyboard_status.jump=0;
389 keyboard_status.creep=0;
390 keyboard_status.fire=0;
391 keyboard_status.weapon=0;
392 keyboard_status.down_ladder=0;
396 static void test_object(struct it *obj)
398 if (obj==hero)return;
399 if (!can_see(obj->x,obj->y))return;
400 switch(obj->type)
402 case T_PLAYER:
403 if (obj->status&S_INVISIBLE)
404 break;
405 if (priority>1)
406 break;
407 priority=1;
408 keyboard_status.fire=1;
409 if (obj->x>hero->x)direction=2;
410 else direction=1;
411 if (my_abs(obj->x-hero->x)<int2double(30))direction=0;
412 break;
414 case T_BULLET:
415 case T_SHRAPNEL:
416 case T_BFGCELL:
417 case T_CHAIN:
418 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))
419 keyboard_status.creep=1;
420 break;
422 case T_RIFLE:
423 if (priority>2)break;
424 if ((weapons&(1<<WEAPON_RIFLE))&&ammo[WEAPON_RIFLE])break;
425 priority=2;
426 if (obj->x>hero->x)direction=2;
427 else direction=1;
428 break;
430 case T_SHOTGUN:
431 if (priority>3)break;
432 if ((weapons&(1<<WEAPON_SHOTGUN))&&ammo[WEAPON_SHOTGUN])break;
433 priority=3;
434 if (obj->x>hero->x)direction=2;
435 else direction=1;
436 break;
438 case T_UZI:
439 if (priority>4)break;
440 if ((weapons&(1<<WEAPON_UZI))&&ammo[WEAPON_UZI])break;
441 priority=4;
442 if (obj->x>hero->x)direction=2;
443 else direction=1;
444 break;
446 case T_AMMO_GRENADE:
447 if (priority>5)break;
448 if (!(weapons&(1<<WEAPON_GRENADE))||ammo[WEAPON_GRENADE])break;
449 priority=5;
450 if (obj->x>hero->x)direction=2;
451 else direction=1;
452 break;
454 case T_AMMO_GUN:
455 if (priority>6)break;
456 if (!(weapons&(1<<WEAPON_GUN))||ammo[WEAPON_GUN])break;
457 priority=6;
458 if (obj->x>hero->x)direction=2;
459 else direction=1;
460 break;
462 case T_AMMO_SHOTGUN:
463 if (priority>7)break;
464 if (!(weapons&(1<<WEAPON_SHOTGUN))||ammo[WEAPON_SHOTGUN])break;
465 priority=7;
466 if (obj->x>hero->x)direction=2;
467 else direction=1;
468 break;
470 case T_AMMO_RIFLE:
471 if (priority>8)break;
472 if (!(weapons&(1<<WEAPON_RIFLE))||ammo[WEAPON_RIFLE])break;
473 priority=8;
474 if (obj->x>hero->x)direction=2;
475 else direction=1;
476 break;
478 case T_AMMO_UZI:
479 if (priority>9)break;
480 if (!(weapons&(1<<WEAPON_UZI))||ammo[WEAPON_UZI])break;
481 priority=9;
482 if (obj->x>hero->x)direction=2;
483 else direction=1;
484 break;
486 case T_MEDIKIT:
487 if (priority>10)break;
488 if (health>70)break;
489 priority=10;
490 if (obj->x>hero->x)direction=2;
491 else direction=1;
492 break;
498 /* destroys all objects except hero (before level change) */
499 static void clean_memory(void)
501 struct object_list *o;
503 /* delete all objects except hero */
504 for (o=&objects;o->next;)
505 if ((hero->id)!=(o->next->member.id))delete_obj(o->next->member.id);
506 else o=o->next;
510 static void change_level(void)
512 char *LEVEL;
513 char txt[256];
515 clean_memory();
516 free_sprites(level_sprites_start);
517 reinit_area();
519 LEVEL=load_level(level_number);
520 snprintf(txt,256,"Loading level \"%s\".\n",LEVEL);
521 ERROR(txt);
522 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,LEVEL_SPRITES_SUFFIX);
523 load_sprites(txt);
524 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,STATIC_DATA_SUFFIX);
525 load_data(txt);
526 mem_free(LEVEL);
530 /* recompute object positions */
531 static void update_game(void)
533 struct object_list *p;
534 int w,h;
535 unsigned char stop_x,stop_y,sy;
536 unsigned long_long t;
537 int x,y,x1,y1,DELTA_TIME;
539 for(p=&objects;p->next;p=p->next)
541 if (p->next->member.type == T_NOTHING)
542 continue;
543 if (p->next->member.status & S_DEAD)
544 continue; /* dead player */
545 /* decrement time to live */
546 if (p->next->member.ttl>0)
548 p->next->member.ttl--;
549 if (!p->next->member.ttl)
551 if ((p->next->member.type)==T_PLAYER)
552 p->next->member.status &= ~S_SHOOTING;
553 else
555 if (p->next->member.type!=T_GRENADE){ /* client's waiting for P_EXPLODE_GRENADE and doesn't delete the grenade yet */
556 p=p->prev;
557 delete_obj(p->next->next->member.id);
558 continue;}
562 test_object(&(p->next->member));
563 /* maintain only objects that you are allowed to maintain */
564 if (!(obj_attr[p->next->member.type].maintainer&1))continue;
567 /* if not falling slow down x motion */
568 if (!(p->next->member.status & S_FALLING))
569 p->next->member.xspeed=mul(p->next->member.xspeed,obj_attr[p->next->member.type].slow_down_x);
571 /* fall */
572 if (obj_attr[p->next->member.type].fall)
574 p->next->member.status |= S_FALLING;
575 p->next->member.yspeed+=FALL_ACCEL;
576 /* but not too fast */
577 if (p->next->member.yspeed>MAX_Y_SPEED)p->next->member.yspeed=MAX_Y_SPEED;
580 get_dimensions(p->next->member.type,p->next->member.status,sprites[p->next->member.sprite].positions,&w,&h);
581 x=p->next->member.x;
582 y=p->next->member.y;
583 t=get_time();
584 DELTA_TIME=float2double(((double)(long_long)(t-p->next->member.last_updated))/MICROSECONDS);
585 update_position(
586 &(p->next->member),
587 p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
588 p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
589 w,h,&stop_x,&stop_y);
590 p->next->member.last_updated=t;
592 /* walk up the stairs */
593 if (stop_x&&p->next->member.type==T_PLAYER&&!(p->next->member.status & S_CREEP))
595 x1=p->next->member.x;
596 y1=p->next->member.y;
597 p->next->member.x=x;
598 p->next->member.y=y-int2double(1);
599 update_position(
600 &(p->next->member),
601 p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
602 p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
603 w,h,0,&sy);
604 if ((p->next->member.xspeed>0&&p->next->member.x<=x1)||(p->next->member.xspeed<0&&p->next->member.x>=x1)) /* restore original values */
606 p->next->member.x=x1;
607 p->next->member.y=y1;
609 else
611 stop_y=sy;
612 stop_x=0;
616 if (stop_x)p->next->member.xspeed=-mul(p->next->member.xspeed,obj_attr[p->next->member.type].bounce_x);
617 if (my_abs(p->next->member.xspeed)<MIN_X_SPEED)
619 p->next->member.xspeed=0;
620 p->next->member.status &= ~S_WALKING;
624 if (stop_y)
626 p->next->member.yspeed=mul(p->next->member.yspeed,obj_attr[p->next->member.type].bounce_y);
627 p->next->member.yspeed=-p->next->member.yspeed;
628 if (my_abs(p->next->member.yspeed)<MIN_Y_SPEED)
630 p->next->member.yspeed=0;
631 if (stop_y==1)p->next->member.status &= ~S_FALLING;
635 if ((p->next->member.type == T_SHRAPNEL || p->next->member.type == T_BULLET ||
636 p->next->member.type == T_BFGCELL || p->next->member.type == T_CHAIN) &&
637 (stop_x || stop_y)) { /* bullet and shrapnel die crashing into wall */
638 p=p->prev; /* deleting object makes a great mess in for cycle, so we must cheat the cycle */
639 delete_obj(p->next->next->member.id);
640 continue;
647 /* returns number of read bytes */
648 static int process_packet(char *packet,int l)
650 int a,n=l;
652 switch(*packet)
654 case P_CHUNK:
655 for (a=1;a<l&&a<MAX_PACKET_LENGTH;a+=n)
656 n=process_packet(packet+a,l-a);
657 break;
659 case P_NEW_OBJ:
660 if (l < (n=30))break; /* invalid packet */
661 new_obj(
662 get_int(packet+1), /* ID */
663 packet[27], /* type */
664 get_int16(packet+28), /* time to live */
665 get_int16(packet+5), /* sprite */
666 0, /* anim position */
667 get_int(packet+23), /* status */
668 get_int(packet+7), /* x */
669 get_int(packet+11), /* y */
670 get_int(packet+15), /* xspeed */
671 get_int(packet+19), /* yspeed */
672 0 /* data */
674 break;
676 case P_PLAYER_DELETED:
677 n=1;
678 shut_down(1);
679 break;
681 case P_DELETE_OBJECT:
682 if (l<5)break; /* invalid packet */
683 delete_obj(get_int(packet+1));
684 n=5;
685 break;
687 case P_UPDATE_OBJECT:
688 if (l < (n=28))break; /* invalid packet */
690 struct object_list *p;
692 p=find_in_table(get_int(packet+1));
693 if (!p)break;
694 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
695 p->member.update_counter=packet[5];
696 p->member.x=get_int(packet+6);
697 p->member.y=get_int(packet+10);
698 p->member.xspeed=get_int(packet+14);
699 p->member.yspeed=get_int(packet+18);
700 p->member.status=get_int(packet+22);
701 p->member.data=0;
702 p->member.ttl=get_int16(packet+26);
703 /* kdyz tasi, tak se nahodi ttl */
704 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
705 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
707 break;
709 case P_UPDATE_OBJECT_POS:
710 if (l<22)break; /* invalid packet */
712 struct object_list *p;
714 n=22;
715 p=find_in_table(get_int(packet+1));
716 if (!p)break;
717 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
718 p->member.update_counter=packet[5];
719 p->member.x=get_int(packet+6);
720 p->member.y=get_int(packet+10);
721 p->member.xspeed=get_int(packet+14);
722 p->member.yspeed=get_int(packet+18);
724 break;
726 case P_UPDATE_OBJECT_SPEED:
727 if (l<14)break; /* invalid packet */
729 struct object_list *p;
731 n=14;
732 p=find_in_table(get_int(packet+1));
733 if (!p)break;
734 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
735 p->member.update_counter=packet[5];
736 p->member.xspeed=get_int(packet+6);
737 p->member.yspeed=get_int(packet+10);
739 break;
741 case P_UPDATE_OBJECT_COORDS:
742 if (l<14)break; /* invalid packet */
744 struct object_list *p;
746 n=14;
747 p=find_in_table(get_int(packet+1));
748 if (!p)break;
749 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
750 p->member.update_counter=packet[5];
751 p->member.x=get_int(packet+6);
752 p->member.y=get_int(packet+10);
754 break;
756 case P_UPDATE_OBJECT_SPEED_STATUS:
757 if (l < (n=18))break; /* invalid packet */
759 struct object_list *p;
761 p=find_in_table(get_int(packet+1));
762 if (!p)break;
763 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
764 p->member.update_counter=packet[5];
765 p->member.xspeed=get_int(packet+6);
766 p->member.yspeed=get_int(packet+10);
767 p->member.status=get_int(packet+14);
768 /* kdyz tasi, tak se nahodi ttl */
769 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
770 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
772 break;
774 case P_UPDATE_OBJECT_COORDS_STATUS:
775 if (l < (n=18))break; /* invalid packet */
777 struct object_list *p;
779 p=find_in_table(get_int(packet+1));
780 if (!p)break;
781 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
782 p->member.update_counter=packet[5];
783 p->member.x=get_int(packet+6);
784 p->member.y=get_int(packet+10);
785 p->member.status=get_int(packet+14);
786 /* kdyz tasi, tak se nahodi ttl */
787 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
788 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
790 break;
792 case P_UPDATE_OBJECT_SPEED_STATUS_TTL:
793 if (l < (n=20))break; /* invalid packet */
795 struct object_list *p;
797 p=find_in_table(get_int(packet+1));
798 if (!p)break;
799 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
800 p->member.update_counter=packet[5];
801 p->member.xspeed=get_int(packet+6);
802 p->member.yspeed=get_int(packet+10);
803 p->member.status=get_int(packet+14);
804 p->member.ttl=get_int16(packet+18);
805 /* kdyz tasi, tak se nahodi ttl */
806 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
807 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
809 break;
811 case P_UPDATE_OBJECT_COORDS_STATUS_TTL:
812 if (l < (n=20))break; /* invalid packet */
814 struct object_list *p;
816 p=find_in_table(get_int(packet+1));
817 if (!p)break;
818 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
819 p->member.update_counter=packet[5];
820 p->member.x=get_int(packet+6);
821 p->member.y=get_int(packet+10);
822 p->member.status=get_int(packet+14);
823 p->member.ttl=get_int16(packet+18);
824 /* kdyz tasi, tak se nahodi ttl */
825 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
826 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
828 break;
830 case P_UPDATE_STATUS:
831 if (l < (n=9))break; /* invalid packet */
833 struct object_list *p;
835 p=find_in_table(get_int(packet+1));
836 if (!p)break; /* ignore objects we don't have */
837 p->member.status=get_int(packet+5);
838 /* kdyz tasi, tak se nahodi ttl */
839 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
840 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
842 break;
844 case P_HIT:
845 if (l<8)break; /* invalid packet */
847 struct object_list *p;
849 n=8;
850 p=find_in_table(get_int(packet+1));
851 if (!p)break; /* ignore objects we don't have */
852 p->member.status |= S_HIT;
853 p->member.data=(void*)(long)((packet[5]<<16)+(packet[7]<<8)+(packet[6]));
854 /* kdyz tasi, tak se nahodi ttl */
855 if (p->member.type==T_PLAYER&&(p->member.status & S_HOLDING)&&(p->member.status & S_SHOOTING))
856 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
858 break;
860 case P_UPDATE_PLAYER:
861 if (l<15+2*ARMS)break; /* invalid packet */
862 health=packet[1];
863 armor=packet[2];
864 for (a=0;a<ARMS;a++)
865 ammo[a]=get_int16(packet+3+(a<<1));
866 frags=get_int(packet+3+ARMS*2);
867 deaths=get_int(packet+7+ARMS*2);
868 current_weapon=get_int16(packet+11+2*ARMS);
869 weapons=get_int16(packet+13+2*ARMS);
870 n=15+2*ARMS;
871 break;
873 case P_MESSAGE:
874 if (l < 3)
875 break; /* invalid packet */
876 n = 3 + strlen(packet + 2);
877 break;
879 case P_END:
880 if (l<2)printf("Game terminated.\n");
881 else printf("Game terminated by %s.\n",packet+1);
882 n=2+strlen(packet+1);
883 shut_down(1);
885 case P_INFO:
886 if (l<=5)break;
887 l=6;
888 for (a=0;a<packet[5]&&a<TOP_PLAYERS_N;a++)
890 int x;
891 x=strlen(packet+l+9)+1;
892 l+=x+9;
894 n=l;
895 break;
897 case P_EXPLODE_GRENADE:
898 case P_EXPLODE_BFG:
900 unsigned int i,j;
901 struct object_list *p;
902 int b;
904 if (l<9)break;
905 n=9;
906 i=get_int(packet+1);
907 j=get_int(packet+5);
908 p=find_in_table(j);
909 if (!p)break;
911 for (b=0;b<N_SHRAPNELS_EXPLODE;b++)
913 double angle=(double)b*2*M_PI/N_SHRAPNELS_EXPLODE;
914 int spd=add_int(mul_int(my_and(mul_int(weapon[WEAPON_GRENADE].speed,b+1),15),16),100);
916 new_obj(
918 T_SHRAPNEL,
919 SHRAPNEL_TTL,
922 WEAPON_GRENADE,
923 p->member.x,
924 p->member.y,
925 p->member.xspeed+mul(spd,float2double(cos(angle))),
926 p->member.yspeed+mul(spd,float2double(sin(angle))),
927 0);
928 i++;
930 delete_obj(j);
933 break;
935 case P_CHANGE_LEVEL:
937 char *md5;
938 int a;
939 char p;
941 if (l<38)break; /* invalid packet */
942 a=get_int(packet+1);
943 if (level_number==a)goto level_changed;
944 level_number=a;
946 md5=md5_level(level_number);
947 if (strcmp((char *)md5,packet+5)) /* MD5s differ */
949 mem_free(md5);
950 ERROR("Invalid MD5 sum. Can't change level. Exiting...");
951 send_quit();
952 shut_down(1);
954 mem_free(md5);
956 /* OK we can change it */
957 change_level();
958 level_changed:
960 p=P_LEVEL_ACCEPTED;
961 send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
962 n=38;
964 break;
967 return n;
971 /* read packet from socket */
972 static void read_data(void)
974 fd_set rfds;
975 struct timeval tv;
976 struct sockaddr_in client;
977 static char packet[MAX_PACKET_LENGTH];
978 int a=sizeof(client);
979 int l;
981 tv.tv_sec=0;
982 tv.tv_usec=0;
983 FD_ZERO(&rfds);
984 FD_SET(fd,&rfds);
985 while(select(fd+1,&rfds,0,0,&tv))
987 if ((l=recv_packet(packet,MAX_PACKET_LENGTH,(struct sockaddr*)(&client),&a,1,my_id,0))<0)
988 return; /* something's strange */
989 process_packet(packet,l);
995 /* handle fatal signal (sigabrt, sigsegv, ...) */
996 static void signal_handler(int signum)
999 if (connected)send_quit();
1000 shut_down(0);
1001 clear_memory();
1002 if (fd) close(fd);
1003 #ifdef HAVE_PSIGNAL
1004 psignal(signum,"Exiting on signal");
1005 #else
1006 fprintf(stderr, "Exiting on signal: %d\n", signum);
1007 #endif
1008 if (!in_signal_handler){in_signal_handler=1;check_memory_leaks();}
1009 free_packet_buffer();
1010 EXIT(1);
1014 /* print command line help */
1015 static void print_help(void)
1017 printf(
1018 "0verkill bot"
1019 ".\n"
1020 "(c)2000 Brainsoft\n"
1021 "Usage: bot [-h] -a <server address> [-p <port>] [-n <name>]"
1022 "\n"
1027 static void parse_command_line(int argc,char **argv)
1029 int a;
1030 char *e;
1032 while(1)
1034 a=getopt(argc,argv,"hp:a:n:");
1035 switch(a)
1037 case EOF:
1038 return;
1040 case '?':
1041 case ':':
1042 EXIT(1);
1044 case 'h':
1045 print_help();
1046 EXIT(0);
1048 case 'a':
1049 host=optarg;
1050 break;
1052 case 'n':
1053 static_name=optarg;
1054 break;
1056 case 'p':
1057 port=(unsigned short)strtoul(optarg,&e,10);
1058 if (*e){ERROR("Error: Decimal number expected.\n");EXIT(1);}
1059 break;
1065 static char * select_name(void)
1067 return static_name? static_name:names[(random())%N_NAMES];
1071 static void where2go(void)
1073 if (!direction)
1075 if (odds(20+const2))direction=2;
1076 if (odds(20+const2))direction=1;
1078 if(direction==1)keyboard_status.left=1;
1079 if(direction==2)keyboard_status.right=1;
1081 if (odds(40+const1))keyboard_status.jump=1;
1082 if (odds(100+const4))keyboard_status.down_ladder=1;
1083 if (odds(3)+const3)keyboard_status.fire=1;
1088 static void action(void)
1090 if (hero->status & S_DEAD)
1091 send_reenter_game(); /* respawn */
1092 where2go();
1095 /*----------------------------------------------------------------------------*/
1096 int main(int argc,char **argv)
1098 int color;
1099 unsigned long_long last_time;
1100 char *m;
1103 #ifdef WIN32
1104 WSADATA wd;
1106 WSAStartup(0x101, &wd);
1107 printf("Started WinSock version %X.%02X\n", wd.wVersion/0x100, wd.wVersion&0xFF);
1108 #endif
1110 chdir_to_data_files();
1111 ERROR("Initialization...\n");
1113 last_obj=&objects;
1114 srandom(get_time());
1116 const1=random()%50;
1117 const2=random()%20;
1118 const3=random()%5;
1119 const4=random()%20;
1121 host=NULL;
1122 parse_command_line(argc,argv);
1123 if (!host){ERROR("No server address specified.\n");EXIT(1);}
1124 hash_table_init();
1125 init_sprites();
1126 init_area();
1127 ERROR("Loading graphics...\n");
1128 load_sprites(DATA_PATH GAME_SPRITES_FILE);
1129 level_sprites_start=n_sprites;
1131 signal(SIGINT,signal_handler);
1132 signal(SIGTERM,signal_handler);
1133 signal(SIGILL,signal_handler);
1134 signal(SIGABRT,signal_handler);
1135 signal(SIGFPE,signal_handler);
1136 signal(SIGSEGV,signal_handler);
1137 #ifndef WIN32
1138 signal(SIGQUIT,signal_handler);
1139 signal(SIGBUS,signal_handler);
1140 #endif
1142 ERROR("Resolving server address ...\n");
1143 if ((m=find_server(host,port))){ERROR(m);EXIT(1);}
1144 ERROR("Initializing socket ...\n");
1145 if ((m=init_socket())){ERROR(m);EXIT(1);}
1146 ERROR("Contacting server ...\n");
1147 color=(random()%15)+1;
1148 if ((m=contact_server(color,select_name()))){ERROR(m);EXIT(1);}
1150 connected=1;
1151 ERROR("OK, connected.\nPlaying...\n");
1153 last_time=get_time();
1154 again:
1155 last_time+=CLIENT_PERIOD_USEC;
1156 if (get_time()-last_time>PERIOD_USEC*100)last_time=get_time();
1157 read_data();
1158 reset_keyboard();
1159 priority=0;
1160 update_game();
1161 action();
1162 send_keyboard();
1163 sleep_until(last_time+CLIENT_PERIOD_USEC);
1164 goto again;
1165 if (fd) close(fd);