/* tree1.c (tree.c) - Tree - Don Yang (uguu.org) Preprocess step 1: Remove prototypes and comments 07/23/99 */ #include #include #define PI 3.14159265358979323846264338327950288419716939937510 #define PARTICLE_COUNT 2001 #define PARTICLE_DUST 0 #define PARTICLE_LEAF 1 #define PARTICLE_FRUIT 2 #define PARTICLE_TREE 3 #define COLOR_BRANCH0 0 #define COLOR_BRANCH1 1 #define COLOR_ROOT0 2 #define COLOR_ROOT1 3 #define COLOR_LEAF0 4 #define COLOR_LEAF1 5 #define COLOR_LEAF2 6 #define COLOR_DUST0 7 #define COLOR_DUST1 8 #define SCREEN_RENDER 0 #define SCREEN_ALPHA 1 #define SCREEN_SAVE 2 #define MAX_VELOCITY_X 32 #define MAX_VELOCITY_Y 32 #define X_PRECISION 4 #define Y_PRECISION 8 #define MAX_FADE_IN_TIME 128 #define MOON_PRECISION 3 #define color(n, i) tpal[altcolor][COLOR_##n##i] #define swap(s, a, b) \ iy = particle[a].s; \ particle[a].s = particle[b].s; \ particle[b].s = iy; int far *screen = (int far *)(23L << 27); volatile long far *clock = (long far *)1132L; long tick; long rseed; int altcolor; int page[3][2048]; int row[25]; int tpal[2][9] = { {0x7600, 0xf600, 0x7800, 0xf700, 0x2700, 0xaf00, 0xac00, 0x0300, 0x0100}, {0x7800, 0xf700, 0x7300, 0xfb00, 0x1700, 0x9f00, 0x9d00, 0x0300, 0x0200} }; int pcount; int dcount; int mpal[5] = {0, 8, 7, 11, 15}; int moon[5][10]; int moonage; int moonpos; int Extra[3] = {'D', 'O', 'N'}; int spal[6][2] = { {0x0fdf, 0x0000}, {0x78dc, 0x0000}, {0x78df, 0x0000}, {0x0fdc, 0x0000}, {0x07dc, 0x08df}, {0x08dc, 0x07df} }; int ix, iy, iz, sx, sy, sz, rx, bx[4], by[4]; double fx, fy, tx, ty; struct _particle { int ptype; int cx, cy, dx, dy, rx, ry; int color; } particle[PARTICLE_COUNT]; int rnd(void) { rseed = rseed * 0x343fdL + 0x269ec3L; return (int)(rseed >> 16) & 0x7fff; } void Blit(void) { while( tick == *clock ); tick = *clock; for(ix = 0; ix < 2000;) screen[ix++] = page[SCREEN_RENDER][ix]; } void AddCut(void) { if( rx++ & 1 ) { sx = 16 * 6 + rnd() % (7 * 6); sy = 14 * 6 - rnd() % (7 * 6); } else { sx = 14 * 6 - rnd() % (7 * 6); sy = 16 * 6 + rnd() % (7 * 6); } for(ix = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = -1; Blit(); iz = rnd() & 1; for(sz = iz ? 0 : 7; sz < 8 && sz >= 0; sz += iz ? 1 : -1) { for(ix = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = 0; for(ix = (sz < 4 ? 0 : sz * 20 - 80); ix < (sz < 4 ? sz * 20 + 20 : 80); ix++) { iy = (ix * (sy - sx)) / 80 + sx; page[SCREEN_RENDER][row[iy / 6] + ix] = spal[iy % 6][0]; page[SCREEN_RENDER][row[iy / 6 + 1] + ix] = spal[iy % 6][1]; } Blit(); } bx[ix = rx - 1] = rnd() % 16 + 8; by[ix] = rnd() % 16 + 8; if( !(rx & 1) ) bx[ix] = -bx[ix]; sx /= 6; sy /= 6; for(ix = 0; ix < 80; ix++) { for(iy = (ix * (sy - sx)) / 80 + sx; iy >= 0;) page[SCREEN_ALPHA][row[iy--] + ix] = rx; } } void ClearKey(void) { if( !getch() ) getch(); } void ClearScreen(void) { for(ix = 0; ix < 2000;) page[SCREEN_SAVE][ix++] = screen[ix]; for(ix = pcount = 0; ix < 2000; ix++) { if( (screen[ix] & 255) != 32 || (screen[ix] & 0xf000) ) { particle[pcount].cx = ix % 80; particle[pcount].cy = ix / 80; particle[pcount].color = screen[ix]; particle[pcount++].rx = rnd() % 64 + 1; } } for(dcount = pcount; dcount && !kbhit();) { for(ix = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = 0; for(ix = pcount - 1; ix >= 0; ix--) { if( particle[ix].rx ) { page[SCREEN_RENDER][row[particle[ix].cy] + particle[ix].cx] = particle[ix].color; if( !(--particle[ix].rx) ) { particle[ix].dx = rnd() % 4 + 6; particle[ix].dy = rnd() % 4; } } else { if( particle[ix].cy >= 0 && particle[ix].cy < 25 && particle[ix].cx >= 0 && particle[ix].cx < 80 ) { page[SCREEN_RENDER][row[particle[ix].cy] + particle[ix].cx] = particle[ix].color; } else { if( particle[ix].dx ) { dcount--; particle[ix].dx = particle[ix].dy = 0; } } particle[ix].cx -= particle[ix].dx; particle[ix].cy += particle[ix].dy; } } Blit(); } if( kbhit() ) ClearKey(); } void DrawPoint(int x, int y, int t, int c) { if( y >= 0 && y < 25 && x >= 0 && x < 80 ) { if( page[SCREEN_ALPHA][row[y] + x] ) return; page[SCREEN_ALPHA][row[y] + x] = 1; particle[pcount].cx = x; particle[pcount].cy = y; particle[pcount].ptype = t; particle[pcount++].color = c; } } void DrawLine(int x, int y, int i, int j, int t, int c) { fx = (i - x) / 64.0; fy = (j - y) / 64.0; for(iz = 0; iz <= 64; iz++) DrawPoint((int)(iz * fx) + x, (int)(iz * fy) + y, t, c); } void GenerateElm1(void) { ix = sx = rnd() % 18 + 30; sy = rnd() % 4 + 11; rx = sx + 8; for(iy = sy; iy < 25; iy++) { DrawLine(rx - (rx - ix) / 3, iy, rx, iy, PARTICLE_TREE, color(BRANCH, 0)); DrawLine(ix, iy, rx, iy, PARTICLE_TREE, color(BRANCH, 1)); if( (sz = rnd()) & 3 ) { if( sz & 4 ) { ix--; if( sz & 8 ) rx--; } else { rx++; if( sz & 8 ) ix++; } if( rx - ix < 4 ) sz = (sz & 1) ? ix-- : rx++; if( rx - ix > 15 ) sz = (sz & 1) ? ix++ : rx--; } if( iy > 20 && iy < 24 ) { if( rnd() & 1 ) break; } } for(; iy < 25; iy++) { for(sz = ix; sz <= rx;) { DrawPoint(sz++, iy, PARTICLE_TREE, rnd() & 3 ? color(ROOT, 1) : color(ROOT, 0)); } ix -= rnd() % 7 + 6; rx += rnd() % 7 + 6; } for(sz = 0; sz < 4; sz++) { rx = sz * 8 + rnd() % 5 + 2; bx[sz] = (int)(sx + 25 * cos((PI * rx) / 32) + sz * 2); by[sz] = (int)(sy - 10 * sin((PI * rx) / 32) + 2); for(rx = 0; rx < 4; rx++) { ix = rnd() % 3 - 1 + (sx + bx[sz]) / 2 + sz; iy = rnd() % 3 - 1 + (sy + by[sz]) / 2; DrawLine(rnd() % 3 - 1 + bx[sz], rnd() % 3 - 1 + by[sz], ix, iy, PARTICLE_TREE, rx - 1 ? color(BRANCH, 1) : color(BRANCH, 0)); DrawLine(sx + sz * 2, sy, ix, iy, PARTICLE_TREE, rx - 1 ? color(BRANCH, 1) : color(BRANCH, 0)); } } for(sx = 0; sx < 4; sx++) { for(sy = 0; sy++ < 40;) { if( rnd() & 1 ) { fx = (5 - sy) * PI / 64; DrawPoint(bx[sx] + (int)(14 * cos(fx)), by[sx] - (int)(7 * sin(fx)), PARTICLE_LEAF, color(LEAF, 0)); } } } for(sx = 0; sx < 4; sx++) { for(sy = 0; sy++ < 512;) { fx = sy * PI / 256; fy = (rnd() & 0xfff) / 300; rx = rnd() & 7; DrawPoint(bx[sx] + (int)(fy * cos(fx)), by[sx] + (int)(fy * sin(fx) * .4), rx ? PARTICLE_LEAF : PARTICLE_FRUIT, rx ? color(LEAF, 1) : color(LEAF, 2)); } } } void GenerateElm2(void) { ix = sx = rnd() % 14 + 31; sy = rnd() % 6 + 12; rx = sx + 7; for(iy = sy; iy < 25; iy++) { DrawLine(rx - (rx - ix) / 3, iy, rx, iy, PARTICLE_TREE, color(BRANCH, 0)); DrawLine(ix, iy, rx, iy, PARTICLE_TREE, color(BRANCH, 1)); if( (sz = rnd()) & 3 ) { if( sz & 4 ) { ix--; if( sz & 8 ) rx--; } else { rx++; if( sz & 8 ) ix++; } if( rx - ix < 4 ) sz = (sz & 1) ? ix-- : rx++; if( rx - ix > 15 ) sz = (sz & 1) ? ix++ : rx--; } if( iy > 20 && iy < 24 ) { if( rnd() & 1 ) break; } } for(; iy < 25; iy++) { for(sz = ix; sz <= rx;) { DrawPoint(sz++, iy, PARTICLE_TREE, rnd() & 3 ? color(ROOT, 1) : color(ROOT, 0)); } ix -= rnd() % 7 + 6; rx += rnd() % 7 + 6; } for(ix = 0; ix < 4;) { rx = ix * 8 + rnd() % 5 + 2; bx[ix] = (int)(sx + 25 * cos((PI * rx) / 32) + ix * 2); by[ix++] = (int)(sy - 10 * sin((PI * rx) / 32) + 2); } for(ix = 0; ix < 4; ix++) { for(iy = 0; iy++ < 32;) { fx = PI * (rnd() % 256) / 128; iz = rnd() % 8; DrawPoint((int)(iz * cos(fx)) + bx[ix] + ix * 2 + rnd() % 2, (int)(iz * sin(fx) / 2) + by[ix], PARTICLE_LEAF, color(LEAF, 1)); } } for(ix = 0; ix < 4; ix++) { DrawLine(bx[ix], by[ix], sx + ix * 2, sy, PARTICLE_TREE, iy ? color(BRANCH, 1) : color(BRANCH, 0)); for(iy = 0; iy++ < 3;) { fx = PI * (rnd() % 256) / 128; iz = rnd() % 4 + 6; DrawLine((int)(iz * cos(fx)) + bx[ix], (int)(iz * sin(fx) / 2) + by[ix], sx + ix * 2, sy, PARTICLE_TREE, color(BRANCH, 1)); } } for(ix = 0; ix < 4; ix++) { for(iy = 0; iy++ < 40;) { if( rnd() & 1 ) { fx = (5 - iy) * PI / 64; DrawPoint(bx[ix] + (int)(14 * cos(fx)), by[ix] - (int)(7 * sin(fx)), PARTICLE_LEAF, color(LEAF, 0)); } } } for(ix = 0; ix < 4; ix++) { for(iy = 0; iy++ < 512;) { fx = iy * PI / 256; fy = (rnd() & 0xfff) / 300; DrawPoint(bx[ix] + (int)(fy * cos(fx)), by[ix] + (int)(fy * sin(fx) / 2), PARTICLE_LEAF, color(LEAF, 1)); } } } void GeneratePine1(void) { sx = (rnd() % 16) + 32; sy = (rnd() % 2) + 4; sz = (rnd() % 16) + 32; for(ix = 5; ix > 2; ix--) DrawLine(sx + (ix / 3), sy, sz + ix, 24, PARTICLE_TREE, color(BRANCH, 0)); for(; ix > -5; ix--) DrawLine(sx + (ix / 3), sy, sz + ix, 24, PARTICLE_TREE, color(BRANCH, 1)); for(iy = 0; iy < 21; iy++) { ix = 3 * (iy < 10 ? iy : iy - 6) + 1; if( rnd() & 1 ) { DrawPoint(sx + (iy * (sz - sx)) / (24 - sy) + ix / 2 - rnd() % ix, iy, PARTICLE_FRUIT, color(LEAF, 2)); } for(iz = 0; iz++ < ix;) DrawPoint((rx = sx + (iy * (sz - sx)) / (24 - sy) + ix / 2) - rnd() % ix - 1, iy, PARTICLE_LEAF, color(LEAF, 1)); for(; ix > -1; ix--) { if( rnd() & 3 ) DrawPoint(rx - ix, iy, PARTICLE_LEAF, color(LEAF, 0)); } } } void GeneratePine2(void) { if( !(sz = rnd() & 1) ) { bx[0] = rnd() % 10 + 35; by[0] = rnd() % 4 + 9; bx[2] = rnd() % 10 + 35; sx = 16; sy = 11; } else { bx[0] = rnd() % 8 + 16; by[0] = rnd() % 4 + 10; bx[1] = rnd() % 8 + 46; by[1] = rnd() % 4 + 10; bx[2] = rnd() % 8 + 16; bx[3] = rnd() % 8 + 46; sx = 10; sy = 10; } for(; sz >= 0; sz--) { for(ix = 4; ix > 2; ix--) DrawLine(bx[sz] + (ix / 3), by[sz], bx[sz + 2] + ix, 24, PARTICLE_TREE, color(BRANCH, 0)); for(; ix > -4; ix--) DrawLine(bx[sz] + (ix / 3), by[sz], bx[sz + 2] + ix, 24, PARTICLE_TREE, color(BRANCH, 1)); fx = atan2(24 - by[sz], bx[sz] - bx[sz + 2]); fy = sin(fx); fx = cos(fx); for(iz = 0; iz < 256; iz++) { if( rnd() & 1 ) continue; tx = sx * sin(iz * PI / 128); ty = ((iz < 192 && iz > 64) ? 3 * sy : sy) * cos(iz * PI / 128); ix = (int)(tx * fy - ty * fx) + (bx[sz] + bx[sz + 2]) / 2; iy = ((int)(tx * fx + ty * fy) + by[sz] + 24) / 2; DrawPoint(ix, iy, PARTICLE_LEAF, (iz > 96 && iz < 224) ? color(LEAF, 1) : color(LEAF, 0)); } for(iz = 0; iz < 256; iz++) { tx = sx * sin(iz * PI / 128); ty = ((iz < 192 && iz > 64) ? 3 * sy : sy) * cos(iz * PI / 128); ix = (int)(tx * fy - ty * fx) + (bx[sz] + bx[sz + 2]) / 2; iy = ((int)(tx * fx + ty * fy) + by[sz] + 24) / 2; for(rx = 0; rx++ < 8;) { tx = (rnd() % 32) / 32.0; if( rnd() & 7 ) { DrawPoint(ix - (int)(tx * (ix - (bx[sz] + bx[sz + 2]) / 2)), iy - (int)(tx * (iy - (by[sz] + 24) / 2)), PARTICLE_LEAF, rnd() % 4 ? color(LEAF, 1) : color(LEAF, 0)); } else { DrawPoint(ix - (int)(tx * (ix - (bx[sz] + bx[sz + 2]) / 2)), iy - (int)(tx * (iy - (by[sz] + 24) / 2)), PARTICLE_FRUIT, color(LEAF, 2)); } } } } } void InitMoon(void) { if( !moonage ) { for(iz = 0; iz < 400;) page[SCREEN_ALPHA][iz++] = 0; } else if( moonage == 15 ) { for(iy = iz = 0; iy < 20; iy++) { for(ix = -10; ix < 10; ix++) { page[SCREEN_ALPHA][iz++] = ((ix + 0.5) * (ix + 0.5) + (iy - 9.5) * (iy - 9.5)) <= 90.25 ? 1 : 0; } } } else { for(ix = 0; ix < 400;) page[SCREEN_ALPHA][ix++] = 0; if( moonage < 15 ) { fx = (15 - moonage) / 7.5 - 1; fy = 1; } else { fx = -1; fy = (30 - moonage) / 7.5 - 1; } for(iy = 0; iy < 20; iy++) { sx = (int)(fx * sqrt(90.25 - (iy - 9.5) * (iy - 9.5))) + 10; rx = (int)(fy * sqrt(90.25 - (iy - 9.5) * (iy - 9.5))) + 10; for(ix = sx; ix <= rx; ix++) page[SCREEN_ALPHA][iy * 20 + ix] = 1; } } for(iy = 0; iy < 5; iy++) { for(ix = 0; ix < 10; ix++) { iz = iy * 80 + ix * 2; sx = page[SCREEN_ALPHA][iz] + page[SCREEN_ALPHA][iz + 1] + page[SCREEN_ALPHA][iz + 20] + page[SCREEN_ALPHA][iz + 21]; rx = page[SCREEN_ALPHA][iz + 40] + page[SCREEN_ALPHA][iz + 41] + page[SCREEN_ALPHA][iz + 60] + page[SCREEN_ALPHA][iz + 61]; moon[iy][ix] = !(sx + rx) ? 0 : ((sx > rx) ? ((mpal[sx] << 12) | (mpal[rx] << 8) | 220) : ((mpal[rx] << 12) | (mpal[sx] << 8) | 223)); } } moonpos = -12 << MOON_PRECISION; } void InitTree(void) { for(ix = pcount = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = (page[SCREEN_ALPHA][ix] = 0) - 1; Blit(); if( (ix = rnd()) & 3 ) { if( ix & 4 ) GenerateElm1(); else GenerateElm2(); } else { if( ix & 4 ) GeneratePine1(); else GeneratePine2(); } } void InitParticles(void) { for(iz = 1024; iz > 0; iz /= 2) { do { for(ix = iy = 0; ix < pcount - iz; ix++) { if( (row[particle[ix].cy] + particle[ix].cx) > (row[particle[ix + iz].cy] + particle[ix + iz].cx) ) { swap(ptype, ix, ix + iz); swap(cx, ix, ix + iz); swap(cy, ix, ix + iz); swap(color, ix, ix + iz); } } } while( iy ); } for(ix = iy = iz = 0; ix < pcount; ix++) { for(; iy < 2000 && (page[SCREEN_SAVE][iy] & 255) == 32; iy++); particle[ix].color |= (iy == 2000) ? Extra[rnd() % 3] : (page[SCREEN_SAVE][iy++] & 255); particle[ix].rx = rnd() % MAX_FADE_IN_TIME + 1; particle[ix].ry = rnd() % MAX_FADE_IN_TIME + MAX_FADE_IN_TIME; } for(; !iz || (ix - pcount < 16); ix++) { for(; iy < 2000 && (page[SCREEN_SAVE][iy] & 255) == 32; iy++); particle[ix].cy = particle[ix].ptype = 0; particle[ix].color = (rnd() & 1 ? color(DUST, 0) : color(DUST, 1)) | ((iy == 2000) ? iz = Extra[rnd() % 3] : (page[SCREEN_SAVE][iy++] & 255)); particle[ix].rx = -1999; } dcount = ix - pcount; pcount = ix; for(iz = dcount / 2; iz; iz--) { for(ix = pcount - 1; ix > 0; ix--) { swap(ptype, ix, ix - 1); swap(cx, ix, ix - 1); swap(cy, ix, ix - 1); swap(rx, ix, ix - 1); swap(ry, ix, ix - 1); swap(color, ix, ix - 1); } } for(ix = 0; ix < pcount;) particle[ix++].dx = row[particle[ix].cy] + particle[ix].cx; } void MoonAge(void) { int ages[] = {18, 0, 11, 22, 3, 14, 25, 6, 17, 28, 9, 20, 1, 12, 23, 4, 15, 26, 7}, offsets[] = {-1, 1, 0, 1, 2, 3, 4, 5, 7, 7, 9, 9}; if( iy == 31 ) iy = 1; moonage = (ages[(iz + 1) % 19] + iy + offsets[ix - 1]) % 30; } void RegenerateDust(void) { for(ix = 0; ix < pcount; ix++) { if( particle[ix].rx < 0 || particle[ix].ry > (25 << Y_PRECISION) ) { particle[ix].dx = (rnd() % MAX_VELOCITY_X) + 4; particle[ix].dy = (rnd() % MAX_VELOCITY_Y) + 8; if( rnd() & 1 ) { particle[ix].rx = rnd() % (80 << X_PRECISION); particle[ix].ry = -2 << Y_PRECISION; } else { particle[ix].rx = 81 << X_PRECISION; particle[ix].ry = rnd() % (25 << Y_PRECISION); } } } } void RenderDust(void) { particle[ix].cx = particle[ix].rx >> X_PRECISION; particle[ix].cy = particle[ix].ry >> Y_PRECISION; if( particle[ix].cy >= 0 && particle[ix].cy < 25 && particle[ix].cx >= 0 && particle[ix].cx < 80 ) { sx = row[particle[ix].cy] + particle[ix].cx; page[SCREEN_RENDER][sx] = ( (page[SCREEN_RENDER][sx] & 0x0fff) && (page[SCREEN_RENDER][sx] & 0xf000) ) ? (page[SCREEN_RENDER][sx] & 0xf000) | 0x800 | particle[ix].color : particle[ix].color; } particle[ix].rx -= particle[ix].dx; particle[ix].ry += particle[ix].dy; } void RenderFruit(void) { if( particle[ix].rx ) { if( particle[ix].ry ) { particle[ix].ry--; page[SCREEN_RENDER][particle[ix].dx] = (particle[ix].color & 255) | ((rnd() % MAX_FADE_IN_TIME > particle[ix].ry) ? 0xf700 : 0xff00); } else { particle[ix].rx--; page[SCREEN_RENDER][particle[ix].dx] = (rnd() % MAX_FADE_IN_TIME > particle[ix].rx) ? ((rnd() & 3) ? particle[ix].color : particle[ix].color ^ 0x100) : ((particle[ix].color & 255) | 0xf700); } } else { page[SCREEN_RENDER][particle[ix].dx] = rnd() & 3 ? particle[ix].color : particle[ix].color ^ 0x100; } } void RenderLeaf(void) { if( particle[ix].rx ) { if( particle[ix].ry ) { particle[ix].ry--; page[SCREEN_RENDER][particle[ix].dx] = (particle[ix].color & 255) | ((rnd() % MAX_FADE_IN_TIME > particle[ix].ry) ? 0xf700 : 0xff00); } else { particle[ix].rx--; page[SCREEN_RENDER][particle[ix].dx] = (rnd() % MAX_FADE_IN_TIME > particle[ix].rx) ? ((rnd() & 7) ? particle[ix].color : particle[ix].color ^ 0x800) : ((particle[ix].color & 255) | 0xf700); } } else { page[SCREEN_RENDER][particle[ix].dx] = (rnd() & 7) ? particle[ix].color : particle[ix].color ^ 0x800; } } void RenderMoon(void) { iz = moonpos >> MOON_PRECISION; for(ix = 0; ix < 10; ix++) { if( iz + ix >= 0 && iz + ix < 80 ) { for(iy = 0; iy < 5; iy++) page[SCREEN_RENDER][row[iy + 2] + ix + iz] = moon[iy][ix]; } } if( moonpos++ > (82 << MOON_PRECISION) ) moonpos = -12 << MOON_PRECISION; } void RenderTree(void) { if( particle[ix].rx ) { if( particle[ix].ry ) { particle[ix].ry--; page[SCREEN_RENDER][particle[ix].dx] = (particle[ix].color & 255) | ((rnd() % MAX_FADE_IN_TIME > particle[ix].ry) ? 0xf700 : 0xff00); } else { particle[ix].rx--; page[SCREEN_RENDER][particle[ix].dx] = (rnd() % MAX_FADE_IN_TIME > particle[ix].rx) ? particle[ix].color : ((particle[ix].color & 255) | 0xf700); } } else { page[SCREEN_RENDER][particle[ix].dx] = particle[ix].color; } } void Render(void) { for(ix = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = 0; RenderMoon(); for(ix = 0; ix < pcount; ix++) { if( particle[ix].ptype & 1 ) { if( particle[ix].ptype & 2 ) RenderTree(); else RenderLeaf(); } else { if( particle[ix].ptype & 2 ) RenderFruit(); else RenderDust(); } } Blit(); } void DestroyTree(void) { ClearKey(); for(ix = rx = 0; ix < 2000;) page[SCREEN_ALPHA][ix++] = 0; for(ix = 0; ix < pcount; ix++) { if( particle[ix].ptype ) { particle[ix].rx = particle[ix].ry = 0; particle[ix].color = ( particle[ix].ptype == PARTICLE_TREE ? ((particle[ix].color & 0x8000) ? 0xf700 : 0x7f00) : ((particle[ix].color & 0x8000) ? 0x7800 : 0x8700) ) | (particle[ix].color & 255); } } if( rnd() & 1 ) { rx++; tx = 1; } else { tx = 0; } AddCut(); for(dcount = 1; dcount;) { if( kbhit() ) { if( rx < 3 + (int)tx ) { ClearKey(); AddCut(); } else { break; } } else { Render(); } for(ix = dcount = 0; ix < pcount; ix++) { if( !particle[ix].ptype ) { if( particle[ix].rx >= 0 && particle[ix].ry < (25 << Y_PRECISION) ) dcount++; else particle[ix].dx = particle[ix].dy = 0; } } } for(ix = 0; ix < 2000;) { particle[ix].rx = particle[ix].cx << X_PRECISION; particle[ix++].ry = particle[ix].cy << Y_PRECISION; } for(ix = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = -1; Blit(); for(iz = 1; iz;) { for(ix = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = 0; RenderMoon(); for(ix = iz = 0; ix < pcount; ix++) { if( particle[ix].ptype ) { particle[ix].cx = particle[ix].rx >> X_PRECISION; particle[ix].cy = particle[ix].ry >> Y_PRECISION; if( particle[ix].cy >= 0 && particle[ix].cy < 25 && particle[ix].cx >= 0 && particle[ix].cx < 80 ) { iz++; page[SCREEN_RENDER][row[particle[ix].cy] + particle[ix].cx] = particle[ix].color; if( !(iy = page[SCREEN_ALPHA][particle[ix].dx]) ) { particle[ix].ry += 1 << (Y_PRECISION - 2); } else { particle[ix].rx += bx[--iy]; particle[ix].ry += by[iy]; } } } } Blit(); if( kbhit() ) { ClearKey(); break; } } if( tx > 0 ) rx--; } void RestoreScreen(void) { for(ix = pcount = 0; ix < 2000; ix++) { if( (page[SCREEN_SAVE][ix] & 255) != 32 || (page[SCREEN_SAVE][ix] & 0xf000) ) { particle[pcount].rx = rnd() % 4 + 2; particle[pcount].ry = rnd() % 6 + 2; particle[pcount].dx = rnd() % 32 + 20; particle[pcount].dy = rnd() % 8; particle[pcount].cx = (ix % 80) << particle[pcount].rx; particle[pcount].cy = (ix / 80) << particle[pcount].ry; particle[pcount++].color = page[SCREEN_SAVE][ix]; } } for(dcount = 1; dcount && !kbhit();) { for(ix = dcount = 0; ix < 2000;) page[SCREEN_RENDER][ix++] = 0; for(iz = pcount - 1; iz >= 0; iz--) { if( particle[iz].dx ) { dcount++; ix = (particle[iz].cx + (iy = particle[iz].dx * particle[iz].dx)) >> particle[iz].rx; iy = (particle[iz].cy - (particle[iz].dy ? iy : 0)) >> particle[iz].ry; if( iy >= 0 && iy < 25 && ix >=0 && ix < 80 ) page[SCREEN_RENDER][row[iy] + ix] = particle[iz].color; if( !(--particle[iz].dx) ) { particle[iz].dy = row[particle[iz].cy >> particle[iz].ry] + (particle[iz].cx >> particle[iz].rx); } } else { page[SCREEN_RENDER][particle[iz].dy] = particle[iz].color; } } Blit(); } if( kbhit() ) ClearKey(); for(ix = 0; ix < 2000;) screen[ix++] = page[SCREEN_SAVE][ix]; } void cdecl main(void) { rseed = *clock; iy = -80; for(ix = 0; ix < 25;) row[ix++] = iy += 80; _asm { mov ax, 1003h xor bx, bx int 10h mov ah, 2ah int 21h mov iz, cx mov iy, dx } ix = iy >> 8; iy &= 255; MoonAge(); altcolor = (moonage - 15 >= -1 && moonage - 15 <= 1) ? 1 : 0; InitMoon(); ClearScreen(); do { InitTree(); InitParticles(); while( !kbhit() ) { Render(); RegenerateDust(); } DestroyTree(); } while( rx <= 1 ); RestoreScreen(); _asm { mov ax, 1003h mov bx, 1 int 10h } }