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
;
96 /* connection with server */
97 static int connected
=0;
103 static struct sockaddr_in server
; /* server address */
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
;
119 static char *names
[N_NAMES
]={
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
;
152 * 7=find shotgun ammo
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
);
183 /* shut down the client */
184 static void shut_down(int a
)
189 free_packet_buffer();
190 check_memory_leaks();
196 /* find address of server and fill the server address structure */
197 static char * find_server(char *name
,unsigned short port
)
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]));
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";
222 /* send quit request to server */
223 static void send_quit(void)
228 int a
=sizeof(server
);
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
;
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;
263 packet
[0]=P_NEW_PLAYER
;
265 packet
[2]=VERSION_MAJOR
;
266 packet
[3]=VERSION_MINOR
;
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";
283 case P_PLAYER_REFUSED
:
286 case E_INCOMPATIBLE_VERSION
:
287 return "Incompatible client version. Connection refused.\n";
290 return "This name is already in use. Connection refused.\n";
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";}
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);
309 ammo
[0]=weapon
[0].basic_ammo
;
311 weapons
= WEAPON_MASK_GUN
|
312 WEAPON_MASK_GRENADE
|
313 WEAPON_MASK_CHAINSAW
|
314 WEAPON_MASK_BLOODRAIN
; /* gun, grenades, chainsaw
317 get_int(packet
+1), /* ID */
319 0, /* time to live */
320 get_int16(packet
+5), /* sprite */
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 */
332 return "Connection error.\n";
338 /* I want to be born again */
339 static void send_reenter_game(void)
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];
353 len
= strlen(msg
) + 1;
354 packet
[0] = P_MESSAGE
;
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)
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;
398 if (obj
->status
&S_INVISIBLE
)
403 keyboard_status
.fire
=1;
404 if (obj
->x
>hero
->x
)direction
=2;
406 if (my_abs(obj
->x
-hero
->x
)<int2double(30))direction
=0;
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;
418 if (priority
>2)break;
419 if ((weapons
&(1<<WEAPON_RIFLE
))&&ammo
[WEAPON_RIFLE
])break;
421 if (obj
->x
>hero
->x
)direction
=2;
426 if (priority
>3)break;
427 if ((weapons
&(1<<WEAPON_SHOTGUN
))&&ammo
[WEAPON_SHOTGUN
])break;
429 if (obj
->x
>hero
->x
)direction
=2;
434 if (priority
>4)break;
435 if ((weapons
&(1<<WEAPON_UZI
))&&ammo
[WEAPON_UZI
])break;
437 if (obj
->x
>hero
->x
)direction
=2;
442 if (priority
>5)break;
443 if (!(weapons
&(1<<WEAPON_GRENADE
))||ammo
[WEAPON_GRENADE
])break;
445 if (obj
->x
>hero
->x
)direction
=2;
450 if (priority
>6)break;
451 if (!(weapons
&(1<<WEAPON_GUN
))||ammo
[WEAPON_GUN
])break;
453 if (obj
->x
>hero
->x
)direction
=2;
458 if (priority
>7)break;
459 if (!(weapons
&(1<<WEAPON_SHOTGUN
))||ammo
[WEAPON_SHOTGUN
])break;
461 if (obj
->x
>hero
->x
)direction
=2;
466 if (priority
>8)break;
467 if (!(weapons
&(1<<WEAPON_RIFLE
))||ammo
[WEAPON_RIFLE
])break;
469 if (obj
->x
>hero
->x
)direction
=2;
474 if (priority
>9)break;
475 if (!(weapons
&(1<<WEAPON_UZI
))||ammo
[WEAPON_UZI
])break;
477 if (obj
->x
>hero
->x
)direction
=2;
482 if (priority
>10)break;
485 if (obj
->x
>hero
->x
)direction
=2;
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
);
505 static void change_level(void)
511 free_sprites(level_sprites_start
);
514 LEVEL
=load_level(level_number
);
515 snprintf(txt
,256,"Loading level \"%s\".\n",LEVEL
);
517 snprintf(txt
,256,"%s%s%s",DATA_PATH
,LEVEL
,LEVEL_SPRITES_SUFFIX
);
519 snprintf(txt
,256,"%s%s%s",DATA_PATH
,LEVEL
,STATIC_DATA_SUFFIX
);
525 /* recompute object positions */
526 static void update_game(void)
528 struct object_list
*p
;
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
)
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
;
550 if (p
->next
->member
.type
!=T_GRENADE
){ /* client's waiting for P_EXPLODE_GRENADE and doesn't delete the grenade yet */
552 delete_obj(p
->next
->next
->member
.id
);
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
);
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
);
579 DELTA_TIME
=float2double(((double)(long_long
)(t
-p
->next
->member
.last_updated
))/MICROSECONDS
);
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
;
593 p
->next
->member
.y
=y
-int2double(1);
596 p
->next
->member
.x
+mul(p
->next
->member
.xspeed
,DELTA_TIME
),
597 p
->next
->member
.y
+mul(p
->next
->member
.yspeed
,DELTA_TIME
),
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
;
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
;
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
);
642 /* returns number of read bytes */
643 static int process_packet(char *packet
,int l
)
650 for (a
=1;a
<l
&&a
<MAX_PACKET_LENGTH
;a
+=n
)
651 n
=process_packet(packet
+a
,l
-a
);
655 if (l
< (n
=30))break; /* invalid packet */
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 */
671 case P_PLAYER_DELETED
:
676 case P_DELETE_OBJECT
:
677 if (l
<5)break; /* invalid packet */
678 delete_obj(get_int(packet
+1));
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));
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);
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
;
704 case P_UPDATE_OBJECT_POS
:
705 if (l
<22)break; /* invalid packet */
707 struct object_list
*p
;
710 p
=find_in_table(get_int(packet
+1));
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);
721 case P_UPDATE_OBJECT_SPEED
:
722 if (l
<14)break; /* invalid packet */
724 struct object_list
*p
;
727 p
=find_in_table(get_int(packet
+1));
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);
736 case P_UPDATE_OBJECT_COORDS
:
737 if (l
<14)break; /* invalid packet */
739 struct object_list
*p
;
742 p
=find_in_table(get_int(packet
+1));
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);
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));
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
;
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));
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
;
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));
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
;
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));
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
;
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
;
840 if (l
<8)break; /* invalid packet */
842 struct object_list
*p
;
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
;
855 case P_UPDATE_PLAYER
:
856 if (l
<15+2*ARMS
)break; /* invalid packet */
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
);
870 break; /* invalid packet */
871 n
= 3 + strlen(packet
+ 2);
875 if (l
<2)printf("Game terminated.\n");
876 else printf("Game terminated by %s.\n",packet
+1);
877 n
=2+strlen(packet
+1);
883 for (a
=0;a
<packet
[5]&&a
<TOP_PLAYERS_N
;a
++)
886 x
=strlen(packet
+l
+9)+1;
892 case P_EXPLODE_GRENADE
:
896 struct object_list
*p
;
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);
920 p
->member
.xspeed
+mul(spd
,float2double(cos(angle
))),
921 p
->member
.yspeed
+mul(spd
,float2double(sin(angle
))),
936 if (l
<38)break; /* invalid packet */
938 if (level_number
==a
)goto level_changed
;
941 md5
=md5_level(level_number
);
942 if (strcmp((char *)md5
,packet
+5)) /* MD5s differ */
945 ERROR("Invalid MD5 sum. Can't change level. Exiting...");
951 /* OK we can change it */
956 send_packet(&p
,1,(struct sockaddr
*)(&server
),my_id
,0);
966 /* read packet from socket */
967 static void read_data(void)
971 struct sockaddr_in client
;
972 static char packet
[MAX_PACKET_LENGTH
];
973 int a
=sizeof(client
);
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();
999 psignal(signum
,"Exiting on signal");
1001 fprintf(stderr
, "Exiting on signal: %d\n", signum
);
1003 if (!in_signal_handler
){in_signal_handler
=1;check_memory_leaks();}
1004 free_packet_buffer();
1009 /* print command line help */
1010 static void print_help(void)
1015 "(c)2000 Brainsoft\n"
1016 "Usage: bot [-h] -a <server address> [-p <port>]"
1022 static void parse_command_line(int argc
,char **argv
)
1029 a
=getopt(argc
,argv
,"hp:a:");
1048 port
=(unsigned short)strtoul(optarg
,&e
,10);
1049 if (*e
){ERROR("Error: Decimal number expected.\n");EXIT(1);}
1056 static char * select_name(void)
1058 return names
[(random())%N_NAMES
];
1062 static void where2go(void)
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 */
1086 /*----------------------------------------------------------------------------*/
1087 int main(int argc
,char **argv
)
1090 unsigned long_long last_time
;
1097 WSAStartup(0x101, &wd
);
1098 printf("Started WinSock version %X.%02X\n", wd
.wVersion
/0x100, wd
.wVersion
&0xFF);
1101 chdir_to_data_files();
1102 ERROR("Initialization...\n");
1105 srandom(get_time());
1113 parse_command_line(argc
,argv
);
1114 if (!host
){ERROR("No server address specified.\n");EXIT(1);}
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
);
1129 signal(SIGQUIT
,signal_handler
);
1130 signal(SIGBUS
,signal_handler
);
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);}
1142 ERROR("OK, connected.\nPlaying...\n");
1144 last_time
=get_time();
1146 last_time
+=CLIENT_PERIOD_USEC
;
1147 if (get_time()-last_time
>PERIOD_USEC
*100)last_time
=get_time();
1154 sleep_until(last_time
+CLIENT_PERIOD_USEC
);