home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff131.lzh / Life / life.c < prev    next >
C/C++ Source or Header  |  1988-03-14  |  11KB  |  406 lines

  1. /*
  2.  *   What fun!  A new LIFE program by Tomas Rokicki.  Commented rather
  3.  *   erratically; hell, this is all just one big hack.
  4.  */
  5. int modulo ;
  6. int wmodulo ;
  7. int vsize ;
  8. #define RASTSIZE (wmodulo * (long)(vsize+1))
  9. #include "structures.h"
  10. #include "blit.h"
  11. short *a, *b, *c, *d, *e, *t1=NULL, *t2=NULL, *t3=NULL, *t4=NULL ;
  12. short noplanes ;
  13. short torus ;
  14. short orify ;
  15. struct GfxBase *GfxBase = NULL ;     /* the GfxBase */
  16. struct IntuitionBase *IntuitionBase = NULL ; /* the IntuitionBase */
  17. struct Screen *myscreen = NULL ;
  18. struct Window *mywindow = NULL ;
  19. struct TextAttr myfont = {(STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 };
  20. struct NewScreen mynewscreen = {0, 0, 0, 0, 0, 1, 2, 0,
  21.    CUSTOMSCREEN, &myfont, (UBYTE *)"AmigaLIFE -- Radical Eye Software"} ;
  22. /*
  23.  *   Let's use a borderless window too, so we can get vanilla
  24.  *   keys.  This gives us a nicer way to exit and adjust the
  25.  *   speed of the program.  But we still play with the screen
  26.  *   bitmaps.
  27.  */
  28. static struct NewWindow mynewwindow = { 0, 0, 0, 0, 0, 1,
  29.    VANILLAKEY, SIMPLE_REFRESH | ACTIVATE | NOCAREREFRESH | BORDERLESS | BACKDROP,
  30.    NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, CUSTOMSCREEN } ;
  31. /*
  32.  *   This routine gets a raster for temporary storage.
  33.  */
  34. short *myalloc() {
  35.    void *AllocMem() ;
  36.    void *p ;
  37.  
  38.    if ((p=AllocMem(2L*RASTSIZE, MEMF_CHIP | MEMF_CLEAR))==NULL) {
  39.       printf("Could not allocate raster data\n") ;
  40.       cleanup() ;
  41.    }
  42.    return(p) ;
  43. }
  44. /*
  45.  *   Here we set things up.
  46.  */
  47. initialize() {
  48.    long color ;
  49.  
  50.    if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
  51.       "intuition.library",0L))==NULL ||
  52.        (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L))
  53.       ==NULL) {
  54.       printf("Couldn't open libraries.\n") ;
  55.       cleanup() ;
  56.    }
  57.    if ((myscreen = OpenScreen(&mynewscreen))==NULL) {
  58.       printf("Couldn't open screen.\n") ;
  59.       cleanup() ;
  60.    }
  61.    mynewwindow.Screen = myscreen ;
  62.    if ((mywindow = OpenWindow(&mynewwindow))==NULL) {
  63.       printf("Couldn't open window.\n") ;
  64.       cleanup() ;
  65.    }
  66.    a = ((short *)(myscreen->BitMap.Planes[0])) + 10 * wmodulo ;
  67.    b = ((short *)(myscreen->BitMap.Planes[1])) + 10 * wmodulo ;
  68.    c = ((short *)(myscreen->BitMap.Planes[2])) + 10 * wmodulo ;
  69.    d = ((short *)(myscreen->BitMap.Planes[3])) + 10 * wmodulo ;
  70.    e = ((short *)(myscreen->BitMap.Planes[4])) + 10 * wmodulo ;
  71.    t1 = myalloc() ;
  72.    t2 = myalloc() ;
  73.    t3 = myalloc() ;
  74.    t4 = myalloc() ;
  75.    if (orify) {
  76.       color = GetRGB4(myscreen->ViewPort.ColorMap, 0L) ;
  77.       if (color & 0xf00)
  78.          color -= 256 ;
  79.       if (color & 0xf0)
  80.          color -= 16 ;
  81.       if (color & 0xf)
  82.          color -= 1 ;
  83.       SetRGB4(&(myscreen->ViewPort), 1L << (noplanes - 1), (color >> 8) & 15,
  84.                 (color >> 4) & 15, color & 15) ;
  85.    }
  86. }
  87. /*
  88.  *   Exit routine.
  89.  */
  90. cleanup() {
  91.    if (mywindow != NULL)
  92.       CloseWindow(mywindow) ;
  93.    if (myscreen != NULL)
  94.       CloseScreen(myscreen) ;
  95.    if (IntuitionBase)
  96.       CloseLibrary(IntuitionBase) ;
  97.    IntuitionBase = NULL ;
  98.    if (GfxBase)
  99.       CloseLibrary(GfxBase) ;
  100.    GfxBase = NULL ;
  101.    if (t1)
  102.       FreeMem(t1, 2L*RASTSIZE) ;
  103.    if (t2)
  104.       FreeMem(t2, 2L*RASTSIZE) ;
  105.    if (t3)
  106.       FreeMem(t3, 2L*RASTSIZE) ;
  107.    if (t4)
  108.       FreeMem(t4, 2L*RASTSIZE) ;
  109.    exit(0) ;
  110. }
  111. #define PARITY (0x96)
  112. #define CARRY (0xe8)
  113. #define SPEC1 (0x6a)
  114. #define SPEC2 (0xbe)
  115. #define SPEC3 (0x40)
  116. #define COPY (0xf0)
  117. #define ORIFY (0xfc)
  118. #define ORAC (0xfa)
  119. /*
  120.  *   This routine does the necessary four blits to wrap the LIFE image.
  121.  *   Please make sure that you own the blitter when you call it!
  122.  */
  123. struct blitparam blitparam ;
  124. fixit() {
  125.    register struct blitparam *p = &blitparam ;
  126.  
  127.    p->bltsize = BLTSIZE(1, vsize) ;
  128.    p->asource = a ;
  129.    p->csource = a + wmodulo - 1 ;
  130.    p->dsource = a + wmodulo - 1 ;
  131.    p->amod = 2 * (wmodulo - 1) ;
  132.    p->bmod = 0 ;
  133.    p->cmod = 2 * (wmodulo - 1) ;
  134.    p->dmod = 2 * (wmodulo - 1) ;
  135.    p->fwm = 0x4000 ;
  136.    p->lwm = 0xffff ;
  137.    p->con0 = SHIFTSHIFT(14) + USEA + USEC + USED + ORAC ;
  138.    p->con1 = 0 ;
  139.    blit(p) ;
  140.    p->asource = a + 2 * wmodulo - 1 ;
  141.    p->csource = a ;
  142.    p->dsource = a ;
  143.    p->fwm = 0x0002 ;
  144.    p->con0 = SHIFTSHIFT(2) + USEA + USEC + USED + ORAC ;
  145.    blit(p) ;
  146.    p->bltsize = BLTSIZE(wmodulo, 1) ;
  147.    p->asource = a + wmodulo ;
  148.    p->dsource = a + wmodulo * (long)(vsize - 1) ;
  149.    p->amod = 0 ;
  150.    p->cmod = 0 ;
  151.    p->dmod = 0 ;
  152.    p->fwm = 0xffff ;
  153.    p->lwm = 0xffff ;
  154.    p->con0 = USEA + USED + COPY ;
  155.    blit(p) ;
  156.    p->asource = a + wmodulo * (long)(vsize - 2) ;
  157.    p->dsource = a ;
  158.    blit(p) ;
  159. }
  160. /*
  161.  *   Does one LIFE generation.  Fancy algorithm uses only 9 blits.  If
  162.  *   anyone can improve this, please let me know.
  163.  */
  164. dogeneration() {
  165.    register struct blitparam *p = &blitparam ;
  166. /*
  167.  *   Initialize the parameters we are not going to change.
  168.  */
  169.    p->fwm = 0xffff ;
  170.    p->lwm = 0xffff ;
  171.    p->amod = 0 ;
  172.    p->bmod = 0 ;
  173.    p->cmod = 0 ;
  174.    p->dmod = 0 ;
  175.    p->asource = a - wmodulo ;
  176.    p->bsource = a - wmodulo + 1 ;
  177.    p->csource = a - wmodulo ;
  178.    p->dsource = t1 ;
  179.    p->bltsize = BLTSIZE(wmodulo, vsize+1) ;
  180.    p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ;
  181.    p->con1 = SHIFTSHIFT(15) ;
  182.    OwnBlitter() ;
  183.    blit(p) ;
  184.    p->dsource = t2 ;
  185.    p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ;
  186.    blit(p) ;
  187.    p->csource = t1 + wmodulo ;
  188.    p->dsource = t3 ;
  189.    p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ;
  190.    blit(p) ;
  191.    p->bltsize = BLTSIZE(wmodulo, vsize) ;
  192.    p->asource = t2 ;
  193.    p->bsource = t2 + 2 * wmodulo ;
  194.    p->csource = t3 + wmodulo ;
  195.    p->dsource = t4 ;
  196.    p->con1 = 0 ;
  197.    p->con0 = USEA + USEB + USEC + USED + CARRY ;
  198.    blit(p) ;
  199.    p->dsource = t3 ;
  200.    p->con0 = USEA + USEB + USEC + USED + PARITY ;
  201.    blit(p) ;
  202.    p->bltsize = BLTSIZE(wmodulo, vsize+1) ;
  203.    p->asource = a - wmodulo ;
  204.    p->bsource = a - wmodulo + 1 ;
  205.    p->csource = t1 + wmodulo ;
  206.    p->dsource = t2 ;
  207.    p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ;
  208.    p->con1 = SHIFTSHIFT(15) ;
  209.    blit(p) ;
  210.    p->bltsize = BLTSIZE(wmodulo, vsize) ;
  211.    p->asource = t1 ;
  212.    p->bsource = t2 + wmodulo ;
  213.    p->csource = t3 ;
  214.    p->dsource = t3 ;
  215.    p->con0 = USEA + USEB + USEC + USED + SPEC1 ;
  216.    p->con1 = 0 ;
  217.    blit(p) ;
  218.    p->csource = a ;
  219.    p->dsource = t1 ;
  220.    p->con0 = USEA + USEB + USEC + USED + SPEC2 ;
  221.    blit(p) ;
  222. /*
  223.  *   Before we do the final write, we copy bits down one generation.
  224.  */
  225.    if (orify) {
  226.       a = ((short *)(myscreen->BitMap.Planes[0])) + 10 * wmodulo ;
  227.       p->asource = 
  228.          ((short *)(myscreen->BitMap.Planes[noplanes-1])) + 10 * wmodulo ;
  229.       p->bsource = 
  230.          ((short *)(myscreen->BitMap.Planes[noplanes-2])) + 10 * wmodulo ;
  231.       p->dsource = p->asource ;
  232.       p->con0 = USEA + USEB + USED + ORIFY ;
  233.       blit(p) ;
  234.    }
  235.    p->con0 = USEA + USED + COPY ;
  236.    switch (noplanes - orify) {
  237. case 5:
  238.    p->asource = d ;
  239.    p->dsource = e ;
  240.    blit(p) ;
  241. case 4:
  242.    p->asource = c ;
  243.    p->dsource = d ;
  244.    blit(p) ;
  245. case 3:
  246.    p->asource = b ;
  247.    p->dsource = c ;
  248.    blit(p) ;
  249. case 2:
  250.    p->asource = a ;
  251.    p->dsource = b ;
  252.    blit(p) ;
  253. default: ;
  254. }
  255.    p->bltsize = BLTSIZE(wmodulo, vsize-2) ;
  256.    p->asource = t1 + wmodulo ;
  257.    p->bsource = t3 + wmodulo ;
  258.    p->csource = t4 + wmodulo ;
  259.    p->dsource = a + wmodulo ;
  260.    p->fwm = 0x7fff ;
  261.    p->lwm = 0xfffe ;
  262.    p->con0 = USEA + USEB + USEC + USED + SPEC3 ;
  263.    blit(p) ;
  264. /*
  265.  *   Wrap, if necessary
  266.  */
  267.    if (torus)
  268.       fixit() ;
  269.    DisownBlitter() ;
  270. }
  271. /*
  272.  *   Random number generator; probably not a very good one.
  273.  */
  274. int rnd(i)
  275. int i ;
  276. {
  277.    static long seed = 323214521 ;
  278.    long rval ;
  279.  
  280.    seed = seed * 123213 + 121 ;
  281.    rval = (seed >> 5) & 65535 ;
  282.    return ((i * rval) >> 16) ;
  283. }
  284. /*
  285.  *   Main routine.  If called with no arguments, makes 1 bit plane screen.
  286.  *   Otherwise, first argument is used as the number of bit planes.
  287.  */
  288. char buffer[200] ;
  289. main (argc, argv)
  290. int argc ;
  291. char *argv[] ;
  292. {
  293.    register int x, y ;
  294.    int hires = 320 ;
  295.    int randoms = 0 ;
  296.    int ir ;
  297.    int dvsize = 0 ;
  298.    struct IntuiMessage *message ;
  299.    int code ;
  300.    long delayval = 0 ;
  301.  
  302.    noplanes = 1 ;
  303.    while (argc > 1 && argv[1][0]=='-') {
  304.       argc-- ;
  305.       argv++ ;
  306.       if (argv[0][1]=='h' || argv[0][1]=='H') {
  307.          if (sscanf(argv[0]+2, "%d", &hires)!=1)
  308.             hires = 640 ;
  309.       } else if (argv[0][1]=='r' || argv[0][1]=='R') {
  310.          if (sscanf(argv[0]+2, "%d", &randoms)!=1)
  311.             randoms = 1 ;
  312.       } else if (argv[0][1]=='p' || argv[0][1]=='P') {
  313.          noplanes = argv[0][2] - '0' ;
  314.          if (noplanes < 1 || noplanes > 6)
  315.             noplanes = 1 ;
  316.       } else if (argv[0][1]=='o' || argv[0][1]=='O') {
  317.          orify = 1 ;
  318.       } else if (argv[0][1]=='t' || argv[0][1]=='T') {
  319.          torus = 1 ;
  320.       } else if (argv[0][1]=='v' || argv[0][1]=='V') {
  321.          if (sscanf(argv[0]+2, "%d", &dvsize)!=1)
  322.             dvsize = 0 ;
  323.       } else if (argv[0][1]=='s' || argv[0][1]=='S') {
  324.          delayval = -1 ;
  325.       }
  326.    }
  327.    if (noplanes == 1)
  328.       orify = 0 ;
  329.    if (argc > 1) {
  330.       if (argv[1][0]=='?' && argv[1][1]==0) {
  331.          printf(
  332.    "Usage:  life [-h[n]] [-r[n]] [-p[n]] [-o] [-t] [-v[n]] [-s] [infile]\n") ;
  333.          cleanup() ;
  334.       }
  335.       if (freopen(argv[1], "r", stdin)==NULL) {
  336.          printf("Couldn't open %s\n", argv[1]) ;
  337.          cleanup() ;
  338.       }
  339.    }
  340.    if (hires > 400) {
  341.       vsize = 390 ;
  342.       mynewscreen.ViewModes |= HIRES ;
  343.    } else {
  344.       vsize = 190 ;
  345.    }
  346.    modulo = hires & ~15 ;
  347.    ir = randoms ;
  348.    if (dvsize >= 10 && dvsize <= 600)
  349.       vsize = dvsize ;
  350.    wmodulo = modulo / 16 ;
  351.    mynewscreen.Depth = noplanes ;
  352.    mynewscreen.Width = modulo ;
  353.    mynewscreen.Height = vsize + 10 ;
  354.    mynewwindow.Width = modulo ;
  355.    mynewwindow.Height = vsize + 10 ;
  356.    if (vsize > 300)
  357.       mynewscreen.ViewModes |= LACE ;
  358.    initialize() ;
  359.    readin(a) ;
  360.    if (torus) {
  361.       OwnBlitter() ;
  362.       fixit() ;
  363.       DisownBlitter() ;
  364.    }
  365.    while (1) {
  366.       if (message = (struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
  367.          code = message->Code ;
  368.          ReplyMsg(message) ;
  369.          switch(code) {
  370. case 27 : case 3 : case 'q' : case 'Q' : case 'x' : case 'X' :
  371.             cleanup() ;
  372. case '0' : case 'g' : case 'G' :
  373.             delayval = 0 ;
  374.             break ;
  375. case '1' : case '2' : case '3' : case '4' :
  376. case '5' : case '6' : case '7' : case '8' : case '9' :
  377.             delayval = 1L << (code - '0') ;
  378.             break ;
  379. case ' ' :
  380.             delayval = -1 ;
  381.             goto doone ;
  382. case 'S' : case 's' :
  383.             delayval = -1 ;
  384. default :
  385.             break ;
  386.          }
  387.       }
  388.       if (delayval) {
  389.          if (delayval == -1)
  390.             continue ;
  391.          Delay(delayval) ;
  392.       }
  393. doone:
  394.       if (randoms) {
  395.          if (ir-- == 0) {
  396.             x = rnd(modulo-2) + 1 ;
  397.             y = rnd(vsize-2) + 1 ;
  398.             a[y * (long)wmodulo + (x >> 4)] |= 1 << (15 - (15 & x)) ;
  399.             ir = randoms ;
  400.          }
  401.       }
  402.       dogeneration() ;
  403.    }
  404.    cleanup() ;
  405. }
  406.