diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/graphics.c | 1 | ||||
| -rwxr-xr-x | src/main.c | 4 | ||||
| -rw-r--r-- | src/powder-reflection.diff | 510 | ||||
| -rw-r--r-- | src/powder.c | 305 |
4 files changed, 749 insertions, 71 deletions
diff --git a/src/graphics.c b/src/graphics.c index 7ac641e..08798dc 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -16,6 +16,7 @@ #include <air.h> #include <powder.h> #include <graphics.h> +#define INCLUDE_FONTDATA #include <font.h> #include <misc.h> @@ -1302,7 +1302,7 @@ int main(int argc, char *argv[]) if(sdl_key=='h') hud_enable = !hud_enable; if(sdl_key=='p') - dump_frame(vid_buf, XRES, YRES, XRES); + dump_frame(vid_buf, XRES, YRES, XRES+BARSIZE); if(sdl_key=='v'&&(sdl_mod & (KMOD_LCTRL|KMOD_RCTRL))) { if(clipboard_ready==1) @@ -1361,7 +1361,7 @@ int main(int argc, char *argv[]) if(sdl_key=='v') vs = !vs; if(vs) - dump_frame(vid_buf, XRES, YRES, XRES); + dump_frame(vid_buf, XRES, YRES, XRES+BARSIZE); #endif if(sdl_wheel) diff --git a/src/powder-reflection.diff b/src/powder-reflection.diff new file mode 100644 index 0000000..1adcbf7 --- /dev/null +++ b/src/powder-reflection.diff @@ -0,0 +1,510 @@ +diff -urN powder-42.3/air.c powder-42.4/air.c +--- powder-42.3/air.c 2010-09-03 10:20:00.000000000 -0400 ++++ powder-42.4/air.c 2010-10-02 08:05:31.000000000 -0400 +@@ -138,4 +138,4 @@ + memcpy(vx, ovx, sizeof(vx)); + memcpy(vy, ovy, sizeof(vy)); + memcpy(pv, opv, sizeof(pv)); +-} +\ No newline at end of file ++} +diff -urN powder-42.3/air.h powder-42.4/air.h +--- powder-42.3/air.h 2010-09-03 10:20:00.000000000 -0400 ++++ powder-42.4/air.h 2010-10-02 08:05:26.000000000 -0400 +@@ -18,4 +18,4 @@ + + void update_air(void); + +-#endif +\ No newline at end of file ++#endif +diff -urN powder-42.3/defines.h powder-42.4/defines.h +--- powder-42.3/defines.h 2010-09-22 15:07:00.000000000 -0400 ++++ powder-42.4/defines.h 2010-10-02 10:18:19.000000000 -0400 +@@ -8,8 +8,8 @@ + #endif + + #define SAVE_VERSION 42 +-#define MINOR_VERSION 3 +-#define IDENT_VERSION "S" //Change this if you're not Simon! It should be a single letter. ++#define MINOR_VERSION 4 ++#define IDENT_VERSION "$" //Change this if you're not Simon! It should be a single letter. + //#define BETA + + #define SERVER "powdertoy.co.uk" +@@ -115,4 +115,4 @@ + int parse_save(void *save, int size, int replace, int x0, int y0); + void del_stamp(int d); + void sdl_seticon(void); +-#endif +\ No newline at end of file ++#endif +diff -urN powder-42.3/font.h powder-42.4/font.h +--- powder-42.3/font.h 2010-09-03 10:20:00.000000000 -0400 ++++ powder-42.4/font.h 2010-10-02 08:10:42.000000000 -0400 +@@ -21,5 +21,6 @@ + #ifndef FONT_H_CHECK + #define FONT_H_CHECK + #define FONT_H 10 ++#ifdef INCLUDE_FONTDATA + static char font_data[] = + { +@@ -31,2 +32,3 @@ + { +-#endif +\ No newline at end of file ++#endif ++#endif +diff -urN powder-42.3/graphics.c powder-42.4/graphics.c +--- powder-42.3/graphics.c 2010-09-22 14:05:00.000000000 -0400 ++++ powder-42.4/graphics.c 2010-10-02 08:10:38.000000000 -0400 +@@ -16,6 +16,7 @@ + #include "air.h" + #include "powder.h" + #include "graphics.h" ++#define INCLUDE_FONTDATA + #include "font.h" + #include "misc.h" + +diff -urN powder-42.3/interface.c powder-42.4/interface.c +--- powder-42.3/interface.c 2010-09-22 14:05:00.000000000 -0400 ++++ powder-42.4/interface.c 2010-10-02 08:10:56.000000000 -0400 +@@ -6,10 +6,10 @@ + #include <time.h> + #include "http.h" + #include "md5.h" +-#include "font.h" + #include "defines.h" + #include "powder.h" + #include "interface.h" ++#include "font.h" + #include "misc.h" + + SDLMod sdl_mod; +@@ -2958,4 +2958,4 @@ + if(result) + free(result); + return 1; +-} +\ No newline at end of file ++} +diff -urN powder-42.3/main.c powder-42.4/main.c +--- powder-42.3/main.c 2010-09-22 15:04:00.000000000 -0400 ++++ powder-42.4/main.c 2010-10-02 10:14:46.000000000 -0400 +@@ -38,7 +38,6 @@ + #endif + + #include "misc.h" +-#include "font.h" + #include "defines.h" + #include "powder.h" + #include "graphics.h" +@@ -1302,7 +1301,7 @@ + if(sdl_key=='h') + hud_enable = !hud_enable; + if(sdl_key=='p') +- dump_frame(vid_buf, XRES, YRES, XRES); ++ dump_frame(vid_buf, XRES, YRES, XRES+BARSIZE); + if(sdl_key=='v'&&(sdl_mod & (KMOD_LCTRL|KMOD_RCTRL))) + { + if(clipboard_ready==1) +@@ -1361,7 +1360,7 @@ + if(sdl_key=='v') + vs = !vs; + if(vs) +- dump_frame(vid_buf, XRES, YRES, XRES); ++ dump_frame(vid_buf, XRES, YRES, XRES+BARSIZE); + #endif + + if(sdl_wheel) +diff -urN powder-42.3/misc.c powder-42.4/misc.c +--- powder-42.3/misc.c 2010-09-22 14:05:00.000000000 -0400 ++++ powder-42.4/misc.c 2010-10-02 08:05:12.000000000 -0400 +@@ -280,4 +280,4 @@ + #endif + #endif + return 0; +-} +\ No newline at end of file ++} +diff -urN powder-42.3/misc.h powder-42.4/misc.h +--- powder-42.3/misc.h 2010-09-22 14:05:00.000000000 -0400 ++++ powder-42.4/misc.h 2010-10-02 08:05:47.000000000 -0400 +@@ -69,4 +69,4 @@ + + int cpu_check(void); + +-#endif +\ No newline at end of file ++#endif +diff -urN powder-42.3/powder.c powder-42.4/powder.c +--- powder-42.3/powder.c 2010-09-22 14:05:00.000000000 -0400 ++++ powder-42.4/powder.c 2010-10-02 10:07:00.000000000 -0400 +@@ -21,80 +21,96 @@ + unsigned pmap[YRES][XRES]; + unsigned cb_pmap[YRES][XRES]; + +-int try_move(int i, int x, int y, int nx, int ny) ++static int eval_move(int pt, int nx, int ny, unsigned *rr) + { + unsigned r; + +- + if(nx<0 || ny<0 || nx>=XRES || ny>=YRES) + return 0; +- if(x==nx && y==ny) +- return 1; ++ + r = pmap[ny][nx]; + if(r && (r>>8)<NPART) + r = (r&~0xFF) | parts[r>>8].type; ++ if(rr) ++ *rr = r; ++ ++ if(pt==PT_PHOT&&((r&0xFF)==PT_GLAS||(r&0xFF)==PT_PHOT||(r&0xFF)==PT_CLNE||((r&0xFF)==PT_LCRY&&parts[r>>8].life > 5))) ++ return 2; + +- if(parts[i].type==PT_PHOT&&((r&0xFF)==PT_GLAS||(r&0xFF)==PT_PHOT||(r&0xFF)==PT_CLNE||((r&0xFF)==PT_LCRY&&parts[r>>8].life > 5))) ++ if(pt==PT_STKM) //Stick man's head shouldn't collide + { +- return 1; ++ return 2; + } + +- if((r&0xFF)==PT_VOID) ++ if(bmap[ny/CELL][nx/CELL]==13 && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE) + { +- parts[i].type=PT_NONE; + return 0; + } +- if((r&0xFF)==PT_BHOL) +- { +- parts[i].type=PT_NONE; +- if(!legacy_enable) +- { +- parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f; +- } ++ ++ if(ptypes[pt].falldown!=2 && bmap[ny/CELL][nx/CELL]==3) + return 0; +- } + +- if(parts[i].type==PT_STKM) //Stick man's head shouldn't collide +- { ++ if((pt==PT_NEUT ||pt==PT_PHOT) && bmap[ny/CELL][nx/CELL]==7 && !emap[ny/CELL][nx/CELL]) ++ return 0; ++ ++ if(bmap[ny/CELL][nx/CELL]==9) ++ return 0; ++ ++ if(ptypes[pt].falldown!=1 && bmap[ny/CELL][nx/CELL]==10) ++ return 0; ++ ++ if (r && ((r&0xFF) >= PT_NUM || !can_move[pt][(r&0xFF)])) ++ return 0; ++ ++ return 1; ++} ++ ++int try_move(int i, int x, int y, int nx, int ny) ++{ ++ unsigned r, e; ++ ++ if(x==nx && y==ny) + return 1; +- } ++ ++ e = eval_move(parts[i].type, nx, ny, &r); ++ if(!e) ++ return 0; ++ if(e == 2) ++ return 1; + + if(bmap[ny/CELL][nx/CELL]==12 && !emap[y/CELL][x/CELL]) + { + return 1; + } +- if(bmap[ny/CELL][nx/CELL]==13 && ptypes[parts[i].type].falldown!=0 && parts[i].type!=PT_FIRE && parts[i].type!=PT_SMKE) +- { +- return 0; +- } + if((bmap[y/CELL][x/CELL]==12 && !emap[y/CELL][x/CELL]) && (bmap[ny/CELL][nx/CELL]!=12 && !emap[ny/CELL][nx/CELL])) + { + return 0; + } +- +- if(ptypes[parts[i].type].falldown!=2 && bmap[ny/CELL][nx/CELL]==3) +- return 0; +- if((parts[i].type==PT_NEUT ||parts[i].type==PT_PHOT) && bmap[ny/CELL][nx/CELL]==7 && !emap[ny/CELL][nx/CELL]) +- return 0; + if(r && (r>>8)<NPART && ptypes[r&0xFF].falldown!=2 && bmap[y/CELL][x/CELL]==3) + return 0; + +- if(bmap[ny/CELL][nx/CELL]==9) +- return 0; +- +- if(ptypes[parts[i].type].falldown!=1 && bmap[ny/CELL][nx/CELL]==10) ++ if((r&0xFF)==PT_VOID) ++ { ++ parts[i].type=PT_NONE; + return 0; ++ } + +- if (r && ((r&0xFF) >= PT_NUM || !can_move[parts[i].type][(r&0xFF)])) ++ if((r&0xFF)==PT_BHOL) ++ { ++ parts[i].type=PT_NONE; ++ if(!legacy_enable) ++ { ++ parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f; ++ } + return 0; ++ } + + if(parts[i].type==PT_CNCT && y<ny && (pmap[y+1][x]&0xFF)==PT_CNCT) +- { + return 0; +- } + + pmap[ny][nx] = (i<<8)|parts[i].type; + pmap[y][x] = r; ++ + if(r && (r>>8)<NPART) + { + r >>= 8; +@@ -456,10 +472,147 @@ + return id; + } + ++#define SURF_RANGE 10 ++#define NORMAL_MIN_EST 3 ++#define NORMAL_INTERP 20 ++#define NORMAL_FRAC 16 ++ ++static unsigned direction_to_map(float dx, float dy) ++{ ++ return (dx >= 0) | ++ (((dx + dy) >= 0) << 1) | /* 567 */ ++ ((dy >= 0) << 2) | /* 4+0 */ ++ (((dy - dx) >= 0) << 3) | /* 321 */ ++ ((dx <= 0) << 4) | ++ (((dx + dy) <= 0) << 5) | ++ ((dy <= 0) << 6) | ++ (((dy - dx) <= 0) << 7); ++} ++ ++static int is_blocking(int t, int x, int y) ++{ ++ return eval_move(t, x, y, NULL); ++} ++ ++static int is_boundary(int pt, int x, int y) ++{ ++ if(!is_blocking(pt,x,y)) ++ return 0; ++ if(is_blocking(pt,x,y-1) && is_blocking(pt,x,y+1) && is_blocking(pt,x-1,y) && is_blocking(pt,x+1,y)) ++ return 0; ++ return 1; ++} ++ ++static int find_next_boundary(int pt, int *x, int *y, int dm, int *em) ++{ ++ static int dx[8] = {1,1,0,-1,-1,-1,0,1}; ++ static int dy[8] = {0,1,1,1,0,-1,-1,-1}; ++ static int de[8] = {0x83,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC1}; ++ int i, ii, i0; ++ ++ if(*x <= 0 || *x >= XRES-1 || *y <= 0 || *y >= YRES-1) ++ return 0; ++ ++ if(*em != -1) { ++ i0 = *em; ++ dm &= de[i0]; ++ } else ++ i0 = 0; ++ ++ for(ii=0; ii<8; ii++) { ++ i = (ii + i0) & 7; ++ if((dm & (1 << i)) && is_boundary(pt, *x+dx[i], *y+dy[i])) { ++ *x += dx[i]; ++ *y += dy[i]; ++ *em = i; ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int vec_colinear(float nx, float ny, float vx, float vy) ++{ ++ float d = 1.0f/hypot(vx, vy); ++ d *= nx*vx + ny*vy; ++ return (d >= 0.99) || (d <= -0.99); ++} ++ ++int get_normal(int pt, int x, int y, float dx, float dy, float *nx, float *ny) ++{ ++ int ldm, rdm, lm, rm; ++ int lx, ly, lv, rx, ry, rv; ++ int i, j; ++ float r, ex, ey; ++ ++ if(!dx && !dy) ++ return 0; ++ ++ if(!is_boundary(pt, x, y)) ++ return 0; ++ ++ ldm = direction_to_map(-dy, dx); ++ rdm = direction_to_map(dy, -dx); ++ lx = rx = x; ++ ly = ry = y; ++ lv = rv = 1; ++ lm = rm = -1; ++ ++ j = 0; ++ for(i=0; i<SURF_RANGE; i++) { ++ if(lv) ++ lv = find_next_boundary(pt, &lx, &ly, ldm, &lm); ++ if(rv) ++ rv = find_next_boundary(pt, &rx, &ry, rdm, &rm); ++ j += lv + rv; ++ if(!lv && !rv) ++ break; ++ } ++ ++ if(j < NORMAL_MIN_EST) ++ return 0; ++ ++ if((lx == rx) && (ly == ry)) ++ return 0; ++ ++ ex = rx - lx; ++ ey = ry - ly; ++ r = 1.0f/hypot(ex, ey); ++ *nx = ey * r; ++ *ny = -ex * r; ++ ++ if(vec_colinear(*ny, -*nx, dx, dy)) ++ return 0; ++ ++ return 1; ++} ++ ++int get_normal_interp(int pt, float x0, float y0, float dx, float dy, float *nx, float *ny) ++{ ++ int x, y, i; ++ ++ dx /= NORMAL_FRAC; ++ dy /= NORMAL_FRAC; ++ ++ for(i=0; i<NORMAL_INTERP; i++) { ++ x = (int)(x0 + 0.5f); ++ y = (int)(y0 + 0.5f); ++ if(is_boundary(pt, x, y)) ++ break; ++ x0 += dx; ++ y0 += dy; ++ } ++ if(i >= NORMAL_INTERP) ++ return 0; ++ ++ return get_normal(pt, x, y, dx, dy, nx, ny); ++} ++ + void update_particles_i(pixel *vid, int start, int inc) + { + int i, j, x, y, t, nx, ny, r, a, s, rt, fe, nt, lpv, nearp, pavg; +- float mv, dx, dy, ix, iy, lx, ly, d, pp; ++ float mv, dx, dy, ix, iy, lx, ly, d, pp, nrx, nry, dp; + float pt = R_TEMP; + float c_heat = 0.0f; + int h_count = 0; +@@ -886,7 +1039,7 @@ + r = pmap[y+ny][x+nx]; + if((r>>8)>=NPART || !r) + continue; +- if(((r&0xFF)==PT_METL || (r&0xFF)==PT_ETRD || (r&0xFF)==PT_PSCN || (r&0xFF)==PT_NSCN || (r&0xFF)==PT_NTCT || (r&0xFF)==PT_PTCT || (r&0xFF)==PT_BMTL || (r&0xFF)==PT_RBDM || (r&0xFF)==PT_LRBD || (r&0xFF)==PT_BRMT||(r&0xFF)==PT_NBLE) || (r&0xFF)==PT_INWR && parts[r>>8].ctype!=PT_SPRK ) ++ if(((r&0xFF)==PT_METL || (r&0xFF)==PT_ETRD || (r&0xFF)==PT_PSCN || (r&0xFF)==PT_NSCN || (r&0xFF)==PT_NTCT || (r&0xFF)==PT_PTCT || (r&0xFF)==PT_BMTL || (r&0xFF)==PT_RBDM || (r&0xFF)==PT_LRBD || (r&0xFF)==PT_BRMT||(r&0xFF)==PT_NBLE) || (r&0xFF)==PT_INWR && parts[r>>8].ctype!=PT_SPRK) + { + t = parts[i].type = PT_NONE; + parts[r>>8].ctype = parts[r>>8].type; +@@ -2075,32 +2228,55 @@ + else + { + parts[i].flags |= FLAG_STAGNANT; +- if(nx>x+ISTP) nx=x+ISTP; +- if(nx<x-ISTP) nx=x-ISTP; +- if(ny>y+ISTP) ny=y+ISTP; +- if(ny<y-ISTP) ny=y-ISTP; + if(t==PT_NEUT && 100>(rand()%1000)) + { + kill_part(i); + continue; + } +- else if(try_move(i, x, y, 2*x-nx, ny)) +- { +- parts[i].x = (float)(2*x-nx); +- parts[i].y = (float)iy; +- parts[i].vx *= ptypes[t].collision; +- } +- else if(try_move(i, x, y, nx, 2*y-ny)) +- { +- parts[i].x = (float)ix; +- parts[i].y = (float)(2*y-ny); +- parts[i].vy *= ptypes[t].collision; +- } +- else +- { +- parts[i].vx *= ptypes[t].collision; +- parts[i].vy *= ptypes[t].collision; +- } ++ else if(t==PT_NEUT || t==PT_PHOT) ++ { ++ if(get_normal_interp(t, lx, ly, parts[i].vx, parts[i].vy, &nrx, &nry)) { ++ dp = nrx*parts[i].vx + nry*parts[i].vy; ++ parts[i].vx -= 2.0f*dp*nrx; ++ parts[i].vy -= 2.0f*dp*nry; ++ nx = (int)(parts[i].x + parts[i].vx + 0.5f); ++ ny = (int)(parts[i].y + parts[i].vy + 0.5f); ++ if(try_move(i, x, y, nx, ny)) { ++ parts[i].x = (float)nx; ++ parts[i].y = (float)ny; ++ } else { ++ kill_part(i); ++ continue; ++ } ++ } else { ++ kill_part(i); ++ continue; ++ } ++ } ++ else ++ { ++ if(nx>x+ISTP) nx=x+ISTP; ++ if(nx<x-ISTP) nx=x-ISTP; ++ if(ny>y+ISTP) ny=y+ISTP; ++ if(ny<y-ISTP) ny=y-ISTP; ++ if(try_move(i, x, y, 2*x-nx, ny)) ++ { ++ parts[i].x = (float)(2*x-nx); ++ parts[i].y = (float)iy; ++ parts[i].vx *= ptypes[t].collision; ++ } ++ else if(try_move(i, x, y, nx, 2*y-ny)) ++ { ++ parts[i].x = (float)ix; ++ parts[i].y = (float)(2*y-ny); ++ parts[i].vy *= ptypes[t].collision; ++ } ++ else ++ { ++ parts[i].vx *= ptypes[t].collision; ++ parts[i].vy *= ptypes[t].collision; ++ } ++ } + } + } + if(nx<CELL || nx>=XRES-CELL || ny<CELL || ny>=YRES-CELL) +Binary files powder-42.3/powder.def and powder-42.4/powder.def differ diff --git a/src/powder.c b/src/powder.c index 15a2afe..f5da09c 100644 --- a/src/powder.c +++ b/src/powder.c @@ -22,80 +22,86 @@ int pfree; unsigned pmap[YRES][XRES]; unsigned cb_pmap[YRES][XRES]; -int try_move(int i, int x, int y, int nx, int ny) +static int eval_move(int pt, int nx, int ny, unsigned *rr) { unsigned r; if(nx<0 || ny<0 || nx>=XRES || ny>=YRES) return 0; - if(x==nx && y==ny) - return 1; - r = pmap[ny][nx]; + + r = pmap[ny][nx]; if(r && (r>>8)<NPART) r = (r&~0xFF) | parts[r>>8].type; + if(rr) + *rr = r; - if(parts[i].type==PT_PHOT&&((r&0xFF)==PT_GLAS||(r&0xFF)==PT_PHOT||(r&0xFF)==PT_CLNE||(r&0xFF)==PT_PCLN||((r&0xFF)==PT_LCRY&&parts[r>>8].life > 5))) - { - return 1; - } - - if((r&0xFF)==PT_VOID) - { - parts[i].type=PT_NONE; - return 0; - } - if((r&0xFF)==PT_BHOL) - { - parts[i].type=PT_NONE; - if(!legacy_enable) - { - parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f; - } - return 0; - } + if(pt==PT_PHOT&&((r&0xFF)==PT_GLAS||(r&0xFF)==PT_PHOT||(r&0xFF)==PT_CLNE||((r&0xFF)==PT_LCRY||((r&0xFF)==PT_PCLN&&parts[r>>8].life > 5)))) + return 2; - if(parts[i].type==PT_STKM) //Stick man's head shouldn't collide - { - return 1; - } + if(pt==PT_STKM) //Stick man's head shouldn't collide + { + return 2; + } - if(bmap[ny/CELL][nx/CELL]==12 && !emap[y/CELL][x/CELL]) - { - return 1; - } - if(bmap[ny/CELL][nx/CELL]==13 && ptypes[parts[i].type].falldown!=0 && parts[i].type!=PT_FIRE && parts[i].type!=PT_SMKE) - { + if(bmap[ny/CELL][nx/CELL]==13 && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE) return 0; - } - if((bmap[y/CELL][x/CELL]==12 && !emap[y/CELL][x/CELL]) && (bmap[ny/CELL][nx/CELL]!=12 && !emap[ny/CELL][nx/CELL])) - { + if(ptypes[pt].falldown!=2 && bmap[ny/CELL][nx/CELL]==3) + return 0; + if((pt==PT_NEUT ||pt==PT_PHOT) && bmap[ny/CELL][nx/CELL]==7 && !emap[ny/CELL][nx/CELL]) return 0; - } - if(ptypes[parts[i].type].falldown!=2 && bmap[ny/CELL][nx/CELL]==3) - return 0; - if((parts[i].type==PT_NEUT ||parts[i].type==PT_PHOT) && bmap[ny/CELL][nx/CELL]==7 && !emap[ny/CELL][nx/CELL]) + if(bmap[ny/CELL][nx/CELL]==9) return 0; - if(r && (r>>8)<NPART && ptypes[r&0xFF].falldown!=2 && bmap[y/CELL][x/CELL]==3) + + if(ptypes[pt].falldown!=1 && bmap[ny/CELL][nx/CELL]==10) return 0; - if(bmap[ny/CELL][nx/CELL]==9) + if (r && ((r&0xFF) >= PT_NUM || !can_move[pt][(r&0xFF)])) return 0; - if(ptypes[parts[i].type].falldown!=1 && bmap[ny/CELL][nx/CELL]==10) + return 1; +} +int try_move(int i, int x, int y, int nx, int ny) +{ + unsigned r, e; + + if(x==nx && y==ny) + return 1; + e = eval_move(parts[i].type, nx, ny, &r); + if(!e) + return 0; + if(e == 2) + return 1; + if(bmap[ny/CELL][nx/CELL]==12 && !emap[y/CELL][x/CELL]) + return 1; + if((bmap[y/CELL][x/CELL]==12 && !emap[y/CELL][x/CELL]) && (bmap[ny/CELL][nx/CELL]!=12 && !emap[ny/CELL][nx/CELL])) return 0; - if (r && ((r&0xFF) >= PT_NUM || !can_move[parts[i].type][(r&0xFF)])) + if(r && (r>>8)<NPART && ptypes[r&0xFF].falldown!=2 && bmap[y/CELL][x/CELL]==3) return 0; - if(parts[i].type==PT_CNCT && y<ny && (pmap[y+1][x]&0xFF)==PT_CNCT) + if((r&0xFF)==PT_VOID) { + parts[i].type=PT_NONE; return 0; } + if((r&0xFF)==PT_BHOL) + { + parts[i].type=PT_NONE; + if(!legacy_enable) + { + parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f; + } + + return 0; + } + if(parts[i].type==PT_CNCT && y<ny && (pmap[y+1][x]&0xFF)==PT_CNCT) + return 0; pmap[ny][nx] = (i<<8)|parts[i].type; pmap[y][x] = r; + if(r && (r>>8)<NPART) { r >>= 8; @@ -105,6 +111,142 @@ int try_move(int i, int x, int y, int nx, int ny) return 1; } +#define SURF_RANGE 10 +#define NORMAL_MIN_EST 3 +#define NORMAL_INTERP 20 +#define NORMAL_FRAC 16 + +static unsigned direction_to_map(float dx, float dy) +{ + return (dx >= 0) | + (((dx + dy) >= 0) << 1) | /* 567 */ + ((dy >= 0) << 2) | /* 4+0 */ + (((dy - dx) >= 0) << 3) | /* 321 */ + ((dx <= 0) << 4) | + (((dx + dy) <= 0) << 5) | + ((dy <= 0) << 6) | + (((dy - dx) <= 0) << 7); +} + +static int is_blocking(int t, int x, int y) +{ + return eval_move(t, x, y, NULL); +} + +static int is_boundary(int pt, int x, int y) +{ + if(!is_blocking(pt,x,y)) + return 0; + if(is_blocking(pt,x,y-1) && is_blocking(pt,x,y+1) && is_blocking(pt,x-1,y) && is_blocking(pt,x+1,y)) + return 0; + return 1; +} + +static int find_next_boundary(int pt, int *x, int *y, int dm, int *em) +{ + static int dx[8] = {1,1,0,-1,-1,-1,0,1}; + static int dy[8] = {0,1,1,1,0,-1,-1,-1}; + static int de[8] = {0x83,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC1}; + int i, ii, i0; + + if(*x <= 0 || *x >= XRES-1 || *y <= 0 || *y >= YRES-1) + return 0; + + if(*em != -1) { + i0 = *em; + dm &= de[i0]; + } else + i0 = 0; + + for(ii=0; ii<8; ii++) { + i = (ii + i0) & 7; + if((dm & (1 << i)) && is_boundary(pt, *x+dx[i], *y+dy[i])) { + *x += dx[i]; + *y += dy[i]; + *em = i; + return 1; + } + } + + return 0; +} + +static int vec_colinear(float nx, float ny, float vx, float vy) +{ + float d = 1.0f/hypot(vx, vy); + d *= nx*vx + ny*vy; + return (d >= 0.99) || (d <= -0.99); +} + +int get_normal(int pt, int x, int y, float dx, float dy, float *nx, float *ny) +{ + int ldm, rdm, lm, rm; + int lx, ly, lv, rx, ry, rv; + int i, j; + float r, ex, ey; + + if(!dx && !dy) + return 0; + + if(!is_boundary(pt, x, y)) + return 0; + + ldm = direction_to_map(-dy, dx); + rdm = direction_to_map(dy, -dx); + lx = rx = x; + ly = ry = y; + lv = rv = 1; + lm = rm = -1; + + j = 0; + for(i=0; i<SURF_RANGE; i++) { + if(lv) + lv = find_next_boundary(pt, &lx, &ly, ldm, &lm); + if(rv) + rv = find_next_boundary(pt, &rx, &ry, rdm, &rm); + j += lv + rv; + if(!lv && !rv) + break; + } + + if(j < NORMAL_MIN_EST) + return 0; + + if((lx == rx) && (ly == ry)) + return 0; + + ex = rx - lx; + ey = ry - ly; + r = 1.0f/hypot(ex, ey); + *nx = ey * r; + *ny = -ex * r; + + if(vec_colinear(*ny, -*nx, dx, dy)) + return 0; + + return 1; +} + +int get_normal_interp(int pt, float x0, float y0, float dx, float dy, float *nx, float *ny) +{ + int x, y, i; + + dx /= NORMAL_FRAC; + dy /= NORMAL_FRAC; + + for(i=0; i<NORMAL_INTERP; i++) { + x = (int)(x0 + 0.5f); + y = (int)(y0 + 0.5f); + if(is_boundary(pt, x, y)) + break; + x0 += dx; + y0 += dy; + } + if(i >= NORMAL_INTERP) + return 0; + + return get_normal(pt, x, y, dx, dy, nx, ny); +} void kill_part(int i) { @@ -477,7 +619,7 @@ void update_particles_i(pixel *vid, int start, int inc) uint16_t tempu1, tempu2; int16_t temps1, temps2; float tempf1, tempf2; - float mv, dx, dy, ix, iy, lx, ly, d, pp; + float mv, dx, dy, ix, iy, lx, ly, d, pp, nrx, nry, dp; float pt = R_TEMP; float c_heat = 0.0f; int h_count = 0; @@ -906,7 +1048,8 @@ void update_particles_i(pixel *vid, int start, int inc) r = pmap[y+ny][x+nx]; if((r>>8)>=NPART || !r) continue; - if(((r&0xFF)==PT_METL || (r&0xFF)==PT_ETRD || (r&0xFF)==PT_PSCN || (r&0xFF)==PT_NSCN || (r&0xFF)==PT_NTCT || (r&0xFF)==PT_PTCT || (r&0xFF)==PT_BMTL || (r&0xFF)==PT_RBDM || (r&0xFF)==PT_LRBD || (r&0xFF)==PT_BRMT||(r&0xFF)==PT_NBLE) || (r&0xFF)==PT_INWR && parts[r>>8].ctype!=PT_SPRK ) + if(((r&0xFF)==PT_METL || (r&0xFF)==PT_ETRD || (r&0xFF)==PT_PSCN || (r&0xFF)==PT_NSCN || (r&0xFF)==PT_NTCT || (r&0xFF)==PT_PTCT || (r&0xFF)==PT_BMTL || (r&0xFF)==PT_RBDM || (r&0xFF)==PT_LRBD || (r&0xFF)==PT_BRMT||(r&0xFF)==PT_NBLE) || (r&0xFF)==PT_INWR && parts[r>>8].ctype!=PT_SPRK) + { t = parts[i].type = PT_NONE; parts[r>>8].ctype = parts[r>>8].type; @@ -2381,33 +2524,57 @@ void update_particles_i(pixel *vid, int start, int inc) else { parts[i].flags |= FLAG_STAGNANT; - if(nx>x+ISTP) nx=x+ISTP; - if(nx<x-ISTP) nx=x-ISTP; - if(ny>y+ISTP) ny=y+ISTP; - if(ny<y-ISTP) ny=y-ISTP; if(t==PT_NEUT && 100>(rand()%1000)) { kill_part(i); continue; } - else if(try_move(i, x, y, 2*x-nx, ny)) - { - parts[i].x = (float)(2*x-nx); - parts[i].y = (float)iy; - parts[i].vx *= ptypes[t].collision; - } - else if(try_move(i, x, y, nx, 2*y-ny)) - { - parts[i].x = (float)ix; - parts[i].y = (float)(2*y-ny); - parts[i].vy *= ptypes[t].collision; - } - else - { - parts[i].vx *= ptypes[t].collision; - parts[i].vy *= ptypes[t].collision; - } - } + else if(t==PT_NEUT || t==PT_PHOT) + { + if(get_normal_interp(t, lx, ly, parts[i].vx, parts[i].vy, &nrx, &nry)) { + dp = nrx*parts[i].vx + nry*parts[i].vy; + parts[i].vx -= 2.0f*dp*nrx; + parts[i].vy -= 2.0f*dp*nry; + nx = (int)(parts[i].x + parts[i].vx + 0.5f); + ny = (int)(parts[i].y + parts[i].vy + 0.5f); + if(try_move(i, x, y, nx, ny)) { + parts[i].x = (float)nx; + parts[i].y = (float)ny; + } else { + kill_part(i); + continue; + } + } else { + kill_part(i); + continue; + } + } + + else + { + if(nx>x+ISTP) nx=x+ISTP; + if(nx<x-ISTP) nx=x-ISTP; + if(ny>y+ISTP) ny=y+ISTP; + if(ny<y-ISTP) ny=y-ISTP; + if(try_move(i, x, y, 2*x-nx, ny)) + { + parts[i].x = (float)(2*x-nx); + parts[i].y = (float)iy; + parts[i].vx *= ptypes[t].collision; + } + else if(try_move(i, x, y, nx, 2*y-ny)) + { + parts[i].x = (float)ix; + parts[i].y = (float)(2*y-ny); + parts[i].vy *= ptypes[t].collision; + } + else + { + parts[i].vx *= ptypes[t].collision; + parts[i].vy *= ptypes[t].collision; + } + } + } } if(nx<CELL || nx>=XRES-CELL || ny<CELL || ny>=YRES-CELL) { |
