1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 
5 #ifndef WIN32
6 #include "config.h"
7 #endif
8 
9 #include "data.h"
10 #include "cfg.h"
11 #include "hash.h"
12 #include "time.h"
13 #include "md5.h"
14 #include "error.h"
15 
16 
17 #ifdef TRI_D
18 int tri_d=0;
19 int TRI_D_ON=0;
20 #endif
21 
22 
23 /* static map of the level */
24 unsigned char *area;
25 
26 /* attributes:
27 	lower 4 bits=color
28 	higher 4 bits=type
29 */
30 unsigned char *area_a;
31 
32 
33 struct sprite *sprites=DUMMY;
34 unsigned char **sprite_names=DUMMY;
35 int n_sprites;  /* number of sprites */
36 
37 struct object_list *last_obj;
38 
39 #define NOBODY 0
40 #define CLIENT 1
41 #define BOTH 3
42 #define BOTH_UPDATE 7
43 
44 /* object attributes */
45 struct obj_attr_type obj_attr[N_TYPES]=
46 {
47 	/* fall, bounce x, bounce y, slow down x, maintainer, foreground */
48 	{1,0,0,PLAYER_SLOW_DOWN_X,BOTH_UPDATE,0},  /* player */
49 	{0,0,0,int2double(1),BOTH,0},  /* bullet */
50 	{1,0,float2double(.25),PLAYER_SLOW_DOWN_X,BOTH,0},  /* corpse */
51 	{1,0,0,0,NOBODY,0},  /* medikit */
52 	{1,0,0,0,NOBODY,0},  /* shotgun */
53 	{1,0,0,0,NOBODY,0},  /* uzi */
54 	{1,0,0,0,NOBODY,0},  /* rifle */
55 	{1,float2double(.8),float2double(.5),float2double(.8),CLIENT,0},  /* shell */
56 	{1,0,0,0,NOBODY,0},  /* ammo for gun */
57 	{1,0,0,0,NOBODY,0},  /* ammo for shotgun */
58 	{1,0,0,0,NOBODY,0},  /* ammo for uzi */
59 	{1,0,0,0,NOBODY,0},  /* ammo for rifle */
60 	{0,0,0,0,NOBODY,0},  /* nothing */
61 	{1,float2double(.4),float2double(.4),float2double(.3),CLIENT,0},   /* mess */
62 	{1,float2double(.5),float2double(.5),float2double(.9),BOTH/*_UPDATE*/,0},    /* grenade */
63 	{1,0,0,0,NOBODY,0},  /* grenade ammo */
64 	{1,0,0,int2double(1),BOTH,0},  /* grenade shrapnel */
65 	{1,0,0,0,NOBODY,0},  /* armor */
66 	{1,0,0,0,NOBODY,0},  /* invisibility */
67 	{1,0,0,0,NOBODY,0},  /* noise */
68 	{0,0,0,0,NOBODY,1},  /* nothing in foreground */
69 	{0,0,0,0,NOBODY,1},  /* killing object */
70 };
71 
72 
73 /* weapon attributes */
74 struct weapon_type weapon[ARMS]=
75 {
76 	/* name, cadence, ttl, bullet speed, impact, lethalness, armor damage, basic ammo, additional ammo, max ammo, shell xspeed, shell yspeed */
77 	{"Browning",16,50,float2double(3*36),float2double(.3*36),20,2,13,12,48,float2double((double).3*36),-float2double(1*36)},
78 	{"Shotgun",25,50,float2double(3*36),float2double(.5*36),10,5,6,12,30,float2double((double).3*36),-float2double((double)1.2*36)},
79 	{"Uzi",3,50,float2double(4*36),float2double(.25*36),15,4,50,50,150,float2double((double).9*36),-float2double((double)1.5*36)},
80 	{"Rifle",40,70,float2double(6*36),float2double(.4*36),50,20,1,15,15,0,0},
81 	{"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 */
82 };
83 
84 
85 /* initialize playing area */
86 /* must be run before loading data */
init_area(void)87 void init_area(void)
88 {
89 	area=mem_alloc(AREA_X*AREA_Y);
90 	if (!area){ERROR("Error: Not enough memory!\n");EXIT(1);}
91 	area_a=mem_alloc(AREA_X*AREA_Y);
92 	if (!area_a){ERROR("Error: Not enough memory!\n");EXIT(1);}
93 	memset(area,' ',AREA_X*AREA_Y);
94 	memset(area_a,0,AREA_X*AREA_Y);
95 }
96 
free_area(void)97 void free_area(void)
98 {
99 	mem_free(area);
100 	mem_free(area_a);
101 }
102 
103 
104 /* reinitializes playing area */
105 /* must be called before loading new level */
reinit_area(void)106 void reinit_area(void)
107 {
108 	memset(area,' ',AREA_X*AREA_Y);
109 	memset(area_a,0,AREA_X*AREA_Y);
110 }
111 
112 /* skip white space */
113 /* ancillary function */
_skip_ws(char ** txt)114 void _skip_ws(char **txt)
115 {
116  for (;(**txt)==' '||(**txt)==9||(**txt)==10;(*txt)++);
117 }
118 
119 
120 /* find sprite according to its name */
121 /* returns 1 on error */
122 /* it's slow but not called in speed critical parts of the program */
find_sprite(unsigned char * name,int * num)123 int find_sprite(unsigned char *name,int *num)
124 {
125  for ((*num)=0;(*num)<n_sprites;(*num)++)
126   if (!strcmp(sprite_names[*num],name))return 0;
127  return 1;
128 }
129 
130 
131 /* convert type character (from data files) into type */
_convert_type(unsigned char c)132 int _convert_type(unsigned char c)
133 {
134  switch(c)
135  {
136 
137 /* static objects */
138   case 'b': return TYPE_BACKGROUND;
139 
140   case 'w': return TYPE_WALL;
141 
142   case 'j': return TYPE_JUMP;
143 
144   case 'f': return TYPE_FOREGROUND;
145 
146   case 'i': return TYPE_JUMP_FOREGROUND;
147 
148 /* dynamic objects, they use great letter */
149 
150   case 'M': return T_MEDIKIT;
151 
152   case 'A': return T_ARMOR;
153 
154   case 'N': return T_NOTHING;
155 
156   case 'F': return T_NOTHING_FORE;
157 
158   case 'K': return T_KILL;
159 
160   case 'S': return T_SHOTGUN;
161 
162   case 'U': return T_UZI;
163 
164   case 'R': return T_RIFLE;
165 
166   case '1': return T_AMMO_GUN;
167 
168   case '2': return T_AMMO_SHOTGUN;
169 
170   case '3': return T_AMMO_UZI;
171 
172   case '4': return T_AMMO_RIFLE;
173 
174   case '5': return T_AMMO_GRENADE;
175 
176   case 'I': return T_INVISIBILITY;
177 
178   /* birthplace */
179   case 'B': return TYPE_BIRTHPLACE;
180 
181   default:
182   return -1;
183  }
184 }
185 
186 
187 /* load static data */
load_data(unsigned char * filename)188 void load_data(unsigned char * filename)
189 {
190  FILE * stream;
191  static char line[1024];
192  char *p,*q,*name;
193  int n,x,y;
194  int t;
195 
196  if (!(stream=fopen(filename,"rb")))
197  {
198 	char msg[256];
199  	snprintf(msg,256,"Can't open file \"%s\"!\n",filename);
200 	ERROR(msg);
201 	EXIT(1);
202  }
203  while(fgets(line,1024,stream))
204  {
205   p=line;
206   _skip_ws(&p);
207   for (name=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++);
208   if (!(*p))continue;
209   *p=0;p++;
210   _skip_ws(&p);
211   if ((t=_convert_type(*p))<0)
212   {
213 	char msg[256];
214   	snprintf(msg,256,"Unknown object type '%c'.\n",*p);
215 	ERROR(msg);
216 	EXIT(1);
217   }
218   p++;
219   _skip_ws(&p);
220   x=strtol(p,&q,0);
221   _skip_ws(&q);
222   y=strtol(q,&p,0);
223   if (find_sprite(name,&n))
224   {
225 	char msg[256];
226   	snprintf(msg,256,"Unknown bitmap name \"%s\"!\n",name);
227 	ERROR(msg);
228 	EXIT(1);
229   }
230   _put_sprite(AREA_X,AREA_Y,area,area_a,x,y,sprites[n].positions,t,0);
231  }
232  fclose(stream);
233 }
234 
235 
236 /* load sprites */
load_sprites(unsigned char * filename)237 void load_sprites(unsigned char * filename)
238 {
239  FILE *stream;
240  static char line[1024];
241  char *p,*q;
242  int l;
243 
244  stream=fopen(filename,"rb");
245  if (!stream)
246  {
247  	char msg[256];
248 	snprintf(msg,256,"Can't open file \"%s\"!\n",filename);
249 	ERROR(msg);
250 	EXIT(1);
251  }
252  while(fgets(line,1024,stream))
253  {
254   p=line;
255   _skip_ws(&p);
256   for (q=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++);
257   if (!(*p))continue;
258   *p=0;p++;
259   l=strlen(q);
260   n_sprites++;
261   sprite_names=(unsigned char **)mem_realloc(sprite_names,n_sprites*sizeof(unsigned char*));
262   if (!sprite_names){ERROR("Memory allocation error!\n");EXIT(1);}
263   sprites=(struct sprite *)mem_realloc(sprites,n_sprites*sizeof(struct sprite));
264   if (!sprites){ERROR("Memory allocation error!\n");EXIT(1);}
265   sprite_names[n_sprites-1]=(char *)mem_alloc(l+1);
266   if (!sprite_names[n_sprites-1]){ERROR("Memory allocation error!\n");EXIT(1);}
267   memcpy(sprite_names[n_sprites-1],q,l+1);
268   _skip_ws(&p);
269   for (q=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++);
270   *p=0;p++;
271   load_sprite(q,sprites+(n_sprites-1));
272  }
273  fclose(stream);
274 }
275 
276 
free_sprites(int start_num)277 void free_sprites(int start_num)
278 {
279 	int a;
280 
281 	for (a=start_num;a<n_sprites;a++)
282 	{
283 		mem_free(sprite_names[a]);
284 		free_sprite(sprites+a);
285 	}
286 	n_sprites=start_num;
287   	sprite_names=(unsigned char **)mem_realloc(sprite_names,n_sprites*sizeof(unsigned char*));
288 	if (!sprite_names){ERROR("Memory allocation error!\n");EXIT(1);}
289 	sprites=mem_realloc(sprites,n_sprites*sizeof(struct sprite));
290 	if (!sprites){ERROR("Memory allocation error!\n");EXIT(1);}
291 }
292 
293 
294 /* returns allocated string with level name or NULL on error */
295 /* level_num is a line number in the LEVEL_FILE */
load_level(int level_num)296 unsigned char *load_level(int level_num)
297 {
298 	unsigned char txt[1024];
299 	unsigned char *retval;
300 	int a;
301 	FILE *f;
302 
303 	f=fopen(DATA_PATH LEVEL_FILE,"r");
304 	if (!f)return NULL;
305 
306 	for (a=0;a<=level_num;)
307 	{
308 		if (!(fgets(txt,1024,f)))return NULL;
309 
310 		/* remove trailing CR and/or LF */
311 		if (txt[strlen(txt)-1]==10)txt[strlen(txt)-1]=0;
312 		if (txt[strlen(txt)-1]==13)txt[strlen(txt)-1]=0;
313 
314 		if (strlen(txt))a++;
315 	}
316 
317 	fclose(f);
318 
319 	a=strlen(txt);
320 	retval=mem_alloc(1+a*sizeof(unsigned char));
321 	if (!retval)return NULL;
322 	memcpy(retval,txt,a+1); /* including trailing zero */
323 	if (!strlen(retval)){mem_free(retval);return NULL;}
324 	return retval;
325 
326 }
327 
328 /* create a new object and fill with data and add to hash table */
new_obj(unsigned int id,unsigned char type,int ttl,int sprite,unsigned char pos,int status,my_double x,my_double y,my_double xspeed,my_double yspeed,void * data)329 struct it * new_obj(
330 	unsigned int id,
331 	unsigned char type,
332 	int ttl,
333 	int sprite,
334 	unsigned char pos,
335 	int status,
336 	my_double x,
337 	my_double y,
338 	my_double xspeed,
339 	my_double yspeed,
340 	void * data)
341 {
342         last_obj->next=mem_alloc(sizeof(struct object_list));
343         if (!last_obj->next)return 0;
344         last_obj->next->prev=last_obj;
345         last_obj=last_obj->next;
346         last_obj->next=0;
347         last_obj->member.x=x;
348         last_obj->member.y=y;
349         last_obj->member.xspeed=xspeed;
350         last_obj->member.yspeed=yspeed;
351         last_obj->member.type=type;
352         last_obj->member.ttl=ttl;
353         last_obj->member.sprite=sprite;
354         last_obj->member.anim_pos=pos;
355         last_obj->member.data=data;
356 	last_obj->member.id=id;
357 	last_obj->member.status=status;
358 	last_obj->member.update_counter=0;
359 	last_obj->member.last_updated=get_time();
360 	add_to_table(last_obj);
361         return &(last_obj->member);
362 }
363 
364 
365 /* completely delete object from the list */
delete_obj(unsigned long id)366 void delete_obj(unsigned long id)
367 {
368 	struct object_list *q;
369 	if (!(q=remove_from_table(id)))return;  /* packets can come more than once, so we must ignore deleting deleted object */
370 	q->prev->next=q->next;
371 	if (!q->next) last_obj=q->prev;  /* q is last object in list */
372 	else q->next->prev=q->prev;
373 	mem_free(q);
374 }
375 
376 
put_long_long(unsigned char * p,unsigned long_long num)377 void put_long_long(unsigned char *p,unsigned long_long num)
378 {
379         p[0]=num&255;num>>=8;
380         p[1]=num&255;num>>=8;
381         p[2]=num&255;num>>=8;
382         p[3]=num&255;num>>=8;
383         p[4]=num&255;num>>=8;
384         p[5]=num&255;num>>=8;
385         p[6]=num&255;num>>=8;
386         p[7]=num&255;
387 }
388 
389 
put_int(unsigned char * p,int num)390 void put_int(unsigned char *p,int num)
391 {
392         p[0]=num&255;num>>=8;
393         p[1]=num&255;num>>=8;
394         p[2]=num&255;num>>=8;
395         p[3]=num&255;
396 }
397 
398 
get_int(unsigned char * p)399 int get_int(unsigned char *p)
400 {
401         return 	(int)p[0]+
402 		((int)(p[1])<<8)+
403 		((int)(p[2])<<16)+
404 		((int)(p[3])<<24);
405 }
406 
407 
put_int16(unsigned char * p,int num)408 void put_int16(unsigned char *p,int num)
409 {
410         p[0]=num&255;num>>=8;
411         p[1]=num&255;
412 }
413 
414 
get_int16(unsigned char * p)415 int get_int16(unsigned char *p)
416 {
417         return (int)p[0]+((int)(p[1])<<8);
418 }
419 
420 
get_float(unsigned char * p)421 my_double get_float(unsigned char *p)
422 {
423 	int a;
424 	a=	(int)p[0]+
425 		((int)(p[1])<<8)+
426 		((int)(p[2])<<16)+
427 		((int)(p[3])<<24);
428 	return a;
429 }
430 
431 
put_float(unsigned char * p,my_double num)432 void put_float(unsigned char *p,my_double num)
433 {
434         p[0]=num&255;num>>=8;
435         p[1]=num&255;num>>=8;
436         p[2]=num&255;num>>=8;
437         p[3]=num&255;
438 }
439 
440 
get_long_long(unsigned char * p)441 unsigned long_long get_long_long(unsigned char *p)
442 {
443 #define ULL unsigned long_long
444         return 	(ULL)p[0]+
445 		((ULL)(p[1])<<8)+
446 		((ULL)(p[2])<<16)+
447 		((ULL)(p[3])<<24)+
448 		((ULL)(p[4])<<32)+
449 		((ULL)(p[5])<<40)+
450 		((ULL)(p[6])<<48)+
451 		((ULL)(p[7])<<56);
452 #undef ULL
453 }
454 
455 
456 
457 /* test if vertical line from yh to yl can move from old_x to new_x axis */
458 /* returns farthest possible x axis */
459 /* flag is filled with 1 if objects is stopped */
can_go_x(my_double old_x,my_double new_x,int yh,int yl,unsigned char * flag)460 my_double can_go_x(my_double old_x,my_double new_x,int yh, int yl,unsigned char *flag)
461 {
462 	int x,y;
463 	if (yh<0) yh=0;
464 	if (old_x==new_x+.5)
465 	{
466 		if(flag)*flag=0;
467 		return new_x;
468 	}
469 	if(flag)*flag=1;
470 	if (old_x<new_x)
471 		for (x=double2int(old_x)+1;x<=round_up(new_x);x++)  /* go to the right */
472 		{
473 			if (x>AREA_X-1) return int2double(AREA_X-1);
474 			for (y=yh;y<=yl;y++)
475 				if ((area_a[x+y*AREA_X]&240)==TYPE_WALL)
476 					return int2double(x-1);
477 		}
478 	else
479 		for (x=round_up(old_x)-1;x>=double2int(new_x);x--)  /* go to the left */
480 		{
481 			if (x<0) return 0;
482 			for (y=yh;y<=yl;y++)
483 				if ((area_a[x+y*AREA_X]&240)==TYPE_WALL) return int2double(x+1);
484 		}
485 	if(flag)*flag=0;
486 	return new_x;
487 }
488 
489 
490 /* test if horizontal line from xl to xr can move from old_y to new_y axis */
491 /* returns farthest possible y axis */
492 /* flag is filled with 1 if objects is stopped */
493 /* down ladder: 1=fall through ladders etc., 0=stand on ladders */
can_go_y(my_double old_y,my_double new_y,int xl,int xr,unsigned char * flag,unsigned char down_ladder)494 my_double can_go_y(my_double old_y, my_double new_y,int xl, int xr,unsigned char *flag,unsigned char down_ladder)
495 {
496 	int x,y;
497 	if (xl<0) xl=0;
498 	if (old_y==new_y){if(flag)*flag=0;return new_y;}
499 	if(flag)*flag=1;
500 	if (old_y<new_y)
501 		for (y=double2int(old_y)+1;y<=round_up(new_y);y++)  /* go down */
502 		{
503 			if (y>AREA_Y-1) return int2double(AREA_Y-1);
504 			for (x=xl;x<=xr;x++)
505 				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);
506 		}
507 	else
508 	{
509 		if (flag)*flag=2;
510 		for (y=round_up(old_y)-1;y>=double2int(new_y);y--)  /* go up */
511 		{
512 			if (y<0) return 0;
513 			for (x=xl;x<=xr;x++)
514 				if ((area_a[x+y*AREA_X]&240)==TYPE_WALL) return int2double(y+1);
515 		}
516 	}
517 	if(flag)*flag=0;
518 	return new_y;
519 }
520 
521 
522 /* automatically computes dimensions of unknown type, if anim positions is given */
523 /* object must be rectangular */
524 #ifdef HAVE_INLINE
525 	inline void
526 #else
527 	void
528 #endif
get_dimensions(int type,int status,struct pos * s,int * w,int * h)529 get_dimensions(int type,int status,struct pos *s,int *w,int *h)
530 {
531 	switch(type)
532 	{
533 		case T_PLAYER:
534 		if (status&256)
535 		{
536 			*w=CREEP_WIDTH;
537 			*h=CREEP_HEIGHT;
538 		}
539 		else
540 		{
541 			*w=PLAYER_WIDTH;
542 			*h=PLAYER_HEIGHT;
543 		}
544 		return;
545 
546 		case T_SHOTGUN:
547 		*w=22;
548 		*h=3;
549 		return;
550 
551 		case T_UZI:
552 		*w=12;
553 		*h=3;
554 		return;
555 
556 		default:
557 		*w=0;
558 		if (!s){*h=0;return;}
559 		*h=s->n;
560 		if (*h)*w=s->lines[0].len;
561 	}
562 }
563 
564 
565 
566 /* updates object's position */
update_position(struct it * obj,my_double new_x,my_double new_y,int width,int height,unsigned char * fx,unsigned char * fy)567 void update_position(struct it* obj,my_double new_x,my_double new_y,int width, int height,unsigned char *fx,unsigned char *fy)
568 {
569 	unsigned char down_ladder=0;
570 
571 	/* player is climbing ladder down */
572 	if (obj->type==T_PLAYER&&obj->status&2048) down_ladder=1;
573 
574 	if (obj->xspeed>0)
575 		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);
576 	else
577 		obj->x=can_go_x(obj->x,new_x,double2int(obj->y),round_up(obj->y)+height-1,fx);
578 
579 	if (obj->yspeed>0)
580 		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);
581 	else
582 		obj->y=can_go_y(obj->y,new_y,double2int(obj->x),round_up(obj->x)+width-1,fy,down_ladder);
583 }
584 
585 
__add_md5(unsigned char * filename,int * len,unsigned char ** result)586 unsigned char *__add_md5(unsigned char *filename, int *len, unsigned char**result)
587 {
588 	unsigned char *p,*q;
589 	int a;
590 
591 	q=MD5File(filename,NULL);
592 	a=strlen(q);
593 	if (!(*result))*result=DUMMY;
594 	p=mem_realloc((*result),(*len)+a+1);
595 	if (!result)return NULL;
596 	(*result)=p;
597 	memcpy((*result)+(*len),q,a+1);
598 	mem_free(q);
599 	(*len)+=a;
600 	return (*result);
601 }
602 
603 /* computes md5 sum from the level
604  * level_num is the line number in level.dat file
605  * returns allocated string with the MD5 sum or NULL (on error)
606  */
md5_level(int level_num)607 unsigned char* md5_level(int level_num)
608 {
609 	unsigned char *result=0;
610 	char *q;
611 	int len=0;
612 	unsigned char p[2048];
613 
614 	q=load_level(level_num);
615 	if (!q)return NULL;
616 
617 	if (!__add_md5(DATA_PATH LEVEL_FILE,&len,&result)){mem_free(result);return NULL;}
618 
619 	snprintf(p,2048,"%s%s%s",DATA_PATH,q,LEVEL_SPRITES_SUFFIX);
620 	if (!__add_md5(p,&len,&result)){mem_free(result);return NULL;}
621 
622 	snprintf(p,2048,"%s%s%s",DATA_PATH,q,STATIC_DATA_SUFFIX);
623 	if (!__add_md5(p,&len,&result)){mem_free(result);return NULL;}
624 
625 	snprintf(p,2048,"%s%s%s",DATA_PATH,q,DYNAMIC_DATA_SUFFIX);
626 	if (!__add_md5(p,&len,&result)){mem_free(result);return NULL;}
627 
628 	snprintf(p,2048,"%s%s%s",DATA_PATH,q,LEVEL_SPRITES_SUFFIX);
629 	mem_free(q);
630 
631 	{
632 		FILE *f;
633 
634 		f=fopen(p,"r");
635 		if (!f){mem_free(result);return NULL;}
636 		while (fgets(p,2048,f))
637 		{
638 			if (p[strlen(p)-1]==13)p[strlen(p)-1]=0;
639 			if (p[strlen(p)-1]==10)p[strlen(p)-1]=0;
640 
641 			q=p;
642 			_skip_ws(&q);
643 			for (;(*q)&&(*q)!=' '&&(*q)!=9&&(*q)!=10&&(*q)!=13;q++);
644 			_skip_ws(&q);
645 			if (!strlen(q))continue;
646 			if (!__add_md5(q,&len,&result)){mem_free(result);return NULL;}
647 		}
648 		fclose(f);
649 	}
650 
651 	q=MD5Data(result,len,NULL);
652 	mem_free(result);
653 	return q;
654 }
655