/* AutomaTron.c Gary Teachout August 1989 lc -L AutomaTron To compile and link with Lattice 5.0 */ #include #define FPEN 7 #define DPEN 7 #define BPEN 0 #define CMAX 8 #define SWIDTH 320 #define SHEIGHT 200 #define PLANES 3 #define RULEMAX ( 7 * 7 ) + 1 #define SEEDMAX 80 #define STOPMODE 1 #define RULEMODE 2 #define SEEDMODE 4 struct menubox { struct MenuItem item ; struct IntuiText text ; } ; struct IntuitionBase *IntuitionBase ; struct GfxBase *GfxBase ; struct Screen *screen ; struct Window *window ; struct IntuiMessage *mes ; ULONG class ; USHORT code ; struct NewScreen ns = { 0 , 0 , SWIDTH , SHEIGHT , PLANES , DPEN , BPEN , 0 , CUSTOMSCREEN , NULL , " AutomaTron" , NULL , NULL } ; struct TextAttr stext = { "topaz.font" , 8 , 0 , 0 } ; struct NewWindow nw = /* for display window */ { 0 , 0 , SWIDTH , SHEIGHT , 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[ SEEDMAX + 1 ] , ubuff[ SEEDMAX + 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[ 3 ] = { { NULL , 1 , 0 , 90 , 8 , MENUENABLED , " Control" , NULL } , { NULL , 91 , 0 , 90 , 10 , MENUENABLED , " Rules" , NULL } , { NULL , 181 , 0 , 90 , 10 , MENUENABLED , " Seeds" , 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 , "Precision" , NULL } } , { { NULL , 0 , 33 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Neighborhood" , NULL } } , { { NULL , 0 , 44 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Modes" , NULL } } , { { NULL , 0 , 66 , 140 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ , 0 , NULL , NULL , 'Q' , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Quit" , NULL } } } , rulesmenu[ 2 ] = { { { NULL , 0 , 0 , 110 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ , 0 , NULL , NULL , 'R' , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Random" , NULL } } , { { NULL , 0 , 11 , 110 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Custom" , NULL } } } , seedsmenu[ 3 ] = { { { NULL , 0 , 0 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ , 0 , NULL , NULL , 'P' , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Random" , NULL } } , { { NULL , 0 , 11 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Custom" , NULL } } , { { NULL , 0 , 22 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ , 0 , NULL , NULL , 'O' , NULL , NULL } , { FPEN , BPEN , JAM1 , 10 , 2 , NULL , "Old Seed" , NULL } } } , precisionsub[ 3 ] = { { { NULL , 130 , 0 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "160 Cells" , NULL } } , { { NULL , 130 , 11 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | CHECKED , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "320 Cells" , NULL } } , { { NULL , 130 , 22 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "640 Cells" , NULL } } } , neighborsub[ 6 ] = { { { NULL , 130 , 0 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0x3e , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "2 Cells" , NULL } } , { { NULL , 130 , 11 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | CHECKED , 0x3d , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "3 Cells" , NULL } } , { { NULL , 130 , 22 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0x3b , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "4 Cells" , NULL } } , { { NULL , 130 , 33 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0x37 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "5 Cells" , NULL } } , { { NULL , 130 , 44 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0x2f , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "6 Cells" , NULL } } , { { NULL , 130 , 55 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT , 0x1f , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "7 Cells" , NULL } } } , modesub[ 3 ] = { { { NULL , 130 , 0 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | MENUTOGGLE | CHECKIT , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "Stop" , NULL } } , { { NULL , 130 , 11 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | MENUTOGGLE | CHECKIT | CHECKED , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "New Seed" , NULL } } , { { NULL , 130 , 22 , 120 , 11 , ITEMTEXT | ITEMENABLED | HIGHCOMP | MENUTOGGLE | CHECKIT | CHECKED , 0 , NULL , NULL , 0 , NULL , NULL } , { FPEN , BPEN , JAM1 , 25 , 2 , NULL , "New Rule" , NULL } } } ; /* assorted global variables */ USHORT line , /* display y */ stopflag = 0 , neighborhood = 3 , precision = SWIDTH , modes = SEEDMODE | RULEMODE ; UBYTE colors = 4 , cells1[ 640 ] , /* cell array 1 */ cells2[ 640 ] , /* cell array 2 */ *old , /* pointer to old cells */ *new , /* pointer to new cells */ oldseed[ SEEDMAX + 1 ] = { 1 , 255 } , rule[ RULEMAX ] = { 0 , 1 , 3 , 1 , 1 , 2 , 3 , 0 , 0 } ; 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 } } ; char *AllocMem() ; struct Screen *OpenScreen() ; struct Window *OpenWindow() ; struct IntuiMessage *GetMsg() ; void cleanup( void ) ; void stepauto( void ) ; void display( void ) ; UBYTE random( UBYTE ) ; void randrule( void ) ; void randseed( void ) ; void handlemsg( void ) ; void handlemenu( void ) ; void stoploop( void ) ; short stringreq( UBYTE * , short ) ; 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() ; SetAPen( window->RPort , 7 ) ; Move( window->RPort , 10 , 140 ) ; Text( window->RPort , "One Dimensional Cellular Automation" , 35 ) ; Move( window->RPort , 10 , 152 ) ; Text( window->RPort , "by Gary Teachout" , 17 ) ; menulist[ 0 ].NextMenu = &menulist[ 1 ] ; menulist[ 0 ].FirstItem = &controlmenu[ 0 ].item ; menulist[ 1 ].NextMenu = &menulist[ 2 ] ; menulist[ 1 ].FirstItem = &rulesmenu[ 0 ].item ; menulist[ 2 ].FirstItem = &seedsmenu[ 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[ 2 ].item.SubItem = &precisionsub[ 0 ].item ; precisionsub[ 0 ].item.ItemFill = ( APTR ) &precisionsub[ 0 ].text ; precisionsub[ 0 ].item.NextItem = &precisionsub[ 1 ].item ; precisionsub[ 1 ].item.ItemFill = ( APTR ) &precisionsub[ 1 ].text ; precisionsub[ 1 ].item.NextItem = &precisionsub[ 2 ].item ; precisionsub[ 2 ].item.ItemFill = ( APTR ) &precisionsub[ 2 ].text ; controlmenu[ 3 ].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 ; neighborsub[ 1 ].item.NextItem = &neighborsub[ 2 ].item ; neighborsub[ 2 ].item.ItemFill = ( APTR ) &neighborsub[ 2 ].text ; neighborsub[ 2 ].item.NextItem = &neighborsub[ 3 ].item ; neighborsub[ 3 ].item.ItemFill = ( APTR ) &neighborsub[ 3 ].text ; neighborsub[ 3 ].item.NextItem = &neighborsub[ 4 ].item ; neighborsub[ 4 ].item.ItemFill = ( APTR ) &neighborsub[ 4 ].text ; neighborsub[ 4 ].item.NextItem = &neighborsub[ 5 ].item ; neighborsub[ 5 ].item.ItemFill = ( APTR ) &neighborsub[ 5 ].text ; controlmenu[ 4 ].item.SubItem = &modesub[ 0 ].item ; modesub[ 0 ].item.ItemFill = ( APTR ) &modesub[ 0 ].text ; modesub[ 0 ].item.NextItem = &modesub[ 1 ].item ; modesub[ 1 ].item.ItemFill = ( APTR ) &modesub[ 1 ].text ; modesub[ 1 ].item.NextItem = &modesub[ 2 ].item ; modesub[ 2 ].item.ItemFill = ( APTR ) &modesub[ 2 ].text ; rulesmenu[ 0 ].item.ItemFill = ( APTR ) &rulesmenu[ 0 ].text ; rulesmenu[ 0 ].item.NextItem = &rulesmenu[ 1 ].item ; rulesmenu[ 1 ].item.ItemFill = ( APTR ) &rulesmenu[ 1 ].text ; seedsmenu[ 0 ].item.ItemFill = ( APTR ) &seedsmenu[ 0 ].text ; seedsmenu[ 0 ].item.NextItem = &seedsmenu[ 1 ].item ; seedsmenu[ 1 ].item.ItemFill = ( APTR ) &seedsmenu[ 1 ].text ; seedsmenu[ 1 ].item.NextItem = &seedsmenu[ 2 ].item ; seedsmenu[ 2 ].item.ItemFill = ( APTR ) &seedsmenu[ 2 ].text ; SetMenuStrip( window , menulist ) ; ShowTitle( screen , TRUE ) ; old = cells1 ; new = cells2 ; randseed() ; for ( ; ; ) /* loop for each line */ { stepauto() ; display() ; if ( old == cells2 ) { old = cells1 ; new = cells2 ; } else { old = cells2 ; new = cells1 ; } if ( line == 12 ) { if ( modes & STOPMODE ) stoploop() ; if ( ( modes & RULEMODE ) && ( line == 12 ) ) randrule() ; if ( ( modes & SEEDMODE ) && ( line == 12 ) ) randseed() ; } handlemsg() ; } } void cleanup() { if ( window ) { ClearMenuStrip( window ) ; CloseWindow( window ) ; } if ( screen ) CloseScreen( screen ) ; if ( GfxBase ) CloseLibrary( GfxBase ) ; if ( IntuitionBase ) CloseLibrary( IntuitionBase ) ; exit() ; } void stepauto() /* this is the actual line automation step */ { short x , t ; UBYTE *n , *or , *ol , *oc ; n = new ; switch ( neighborhood ) { case 2 : ol = old + precision - 1 ; or = old + 1 ; *( n ++ ) = rule[ *( or ++ ) + *ol ] ; ol = old ; for ( x = 2 ; x < precision ; x ++ ) *( n ++ ) = rule[ *( or ++ ) + *( ol ++ ) ] ; or = old ; *n = rule[ *or + *ol ] ; break ; case 3 : t = *( old + precision - 1 ) + *( old + 1 ) + *old ; *( n ++ ) = rule[ t ] ; or = old + 2 ; ol = old + precision - 1 ; t = t - *ol + *( or ++ ) ; *( n ++ ) = rule[ t ] ; ol = old ; for ( x = 3 ; x < precision ; x ++ ) { t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; } or = old ; t = t - *ol + *or ; *n = rule[ t ] ; break ; case 4 : oc = old ; t = *( old + precision - 1 ) + *( old + precision - 2 ) + *( old + 2 ) + *( old + 1 ) + *old ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; or = old + 3 ; ol = old + precision - 2 ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; t = t - *ol + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; ol = old ; for ( x = 5 ; x < precision ; x ++ ) { t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; } or = old ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; t = t - *ol + *or ; *n = rule[ t - *oc ] ; break ; case 5 : t = *( old + precision - 1 ) + *( old + precision - 2 ) + *( old + 2 ) + *( old + 1 ) + *old ; *( n ++ ) = rule[ t ] ; or = old + 3 ; ol = old + precision - 2 ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; t = t - *ol + *( or ++ ) ; *( n ++ ) = rule[ t ] ; ol = old ; for ( x = 5 ; x < precision ; x ++ ) { t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; } or = old ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; t = t - *ol + *or ; *n = rule[ t ] ; break ; case 6 : oc = old ; t = *( old + precision - 1 ) + *( old + precision - 2 ) + *( old + precision - 3 ) + *( old + 3 ) + *( old + 2 ) + *( old + 1 ) + *( old ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; or = old + 4 ; ol = old + precision - 3 ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; t = t - *ol + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; ol = old ; for ( x = 7 ; x < precision ; x ++ ) { t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; } or = old ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t - *( oc ++ ) ] ; t = t - *ol + *or ; *n = rule[ t - *oc ] ; break ; case 7 : t = *( old + precision - 1 ) + *( old + precision - 2 ) + *( old + precision - 3 ) + *( old + 3 ) + *( old + 2 ) + *( old + 1 ) + *( old ) ; *( n ++ ) = rule[ t ] ; or = old + 4 ; ol = old + precision - 3 ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; t = t - *ol + *( or ++ ) ; *( n ++ ) = rule[ t ] ; ol = old ; for ( x = 7 ; x < precision ; x ++ ) { t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; } or = old ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; t = t - *( ol ++ ) + *( or ++ ) ; *( n ++ ) = rule[ t ] ; t = t - *ol + *or ; *n = rule[ t ] ; break ; } } void display() /* render cells directly to screens bit map */ { USHORT d , i , j , k , m , *wp[ PLANES ] , *wpc[ PLANES ] ; UBYTE cm , *c ; if ( precision == 160 ) { i = ( line * screen->BitMap.BytesPerRow ) ; wp[ 0 ] = ( USHORT * ) ( screen->BitMap.Planes[ 0 ] + i ) ; wp[ 1 ] = ( USHORT * ) ( screen->BitMap.Planes[ 1 ] + i ) ; wp[ 2 ] = ( USHORT * ) ( screen->BitMap.Planes[ 2 ] + i ) ; i = ( ( line + 1 ) * screen->BitMap.BytesPerRow ) ; wpc[ 0 ] = ( USHORT * ) ( screen->BitMap.Planes[ 0 ] + i ) ; wpc[ 1 ] = ( USHORT * ) ( screen->BitMap.Planes[ 1 ] + i ) ; wpc[ 2 ] = ( USHORT * ) ( screen->BitMap.Planes[ 2 ] + i ) ; c = new ; for ( i = 0 ; i < precision ; i += 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 ; } line += 2 ; if ( line >= window->Height ) line = 12 ; else { i = ( line * screen->BitMap.BytesPerRow ) ; wp[ 0 ] = ( USHORT * ) ( screen->BitMap.Planes[ 0 ] + i ) ; wp[ 1 ] = ( USHORT * ) ( screen->BitMap.Planes[ 1 ] + i ) ; wp[ 2 ] = ( USHORT * ) ( screen->BitMap.Planes[ 2 ] + i ) ; i = ( ( line + 1 ) * screen->BitMap.BytesPerRow ) ; wpc[ 0 ] = ( USHORT * ) ( screen->BitMap.Planes[ 0 ] + i ) ; wpc[ 1 ] = ( USHORT * ) ( screen->BitMap.Planes[ 1 ] + i ) ; wpc[ 2 ] = ( USHORT * ) ( screen->BitMap.Planes[ 2 ] + i ) ; for ( i = 0 ; i < precision ; i += 8 ) { for ( j = 0 ; j < PLANES ; j ++ ) { *wp[ j ] = 0 ; wp[ j ] ++ ; *wpc[ j ] = 0 ; wpc[ j ] ++ ; } } } } else { i = ( line * screen->BitMap.BytesPerRow ) ; wp[ 0 ] = ( USHORT * ) ( screen->BitMap.Planes[ 0 ] + i ) ; wp[ 1 ] = ( USHORT * ) ( screen->BitMap.Planes[ 1 ] + i ) ; wp[ 2 ] = ( USHORT * ) ( screen->BitMap.Planes[ 2 ] + i ) ; c = new ; for ( i = 0 ; i < precision ; i += 16 ) { for ( cm = 1 , j = 0 ; j < PLANES ; j ++ , cm = cm << 1 ) { d = 0 ; for ( m = 0x8000 , k = 0 ; k < 16 ; m = m >> 1 , k ++ ) { if ( *( c + k ) & cm ) d |= m ; } *wp[ j ] = d ; wp[ j ] ++ ; } c += 16 ; } line ++ ; if ( line == window->Height ) line = 12 ; else { i = ( line * screen->BitMap.BytesPerRow ) ; wp[ 0 ] = ( USHORT * ) ( screen->BitMap.Planes[ 0 ] + i ) ; wp[ 1 ] = ( USHORT * ) ( screen->BitMap.Planes[ 1 ] + i ) ; wp[ 2 ] = ( USHORT * ) ( screen->BitMap.Planes[ 2 ] + i ) ; for ( i = 0 ; i < precision ; i += 16 ) { for ( j = 0 ; j < PLANES ; j ++ ) { *wp[ j ] = 0 ; wp[ j ] ++ ; } } } } } 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 randrule() { short i , s ; UBYTE c ; if ( random( 2 ) ) c = 2 + random( 6 ) ; /* 2 - 7 colors */ else c = 3 + random( 3 ) ; /* 3 - 5 colors */ s = ( ( c - 1 ) * neighborhood ) + 1 ; do { for ( i = 0 ; i < s ; i ++ ) rule[ i ] = random( c ) ; for ( ; i < RULEMAX ; i ++ ) rule[ i ] = 0 ; if ( random( 2 ) ) rule[ 0 ] = 0 ; for ( colors = 0 , i = 0 ; i < RULEMAX ; i ++ ) if ( rule[ i ] >= colors ) colors = rule[ i ] + 1 ; } while ( colors <= 1 ) ; } void randseed() { short x ; line = 12 ; for ( x = 0 ; x < precision ; x ++ ) *( new + x ) = random( colors ) ; display() ; if ( old == cells2 ) { old = cells1 ; new = cells2 ; } else { old = cells2 ; new = cells1 ; } } 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 ; switch ( MENUNUM( code ) ) { case 0 : /* control */ switch ( ITEMNUM( code ) ) { case 0 : /* stop */ stoploop() ; break ; case 1 : /* continue */ stopflag = 0 ; break ; case 2 : /* precision */ switch ( SUBNUM( code ) ) { case 0 : switch ( precision ) { case 160 : break ; case 320 : line = 12 ; break ; case 640 : line = 12 ; ns.Width = 320 ; ns.Height = 200 ; ns.ViewModes = 0 ; nw.Width = 320 ; nw.Height = 200 ; ClearMenuStrip( window ) ; CloseWindow( window ) ; CloseScreen( screen ) ; window = NULL ; screen = OpenScreen( &ns ) ; if ( screen ) window = OpenWindow( &nw ) ; if ( window ) { SetMenuStrip( window , menulist ) ; for ( i = 0 ; i < CMAX ; i ++ ) SetRGB4( &screen->ViewPort , i , ctab[ i ][ 0 ] , ctab[ i ][ 1 ] , ctab[ i ][ 2 ] ) ; } else { cleanup() ; } break ; } precision = 160 ; precisionsub[ 1 ].item.Flags = precisionsub[ 1 ].item.Flags & ( ~ CHECKED ) ; precisionsub[ 2 ].item.Flags = precisionsub[ 2 ].item.Flags & ( ~ CHECKED ) ; break ; case 1 : switch ( precision ) { case 160 : line = 12 ; for ( i = 0 ; i < 160 ; i ++ ) *( old + 160 + i ) = *( old + i ) ; break ; case 320 : break ; case 640 : line = 12 ; ns.Width = 320 ; ns.Height = 200 ; ns.ViewModes = 0 ; nw.Width = 320 ; nw.Height = 200 ; ClearMenuStrip( window ) ; CloseWindow( window ) ; CloseScreen( screen ) ; window = NULL ; screen = OpenScreen( &ns ) ; if ( screen ) window = OpenWindow( &nw ) ; if ( window ) SetMenuStrip( window , menulist ) ; else cleanup() ; for ( i = 0 ; i < CMAX ; i ++ ) SetRGB4( &screen->ViewPort , i , ctab[ i ][ 0 ] , ctab[ i ][ 1 ] , ctab[ i ][ 2 ] ) ; break ; } precision = 320 ; precisionsub[ 0 ].item.Flags = precisionsub[ 0 ].item.Flags & ( ~ CHECKED ) ; precisionsub[ 2 ].item.Flags = precisionsub[ 2 ].item.Flags & ( ~ CHECKED ) ; break ; case 2 : switch ( precision ) { case 160 : for ( i = 0 ; i < 160 ; i ++ ) *( old + 160 + i ) = *( old + i ) ; case 320 : for ( i = 0 ; i < 320 ; i ++ ) *( old + 320 + i ) = *( old + i ) ; line = 12 ; ns.Width = 640 ; ns.Height = 400 ; ns.ViewModes = HIRES | LACE ; nw.Width = 640 ; nw.Height = 400 ; ClearMenuStrip( window ) ; CloseWindow( window ) ; CloseScreen( screen ) ; window = NULL ; screen = OpenScreen( &ns ) ; if ( screen ) window = OpenWindow( &nw ) ; if ( window ) { for ( i = 0 ; i < CMAX ; i ++ ) SetRGB4( &screen->ViewPort , i , ctab[ i ][ 0 ] , ctab[ i ][ 1 ] , ctab[ i ][ 2 ] ) ; SetMenuStrip( window , menulist ) ; precision = 640 ; precisionsub[ 0 ].item.Flags = precisionsub[ 0 ].item.Flags & ( ~ CHECKED ) ; precisionsub[ 1 ].item.Flags = precisionsub[ 1 ].item.Flags & ( ~ CHECKED ) ; } else { ns.Width = 320 ; ns.Height = 200 ; ns.ViewModes = 0 ; nw.Width = 320 ; nw.Height = 200 ; if ( screen ) CloseScreen( screen ) ; screen = OpenScreen( &ns ) ; if ( screen ) window = OpenWindow( &nw ) ; if ( window ) SetMenuStrip( window , menulist ) ; else cleanup() ; for ( i = 0 ; i < CMAX ; i ++ ) SetRGB4( &screen->ViewPort , i , ctab[ i ][ 0 ] , ctab[ i ][ 1 ] , ctab[ i ][ 2 ] ) ; SetAPen( window->RPort , 7 ) ; Move( window->RPort , 10 , 140 ) ; Text( window->RPort , "Unable to open high res screen" , 30 ) ; precision = 320 ; precisionsub[ 0 ].item.Flags = precisionsub[ 0 ].item.Flags & ( ~ CHECKED ) ; precisionsub[ 1 ].item.Flags = precisionsub[ 1 ].item.Flags | CHECKED ; precisionsub[ 2 ].item.Flags = precisionsub[ 2 ].item.Flags & ( ~ CHECKED ) ; } break ; case 640 : break ; } break ; } break ; case 3 : /* neighborhood */ neighborhood = 2 + SUBNUM( code ) ; break ; case 4 : /* modes */ switch ( SUBNUM( code ) ) { case 0 : modes = modes ^ STOPMODE ; break ; case 1 : modes = modes ^ SEEDMODE ; break ; case 2 : modes = modes ^ RULEMODE ; break ; } break ; case 5 : /* quit */ cleanup() ; break ; } break ; case 1 : /* rule */ switch ( ITEMNUM( code ) ) { case 0 : randrule() ; break ; case 1 : for ( i = RULEMAX - 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 " , RULEMAX + 1 ) ) { for ( i = 0 ; ( i < RULEMAX + 1 ) && ( buff[ i ] ) ; i ++ ) ; for ( j = 0 , i -- ; i >= 0 ; i -- , j ++ ) rule[ j ] = ( buff[ i ] - 48 ) & 7 ; for ( ; j < RULEMAX ; j ++ ) rule[ j ] = 0 ; for ( colors = 0 , i = 0 ; i < RULEMAX ; i ++ ) if ( rule[ i ] >= colors ) colors = rule[ i ] + 1 ; } break ; } break ; case 2 : /* seed */ switch ( ITEMNUM( code ) ) { case 0 : randseed() ; break ; case 1 : 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 < SEEDMAX + 1 ) && buff[ i ] ; i ++ ) oldseed[ i ] = ( buff[ i ] - 48 ) & 7 ; oldseed[ i ] = 255 ; } else break ; case 2 : line = 12 ; for ( i = 0 ; i < precision ; i ++ ) *( new + i ) = 0 ; j = ( precision >> 1 ) - 10 ; for ( i = 0 ; ( i < SEEDMAX ) && ( oldseed[ i ] != 255 ) ; i ++ ) *( new + i + j ) = oldseed[ i ] ; display() ; if ( old == cells2 ) { old = cells1 ; new = cells2 ; } else { old = cells2 ; new = cells1 ; } break ; } break ; } } void stoploop() { if ( ! stopflag ) { stopflag = 1 ; while ( stopflag ) { Wait( 1 << window->UserPort->mp_SigBit ) ; handlemsg() ; } } } 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 ; } }