home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-11 | 6.6 KB | 332 lines | [TEXT/KAHL] |
- // StupidWay.c
- // Handle Life propagation the stupid, but simple way
- // Copyright ©1995 Michael D. Crawford. All Rights Reserved.
- // 23 Jun 95 Mike Crawford crawford@scruznet.com
- //
- // Revision History:
- // 12 Jul 95 MDC New today
-
- #include <QDOffscreen.h>
- #include "Control.h"
- #include "LifeModules.h"
- #include "StupidWay.h"
-
- OSErr StAlloc( tLifeWorldPtr worldPtr, long height, long width );
- OSErr StClearPix( tLifeWorldPtr worldPtr, tLongRect *theRectPtr );
- OSErr StFree( tLifeWorldPtr worldPtr );
- OSErr StDrawCell( tLifeWorldPtr worldPtr, long h, long v );
- OSErr StToggle( tLifeWorldPtr worldPtr, long h, long v );
- OSErr StStep( tLifeWorldPtr worldPtr );
- OSErr StDraw( tLifeWorldPtr worldPtr );
-
- OSErr AddStupidWay( tLifeProcsPtr lifeProcPtr )
- {
- FSSpec speck;
- OSErr err;
-
- speck.vRefNum = 0;
- speck.parID = 0L;
- speck.name[ 0 ] = 0;
-
- err = AddLifeProcs( lifeProcPtr,
- kBuiltIn,
- "\pThe Stupid Way",
- (tStepProc)StStep,
- (tLifeAllocProc) StAlloc,
- (tClearRectProc) StClearPix,
- (tFreeProc) StFree,
- (tToggleCellProc) StToggle,
- (tDrawCellProc) StDrawCell,
- (tDrawWinProc) StDraw,
- (FSSpecPtr)&speck );
-
- return err;
- }
-
- OSErr StAlloc( tLifeWorldPtr worldPtr, long height, long width )
- {
- GWorldPtr hip;
- GWorldPtr hop;
- tStupidPtr lifeData;
- Rect boundsRect;
- QDErr err;
-
- // Allocate the memory for a life world
-
- worldPtr->lifeData = (void*)NULL;
-
- lifeData = (tStupidPtr)NewPtr( sizeof( tStupidData ) );
- if ( !lifeData )
- return memFullErr;
-
- // STUB center boundsRect around 0, 0
-
- SetRect( &boundsRect, 0, 0, width, height );
-
- err = NewGWorld( &hip, 8, &boundsRect, (CTabHandle)NULL, (GDHandle)NULL, (GWorldFlags)0 );
- if ( err ){
- return;
- }
-
- err = NewGWorld( &hop, 8, &boundsRect, (CTabHandle)NULL, (GDHandle)NULL, (GWorldFlags)0 );
- if ( err ){
- DisposeGWorld( hip );
- return;
- }
-
- lifeData->hip = hip;
- lifeData->hop = hop;
- lifeData->isHip = true;
-
- lifeData->width = width;
- lifeData->height = height;
-
- if ( !LockPixels( GetGWorldPixMap( hip ) ) || !LockPixels( GetGWorldPixMap( hop ) ) ){
- DisposeGWorld( hip );
- DisposeGWorld( hop );
- return;
- }
-
- worldPtr->lifeData = (void*)lifeData;
-
- return noErr;
- }
-
- OSErr StClearPix( tLifeWorldPtr worldPtr, tLongRect *theRectPtr )
- {
- tStupidPtr lifeData;
- PixMapHandle pHdl;
- short hLim;
- short vLim;
- char *frPtr;
- char *cellPtr;
- long rowBytes;
- long i;
- short j;
-
- // Clear a rectangle of cells
-
- lifeData = worldPtr->lifeData;
-
- if ( lifeData->isHip ){
- pHdl = GetGWorldPixMap( lifeData->hip );
- frPtr = (*pHdl)->baseAddr;
- }else{
- pHdl = GetGWorldPixMap( lifeData->hop );
- frPtr = (*pHdl)->baseAddr;
- }
- rowBytes = (*pHdl)->rowBytes & 0x3fff;
-
- vLim = theRectPtr->bottom - 1;
- hLim = theRectPtr->right - 1;
-
- for ( i = theRectPtr->top; i < vLim; i++ ){
-
- cellPtr = frPtr + theRectPtr->left + i * rowBytes; // Note we need a long multiply
-
- for ( j = theRectPtr->left; j < hLim; j++ ){
- *cellPtr++ = (char)0;
- }
- }
-
- return noErr;
- }
-
- OSErr StFree( tLifeWorldPtr worldPtr )
- {
- // Free a life world when one is through with it.
-
- return noErr;
- }
-
- OSErr StDrawCell( tLifeWorldPtr worldPtr, long h, long v )
- {
- // Draw a single cell; used while interactively sketching
-
- return noErr;
- }
-
- OSErr StToggle( tLifeWorldPtr worldPtr, long h, long v )
- {
- // Switch the state of a cell
-
- return noErr;
- }
-
- OSErr StStep( tLifeWorldPtr worldPtr )
- {
- tStupidPtr lifeData;
- GWorldPtr gPtr;
- PixMapHandle pHdl;
- long rowBytes; // Must be long for multiply to work
- short i; // Must be long for multiply to work
- short j; // Must be long for multiply to work
- short total;
- short hLim;
- short vLim;
- char *toCell;
- char *frCell;
- char *toPtr;
- char *frPtr;
- char oldCell;
- short neighbors;
- static char deadArray[] = { 0, 0, 0, 0xff, 0, 0, 0, 0, 0 };
- static char liveArray[] = { 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0 };
-
- // Step a single generation. This might include a blit to the screen
-
- lifeData = worldPtr->lifeData;
-
- if ( lifeData->isHip ){
- pHdl = GetGWorldPixMap( lifeData->hip );
- frPtr = (*pHdl)->baseAddr;
-
- pHdl = GetGWorldPixMap( lifeData->hop );
- toPtr = (*pHdl)->baseAddr;
-
- lifeData->isHip = false;
-
- }else{
- pHdl = GetGWorldPixMap( lifeData->hop );
-
- frPtr = (*pHdl)->baseAddr;
-
- pHdl = GetGWorldPixMap( lifeData->hip );
- toPtr = (*pHdl)->baseAddr;
-
- lifeData->isHip = true;
-
- }
- rowBytes = (*pHdl)->rowBytes & 0x3ff;
-
- // We consider all of the cells around the edges to be dead... later we will add
- // an option to wrap around
-
- vLim = worldPtr->height - 1;
- hLim = worldPtr->width - 1;
-
- for ( i = 1; i < vLim; i++ ){
- for ( j = 1; j < hLim; j++ ){
-
- neighbors = 0;
-
- frCell = frPtr + ( j - 1 ) + ( rowBytes * ( i - 1 ) );
-
- if ( *frCell++ )
- neighbors++;
- if ( *frCell++ )
- neighbors++;
- if ( *frCell )
- neighbors++;
-
- frCell = frPtr + ( j - 1 ) + ( rowBytes * i );
-
- if ( *frCell++ )
- neighbors++;
-
- oldCell = *frCell++; // For use in the 2 case
-
- if ( *frCell )
- neighbors++;
-
- frCell = frPtr + ( j - 1 ) + ( rowBytes * ( i + 1 ) );
-
- if ( *frCell++ )
- neighbors++;
- if ( *frCell++ )
- neighbors++;
- if ( *frCell )
- neighbors++;
-
- toCell = toPtr + j + rowBytes * i;
-
- #ifdef NEVER
- if ( oldCell ){
- *toCell = liveArray[ neighbors ];
- }else{
- *toCell = deadArray[ neighbors ];
- }
- #endif
-
- switch( neighbors ){
- case 0:
- *toCell = 0;
- break;
- case 1:
- *toCell = 0;
- break;
- case 2:
- *toCell = oldCell; // Stay the same
- break;
- case 3:
- *toCell = (unsigned char)0xff;
- break;
- case 4:
- *toCell = 0;
- break;
- case 5:
- *toCell = 0;
- break;
- case 6:
- *toCell = 0;
- break;
- case 7:
- *toCell = 0;
- break;
- case 8:
- *toCell = 0;
- break;
- default:
- DebugStr( "\pImpossible neighbor count" );
- break;
- }
- }
- }
-
-
- return noErr;
- }
-
- OSErr StDraw( tLifeWorldPtr worldPtr )
- {
- tStupidPtr lifeData;
- GWorldPtr gPtr;
- short rowBytes;
- PixMapHandle pHdl;
- unsigned char *pixPtr;
- Rect cellRect;
-
- // Draw to the window in a normal, QuickDraw way, as for handling an update
-
- lifeData = worldPtr->lifeData;
-
- if ( lifeData->isHip )
- gPtr = lifeData->hip;
- else
- gPtr = lifeData->hop;
-
- SetRect( &cellRect, 0, 0, lifeData->width, lifeData->height );
-
- // cellRect = winPtr->portRect;
-
- SetGWorld( (GWorldPtr)( worldPtr->win ), GetMainDevice() );
-
- pHdl = GetGWorldPixMap( gPtr );
-
- CopyBits( &( (GrafPtr)gPtr )->portBits,
- &( worldPtr->win )->portBits,
- &cellRect,
- &cellRect,
- srcCopy,
- (RgnHandle)NULL );
-
- // Use this for debugging the drawing operation
-
- // SetRect( &cellRect, 25, 25, 50, 50 );
- // PenNormal();
- // FrameOval( &cellRect );
-
-
- return noErr;
- }
-