17 #ifdef HAVE_SYS_SELECT_H
18 #include <sys/select.h>
24 #ifdef TIME_WITH_SYS_TIME
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
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
;
80 unsigned char *screen2
,*screen2_a
;
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
;
95 /* for use with the -n option */
96 static char *static_name
=NULL
;
98 /* connection with server */
99 static int connected
=0;
105 static struct sockaddr_in server
; /* server address */
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
;
121 static char *names
[N_NAMES
]={
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
;
154 * 7=find shotgun ammo
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
);
185 /* shut down the client */
186 static void shut_down(int a
)
191 free_packet_buffer();
192 check_memory_leaks();
198 /* find address of server and fill the server address structure */
199 static char * find_server(char *name
,unsigned short port
)
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]));
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";
224 /* send quit request to server */
225 static void send_quit(void)
230 int a
=sizeof(server
);
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
;
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;
265 packet
[0]=P_NEW_PLAYER
;
267 packet
[2]=VERSION_MAJOR
;
268 packet
[3]=VERSION_MINOR
;
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";
288 case P_PLAYER_REFUSED
:
291 case E_INCOMPATIBLE_VERSION
:
292 return "Incompatible client version. Connection refused.\n";
295 return "This name is already in use. Connection refused.\n";
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";}
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);
314 ammo
[0]=weapon
[0].basic_ammo
;
316 weapons
= WEAPON_MASK_GUN
|
317 WEAPON_MASK_GRENADE
|
318 WEAPON_MASK_CHAINSAW
|
319 WEAPON_MASK_BLOODRAIN
; /* gun, grenades, chainsaw
322 get_int(packet
+1), /* ID */
324 0, /* time to live */
325 get_int16(packet
+5), /* sprite */
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 */
337 return "Connection error.\n";
343 /* I want to be born again */
344 static void send_reenter_game(void)
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];
358 len
= strlen(msg
) + 1;
359 packet
[0] = P_MESSAGE
;
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)
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;
403 if (obj
->status
&S_INVISIBLE
)
408 keyboard_status
.fire
=1;
409 if (obj
->x
>hero
->x
)direction
=2;
411 if (my_abs(obj
->x
-hero
->x
)<int2double(30))direction
=0;
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;
423 if (priority
>2)break;
424 if ((weapons
&(1<<WEAPON_RIFLE
))&&ammo
[WEAPON_RIFLE
])break;
426 if (obj
->x
>hero
->x
)direction
=2;
431 if (priority
>3)break;
432 if ((weapons
&(1<<WEAPON_SHOTGUN
))&&ammo
[WEAPON_SHOTGUN
])break;
434 if (obj
->x
>hero
->x
)direction
=2;
439 if (priority
>4)break;
440 if ((weapons
&(1<<WEAPON_UZI
))&&ammo
[WEAPON_UZI
])break;
442 if (obj
->x
>hero
->x
)direction
=2;
447 if (priority
>5)break;
448 if (!(weapons
&(1<<WEAPON_GRENADE
))||ammo
[WEAPON_GRENADE
])break;
450 if (obj
->x
>hero
->x
)direction
=2;
455 if (priority
>6)break;
456 if (!(weapons
&(1<<WEAPON_GUN
))||ammo
[WEAPON_GUN
])break;
458 if (obj
->x
>hero
->x
)direction
=2;
463 if (priority
>7)break;
464 if (!(weapons
&(1<<WEAPON_SHOTGUN
))||ammo
[WEAPON_SHOTGUN
])break;
466 if (obj
->x
>hero
->x
)direction
=2;
471 if (priority
>8)break;
472 if (!(weapons
&(1<<WEAPON_RIFLE
))||ammo
[WEAPON_RIFLE
])break;
474 if (obj
->x
>hero
->x
)direction
=2;
479 if (priority
>9)break;
480 if (!(weapons
&(1<<WEAPON_UZI
))||ammo
[WEAPON_UZI
])break;
482 if (obj
->x
>hero
->x
)direction
=2;
487 if (priority
>10)break;
490 if (obj
->x
>hero
->x
)direction
=2;
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
);
510 static void change_level(void)
516 free_sprites(level_sprites_start
);
519 LEVEL
=load_level(level_number
);
520 snprintf(txt
,256,"Loading level \"%s\".\n",LEVEL
);
522 snprintf(txt
,256,"%s%s%s",DATA_PATH
,LEVEL
,LEVEL_SPRITES_SUFFIX
);
524 snprintf(txt
,256,"%s%s%s",DATA_PATH
,LEVEL
,STATIC_DATA_SUFFIX
);
530 /* recompute object positions */
531 static void update_game(void)
533 struct object_list
*p
;
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
)
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
;
555 if (p
->next
->member
.type
!=T_GRENADE
){ /* client's waiting for P_EXPLODE_GRENADE and doesn't delete the grenade yet */
557 delete_obj(p
->next
->next
->member
.id
);
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
);
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
);
584 DELTA_TIME
=float2double(((double)(long_long
)(t
-p
->next
->member
.last_updated
))/MICROSECONDS
);
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
;
598 p
->next
->member
.y
=y
-int2double(1);
601 p
->next
->member
.x
+mul(p
->next
->member
.xspeed
,DELTA_TIME
),
602 p
->next
->member
.y
+mul(p
->next
->member
.yspeed
,DELTA_TIME
),
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
;
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
;
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
);
647 /* returns number of read bytes */
648 static int process_packet(char *packet
,int l
)
655 for (a
=1;a
<l
&&a
<MAX_PACKET_LENGTH
;a
+=n
)
656 n
=process_packet(packet
+a
,l
-a
);
660 if (l
< (n
=30))break; /* invalid packet */
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 */
676 case P_PLAYER_DELETED
:
681 case P_DELETE_OBJECT
:
682 if (l
<5)break; /* invalid packet */
683 delete_obj(get_int(packet
+1));
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));
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);
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
;
709 case P_UPDATE_OBJECT_POS
:
710 if (l
<22)break; /* invalid packet */
712 struct object_list
*p
;
715 p
=find_in_table(get_int(packet
+1));
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);
726 case P_UPDATE_OBJECT_SPEED
:
727 if (l
<14)break; /* invalid packet */
729 struct object_list
*p
;
732 p
=find_in_table(get_int(packet
+1));
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);
741 case P_UPDATE_OBJECT_COORDS
:
742 if (l
<14)break; /* invalid packet */
744 struct object_list
*p
;
747 p
=find_in_table(get_int(packet
+1));
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);
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));
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
;
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));
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
;
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));
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
;
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));
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
;
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
;
845 if (l
<8)break; /* invalid packet */
847 struct object_list
*p
;
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
;
860 case P_UPDATE_PLAYER
:
861 if (l
<15+2*ARMS
)break; /* invalid packet */
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
);
875 break; /* invalid packet */
876 n
= 3 + strlen(packet
+ 2);
880 if (l
<2)printf("Game terminated.\n");
881 else printf("Game terminated by %s.\n",packet
+1);
882 n
=2+strlen(packet
+1);
888 for (a
=0;a
<packet
[5]&&a
<TOP_PLAYERS_N
;a
++)
891 x
=strlen(packet
+l
+9)+1;
897 case P_EXPLODE_GRENADE
:
901 struct object_list
*p
;
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);
925 p
->member
.xspeed
+mul(spd
,float2double(cos(angle
))),
926 p
->member
.yspeed
+mul(spd
,float2double(sin(angle
))),
941 if (l
<38)break; /* invalid packet */
943 if (level_number
==a
)goto level_changed
;
946 md5
=md5_level(level_number
);
947 if (strcmp((char *)md5
,packet
+5)) /* MD5s differ */
950 ERROR("Invalid MD5 sum. Can't change level. Exiting...");
956 /* OK we can change it */
961 send_packet(&p
,1,(struct sockaddr
*)(&server
),my_id
,0);
971 /* read packet from socket */
972 static void read_data(void)
976 struct sockaddr_in client
;
977 static char packet
[MAX_PACKET_LENGTH
];
978 int a
=sizeof(client
);
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();
1004 psignal(signum
,"Exiting on signal");
1006 fprintf(stderr
, "Exiting on signal: %d\n", signum
);
1008 if (!in_signal_handler
){in_signal_handler
=1;check_memory_leaks();}
1009 free_packet_buffer();
1014 /* print command line help */
1015 static void print_help(void)
1020 "(c)2000 Brainsoft\n"
1021 "Usage: bot [-h] -a <server address> [-p <port>] [-n <name>]"
1027 static void parse_command_line(int argc
,char **argv
)
1034 a
=getopt(argc
,argv
,"hp:a:n:");
1057 port
=(unsigned short)strtoul(optarg
,&e
,10);
1058 if (*e
){ERROR("Error: Decimal number expected.\n");EXIT(1);}
1065 static char * select_name(void)
1067 return static_name
? static_name
:names
[(random())%N_NAMES
];
1071 static void where2go(void)
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 */
1095 /*----------------------------------------------------------------------------*/
1096 int main(int argc
,char **argv
)
1099 unsigned long_long last_time
;
1106 WSAStartup(0x101, &wd
);
1107 printf("Started WinSock version %X.%02X\n", wd
.wVersion
/0x100, wd
.wVersion
&0xFF);
1110 chdir_to_data_files();
1111 ERROR("Initialization...\n");
1114 srandom(get_time());
1122 parse_command_line(argc
,argv
);
1123 if (!host
){ERROR("No server address specified.\n");EXIT(1);}
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
);
1138 signal(SIGQUIT
,signal_handler
);
1139 signal(SIGBUS
,signal_handler
);
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);}
1151 ERROR("OK, connected.\nPlaying...\n");
1153 last_time
=get_time();
1155 last_time
+=CLIENT_PERIOD_USEC
;
1156 if (get_time()-last_time
>PERIOD_USEC
*100)last_time
=get_time();
1163 sleep_until(last_time
+CLIENT_PERIOD_USEC
);