make the bot print its name
[0verkill.git] / data.c
blob0279f78b2830491b4dcb764e9d57ce93a959e311
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
5 #ifndef WIN32
6 #include "config.h"
7 #endif
9 #ifdef HAVE_ACCESS
10 # ifdef HAVE_UNISTD_H
11 # include <unistd.h>
12 # endif
13 #endif
15 #include "data.h"
16 #include "cfg.h"
17 #include "hash.h"
18 #include "time.h"
19 #include "md5.h"
20 #include "error.h"
23 #ifdef TRI_D
24 int tri_d=0;
25 int TRI_D_ON=0;
26 #endif
29 /* static map of the level */
30 unsigned char *area;
32 /* attributes:
33 lower 4 bits=color
34 higher 4 bits=type
36 unsigned char *area_a;
39 struct sprite *sprites=DUMMY;
40 char **sprite_names=DUMMY;
41 int n_sprites; /* number of sprites */
43 struct object_list *last_obj;
45 #define NOBODY 0
46 #define CLIENT 1
47 #define BOTH 3
48 #define BOTH_UPDATE 7
50 /* object attributes */
51 struct obj_attr_type obj_attr[N_TYPES]=
53 /* fall, bounce x, bounce y, slow down x, maintainer, foreground */
54 {1,0,0,PLAYER_SLOW_DOWN_X,BOTH_UPDATE,0}, /* player */
55 {0,0,0,int2double(1),BOTH,0}, /* bullet */
56 {1,0,float2double(.25),PLAYER_SLOW_DOWN_X,BOTH,0}, /* corpse */
57 {1,0,0,0,NOBODY,0}, /* medikit */
58 {1,0,0,0,NOBODY,0}, /* shotgun */
59 {1,0,0,0,NOBODY,0}, /* uzi */
60 {1,0,0,0,NOBODY,0}, /* rifle */
61 {1,float2double(.8),float2double(.5),float2double(.8),CLIENT,0}, /* shell */
62 {1,0,0,0,NOBODY,0}, /* ammo for gun */
63 {1,0,0,0,NOBODY,0}, /* ammo for shotgun */
64 {1,0,0,0,NOBODY,0}, /* ammo for uzi */
65 {1,0,0,0,NOBODY,0}, /* ammo for rifle */
66 {0,0,0,0,NOBODY,0}, /* nothing */
67 {1,float2double(.4),float2double(.4),float2double(.3),CLIENT,0}, /* mess */
68 {1,float2double(.5),float2double(.5),float2double(.9),BOTH/*_UPDATE*/,0}, /* grenade */
69 {1,0,0,0,NOBODY,0}, /* grenade ammo */
70 {1,0,0,int2double(1),BOTH,0}, /* grenade shrapnel */
71 {1,0,0,0,NOBODY,0}, /* armor */
72 {1,0,0,0,NOBODY,0}, /* invisibility */
73 {1,0,0,0,NOBODY,0}, /* noise */
74 {0,0,0,0,NOBODY,1}, /* nothing in foreground */
75 {0,0,0,0,NOBODY,1}, /* killing object */
76 {1,0,0,0,NOBODY,0}, /* teleport */
77 {1,0,0,0,NOBODY,0}, /* BFG */
78 {0,0,0,int2double(1),BOTH,0}, /* BFG cell */
79 {0,0,0,int2double(1),BOTH,0}, /* chainsaw chain */
83 /* weapon attributes */
84 struct weapon_type weapon[ARMS]=
86 /* name, cadence, ttl, bullet speed, impact, lethalness, armor damage, basic ammo, additional ammo, max ammo, shell xspeed, shell yspeed */
87 {"Browning",16,50,float2double(3*36),float2double(.3*36),20,2,13,12,48,float2double((double).3*36),-float2double(1*36)},
88 {"Shotgun",25,50,float2double(3*36),float2double(.5*36),10,5,6,12,30,float2double((double).3*36),-float2double((double)1.2*36)},
89 {"Uzi",3,50,float2double(4*36),float2double(.25*36),15,4,50,50,150,float2double((double).9*36),-float2double((double)1.5*36)},
90 {"Rifle",40,70,float2double(6*36),float2double(.4*36),50,20,1,15,15,0,0},
91 {"Grenades",15,60,float2double((double)3.73*36),0,75,40,0,6,24,float2double(3*36),-float2double((double)1.5*36)}, /* shell speed=grenade throwing speed, bullet speed=shrapnel speed */
92 {"BFG",200,80,float2double(2*36),float2double(1*36),100,100,10,10,10,float2double((double).1*36),-float2double((double)1.5*36)},
93 {"Chainsaw",1,5,float2double(1.8*36),0,10,10,1,1,1,0,0},
94 {"Bloodrain",15,0,float2double((double)3.73*36),0,75,40,1,1,1,0,0},
98 /* initialize playing area */
99 /* must be run before loading data */
100 void init_area(void)
102 area=mem_alloc(AREA_X*AREA_Y);
103 if (!area){ERROR("Error: Not enough memory!\n");EXIT(1);}
104 area_a=mem_alloc(AREA_X*AREA_Y);
105 if (!area_a){ERROR("Error: Not enough memory!\n");EXIT(1);}
106 memset(area,' ',AREA_X*AREA_Y);
107 memset(area_a,0,AREA_X*AREA_Y);
110 void free_area(void)
112 mem_free(area);
113 mem_free(area_a);
117 /* reinitializes playing area */
118 /* must be called before loading new level */
119 void reinit_area(void)
121 memset(area,' ',AREA_X*AREA_Y);
122 memset(area_a,0,AREA_X*AREA_Y);
125 /* skip white space */
126 /* ancillary function */
127 void _skip_ws(char **txt)
129 for (;(**txt)==' '||(**txt)==9||(**txt)==10;(*txt)++);
133 /* find sprite according to its name */
134 /* returns 1 on error */
135 /* it's slow but not called in speed critical parts of the program */
136 int find_sprite(char *name,int *num)
138 for ((*num)=0;(*num)<n_sprites;(*num)++)
139 if (!strcmp(sprite_names[*num],name))return 0;
140 return 1;
144 /* convert type character (from data files) into type */
145 int _convert_type(unsigned char c)
147 switch(c) {
148 /* static objects */
149 case 'b': return TYPE_BACKGROUND;
150 case 'w': return TYPE_WALL;
151 case 'j': return TYPE_JUMP;
152 case 'f': return TYPE_FOREGROUND;
153 case 'i': return TYPE_JUMP_FOREGROUND;
155 /* dynamic objects, they use great letter */
156 case 'M': return T_MEDIKIT;
157 case 'A': return T_ARMOR;
158 case 'N': return T_NOTHING;
159 case 'F': return T_NOTHING_FORE;
160 case 'K': return T_KILL;
161 case 'S': return T_SHOTGUN;
162 case 'Z': return T_BFG;
163 case 'U': return T_UZI;
164 case 'R': return T_RIFLE;
165 case '1': return T_AMMO_GUN;
166 case '2': return T_AMMO_SHOTGUN;
167 case '3': return T_AMMO_UZI;
168 case '4': return T_AMMO_RIFLE;
169 case '5': return T_AMMO_GRENADE;
170 case 'I': return T_INVISIBILITY;
171 case 'T': return T_TELEPORT;
172 case 'X': return T_BIOSKULL;
173 case 'x': return T_BIOMED;
174 case 'r': return T_BLOODRAIN;
175 case 'J': return T_JETPACK;
176 case 'P': return T_PS;
178 /* birthplace */
179 case 'B': return TYPE_BIRTHPLACE;
181 default: return -1;
186 /* load static data */
187 void load_data(char * filename)
189 FILE * stream;
190 static char line[1024];
191 char *p,*q,*name;
192 int n,x,y;
193 int t;
195 #ifndef WIN32
196 if (!(stream=fopen(filename,"rb")))
197 #else
198 if (!fopen_s(&stream,filename,"rb"))
199 #endif
201 char msg[256];
202 snprintf(msg,256,"Can't open file \"%s\"!\n",filename);
203 ERROR(msg);
204 EXIT(1);
206 while(fgets(line,1024,stream))
208 p=line;
209 _skip_ws(&p);
210 for (name=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++);
211 if (!(*p))continue;
212 *p=0;p++;
213 _skip_ws(&p);
214 if ((t=_convert_type(*p))<0)
216 char msg[256];
217 snprintf(msg,256,"Unknown object type '%c'.\n",*p);
218 ERROR(msg);
219 EXIT(1);
221 p++;
222 _skip_ws(&p);
223 x=strtol(p,&q,0);
224 _skip_ws(&q);
225 y=strtol(q,&p,0);
226 if (find_sprite(name,&n))
228 char msg[256];
229 snprintf(msg,256,"Unknown bitmap name \"%s\"!\n",name);
230 ERROR(msg);
231 EXIT(1);
233 _put_sprite(AREA_X,AREA_Y,area,area_a,x,y,sprites[n].positions,t,0);
235 fclose(stream);
239 /* load sprites */
240 void load_sprites(char * filename)
242 FILE *stream;
243 char line[1024];
244 char *p,*q;
245 int l;
247 #ifndef WIN32
248 if(!(stream=fopen(filename,"rb")))
249 #else
250 int err;
251 char r[1024];
252 if((err = fopen_s(&stream,filename,"rb")) != 0)
253 #endif
255 char msg[256];
256 snprintf(msg,256,"Can't open file \"%s\"!\n",filename);
257 ERROR(msg);
258 EXIT(1);
260 while(fgets(line,1024,stream))
262 p=line;
263 _skip_ws(&p);
264 for (q=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++);
265 if (!(*p))continue;
266 *p=0;p++;
267 l=strlen(q);
268 n_sprites++;
269 sprite_names=(char **)mem_realloc(sprite_names,n_sprites*sizeof(unsigned char*));
270 if (!sprite_names){ERROR("Memory allocation error!\n");EXIT(1);}
271 sprites=(struct sprite *)mem_realloc(sprites,n_sprites*sizeof(struct sprite));
272 if (!sprites){ERROR("Memory allocation error!\n");EXIT(1);}
273 sprite_names[n_sprites-1]=(char *)mem_alloc(l+1);
274 if (!sprite_names[n_sprites-1]){ERROR("Memory allocation error!\n");EXIT(1);}
275 memcpy(sprite_names[n_sprites-1],q,l+1);
276 _skip_ws(&p);
277 for (q=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++)
278 #ifdef WIN32
279 if (*p == '/')
280 *p = '\\';
281 snprintf(r, sizeof(r), "%s\\%s", _getcwd(NULL, 0), q)
282 #endif
284 *p=0;p++;
285 load_sprite(q,sprites+(n_sprites-1));
287 fclose(stream);
291 void free_sprites(int start_num)
293 int a;
295 for (a=start_num;a<n_sprites;a++)
297 mem_free(sprite_names[a]);
298 free_sprite(sprites+a);
300 n_sprites=start_num;
301 sprite_names=(char **)mem_realloc(sprite_names,n_sprites*sizeof(unsigned char*));
302 if (!sprite_names){ERROR("Memory allocation error!\n");EXIT(1);}
303 sprites=mem_realloc(sprites,n_sprites*sizeof(struct sprite));
304 if (!sprites){ERROR("Memory allocation error!\n");EXIT(1);}
308 /* returns allocated string with level name or NULL on error */
309 /* level_num is a line number in the LEVEL_FILE */
310 char *load_level(int level_num)
312 char txt[1024];
313 char *retval;
314 int a;
315 FILE *f;
317 #ifndef WIN32
318 if(!(f=fopen(DATA_PATH LEVEL_FILE,"r")))
319 #else
320 int err;
321 snprintf(txt,sizeof(txt),"%s\\data\\level.dat",_getcwd(NULL, 0));
322 if((err = fopen_s(&f, txt, "r")) != 0)
323 #endif
324 return NULL;
326 for (a=0;a<=level_num;)
328 if (!(fgets(txt,1024,f)))return NULL;
330 /* remove trailing CR and/or LF */
331 if (txt[strlen(txt)-1]==10)txt[strlen(txt)-1]=0;
332 if (txt[strlen(txt)-1]==13)txt[strlen(txt)-1]=0;
334 if (strlen(txt))a++;
337 fclose(f);
339 a=strlen(txt);
340 retval=mem_alloc(1+a*sizeof(unsigned char));
341 if (!retval)return NULL;
342 memcpy(retval,txt,a+1); /* including trailing zero */
343 if (!strlen(retval)){mem_free(retval);return NULL;}
344 return retval;
348 /* create a new object and fill with data and add to hash table */
349 struct it * new_obj(
350 unsigned int id,
351 unsigned char type,
352 int ttl,
353 int sprite,
354 unsigned char pos,
355 int status,
356 int x,
357 int y,
358 int xspeed,
359 int yspeed,
360 void * data)
362 last_obj->next=mem_alloc(sizeof(struct object_list));
363 if (!last_obj->next)return 0;
364 last_obj->next->prev=last_obj;
365 last_obj=last_obj->next;
366 last_obj->next=0;
367 last_obj->member.x=x;
368 last_obj->member.y=y;
369 last_obj->member.xspeed=xspeed;
370 last_obj->member.yspeed=yspeed;
371 last_obj->member.type=type;
372 last_obj->member.ttl=ttl;
373 last_obj->member.sprite=sprite;
374 last_obj->member.anim_pos=pos;
375 last_obj->member.data=data;
376 last_obj->member.id=id;
377 last_obj->member.status=status;
378 last_obj->member.update_counter=0;
379 last_obj->member.last_updated=get_time();
380 add_to_table(last_obj);
381 return &(last_obj->member);
385 /* completely delete object from the list */
386 void delete_obj(unsigned long id)
388 struct object_list *q;
389 if (!(q=remove_from_table(id)))return; /* packets can come more than once, so we must ignore deleting deleted object */
390 q->prev->next=q->next;
391 if (!q->next) last_obj=q->prev; /* q is last object in list */
392 else q->next->prev=q->prev;
393 mem_free(q);
396 void put_long_long(char *p,unsigned long_long num, int *offset)
398 p[(*offset)++]=(char)(num & 0xff);num>>=8;
399 p[(*offset)++]=(char)(num & 0xff);num>>=8;
400 p[(*offset)++]=(char)(num & 0xff);num>>=8;
401 p[(*offset)++]=(char)(num & 0xff);num>>=8;
402 p[(*offset)++]=(char)(num & 0xff);num>>=8;
403 p[(*offset)++]=(char)(num & 0xff);num>>=8;
404 p[(*offset)++]=(char)(num & 0xff);num>>=8;
405 p[(*offset)++]=(char)(num & 0xff);
409 void put_int(char *p,int num, int *offset)
411 p[(*offset)++]=(char)(num & 0xff);num>>=8;
412 p[(*offset)++]=(char)(num & 0xff);num>>=8;
413 p[(*offset)++]=(char)(num & 0xff);num>>=8;
414 p[(*offset)++]=(char)(num & 0xff);
418 int get_int(char *p)
420 return ((p[0]&0xff) | ((p[1]&0xff)<<8) |
421 ((p[2]&0xff)<<16) | ((p[3]&0xff)<<24));
425 void put_int16(char *p, short num, int *offset)
427 p[(*offset)++]=(char)(num & 0xff);num>>=8;
428 p[(*offset)++]=(char)(num & 0xff);
432 int get_int16(char *p)
434 return ((p[0]&0xff) | ((p[1]&0xff)<<8));
438 unsigned long_long get_long_long(char *p)
440 #define ULL unsigned long_long
441 return (ULL)p[0]+
442 ((ULL)(p[1])<<8)+
443 ((ULL)(p[2])<<16)+
444 ((ULL)(p[3])<<24)+
445 ((ULL)(p[4])<<32)+
446 ((ULL)(p[5])<<40)+
447 ((ULL)(p[6])<<48)+
448 ((ULL)(p[7])<<56);
449 #undef ULL
454 /* test if vertical line from yh to yl can move from old_x to new_x axis */
455 /* returns farthest possible x axis */
456 /* flag is filled with 1 if objects is stopped */
457 int can_go_x(int old_x,int new_x,int yh, int yl,unsigned char *flag)
459 int x,y;
460 if (yh<0) yh=0;
461 if (old_x==new_x+.5)
463 if(flag)*flag=0;
464 return new_x;
466 if(flag)*flag=1;
467 if (old_x<new_x)
468 for (x=double2int(old_x)+1;x<=round_up(new_x);x++) /* go to the right */
470 if (x>AREA_X-1) return int2double(AREA_X-1);
471 for (y=yh;y<=yl;y++)
472 if ((area_a[x+y*AREA_X]&240)==TYPE_WALL)
473 return int2double(x-1);
475 else
476 for (x=round_up(old_x)-1;x>=double2int(new_x);x--) /* go to the left */
478 if (x<0) return 0;
479 for (y=yh;y<=yl;y++)
480 if ((area_a[x+y*AREA_X]&240)==TYPE_WALL) return int2double(x+1);
482 if(flag)*flag=0;
483 return new_x;
487 /* test if horizontal line from xl to xr can move from old_y to new_y axis */
488 /* returns farthest possible y axis */
489 /* flag is filled with 1 if objects is stopped */
490 /* down ladder: 1=fall through ladders etc., 0=stand on ladders */
491 int can_go_y(int old_y, int new_y,int xl, int xr,unsigned char *flag,unsigned char down_ladder)
493 int x,y;
494 if (xl<0) xl=0;
495 if (old_y==new_y){if(flag)*flag=0;return new_y;}
496 if(flag)*flag=1;
497 if (old_y<new_y)
498 for (y=double2int(old_y)+1;y<=round_up(new_y);y++) /* go down */
500 if (y>AREA_Y-1) return int2double(AREA_Y-1);
501 for (x=xl;x<=xr;x++)
502 if ((area_a[x+y*AREA_X]&240)==TYPE_WALL||(!down_ladder&&((area_a[x+y*AREA_X]&240)==TYPE_JUMP||(area_a[x+y*AREA_X]&240)==TYPE_JUMP_FOREGROUND))) return int2double(y-1);
504 else
506 if (flag)*flag=2;
507 for (y=round_up(old_y)-1;y>=double2int(new_y);y--) /* go up */
509 if (y<0) return 0;
510 for (x=xl;x<=xr;x++)
511 if ((area_a[x+y*AREA_X]&240)==TYPE_WALL) return int2double(y+1);
514 if(flag)*flag=0;
515 return new_y;
519 /* automatically computes dimensions of unknown type, if anim positions is given */
520 /* object must be rectangular */
521 #ifdef HAVE_INLINE
522 inline void
523 #else
524 void
525 #endif
526 get_dimensions(int type,int status,struct pos *s,int *w,int *h)
528 switch(type)
530 case T_PLAYER:
531 if (status & S_CREEP)
533 *w=CREEP_WIDTH;
534 *h=CREEP_HEIGHT;
536 else
538 *w=PLAYER_WIDTH;
539 *h=PLAYER_HEIGHT;
541 return;
543 case T_SHOTGUN:
544 *w=22;
545 *h=3;
546 return;
548 case T_UZI:
549 *w=12;
550 *h=3;
551 return;
553 default:
554 *w=0;
555 if (!s){*h=0;return;}
556 *h=s->n;
557 if (*h)*w=s->lines[0].len;
563 /* updates object's position */
564 void update_position(struct it* obj,int new_x,int new_y,int width, int height,unsigned char *fx,unsigned char *fy)
566 unsigned char down_ladder=0;
568 /* player is climbing ladder down */
569 if (obj->type == T_PLAYER && obj->status & S_CLIMB_DOWN)
570 down_ladder = 1;
572 if (obj->xspeed>0)
573 obj->x=sub_int(can_go_x(add_int(obj->x,width-1),add_int(new_x,width-1),double2int(obj->y),round_up(obj->y)+height-1,fx),width-1);
574 else
575 obj->x=can_go_x(obj->x,new_x,double2int(obj->y),round_up(obj->y)+height-1,fx);
577 if (obj->yspeed>0)
578 obj->y=sub_int(can_go_y(add_int(obj->y,height-1),add_int(new_y,height-1),double2int(obj->x),round_up(obj->x)+width-1,fy,down_ladder),height-1);
579 else
580 obj->y=can_go_y(obj->y,new_y,double2int(obj->x),round_up(obj->x)+width-1,fy,down_ladder);
584 unsigned char *__add_md5(char *filename, int *len, unsigned char**result)
586 unsigned char *p;
587 char *q;
588 int a;
590 q=MD5File(filename,NULL);
591 a=strlen(q);
592 if (!(*result))*result=DUMMY;
593 p=mem_realloc((*result),(*len)+a+1);
594 if (!result)return NULL;
595 (*result)=p;
596 memcpy((*result)+(*len),q,a+1);
597 mem_free(q);
598 (*len)+=a;
599 return (*result);
602 /* computes md5 sum from the level
603 * level_num is the line number in level.dat file
604 * returns allocated string with the MD5 sum or NULL (on error)
606 char* md5_level(int level_num)
608 unsigned char *result=0;
609 char *q;
610 int len=0;
611 char p[2048];
613 q=load_level(level_num);
614 if (!q)return NULL;
616 if (!__add_md5(DATA_PATH LEVEL_FILE,&len,&result)){mem_free(result);return NULL;}
618 snprintf(p,2048,"%s%s%s",DATA_PATH,q,LEVEL_SPRITES_SUFFIX);
619 if (!__add_md5(p,&len,&result)){mem_free(result);return NULL;}
621 snprintf(p,2048,"%s%s%s",DATA_PATH,q,STATIC_DATA_SUFFIX);
622 if (!__add_md5(p,&len,&result)){mem_free(result);return NULL;}
624 snprintf(p,2048,"%s%s%s",DATA_PATH,q,DYNAMIC_DATA_SUFFIX);
625 if (!__add_md5(p,&len,&result)){mem_free(result);return NULL;}
627 snprintf(p,2048,"%s%s%s",DATA_PATH,q,LEVEL_SPRITES_SUFFIX);
628 mem_free(q);
631 FILE *f;
633 #ifndef WIN32
634 if(!(f=fopen(p,"r")))
635 #else
636 if(!fopen_s(&f, p, "r"))
637 #endif
639 mem_free(result);
640 return NULL;
642 while (fgets(p,2048,f))
644 if (p[strlen(p)-1]==13)p[strlen(p)-1]=0;
645 if (p[strlen(p)-1]==10)p[strlen(p)-1]=0;
647 q=p;
648 _skip_ws(&q);
649 for (;(*q)&&(*q)!=' '&&(*q)!=9&&(*q)!=10&&(*q)!=13;q++);
650 _skip_ws(&q);
651 if (!strlen(q))continue;
652 if (!__add_md5(q,&len,&result)){mem_free(result);return NULL;}
654 fclose(f);
657 q=MD5Data(result,len,NULL);
658 mem_free(result);
659 return q;
662 /* returns 1 if the file is readable */
663 static int r_access(const char *filename)
665 #ifdef HAVE_ACCESS
666 return !access(filename, R_OK);
667 #else
668 FILE *f;
669 #ifndef WIN32
670 if(f = fopen(filename, "r"))
671 #else
672 if(fopen_s(&f, filename, "r"))
673 #endif
675 fclose(f);
676 return 1;
678 return 0;
679 #endif
682 /* changes the current dir to where the data files can be found */
683 void chdir_to_data_files(void)
685 if (!r_access(DATA_PATH BANNER_FILE))
686 chdir(BASE_DIR);