home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff306.lzh
/
Life
/
life.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-11
|
13KB
|
486 lines
/*
* What fun! A new LIFE program by Tomas Rokicki. Commented rather
* erratically; hell, this is all just one big hack.
*/
int modulo ;
int wmodulo ;
int vsize ;
#define RASTSIZE (wmodulo * (long)(vsize+1))
#include "structures.h"
#include "blit.h"
short *a, *b, *c, *d, *e, *t1=NULL, *t2=NULL, *t3=NULL, *t4=NULL ;
short noplanes ;
short torus ;
short orify ;
short asm ;
struct GfxBase *GfxBase = NULL ; /* the GfxBase */
struct IntuitionBase *IntuitionBase = NULL ; /* the IntuitionBase */
struct Screen *myscreen = NULL ;
struct Window *mywindow = NULL ;
struct TextAttr myfont = {(STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 };
struct NewScreen mynewscreen = {0, 0, 0, 0, 0, 1, 2, 0,
CUSTOMSCREEN, &myfont, (UBYTE *)"AmigaLIFE -- Radical Eye Software"} ;
/*
* Let's use a borderless window too, so we can get vanilla
* keys. This gives us a nicer way to exit and adjust the
* speed of the program. But we still play with the screen
* bitmaps.
*/
static struct NewWindow mynewwindow = { 0, 0, 0, 0, 0, 1,
VANILLAKEY, SIMPLE_REFRESH | ACTIVATE | NOCAREREFRESH | BORDERLESS | BACKDROP,
NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, CUSTOMSCREEN } ;
/*
* This routine gets a raster for temporary storage.
*/
short *myalloc(type)
long type ;
{
void *AllocMem() ;
void *p ;
if ((p=AllocMem(2L*RASTSIZE, type | MEMF_CLEAR))==NULL) {
printf("Could not allocate raster data\n") ;
cleanup() ;
}
return(p) ;
}
/*
* Here we set things up.
*/
initialize() {
long color ;
if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
"intuition.library",0L))==NULL ||
(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L))
==NULL) {
printf("Couldn't open libraries.\n") ;
cleanup() ;
}
if ((myscreen = OpenScreen(&mynewscreen))==NULL) {
printf("Couldn't open screen.\n") ;
cleanup() ;
}
mynewwindow.Screen = myscreen ;
if ((mywindow = OpenWindow(&mynewwindow))==NULL) {
printf("Couldn't open window.\n") ;
cleanup() ;
}
a = ((short *)(myscreen->BitMap.Planes[0])) ;
b = ((short *)(myscreen->BitMap.Planes[1])) ;
c = ((short *)(myscreen->BitMap.Planes[2])) ;
d = ((short *)(myscreen->BitMap.Planes[3])) ;
e = ((short *)(myscreen->BitMap.Planes[4])) ;
if (asm) {
t1 = myalloc(0L) ;
t2 = myalloc(0L) ;
} else {
t1 = myalloc(MEMF_CHIP) ;
t2 = myalloc(MEMF_CHIP) ;
t4 = myalloc(MEMF_CHIP) ;
}
t3 = myalloc(MEMF_CHIP) ;
if (orify) {
color = GetRGB4(myscreen->ViewPort.ColorMap, 0L) ;
if (color & 0xf00)
color -= 256 ;
if (color & 0xf0)
color -= 16 ;
if (color & 0xf)
color -= 1 ;
SetRGB4(&(myscreen->ViewPort), 1L << (noplanes - 1), (color >> 8) & 15,
(color >> 4) & 15, color & 15) ;
}
WaitBlit() ;
}
/*
* Exit routine.
*/
cleanup() {
if (mywindow != NULL)
CloseWindow(mywindow) ;
if (myscreen != NULL)
CloseScreen(myscreen) ;
if (IntuitionBase)
CloseLibrary(IntuitionBase) ;
IntuitionBase = NULL ;
if (GfxBase)
CloseLibrary(GfxBase) ;
GfxBase = NULL ;
if (t1)
FreeMem(t1, 2L*RASTSIZE) ;
if (t2)
FreeMem(t2, 2L*RASTSIZE) ;
if (t3)
FreeMem(t3, 2L*RASTSIZE) ;
if (t4)
FreeMem(t4, 2L*RASTSIZE) ;
exit(0) ;
}
#define PARITY (0x96)
#define CARRY (0xe8)
#define SPEC1 (0x6a)
#define SPEC2 (0xbe)
#define SPEC3 (0x40)
#define COPY (0xf0)
#define ORIFY (0xfc)
#define ORAC (0xfa)
/*
* This routine does the necessary four blits to wrap the LIFE image.
* Please make sure that you own the blitter when you call it!
*/
struct blitparam blitparam ;
fixit() {
register struct blitparam *p = &blitparam ;
if (asm) {
pass3t(a, wmodulo * 2L, (long)vsize) ;
return ;
}
p->bltsize = BLTSIZE(1, vsize) ;
p->asource = a ;
p->csource = a + wmodulo - 1 ;
p->dsource = a + wmodulo - 1 ;
p->amod = 2 * (wmodulo - 1) ;
p->bmod = 0 ;
p->cmod = 2 * (wmodulo - 1) ;
p->dmod = 2 * (wmodulo - 1) ;
p->fwm = 0x4000 ;
p->lwm = 0xffff ;
p->con0 = SHIFTSHIFT(14) + USEA + USEC + USED + ORAC ;
p->con1 = 0 ;
blit(p) ;
p->asource = a + 2 * wmodulo - 1 ;
p->csource = a ;
p->dsource = a ;
p->fwm = 0x0002 ;
p->con0 = SHIFTSHIFT(2) + USEA + USEC + USED + ORAC ;
blit(p) ;
p->bltsize = BLTSIZE(wmodulo, 1) ;
p->asource = a + wmodulo ;
p->dsource = a + wmodulo * (long)(vsize - 1) ;
p->amod = 0 ;
p->cmod = 0 ;
p->dmod = 0 ;
p->fwm = 0xffff ;
p->lwm = 0xffff ;
p->con0 = USEA + USED + COPY ;
blit(p) ;
p->asource = a + wmodulo * (long)(vsize - 2) ;
p->dsource = a ;
blit(p) ;
}
/*
* Does one LIFE generation. Fancy algorithm uses only 9 blits. If
* anyone can improve this, please let me know.
*/
dogeneration() {
register struct blitparam *p = &blitparam ;
register long t ;
register short *tt ;
/*
* Initialize the parameters we are not going to change.
*/
p->fwm = 0xffff ;
p->lwm = 0xffff ;
p->amod = 0 ;
p->bmod = 0 ;
p->cmod = 0 ;
p->dmod = 0 ;
p->asource = a - wmodulo ;
p->bsource = a - wmodulo + 1 ;
p->csource = a - wmodulo ;
p->dsource = t1 ;
p->bltsize = BLTSIZE(wmodulo, vsize+1) ;
p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ;
p->con1 = SHIFTSHIFT(15) ;
if (asm) {
if (noplanes > 1)
tt = t3 ;
else
tt = a ;
t = (wmodulo * (long)vsize) >> 1 ;
pass1(a, t1, t2, t) ;
pass2(a + wmodulo, t1 + wmodulo, t2 + wmodulo, tt + wmodulo,
wmodulo * 2L, t - wmodulo) ;
p->con1 = 0 ;
} else {
OwnBlitter() ;
blit(p) ;
p->dsource = t2 ;
p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ;
blit(p) ;
p->csource = t1 + wmodulo ;
p->dsource = t3 ;
p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ;
blit(p) ;
p->bltsize = BLTSIZE(wmodulo, vsize) ;
p->asource = t2 ;
p->bsource = t2 + 2 * wmodulo ;
p->csource = t3 + wmodulo ;
p->dsource = t4 ;
p->con1 = 0 ;
p->con0 = USEA + USEB + USEC + USED + CARRY ;
blit(p) ;
p->dsource = t3 ;
p->con0 = USEA + USEB + USEC + USED + PARITY ;
blit(p) ;
p->bltsize = BLTSIZE(wmodulo, vsize+1) ;
p->asource = a - wmodulo ;
p->bsource = a - wmodulo + 1 ;
p->csource = t1 + wmodulo ;
p->dsource = t2 ;
p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ;
p->con1 = SHIFTSHIFT(15) ;
blit(p) ;
p->bltsize = BLTSIZE(wmodulo, vsize) ;
p->asource = t1 ;
p->bsource = t2 + wmodulo ;
p->csource = t3 ;
p->dsource = t3 ;
p->con0 = USEA + USEB + USEC + USED + SPEC1 ;
p->con1 = 0 ;
blit(p) ;
p->csource = a ;
p->dsource = t1 ;
p->con0 = USEA + USEB + USEC + USED + SPEC2 ;
blit(p) ;
}
/*
* Before we do the final write, we copy bits down one generation.
*/
p->bltsize = BLTSIZE(wmodulo, vsize) ;
if (noplanes > 1 && asm)
OwnBlitter() ;
if (orify) {
a = ((short *)(myscreen->BitMap.Planes[0])) ;
p->asource =
((short *)(myscreen->BitMap.Planes[noplanes-1])) ;
p->bsource =
((short *)(myscreen->BitMap.Planes[noplanes-2])) ;
p->dsource = p->asource ;
p->con0 = USEA + USEB + USED + ORIFY ;
blit(p) ;
}
p->con0 = USEA + USED + COPY ;
switch (noplanes - orify) {
case 5:
p->asource = d ;
p->dsource = e ;
blit(p) ;
case 4:
p->asource = c ;
p->dsource = d ;
blit(p) ;
case 3:
p->asource = b ;
p->dsource = c ;
blit(p) ;
case 2:
p->asource = a ;
p->dsource = b ;
blit(p) ;
default: ;
}
if (! asm) {
p->bltsize = BLTSIZE(wmodulo, vsize-2) ;
p->asource = t1 + wmodulo ;
p->bsource = t3 + wmodulo ;
p->csource = t4 + wmodulo ;
p->dsource = a + wmodulo ;
p->fwm = 0x7fff ;
p->lwm = 0xfffe ;
p->con0 = USEA + USEB + USEC + USED + SPEC3 ;
blit(p) ;
} else if (noplanes > 1) {
p->asource = t3 ;
p->dsource = a ;
p->bltsize = BLTSIZE(wmodulo, vsize) ;
blit(p) ;
}
/*
* Wrap, if necessary
*/
if (torus)
fixit() ;
else if (asm)
pass3(a, wmodulo * 2L, (long)vsize) ;
if (! asm || noplanes > 1)
DisownBlitter() ;
}
/*
* Random number generator; probably not a very good one.
*/
int rnd(i)
int i ;
{
static long seed = 323214521 ;
long rval ;
seed = seed * 123213 + 121 ;
rval = (seed >> 5) & 65535 ;
return ((i * rval) >> 16) ;
}
/*
* Main routine. If called with no arguments, makes 1 bit plane screen.
* Otherwise, first argument is used as the number of bit planes.
*/
char buffer[200] ;
long time1[3], time2[3] ;
long ratio(a,b,c)
register long a, b, c ;
{
while (a > 32768L) {
a /= 2 ;
c /= 2 ;
}
while (b > 32768L) {
b /= 2 ;
c /= 2 ;
}
if (c == 0)
return(0) ;
else
return(a * b / c) ;
}
main (argc, argv)
int argc ;
char *argv[] ;
{
register int x, y ;
int hires = 320 ;
int randoms = 0 ;
int ir ;
int dvsize = 0 ;
struct IntuiMessage *message ;
int code ;
long delayval = 0 ;
long generations ;
long t ;
noplanes = 1 ;
while (argc > 1 && argv[1][0]=='-') {
argc-- ;
argv++ ;
if (argv[0][1]=='h' || argv[0][1]=='H') {
if (sscanf(argv[0]+2, "%d", &hires)!=1)
hires = 640 ;
} else if (argv[0][1]=='a' || argv[0][1]=='A') {
asm = 1 ;
} else if (argv[0][1]=='r' || argv[0][1]=='R') {
if (sscanf(argv[0]+2, "%d", &randoms)!=1)
randoms = 1 ;
} else if (argv[0][1]=='p' || argv[0][1]=='P') {
noplanes = argv[0][2] - '0' ;
if (noplanes < 1 || noplanes > 6)
noplanes = 1 ;
} else if (argv[0][1]=='o' || argv[0][1]=='O') {
orify = 1 ;
} else if (argv[0][1]=='t' || argv[0][1]=='T') {
torus = 1 ;
} else if (argv[0][1]=='v' || argv[0][1]=='V') {
if (sscanf(argv[0]+2, "%d", &dvsize)!=1)
dvsize = 0 ;
} else if (argv[0][1]=='s' || argv[0][1]=='S') {
delayval = -1 ;
}
}
if (noplanes == 1)
orify = 0 ;
if (argc > 1) {
if (argv[1][0]=='?' && argv[1][1]==0) {
printf(
"Usage: life [-h[n]] [-r[n]] [-p[n]] [-o] [-t] [-v[n]] [-s] [infile]\n") ;
cleanup() ;
}
if (freopen(argv[1], "r", stdin)==NULL) {
printf("Couldn't open %s\n", argv[1]) ;
cleanup() ;
}
}
if (hires > 400) {
vsize = 400 ;
mynewscreen.ViewModes |= HIRES ;
} else {
vsize = 200 ;
}
modulo = hires & ~31 ;
hires = modulo ;
ir = randoms ;
if (dvsize >= 10 && dvsize <= 600)
vsize = dvsize ;
wmodulo = modulo / 16 ;
mynewscreen.Depth = noplanes ;
mynewscreen.Width = modulo ;
mynewscreen.Height = vsize ;
mynewwindow.Width = modulo ;
mynewwindow.Height = vsize ;
if (vsize > 300)
mynewscreen.ViewModes |= LACE ;
initialize() ;
SetAPen(&myscreen->RastPort, 0L) ;
RectFill(&myscreen->RastPort, 0L, 0L, (long)hires-1, (long)vsize-1) ;
WaitBlit() ;
readin(a) ;
if (torus) {
OwnBlitter() ;
fixit() ;
DisownBlitter() ;
}
WaitBlit() ;
generations = 0 ;
DateStamp(time1) ;
while (1) {
if (message = (struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
code = message->Code ;
ReplyMsg(message) ;
switch(code) {
case 27 : case 3 : case 'q' : case 'Q' : case 'x' : case 'X' :
goto done ;
case '0' : case 'g' : case 'G' :
delayval = 0 ;
break ;
case '1' : case '2' : case '3' : case '4' :
case '5' : case '6' : case '7' : case '8' : case '9' :
delayval = 1L << (code - '0') ;
break ;
case ' ' :
delayval = -1 ;
goto doone ;
case 'S' : case 's' :
delayval = -1 ;
default :
break ;
}
}
if (delayval) {
if (delayval == -1)
continue ;
Delay(delayval) ;
}
doone:
if (randoms) {
if (ir-- == 0) {
x = rnd(modulo-2) + 1 ;
y = rnd(vsize-2) + 1 ;
if (!asm || noplanes > 1)
WaitBlit() ;
a[y * (long)wmodulo + (x >> 4)] |= 1 << (15 - (15 & x)) ;
ir = randoms ;
}
}
dogeneration() ;
generations++ ;
}
done:
DateStamp(time2) ;
delayval = time2[2]-time1[2] + (time2[1]-time1[1]) * 3000L
+ (time2[0]-time1[0]) * 4320000L ;
t = (modulo - 2) * (long)(vsize - 2) * 50L ;
t = ((t / delayval) * generations +
ratio(t % delayval, generations, delayval)) ;
printf("%ld generations by %ld pixels in %ld ticks is %ld cells/sec\n",
generations, (modulo-2)*(long)(vsize-2), delayval, t) ;
cleanup() ;
}