summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix Wallin <nibbler.v1@gmail.com>2010-10-02 15:59:24 (GMT)
committer Felix Wallin <nibbler.v1@gmail.com>2010-10-02 15:59:24 (GMT)
commit6e81c2a88cc9a2bda3189b01b4edd5da1a0bd0a8 (patch)
treeb7b54fb71ec0919079e0b949bc1ba8bd090c6470 /src
parent0a9d6adca47eae3b2c06c958a69352adeda4daca (diff)
downloadpowder-6e81c2a88cc9a2bda3189b01b4edd5da1a0bd0a8.zip
powder-6e81c2a88cc9a2bda3189b01b4edd5da1a0bd0a8.tar.gz
Added reflection, thanks to Skylark
Diffstat (limited to 'src')
-rw-r--r--src/graphics.c1
-rwxr-xr-xsrc/main.c4
-rw-r--r--src/powder-reflection.diff510
-rw-r--r--src/powder.c305
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>
diff --git a/src/main.c b/src/main.c
index 8c7035b..d88b972 100755
--- a/src/main.c
+++ b/src/main.c
@@ -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)
{