home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / bomb.tar.gz / bomb.tar / bomb / bomb.c < prev    next >
C/C++ Source or Header  |  1998-03-08  |  65KB  |  2,772 lines

  1. /*
  2.     bomb - automatic interactive visual stimulation
  3.     Copyright (C) 1994  Scott Draves <spot@cs.cmu.edu>
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #include "defs.h"
  21. #include "image.h"
  22. #include "image_db.h"
  23. #include "bomb.h"
  24. #include "match.h"
  25. #include "sound.h"
  26.  
  27. board_t board[2];
  28. board_t board2[2];
  29. board_t board3[2];
  30. int dbuf=0;
  31. int remap[max_heat]; /* > largest possible mask */
  32. int p1 = 0;
  33.  
  34. int auto_mode = 0;
  35. int auto_rule = 0;
  36. int delayed_fill = 0;
  37.  
  38. char status_string[status_string_length];
  39.  
  40.  
  41.    int key;
  42.    int frame = 0;
  43.    double timer = 500;
  44.    int overdrive_speed = 20;
  45.    int dtime = 1;
  46.    int flipper, flipper2;
  47.    int param = 0;
  48.    int curs = 0;
  49.    int *gparam;
  50.    int old_rule;
  51.    int pulse = 0;
  52.    int pulse_driver = 0;
  53.    int periodic_write = 0;
  54.    int cmap_changed = 0;
  55.    int image_rate = 0;     /* should be in rule struct */
  56.    int image_dst = 0;
  57.    int rule_lock = 0;
  58.    int pop_back = 0, back_to;
  59.    int permuting = 0;
  60.    double delay = 0.0;
  61.    int kbd_mode = 0;
  62.    int stabilize_fps;
  63.    int display_fps = 0;
  64.    int rule_mask = -1;
  65.    int last_clear = 0;
  66.    int fastflip = 0;
  67. int scramble = 0;
  68.  
  69. int keyboard_enabled = 1;
  70.  
  71. double fps;
  72.  
  73. /* for colormap changes */
  74. static u_char target_cmap[256][3];
  75. int current_cmap[256 * 3];
  76. #define SET_TARGET_PALETTE(x, r, g, b) \
  77.     target_cmap[x][0] = r; \
  78.     target_cmap[x][1] = g; \
  79.     target_cmap[x][2] = b
  80.  
  81.  
  82. cmap_t cmap;
  83. fill_t fill2;
  84. rule_t rule;
  85.  
  86. int nrecords = 0;
  87. FILE *recording = NULL;
  88.  
  89. image8_t fb;
  90.  
  91. int masks[max_heat];
  92.  
  93. #if mac_bomb && !use_sioux
  94. #include <console.h>
  95. short InstallConsole(short fd){return 0;}
  96. void RemoveConsole(void){}
  97. long WriteCharsToConsole(char *buffer, long n){return 0;}
  98. long ReadCharsFromConsole(char *buffer, long n){return 0;}
  99. #endif
  100.  
  101.  
  102. #if xws_bomb && vga_bomb
  103. int running_x;
  104. #endif
  105.  
  106. #if (xws_bomb|ogl_bomb)
  107. Display *disp;
  108. Visual *visual;
  109. int fb_bpp;
  110. Window win;
  111. Colormap xws_cmap;
  112. int depth;
  113. int *xws_lut;
  114. #if xws_bomb
  115. GC gc;
  116. XImage *xws_image;
  117. char *image_buf;
  118. #endif
  119. #endif
  120.  
  121. #if mac_bomb
  122. #include <AppleEvents.h>
  123. #include <Types.h>
  124. #include <Resources.h>
  125. #include <QuickDraw.h>
  126. #include <Fonts.h>
  127. #include <Events.h>
  128. #include <Windows.h>
  129. #include <Menus.h>
  130. #include <TextEdit.h>
  131. #include <Dialogs.h>
  132. #include <Desk.h>
  133. #include <ToolUtils.h>
  134. #include <Memory.h>
  135. #include <SegLoad.h>
  136. #include <Files.h>
  137. #include <OSUtils.h>
  138. #include <OSEvents.h>
  139. #include <DiskInit.h>
  140. #include <Packages.h>
  141. #include <Traps.h>
  142. #include <QDOffscreen.h>
  143. #include <Palettes.h>
  144. #include <LowMem.h>
  145. #endif
  146.  
  147. void
  148. ramp(int c, int i0, int i1, int n, int k)
  149. {
  150.    int x, r, g, b;
  151.    for (x = 0; x < n; x++) {
  152.       double alpha = x / (double) n;
  153.       r = (int) (the_cmaps[c][i0][0] * (1 - alpha) +
  154.        the_cmaps[c][i1][0] * alpha);
  155.       g = (int) (the_cmaps[c][i0][1] * (1 - alpha) +
  156.        the_cmaps[c][i1][1] * alpha);
  157.       b = (int) (the_cmaps[c][i0][2] * (1 - alpha) +
  158.        the_cmaps[c][i1][2] * alpha);
  159.       SET_TARGET_PALETTE(k + x, r, g, b);
  160.    }
  161. }
  162.  
  163. int
  164. round_up8(int n)
  165. {
  166.    if (n < 0)
  167.       n = (n - 7) >> 3;
  168.    else
  169.       n = (n + 7) >> 3;
  170.    return n;
  171. }
  172.  
  173. int
  174. round_up5(int n)
  175. {
  176.    if (n < 0)
  177.       n = (n - 31) >> 5;
  178.    else
  179.       n = (n + 31) >> 5;
  180.    return n;
  181. }
  182.  
  183. void
  184. step_cmap()
  185. {
  186.    int i;
  187.    for (i = 0; i < 256; i++) {
  188.       current_cmap[3*i]   += round_up8(target_cmap[i][0] - current_cmap[3*i]);
  189.       current_cmap[3*i+1] += round_up8(target_cmap[i][1] - current_cmap[3*i+1]);
  190.       current_cmap[3*i+2] += round_up8(target_cmap[i][2] - current_cmap[3*i+2]);
  191.    }
  192. #define difff(x,y) ((x)!=(y))
  193.    for (i = 0; i < 256; i++) {
  194.       if (difff(current_cmap[3*i+0], target_cmap[i][0]) ||
  195.       difff(current_cmap[3*i+1], target_cmap[i][1]) ||
  196.       difff(current_cmap[3*i+2], target_cmap[i][2])) {
  197.      image8_set_cmap(0, 256, current_cmap);
  198.      return;
  199.       }
  200.    }
  201. }
  202.  
  203. void brighten_cmap() {
  204.    int i;
  205.    for (i = 0; i < 256; i++) {
  206.       int r = (255 + 4*current_cmap[3*i+0])/5;
  207.       int g = (255 + 4*current_cmap[3*i+1])/5;
  208.       int b = (255 + 4*current_cmap[3*i+2])/5;
  209.       SET_TARGET_PALETTE(i, r, g, b);
  210.    }
  211. }
  212.  
  213. void pulse_cmap_rotate() {
  214.    int i;
  215.    for (i = 1; i < 220; i++) {
  216.       current_cmap[3*i+0] = current_cmap[(3*i+0+90)%(3*256)];
  217.       current_cmap[3*i+1] = current_cmap[(3*i+0+91)%(3*256)];
  218.       current_cmap[3*i+2] = current_cmap[(3*i+0+92)%(3*256)];
  219.    }
  220. }
  221.  
  222. void pulse_cmap_black() {
  223.    int i;
  224.    for (i = 100; i < 150; i++) {
  225.       current_cmap[3*i+0] = current_cmap[3*i+0] * (150 - i) / 50;
  226.       current_cmap[3*i+1] = current_cmap[3*i+1] * (150 - i) / 50;
  227.       current_cmap[3*i+2] = current_cmap[3*i+2] * (150 - i) / 50;
  228.    }
  229.    for (i = 150; i < 250; i++) {
  230.       current_cmap[3*i+0] = 0;
  231.       current_cmap[3*i+1] = 0;
  232.       current_cmap[3*i+2] = 0;
  233.    }
  234. }
  235.  
  236. void pulse_cmap_white() {
  237.    int i;
  238.    for (i = 1; i < 10; i++) {
  239.       current_cmap[3*i+0] = ((current_cmap[3*i+0] * (10 - i) / 10) +
  240.                  (255 * i / 10));
  241.       current_cmap[3*i+1] = ((current_cmap[3*i+1] * (10 - i) / 10) +
  242.                  (255 * i / 10));
  243.       current_cmap[3*i+2] = ((current_cmap[3*i+2] * (10 - i) / 10) +
  244.                  (255 * i / 10));
  245.    }
  246.    for (i = 10; i < 20; i++) {
  247.       current_cmap[3*i+0] = 255;
  248.       current_cmap[3*i+1] = 255;
  249.       current_cmap[3*i+2] = 255;
  250.    }
  251.    for (i = 20; i < 30; i++) {
  252.       current_cmap[3*i+0] = ((current_cmap[3*i+0] * (i - 20) / 10) +
  253.                  (255 * (30 - i) / 10));
  254.       current_cmap[3*i+1] = ((current_cmap[3*i+1] * (i - 20) / 10) +
  255.                  (255 * (30 - i) / 10));
  256.       current_cmap[3*i+2] = ((current_cmap[3*i+2] * (i - 20) / 10) +
  257.                  (255 * (30 - i) / 10));
  258.    }
  259. }
  260.  
  261. void
  262. fade2cmap(cmap_t *p)
  263. {
  264.    int r, g, b, x;
  265.    int c, i, i0, i1, i2;
  266.  
  267.    switch (p->cmap) {
  268.     case cmap_mono:
  269.       for(x=0;x<256;x++) {
  270.      SET_TARGET_PALETTE(x,x,x,x);
  271.       }
  272.       break;
  273.     case cmap_mono4:
  274.       i0 = p->index;
  275.       i1 = p->index2;
  276.       for(x=0;x<256;x++) {
  277.      if (x == i0) {
  278.         r = (i1&3)<<4;
  279.         g = (i1&12)<<2;
  280.         b = (i1&48);
  281.      } else
  282.         r = g = b = (x&63)<<2;
  283.      SET_TARGET_PALETTE(x,r,g,b);
  284.       }
  285.       break;
  286.     case cmap_loop:
  287.       c = p->index;
  288.       i0 = R%256;
  289.       i1 = next_contrasting_color(c, i0, 60000);
  290.       i2 = next_contrasting_color(c, i1, 60000);
  291.       ramp(c, i0, i1, 64, 0);
  292.       ramp(c, i1, i2, 64, 64);
  293.       ramp(c, i2, i1, 64, 128);
  294.       ramp(c, i1, i0, 64, 192);
  295.       break;
  296.     case cmap_path:
  297.       if (1) {
  298.      int n = 10;
  299.      int len = 30000;
  300.      int each = 256/(n+1);
  301.      c = p->index;
  302.      i2 = i0 = R%256;
  303.      for (i = 0; i < n; i++) {
  304.         i1 = next_contrasting_color(c, i0, len);
  305.         ramp(c, i0, i1, each, i*each);
  306.         i0 = i1;
  307.      }
  308.      ramp(c, i1, i2, 256 - n*each, n*each);
  309.       }
  310.       break;
  311.     case cmap_heat:
  312.       /* black -> midred -> red -> yellow -> white
  313.      -> = 64 */
  314.       for (x = 0; x < 128; x++) {
  315.      r = g = 255;
  316.      b = x << 1;
  317.      SET_TARGET_PALETTE(128 + x, r, g, b);
  318.       }
  319.       for (x = 0; x < 64 ;x++) {
  320.      r = 255;
  321.      b = 0;
  322.      g = x<<2;
  323.      SET_TARGET_PALETTE(64 + x, r, g, b);
  324.       }
  325.       for(x = 0; x < 64; x++) {
  326.      r = x<<2;
  327.      g = 0;
  328.      b = 0;
  329.      SET_TARGET_PALETTE(x, r, g, b);
  330.       }
  331.       break;
  332.     case cmap_plain:
  333.       i = p->index;
  334.       for (x = 0; x < 256; x++) {
  335.      r = the_cmaps[i][x][0];
  336.      g = the_cmaps[i][x][1];
  337.      b = the_cmaps[i][x][2];
  338.      SET_TARGET_PALETTE(x,r,g,b);
  339.       }
  340.       break;
  341.     case cmap_split:
  342.       i = p->index;
  343.       for(x=0;x<128;x++) {
  344.      r = the_cmaps[i][x][0];
  345.      g = the_cmaps[i][x][1];
  346.      b = the_cmaps[i][x][2];
  347.      SET_TARGET_PALETTE(x,r,g,b);
  348.       }
  349.       i = p->index2;
  350.       for(x=128;x<256;x++) {
  351.      r = the_cmaps[i][x][0];
  352.      g = the_cmaps[i][x][1];
  353.      b = the_cmaps[i][x][2];
  354.      SET_TARGET_PALETTE(x,r,g,b);
  355.       }
  356.       break;
  357.     case cmap_noise:
  358.       for (x = 0; x < 256; x++) {
  359.      SET_TARGET_PALETTE(x,R,R,R);
  360.       }
  361.       break;
  362.     case cmap_black:
  363.       for (x = 0; x < 256; x++) {
  364.      SET_TARGET_PALETTE(x,0,0,0);
  365.       }
  366.       break;
  367.    case cmap_ramp:
  368.      c = p->index;
  369.      i0 = R%256;
  370.      i1 = next_contrasting_color(c, i0, 80000);
  371.      ramp(c, i0, i1, 256, 0);
  372.      break;
  373.    }
  374. }
  375.  
  376. void set_remap(int mask, int rm) {
  377.     int x;
  378.     for (x = 0; x < mask; x++) {
  379.          int r;
  380.          r = rm
  381.              ? (int)(255 * x / (double)mask)
  382.              : x;
  383.          r = r & 255;
  384.          if (0 == r) r = 1;
  385.          if (255 == r) r = 254;
  386.          remap[x] = r;
  387.     }
  388. }
  389.  
  390.  
  391. /* spook */
  392. int
  393. count_bits16(int i)
  394. {
  395.    int b, r = 0;
  396.    for (b = 1; b < 0x10000; b = b << 1)
  397.       if (b & i)
  398.      r++;
  399.    return r;
  400. }
  401.  
  402. /* find last set, like ffs */
  403. int
  404. fls(int i)
  405. {
  406.    int r = 1;
  407.    int b = 1;
  408.    while (b < i) {
  409.       r++;
  410.       b = b << 1;
  411.    }
  412.    return r;
  413. }
  414.  
  415. void
  416. init_masks()
  417. {
  418.    int i, c;
  419.    c = 0;
  420.    i = 1;
  421.    while (c < max_heat) {
  422.       if (8 < count_bits16(i)) {
  423.      masks[c++] = i;
  424.       }
  425.       i += 2;
  426.    }
  427. }
  428.  
  429. int
  430. compare_integers(const void *k, const void *a)
  431. {
  432.    return *(int *)a - *(int *)k;
  433. }
  434.  
  435. /* generally should just keep the index */
  436. int
  437. next_mask(int mask, int d)
  438. {
  439.    int *r;
  440.    int i;
  441.    int s = (d > 0) ? 2 : -2;
  442.    d = abs(d);
  443.    d = (d > 0) ? d : -d;
  444.    while (d) {
  445.       if (8 < count_bits16(mask))
  446.      d--;
  447.       mask += s;
  448.    }
  449.    return mask;
  450. #if 0
  451.    r = bsearch(&mask, masks, max_heat, sizeof(int), compare_integers);
  452.    if (NULL == r)
  453.       return masks[0];
  454.    i = (r - masks + d) % max_heat;
  455.    return masks[i];
  456. #endif
  457. }
  458.  
  459. int load_title(char *fn)
  460. {
  461.    int i;
  462.    Image im;
  463. #if !use_sioux
  464.    /* set cmaps to grayscale */
  465.    for (i = 0; i < 256; i++) {
  466.       int *v = ¤t_cmap[3*i];
  467.       v[0] = v[1] = v[2] = i;
  468.    }
  469.    image8_set_cmap(0, 256, current_cmap);
  470.  
  471.    image_init(&im);
  472.    if (TCL_ERROR == image_read(&im, fn))
  473.       return 0;
  474.    image8_blit(&im, &fb);
  475.    image8_flush();
  476. #endif
  477.    return 1;
  478. }
  479.  
  480. #if mac_bomb
  481.  
  482. int GetBit( const void *data, int offset )
  483. {
  484.    int d = ((unsigned char *)data)[offset >> 3];
  485.    return (d & (1 << (offset & 7))) != 0;
  486. }
  487.  
  488. #endif
  489.  
  490.  
  491. int
  492. bomb_getkey() {
  493. #if win_bomb
  494.     extern int win_getkey();
  495.     return win_getkey();
  496. #endif
  497. #if vga_bomb && xws_bomb
  498.    if (!running_x)
  499. #endif
  500. #if vga_bomb
  501.    return vga_getkey();
  502. #endif
  503. #if (xws_bomb|ogl_bomb)
  504.    {
  505.      XEvent ev;
  506.      if (XCheckWindowEvent(disp, win, KeyPressMask, &ev)) {
  507.        KeySym s;
  508.        s = XKeycodeToKeysym(disp, ev.xkey.keycode, 0);
  509.        /* doesn't work for shifted digits */
  510.        if (s > 255) return 0;
  511.        if (ShiftMask&ev.xkey.state) {
  512.      return ((int)s) - ('a' - 'A');
  513.        }
  514.        if (ControlMask&ev.xkey.state) {
  515.      return ((int)s) - 'a' + 1;
  516.        }
  517.        return (int) s;
  518.      } else
  519.        return 0;
  520.    }
  521. #endif
  522. #if mac_bomb
  523. #if use_sioux
  524. #  define GetMacEvent GetNextEvent
  525. #else
  526. #  define GetMacEvent GetOSEvent
  527. #endif
  528.    static EventRecord gEvent;
  529.    if (GetMacEvent( keyDownMask, &gEvent)) {
  530.       int key = gEvent.message & charCodeMask;
  531.       if ('q' == key && (gEvent.modifiers & cmdKey))
  532.          return 3;
  533.       else
  534.          return(key);
  535.    } else
  536.       return(0);
  537. #endif
  538. }
  539.  
  540. void bomb_exit() {
  541.   if (recording)
  542.     fclose(recording);
  543.  
  544.   exit_sound();
  545. #if mac_bomb
  546.   if (1) {
  547.     GrafPtr wPort;
  548.     FlushEvents(everyEvent - osMask - diskMask, 0);
  549.   }
  550.   ExitToShell();
  551. #endif
  552.   printf("\nbye\n");
  553.   exit(0);
  554. }
  555.  
  556. #if ogl_bomb || vga_bomb || xws_bomb
  557. void init_random() {
  558.    int t = time(NULL);
  559.    srandom(argd("seed", t));
  560. }
  561. #endif
  562.  
  563. #if mac_bomb
  564. void
  565. init_random()
  566. {
  567.    srand(argd("seed", TickCount()));
  568. }
  569.  
  570. void
  571. init_mac()
  572. {
  573.  
  574. #if mac_bomb
  575.    if (1) {
  576.       Ptr base_address;
  577.       SysEnvRec This_mac;
  578.       Rect *rr;
  579.       int cx, cy;
  580.       CWindowPtr myWindow;
  581.  
  582.       printf("init bomb\n");
  583. #if !use_sioux
  584.       InitGraf(&qd.thePort);
  585.       InitFonts();
  586.       FlushEvents(everyEvent - osMask - diskMask, 0);
  587.       InitWindows();
  588.       InitCursor();
  589.       MaxApplZone();
  590.       MoreMasters();
  591.       HideCursor();
  592. #endif
  593.       SysEnvirons( 1, &This_mac );
  594.       if ( This_mac.hasColorQD ) {
  595.          GDHandle the_monitor;
  596.          the_monitor = GetMainDevice();         /* Get monitor with the menuBar on it. */
  597.          if ((**(**the_monitor).gdPMap).pixelSize != 8)
  598.             SetDepth(the_monitor, 8, 0, 0);    /* Make sure we have 8-bit pixels */
  599.          base_address = (**(**the_monitor).gdPMap).baseAddr;
  600.          fb.stride = ((**(**the_monitor).gdPMap).rowBytes & 0x3FFF);
  601.          rr = &(**(**the_monitor).gdPMap).bounds;
  602.          SetGDevice(the_monitor);
  603.        //  world_x = (**the_monitor).gdRect.left;
  604.        //  world_y = (**the_monitor).gdRect.top;
  605.       } else {
  606.      ExitToShell();   /* Not much point if we don't have color quickdraw. */
  607.    }
  608.    
  609. #if !use_sioux
  610.    if (1) {
  611.       int i, j;
  612.      /* open window covering entire screen so things will be redrawn when the app quits */
  613.       myWindow = (CWindowPtr) NewCWindow(0, rr, "\pBomb", 1, 0, (WindowPtr) -1, 0, 0);
  614.       SetPort((WindowPtr)myWindow);
  615.       for (i = rr->top; i < rr->bottom; i++)
  616.          for (j = rr->left; j < rr->right; j++)
  617.             *(((u_char*)base_address) + j + (i * fb.stride)) = 0;
  618.    }
  619. #endif
  620.  
  621. #if pix_rep
  622. #ifdef copy_bits
  623.       if (1) {
  624.       extern PixMapPtr  offscreenPixMapP, windowPixMapP;
  625.       extern Rect       windowRect, offscreenRect;
  626.       PixMapHandle    offscreenPixMapH, windowPixMapH;
  627.       GWorldPtr         offscreenWorldP;
  628.       GWorldPtr         saveWorld;
  629.       GDHandle          saveDevice;
  630.    
  631.       SetRect(&windowRect, 0, 0, pix_rep*320, pix_rep*200);
  632.       SetRect(&offscreenRect, 0, 0, 320, 200);
  633.       OffsetRect(&windowRect, (rr->right - rr->left - (pix_rep*320)) / 2 & (~3), (rr->bottom - rr->top - (pix_rep*200)) / 2);
  634.    // Get the Graphics World and Device associated with the window
  635.       GetGWorld(&saveWorld, &saveDevice);
  636.    // Set a pointer to the windows PixMap
  637.       windowPixMapH = GetGWorldPixMap(saveWorld);
  638.       HLockHi((Handle)windowPixMapH);
  639.       LockPixels(windowPixMapH);
  640.       windowPixMapP = *windowPixMapH;
  641.  
  642.    // Set Up Offscreen GWorld
  643.       if (NewGWorld(&offscreenWorldP, 0, &offscreenRect, 0, saveDevice, noNewDevice))
  644.          DebugStr("\pCan't get GWorld.");
  645.    // Set a pointer to the Offscreen World's PixMap
  646.       offscreenPixMapH = GetGWorldPixMap(offscreenWorldP);
  647.       HLockHi((Handle)offscreenPixMapH);
  648.       LockPixels(offscreenPixMapH);
  649.       offscreenPixMapP = *offscreenPixMapH;
  650.    // Set up fb.
  651.       fb.p = (Byte*) (*offscreenPixMapH)->baseAddr;
  652.       fb.stride = (*offscreenPixMapH)->rowBytes & 0x3fff;
  653.    }
  654. #else
  655.    if (1) {
  656.       extern unsigned char *real_screen_base;
  657.       extern int real_screen_stride;
  658.       cy = (rr->bottom - rr->top - (pix_rep*200)) / 2;
  659.       cx = (rr->right - rr->left - (pix_rep*320)) / 2;
  660.       real_screen_base = ((u_char *) base_address) + (cy * fb.stride) + cx;
  661.       real_screen_stride = fb.stride;
  662.       fb.p = malloc(320 * 200);
  663.       fb.stride = 320;
  664.    }
  665. #endif
  666. #else
  667.    cy = (rr->bottom - rr->top - 200) / 2;
  668.    cx = (rr->right - rr->left - 320) / 2;
  669.    fb.p = ((u_char *) base_address) + (cy * fb.stride) + cx;
  670. #endif
  671.    fb.width = 320;
  672.    fb.height = 200;
  673.    }
  674. #endif
  675. }
  676. #endif
  677.  
  678. #if vga_bomb
  679. void
  680. init_vga()
  681. {
  682.    vga_modeinfo *modeinfo;
  683.    vga_init();
  684.    vga_setmode(G320x200x256);
  685.    modeinfo = vga_getmodeinfo(G320x200x256);
  686.    fb.p = vga_getgraphmem();
  687.    fb.stride = modeinfo->linewidth;
  688.    fb.width = 320;
  689.    fb.height = 200;
  690. }
  691. #endif
  692.  
  693. #if ogl_bomb || xws_bomb
  694.  
  695. int
  696. screen_number (Screen *screen)
  697. {
  698.   Display *dpy = DisplayOfScreen (screen);
  699.   int i;
  700.   for (i = 0; i < ScreenCount (dpy); i++)
  701.     if (ScreenOfDisplay (dpy, i) == screen)
  702.       return i;
  703.   abort ();
  704. }
  705.  
  706.  
  707. int
  708. visual_class (Screen *screen, Visual *visual)
  709. {
  710.   Display *dpy = DisplayOfScreen (screen);
  711.   XVisualInfo vi_in, *vi_out;
  712.   int out_count, c;
  713.   vi_in.screen = screen_number (screen);
  714.   vi_in.visualid = XVisualIDFromVisual (visual);
  715.   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
  716.                &vi_in, &out_count);
  717.   if (! vi_out) abort ();
  718.   c = vi_out [0].class;
  719.   XFree ((char *) vi_out);
  720.   return c;
  721. }
  722.  
  723.  
  724. int
  725. visual_depth (Screen *screen, Visual *visual)
  726. {
  727.   Display *dpy = DisplayOfScreen (screen);
  728.   XVisualInfo vi_in, *vi_out;
  729.   int out_count, d;
  730.   vi_in.screen = screen_number (screen);
  731.   vi_in.visualid = XVisualIDFromVisual (visual);
  732.   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
  733.                &vi_in, &out_count);
  734.   if (! vi_out) abort ();
  735.   d = vi_out [0].depth;
  736.   XFree ((char *) vi_out);
  737.   return d;
  738. }
  739.  
  740.  
  741. init_x()
  742. {
  743.   Screen *scrn;
  744.   XSetWindowAttributes attr;
  745.   XWindowAttributes xgwa;
  746.   XGCValues argh;
  747.   int fb_sz;
  748.   unsigned long valuemask;
  749.   disp = XOpenDisplay(NULL);
  750.   if (NULL == disp) {
  751.     fprintf(stderr, "couldn't open display.\n");
  752.     exit(1);
  753.   }
  754.   scrn = DefaultScreenOfDisplay(disp);
  755. #if ogl_bomb
  756.   if (1) {
  757.     int attrs[] = {None};
  758.     vl = glXChooseVisual(disp, 0, attrs);
  759.     if (NULL == vl) {
  760.       fprintf(stderr, "couldn't find GLX visual.\n");
  761.       exit(1);
  762.     }
  763.   }
  764. #endif
  765.   visual = DefaultVisualOfScreen (scrn);
  766.   attr.event_mask = KeyPressMask;
  767.   valuemask = CWEventMask;
  768.   if (PseudoColor == visual_class(scrn, visual)) {
  769.     xws_cmap = XCreateColormap(disp, RootWindowOfScreen(scrn),
  770.                    visual, AllocAll);
  771.     valuemask |= CWColormap;
  772.     attr.colormap = xws_cmap;
  773.   }
  774.   win = XCreateWindow(disp,
  775.               RootWindowOfScreen(scrn),
  776.               (WidthOfScreen(scrn)-pix_rep*320)/2,
  777.               (HeightOfScreen(scrn)-pix_rep*200)/2,
  778.               pix_rep*320, pix_rep*200, 5, CopyFromParent,
  779.               InputOutput, visual, valuemask, &attr);
  780.   XMapWindow(disp, win);
  781.   depth = visual_depth(DefaultScreenOfDisplay(disp), visual);
  782.  
  783. #if xws_bomb
  784.   argh.function = GXcopy;
  785.   gc = XCreateGC(disp, win, GCFunction, &argh);
  786.   fb_bpp = ((8 == depth) ? 1 : (16 == depth) ? 2 : 4);
  787. #else
  788.   fb_bpp = 1;
  789. #endif
  790.   fb_sz = 320 * 200 * fb_bpp;
  791.   fb.p = malloc(fb_sz);
  792.   fb.stride = 320;
  793.   fb.width = 320;
  794.   fb.height = 200;
  795.  
  796. #if xws_bomb
  797.   {
  798.     if (1 == pix_rep && fb_bpp == 1)
  799.       image_buf = (char *) fb.p;
  800.     else
  801.       image_buf = malloc(320 * 200 * pix_rep * pix_rep * fb_bpp);
  802.     xws_image = XCreateImage(disp, visual, depth,
  803.                  ZPixmap, 0, image_buf,
  804.                  pix_rep*320, pix_rep*200, 8, 0);
  805.   }
  806. #endif
  807. #if ogl_bomb
  808.   if (1) {
  809.     GLXContext cx;
  810.     cx = glXCreateContext(disp, vl, 0, GL_TRUE);
  811.     glXMakeCurrent(disp, win, cx);
  812.     glRasterPos2f(-1.0, -1.0);
  813.     glPixelZoom(pix_rep, pix_rep);
  814.   }
  815. #endif
  816.   delay = 3.5;
  817. }
  818. #endif
  819.  
  820. void
  821. init()
  822. {
  823.    int i;
  824.    long t;
  825.  
  826.    printf("bomb v1.18\n");
  827.  
  828.    init_random();
  829.  
  830. #if vga_bomb && xws_bomb
  831.    if (getenv("DISPLAY")) {
  832.      running_x = 1;
  833.      init_x();
  834.    } else {
  835.      running_x = 0;
  836.      init_vga();
  837.    }
  838. #else
  839. #if vga_bomb
  840.    init_vga();
  841. #endif
  842. #if ogl_bomb|xws_bomb
  843.    init_x();
  844. #endif
  845. #endif
  846.  
  847.    stabilize_fps = (int) getenv("fps");
  848.    fps = 10.0; // just a guess
  849.  
  850.    gparam = &rule.speed;
  851.  
  852.    init_sound();
  853.    begin_timer();
  854.  
  855.    for (i = 0; i < status_string_length; i++)
  856.        status_string[i] = ' ';
  857.  
  858. #ifndef win_saver
  859.    if (!use_guile) {
  860.       char s[1000];
  861.       int r, i = 0;
  862.       do {
  863.      sprintf(s, "%stitle%d.tif", DATA_DIR, i++);
  864.      r = load_title(s);
  865.      if (1 == r)
  866.         while (0 == bomb_getkey());
  867.       } while (r);
  868.       sprintf(s, "%stitle.tif", DATA_DIR);
  869.       load_title(s);
  870.       load_title("title.tif");
  871.    }
  872. #endif
  873.     init_masks();
  874.     init_rotor();
  875.     init_images();
  876.     init_seq();
  877.     init_cmaps();
  878.  
  879. #if use_mpeg
  880.     mpeg_init();
  881. #endif
  882.  
  883.    distrib(distrib_new, &rule, &cmap, &fill2);
  884.    rule.drift_time = 0.0;
  885.    drive_with_image(current_image);
  886.  
  887. #ifndef win_saver
  888.    /* start out with basically the same rule */
  889.    rule.rule = rule_rug;
  890.    rule.speed = -1;
  891.    rule.speed_base = -1;
  892.    rule.mask = 255;
  893.    rule.remap = 0;
  894.    rule.randomized_underflow = 1;
  895.    rule.speed_beat_size = sound_present ? 7 : 0;
  896.    cmap.cmap = cmap_plain;
  897.    cmap.index = 4%ncmaps;
  898.    fade2cmap(&cmap);
  899.    pix2heat(&fb, &board[dbuf]);
  900. #else
  901.    fade2cmap(&cmap);
  902.    image8_set_cmap(0, 256, target_cmap);
  903.    fill_board(&fill2);
  904. #endif
  905.    set_remap(rule.mask, rule.remap);
  906.    delayed_fill = 0;
  907.  
  908.    /* this forces the next several rule changes */
  909.    auto_rule = 4;
  910.  
  911.    // while (0 == bomb_getkey());
  912. }
  913.  
  914. int
  915. rule_symmetry(int rule)
  916. {
  917.    int r;
  918.    switch (rule) {
  919.     case rule_rd: r = sym_tile4_stack2; break;
  920.     case rule_wave:
  921.     case rule_rug_brain:
  922.     case rule_rug_anneal: 
  923.     case rule_rug_anneal2: r = sym_tile4; break;
  924.     case rule_acidlife2: r = sym_mirror4; break;
  925.     case rule_acidlife1: r = sym_mirror2; break;
  926.     case rule_fuse:
  927.     case rule_slip: r = sym_frame_buffer; break;
  928.     case rule_static: /* false, but useful */
  929.     default:
  930.       r = sym_one; break;
  931.    }
  932.    return r;      
  933. }
  934.  
  935. void
  936. change_rules(int old, int new, image8_t *fb)
  937. {
  938.    int old_sym = rule_symmetry(old);
  939.    int new_sym = rule_symmetry(new);
  940.  
  941.    if (new == rule_rug_image && old != new) {
  942.       drive_with_image(current_image);
  943.    }
  944.    if (old_sym == new_sym)
  945.       return;
  946.    if (sym_frame_buffer == old_sym) {
  947.       pix2heat(fb, &board[dbuf]);
  948.       old_sym = sym_one;
  949.    }
  950.    change_rules2(old_sym, new_sym, &board[dbuf]);
  951.    change_rules2(old_sym, new_sym, &board2[dbuf]);
  952.    /* some of the rules don't copy board2
  953.       rug_rug is always going to fail sometimes until
  954.       dbuf/frame&1 is resolved XXX */
  955.    change_rules2(old_sym, new_sym, &board2[1-dbuf]);
  956. }
  957.  
  958. static last_rec_event = 0;
  959.  
  960. void
  961. record1(char *s, int *n, int nv)
  962. {
  963.   if (*n == nv) return;
  964.  
  965.   if (recording &&
  966.       frame != last_rec_event) {
  967.     fprintf(recording, "(frame %d)\n", frame - last_rec_event);
  968.     last_rec_event = frame;
  969.   }
  970.   *n = nv;
  971.   if (recording) {
  972.     fprintf(recording, "(%s %d)\n", s, nv);
  973.   }
  974. }
  975.  
  976. void
  977. distrib(int dist, rule_t *rulep, cmap_t *cmap, fill_t *fill)
  978. {
  979.    int x, b, i, nbits, nv;
  980.    if (rulep) {
  981.       static int distrib[] =
  982.       {rule_rug, rule_rd, rule_rug_brain, rule_rotorug, rule_rug_image};
  983.       if (!(distrib_continuous & dist)) {
  984.      init_rotate();
  985.      init_shade();
  986.      init_wave();
  987.      if (!(distrib_rule_lock & dist)) {
  988.        do {
  989.          if (auto_rule) {
  990.            nv = distrib[auto_rule%alen(distrib)];
  991.            auto_rule--;
  992.          } else {
  993.            nv = (R%2) ? (R%nrules) : distrib[R%alen(distrib)];
  994.          }
  995.        } while (0 == (rule_mask & (1 << nv)));
  996.        record1("rule", &rulep->rule, nv);
  997.      }
  998.      record1("cycle-bkg", &rulep->cycle_bkg, (0 == R%10));
  999.      record1("brain", &rulep->brain, R);
  1000.      if (high_growth_game(rulep)) {
  1001.         delayed_fill = 1;
  1002.      }
  1003.      if (rule_rug_brain == rulep->rule)
  1004.         record1("brain-shift", &rulep->brain_shift, (R%4) ? 0 : ((R%3) ? (R%5) : (R%25)));
  1005.      else
  1006.         record1("brain-shift", &rulep->brain_shift, R);
  1007.      random_control_point(&rulep->flame_cp);
  1008.      for (i = 0; i < flame_nspan; i++)
  1009.        random_control_point(rulep->flame_span+i);
  1010.      if (auto_rule) {
  1011.         int i, j;
  1012.         static int best[] = {0, 1, 2, 5};
  1013.         int v = best[R%alen(best)];
  1014.         for (i = 0; i < NXFORMS; i++) {
  1015.            for (j = 0; j < NVARS; j++)
  1016.           rulep->flame_cp.xform[i].var[j] = 0.0;
  1017.            rulep->flame_cp.xform[i].var[v] = 1.0;
  1018.         }        
  1019.      }
  1020.      pick_liss_coefs();
  1021.  
  1022.      if (auto_rule) {
  1023.         record1("drift", &rulep->drift, 4);
  1024.      } else if (rule_fuse == rulep->rule)
  1025.         record1("drift", &rulep->drift, (R%5) ? (R%2) : ((R%2)+2));
  1026.      else
  1027.         record1("drift", &rulep->drift, R);
  1028.      rulep->image_window_size = 2 + R%5;
  1029.      rulep->speed_beat_speed = (R%3) ? (5 + R%10) : (30 + R%30);
  1030.      if ((sound_present && (R%3)) || 0 == (R%3))
  1031.         rulep->speed_beat_size = (R%2) ? (4 + R%12) : (10 + R%22);
  1032.      else
  1033.         rulep->speed_beat_size = 0;
  1034.      rulep->seq[0] = R;
  1035.      seq_start(rulep->seq);
  1036.      p1 = R;
  1037.      current_image = R;
  1038.       }
  1039.       rulep->fastflip_rate = ((R&1) ? 0 :
  1040.                   ((R&1) ? (R%5) :
  1041.                    (5+(R%20))));
  1042.       if (1) {
  1043.          int rbase = 4 + R%8;
  1044.          for (i = 0; i < MAXRHYTHM; i++)
  1045.         rulep->rhythm[i] = (R%3 + 1)*rbase;
  1046.       }
  1047.       rulep->bsize = (R%4) ? (20 + R%20 + R%20) : (60 + R%80);
  1048.       rulep->randomized_underflow = R&1;
  1049.       rulep->search_time = 2 + R%5;
  1050.       if (R%2) {
  1051.      rulep->hot = 200;
  1052.      rulep->cool = 5 + R%20 + R%20;
  1053.       } else {
  1054.      rulep->hot = 1 + 5 * (R%3);
  1055.      rulep->cool = 5 + R%20 + R%10 + rulep->hot;
  1056.       }
  1057.       if ((distrib_original & dist) ||
  1058.       rule_acidlife1 == rulep->rule ||
  1059.       rule_acidlife2 == rulep->rule ||
  1060.       rule_rotorug == rulep->rule) {
  1061.      nbits = R%7 + 8;
  1062.      rulep->mask = (1<<nbits) - 1;
  1063.      for (b = R%4; b; b--)
  1064.         rulep->mask &= ~(2<<(R%nbits));
  1065.       } else {
  1066.      nbits = 8 + (R%3 + 1) * (R%2 + 1);
  1067.      rulep->mask = (1<<nbits) - 1;
  1068.      for (b = R%3 + 1; b; b--)
  1069.         rulep->mask &= ~(2<<(R%nbits));
  1070.       }
  1071.  
  1072.       switch (rulep->rule) {
  1073.        case rule_acidlife1:
  1074.      x = -(1 + (rulep->mask/100) + R%(rulep->mask/30));
  1075.      break;
  1076.        case rule_acidlife2:
  1077.      x = -(R%20);
  1078.      break;
  1079.        case rule_rotorug:
  1080.      x = -(9 + R%(rulep->mask/30));
  1081.      break;
  1082.        case rule_wave:
  1083.      x = -(10 + R%10);
  1084.      break;
  1085.        default:
  1086.      if (distrib_original & dist)
  1087.         x = -(9 + R%(rulep->mask/30));
  1088.      else
  1089.         x = -1;
  1090.      break;
  1091.       }
  1092.       rulep->speed_base = x;
  1093.       rulep->speed = x;
  1094.  
  1095.       if (R%4)
  1096.      rulep->driver_slowdown = 1 + R%8 + R%7;
  1097.       else
  1098.      rulep->driver_slowdown = 13 + R%8;
  1099.  
  1100.  
  1101.       rulep->drift_speed = 8 + R%5;
  1102.       rulep->remap = R%4;
  1103.  
  1104.       set_remap(rulep->mask, rulep->remap);
  1105.    
  1106.    }
  1107.    if (cmap) {
  1108.      int nc;
  1109.       static distrib0[] = {cmap_plain, cmap_plain, cmap_plain,
  1110.                cmap_loop, cmap_path, cmap_path};
  1111.       static distrib[] = {cmap_mono, cmap_mono, cmap_mono4, cmap_heat};
  1112.       static distrib1[] = {cmap_mono, cmap_ramp, cmap_plain};
  1113.       if (rule.rule == rule_fuse) {
  1114.     nc = distrib1[R%alen(distrib1)];
  1115.       } else if (rule.rule == rule_acidlife1)
  1116.      nc = cmap_split;
  1117.       else if ((rule.rule == rule_rd) && (R&1))
  1118.      nc = cmap_path;
  1119.       else if ((rule.rule == rule_rd2) ||
  1120.            (rule.rule == rule_quad))
  1121.     nc = cmap_plain;
  1122.       else if (R%7)
  1123.      nc = distrib0[R%alen(distrib0)];
  1124.       else if (R%100)
  1125.      nc = distrib[R%alen(distrib)];
  1126.       else
  1127.      nc = cmap_noise;
  1128.  
  1129.       record1("color-type", &cmap->cmap, nc);
  1130.       record1("color" , &cmap->index,  R%ncmaps);
  1131.  
  1132.       cmap->index2 = R%ncmaps;
  1133.    }
  1134.    if (fill) {
  1135.       static distrib[] = {fill_vnoise, fill_noise};
  1136.       if (rule.rule == rule_rd ||
  1137.           rule.rule == rule_rd2 ||
  1138.           R%2)
  1139.         fill->fill = distrib[R%alen(distrib)];
  1140.       else
  1141.         fill->fill = R%nfills;
  1142.    }
  1143. }
  1144.  
  1145. double adjust_speed(double dt) {
  1146.     return dt * 10.0 / fps;
  1147. }
  1148.  
  1149. void print_state(rule_t *r) {
  1150.    printf("rule=%d\n", r->rule);
  1151.    printf("speed=%d\n", r->speed);
  1152.    printf("mask=%d\n", r->mask);
  1153.    printf("randomized_underflow=%d\n", r->randomized_underflow);
  1154.    printf("cycle_bkg=%d\n", r->cycle_bkg);
  1155.    printf("remap=%d\n", r->remap);
  1156.    printf("floor=%d\n", r->floor);
  1157.    printf("driver_slowdown=%d\n", r->driver_slowdown);
  1158.    printf("brain=%d (%d)\n", r->brain, iclamp(r->brain, 44));
  1159.    printf("brain_shift=%d (%d)\n", r->brain_shift, iclamp(r->brain_shift, 26));
  1160.    printf("hot=%d\n", r->hot);
  1161.    printf("cool=%d\n", r->cool);
  1162.    printf("speed_base=%d\n", r->speed_base);
  1163.    printf("speed_beast_speed=%d\n", r->speed_beat_speed);
  1164.    printf("speed_beat_size=%d\n", r->speed_beat_size);
  1165.    printf("drift=%d (%d)\n", r->drift, iclamp(r->drift, 9));
  1166.    printf("drift_speed=%d\n", r->drift_speed);
  1167.    printf("bsize=%d\n", r->bsize);
  1168.    
  1169.    printf("p1=%d\n", p1);
  1170.    printf("cmap=%d\n", cmap.index);
  1171. }
  1172.    
  1173.  
  1174.  
  1175. flip_image(int rule_lock)
  1176. {
  1177.    /* Z = zxC-b */ /* at one point, that meant something */
  1178.    int im = seq_next_image(rule.seq);
  1179.    file_to_image(im, current_image);
  1180.    distrib(distrib_new | distrib_continuous | rule_lock, &rule, 0, &fill2);
  1181.    fill_board(&fill2);
  1182. }
  1183.  
  1184. int grad_state;
  1185. #if 0
  1186.  
  1187. int grad_step(int steps) {
  1188.    int res;
  1189.    /* fprintf(stderr, "gs%d ", grad_state); */
  1190.    if (0 == grad_state)
  1191.       return 1;
  1192.    else if (grad_none == grad_state) {
  1193.       grad_state = steps;
  1194.    } else if (1 == grad_state ||
  1195.           9 == ((steps - grad_state)%10)) {
  1196.       image2grad(&board2[dbuf], &board3[0], 1);
  1197.    } else {
  1198.       blur(&board2[dbuf], &board2[1-dbuf]);
  1199.    }
  1200.  
  1201.    grad_state--;
  1202.    res = ((steps - grad_state) > 10)
  1203.       || (0 == grad_state);
  1204.    fprintf(stderr, " %d ", res);
  1205.    return res;
  1206. }
  1207. #endif
  1208.  
  1209.  
  1210. cmap_permute_bits()
  1211. {
  1212.    int i;
  1213.    for (i = 0; i < 256; i++) {
  1214.       int j = (i >> 1) | ((i&1) << 7);
  1215.       int r = current_cmap[3*j+0];
  1216.       int g = current_cmap[3*j+1];
  1217.       int b = current_cmap[3*j+2];
  1218.       SET_TARGET_PALETTE(i, r, g, b);
  1219.    }
  1220. }
  1221.  
  1222. #define Rz(d,n) if (n <= 0) return; else d = R%(n)
  1223.  
  1224. image_to_heat(Image *src_img, image8_t *fb, board_t *board)
  1225. {
  1226.    int bsize = rule.bsize;
  1227.    int dest_x, dest_y;
  1228.    Image src_rect;
  1229.    image8_t dest = *fb;
  1230.    int move_heat = 1;
  1231.  
  1232.    switch (rule_symmetry(rule.rule)) {
  1233.     case sym_tile4:
  1234.     case sym_mirror4:
  1235.       Rz(dest_x, (fb->width>>1) - bsize);
  1236.       Rz(dest_y, (fb->height>>1) - bsize);
  1237.       break;
  1238.     case sym_mirror2:
  1239.       Rz(dest_x, (fb->width>>1) - bsize);
  1240.       Rz(dest_y, fb->height - bsize);
  1241.       break;
  1242.     case sym_frame_buffer:
  1243.       move_heat = 0;
  1244.     default:
  1245.       Rz(dest_x, fb->width - bsize);
  1246.       Rz(dest_y, fb->height - bsize);
  1247.       break;
  1248.    }
  1249.    image_random_tile(&src_rect, src_img, bsize);
  1250.    dest.p = fb->p + fb->stride * dest_y + dest_x;
  1251.    dest.width = src_rect.width;
  1252.    dest.height = src_rect.height;
  1253.    /* could be any operation here, not just copy */
  1254.    if (1) {
  1255.       int i, j;
  1256.       for (i = 0; i < src_rect.height; i++)
  1257.      for (j = 0; j < src_rect.width; j++)
  1258.         dest.p[dest.stride * i + j] =
  1259.            255 - src_rect.pixels[src_rect.stride * i + j].r;
  1260.    }
  1261.  
  1262.    if (move_heat)
  1263.       pix2heat2(fb, board,
  1264.         dest_x, dest_y,
  1265.         dest_x + src_rect.width, dest_y + src_rect.height);
  1266. }
  1267.  
  1268.  
  1269. Image *pick_image(rule_t *p)
  1270. {
  1271.    Image *r;
  1272.    int n = iclamp(R, p->image_window_size);
  1273.  
  1274.    switch (p->rule) {
  1275.     case rule_fuse:
  1276.     case rule_static:
  1277.     case rule_slip:
  1278.       r = &global_images[n];
  1279.       break;
  1280.     default:
  1281.       r = &global_images_small[n];
  1282.       break;
  1283.    }
  1284.    return r;
  1285. }
  1286.       
  1287.  
  1288. void
  1289. changed_gparam(int *gparam)
  1290. {
  1291.    if (&cmap.index == gparam) {
  1292.       cmap.index = iclamp(cmap.index, ncmaps);
  1293.       fade2cmap(&cmap);
  1294.    } else if (&rule.cycle_bkg == gparam ||
  1295.           &rule.remap == gparam ||
  1296.           &rule.randomized_underflow == gparam)
  1297.       *gparam = (*gparam)&1;
  1298.    else if (&rule.image_window_size == gparam) {
  1299.       if (*gparam > N_RAM_IMAGES)
  1300.      *gparam = N_RAM_IMAGES;
  1301.       else if (*gparam < 1)
  1302.      *gparam = 1;
  1303.    } else if (&rule.seq[0] == gparam) {
  1304.       seq_start(rule.seq);
  1305.    }
  1306.    
  1307.    if (&rule.remap == gparam ||
  1308.               &rule.mask == gparam) {
  1309.        set_remap(rule.mask, rule.remap);
  1310.    }
  1311.  
  1312.    /* printf("changed gparam %#x to %d\n", gparam, *gparam); */
  1313. }
  1314.  
  1315.  
  1316. void do_mouse(int x, int y) {
  1317.   switch (rule.rule) {
  1318.      case rule_rotorug:
  1319.         rule.bsize = iclamp(x, 320);
  1320.         if (0) {
  1321.            extern double spinner_time;
  1322.            spinner_time = x + y*10;
  1323.            rule.drift_time = x/32.0 + y;
  1324.         }
  1325.         break;
  1326.      case rule_rug:
  1327.         rule.speed = iclamp(x,320)/8-20;
  1328.         break;
  1329.      case rule_rug_brain:
  1330.         pen(&board2[dbuf], 1, iclamp(x, 160), iclamp(y, 100), 10);
  1331.         break;
  1332.      case rule_rd:
  1333.         pen(&board[dbuf], 0, iclamp(x,160), iclamp(y, 100), 5);
  1334.         break;
  1335.      default:
  1336.         pen(&board[dbuf], rule.mask, iclamp(x,300), iclamp(y,180), 12);
  1337.         break;
  1338.    }
  1339. }
  1340.  
  1341.  
  1342.  
  1343. #if mac_bomb
  1344. static long start_time;
  1345. void begin_timer() {
  1346.   start_time = TickCount();
  1347. }
  1348. double end_timer() {
  1349.   return (TickCount() - start_time) / 60.0; /* just a guess */
  1350. }
  1351. #elif win_bomb
  1352. #else
  1353. #include <sys/time.h>
  1354.  
  1355. static struct timeval start_time;
  1356.  
  1357. void
  1358. begin_timer()
  1359. {
  1360.    struct timezone tzp;
  1361.    gettimeofday(&start_time, &tzp);
  1362. }
  1363.  
  1364. double
  1365. end_timer()
  1366. {
  1367.    static struct timeval end_time;
  1368.    struct timezone tzp;
  1369.    double t;
  1370.    gettimeofday(&end_time, &tzp);
  1371.    return
  1372.       ((end_time.tv_sec - start_time.tv_sec) +
  1373.        (end_time.tv_usec - start_time.tv_usec) * 1e-6);
  1374. }
  1375. #endif
  1376.  
  1377. void step_rule_rug(int frame, rule_t *p, image8_t *fb);
  1378. void step_rule_rug2(int frame, rule_t *p, image8_t *fb);
  1379. void step_rule_static(int frame, rule_t *p, image8_t *fb);
  1380. void step_rule_rotorug(int frame, rule_t *p, image8_t *fb);
  1381. void step_rule_acidlife1(int frame, rule_t *p, image8_t *fb);
  1382. void step_rule_acidlife2(int frame, rule_t *p, image8_t *fb);
  1383. void step_rule_rug_anneal(int frame, rule_t *p, image8_t *fb);
  1384. void step_rule_rug_anneal2(int frame, rule_t *p, image8_t *fb);
  1385. void step_rule_rug_rug(int frame, rule_t *p, image8_t *fb);
  1386. void step_rule_rug_brain(int frame, rule_t *p, image8_t *fb);
  1387. void step_rule_shade(int frame, rule_t *p, image8_t *fb);
  1388. void step_rule_wave(int frame, rule_t *p, image8_t *fb);
  1389. void step_rule_rug_image(int frame, rule_t *p, image8_t *fb);
  1390. void step_rule_slip(int frame, rule_t *p, image8_t *fb);
  1391. void step_rule_fuse(int frame, rule_t *p, image8_t *fb);
  1392. void step_rule_rug_multi(int frame, rule_t *p, image8_t *fb);
  1393. void step_rule_rd(int frame, rule_t *p, image8_t *fb);
  1394. void step_rule_rd2(int frame, rule_t *p, image8_t *fb);
  1395.  
  1396. int self_play_enabled = !use_guile;
  1397.  
  1398. void self_play() {
  1399.  
  1400.   if (!self_play_enabled)
  1401.     return;
  1402.  
  1403.       if (0 >= timer) {
  1404.      auto_mode = 1;
  1405.      if (pop_back) {
  1406.         rule.rule = back_to;
  1407.         pop_back = 0;
  1408.         timer = 100;
  1409.      } else if (permuting) {
  1410.         permuting--;
  1411.         cmap_permute_bits();
  1412.         timer = 150;
  1413.      } else if (flipper && (rule_rug_brain == rule.rule) && (R%10)) {
  1414.         switch (flipper) {
  1415.          case 1:
  1416.            rule.brain++;
  1417.            break;
  1418.          case 2:
  1419.            distrib(distrib_new|distrib_continuous|rule_lock, &rule, 0, 0);
  1420.            break;
  1421.          case 3:
  1422.            rule.brain_shift =
  1423.           (R%8) ? (rule.brain_shift + ((R&1) ? -1 : 1)) : 0;
  1424.            break;
  1425.         }
  1426.         timer = 50;
  1427.      } else if (flipper && (rule_rug == rule.rule) && (R%5)) {
  1428.         if (2 == flipper) {
  1429.            rule.rule = rule_rug_image;
  1430.            pop_back = 1;
  1431.            back_to = rule_rug;
  1432.            timer = (R%2) ? 4 : 30;
  1433.            current_image = iclamp(current_image + 1,
  1434.                       rule.image_window_size);
  1435.            drive_with_image(current_image);           
  1436.         }
  1437.      } else if (flipper && (rule_rd == rule.rule) && (R%5)) {
  1438.         timer = 100;
  1439.         switch (flipper) {
  1440.          case 1:
  1441.            if (1) {
  1442.           int im = seq_next_image(rule.seq);
  1443.           file_to_image(im, current_image);
  1444.           drive_with_image(current_image);
  1445.            }
  1446.            break;
  1447.          case 2:
  1448.            rule.brain = R;
  1449.            break;
  1450.          case 3:
  1451.            rule.brain_shift = R;
  1452.            break;
  1453.         }
  1454.      } else if (flipper && (rule_fuse == rule.rule) && (R%5)) {
  1455.        rule.drift = (R%5) ? (R%2) : ((R%2)+2);
  1456.        timer = 100;
  1457.      } else if (flipper && (rule_rug_image == rule.rule) && (R%5)) {
  1458.         static here = 0;
  1459.         /* create an echo */
  1460.         if (here = 1-here) {
  1461.            current_image = iclamp(current_image + 1,
  1462.                       rule.image_window_size);
  1463.            drive_with_image(current_image);           
  1464.         }
  1465.         timer = 100;
  1466.         switch (flipper) {
  1467.          case 0:
  1468.            break;
  1469.          case 1:
  1470.            if (1) {
  1471.           int im = seq_next_image(rule.seq);
  1472.           file_to_image(im, current_image);
  1473.           drive_with_image(current_image);
  1474.            }
  1475.            break;
  1476.          case 2:
  1477.            flip_image(rule_lock);
  1478.            break;
  1479.          case 3:
  1480.            rule.rule = rule_rug;
  1481.            pop_back = 1;
  1482.            back_to = rule_rug_image;
  1483.            timer = (R%2) ? 4 : 30;
  1484.            break;
  1485.         }
  1486.      } else if (flipper && (rule_rotorug == rule.rule) && (R%5)) {
  1487.         timer = 100;
  1488.         switch (flipper) {
  1489.          case 1:
  1490.            p1 = R;
  1491.            rule.flame_cp = flames[iclamp(p1, nflames)];
  1492.            break;
  1493.          case 2:
  1494.            random_control_point(&rule.flame_cp);
  1495.            break;
  1496.         }
  1497.      } else if (flipper && (rule_rug_rug == rule.rule) && (R%5)) {
  1498.         distrib(distrib_new|distrib_continuous|rule_lock, &rule, 0, 0);
  1499.         timer = 200;
  1500.      } else if (R%2 && (frame - cmap_changed) > 200) {
  1501.         /* ugh */
  1502.         if (rule.rule == rule_acidlife1) {
  1503.            cmap.cmap = cmap_split;
  1504.            fade2cmap(&cmap);
  1505.         } else if (rule.rule == rule_quad && R%3) {
  1506.           cmap_permute_bits();
  1507.         } else if (rule.rule == rule_fuse && R%4) {
  1508.            cmap.cmap = cmap_mono;
  1509.            fade2cmap(&cmap);
  1510.         } else {
  1511.            if (frame > 10000 && !(R%20)) {
  1512.           cmap_permute_bits();
  1513.           permuting = 7;
  1514.            } else {
  1515.           distrib(distrib_new, 0, &cmap, 0);
  1516.           fade2cmap(&cmap);
  1517.            }
  1518.         }
  1519.         timer = 300;
  1520.         cmap_changed = frame;
  1521.      } else if (rule.rule == rule_quad && R%4) {
  1522.        rule.brain++;
  1523.        timer = 200;
  1524.      } else if (R%4) {
  1525.         int t = rule_lock;
  1526.         /* this is the same condition as used for overdrive */
  1527.         if (3 == flipper)
  1528.            t |= distrib_rule_lock;
  1529.         distrib(distrib_new | t, &rule, 0, 0);
  1530.         timer = 300;
  1531.         /* ugh */
  1532.         if (rule.rule == rule_acidlife1) {
  1533.            cmap.cmap = cmap_split;
  1534.            fade2cmap(&cmap);
  1535.         }
  1536.      } else {
  1537.         if (rule.rule == rule_rd ||
  1538.             rule.rule == rule_rd2) {
  1539.             timer = 100;
  1540.         } else {
  1541.             distrib(distrib_new, 0, 0, &fill2);
  1542.             delayed_fill = 1;
  1543.             timer = 300;
  1544.         }
  1545.      }
  1546.      if (rule.rule == rule_quad) {
  1547.        timer = timer / 4;
  1548.        }
  1549.      flipper = (frame >> 7) & 0x3;
  1550.      if (!(R%20))
  1551.         overdrive_speed = 5 + R%10 + R%20;
  1552.      if (3 == flipper && !auto_rule)
  1553.         timer = overdrive_speed;
  1554.       }
  1555.  
  1556.       if (auto_mode && !(R%500)) image_dst = !image_dst;
  1557.       if (auto_mode && !(frame%1000)) {
  1558.      rule.seq[0] = R;
  1559.      seq_start(rule.seq);
  1560.       }
  1561.  
  1562.       /* i really don't know how much i like this stuff */
  1563.       if (1) {
  1564.      int tween;
  1565.      static int tab1[] = {3000, 200, 100, 50};
  1566.      static int tab2[] = {10000, 200, 100, 50};
  1567.      if (auto_mode)
  1568.         switch (rule.rule) {
  1569.          case rule_slip:
  1570.          case rule_fuse:
  1571.            if (!(R%tab1[image_rate]))
  1572.           image_rate = R&3;
  1573.            break;
  1574.          default:
  1575.            if (frame < 10000)
  1576.           image_rate = 0;
  1577.            else if (!(R%tab2[image_rate]))
  1578.           image_rate = R&3;
  1579.            break;
  1580.         }
  1581.      if (image_rate) {
  1582.         tween = 1 << ((3-image_rate) * 3);
  1583.         if (!(frame%tween)) {
  1584.            if ((3 == flipper2) && (frame > 20000)) {
  1585.           if (image_dst)
  1586.              image_to_heat(pick_image(&rule), &fb, &board[dbuf]);
  1587.           else
  1588.              image_to_heat(pick_image(&rule), &fb, &board2[dbuf]);
  1589.            } else {
  1590.           double_board(image_dst, &board[dbuf], rule_symmetry(rule.rule));
  1591.           if (flipper2&1)
  1592.              image_dst = 1-image_dst;
  1593.            }
  1594.         }
  1595.      }
  1596.       }
  1597.  
  1598. }
  1599.  
  1600. void param_tweeking(int key) {
  1601.            /* parameter tweeking */
  1602.            switch (key) {
  1603.           /* boy this is really dumb */
  1604.         case '0': case '1': case '2': case '3': case '4':
  1605.         case '5': case '6': case '7': case '8': case '9':
  1606.           param = 10 * param + (key - '0');
  1607.           break;
  1608.         case '\n':
  1609.           *gparam = param;
  1610.           param = 0;
  1611.           changed_gparam(gparam);
  1612.           break;
  1613.         case '.':
  1614.         incr:
  1615.           (*gparam)++;
  1616.           changed_gparam(gparam);
  1617.           break;
  1618.         case ',':
  1619.           (*gparam)--;
  1620.           changed_gparam(gparam);
  1621.           break;
  1622.  
  1623. #define dogparm(field) \
  1624.           if (gparam == &(field)) goto incr; gparam = &(field); break;
  1625.  
  1626.         case 'q': dogparm(cmap.index);
  1627.         case 'w': dogparm(rule.speed_beat_size);
  1628.         case 'e': dogparm(rule.speed_beat_speed);
  1629.         case 'r': dogparm(rule.speed_base);
  1630.         case 't': dogparm(rule.image_window_size);
  1631.         case 'y': dogparm(rule.seq[0]);
  1632.         case 'u': dogparm(rule.remap);
  1633.           /* should skip patterns without enough bits */
  1634.         case 'i': dogparm(rule.mask);
  1635.         case 'o': dogparm(p1); break;
  1636.         case 'p': dogparm(rule.bsize);
  1637.         case '[':
  1638.         case ']': dogparm(rule.driver_slowdown);
  1639.         case '\\':dogparm(rule.search_time);
  1640.         case '{': dogparm(rule.hot);
  1641.         case '}': dogparm(rule.cool);
  1642.         case '|': dogparm(rule.brain);
  1643.         case 'P': dogparm(rule.brain_shift);
  1644.         case 'O': dogparm(rule.cycle_bkg);
  1645.         case 'I': dogparm(rule.randomized_underflow);
  1646.         case 5:   dogparm(rule.fastflip_rate);
  1647.  
  1648.  
  1649.         case 'a':
  1650.           if (rule_rug == rule.rule)
  1651.              rule.rule = rule_rug2;
  1652.           else if (rule_rug2 == rule.rule)
  1653.              rule.rule = rule_rug3;
  1654.           else
  1655.              rule.rule = rule_rug;
  1656.           break;
  1657.         case 's':
  1658.           rule.rule = rule_rug_image;
  1659.           break;
  1660.         case 'd':
  1661.           if (rule.rule == rule_rd)
  1662.               rule.rule = rule_rd2;
  1663.           else
  1664.               rule.rule =  rule_rd;
  1665.           break;
  1666.         case 'f':
  1667.           if (rule.rule == rule_rotorug)
  1668.              rule.drift++;
  1669.           else
  1670.              rule.rule = rule_rotorug;
  1671.           break;
  1672.         case 'g':
  1673.           if (rule.rule == rule_acidlife2)
  1674.              rule.rule = rule_acidlife1;
  1675.           else
  1676.              rule.rule = rule_acidlife2;
  1677.           break;
  1678.         case 'h':
  1679.           rule.rule = rule_rug_multi;
  1680.           break;
  1681.         case 'j':
  1682.           if (rule.rule == rule_rug_anneal)
  1683.              rule.rule = rule_rug_anneal2;
  1684.           else
  1685.              rule.rule = rule_rug_anneal;
  1686.           break;
  1687.         case 'k':
  1688.           rule.rule = rule_slip;
  1689.           break;
  1690.         case 'l':
  1691.           rule.rule = rule_rug_rug;
  1692.           break;
  1693.         case ';':
  1694.           rule.rule = rule_rug_brain;
  1695.           break;
  1696.         case '\'':
  1697.           if (rule.rule == rule_shade)
  1698.              rule.rule = rule_wave;
  1699.           else
  1700.              rule.rule = rule_shade;
  1701.           break;
  1702.         case 'A':
  1703.           rule.rule = rule_static;
  1704.           break;
  1705.  
  1706.         case 'F':
  1707.           if (rule.rule == rule_fuse)
  1708.              rule.drift++;
  1709.           else
  1710.              rule.rule = rule_fuse;
  1711.           break;
  1712.            case 'G':
  1713.          rule.rule = rule_quad;
  1714.          break;
  1715.         case 'L':
  1716.           rule_lock = rule_lock ? 0 : distrib_rule_lock;
  1717.           break;
  1718.  
  1719.         case 'z':
  1720.           distrib(distrib_new | distrib_continuous | rule_lock, &rule, 0, 0);
  1721.           break;
  1722.         case 'x':
  1723.           if (rule_fuse == rule.rule)
  1724.             scramble += 4;
  1725.           else {
  1726.             distrib(distrib_new, 0, 0, &fill2);
  1727.             delayed_fill = 1;
  1728.           }
  1729.           break;
  1730.         case 'c':
  1731.           distrib(distrib_new, 0, &cmap, 0);
  1732.           fade2cmap(&cmap);
  1733.           break;
  1734.         case 'v':
  1735.           switch (rule.rule) {
  1736.           case rule_rug:
  1737.           case rule_rug2:
  1738.             bomb_pulse();
  1739.             break;
  1740.           case rule_rug_image:
  1741.             current_image = iclamp(current_image + 1,
  1742.                        rule.image_window_size);
  1743.             drive_with_image(current_image);
  1744.             break;
  1745.           case rule_rug_rug:
  1746.             bomb_pulse_driver();
  1747.             break;
  1748.           case rule_rotorug:
  1749.             if (1) {
  1750.               int i;
  1751.               random_control_point(&rule.flame_cp);
  1752.               for (i = 0; i < flame_nspan; i++)
  1753.             random_control_point(rule.flame_span+i);
  1754.               pick_liss_coefs();
  1755.               init_rotate();
  1756.               for (i = 0; i < MAXRHYTHM; i++)
  1757.             rule.rhythm[i] = (R%3 + 1)*8;
  1758.             }
  1759.             break;
  1760.           default:
  1761.             rule.brain++;
  1762.             break;
  1763.           case rule_fuse:
  1764.             rotate_images();
  1765.             file_to_image(seq_next_image(rule.seq), 0);
  1766.             break;
  1767.           }
  1768.           break;
  1769.         case 'b':
  1770.           switch (rule.rule) {
  1771.           case rule_rug_brain:
  1772.             rule.brain_shift = rule.brain_shift ? 0 : (R%7);
  1773.             break;
  1774.           case rule_rug_multi:
  1775.             rule.brain_shift++;
  1776.             break;
  1777.           default:
  1778.           case rule_rd:
  1779.             /* maybe this should use seq_next_image, or at least
  1780.                we want the capability (maybe use m) */
  1781.             file_to_image(p1++, current_image);
  1782.             drive_with_image(current_image);
  1783.             break;
  1784.           }
  1785.           break;
  1786.         case 'n':
  1787.           rule.speed_beat_size = rule.speed_beat_size ? 0 : (R%22);
  1788.           rule.speed_beat_speed = (R%3) ? (5 + R%10) : (30 + R%30);
  1789.           break;
  1790.         case 'm':
  1791.           if (rule_rug_image == rule.rule) {
  1792.              int im = seq_next_image(rule.seq);
  1793.              file_to_image(im, current_image);
  1794.              drive_with_image(current_image);
  1795.           } else
  1796.              rule.brain_shift++;
  1797.           break;
  1798.          
  1799.         case '/':
  1800.           drive_with_image(current_image);
  1801.           break;
  1802.         case '?':
  1803. #if vga_bomb
  1804.           vga_setmode(TEXT);
  1805.           system("/usr/bin/less manual.txt");
  1806.           vga_setmode(G320x200x256);
  1807.           image8_set_cmap(0, 256, current_cmap);
  1808. #endif
  1809.           break;
  1810.         case '-':
  1811.           *gparam = - (*gparam);
  1812.           changed_gparam(gparam);
  1813.           break;
  1814.         case '=':
  1815.           write_fb_ppm(&fb);
  1816.           break;
  1817.         case 22: /* ^V */
  1818. #if use_mpeg
  1819.           if (periodic_write) {
  1820.              mpeg_end();
  1821.              periodic_write = 0;
  1822.           } else {
  1823.              char buf[20];
  1824.              sprintf(buf, "dribble/%03d.mpg", frame);
  1825.              mpeg_begin(320, 200, buf);
  1826.              periodic_write = 1;
  1827.           }
  1828. #else
  1829.           periodic_write = 10 - periodic_write;
  1830. #endif
  1831.           break;
  1832.         case 'Z':
  1833.           flip_image(rule_lock);
  1834.           break;
  1835.         case 'X':
  1836.           /* X = zcm */
  1837.           distrib(distrib_new | distrib_continuous | rule_lock, &rule, &cmap, 0);
  1838.           init_rotate();
  1839.           if (rule.rule == rule_acidlife1)
  1840.              cmap.cmap = cmap_split;
  1841.           fade2cmap(&cmap);
  1842.           random_control_point(&rule.flame_cp);
  1843.           pick_liss_coefs();
  1844.           break;
  1845.         case 'Q':
  1846.           timer = 10;
  1847.           break;
  1848.         case 'W':
  1849.           pulse_cmap_white();
  1850.           break;
  1851.         case 'E':
  1852.           pulse_cmap_black();
  1853.           break;
  1854.         case 'R':
  1855.           pulse_cmap_rotate();
  1856.           break;
  1857.         case 'T':
  1858.           brighten_cmap();
  1859.           break;
  1860.         case 'D':
  1861.           cmap_permute_bits();
  1862.           break;
  1863.         case 'V':
  1864.           rule.brain = 0;
  1865.           rule.brain_shift = 0;
  1866.           rule.drift--;
  1867.           break;
  1868.         case 'C':
  1869.           invert_board();
  1870.           break;
  1871.         case 'N':
  1872.           if (1) {
  1873.              extern smooth_checkers;
  1874.              smooth_checkers = 1;
  1875.           }
  1876.           break;
  1877.         case 'S':
  1878.           switch (cmap.cmap) {
  1879.           case cmap_plain: cmap.cmap = cmap_loop; break;
  1880.           case cmap_loop: cmap.cmap = cmap_path; break;
  1881.           case cmap_path: cmap.cmap = cmap_plain; break;
  1882.           }
  1883.           fade2cmap(&cmap);
  1884.           break;
  1885.         case 'Y':
  1886.           cool(&fb);
  1887.           break;
  1888.         case 'U':
  1889.           warm(&fb);
  1890.           break;
  1891.         case 'H':
  1892.           double_board(1, &board[dbuf], rule_symmetry(rule.rule));
  1893.           break;
  1894.         case 'J':
  1895.           double_board(0, &board[dbuf], rule_symmetry(rule.rule));
  1896.           break;
  1897.         case 2:        /* ^B */
  1898.           rotate_images();
  1899.           file_to_image(R, current_image);
  1900.           drive_with_image(current_image);
  1901.          break;
  1902.         case 15:    /* ^O */
  1903.           rotate_images();
  1904.           file_to_image(R, 0);
  1905.           break;
  1906.         case 26:    /* ^Z */
  1907.           random_image_set();
  1908.           break;
  1909.         case 14:    /* ^N */
  1910.           if (recording) {
  1911.             fclose(recording);
  1912.             recording = NULL;
  1913.           } else {
  1914.             char buf[30];
  1915.             sprintf(buf, "clip-%02d.scm", nrecords++);
  1916.             recording = fopen(buf, "w");
  1917.             if (!recording)
  1918.               perror("fopen");
  1919.           }
  1920.           break;
  1921.         case 'M':
  1922.           rule.flame_cp = flames[iclamp(p1, nflames)];
  1923.           break;
  1924.         case 9:        /* ^I */
  1925.           image_to_heat(pick_image(&rule), &fb, &board[dbuf]);
  1926.           image_dst = 1;
  1927.           break;
  1928.         case 21:    /* ^U */
  1929.           image_to_heat(pick_image(&rule), &fb, &board2[dbuf]);
  1930.           image_dst = 0;
  1931.           break;
  1932.         case 25:    /* ^Y */
  1933.           image_rate = (image_rate+1)&0x3;
  1934.           break;
  1935.  
  1936.           /*
  1937.             for rbd's ballet music
  1938.            case 'P':
  1939.          rule.speed = -1;
  1940.          rule.speed_base = -1;
  1941.          rule.mask = 767;
  1942.          rule.driver_slowdown = 9;
  1943.          cmap.cmap = cmap_loop;
  1944.          fade2cmap(&cmap);
  1945.          break;
  1946.            case 'O':
  1947.          rule.speed = -1;
  1948.          rule.speed_base = -1;
  1949.          rule.mask = 1023;
  1950.          rule.driver_slowdown = 60;
  1951.          cmap.cmap = cmap_plain;
  1952.          cmap.index = 58;
  1953.          fade2cmap(&cmap);
  1954.          break;
  1955.            case 'K':
  1956.          cmap.cmap = cmap_mono;
  1957.          fade2cmap(&cmap);
  1958.          break;
  1959.            case 'J':
  1960.          cmap.cmap = cmap_heat;
  1961.          fade2cmap(&cmap);
  1962.          break;
  1963.          */
  1964.         case 'B':
  1965.           cmap.cmap = cmap_black;
  1966.           fade2cmap(&cmap);
  1967.           break;
  1968.         case 18:    /* ^R */
  1969.           dtime++;
  1970.           if (dtime == 8)
  1971.              dtime = 1;
  1972.           break;
  1973.         
  1974.         default:
  1975.           printf("unknown key = %d\n", key);
  1976.           break;
  1977.            }
  1978. }
  1979.  
  1980. void mood_organ(int key) {
  1981.            switch (key) {
  1982.         case 'a':
  1983.           rule.rule = rule_rug;
  1984.           rule.speed = -1;
  1985.           rule.speed_base = -1;
  1986.           rule.mask = 255;
  1987.           rule.remap = 0;
  1988.           rule.randomized_underflow = 1;
  1989.           rule.speed_beat_size = 0;
  1990.           rule.hot = 1;
  1991.           rule.cool = 100;
  1992.           cmap.cmap = cmap_plain;
  1993.           fade2cmap(&cmap);
  1994.           break;
  1995.         case 'b':
  1996.           rule.rule = rule_rug_image;
  1997.           rule.speed = -1;
  1998.           rule.mask = 255;
  1999.           rule.remap = 0;
  2000.           rule.randomized_underflow = 1;
  2001.           rule.speed_base = -1;
  2002.           rule.speed_beat_size = 10;
  2003.           rule.speed_beat_speed = 50;
  2004.           rule.hot = 1;
  2005.           rule.cool = 100;
  2006.           cmap.cmap = cmap_plain;
  2007.           fade2cmap(&cmap);
  2008.           break;
  2009.         case 'c':
  2010.           rule.rule = rule_rug;
  2011.           rule.speed = -1;
  2012.           rule.speed_base = -1;
  2013.           rule.randomized_underflow = 0;
  2014.           rule.mask = 759;
  2015.           rule.remap = 0;
  2016.           rule.hot = 1;
  2017.           rule.cool = 20;
  2018.           rule.speed_beat_size = 0;
  2019.           break;
  2020.         case 'd':
  2021.           rule.rule = rule_rug2;
  2022.           rule.speed = -1;
  2023.           rule.randomized_underflow = 1;
  2024.           rule.mask = 1023;
  2025.           rule.remap = 0;
  2026.           rule.hot = 6;
  2027.           rule.cool = 32;
  2028.           rule.speed_base = -1;
  2029.           rule.speed_beat_size = 0;
  2030.           fill2.fill = fill_vnoise;
  2031.           fill_board(&fill2);
  2032.           break;
  2033.         case 'e':
  2034.           rule.rule = rule_rug;
  2035.           rule.speed = -1;
  2036.           rule.speed_base = -1;
  2037.           rule.mask = 1791;
  2038.           rule.randomized_underflow = 1;
  2039.           rule.hot = 6;
  2040.           rule.remap = 0;
  2041.           rule.cool = 2;
  2042.           rule.speed_beat_size = 0;
  2043.           fill2.fill = fill_noise;
  2044.           fill_board(&fill2);
  2045.           break;
  2046.         case 'f':
  2047.           rule.rule = rule_rug_image;
  2048.           rule.speed = -1;
  2049.           rule.mask = 255;
  2050.           rule.remap = 0;
  2051.           rule.randomized_underflow = 1;
  2052.           rule.speed_base = -1;
  2053.           rule.speed_beat_size = 0;
  2054.           file_to_image(p1++, current_image);
  2055.           drive_with_image(current_image);
  2056.           fill2.fill = fill_noise;
  2057.           fill_board(&fill2);
  2058.           break;
  2059.         case 'g':
  2060.           rule.rule = rule_rd;
  2061.           rule.brain = 0;
  2062.           rule.brain_shift = 0;
  2063.           fill2.fill = fill_noise;
  2064.           fill_board(&fill2);
  2065.           cmap.cmap = cmap_loop;
  2066.           fade2cmap(&cmap);
  2067.           break;
  2068.         case 'h':
  2069.           rule.rule = rule_rd;
  2070.           rule.brain = 1;
  2071.           rule.brain_shift = 3;
  2072.           fill2.fill = fill_noise;
  2073.           fill_board(&fill2);
  2074.           cmap.cmap = cmap_loop;
  2075.           fade2cmap(&cmap);
  2076.           break;
  2077.         case 'i':
  2078.           rule.rule = rule_rd;
  2079.           rule.brain = 1;
  2080.           rule.brain_shift = 5;
  2081.           fill2.fill = fill_noise;
  2082.           fill_board(&fill2);
  2083.           file_to_image(p1++, current_image);
  2084.           drive_with_image(current_image);
  2085.           cmap.cmap = cmap_loop;
  2086.           fade2cmap(&cmap);
  2087.           break;
  2088.         case 'j':
  2089.           rule.rule = rule_rotorug;
  2090.           rule.speed = -18;
  2091.           rule.speed_base = -18;
  2092.           rule.speed_beat_size = 0;
  2093.           rule.mask = 367;
  2094.           rule.remap = 1;
  2095.           rule.drift = 0;
  2096.           rule.drift_speed = 13;
  2097.           rule.bsize = 47;
  2098.           cmap.cmap = cmap_plain;
  2099.           fade2cmap(&cmap);
  2100.           break;
  2101.         case 'k':
  2102.           rule.rule = rule_rotorug;
  2103.           rule.mask = 255;
  2104.           rule.speed = -1;
  2105.           rule.speed_base = -1;
  2106.           rule.speed_beat_size = 0;
  2107.           rule.drift = 4;
  2108.           rule.drift_speed = 10;
  2109.           rule.bsize = 56;
  2110.           rule.remap = 0;
  2111.           cmap.cmap = cmap_plain;
  2112.           fade2cmap(&cmap);
  2113.           break;
  2114.         case 'l':
  2115.           rule.rule = rule_rotorug;
  2116.           rule.mask = 509;
  2117.           rule.speed_beat_size = 0;
  2118.           rule.speed = -11;
  2119.           rule.speed_base = -11;
  2120.           rule.drift = 8;
  2121.           rule.drift_speed = 8;
  2122.           rule.bsize = 89;
  2123.           rule.remap = 0;
  2124.           cmap.cmap = cmap_plain;
  2125.           fade2cmap(&cmap);
  2126.           break;
  2127.         case 'm':
  2128.           rule.rule = rule_acidlife2;
  2129.           rule.mask = 1919;
  2130.           rule.speed_beat_size = 9;
  2131.           rule.speed_beat_speed = 40;
  2132.           rule.speed_base = -2;
  2133.           rule.speed = -2;
  2134.           rule.brain = 0;
  2135.           break;
  2136.         case 'n':
  2137.           rule.rule = rule_acidlife1;
  2138.           rule.mask = 511;
  2139.           rule.brain = 0;
  2140.           rule.speed_base = -19;
  2141.           rule.speed = -19;
  2142.           cmap.cmap = cmap_split;
  2143.           fade2cmap(&cmap);
  2144.           fill2.fill = fill_noise;
  2145.           fill_board(&fill2);
  2146.           break;
  2147.         default:
  2148.           printf("undefined mood = %d\n", key);
  2149.           break;
  2150.            }
  2151.  
  2152. }
  2153.  
  2154.  
  2155. void
  2156. bomb_work()
  2157. {
  2158.   sprintf(status_string+20, "%d %d %d", rule.speed, rule.mask, cmap.index);
  2159.   if (!((frame+1)%100)) {
  2160.      int bs;
  2161.      int notty = NULL != getenv("EMACS");
  2162.      fps = 100.0/end_timer();
  2163.  
  2164.      sprintf(status_string, "%04.1lf ", fps);
  2165.         
  2166. #if 0
  2167.      if (!notty)
  2168.         putchar(13);
  2169.      printf ("frame=%d fps=%.3g delay=%.3g      ",
  2170.          frame+1, fps, delay);
  2171.      if (notty)
  2172.         printf("\n");
  2173.      else
  2174.         fflush(stdout);
  2175. #endif
  2176.      begin_timer();
  2177.      /* here is the target frames per second */
  2178.      delay += 0.2 * (fps - argd("fps", 15.0));
  2179.      if (delay < 0.0) delay = 0.0;
  2180.       }
  2181.       if (delay >= 1.0 && stabilize_fps) {
  2182. #ifdef sgi
  2183.      sginap(quantize(delay));
  2184. #elif defined(linux)
  2185.      usleep((int)(delay * 1e4));
  2186. #else
  2187.      ;
  2188. #endif
  2189.       }
  2190.       
  2191.    if (pulse) {
  2192.      pulse = 0;
  2193.      rule.floor = 0;
  2194.    } else {
  2195.        int n = rule.hot + rule.cool;
  2196.        if (0 == n) rule.floor = 0;
  2197.        else rule.floor = (frame % n) > rule.hot;
  2198.    }
  2199.  
  2200.       if (periodic_write &&
  2201.       0 == (frame % periodic_write)) {
  2202. #if use_mpeg
  2203.      write_fb_mpeg(&fb);
  2204. #else
  2205.      write_fb_ppm(&fb);
  2206. #endif
  2207.       }
  2208.  
  2209.       if (rule.rule == rule_fuse
  2210.       && rule.fastflip_rate
  2211.       && --fastflip<=0) {
  2212.     fastflip = rule.fastflip_rate;
  2213.     rotate_images();
  2214.     file_to_image(seq_next_image(rule.seq), 0);
  2215.       }
  2216.  
  2217.       if (rule.rule == rule_fuse && (1 == iclamp(rule.drift, fuse_ndrifts))) {
  2218.     extern double avg_pix;
  2219.     run_hist(&fb);
  2220.     if (avg_pix > 180.0) cool(&fb);
  2221.       } else if ( auto_mode && run_hist(&fb) &&
  2222.             frame - last_clear > 400) {
  2223.  
  2224.             fill2.fill = fill_noise;
  2225.             delayed_fill = 1;
  2226.       }
  2227.       
  2228.       step_cmap();
  2229.       
  2230.  
  2231. #if win_bomb
  2232.       if (1) {
  2233.           extern int mouse_down, mouse_x, mouse_y;
  2234.           if (mouse_down) {
  2235.               do_mouse(mouse_x, mouse_y);
  2236.           }
  2237.       }
  2238. #endif
  2239. #if mac_bomb
  2240.       if (1) {
  2241.         Point p;
  2242.         EventRecord gEvent;
  2243.         if (GetOSEvent( mDownMask, &gEvent) || StillDown()) {
  2244.            GetMouse(&p);
  2245.            do_mouse(p.h, p.v);
  2246.          }
  2247.          GetOSEvent( mUpMask, &gEvent);
  2248.       }
  2249. #endif
  2250.  
  2251.       switch (rule.rule) {
  2252.        case rule_rug:
  2253.      step_rule_rug(frame, &rule, &fb);
  2254.      break;
  2255.        case rule_rug2:
  2256.      step_rule_rug2(frame, &rule, &fb);
  2257.      break;
  2258.        case rule_rug3:
  2259.      step_rule_rug3(frame, &rule, &fb);
  2260.      break;
  2261.        case rule_static:
  2262.      step_rule_static(frame, &rule, &fb);
  2263.      break;
  2264.        case rule_rotorug:
  2265.      step_rule_rotorug(frame, &rule, &fb);
  2266.      break;
  2267.        case rule_acidlife1:
  2268.      step_rule_acidlife1(frame, &rule, &fb);
  2269.      break;
  2270.        case rule_acidlife2:
  2271.      step_rule_acidlife2(frame, &rule, &fb);
  2272.      break;
  2273.        case rule_rug_anneal:
  2274.      step_rule_rug_anneal(frame, &rule, &fb);
  2275.      break;
  2276.        case rule_rug_anneal2:
  2277.      step_rule_rug_anneal2(frame, &rule, &fb);
  2278.      break;
  2279.        case rule_rug_rug:
  2280.      step_rule_rug_rug(frame, &rule, &fb);
  2281.      break;
  2282.        case rule_rug_brain:
  2283.      step_rule_rug_brain(frame, &rule, &fb);
  2284.      break;
  2285.        case rule_shade:
  2286.      step_rule_shade(frame, &rule, &fb);
  2287.      break;
  2288.        case rule_wave:
  2289.      step_rule_wave(frame, &rule, &fb);
  2290.      break;
  2291.        case rule_rug_image:
  2292.      step_rule_rug_image(frame, &rule, &fb);
  2293.      break;
  2294.        case rule_slip:
  2295.      step_rule_slip(frame, &rule, &fb);
  2296.      break;
  2297.        case rule_fuse:
  2298.      step_rule_fuse(frame, &rule, &fb);
  2299.      break;
  2300.        case rule_rug_multi:
  2301.      step_rule_rug_multi(frame, &rule, &fb);
  2302.      break;
  2303.        case rule_rd:
  2304.      step_rule_rd(frame, &rule, &fb);
  2305.      break;
  2306.        case rule_rd2:
  2307.      step_rule_rd2(frame, &rule, &fb);
  2308.      break;
  2309.        case rule_quad:
  2310.      step_rule_quad(frame, &rule, &fb);
  2311.      /*step_rule_quad(frame, &rule, &fb);*/
  2312.      break;
  2313.        default:
  2314.      printf("bad rule: %d\n", rule.rule);
  2315.      step_rule_rug(frame, &rule, &fb);
  2316.      break;
  2317.       }
  2318.  
  2319.       frame++;
  2320.       timer = timer - adjust_speed(dtime);
  2321.       old_rule = rule.rule;
  2322.  
  2323.          if (pulse_driver) {
  2324.              pulse_driver = 0;
  2325.              rule.driver_slowdown = 0;
  2326.          }
  2327.  
  2328.       if (((key = bomb_getkey()) > 0) && keyboard_enabled) {
  2329.      timer = 100000;
  2330.      auto_mode = 0;
  2331.      image_rate = 0;
  2332.      /* kbd_mode independent controls */
  2333.      switch (key) {
  2334.       case ' ':
  2335.         auto_rule = 0;
  2336.         distrib(distrib_new | rule_lock, &rule, &cmap, &fill2);
  2337.         fade2cmap(&cmap);
  2338.         delayed_fill = 1;
  2339.         timer = 2000;
  2340.         break;
  2341.       case '`':
  2342.         print_state(&rule);
  2343.         break;
  2344.       case 6: /* ^F */
  2345.         display_fps = !display_fps;
  2346.         break;
  2347.  
  2348.       case '1':
  2349.         kbd_mode = 0;
  2350.         break;
  2351.       case '2':
  2352.         kbd_mode = 1;
  2353.         break;
  2354.       case '3':
  2355.         kbd_mode = 2;
  2356.         break;
  2357.       case '4':
  2358.         kbd_mode = 3;
  2359.         break;
  2360.           
  2361.       case 27:
  2362.       case 3:
  2363.         bomb_exit();
  2364.         break;
  2365.       default:
  2366.         switch (kbd_mode) {
  2367.          case 0:
  2368.            param_tweeking(key);
  2369.            break;
  2370.          case 1:
  2371.            mood_organ(key);
  2372.            break;
  2373.          case 2:
  2374.            /* image organ */
  2375.            file_to_image(key, current_image);
  2376.            drive_with_image(current_image);
  2377.            break;
  2378.          case 3:
  2379.            /* color organ */
  2380.            cmap.index = (key>>1)%ncmaps;
  2381.            cmap.cmap = (key&1) ? cmap_plain : cmap_loop;
  2382.            fade2cmap(&cmap);
  2383.            break;
  2384.         }        
  2385.      }
  2386.       }
  2387. #ifndef wbomb
  2388.       self_play();
  2389. #endif
  2390.  
  2391.  
  2392.       flipper = (frame >> 9) & 0x3;
  2393.       flipper2 = (frame >> 10) & 0x3;
  2394.  
  2395.       change_rules(old_rule, rule.rule, &fb);
  2396.  
  2397.       if (delayed_fill) {
  2398.           fill_board(&fill2);
  2399.           delayed_fill = 0;
  2400.            last_clear = frame;
  2401.       }
  2402. #if !use_sioux
  2403.      image8_flush();
  2404. #endif
  2405.  
  2406.       if (1) {
  2407.          int s;         
  2408.   
  2409.          if (rule.rule == rule_rotorug) {
  2410.            if (sound_present) {
  2411.              s = get_beat(1);
  2412.              rule.drift_time = frame + 1000 + 2*s;
  2413.              rule.drift_speed = s;
  2414.            } else 
  2415.              rule.drift_time += rule.drift_speed;
  2416.          } else {
  2417.              s = get_beat(0);
  2418.              if (sound_present) {
  2419.                rule.speed = rule.speed_base - (rule.speed_beat_size * s / 3);
  2420.            } else {
  2421.                rule.speed = rule.speed_base + 0.5 * rule.speed_beat_size *
  2422.                  sin(2.0 * M_PI * frame / rule.speed_beat_speed);
  2423.       }
  2424.     }
  2425.  
  2426. #if mac_bomb
  2427.         if (0) {
  2428.             Rect r;
  2429.             r.top = 0;
  2430.             r.bottom = 100;
  2431.             r.left = 0;
  2432.             r.right = 800;
  2433.             if (frame%800 == 0)
  2434.                EraseRect(&r);
  2435.             PenNormal();
  2436.             MoveTo(frame%800, 50+s);
  2437.             LineTo(frame%800, 50+0);
  2438.          }
  2439. #endif
  2440.  
  2441.     
  2442.       }
  2443. }
  2444.  
  2445. void
  2446. bomb_clear(int c) {
  2447.     fill2.fill = c;
  2448.     delayed_fill = 1;
  2449. }
  2450.  
  2451. void
  2452. bomb_pulse() {
  2453.     rule.floor = 0;
  2454.     rule.cool = 999999;
  2455.     pulse = 1;
  2456. }
  2457.  
  2458. void
  2459. bomb_pulse_driver() {
  2460.     rule.driver_slowdown = -1;
  2461.     pulse_driver = 1;
  2462. }
  2463. void bomb_set_flame(int r) {
  2464.     if (-1 == r) {
  2465.        random_control_point(&rule.flame_cp);
  2466.        pick_liss_coefs();
  2467.     } else {
  2468.        rule.flame_cp = flames[iclamp(r, nflames)];
  2469.     }
  2470. }
  2471. void bomb_set_rule(int r) { rule.rule = r; }
  2472. void bomb_set_speed(int r) {
  2473.     rule.speed = r;
  2474.     rule.speed_base = r;
  2475.     rule.speed_beat_size = 0;
  2476. }
  2477. void bomb_set_mask(int r) { rule.mask = r; }
  2478. void bomb_set_pen_size(int r) { rule.bsize = r; }
  2479. void bomb_set_drift(int r) { rule.drift = r; }
  2480. void bomb_set_brain(int r) { rule.brain = r; }
  2481. void bomb_set_brain_shift(int r) { rule.brain_shift = r; }
  2482. void bomb_set_drift_speed(int r) { rule.drift_speed = r; }
  2483. void bomb_set_randomized_underflow(int r) { rule.randomized_underflow = r; }
  2484. void bomb_set_color(int r) { cmap.index = r; fade2cmap(&cmap); }
  2485. void bomb_set_color_type(int r) { cmap.cmap = r; fade2cmap(&cmap); }
  2486. void bomb_set_cycle_background(int r) {rule.cycle_bkg = r;}
  2487. void bomb_set_remap_colors(int r) {rule.remap = r;}
  2488.  
  2489. #if !win_bomb
  2490.  
  2491. #if use_guile
  2492.  
  2493. #define gh_void (gh_int2scm(0))
  2494.  
  2495. SCM
  2496. c_bomb_work(SCM s_n) {
  2497.   int n = gh_scm2int(s_n);
  2498.   int i;
  2499.  
  2500.   for (i = 0; i < n; i++) {
  2501.     gh_defer_ints();
  2502.     bomb_work();
  2503.     gh_allow_ints();
  2504.   }
  2505.  
  2506.  return gh_void;
  2507. }
  2508.  
  2509. SCM
  2510. c_fill_board(SCM s_fill) {
  2511.   int n = gh_scm2int(s_fill);
  2512.   fill2.fill = n;
  2513.   gh_defer_ints();
  2514.   fill_board(&fill2);
  2515.   gh_allow_ints();
  2516.   return gh_void;
  2517. }
  2518.  
  2519. SCM
  2520. c_set_color(SCM s_color) {
  2521.   int c;
  2522.   gh_defer_ints();
  2523.   c = gh_scm2int(s_color);
  2524.   bomb_set_color(iclamp(c, ncmaps));
  2525.   gh_allow_ints();
  2526.   return gh_void;
  2527. }
  2528.  
  2529. SCM
  2530. c_set_color_type(SCM s_color) {
  2531.   gh_defer_ints();
  2532.   bomb_set_color_type(gh_scm2int(s_color));
  2533.   gh_allow_ints();
  2534.   return gh_void;
  2535. }
  2536.  
  2537. SCM
  2538. c_pulse() {
  2539.   bomb_pulse();
  2540.   return gh_void;
  2541. }
  2542.  
  2543. SCM
  2544. c_pulse_driver() {
  2545.   bomb_pulse_driver();
  2546.   return gh_void;
  2547. }
  2548.  
  2549. SCM
  2550. c_get_flame_cp() {
  2551.   char buf[4000];
  2552.   gh_defer_ints();
  2553.   buf[0] = 0;
  2554.   sprint_control_point(buf, &rule.flame_cp, 0);
  2555.   gh_allow_ints();
  2556.   return gh_str2scm(buf, strlen(buf));
  2557. }
  2558.  
  2559. SCM
  2560. c_set_flame_cp(SCM s_s) {
  2561.   char *s = gh_scm2newstr(s_s, NULL);
  2562.   gh_defer_ints();
  2563.   parse_control_point(&s, &rule.flame_cp);
  2564.   gh_allow_ints();
  2565.   return gh_void;
  2566. }
  2567.  
  2568. SCM
  2569. c_random_flame_dir() {
  2570.   pick_liss_coefs();
  2571.   return gh_void;
  2572. }
  2573.  
  2574. SCM
  2575. c_random_flame_cp() {
  2576.   random_control_point(&rule.flame_cp);
  2577.   return gh_void;
  2578. }
  2579.  
  2580. SCM
  2581. c_get_flame_dir() {
  2582.   char buf[4000];
  2583.   gh_defer_ints();
  2584.   buf[0] = 0;
  2585.   sprint_control_point(buf, &cc_direction, 0);
  2586.   gh_allow_ints();
  2587.   return gh_str2scm(buf, strlen(buf));
  2588. }
  2589.  
  2590. SCM
  2591. c_set_flame_dir(SCM s_s) {
  2592.   char *s = gh_scm2newstr(s_s, NULL);
  2593.   gh_defer_ints();
  2594.   parse_control_point(&s, &cc_direction);
  2595.   normalize_liss_coefs();
  2596.   gh_allow_ints();
  2597.   return gh_void;
  2598. }
  2599.  
  2600. SCM
  2601. c_srandom(SCM s_s) {
  2602.   int seed = gh_scm2int(s_s);
  2603.   srandom(seed);
  2604.   return gh_void;
  2605. }
  2606.  
  2607. SCM
  2608. c_set_drift_time(SCM s_var) {
  2609.   int n = gh_scm2double(s_var);
  2610.   rule.drift_time = n;
  2611.   return gh_void;
  2612. }
  2613.  
  2614. SCM
  2615. c_get_drift_time() {
  2616.   return gh_double2scm(rule.drift_time);
  2617. }
  2618.  
  2619. SCM
  2620. c_file_to_image(SCM s_im, SCM s_n) {
  2621.   int im = gh_scm2int(s_im);
  2622.   int n = gh_scm2int(s_n);
  2623.   file_to_image(im, n);
  2624.   return gh_void;
  2625. }
  2626.  
  2627. SCM
  2628. c_drive_with_image(s_n) {
  2629.   int n = gh_scm2int(s_n);
  2630.   drive_with_image(n);
  2631.   return gh_void;
  2632. }
  2633.  
  2634. /* fails why? */
  2635. #define make_var(loc_name, name) \
  2636. SCM \
  2637. c_var_ ## name(SCM s_var) { \
  2638.   if (NULL == s_var) \
  2639.     return gh_int2scm(loc_name); \
  2640.   loc_name = gh_scm2int(s_var); \
  2641.   return gh_void; \
  2642. }
  2643.  
  2644. #define make_get_set(loc_name, name) \
  2645. \
  2646. SCM \
  2647. c_set_ ## name(SCM s_var) {\
  2648.   int n = gh_scm2int(s_var);\
  2649.   loc_name = n;\
  2650.   return gh_void;\
  2651. }\
  2652.   \
  2653. SCM \
  2654. c_get_ ## name() {\
  2655.   return gh_int2scm(rule.rule);\
  2656. }
  2657.  
  2658.  
  2659.  
  2660. make_get_set(rule.rule, rule)
  2661. make_get_set(rule.speed, speed)
  2662. make_get_set(rule.mask, mask)
  2663. make_get_set(rule.randomized_underflow, randomized_underflow)
  2664. make_get_set(rule.cycle_bkg, cycle_bkg)
  2665. make_get_set(rule.remap, remap)
  2666. make_get_set(rule.floor, floor)
  2667. make_get_set(rule.driver_slowdown, driver_slowdown)
  2668. make_get_set(rule.brain, brain)
  2669. make_get_set(rule.brain_shift, brain_shift)
  2670. make_get_set(rule.drift, drift)
  2671. make_get_set(rule.drift_speed, drift_speed)
  2672. make_get_set(rule.bsize, bsize)
  2673. make_get_set(rule.hot, hot)
  2674. make_get_set(rule.cool, cool)
  2675.  
  2676. void
  2677. main_prog(int argc, char *argv[])
  2678. {
  2679.  
  2680.   init();
  2681.       
  2682.   gh_new_procedure1_0("bomb-do-frame", c_bomb_work);
  2683.   gh_new_procedure1_0("bomb-fill", c_fill_board);
  2684.   gh_new_procedure0_0("bomb-pulse", c_pulse);
  2685.   gh_new_procedure0_0("bomb-pulse-driver", c_pulse_driver);
  2686.  
  2687.   gh_new_procedure1_0("bomb-set-color", c_set_color);
  2688.   gh_new_procedure1_0("bomb-set-color-type", c_set_color_type);
  2689.  
  2690. #if 0
  2691.   gh_new_procedure0_1("bomb-rule", c_var_rule);
  2692. #endif
  2693.  
  2694.   gh_new_procedure1_0("bomb-set-rule", c_set_rule);
  2695.   gh_new_procedure0_0("bomb-get-rule", c_get_rule);
  2696.   gh_new_procedure1_0("bomb-set-speed", c_set_speed);
  2697.   gh_new_procedure0_0("bomb-get-speed", c_get_speed);
  2698.   gh_new_procedure1_0("bomb-set-mask", c_set_mask);
  2699.   gh_new_procedure0_0("bomb-get-mask", c_get_mask);
  2700.   gh_new_procedure1_0("bomb-set-randomized-underflow", c_set_randomized_underflow);
  2701.   gh_new_procedure0_0("bomb-get-randomized-underflow", c_get_randomized_underflow);
  2702.   gh_new_procedure1_0("bomb-set-remap", c_set_remap);
  2703.   gh_new_procedure0_0("bomb-get-remap", c_get_remap);
  2704.   gh_new_procedure1_0("bomb-set-floor", c_set_floor);
  2705.   gh_new_procedure0_0("bomb-get-floor", c_get_floor);
  2706.   gh_new_procedure1_0("bomb-set-driver-slowdown", c_set_driver_slowdown);
  2707.   gh_new_procedure0_0("bomb-get-driver-slowdown", c_get_driver_slowdown);
  2708.   gh_new_procedure1_0("bomb-set-brain", c_set_brain);
  2709.   gh_new_procedure0_0("bomb-get-brain", c_get_brain);
  2710.   gh_new_procedure1_0("bomb-set-brain-shift", c_set_brain_shift);
  2711.   gh_new_procedure0_0("bomb-get-brain-shift", c_get_brain_shift);
  2712.   gh_new_procedure1_0("bomb-set-drift", c_set_drift);
  2713.   gh_new_procedure0_0("bomb-get-drift", c_get_drift);
  2714.   gh_new_procedure1_0("bomb-set-drift-speed", c_set_drift_speed);
  2715.   gh_new_procedure0_0("bomb-get-drift-speed", c_get_drift_speed);
  2716.   gh_new_procedure1_0("bomb-set-pen-size", c_set_bsize);
  2717.   gh_new_procedure0_0("bomb-get-pen-size", c_get_bsize);
  2718.   gh_new_procedure1_0("bomb-set-hot", c_set_hot);
  2719.   gh_new_procedure0_0("bomb-get-hot", c_get_hot);
  2720.   gh_new_procedure1_0("bomb-set-cool", c_set_cool);
  2721.   gh_new_procedure0_0("bomb-get-cool", c_get_cool);
  2722.   gh_new_procedure1_0("bomb-set-cycle-bkg", c_set_cycle_bkg);
  2723.   gh_new_procedure0_0("bomb-get-cycle-bkg", c_get_cycle_bkg);
  2724.   gh_new_procedure1_0("bomb-set-flame-cp", c_set_flame_cp);
  2725.   gh_new_procedure0_0("bomb-get-flame-cp", c_get_flame_cp);
  2726.   gh_new_procedure1_0("bomb-set-flame-dir", c_set_flame_dir);
  2727.   gh_new_procedure0_0("bomb-get-flame-dir", c_get_flame_dir);
  2728.   gh_new_procedure1_0("bomb-set-drift-time", c_set_drift_time);
  2729.   gh_new_procedure0_0("bomb-get-drift-time", c_get_drift_time);
  2730.  
  2731.   gh_new_procedure0_0("bomb-random-flame-cp", c_random_flame_cp);
  2732.   gh_new_procedure0_0("bomb-random-flame-dir", c_random_flame_dir);
  2733.   gh_new_procedure1_0("bomb-srandom", c_srandom);
  2734.  
  2735.   gh_new_procedure1_0("bomb-drive-with-image", c_drive_with_image);
  2736.   gh_new_procedure2_0("bomb-file-to-image", c_file_to_image);
  2737.  
  2738.   gh_eval_str("(load \"bomb.scm\")");
  2739.  
  2740.   if (1 == argc) {
  2741.     while (1)
  2742.       bomb_work();
  2743.   } else {
  2744.     int i;
  2745.     char s[1000];
  2746.     for (i = 1; i < argc; i++) {
  2747.       sprintf(s, "(load \"%s\")", argv[i]);
  2748.       gh_eval_str(s);
  2749.     }
  2750.   }
  2751. }
  2752.  
  2753. void
  2754. main(int argc, char *argv[])
  2755. {
  2756.   gh_enter(argc, argv, main_prog);
  2757. }
  2758.  
  2759. #else
  2760. void
  2761. main()
  2762. {
  2763.    init();
  2764.    
  2765.    while (1) {
  2766.      bomb_work();
  2767.    }
  2768. }
  2769. #endif
  2770. message(char *s) {}
  2771. #endif
  2772.