home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff249.lzh
/
Automata
/
Life.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-09-14
|
16KB
|
640 lines
/*
Life.c Gary Teachout August 1989
lc -L Life To compile and link with Lattice 5.0
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#define FPEN 1
#define DPEN 1
#define BPEN 0
#define SIZEX 160
#define SIZEY 94
#define PLANES 1
struct menubox
{
struct MenuItem item ;
struct IntuiText text ;
} ;
struct IntuitionBase *IntuitionBase ;
struct GfxBase *GfxBase ;
struct IntuiMessage *mes ;
struct Screen *screen ;
struct Window *window ;
ULONG class ;
USHORT code ;
struct NewScreen ns =
{
0 , 0 , 320 , 200 , PLANES , DPEN , BPEN , 0 ,
CUSTOMSCREEN , NULL , NULL , NULL , NULL
} ;
UBYTE *title[ 2 ] =
{
" Life" ,
" Edit Seed"
} ;
struct NewWindow
nw =
{
0 , 0 , 320 , 200 , DPEN , BPEN ,
MENUPICK | MENUVERIFY | MOUSEBUTTONS ,
SMART_REFRESH | ACTIVATE | BACKDROP | BORDERLESS ,
NULL , NULL , NULL ,
NULL , NULL , 0 , 0 , 0 , 0 , CUSTOMSCREEN
} ;
USHORT chip pointer[ 20 ] =
{
0x0000 , 0x0000 ,
0x8000 , 0x0000 ,
0xc000 , 0x0000 ,
0xa000 , 0x0000 ,
0x9000 , 0x0000 ,
0x8800 , 0x0000 ,
0x8400 , 0x0000 ,
0x8000 , 0x0000 ,
0x0000 , 0x0000 ,
0x0000 , 0x0000
} ;
struct Menu
menulist[ 2 ] =
{
{ NULL , 1 , 0 , 90 , 8 , MENUENABLED , " Control" , NULL } ,
{ NULL , 1 , 0 , 90 , 8 , MENUENABLED , " Edit" , NULL }
} ;
struct menubox
controlmenu[ 5 ] =
{
{
{ NULL , 0 , 0 , 140 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , 'S' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Stop" , NULL }
} ,
{
{ NULL , 0 , 11 , 140 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , 'G' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Go" , NULL }
} ,
{
{ NULL , 0 , 22 , 140 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , 'C' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Custom Seed" , NULL }
} ,
{
{ NULL , 0 , 33 , 140 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP ,
0 , NULL , NULL , 0 , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Random Seed" , NULL }
} ,
{
{ NULL , 0 , 50 , 140 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , 'Q' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Quit" , NULL }
}
} ,
seedsub[ 3 ] =
{
{
{ NULL , 130 , 0 , 120 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , '1' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Small" , NULL }
} ,
{
{ NULL , 130 , 11 , 120 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ,
0 , NULL , NULL , '2' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Medium" , NULL }
} ,
{
{ NULL , 130 , 22 , 120 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , '3' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Large" , NULL }
}
} ,
editmenu[ 4 ] =
{
{
{ NULL , 0 , 0 , 170 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ | CHECKIT ,
0x02 , NULL , NULL , 'A' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 25 , 2 , NULL , "Alive (White)" , NULL }
} ,
{
{ NULL , 0 , 11 , 170 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ | CHECKIT ,
0x01 , NULL , NULL , 'D' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 25 , 2 , NULL , "Dead (Black)" , NULL }
} ,
{
{ NULL , 0 , 22 , 170 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , 'B' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 25 , 2 , NULL , "Blank Field" , NULL }
} ,
{
{ NULL , 0 , 33 , 170 , 11 ,
ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ ,
0 , NULL , NULL , 'C' , NULL , NULL } ,
{ FPEN , BPEN , JAM1 , 25 , 2 , NULL , "Continue" , NULL }
}
} ;
struct TextAttr stext = { "topaz.font" , 8 , 0 , 0 } ;
UBYTE *cells1 , *cells2 , *old , *new ;
short stopflag = 0 , reseed = 0 ;
char *AllocMem() ;
struct Screen *OpenScreen() ;
struct Window *OpenWindow() ;
struct IntuiMessage *GetMsg() ;
void cleanup( void ) ;
void stepauto( void ) ;
void display( void ) ;
UBYTE random( UBYTE ) ;
void scramble( short ) ;
short stringreq( UBYTE * , short ) ;
void handlemsg( void ) ;
void handlemenu( void ) ;
void randrule( void ) ;
void stoploop( void ) ;
void editmode( void ) ;
void main()
{
IntuitionBase = ( struct IntuitionBase * )
OpenLibrary( "intuition.library" , 33 ) ;
if ( ! IntuitionBase )
cleanup() ;
GfxBase = ( struct GfxBase * )
OpenLibrary( "graphics.library" , 33 ) ;
if ( ! GfxBase )
cleanup() ;
ns.Font = &stext ;
screen = OpenScreen( &ns ) ;
if ( ! screen )
cleanup() ;
SetRGB4( &screen->ViewPort , 0 , 0 , 0 , 0 ) ;
SetRGB4( &screen->ViewPort , 1 , 15 , 15 , 15 ) ;
nw.Screen = screen ;
window = OpenWindow( &nw ) ;
if ( ! window )
cleanup() ;
SetBPen( window->RPort , 0 ) ;
SetAPen( window->RPort , 15 ) ;
Move( window->RPort , 60 , 90 ) ;
Text( window->RPort , "The Game of Life" , 16 ) ;
Move( window->RPort , 60 , 102 ) ;
Text( window->RPort , "by Gary Teachout" , 17 ) ;
cells1 = AllocMem( 2 * SIZEX * SIZEY , MEMF_FAST | MEMF_CLEAR ) ;
if ( ! cells1 )
cleanup() ;
cells2 = cells1 + ( SIZEX * SIZEY ) ;
menulist[ 0 ].FirstItem = &controlmenu[ 0 ].item ;
controlmenu[ 0 ].item.ItemFill = ( APTR ) &controlmenu[ 0 ].text ;
controlmenu[ 0 ].item.NextItem = &controlmenu[ 1 ].item ;
controlmenu[ 1 ].item.ItemFill = ( APTR ) &controlmenu[ 1 ].text ;
controlmenu[ 1 ].item.NextItem = &controlmenu[ 2 ].item ;
controlmenu[ 2 ].item.ItemFill = ( APTR ) &controlmenu[ 2 ].text ;
controlmenu[ 2 ].item.NextItem = &controlmenu[ 3 ].item ;
controlmenu[ 3 ].item.ItemFill = ( APTR ) &controlmenu[ 3 ].text ;
controlmenu[ 3 ].item.NextItem = &controlmenu[ 4 ].item ;
controlmenu[ 4 ].item.ItemFill = ( APTR ) &controlmenu[ 4 ].text ;
controlmenu[ 3 ].item.SubItem = &seedsub[ 0 ].item ;
seedsub[ 0 ].item.ItemFill = ( APTR ) &seedsub[ 0 ].text ;
seedsub[ 0 ].item.NextItem = &seedsub[ 1 ].item ;
seedsub[ 1 ].item.ItemFill = ( APTR ) &seedsub[ 1 ].text ;
seedsub[ 1 ].item.NextItem = &seedsub[ 2 ].item ;
seedsub[ 2 ].item.ItemFill = ( APTR ) &seedsub[ 2 ].text ;
menulist[ 1 ].FirstItem = &editmenu[ 0 ].item ;
editmenu[ 0 ].item.ItemFill = ( APTR ) &editmenu[ 0 ].text ;
editmenu[ 0 ].item.NextItem = &editmenu[ 1 ].item ;
editmenu[ 1 ].item.ItemFill = ( APTR ) &editmenu[ 1 ].text ;
editmenu[ 1 ].item.NextItem = &editmenu[ 2 ].item ;
editmenu[ 2 ].item.ItemFill = ( APTR ) &editmenu[ 2 ].text ;
editmenu[ 2 ].item.NextItem = &editmenu[ 3 ].item ;
editmenu[ 3 ].item.ItemFill = ( APTR ) &editmenu[ 3 ].text ;
SetMenuStrip( window , &menulist[ 0 ] ) ;
SetWindowTitles( window , NULL , title[ 0 ] ) ;
ShowTitle( screen , TRUE ) ;
Delay( 100 ) ;
old = cells1 ;
new = cells2 ;
scramble( 25 ) ;
display() ;
old = cells2 ;
new = cells1 ;
for ( ; ; )
{
stepauto() ;
display() ;
if ( old == cells2 )
{
old = cells1 ;
new = cells2 ;
}
else
{
old = cells2 ;
new = cells1 ;
}
}
cleanup() ;
}
void cleanup()
{
if ( cells1 )
FreeMem( cells1 , 2 * SIZEX * SIZEY ) ;
if ( window )
CloseWindow( window ) ;
if ( screen )
CloseScreen( screen ) ;
if ( GfxBase )
CloseLibrary( GfxBase ) ;
if ( IntuitionBase )
CloseLibrary( IntuitionBase ) ;
exit() ;
}
void stepauto()
{
short x , y ;
UBYTE *oc , *n , *yp , *ym , *xp , *xm , *yy ,
*mm , *pm , *mp , *pp , t ;
oc = old ;
n = new ;
yy = old ;
for ( y = 0 ; y < SIZEY ; y ++ )
{
yp = old + ( ( ( y + 1 ) % SIZEY ) * SIZEX ) ;
ym = old + ( ( ( y + SIZEY - 1 ) % SIZEY ) * SIZEX ) ;
xp = yy + 1 ;
xm = yy + SIZEX - 1 ;
mm = ym + SIZEX - 1 ;
mp = yp + SIZEX - 1 ;
pm = ym + 1 ;
pp = yp + 1 ;
t = *yp + *ym + *( xp ++ ) + *xm
+ *mm + *( pm ++ ) + *mp + *( pp ++ ) ;
if ( *( oc ++ ) )
*( n ++ ) = ( ( t == 2 ) || ( t == 3 ) ) ? 1 : 0 ;
else
*( n ++ ) = ( t == 3 ) ? 1 : 0 ;
mm = ym ;
mp = yp ;
yp ++ ;
ym ++ ;
xm = yy ;
for ( x = 2 ; x < SIZEX ; x ++ )
{
t = *( yp ++ ) + *( ym ++ ) + *( xp ++ ) + *( xm ++ )
+ *( mm ++ ) + *( pm ++ ) + *( mp ++ ) + *( pp ++ ) ;
if ( *( oc ++ ) )
*( n ++ ) = ( ( t == 2 ) || ( t == 3 ) ) ? 1 : 0 ;
else
*( n ++ ) = ( t == 3 ) ? 1 : 0 ;
}
xp = yy ;
pm -= SIZEX ;
pp -= SIZEX ;
t = *yp + *ym + *xp + *xm + *mm + *pm + *mp + *pp ;
if ( *( oc ++ ) )
*( n ++ ) = ( ( t == 2 ) || ( t == 3 ) ) ? 1 : 0 ;
else
*( n ++ ) = ( t == 3 ) ? 1 : 0 ;
yy += SIZEX ;
}
}
void display()
{
USHORT x , y , d , i , k , m , *wp , *wpc ;
UBYTE *c ;
do
{
reseed = 0 ;
i = screen->BitMap.BytesPerRow >> 1 ;
wp = ( USHORT * ) screen->BitMap.Planes[ 0 ] + ( 12 * i ) ;
wpc = ( USHORT * ) screen->BitMap.Planes[ 0 ] + ( 13 * i ) ;
c = new ;
for ( y = 0 ; y < SIZEY ; y ++ )
{
for ( x = 0 ; x < SIZEX ; x += 8 )
{
d = 0 ;
for ( m = 0xc000 , k = 0 ; k < 8 ; m = m >> 2 , k ++ )
{
if ( *( c + k ) & 1 )
d |= m ;
}
*wp = d ;
wp ++ ;
*wpc = d ;
wpc ++ ;
c += 8 ;
}
wp += i ;
wpc += i ;
handlemsg() ;
if ( reseed )
break ;
}
} while ( reseed ) ;
}
UBYTE random( a )
UBYTE a ;
{
#define RANDSHIFT 8
#define RANDTAB 23
#define RANDCOMP 8388608
static UBYTE fp = 1 ;
static long v[ RANDTAB ] , rr ;
short vi ;
if ( fp )
{
CurrentTime( &v[ 0 ] , &v[ 1 ] ) ;
srand( v[ 1 ] ) ;
for ( vi = 0 ; vi < RANDTAB ; vi ++ )
v[ vi ] = rand() >> RANDSHIFT ;
rr = rand() >> RANDSHIFT ;
fp = 0 ;
}
vi = RANDTAB * rr / RANDCOMP ;
rr = v[ vi ] ;
v[ vi ] = rand() >> RANDSHIFT ;
return ( UBYTE ) ( ( a * rr ) / RANDCOMP ) ;
}
void scramble( s )
short s ;
{
short x , y ;
for ( x = 0 ; x < ( SIZEX * SIZEY ) ; x ++ )
*( new + x ) = 0 ;
for ( y = ( SIZEY - s ) >> 1 ; y < ( ( SIZEY + s ) >> 1 ) ; y ++ )
{
for ( x = ( SIZEX - s ) >> 1 ; x < ( ( SIZEX + s ) >> 1 ) ; x ++ )
{
*( new + x + ( y * SIZEX ) ) = random( 2 ) ;
}
}
}
void handlemsg()
{
while ( mes = GetMsg( window->UserPort ) )
{
class = mes->Class ;
code = mes->Code ;
ReplyMsg( mes ) ;
switch ( class )
{
case MENUVERIFY :
Wait( 1 << window->UserPort->mp_SigBit ) ;
while ( class != MENUPICK )
{
if ( mes = GetMsg( window->UserPort ) )
{
class = mes->Class ;
code = mes->Code ;
ReplyMsg( mes ) ;
}
}
case MENUPICK :
handlemenu() ;
break ;
}
}
}
void handlemenu()
{
if ( ! MENUNUM( code ) )
{
switch ( ITEMNUM( code ) )
{
case 0 :
stoploop() ;
break ;
case 1 :
stopflag = 0 ;
break ;
case 2 :
editmode() ;
break ;
case 3 :
switch ( SUBNUM( code ) )
{
case 0 :
scramble( 5 ) ;
break ;
case 1 :
scramble( 25 ) ;
break ;
case 2 :
scramble( 80 ) ;
break ;
}
reseed = 1 ;
break ;
case 4 : /* quit */
cleanup() ;
break ;
}
}
}
void stoploop()
{
if ( ! stopflag )
{
stopflag = 1 ;
while ( stopflag )
{
Wait( 1 << window->UserPort->mp_SigBit ) ;
handlemsg() ;
}
}
}
void editmode()
{
UBYTE live = 1 ;
short x , y , ox , oy , mx , my ;
SetWindowTitles( window , NULL , title[ 1 ] ) ;
ClearMenuStrip( window ) ;
display() ;
editmenu[ 0 ].item.Flags = editmenu[ 0 ].item.Flags | CHECKED ;
editmenu[ 1 ].item.Flags = editmenu[ 1 ].item.Flags & ( ~ CHECKED ) ;
SetMenuStrip( window , &menulist[ 1 ] ) ;
SetPointer( window , pointer , 7 , 7 , -1 , 0 ) ;
stopflag = 0 ;
reseed = 0 ;
while( ! reseed )
{
Wait( 1 << window->UserPort->mp_SigBit ) ;
while ( mes = GetMsg( window->UserPort ) )
{
class = mes->Class ;
code = mes->Code ;
ReplyMsg( mes ) ;
switch ( class )
{
case MENUVERIFY :
Wait( 1 << window->UserPort->mp_SigBit ) ;
while ( class != MENUPICK )
{
if ( mes = GetMsg( window->UserPort ) )
{
class = mes->Class ;
code = mes->Code ;
ReplyMsg( mes ) ;
}
}
case MENUPICK :
switch ( ITEMNUM( code ) )
{
case 0 :
live = 1 ;
break ;
case 1 :
live = 0 ;
break ;
case 2 :
for ( y = 0 ; y < ( SIZEY * SIZEX ) ; y ++ )
*( new + y ) = 0 ;
SetRast( window->RPort , 0 ) ;
break ;
case 3 :
reseed = 1 ;
break ;
}
break ;
case MOUSEBUTTONS :
if ( code == SELECTDOWN )
{
ox = oy = -1 ;
while ( code != SELECTUP )
{
mx = window->MouseX & 0xfffe ;
my = window->MouseY & 0xfffe ;
x = mx >> 1 ;
y = ( my >> 1 ) - 6 ;
if ( ( ( x != ox ) || ( y != oy ) ) && ( y >= 0 ) )
{
*( new + x + ( y * SIZEX ) ) = live ;
if ( live )
SetAPen( window->RPort , 1 ) ;
else
SetAPen( window->RPort , 0 ) ;
WritePixel( window->RPort , mx , my ) ;
WritePixel( window->RPort , mx + 1 , my ) ;
WritePixel( window->RPort , mx , my + 1 ) ;
WritePixel( window->RPort , mx + 1 , my + 1 ) ;
ox = x ;
oy = y ;
}
while ( mes = GetMsg( window->UserPort ) )
{
if ( mes->Class == MOUSEBUTTONS )
code = mes->Code ;
ReplyMsg( mes ) ;
}
}
}
break ;
}
}
}
ClearPointer( window ) ;
ClearMenuStrip( window ) ;
SetMenuStrip( window , &menulist[ 0 ] ) ;
SetWindowTitles( window , NULL , title[ 0 ] ) ;
}