home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / maze / algorithms.c next >
Encoding:
C/C++ Source or Header  |  2000-04-14  |  17.9 KB  |  597 lines

  1. /* $Id: algorithms.c,v 1.5 2000/04/14 08:59:52 neo Exp $
  2.  * Contains routines for generating mazes, somewhat intertwined with 
  3.  * Gimp plug-in-maze specific stuff.
  4.  *
  5.  * Kevin Turner <acapnotic@users.sourceforge.net>
  6.  * http://gimp-plug-ins.sourceforge.net/maze/
  7.  */
  8.  
  9. /* mazegen code from rec.games.programmer's maze-faq:
  10.  * * maz.c - generate a maze
  11.  * *
  12.  * * algorithm posted to rec.games.programmer by jallen@ic.sunysb.edu
  13.  * * program cleaned and reorganized by mzraly@ldbvax.dnet.lotus.com
  14.  * *
  15.  * * don't make people pay for this, or I'll jump up and down and
  16.  * * yell and scream and embarass you in front of your friends...
  17.  */
  18.  
  19. /* I've put a HTMLized version of the FAQ up at 
  20.  * http://www.poboxes.com/kevint/gimp/maze-faq/maze-faq.html
  21.  */
  22.  
  23. /*
  24.  * This program is free software; you can redistribute it and/or modify
  25.  * it under the terms of the GNU General Public License as published by
  26.  * the Free Software Foundation; either version 2 of the License, or
  27.  * (at your option) any later version.
  28.  *
  29.  * This program is distributed in the hope that it will be useful,
  30.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  31.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  32.  * GNU General Public License for more details.
  33.  *
  34.  * You should have received a copy of the GNU General Public License
  35.  * along with this program; if not, write to the Free Software
  36.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  37.  *
  38.  */
  39.  
  40. #ifndef SOLO_COMPILE
  41. #include "config.h"
  42. #endif
  43.  
  44. #include <stdlib.h>
  45. #include "maze.h"
  46. #include "libgimp/gimp.h"
  47. #include "libgimp/gimpui.h"
  48. #include "libgimp/stdplugins-intl.h"
  49.  
  50. extern MazeValues mvals;
  51.  
  52. void      mazegen(gint     pos,
  53.           gchar   *maz,
  54.           gint     x,
  55.           gint     y,
  56.           gint     rnd);
  57. void      mazegen_tileable(gint     pos,
  58.                gchar   *maz,
  59.                gint     x,
  60.                gint     y,
  61.                gint     rnd);
  62. void      prim(gint pos,
  63.            gchar *maz, 
  64.            guint x, 
  65.            guint y, 
  66.            gint rnd);
  67. void      prim_tileable(gchar *maz, 
  68.             guint x, 
  69.             guint y, 
  70.             gint rnd);
  71.  
  72. #define ABSMOD(A,B) ( ((A) < 0) ? (((B) + (A)) % (B)) : ((A) % (B)) )
  73.  
  74. /* Since we are using a 1D array on 2D space, we need to do our own
  75.    calculations.  (Ok, so there are ways of doing dynamically allocated
  76.    2D arrays, but we started this way, so let's stick with it. */
  77.  
  78. /* The difference between CELL_* and WALL_* is that cell moves two spaces,
  79.    while wall moves one. */
  80.  
  81. /* Macros assume that x and y will be defined where they are used. */
  82. /* A return of -1 means "no such place, don't go there". */
  83. #define CELL_UP(POS) ((POS) < (x*2) ? -1 : (POS) - x - x)
  84. #define CELL_DOWN(POS) ((POS) >= x*(y-2) ? -1 : (POS) + x + x)
  85. #define CELL_LEFT(POS) (((POS) % x) <= 1 ? -1 : (POS) - 2)
  86. #define CELL_RIGHT(POS) (((POS) % x) >= (x - 2) ? -1 : (POS) + 2)
  87.  
  88. /* With walls, we don't need to check for boundaries, since we are
  89.    assured that there *is* a valid cell on the other side of the
  90.    wall. */
  91. #define WALL_UP(POS) ((POS) - x)
  92. #define WALL_DOWN(POS) ((POS) + x)
  93. #define WALL_LEFT(POS) ((POS) - 1)
  94. #define WALL_RIGHT(POS) ((POS) + 1)
  95.  
  96. /***** For tileable mazes *****/
  97.  
  98. #define CELL_UP_TILEABLE(POS) ((POS) < (x*2) ? x*(y-2)+(POS) : (POS) - x - x)
  99. #define CELL_DOWN_TILEABLE(POS) ((POS) >= x*(y-2) ? (POS) - x*(y-2) : (POS) + x + x)
  100. #define CELL_LEFT_TILEABLE(POS) (((POS) % x) <= 1 ? (POS) + x - 2 : (POS) - 2)
  101. #define CELL_RIGHT_TILEABLE(POS) (((POS) % x) >= (x - 2) ? (POS) + 2 - x : (POS) + 2)         
  102. /* Up and left need checks, but down and right should never have to
  103.    wrap on an even sized maze. */
  104. #define WALL_UP_TILEABLE(POS) ((POS) < x ? x*(y-1)+(POS) : (POS) - x)
  105. #define WALL_DOWN_TILEABLE(POS) ((POS) + x)
  106. #define WALL_LEFT_TILEABLE(POS) (((POS) % x) == 0 ? (POS) + x - 1 : (POS) - 1)
  107. #define WALL_RIGHT_TILEABLE(POS) ((POS) + 1)
  108.  
  109. /* Down and right with checks.
  110. #define WALL_DOWN_TILEABLE(POS) ((POS) >= x*(y-1) ? (POS) - x * (y-1) : (POS) + x)
  111. #define WALL_RIGHT_TILEABLE(POS) (((POS) % x) == (x - 1) ? (POS) + 1 - x : (POS) + 1)
  112. */
  113.  
  114. /* The Incredible Recursive Maze Generation Routine */
  115. /* Ripped from rec.programmers.games maze-faq       */
  116. /* Modified and commented by me, Kevin Turner. */
  117. void
  118. mazegen(gint pos, gchar *maz, gint x, gint y, gint rnd)
  119. {
  120.     gchar d, i;
  121.     gint c=0, j=1;
  122.  
  123.     /* Punch a hole here...  */
  124.     maz[pos] = IN;
  125.  
  126.     /* If there is a wall two rows above us, bit 1 is 1. */
  127.     while((d= (pos <= (x * 2) ? 0 : (maz[pos - x - x ] ? 0 : 1))
  128.       /* If there is a wall two rows below us, bit 2 is 1. */
  129.       | (pos >= x * (y - 2) ? 0 : (maz[pos + x + x] ? 0 : 2))
  130.       /* If there is a wall two columns to the right, bit 3 is 1. */
  131.       | (pos % x == x - 2 ? 0 : (maz[pos + 2] ? 0 : 4))
  132.       /* If there is a wall two colums to the left, bit 4 is 1.  */
  133.       | ((pos % x == 1 ) ? 0 : (maz[pos-2] ? 0 : 8)))) {
  134.  
  135.     /* Note if all bits are 0, d is false, we don't do this
  136.        while loop, we don't call ourselves again, so this branch
  137.            is done.  */
  138.  
  139.     /* I see what this loop does (more or less), but I don't know
  140.        _why_ it does it this way...  I also haven't figured out exactly
  141.        which values of multiple will work and which won't.  */
  142.     do {
  143.         rnd = (rnd * mvals.multiple + mvals.offset);
  144.         i = 3 & (rnd / d);
  145.         if (++c > 100) {  /* Break and try to salvage something */
  146.         i=99;         /* if it looks like we're going to be */
  147.         break;        /* here forever...                    */
  148.         }
  149.     } while ( !(d & ( 1 << i) ) );
  150.     /* ...While there's *not* a wall in direction i. */
  151.         /* (stop looping when there is) */
  152.  
  153.     switch (i) {  /* This is simple enough. */
  154.     case 0:       /* Go in the direction we just figured . . . */
  155.         j= -x;   
  156.         break;
  157.     case 1:
  158.         j = x;
  159.         break;
  160.     case 2:
  161.         j=1;
  162.         break;
  163.     case 3:
  164.         j= -1;
  165.         break;
  166.     case 99:
  167.         return;  /* Hey neat, broken mazes! */
  168.         break;     /* (Umm... Wow... Yeah, neat.) */
  169.     default:
  170.          g_warning("maze: mazegen: Going in unknown direction.\n"
  171.                "i: %d, d: %d, seed: %d, mw: %d, mh: %d, mult: %d, offset: %d\n",
  172.                i, d,mvals.seed, x, y, mvals.multiple, mvals.offset);
  173.         break;
  174.     }
  175.  
  176.     /* And punch a hole there. */
  177.     maz[pos + j] = 1;
  178.  
  179.         /* Now, start again just past where we punched the hole... */
  180.     mazegen(pos + 2 * j, maz, x, y, rnd);
  181.  
  182.     } /* End while(d=...) Loop */
  183.  
  184.     /* This routine is quite quick, even for rather large mazes.
  185.        For that reason, it doesn't need a progress bar. */
  186.     return;
  187. }
  188.  
  189. /* Tileable mazes are my creation, based on the routine above. */
  190. void
  191. mazegen_tileable(gint pos, gchar *maz, gint x, gint y, gint rnd)
  192. {
  193.     gchar d, i;
  194.     gint c=0, npos=2;
  195.  
  196.     /* Punch a hole here...  */
  197.     maz[pos] = IN;
  198.  
  199.     /* If there is a wall two rows above us, bit 1 is 1. */
  200.     while((d= (maz[CELL_UP_TILEABLE(pos)] ? 0 : 1)
  201.       /* If there is a wall two rows below us, bit 2 is 1. */
  202.       | (maz[CELL_DOWN_TILEABLE(pos)] ? 0 : 2)
  203.       /* If there is a wall two columns to the right, bit 3 is 1. */
  204.       | (maz[CELL_RIGHT_TILEABLE(pos)] ? 0 : 4)
  205.       /* If there is a wall two colums to the left, bit 4 is 1.  */
  206.       | (maz[CELL_LEFT_TILEABLE(pos)] ? 0 : 8))) {
  207.  
  208.      /* Note if all bits are 0, d is false, we don't do this
  209.        while loop, we don't call ourselves again, so this branch
  210.            is done.  */
  211.  
  212.     /* I see what this loop does (more or less), but I don't know
  213.        _why_ it does it this way...  I also haven't figured out exactly
  214.        which values of multiple will work and which won't.  */
  215.     do {
  216.         rnd = (rnd * mvals.multiple + mvals.offset);
  217.         i = 3 & (rnd / d);
  218.         if (++c > 100) {  /* Break and try to salvage something */
  219.         i=99;         /* if it looks like we're going to be */
  220.         break;        /* here forever...                    */
  221.         }
  222.     } while ( !(d & ( 1 << i) ) );
  223.     /* ...While there's *not* a wall in direction i. */
  224.         /* (stop looping when there is) */
  225.  
  226.     switch (i) {  /* This is simple enough. */
  227.     case 0:       /* Go in the direction we just figured . . . */
  228.          maz[WALL_UP_TILEABLE(pos)]=IN;
  229.          npos = CELL_UP_TILEABLE(pos);
  230.          break;
  231.     case 1:
  232.          maz[WALL_DOWN_TILEABLE(pos)]=IN;
  233.          npos = CELL_DOWN_TILEABLE(pos); 
  234.          break;
  235.     case 2:
  236.          maz[WALL_RIGHT_TILEABLE(pos)]=IN;
  237.          npos = CELL_RIGHT_TILEABLE(pos);
  238.          break;
  239.     case 3:
  240.          maz[WALL_LEFT_TILEABLE(pos)]=IN;
  241.          npos = CELL_LEFT_TILEABLE(pos);
  242.          break;
  243.     case 99:
  244.          return;  /* Hey neat, broken mazes! */
  245.          break;     /* (Umm... Wow... Yeah, neat.) */
  246.     default:
  247.          g_warning("maze: mazegen_tileable: Going in unknown direction.\n"
  248.                "i: %d, d: %d, seed: %d, mw: %d, mh: %d, mult: %d, offset: %d\n",
  249.                i, d,mvals.seed, x, y, mvals.multiple, mvals.offset);
  250.          break;
  251.     }
  252.  
  253.         /* Now, start again just past where we punched the hole... */
  254.     mazegen_tileable(npos, maz, x, y, rnd);
  255.  
  256.     } /* End while(d=...) Loop */
  257.  
  258.     return;
  259. }
  260.  
  261. #if 0
  262. static void
  263. print_glist(gpointer data, gpointer user_data)
  264. {
  265.      g_print("%d ",(guint)data);
  266. }
  267. #endif
  268.  
  269. /* This function (as well as prim_tileable) make use of the somewhat
  270.    unclean practice of storing ints as pointers.  I've been informed
  271.    that this may cause problems with 64-bit stuff.  However, hopefully
  272.    it will be okay, since the only values stored are positive.  If it
  273.    does break, let me know, and I'll go cry in a corner for a while
  274.    before I get up the strength to re-code it. */
  275. void
  276. prim(gint pos, gchar *maz, guint x, guint y, gint rnd)
  277. {
  278.      GSList *front_cells=NULL;
  279.      guint current;
  280.      gint up, down, left, right; /* Not unsigned, because macros return -1. */
  281.      guint progress=0, max_progress;
  282.      char d, i;
  283.      guint c=0;
  284.  
  285.      gimp_progress_init (_("Constructing maze using Prim's Algorithm..."));
  286.  
  287.      /* OUT is zero, so we should be already initalized. */
  288.  
  289.      max_progress=x*y/4;
  290.  
  291.      /* Starting position has already been determined by the calling function. */
  292.  
  293.      maz[pos]=IN;
  294.  
  295.      /* For now, repeating everything four times seems manageable.  But when 
  296.     Gimp is extended to drawings in n-dimensional space instead of 2D,
  297.         this will require a bit of a re-write. */
  298.      /* Add frontier. */
  299.      up=CELL_UP(pos);
  300.      down=CELL_DOWN(pos);
  301.      left=CELL_LEFT(pos);
  302.      right=CELL_RIGHT(pos);
  303.  
  304.      if (up >= 0) {
  305.       maz[up]=FRONTIER;
  306.       front_cells=g_slist_append(front_cells,GINT_TO_POINTER(up));
  307.      }
  308.      if (down >= 0) {
  309.       maz[down]=FRONTIER;
  310.       front_cells=g_slist_append(front_cells,GINT_TO_POINTER(down));
  311.      }
  312.      if (left >= 0) {
  313.       maz[left]=FRONTIER;
  314.       front_cells=g_slist_append(front_cells,GINT_TO_POINTER(left));
  315.      }
  316.      if (right >= 0) {
  317.       maz[right]=FRONTIER;
  318.       front_cells=g_slist_append(front_cells,GINT_TO_POINTER(right));
  319.      }
  320.  
  321.      /* While frontier is not empty do the following... */
  322.      while(g_slist_length(front_cells) > 0) {
  323.  
  324.       /* Remove one cell at random from frontier and place it in IN. */
  325.       current = rand() % g_slist_length(front_cells);
  326.       pos = GPOINTER_TO_INT(g_slist_nth(front_cells,current)->data);
  327.  
  328.       front_cells=g_slist_remove(front_cells,GINT_TO_POINTER(pos));
  329.       maz[pos]=IN;
  330.  
  331.       /* If the cell has any neighbors in OUT, remove them from
  332.              OUT and place them in FRONTIER. */
  333.  
  334.       up=CELL_UP(pos);
  335.       down=CELL_DOWN(pos);
  336.       left=CELL_LEFT(pos);
  337.       right=CELL_RIGHT(pos);
  338.  
  339.       d=0;
  340.       if (up>=0) {
  341.            switch (maz[up]) {
  342.            case OUT:
  343.             maz[up]=FRONTIER;
  344.             front_cells=g_slist_prepend(front_cells,
  345.                         GINT_TO_POINTER(up)); 
  346.            break;
  347.            case IN:
  348.             d=1;
  349.             break;
  350.            default:
  351.             ;
  352.            }
  353.       }
  354.       if (down>=0) {
  355.            switch (maz[down]) {
  356.            case OUT:
  357.             maz[down]=FRONTIER;
  358.             front_cells=g_slist_prepend(front_cells,
  359.                         GINT_TO_POINTER(down)); 
  360.             break;
  361.            case IN:
  362.             d=d|2;
  363.             break;
  364.            default:
  365.             ;
  366.            }
  367.       }
  368.       if (left>=0) {
  369.            switch (maz[left]) {
  370.            case OUT:
  371.             maz[left]=FRONTIER;
  372.             front_cells=g_slist_prepend(front_cells,
  373.                         GINT_TO_POINTER(left)); 
  374.             break;
  375.            case IN:
  376.             d=d|4;
  377.             break;
  378.            default:
  379.             ;
  380.            }
  381.       }
  382.       if (right>=0) {
  383.            switch (maz[right]) {
  384.            case OUT:
  385.             maz[right]=FRONTIER;
  386.             front_cells=g_slist_prepend(front_cells,
  387.                         GINT_TO_POINTER(right)); 
  388.             break;
  389.            case IN:
  390.             d=d|8;
  391.             break;
  392.            default:
  393.             ;
  394.            }           
  395.       }
  396.  
  397.       /* The cell is guaranteed to have at least one neighbor in
  398.          IN (otherwise it would not have been in FRONTIER); pick
  399.          one such neighbor at random and connect it to the new
  400.          cell (ie knock out a wall).  */
  401.  
  402.       if (!d) {
  403.            g_warning("maze: prim: Lack of neighbors.\n"
  404.              "seed: %d, mw: %d, mh: %d, mult: %d, offset: %d\n",
  405.              mvals.seed, x, y, mvals.multiple, mvals.offset);
  406.            break;       
  407.       }
  408.  
  409.       c=0;
  410.       do {
  411.            rnd = (rnd * mvals.multiple + mvals.offset);
  412.            i = 3 & (rnd / d);
  413.            if (++c > 100) {  /* Break and try to salvage something */
  414.             i=99;         /* if it looks like we're going to be */
  415.             break;        /* here forever...                    */
  416.            }
  417.       } while ( !(d & ( 1 << i) ) );
  418.       
  419.       switch (i) {
  420.       case 0:
  421.            maz[WALL_UP(pos)]=IN;
  422.            break;
  423.       case 1:
  424.            maz[WALL_DOWN(pos)]=IN;
  425.            break;
  426.       case 2:
  427.            maz[WALL_LEFT(pos)]=IN;
  428.            break;
  429.       case 3:
  430.            maz[WALL_RIGHT(pos)]=IN;
  431.            break;
  432.       case 99:
  433.            break;
  434.       default:
  435.            g_warning("maze: prim: Going in unknown direction.\n"
  436.              "i: %d, d: %d, seed: %d, mw: %d, mh: %d, mult: %d, offset: %d\n",
  437.              i, d, mvals.seed, x, y, mvals.multiple, mvals.offset);
  438.       }
  439.  
  440.       if (progress++ % PRIMS_PROGRESS_UPDATE)
  441.            gimp_progress_update ((double) progress / (double) max_progress);
  442.  
  443.      } /* while front_cells */
  444.  
  445.      g_slist_free(front_cells);
  446. } /* prim */
  447.  
  448. void
  449. prim_tileable(gchar *maz, guint x, guint y, gint rnd)
  450. {
  451.      GSList *front_cells=NULL;
  452.      guint current, pos;
  453.      guint up, down, left, right;
  454.      guint progress=0, max_progress;
  455.      char d, i;
  456.      guint c=0;
  457.  
  458.      gimp_progress_init (_("Constructing tileable maze using Prim's Algorithm..."));
  459.  
  460.      /* OUT is zero, so we should be already initalized. */
  461.  
  462.      max_progress=x*y/4;
  463.  
  464.      /* Pick someplace to start. */
  465.      srand(rnd);
  466.      pos = x * 2 * (rand() % y / 2) + 2 * (rand() % x / 2);
  467.  
  468.      maz[pos]=IN;
  469.  
  470.      /* Add frontier. */
  471.      up=CELL_UP_TILEABLE(pos);
  472.      down=CELL_DOWN_TILEABLE(pos);
  473.      left=CELL_LEFT_TILEABLE(pos);
  474.      right=CELL_RIGHT_TILEABLE(pos);
  475.  
  476.      maz[up]=maz[down]=maz[left]=maz[right]=FRONTIER;
  477.  
  478.      front_cells=g_slist_append(front_cells,(gpointer)up);
  479.      front_cells=g_slist_append(front_cells,(gpointer)down);
  480.      front_cells=g_slist_append(front_cells,(gpointer)left);
  481.      front_cells=g_slist_append(front_cells,(gpointer)right);
  482.  
  483.      /* While frontier is not empty do the following... */
  484.      while(g_slist_length(front_cells) > 0) {
  485.  
  486.       /* Remove one cell at random from frontier and place it in IN. */
  487.       current = rand() % g_slist_length(front_cells);
  488.       pos = (guint)g_slist_nth(front_cells,current)->data;
  489.  
  490.       front_cells=g_slist_remove(front_cells,(gpointer)pos);
  491.       maz[pos]=IN;
  492.  
  493.       /* If the cell has any neighbors in OUT, remove them from
  494.              OUT and place them in FRONTIER. */
  495.  
  496.       up=CELL_UP_TILEABLE(pos);
  497.       down=CELL_DOWN_TILEABLE(pos);
  498.       left=CELL_LEFT_TILEABLE(pos);
  499.       right=CELL_RIGHT_TILEABLE(pos);
  500.  
  501.       d=0;
  502.       switch (maz[up]) {
  503.       case OUT:
  504.            maz[up]=FRONTIER;
  505.            front_cells=g_slist_append(front_cells,(gpointer)up); 
  506.            break;
  507.       case IN:
  508.            d=1;
  509.            break;
  510.       default:
  511.            ;
  512.       }
  513.       switch (maz[down]) {
  514.       case OUT:
  515.            maz[down]=FRONTIER;
  516.            front_cells=g_slist_append(front_cells,(gpointer)down); 
  517.            break;
  518.       case IN:
  519.            d=d|2;
  520.            break;
  521.       default:
  522.            ;
  523.       }
  524.       switch (maz[left]) {
  525.       case OUT:
  526.            maz[left]=FRONTIER;
  527.            front_cells=g_slist_append(front_cells,(gpointer)left); 
  528.            break;
  529.       case IN:
  530.            d=d|4;
  531.            break;
  532.       default:
  533.            ;
  534.       }
  535.       switch (maz[right]) {
  536.       case OUT:
  537.            maz[right]=FRONTIER;
  538.            front_cells=g_slist_append(front_cells,(gpointer)right); 
  539.            break;
  540.       case IN:
  541.            d=d|8;
  542.            break;
  543.       default:
  544.            ;
  545.       }           
  546.  
  547.       /* The cell is guaranteed to have at least one neighbor in
  548.          IN (otherwise it would not have been in FRONTIER); pick
  549.          one such neighbor at random and connect it to the new
  550.          cell (ie knock out a wall).  */
  551.  
  552.       if (!d) {
  553.            g_warning("maze: prim's tileable: Lack of neighbors.\n"
  554.              "seed: %d, mw: %d, mh: %d, mult: %d, offset: %d\n",
  555.              mvals.seed, x, y, mvals.multiple, mvals.offset);
  556.            break;       
  557.       }
  558.  
  559.       c=0;
  560.       do {
  561.            rnd = (rnd * mvals.multiple + mvals.offset);
  562.            i = 3 & (rnd / d);
  563.            if (++c > 100) {  /* Break and try to salvage something */
  564.             i=99;         /* if it looks like we're going to be */
  565.             break;        /* here forever...                    */
  566.            }
  567.       } while ( !(d & ( 1 << i) ) );
  568.       
  569.       switch (i) {
  570.       case 0:
  571.            maz[WALL_UP_TILEABLE(pos)]=IN;
  572.            break;
  573.       case 1:
  574.            maz[WALL_DOWN_TILEABLE(pos)]=IN;
  575.            break;
  576.       case 2:
  577.            maz[WALL_LEFT_TILEABLE(pos)]=IN;
  578.            break;
  579.       case 3:
  580.            maz[WALL_RIGHT_TILEABLE(pos)]=IN;
  581.            break;
  582.       case 99:
  583.            break;
  584.       default:
  585.            g_warning("maze: prim's tileable: Going in unknown direction.\n"
  586.              "i: %d, d: %d, seed: %d, mw: %d, mh: %d, mult: %d, offset: %d\n",
  587.              i, d, mvals.seed, x, y, mvals.multiple, mvals.offset);
  588.       }
  589.  
  590.       if (progress++ % PRIMS_PROGRESS_UPDATE)
  591.            gimp_progress_update ((double) progress / (double) max_progress);
  592.  
  593.      } /* while front_cells */
  594.  
  595.      g_slist_free(front_cells);
  596. }
  597.