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