windows-nt/Source/XPSP1/NT/shell/osshell/ep/idlewild/life/life.c
2020-09-26 16:20:57 +08:00

424 lines
6.9 KiB
C

#ifdef PM
#define INCL_WIN
#define INCL_GPI
#include <os2.h>
INT _acrtused = 0;
#endif
#ifdef WIN
#include <windows.h>
#include <port1632.h>
#endif
#include "std.h"
#include "scrsave.h"
#ifdef WIN
LONG mppenrgb [] =
{
RGB(0x00, 0x00, 0x00),
RGB(0x00, 0x00, 0x80),
RGB(0x00, 0x80, 0x00),
RGB(0x00, 0x80, 0x80),
RGB(0x80, 0x00, 0x00),
RGB(0x80, 0x00, 0x80),
RGB(0x80, 0x80, 0x00),
RGB(0x80, 0x80, 0x80),
RGB(0xc0, 0xc0, 0xc0),
RGB(0x00, 0x00, 0xff),
RGB(0x00, 0xff, 0x00),
RGB(0x00, 0xff, 0xff),
RGB(0xff, 0x00, 0x00),
RGB(0xff, 0x00, 0xff),
RGB(0xff, 0xff, 0x00),
RGB(0xff, 0xff, 0xff)
};
#define CLR_BLACK 0
#define CLR_BACKGROUND 0
#endif
#define MultDiv(a, b, c) ((int) (((long) (a) * (long) (b)) / (c)))
INT dxScreen, dyScreen;
#define dxcMax 80
#define dycMax 50
typedef UCHAR GRID [dxcMax][dycMax];
GRID gridOld, gridNew;
BOOL fRedraw;
INT csecRandomize;
VOID SetCell(CVS hps, GRID grid, INT dxc, INT dyc, INT clr);
VOID Redraw(CVS hps);
Randomize();
Animate(CVS hps);
ClrAverage(GRID grid, INT dxc, INT dyc);
BOOL EXPENTRY ScrSaveProc(INT ssm, LPVOID l1, LONG_PTR l2, LONG_PTR l3)
{
CHAR FAR * lpsz;
CHAR FAR * lpch;
switch (ssm)
{
default:
return FALSE;
case SSM_OPEN:
lpsz = (PSZ) l1;
lpch = "Life";
while ((*lpsz++ = *lpch++) != '\0')
;
lpsz = (PSZ) l2;
lpch = "Life in Color\n\nby Brad Christian";
while ((*lpsz++ = *lpch++) != '\0')
;
#ifdef PM
dxScreen = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
dyScreen = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
#endif
#ifdef WIN
dxScreen = GetSystemMetrics(SM_CXSCREEN);
dyScreen = GetSystemMetrics(SM_CYSCREEN);
#endif
// FALL THROUGH
case SSM_SECOND:
if (--csecRandomize < 0)
{
Randomize();
csecRandomize = 60 + WRand(120);
}
break;
case SSM_BLANK:
Randomize();
fRedraw = TRUE;
break;
case SSM_ANIMATE:
{
static INT foo;
if (foo++ & 1)
return TRUE;
}
if (GetInputState())
return TRUE;
if (fRedraw)
{
Redraw((CVS) l1);
if (fRedraw)
return TRUE;
}
Animate((CVS) l1);
break;
}
return TRUE;
}
Randomize()
{
INT dxc, dyc;
for (dyc = 0; dyc < dycMax; dyc += 1)
{
for (dxc = 0; dxc < dxcMax; dxc += 1)
{
gridOld[dxc][dyc] = CLR_BACKGROUND << 4;
}
}
for (dyc = 0; dyc < dycMax; dyc += 1)
{
for (dxc = 0; dxc < dxcMax; dxc += 1)
{
if (WRand(10) < 5)
SetCell(NULL, gridOld, dxc, dyc, WRand(16));
}
}
fRedraw = TRUE;
}
VOID Redraw(CVS hps)
{
INT dxc, dyc;
for (dyc = 0; dyc < dycMax; dyc += 1)
{
if (GetInputState())
return;
for (dxc = 0; dxc < dxcMax; dxc += 1)
{
#ifdef PM
RECTL rectl;
LONG clr;
rectl.xLeft = MultDiv(dxc, dxScreen, dxcMax);
rectl.xRight = MultDiv(dxc + 1, dxScreen, dxcMax);
rectl.yBottom = MultDiv(dyc, dyScreen, dycMax);
rectl.yTop = MultDiv(dyc + 1, dyScreen, dycMax);
if ((clr = gridOld[dxc][dyc] >> 4) == CLR_BACKGROUND)
clr = CLR_BLACK;
WinFillRect(hps, &rectl, clr);
#endif
#ifdef WIN
HANDLE hT;
LOGBRUSH lbrush;
INT clr, x, y;
if ((clr = gridOld[dxc][dyc] >> 4) == CLR_BACKGROUND)
clr = CLR_BLACK;
lbrush.lbStyle = BS_SOLID;
lbrush.lbColor = mppenrgb[clr];
lbrush.lbHatch = 0;
hT = SelectObject(hps,
CreateBrushIndirect(&lbrush));
x = MultDiv(dxc, dxScreen, dxcMax);
y = MultDiv(dyc, dyScreen, dycMax);
PatBlt(hps, x, y,
MultDiv(dxc + 1, dxScreen, dxcMax) - x,
MultDiv(dyc + 1, dyScreen, dycMax) - y,
PATCOPY);
DeleteObject(SelectObject(hps, hT));
#endif
}
}
fRedraw = FALSE;
}
Animate(CVS hps)
{
INT dxc, dyc;
INT c;
for (dyc = 0; dyc < dycMax; dyc += 1)
{
for (dxc = 0; dxc < dxcMax; dxc += 1)
{
gridNew[dxc][dyc] = gridOld[dxc][dyc];
}
}
for (dyc = 0; dyc < dycMax; dyc += 1)
{
for (dxc = 0; dxc < dxcMax; dxc += 1)
{
c = gridOld[dxc][dyc] & 0x0f;
if ((gridOld[dxc][dyc] >> 4) != CLR_BACKGROUND)
{
if (c < 2 || c > 3)
{
SetCell(hps, gridNew, dxc, dyc,
CLR_BACKGROUND);
}
}
else
{
if (c == 3)
{
SetCell(hps, gridNew, dxc, dyc,
ClrAverage(gridOld, dxc, dyc));
}
}
}
}
for (dyc = 0; dyc < dycMax; dyc += 1)
{
for (dxc = 0; dxc < dxcMax; dxc += 1)
{
gridOld[dxc][dyc] = gridNew[dxc][dyc];
}
}
}
// Boy, this is ugly! Find the average color around cell [dxc][dyc]...
ClrAverage(GRID grid, INT dxc, INT dyc)
{
INT c, clr, clrT;
c = clr = 0;
if (dxc > 0)
{
if ((clrT = grid[dxc - 1][dyc] >> 4) != 0)
{
clr += clrT;
c += 1;
}
if (dyc > 0)
{
if ((clrT = grid[dxc - 1][dyc - 1] >> 4) != 0)
{
clr += clrT;
c += 1;
}
}
if (dyc < dycMax - 1)
{
if ((clrT = grid[dxc - 1][dyc + 1] >> 4) != 0)
{
clr += clrT;
c += 1;
}
}
}
if (dyc > 0)
{
if ((clrT = grid[dxc][dyc - 1] >> 4) != 0)
{
clr += clrT;
c += 1;
}
}
if (dyc < dycMax - 1)
{
if ((clrT = grid[dxc][dyc + 1] >> 4) != 0)
{
clr += clrT;
c += 1;
}
}
if (dxc < dxcMax - 1)
{
if ((clrT = grid[dxc + 1][dyc] >> 4) != 0)
{
clr += clrT;
c += 1;
}
if (dyc > 0)
{
if ((clrT = grid[dxc + 1][dyc - 1] >> 4) != 0)
{
clr += clrT;
c += 1;
}
}
if (dyc < dycMax - 1)
{
if ((clrT = grid[dxc + 1][dyc + 1] >> 4) != 0)
{
clr += clrT;
c += 1;
}
}
}
return clr / c;
}
VOID SetCell(CVS hps, GRID grid, INT dxc, INT dyc, INT clr)
{
INT d, clrPrev;
clrPrev = grid[dxc][dyc] >> 4;
if (clr == clrPrev)
return;
grid[dxc][dyc] &= 0x0f;
grid[dxc][dyc] |= clr << 4;
if (hps != NULL)
{
#ifdef PM
RECTL rectl;
rectl.xLeft = MultDiv(dxc, dxScreen, dxcMax);
rectl.xRight = MultDiv(dxc + 1, dxScreen, dxcMax);
rectl.yBottom = MultDiv(dyc, dyScreen, dycMax);
rectl.yTop = MultDiv(dyc + 1, dyScreen, dycMax);
WinFillRect(hps, &rectl,
(clr == CLR_BACKGROUND ? CLR_BLACK : (LONG) clr));
#endif
#ifdef WIN
HANDLE hT;
LOGBRUSH lbrush;
INT x, y;
if (clr == CLR_BACKGROUND)
clr = CLR_BLACK;
lbrush.lbStyle = BS_SOLID;
lbrush.lbColor = mppenrgb[clr];
lbrush.lbHatch = 0;
hT = SelectObject(hps,
CreateBrushIndirect(&lbrush));
x = MultDiv(dxc, dxScreen, dxcMax);
y = MultDiv(dyc, dyScreen, dycMax);
PatBlt(hps, x, y,
MultDiv(dxc + 1, dxScreen, dxcMax) - x,
MultDiv(dyc + 1, dyScreen, dycMax) - y,
PATCOPY);
DeleteObject(SelectObject(hps, hT));
#endif
}
if ((clrPrev == CLR_BACKGROUND) == (clr == CLR_BACKGROUND))
return;
d = clr > 0 ? 1 : -1;
if (dxc > 0)
{
grid[dxc - 1][dyc] += (UCHAR)d;
if (dyc > 0)
grid[dxc - 1][dyc - 1] += (UCHAR)d;
if (dyc < dycMax - 1)
grid[dxc - 1][dyc + 1] += (UCHAR)d;
}
if (dyc > 0)
grid[dxc][dyc - 1] += (UCHAR)d;
if (dyc < dycMax - 1)
grid[dxc][dyc + 1] += (UCHAR)d;
if (dxc < dxcMax - 1)
{
grid[dxc + 1][dyc] += (UCHAR)d;
if (dyc > 0)
grid[dxc + 1][dyc - 1] += (UCHAR)d;
if (dyc < dycMax - 1)
grid[dxc + 1][dyc + 1] += (UCHAR)d;
}
}