DEADSOFTWARE

portability: remove dependency on str(n)casemp
[flatwaifu.git] / src / miscc.c
1 /* Copyright (C) 1996-1997 Aleksey Volynskov
2 * Copyright (C) 2011 Rambo
3 * Copyright (C) 2020 SovietPony
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
18 #include "glob.h"
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include "files.h"
24 #include "memory.h"
25 #include "sound.h"
26 #include "view.h"
27 #include "bmap.h"
28 #include "dots.h"
29 #include "monster.h"
30 #include "misc.h"
31 #include "render.h"
33 //#define WD 200
34 //#define HT 98
36 #define MAX_YV 30
38 byte z_dot;
39 byte z_mon;
40 static void *bulsnd[2];
41 static byte wfront;
43 int Z_sign(int a) {
44 if(a>0) return 1;
45 if(a<0) return -1;
46 return 0;
47 }
49 int Z_dec(int a,int b) {
50 if(abs(a)<=b) return 0;
51 if(a>0) return a-b;
52 if(a<0) return a+b;
53 return 0;
54 }
56 void *Z_getsnd(char n[6]) {
57 char s[8];
58 s[0] = 'D';
59 s[1] = 'S';
60 strncpy(&s[2], n, 6);
61 return S_load(s);
62 }
64 int Z_sound (void *s, int v) {
65 if (s != NULL) {
66 S_play(s, 0, v);
67 // TODO ???
68 //S_play(s, -1, 1024, v);
69 //return F_getreslen(((int*)s)[-1])/605;
70 return 0;
71 } else {
72 return 0;
73 }
74 }
76 #define GAS_START (MN__LAST-MN_DEMON+5)
77 #define GAS_TOTAL (MN__LAST-MN_DEMON+16+10)
79 void Z_initst(void) {
80 bulsnd[0]=Z_getsnd("BUL1");
81 bulsnd[1]=Z_getsnd("BUL2");
82 }
84 int Z_canstand(int x,int y,int r) {
85 int i;
87 i=(x-r)/CELW;
88 x=(x+r)/CELW;
89 y=(y+1)/CELH;
90 if(y>=FLDH || y<0) return 0;
91 if(i<0) i=0;
92 if(x>=FLDW) x=FLDW-1;
93 for(;i<=x;++i)
94 if(fld[y][i]==1 || fld[y][i]==2 || fld[y][i]==4)
95 if(!z_dot) return 1;
96 else if(!((walf[fldf[y][i]]|walf[fldb[y][i]])&2)) return 1;
97 return 0;
98 }
100 static int Z_hitceil(int x,int y,int r,int h) {
101 int i;
103 i=(x-r)/CELW;
104 x=(x+r)/CELW;
105 y=(y-h+1)/CELH;
106 if(y>=FLDH || y<0) return 0;
107 if(i<0) i=0;
108 if(x>=FLDW) x=FLDW-1;
109 for(;i<=x;++i)
110 if(fld[y][i]==1 || fld[y][i]==2)
111 if(!z_dot) return 1;
112 else if(!((walf[fldf[y][i]]|walf[fldb[y][i]])&2)) return 1;
113 return 0;
116 int Z_canfit(int x,int y,int r,int h) {
117 int i,j,sx,sy;
119 sx=(x-r)/CELW;
120 sy=(y-h+1)/CELH;
121 if(sx<0) sx=0;
122 if(sy<0) sy=0;
123 x=(x+r)/CELW;
124 y=(y-0)/CELH;
125 if(x>=FLDW) x=FLDW-1;
126 if(y>=FLDH) y=FLDH-1;
127 for(i=sx;i<=x;++i)
128 for(j=sy;j<=y;++j)
129 if(fld[j][i]==1 || fld[j][i]==2)
130 if(!z_dot) return 0;
131 else if(!((walf[fldf[j][i]]|walf[fldb[j][i]])&2)) return 0;
132 return 1;
135 static int Z_inlift(int x,int y,int r,int h) {
136 int i,j,sx,sy;
138 sx=(x-r)/CELW;
139 sy=(y-h+1)/CELH;
140 if(sx<0) sx=0;
141 if(sy<0) sy=0;
142 x=(x+r)/CELW;
143 y=(y-1)/CELH;
144 if(x>=FLDW) x=FLDW-1;
145 if(y>=FLDH) y=FLDH-1;
146 for(i=sx;i<=x;++i)
147 for(j=sy;j<=y;++j)
148 if(fld[j][i]==9 || fld[j][i]==10) return fld[j][i]-8;
149 return 0;
152 static int Z_isblocked(int x,int y,int r,int h,int xv) {
153 int i,j,sx,sy;
155 sx=(x-r)/CELW;
156 sy=(y-h+1)/CELH;
157 if(sx<0) sx=0;
158 if(sy<0) sy=0;
159 x=(x+r)/CELW;
160 y=(y-1)/CELH;
161 if(xv<0) x=sx;
162 else if(xv>0) sx=x;
163 if(x>=FLDW) x=FLDW-1;
164 if(y>=FLDH) y=FLDH-1;
165 for(i=sx;i<=x;++i)
166 for(j=sy;j<=y;++j)
167 if(fld[j][i]==8) return 1;
168 return 0;
171 int Z_istrapped(int x,int y,int r,int h) {
172 int i,j,sx,sy;
174 sx=(x-r)/CELW;
175 sy=(y-h+1)/CELH;
176 if(sx<0) sx=0;
177 if(sy<0) sy=0;
178 x=(x+r)/CELW;
179 y=(y-1)/CELH;
180 if(x>=FLDW) x=FLDW-1;
181 if(y>=FLDH) y=FLDH-1;
182 for(i=sx;i<=x;++i)
183 for(j=sy;j<=y;++j)
184 if(fld[j][i]==255) return 1;
185 return 0;
188 void Z_set_speed(obj_t *o,int s) {
189 int m;
191 if(!(m=max(abs(o->xv),abs(o->yv)))) m=1;
192 o->xv=o->xv*s/m;o->yv=o->yv*s/m;
195 int Z_inwater(int x,int y,int r,int h) {
196 int i,j,sx,sy;
198 sx=(x-r)/CELW;
199 sy=(y-h+1)/CELH;
200 if(sx<0) sx=0;
201 if(sy<0) sy=0;
202 x=(x+r)/CELW;
203 y=(y-h/2)/CELH;
204 if(x>=FLDW) x=FLDW-1;
205 if(y>=FLDH) y=FLDH-1;
206 for(i=sx;i<=x;++i)
207 for(j=sy;j<=y;++j)
208 if(fld[j][i]>=5 && fld[j][i]<=7) {wfront=fldf[j][i];return 1;}
209 return 0;
212 int Z_getacid(int x,int y,int r,int h) {
213 int i,j,sx,sy,a;
214 static byte tab[4]={0,5,10,20};
216 a=0;
217 sx=(x-r)/CELW;
218 sy=(y-h+1)/CELH;
219 if(sx<0) sx=0;
220 if(sy<0) sy=0;
221 x=(x+r)/CELW;
222 y=y/CELH;
223 if(x>=FLDW) x=FLDW-1;
224 if(y>=FLDH) y=FLDH-1;
225 for(i=sx;i<=x;++i)
226 for(j=sy;j<=y;++j)
227 if(fld[j][i]==6) a|=1;
228 else if(fld[j][i]==7) a|=2;
229 return tab[a];
232 int Z_canbreathe(int x,int y,int r,int h) {
233 int i,j,sx,sy;
235 sx=(x-r)/CELW;
236 sy=(y-h+1)/CELH;
237 if(sx<0) sx=0;
238 if(sy<0) sy=0;
239 x=(x+r)/CELW;
240 y=(y-h/2)/CELH;
241 if(x>=FLDW) x=FLDW-1;
242 if(y>=FLDH) y=FLDH-1;
243 if(sx>x || sy>y) return 1;
244 for(i=sx;i<=x;++i)
245 for(j=sy;j<=y;++j)
246 if(fld[j][i]==0 || fld[j][i]==3 || fld[j][i]==9 || fld[j][i]==10) return 1;
247 return 0;
250 int Z_overlap(obj_t *a,obj_t *b) {
251 if(a->x - a->r > b->x + b->r) return 0;
252 if(a->x + a->r < b->x - b->r) return 0;
253 if(a->y <= b->y - b->h) return 0;
254 if(a->y - a->h >= b->y) return 0;
255 return 1;
258 static void Z_kickobj(obj_t *o,int x,int y,int pwr) {
259 int dx,dy,m;
261 dx=o->x-x;dy=o->y-o->h/2-y;
262 if(!(m=max(abs(dx),abs(dy)))) m=1;
263 o->vx+=(long)dx*pwr/m;
264 o->vy+=(long)dy*pwr/m;
267 int Z_cansee(int x,int y,int xd,int yd) {
268 register dword d,m;
269 int sx,sy;
270 dword xe,ye,s,i;
272 if((xd-=x)>0) sx=1;
273 else if(xd<0) sx=-1;
274 else sx=0;
275 if((yd-=y)>0) sy=1;
276 else if(yd<0) sy=-1;
277 else sy=0;
278 if(!xd && !yd) return 1;
279 if((xd=abs(xd)) > (yd=abs(yd))) d=xd; else d=yd;
280 xe=ye=0;
281 for(i=0;i<=d;) {
282 if(x<0 || x>=FLDW*8 || y<0 || y>=FLDH*8) return 0;
283 if((bmap[y>>5][x>>5]&BM_WALL)) {
284 if(fld[y>>3][x>>3]==1 || fld[y>>3][x>>3]==2) return 0;
285 if((xe+=(xd<<3))>=d) {
286 x+=xe/d*sx;xe=xe%d;
288 if((ye+=(yd<<3))>=d) {
289 y+=ye/d*sy;ye=ye%d;
291 i+=8;
292 }else{
293 if(sx==0) m=0;
294 else{m=x&31;if(sx>0) m^=31; ++m;}
295 if(sy==0) s=0;
296 else{s=y&31;if(sy>0) s^=31; ++s;}
297 if((s<m && s!=0) || m==0) m=s;
298 i+=m;
299 x+=(xd*m+xe)/d*sx;xe=(xd*m+xe)%d;
300 y+=(yd*m+ye)/d*sy;ye=(yd*m+ye)%d;
303 return 1;
306 int Z_look(obj_t *a,obj_t *b,int d) {
307 if(Z_sign(b->x-a->x)!=d*2-1) return 0;
308 return Z_cansee(a->x,a->y-a->h/2,b->x,b->y-b->h/2);
311 #define wvel(v) if((xv=abs(v)+1)>5) v=Z_dec(v,xv/2-2)
313 int Z_moveobj(obj_t *p) {
314 static int x,y,xv,yv,r,h,lx,ly,st;
315 static byte inw;
317 st=0;
318 switch(Z_inlift(x=p->x,y=p->y,r=p->r,h=p->h)) {
319 case 0:
320 if(++p->yv>MAX_YV) --p->yv;
321 break;
322 case 1:
323 if(--p->yv < -5) ++p->yv;
324 break;
325 case 2:
326 if(p->yv > 5) {--p->yv;break;}
327 ++p->yv;break;
329 if((inw=Z_inwater(x,y,r,h))!=0) {
330 st|=Z_INWATER;
331 wvel(p->xv);
332 wvel(p->yv);
333 wvel(p->vx);
334 wvel(p->vy);
336 p->vx=Z_dec(p->vx,1);
337 p->vy=Z_dec(p->vy,1);
338 xv=p->xv+p->vx;yv=p->yv+p->vy;
339 while(xv || yv) {
340 if(x<-100 || x>=FLDW*8+100 || y<-100 || y>=FLDH*8+100)
341 {st|=Z_FALLOUT;}
343 lx=x;
344 x+=(abs(xv)<=7)?xv:((xv>0)?7:-7);
345 if(z_mon) if(Z_isblocked(x,y,r,h,xv)) st|=Z_BLOCK;
346 if(!Z_canfit(x,y,r,h)) {
347 if(xv==0) x=lx;
348 else if(xv<0) x=((lx-r)&0xFFF8)+r;
349 else x=((lx+r)&0xFFF8)-r+7;
350 xv=p->xv=p->vx=0;st|=Z_HITWALL;
352 xv-=(abs(xv)<=7)?xv:((xv>0)?7:-7);
354 ly=y;
355 y+=(abs(yv)<=7)?yv:((yv>0)?7:-7);
356 if(yv>=8) --y;
357 if(yv<0 && Z_hitceil(x,y,r,h)) {
358 y=((ly-h+1)&0xFFF8)+h-1;
359 yv=p->vy=1;p->yv=0;st|=Z_HITCEIL;
361 if(yv>0 && Z_canstand(x,y,r)) {
362 y=((y+1)&0xFFF8)-1;
363 yv=p->yv=p->vy=0;st|=Z_HITLAND;
365 yv-=(abs(yv)<=7)?yv:((yv>0)?7:-7);
367 p->x=x;p->y=y;
368 if(Z_inwater(x,y,r,h)) {
369 st|=Z_INWATER;
370 if(!inw) st|=Z_HITWATER;
371 }else if(inw) st|=Z_HITAIR;
372 return st;
375 void Z_splash (obj_t *p, int n) {
376 Z_sound(bulsnd[0], 128);
377 DOT_water(p->x, p->y-p->h / 2, p->xv + p->vx, p->yv + p->vy, n, R_get_special_id(wfront) - 1);
380 void Z_calc_time(dword t,word *h,word *m,word *s)
382 t = t * DELAY;
383 t = t / 1000;
384 *s = t % 60;
385 t = t - *s;
386 t = t / 60;
387 *m = t % 60;
388 t = t - *m;
389 t = t / 60;
390 *h = t;
393 #define SWAP_VAR(a, b) do { unsigned char t = a; a = b; b = t; } while(0)
395 static int16_t short2swap (int16_t x) {
396 union {
397 uint8_t a[2];
398 int16_t x;
399 } y;
400 y.x = x;
401 SWAP_VAR(y.a[0], y.a[1]);
402 return y.x;
405 static int32_t int2swap (int32_t x) {
406 union {
407 uint8_t a[4];
408 int32_t x;
409 } y;
410 y.x = x;
411 SWAP_VAR(y.a[0], y.a[3]);
412 SWAP_VAR(y.a[1], y.a[2]);
413 return y.x;
416 #undef SWAP_VAR
418 int16_t short2host (int16_t x) {
419 #if __BIG_ENDIAN__
420 return short2swap(x);
421 #else
422 return x;
423 #endif
426 int32_t int2host (int32_t x) {
427 #if __BIG_ENDIAN__
428 return int2swap(x);
429 #else
430 return x;
431 #endif