/* crud.c Gary Teachout August 1989 lc -L Crud To compile and link with Lattice 5.0 */ #include #include #include #define FPEN 7 #define DPEN 7 #define BPEN 0 #define SIZEX 160 #define SIZEY 94 #define CMAX 8 #define PLANES 3 #define COLORS 4 #define RULESIZE ( 7 * 9 ) + 1 #define SEEDMAX 50 #define SEEDOFF ( 60 * SIZEX ) + 70 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 , " Creeping Crud" , NULL , NULL } ; struct NewWindow nw = { 0 , 0 , 320 , 200 , DPEN , BPEN , MENUPICK | MENUVERIFY , SMART_REFRESH | ACTIVATE | BACKDROP | BORDERLESS , NULL , NULL , NULL , NULL , NULL , 0 , 0 , 0 , 0 , CUSTOMSCREEN } , rnw = /* for string request window */ { 0 , 30 , 320 , 38 , DPEN , 3 , GADGETUP , SMART_REFRESH | ACTIVATE | WINDOWDRAG , NULL , NULL , NULL , NULL , NULL , 0 , 0 , 0 , 0 , CUSTOMSCREEN } ; /* string request gadgets and stuff */ struct Gadget rgadget[ 3 ] = { { NULL , 4 , 13 , 312 , 8 , GADGHCOMP , TOGGLESELECT | RELVERIFY | STRINGCENTER , STRGADGET , NULL , NULL , NULL , 0 , NULL , 1 , NULL } , { NULL , 8 , 25 , 100 , 10 , GADGHCOMP , RELVERIFY , BOOLGADGET , NULL , NULL , NULL , 0 , NULL , 2 , NULL } , { NULL , 212 , 25 , 100 , 10 , GADGHCOMP , RELVERIFY , BOOLGADGET , NULL , NULL , NULL , 0 , NULL , 3 , NULL } } ; struct StringInfo reqinfo ; UBYTE buff[ RULESIZE + 1 ] , ubuff[ RULESIZE + 1 ] ; struct Border borders[ 3 ] = { { -2 , -2 , 4 , 0 , JAM1 , 5 } , { -1 , -1 , 2 , 0 , JAM1 , 5 } , { -1 , -1 , 1 , 0 , JAM1 , 5 } , } ; short xyborders[ 2 ][ 10 ] = { { 0 , 0 , 315 , 0 , 315 , 11 , 0 , 11 , 0 , 0 } , { 0 , 0 , 101 , 0 , 101 , 11 , 0 , 11 , 0 , 0 } } ; struct IntuiText gtext[ 2 ] = { { FPEN , BPEN , JAM1 , 42 , 2 , NULL , "OK" , NULL } , { FPEN , BPEN , JAM1 , 26 , 2 , NULL , "CANCEL" , NULL } } ; /* display window menus */ struct Menu menulist[ 1 ] = { { NULL , 1 , 0 , 90 , 8 , MENUENABLED , " Control" , NULL } } ; struct menubox controlmenu[ 6 ] = { { { 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 , 'C' , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Continue" , NULL } } , { { NULL , 0 , 22 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "New Rule" , NULL } } , { { NULL , 0 , 33 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "New Seed" , NULL } } , { { NULL , 0 , 44 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Neighborhood" , NULL } } , { { NULL , 0 , 66 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ , 0 , NULL , NULL , 'Q' , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Quit" , NULL } } } , seedsub[ 5 ] = { { { 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 } } , { { NULL , 130 , 33 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Horizontal" , NULL } } , { { NULL , 130 , 44 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Diagonal" , NULL } } } , neighborsub[ 2 ] = { { { NULL , 130 , 0 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0x02 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "Von Neumann" , NULL } } , { { NULL , 130 , 11 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | CHECKED , 0x01 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "Moore" , NULL } } } , rulesub[ 2 ] = { { { NULL , 130 , 0 , 110 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ , 0 , NULL , NULL , 'R' , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Random" , NULL } } , { { NULL , 130 , 11 , 110 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Custom" , NULL } } } ; struct TextAttr stext = { "topaz.font" , 8 , 0 , 0 } ; UBYTE *cells1 , *cells2 , *old , *new ; UBYTE ctab[ CMAX ][ 3 ] = /* screen colors */ { { 0 , 0 , 0 } , { 15 , 0 , 0 } , { 0 , 15 , 0 } , { 0 , 0 , 15 } , { 14 , 14 , 0 } , { 14 , 0 , 14 } , { 0 , 14 , 14 } , { 14 , 14 , 14 } } ; UBYTE rule[ RULESIZE ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 , 4 } ; UBYTE oldseed[ SEEDMAX + 1 ] = { 1 , 255 } ; UBYTE colors = 4 ; short stopflag = 0 , neighborhood = 1 , 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 main() { short i ; 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() ; for ( i = 0 ; i < CMAX ; i ++ ) SetRGB4( &screen->ViewPort , i , ctab[ i ][ 0 ] , ctab[ i ][ 1 ] , ctab[ i ][ 2 ] ) ; rgadget[ 0 ].NextGadget = &rgadget[ 1 ] ; rgadget[ 1 ].NextGadget = &rgadget[ 2 ] ; rgadget[ 0 ].SpecialInfo = ( APTR ) &reqinfo ; reqinfo.Buffer = buff ; reqinfo.UndoBuffer = ubuff ; rgadget[ 0 ].GadgetRender = ( APTR ) &borders[ 0 ] ; rgadget[ 1 ].GadgetRender = ( APTR ) &borders[ 1 ] ; rgadget[ 2 ].GadgetRender = ( APTR ) &borders[ 2 ] ; borders[ 0 ].XY = &xyborders[ 0 ][ 0 ] ; borders[ 1 ].XY = &xyborders[ 1 ][ 0 ] ; borders[ 2 ].XY = &xyborders[ 1 ][ 0 ] ; rgadget[ 1 ].GadgetText = >ext[ 0 ] ; rgadget[ 2 ].GadgetText = >ext[ 1 ] ; rnw.FirstGadget = &rgadget[ 0 ] ; 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 , "A Cellular Automation" , 21 ) ; 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[ 4 ].item.NextItem = &controlmenu[ 5 ].item ; controlmenu[ 5 ].item.ItemFill = ( APTR ) &controlmenu[ 5 ].text ; controlmenu[ 4 ].item.SubItem = &neighborsub[ 0 ].item ; neighborsub[ 0 ].item.ItemFill = ( APTR ) &neighborsub[ 0 ].text ; neighborsub[ 0 ].item.NextItem = &neighborsub[ 1 ].item ; neighborsub[ 1 ].item.ItemFill = ( APTR ) &neighborsub[ 1 ].text ; controlmenu[ 2 ].item.SubItem = &rulesub[ 0 ].item ; rulesub[ 0 ].item.ItemFill = ( APTR ) &rulesub[ 0 ].text ; rulesub[ 0 ].item.NextItem = &rulesub[ 1 ].item ; rulesub[ 1 ].item.ItemFill = ( APTR ) &rulesub[ 1 ].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 ; seedsub[ 2 ].item.NextItem = &seedsub[ 3 ].item ; seedsub[ 3 ].item.ItemFill = ( APTR ) &seedsub[ 3 ].text ; seedsub[ 3 ].item.NextItem = &seedsub[ 4 ].item ; seedsub[ 4 ].item.ItemFill = ( APTR ) &seedsub[ 4 ].text ; SetMenuStrip( window , menulist ) ; ShowTitle( screen , TRUE ) ; 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 ; oc = old ; n = new ; yy = old ; if ( neighborhood ) { 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 ; *( n ++ ) = rule[ *( oc ++ ) + *yp + *ym + *( xp ++ ) + *xm + *mm + *( pm ++ ) + *mp + *( pp ++ ) ] ; mm = ym ; mp = yp ; yp ++ ; ym ++ ; xm = yy ; for ( x = 2 ; x < SIZEX ; x ++ ) { *( n ++ ) = rule[ *( oc ++ ) + *( yp ++ ) + *( ym ++ ) + *( xp ++ ) + *( xm ++ ) + *( mm ++ ) + *( pm ++ ) + *( mp ++ ) + *( pp ++ ) ] ; } xp = yy ; pm -= SIZEX ; pp -= SIZEX ; *( n ++ ) = rule[ *( oc ++ ) + *yp + *ym + *xp + *xm + *mm + *pm + *mp + *pp ] ; yy += SIZEX ; handlemsg() ; if ( reseed ) { reseed = 0 ; break ; } } } else { 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 ; *( n ++ ) = rule[ *( oc ++ ) + *( yp ++ ) + *( ym ++ ) + *( xp ++ ) + *xm ] ; xm = yy ; for ( x = 2 ; x < SIZEX ; x ++ ) { *( n ++ ) = rule[ *( oc ++ ) + *( yp ++ ) + *( ym ++ ) + *( xp ++ ) + *( xm ++ ) ] ; } xp = yy ; *( n ++ ) = rule[ *( oc ++ ) + *yp + *ym + *xp + *xm ] ; yy += SIZEX ; handlemsg() ; if ( reseed ) { reseed = 0 ; break ; } } } } void display() { USHORT x , y , d , i , j , k , m , *wp[ PLANES ] , *wpc[ PLANES ] ; UBYTE cm , *c ; do { reseed = 0 ; i = screen->BitMap.BytesPerRow >> 1 ; wp[ 0 ] = ( USHORT * ) screen->BitMap.Planes[ 0 ] + ( 12 * i ) ; wp[ 1 ] = ( USHORT * ) screen->BitMap.Planes[ 1 ] + ( 12 * i ) ; wp[ 2 ] = ( USHORT * ) screen->BitMap.Planes[ 2 ] + ( 12 * i ) ; wpc[ 0 ] = ( USHORT * ) screen->BitMap.Planes[ 0 ] + ( 13 * i ) ; wpc[ 1 ] = ( USHORT * ) screen->BitMap.Planes[ 1 ] + ( 13 * i ) ; wpc[ 2 ] = ( USHORT * ) screen->BitMap.Planes[ 2 ] + ( 13 * i ) ; c = new ; for ( y = 0 ; y < SIZEY ; y ++ ) { for ( x = 0 ; x < SIZEX ; x += 8 ) { for ( cm = 1 , j = 0 ; j < PLANES ; j ++ , cm = cm << 1 ) { d = 0 ; for ( m = 0xc000 , k = 0 ; k < 8 ; m = m >> 2 , k ++ ) { if ( *( c + k ) & cm ) d |= m ; } *wp[ j ] = d ; wp[ j ] ++ ; *wpc[ j ] = d ; wpc[ j ] ++ ; } c += 8 ; } wp[ 0 ] += i ; wp[ 1 ] += i ; wp[ 2 ] += i ; wpc[ 0 ] += i ; wpc[ 1 ] += i ; wpc[ 2 ] += 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( colors ) ; } } } short stringreq( t , l ) UBYTE *t ; short l ; { struct Window *rw ; struct Gadget *g ; long sig ; rnw.Title = t ; rnw.Screen = screen ; reqinfo.BufferPos = 0 ; reqinfo.DispPos = 0 ; reqinfo.MaxChars = l ; rw = OpenWindow( &rnw ) ; /* a window but it looks like a requester */ if ( rw ) { sig = ( 1 << window->UserPort->mp_SigBit ) | ( 1 << rw->UserPort->mp_SigBit ) ; while ( class != GADGETUP ) { Wait( sig ) ; while ( mes = GetMsg( window->UserPort ) ) { if ( ( mes->Class == MENUVERIFY ) && ( mes->Code == MENUHOT ) ) mes->Code = MENUCANCEL ; ReplyMsg( mes ) ; } while ( mes = GetMsg( rw->UserPort ) ) { class = mes->Class ; g = ( struct Gadget * ) mes->IAddress ; ReplyMsg( mes ) ; } } CloseWindow( rw ) ; if ( g->GadgetID == 3 ) return 0 ; else return 1 ; } else { DisplayBeep( screen ) ; return 0 ; } } 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() { short i , j ; if ( ! MENUNUM( code ) ) { switch ( ITEMNUM( code ) ) { case 0 : stoploop() ; break ; case 1 : stopflag = 0 ; break ; case 2 : switch ( SUBNUM( code ) ) { case 0 : randrule() ; break ; case 1 : for ( i = RULESIZE - 1 ; ( i >= 0 ) && ( ! rule[ i ] ) ; i -- ) ; for ( j = 0 ; i >= 0 ; i -- , j ++ ) buff[ j ] = rule[ i ] + 48 ; buff[ j ] = 0 ; if ( stringreq( " Enter New Rule " , RULESIZE + 1 ) ) { for ( i = 0 ; ( i < RULESIZE + 1 ) && ( buff[ i ] ) ; i ++ ) ; for ( j = 0 , i -- ; i >= 0 ; i -- , j ++ ) rule[ j ] = ( buff[ i ] - 48 ) & 7 ; for ( ; j < RULESIZE ; j ++ ) rule[ j ] = 0 ; for ( colors = 0 , i = 0 ; i < RULESIZE ; i ++ ) if ( rule[ i ] >= colors ) colors = rule[ i ] + 1 ; } break ; } break ; case 3 : switch ( SUBNUM( code ) ) { case 0 : scramble( 5 ) ; reseed = 1 ; break ; case 1 : scramble( 25 ) ; reseed = 1 ; break ; case 2 : scramble( 80 ) ; reseed = 1 ; break ; case 3 : case 4 : for ( i = 0 ; ( i < SEEDMAX + 1 ) && ( oldseed[ i ] != 255 ) ; i ++ ) buff[ i ] = oldseed[ i ] + 48 ; buff[ i ] = 0 ; if ( stringreq( " Enter New Seed " , SEEDMAX + 1 ) ) { for ( i = 0 ; i < ( SIZEX * SIZEY ) ; i ++ ) *( new + i ) = 0 ; for ( i = 0 ; ( i < SEEDMAX + 1 ) && buff[ i ] ; i ++ ) oldseed[ i ] = ( buff[ i ] - 48 ) & 7 ; oldseed[ i ] = 255 ; reseed = 1 ; } else break ; switch ( SUBNUM( code ) ) { case 3 : for ( i = 0 ; ( i < SEEDMAX ) && ( oldseed[ i ] != 255 ) ; i ++ ) *( new + i + SEEDOFF ) = oldseed[ i ] ; break ; case 4 : for ( i = 0 ; ( i < SEEDMAX ) && ( oldseed[ i ] != 255 ) ; i ++ ) *( new + i + SEEDOFF - ( i * SIZEX ) ) = oldseed[ i ] ; break ; } break ; } break ; case 4 : neighborhood = SUBNUM( code ) ; break ; case 5 : /* quit */ cleanup() ; break ; } } } void randrule() { short i , s ; UBYTE c ; if ( random( 2 ) ) c = 2 + random( 6 ) ; /* 2 - 7 colors */ else c = 3 + random( 3 ) ; /* 3 - 5 colors */ do { s = 2 + random( ( UBYTE ) ( ( c - 1 ) * ( ( neighborhood + 1 ) * 4 + 1 ) ) ) ; for ( i = 0 ; i < s ; i ++ ) rule[ i ] = random( c ) ; for ( ; i < RULESIZE ; i ++ ) rule[ i ] = 0 ; if ( random( 4 ) ) { rule[ 0 ] = 0 ; if ( random( 4 ) ) { rule[ 1 ] = 0 ; if ( random( 4 ) ) { rule[ 2 ] = 0 ; if ( random( 4 ) ) rule[ 3 ] = 0 ; } } } for ( colors = 0 , i = 0 ; i < RULESIZE ; i ++ ) if ( rule[ i ] >= colors ) colors = rule[ i ] + 1 ; } while ( colors <= 1 ) ; } void stoploop() { if ( ! stopflag ) { stopflag = 1 ; while ( stopflag ) { Wait( 1 << window->UserPort->mp_SigBit ) ; handlemsg() ; } } }