home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Life 1.0d2 / StupidWay.c < prev    next >
Encoding:
Text File  |  1995-07-11  |  6.6 KB  |  332 lines  |  [TEXT/KAHL]

  1. // StupidWay.c
  2. // Handle Life propagation the stupid, but simple way
  3. // Copyright ©1995 Michael D. Crawford.  All Rights Reserved.
  4. // 23 Jun 95 Mike Crawford crawford@scruznet.com
  5. //
  6. // Revision History:
  7. // 12 Jul 95    MDC    New today
  8.  
  9. #include <QDOffscreen.h>
  10. #include "Control.h"
  11. #include "LifeModules.h"
  12. #include "StupidWay.h"
  13.  
  14. OSErr StAlloc( tLifeWorldPtr worldPtr, long height, long width );
  15. OSErr StClearPix( tLifeWorldPtr worldPtr, tLongRect *theRectPtr );
  16. OSErr StFree( tLifeWorldPtr worldPtr );
  17. OSErr StDrawCell( tLifeWorldPtr worldPtr, long h, long v );
  18. OSErr StToggle( tLifeWorldPtr worldPtr, long h, long v );
  19. OSErr StStep( tLifeWorldPtr worldPtr );
  20. OSErr StDraw( tLifeWorldPtr worldPtr );
  21.  
  22. OSErr AddStupidWay( tLifeProcsPtr lifeProcPtr )
  23. {
  24.     FSSpec    speck;
  25.     OSErr    err;
  26.     
  27.     speck.vRefNum = 0;
  28.     speck.parID = 0L;
  29.     speck.name[ 0 ] = 0;
  30.  
  31.     err = AddLifeProcs( lifeProcPtr,
  32.                         kBuiltIn,
  33.                         "\pThe Stupid Way",
  34.                         (tStepProc)StStep,
  35.                         (tLifeAllocProc) StAlloc,
  36.                         (tClearRectProc) StClearPix,
  37.                         (tFreeProc) StFree,
  38.                         (tToggleCellProc) StToggle,
  39.                         (tDrawCellProc) StDrawCell,
  40.                         (tDrawWinProc) StDraw,
  41.                         (FSSpecPtr)&speck );
  42.  
  43.     return err;
  44. }
  45.  
  46. OSErr StAlloc( tLifeWorldPtr worldPtr, long height, long width )
  47. {
  48.     GWorldPtr        hip;
  49.     GWorldPtr        hop;
  50.     tStupidPtr        lifeData;
  51.     Rect            boundsRect;
  52.     QDErr            err;
  53.  
  54.     // Allocate the memory for a life world
  55.     
  56.     worldPtr->lifeData = (void*)NULL;
  57.  
  58.     lifeData = (tStupidPtr)NewPtr( sizeof( tStupidData ) );
  59.     if ( !lifeData )
  60.         return memFullErr;
  61.  
  62.     // STUB center boundsRect around 0, 0
  63.  
  64.     SetRect( &boundsRect, 0, 0, width, height );
  65.  
  66.     err = NewGWorld( &hip, 8, &boundsRect, (CTabHandle)NULL, (GDHandle)NULL, (GWorldFlags)0 );
  67.     if ( err ){
  68.         return;
  69.     }
  70.     
  71.     err = NewGWorld( &hop, 8, &boundsRect, (CTabHandle)NULL, (GDHandle)NULL, (GWorldFlags)0 );
  72.     if ( err ){
  73.         DisposeGWorld( hip );
  74.         return;
  75.     }
  76.  
  77.     lifeData->hip = hip;
  78.     lifeData->hop = hop;
  79.     lifeData->isHip = true;
  80.  
  81.     lifeData->width = width;
  82.     lifeData->height = height;
  83.  
  84.     if ( !LockPixels( GetGWorldPixMap( hip ) ) || !LockPixels( GetGWorldPixMap( hop ) ) ){
  85.         DisposeGWorld( hip );
  86.         DisposeGWorld( hop );
  87.         return;
  88.     }
  89.  
  90.     worldPtr->lifeData = (void*)lifeData;
  91.  
  92.     return noErr;
  93. }
  94.  
  95. OSErr StClearPix( tLifeWorldPtr worldPtr, tLongRect *theRectPtr )
  96. {
  97.     tStupidPtr        lifeData;
  98.     PixMapHandle    pHdl;
  99.     short            hLim;
  100.     short            vLim;
  101.     char            *frPtr;
  102.     char            *cellPtr;
  103.     long            rowBytes;
  104.     long            i;
  105.     short            j;
  106.  
  107.     // Clear a rectangle of cells
  108.     
  109.     lifeData = worldPtr->lifeData;
  110.  
  111.     if ( lifeData->isHip ){
  112.         pHdl = GetGWorldPixMap( lifeData->hip );
  113.         frPtr = (*pHdl)->baseAddr;
  114.     }else{
  115.         pHdl = GetGWorldPixMap( lifeData->hop );
  116.         frPtr = (*pHdl)->baseAddr;
  117.     }
  118.     rowBytes = (*pHdl)->rowBytes & 0x3fff;
  119.         
  120.     vLim = theRectPtr->bottom - 1;
  121.     hLim = theRectPtr->right - 1;
  122.  
  123.     for ( i = theRectPtr->top; i < vLim; i++ ){
  124.     
  125.         cellPtr = frPtr + theRectPtr->left + i * rowBytes;        // Note we need a long multiply
  126.  
  127.         for ( j = theRectPtr->left; j < hLim; j++ ){
  128.             *cellPtr++ = (char)0;
  129.         }
  130.     }
  131.  
  132.     return noErr;
  133. }
  134.  
  135. OSErr StFree( tLifeWorldPtr worldPtr )
  136. {
  137.     // Free a life world when one is through with it.
  138.     
  139.     return noErr;
  140. }
  141.  
  142. OSErr StDrawCell( tLifeWorldPtr worldPtr, long h, long v )
  143. {
  144.     // Draw a single cell; used while interactively sketching
  145.     
  146.     return noErr;
  147. }
  148.  
  149. OSErr StToggle( tLifeWorldPtr worldPtr, long h, long v )
  150. {
  151.     // Switch the state of a cell
  152.     
  153.     return noErr;
  154. }
  155.  
  156. OSErr StStep( tLifeWorldPtr worldPtr )
  157. {
  158.     tStupidPtr        lifeData;
  159.     GWorldPtr        gPtr;
  160.     PixMapHandle    pHdl;
  161.     long            rowBytes;        // Must be long for multiply to work
  162.     short            i;                // Must be long for multiply to work
  163.     short            j;                // Must be long for multiply to work
  164.     short            total;
  165.     short            hLim;
  166.     short            vLim;
  167.     char            *toCell;
  168.     char            *frCell;
  169.     char            *toPtr;
  170.     char            *frPtr;
  171.     char            oldCell;
  172.     short            neighbors;
  173.     static            char deadArray[] = { 0, 0, 0, 0xff, 0, 0, 0, 0, 0 };
  174.     static            char liveArray[] = { 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0 };
  175.  
  176.     // Step a single generation.  This might include a blit to the screen    
  177.  
  178.     lifeData = worldPtr->lifeData;
  179.  
  180.     if ( lifeData->isHip ){
  181.         pHdl = GetGWorldPixMap( lifeData->hip );
  182.         frPtr = (*pHdl)->baseAddr;
  183.         
  184.         pHdl = GetGWorldPixMap( lifeData->hop );
  185.         toPtr = (*pHdl)->baseAddr;
  186.         
  187.         lifeData->isHip = false;
  188.  
  189.     }else{
  190.         pHdl = GetGWorldPixMap( lifeData->hop );
  191.         
  192.         frPtr = (*pHdl)->baseAddr;
  193.         
  194.         pHdl = GetGWorldPixMap( lifeData->hip );
  195.         toPtr = (*pHdl)->baseAddr;
  196.  
  197.         lifeData->isHip = true;
  198.  
  199.     }
  200.     rowBytes = (*pHdl)->rowBytes & 0x3ff;
  201.     
  202.     // We consider all of the cells around the edges to be dead... later we will add
  203.     // an option to wrap around
  204.     
  205.     vLim = worldPtr->height - 1;
  206.     hLim = worldPtr->width - 1;
  207.  
  208.     for ( i = 1; i < vLim; i++ ){
  209.         for ( j = 1; j < hLim; j++ ){
  210.             
  211.             neighbors = 0;
  212.  
  213.             frCell = frPtr + ( j - 1 ) + ( rowBytes * ( i - 1 ) );
  214.  
  215.             if ( *frCell++ )
  216.                 neighbors++;
  217.             if ( *frCell++ )
  218.                 neighbors++;
  219.             if ( *frCell )
  220.                 neighbors++;
  221.  
  222.             frCell = frPtr + ( j - 1 ) + ( rowBytes * i );
  223.  
  224.             if ( *frCell++ )
  225.                 neighbors++;
  226.             
  227.             oldCell = *frCell++;        // For use in the 2 case
  228.  
  229.             if ( *frCell )
  230.                 neighbors++;
  231.  
  232.             frCell = frPtr + ( j - 1 ) + ( rowBytes * ( i + 1 ) );
  233.  
  234.             if ( *frCell++ )
  235.                 neighbors++;
  236.             if ( *frCell++ )
  237.                 neighbors++;
  238.             if ( *frCell )
  239.                 neighbors++;
  240.                 
  241.             toCell = toPtr + j + rowBytes * i;
  242.  
  243. #ifdef NEVER            
  244.             if ( oldCell ){
  245.                 *toCell = liveArray[ neighbors ];
  246.             }else{
  247.                 *toCell = deadArray[ neighbors ];            
  248.             }
  249. #endif
  250.  
  251.             switch( neighbors ){
  252.                 case 0:
  253.                     *toCell = 0;
  254.                     break;
  255.                 case 1:
  256.                     *toCell = 0;
  257.                     break;
  258.                 case 2:
  259.                     *toCell = oldCell;            // Stay the same
  260.                     break;
  261.                 case 3:
  262.                     *toCell = (unsigned char)0xff;
  263.                     break;
  264.                 case 4:
  265.                     *toCell = 0;
  266.                     break;
  267.                 case 5:
  268.                     *toCell = 0;
  269.                     break;
  270.                 case 6:
  271.                     *toCell = 0;
  272.                     break;
  273.                 case 7:
  274.                     *toCell = 0;
  275.                     break;
  276.                 case 8:
  277.                     *toCell = 0;
  278.                     break;
  279.                 default:
  280.                     DebugStr( "\pImpossible neighbor count" );
  281.                     break;
  282.             }
  283.         }
  284.     }
  285.  
  286.     
  287.     return noErr;
  288. }
  289.  
  290. OSErr StDraw( tLifeWorldPtr worldPtr )
  291. {
  292.     tStupidPtr        lifeData;
  293.     GWorldPtr    gPtr;
  294.     short        rowBytes;
  295.     PixMapHandle    pHdl;
  296.     unsigned char    *pixPtr;
  297.     Rect            cellRect;
  298.  
  299.     // Draw to the window in a normal, QuickDraw way, as for handling an update
  300.  
  301.     lifeData = worldPtr->lifeData;
  302.  
  303.     if ( lifeData->isHip )
  304.         gPtr = lifeData->hip;
  305.     else
  306.         gPtr = lifeData->hop;
  307.     
  308.     SetRect( &cellRect, 0, 0, lifeData->width, lifeData->height );
  309.  
  310. //    cellRect = winPtr->portRect;
  311.     
  312.     SetGWorld( (GWorldPtr)( worldPtr->win ), GetMainDevice() );
  313.     
  314.     pHdl = GetGWorldPixMap( gPtr );
  315.     
  316.     CopyBits( &( (GrafPtr)gPtr )->portBits,
  317.                 &( worldPtr->win )->portBits,
  318.                 &cellRect,
  319.                 &cellRect,
  320.                 srcCopy,
  321.                 (RgnHandle)NULL );
  322.  
  323. //    Use this for debugging the drawing operation
  324.                 
  325. //    SetRect( &cellRect, 25, 25, 50, 50 );
  326. //    PenNormal();
  327. //    FrameOval( &cellRect );
  328.  
  329.     
  330.     return noErr;
  331. }
  332.