424 lines
6.9 KiB
C
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;
|
|
}
|
|
}
|