v07i080: Whales and Plankton, part 07/13
Brandon S. Allbery - comp.sources.misc
allbery at uunet.UU.NET
Wed Jul 19 11:40:06 AEST 1989
Posting-number: Volume 7, Issue 80
Submitted-by: loy at gtx.UUCP (Bob Loy)
Archive-name: whpl/part07
# whpl07of13.shar
#---cut here---cut here---cut here---cut here---cut here---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files.
# This archive created: Sat Jan 14 04:04:43 MST 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'whx.c2'" '(29028 characters)'
if test -f 'whx.c2'
then
echo shar: will not over-write existing file "'whx.c2'"
else
sed 's/^X//' << \SHAR_EOF > 'whx.c2'
X
X/*---------------------------------------------------------------------------*
X@^
X@@^ void interim() - Handles interim file output during long runs. Likely to
X@@^ be called under the -y cmnd line opt, or if NUMWH is high.
X@ output: global chappend[0], filename append character, is incremented
X@ global chapend[0], filename append character, may be incremented
X@ caller: main()
X@ calls : lastuff(), fileout(), countwhales(); malloc(), free(),
X@ may call finish()
X@^ proc : Outputs interim whale & stat files, and then reallocates the
X@^ whale structures of the still living whales
X@
X@^ Note : The internal numbering of the whales also gets changed as they
X@^ are reallocated into a smaller space.
X@
X@*---------------------------------------------------------------------------*/
X
Xvoid
Xinterim()
X{
X register int j, k = 0;
X whale_type *newhales;
X
X lastuff(1);
X fileout(1);
X if (debug >= 5)
X fprintf(stderr, "\n CONTINUING -- FILES OUTPUT\n");
X if (debug >= 6)
X fprintf(stdout, "\n CONTINUING -- FILES OUTPUT\n");
X /* Now create the next interim filename append of two extra chars
X from "aa" all the way to "zz", if necessary */
X chappend[0]++;
X if (chappend[0] == '{') /* Oops, stepped past the ascii 'z' } */
X {
X chappend[0] = 'a';
X chapend[0]++;
X if (chapend[0] == '{') /* Oops, stepped past the ascii 'z' } */
X {
X finish(1);
X }
X }
X countwhales();
X if(truwh != malwh + femwh)
X {
X if (debug >= 2)
X fprintf(stderr, "interim(): truwh != malwh + femwh; %4d != %4d\n",
X truwh, malwh + femwh);
X truwh = malwh + femwh;
X }
X /* Create room for live whales only */
X newhales = (whale_type *) malloc(truwh * whale_size);
X if (newhales == NULL)
X {
X if (debug >= 2)
X fprintf(stderr, "\ninterim(): whale malloc problems.\n");
X finish(7);
X }
X /* Do any resets and assign only live whales to a new array */
X for (j = 0; j < numwh; j++)
X {
X if (whale[j].energy > 9999)
X {
X /* Now that the files have been output, we want to clear the
X most recent internal arrays that were used for printing */
X whale[j].endex--; /* 'cleared' just by dropping the index */
X /* endex should also track the array of success structures: */
X whale[j].comp[whale[j].endex].diff = 0;
X whale[j].comp[whale[j].endex].totl = 0;
X whale[j].comp[whale[j].endex].rank = 0;
X if (k >= truwh)
X {
X if (debug >= 2)
X fprintf(stderr,
X "\ninterim(): truwh >= new whale array size.\n");
X free((char*) newhales);
X finish(6);
X }
X newhales[k] = whale[j];
X k++;
X }
X }
X /* Close and reassign pointer to whale array */
X free((char*) whale);
X whale = newhales;
X numwh = truwh;
X if (debug >= 5)
X fprintf(stderr, "\n numwh being reset to: %d.\n\n", numwh);
X if (debug >= 6)
X fprintf(stdout, "\n numwh being reset to: %d.\n\n", numwh);
X}
X
X/*---------------------------------------------------------------------------*
X@
X@@ int plankcall() - Calling function for ongoing plankton regeneration.
X@ input : global variable regrow
X@ output: plankton may be regrown in locarr[] if population is below the
X@ lower floor limit
X@ caller: movewhale()
X@ calls : plankgrow(), countplank(), printscreen()
X@
X@*---------------------------------------------------------------------------*/
X
Xint
Xplankcall()
X{
X int plank;
X
X plank = countplank();
X if (plank < regrow)
X {
X printscreen();
X if (debug >= 7)
X fprintf(stdout, " plank = %d\n", plank);
X plankgrow(2);
X plankgrow(1);
X /* one possible use of stopgrow: ----
X while (plank < stopgrow)
X {
X plankgrow(2);
X plankgrow(1);
X plank = countplank();
X } --------------------------------------*/
X plank = countplank();
X if (debug >= 7)
X fprintf(stdout, " plank = %d\n", plank);
X printscreen();
X return(1);
X }
X return(0);
X}
X
X/*---------------------------------------------------------------------------*
X@
X@@ void movewhale(one) - Moves whales based on individual genes fired. See
X@@ also comments in genes.c: at top of file, and in genesets()
X@ input : Whole whale list, mvwhle[] & locarr[] arrays
X@ output: .energy field changes & location changes for individual whales
X@ Plankton removed from locarr[]
X@ caller: look(), main()
X@ calls : nextrand(), genesets(), boundstest(), plankcall();
X@ malloc(), may call finish(); may call exit()
X@ proc : First, an overview of the loops in this function:
X@ (1) For the number of move turns this month
X@ (2) For each (live) whale
X@ (3) While this whale still has room to store moves
X@ If whale is in hunt or feed mode?
X@ Hunt mode:
X@ (4) For each gene in a (randomly picked) chromosome
X@ (5) For all the moves that gene stores in mvwhle[],
X@ transfer them to proper place in moves[],
X@ and update the whale's location in locarr[].
X@ Feed mode:
X@ (4)(5), Same basic For-loops
X@ Then, a look at what can cause breaks from the loops:
X@ (5) Constant BRKGENE = 1 will force break in middle
X@ of gene as soon as whale[wich].huntfeed
X@ changes state, otherwise gene 'finishes'
X@ Chngemode is incremented upon .huntfeed change
X@ (4) Variable chngemode > 0 will force break in middle
X@ of chromosome loop
X@ While-loop test is also specifically tested at
X@ this level as well; break is propagated thru
X@ level (3) by variable "endturn"
X@ (3) While-loop test is to make sure each whale's section
X@ of the moves[] array isn't overwritten when
X@ constant NORMAL = 1
X@ If constant NORMAL = 0, only one chromosome per
X@ whale per move will fire (otherwise all whale
X@ moves, regardless of genetypes of whales, will
X@ 'normalize' to the maximum .hgperchr or .fgperchr
X@ of all the whales in the run), so loop is broken
X@ (2) End of loop (3) propagates through this level
X@ (1) Counts through constant MVGRP for number of whale turns this
X@ 'month' (Do-loop with "months" switch statement in main()
X@ can be considered loop level (0)).
X@
X@ Note : All whales get a chance to hunt/feed, then plankton are erased
X@
X@*---------------------------------------------------------------------------*/
X
Xvoid
Xmovewhale()
X{
X register int h, j, test;
X register int wich;
X int e, k, n;
X int *moves;
X int movesdex;
X short chromo;
X short totmvs;
X short maxtotmv;
X short chngemode;
X short endturn;
X int f = 0;
X int mvgroup = MVGRP;
X
X /* Size the maximum number of location changes */
X maxtotmv = MAX(hgpcflg * MAXGMV, fgpcflg * MAXGMV);
X /* Allocate space for storage of location changes */
X moves = (int*) malloc(numwh * maxtotmv * MAXGMV * (sizeof(int)));
X if (moves == NULL)
X {
X if (debug >= 2)
X fprintf(stderr, "\nMoves malloc problems.\n");
X finish(8);
X }
X /* Initialize array */
X for (j = 0; j < numwh * maxtotmv * MAXGMV; j++)
X moves[j] = -1;
X /* Start moving */
X for (k = 0; k < mvgroup; k++)
X {
X /* For each whale */
X for (wich = 0; wich < numwh; wich++)
X {
X totmvs = 0;
X chngemode = 0;
X endturn = 0;
X /* Find this whale's section of moves[] */
X movesdex = wich * maxtotmv * MAXGMV;
X /* If whale is alive */
X if (whale[wich].energy > 9999)
X {
X /* While whale's moves are less than there is space for */
X while (totmvs < maxtotmv)
X {
X /* Is it hunting or feeding? */
X if (whale[wich].huntfeed == 'H')
X {
X /* Pick a chromosome to fire */
X switch(whale[wich].hgperchr - '0')
X {
X case 0:
X chromo = 0;
X randflg = TRUE;
X whale[wich].hgperchr += (Uchar) hgpcflg;
X break;
X case 1:
X chromo = nextrand() & 0xF;
X break;
X case 2:
X chromo = nextrand() & 0xE;
X break;
X case 4:
X chromo = nextrand() & 0xC;
X break;
X case 8:
X chromo = nextrand() & 0x8;
X break;
X case 16:
X chromo = 0;
X break;
X default:
X if (debug >= 2)
X {
X fprintf(stderr,
X "whale[%d].hgperchr = %d,\n",
X wich, whale[wich].hgperchr - '0');
X fprintf(stderr, " must divide into 16\n");
X }
X exit(22);
X }
X /* For each gene in the chromosome */
X for (j = 0; j < whale[wich].hgperchr - '0'; j++)
X {
X whale[wich].huntdex = chromo + j;
X genesets(wich);
X if (totmvs + mvwhle[0] > maxtotmv)
X {
X endturn++;
X break;
X }
X test = whale[wich].locatn;
X /* For each move mapped by the gene */
X for (h = 1; h <= mvwhle[0]; h++)
X {
X /* Hopefully, this test saves some time */
X if ((test <= MAXGMV * vbias) ||
X (test >= area - MAXGMV * vbias))
X {
X n = mvwhle[h];
X n = boundstest(n);
X mvwhle[h] = n;
X }
X /* Assign moves and increment move count */
X moves[movesdex + (totmvs)] = mvwhle[h];
X whale[wich].locatn = mvwhle[h];
X totmvs++;
X /* Found plankton?... */
X if (locarr[whale[wich].locatn] == '.')
X {
X whale[wich].energy += PLUS;
X whale[wich].lastfed = 0;
X chngemode++;
X if (BRKGENE)
X break;
X }
X else /* ...or not */
X {
X whale[wich].energy -= MINUS;
X whale[wich].lastfed++;
X }
X }
X if (chngemode) /* Change from hunt to feed */
X {
X if (whale[wich].lastfed < COUNTVAL)
X whale[wich].huntfeed = 'F';
X chngemode = 0;
X break;
X }
X }
X if (randflg) /* Do resets */
X {
X whale[wich].hgperchr = '0';
X randflg = FALSE;
X }
X if (!NORMAL)
X break;
X if (endturn)
X break;
X }
X else if (whale[wich].huntfeed == 'F')
X {
X /* Pick a chromosome to fire */
X switch(whale[wich].fgperchr - '0')
X {
X case 0:
X chromo = 0;
X randflg = TRUE;
X whale[wich].fgperchr += (Uchar) fgpcflg;
X break;
X case 1:
X chromo = nextrand() & 0xF;
X break;
X case 2:
X chromo = nextrand() & 0xE;
X break;
X case 4:
X chromo = nextrand() & 0xC;
X break;
X case 8:
X chromo = nextrand() & 0x8;
X break;
X case 16:
X chromo = 0;
X break;
X default:
X if (debug >= 2)
X {
X fprintf(stderr,
X "whale[%d].fgperchr = %d,\n",
X wich, whale[wich].fgperchr - '0');
X fprintf(stderr, " must divide into 16\n");
X }
X exit(22);
X }
X /* For each gene in the chromosome */
X for (j = 0; j < whale[wich].fgperchr - '0'; j++)
X {
X whale[wich].feeddex = chromo + j;
X genesets(wich);
X if (totmvs + mvwhle[0] > maxtotmv)
X {
X endturn++;
X break;
X }
X test = whale[wich].locatn;
X /* For each move mapped by the gene */
X for (h = 1; h <= mvwhle[0]; h++)
X {
X /* Hopefully, this test saves some time */
X if ((test <= MAXGMV * vbias) ||
X (test >= area - MAXGMV * vbias))
X {
X n = mvwhle[h];
X n = boundstest(n);
X mvwhle[h] = n;
X }
X /* Assign moves and increment move count */
X moves[movesdex + (totmvs)] = mvwhle[h];
X whale[wich].locatn = mvwhle[h];
X totmvs++;
X /* Found plankton?... */
X if (locarr[whale[wich].locatn] == '.')
X {
X whale[wich].energy += PLUS;
X whale[wich].lastfed = 0;
X }
X else /* ...or not */
X {
X whale[wich].energy -= MINUS;
X whale[wich].lastfed++;
X if (whale[wich].lastfed >= COUNTVAL)
X {
X chngemode++;
X if (BRKGENE)
X break;
X }
X }
X }
X if (chngemode) /* Change from feed to hunt */
X {
X if (whale[wich].lastfed >= COUNTVAL)
X whale[wich].huntfeed = 'H';
X chngemode = 0;
X break;
X }
X }
X if (randflg) /* Do resets */
X {
X whale[wich].fgperchr = '0';
X randflg = FALSE;
X }
X if (!NORMAL)
X break;
X if (endturn)
X break;
X }
X else
X {
X if (debug >= 2)
X fprintf(stderr,
X "movewhale(): whale[].huntfeed != H or F\n");
X exit(22);
X }
X }
X }
X }
X /* Find all the moves (locations) in moves[] and remove plankton */
X /* in locarr[] at those locations */
X for (j = 0; j < numwh * maxtotmv * MAXGMV; j++)
X {
X if (moves[j] >= 0)
X locarr[moves[j]] = ' ';
X }
X /* The following three if()'s playing with variables e & f are to */
X /* get around the times the % operator yields a result of 0 */
X /* twice or more in a row due to rounding */
X if ((k + 1) % (mvgroup / truwh) == 0)
X {
X e = k + 10;
X f++;
X }
X if ((f == 1) && (k > 0))
X {
X if (debug >= 7)
X fprintf(stdout, " Move %5d\n", k);
X if (debug >= 9)
X {
X fprintf(stdout, " hunt moves = %ld\n", aiches);
X fprintf(stdout, " feed moves = %ld\n", effs);
X }
X if (debug >= 9)
X for (j = 0; j < numwh; j++)
X fprintf(stdout, "Whale %3d has %8d energy.\n",
X j, whale[j].energy);
X /* Test for low plankton population & regrow, if necessary */
X j = plankcall();
X if (j) /* Re-initialize array of location changes */
X {
X for (j = 0; j < numwh * maxtotmv * MAXGMV; j++)
X moves[j] = -1;
X }
X f++;
X }
X if ((k == e) || ((k + 1) == mvgroup))
X f = 0;
X }
X if (debug >= 7)
X fprintf(stdout, " Move %5d\n", k);
X if (debug >= 9)
X for (wich = 0; wich < numwh; wich++)
X fprintf(stdout, " Whale %3d has %8d energy.\n",
X wich, whale[wich].energy);
X free((char *) moves);
X}
X
X/*---------------------------------------------------------------------------*
X@
X@@ void main(argc, argv) - Calling function for whpl.c and associated files.
X@ input : Constants from whpl.h and command line arguments.
X@ output: Most output comes from other functions called directly or indir-
X@ ectly from here, including finish(), which handles most of the
X@ program's file output.
X@ calls : ophandle(), randinit(), whaleinit(), finish(), countwhales(),
X@ clearlocarr(), plankplace(), countplank(), printscreen(),
X@ plankgrow(), movewhale(), whaleplace(), whaledie(), interim(),
X@ look(), mate()
X@ proc : There are three basic sections to this function:
X@ First, the whales are initialized, either randomly, or by a read
X@ from a whale file (call to whaleinit). Command line opts
X@ heavily condition how these two sources of whales are combined.
X@ Second, other initializations take place, including the plankton,
X@ which are then grown into their normal population range.
X@ Finally comes the main program loops which control the timing of
X@ the ecology's overall events; hunting, eating, mating, dying.
X@
X@ Note : The variables "months" and "year" do not have the chronological
X@ meaning normally associated with them on Earth. Months is
X@ the loop variable and switch value used in the main control
X@ do-loop, while year is normally incremented when mate() is
X@ called, and used in computations involving the "age" of speci-
X@ fic whales. "cycle", incremented once each time through the
X@ main control do-loop, cooresponds better to our earthly notion
X@ of a year. The "MONTHS" constant in whpl.h sets the number of
X@ months per cycle.
X@ In the version 1.10 release of this function, one cycle equals
X@ 5 years. This can have an unexpected effect on the -y option,
X@ e.g., using -y6 on the command line will actually create 10
X@ generations of whales, rather than 6, due to this granularity.
X@ If you modify the do-loop to call mate() only once, then one
X@ cycle will equal one year.
X@
X@ Note : Variable "dielim" is changed dynamically in the present (whpl.c
X@ v1.10) release version of this function. This variable has
X@ the most effect of any as far as keeping the whale population
X@ steady. Setting it to 2 for two mate cycles and to 1 for
X@ three seems to do reasonably well. When, (in relation to
X@ mate()), and how often, whaledie() is called also has an
X@ effect on whether whales generaly increase or decrease.
X@
X@*---------------------------------------------------------------------------*/
X
Xvoid
Xmain(argc, argv)
X int argc;
X char *argv[];
X{
X static int months;
X int j = FNMTRUNC - 1;
X char datr[11];
X char temp[11];
X Uint dater;
X int plank;
X short pre = 0;
X short post = 0;
X short cycle = 0;
X
X /* Do some simple tests on constants ? */
X
X /* Get command line args */
X ophandle(argc, argv);
X /* Initialize random number generators */
X randinit();
X /* Other initializations */
X regrow = area / 6;
X stopgrow = area / 3;
X /* Will we be looking at whale tracks? (Use of -t option restricts
X locarr[] array size to 288 * 225 pixels) */
X if(trakflg)
X {
X area = 64800;
X vbias = 225;
X }
X /* Initialize location array and scratch array */
X locarr = (Uchar*) malloc(area);
X if (locarr == NULL)
X {
X if (debug >= 2)
X fprintf(stderr, "\nlocarr malloc problems.\n\n");
X exit(8);
X }
X secarr = (Uchar*) malloc(area);
X if (secarr == NULL)
X {
X if (debug >= 2)
X fprintf(stderr, "\nsecarr malloc problems.\n\n");
X exit(8);
X }
X /* Are we just browsing... */
X if(trakflg)
X {
X look();
X exit(0);
X }
X /* ...or running the program? */
X if (debug >= 5)
X fprintf(stdout, "\n\n RUN %u\n\n", daterun);
X /* Create archive file name */
X if (!wharcflg)
X {
X dater = daterun / 10000;
X dater *= 100;
X sprintf(temp, "%8u", dater);
X do{
X j++;
X datr[j - FNMTRUNC] = temp[j];
X } while (temp[j] != '\0');
X strcat(wharcfile, "wha");
X strcat(wharcfile, datr);
X }
X /* Initialize whales */
X whaleinit();
X countwhales();
X /* We've initialized the whales, now let's init the plankton: */
X clearlocarr();
X plankplace(1, 0);
X plank = countplank();
X if (debug >= 5)
X fprintf(stdout, " Seeded plankton = %7d\n", plank);
X printscreen();
X for (j = 0; j < 4; j++)
X plankgrow(1);
X plank = countplank();
X if (debug >= 7)
X fprintf(stdout, " Interim plankton = %7d\n", plank);
X printscreen();
X plankgrow(2);
X plankgrow(1);
X plank = countplank();
X if (debug >= 5)
X fprintf(stdout, " Final initial plankton = %7d\n\n", plank);
X printscreen();
X /* One finial initialization step; tune Wa-Tor to this set of whales: */
X pre = 6; /* <-- Remove this line to bypass the "pre" loop altogether */
X if (pre)
X {
X if (debug >= 5)
X fprintf(stdout, "Conditioning world for %d months\n", pre);
X for (months = 1; months <= pre; months++)
X {
X movewhale();
X if (debug >= 5)
X fprintf(stdout, " %2d\n", months);
X }
X for (j = 0; j < numwh; j++)
X {
X whale[j].locatn = whaleplace();
X whale[j].energy = 1000000;
X whale[j].lastfed = 1000000;
X }
X }
X /* Now to get into the run for real: */
X dielim = 1; /* Set here just to make sure it's set to a reasonable value */
X do{
X cycle++; /* Number of times through the do-loop */
X /* Count up through the 'months' from 1, THRU the value of MONTHS */
X for (months = 1; months <= MONTHS; months++)
X {
X if (debug >= 7)
X fprintf(stdout, "\nCycle %d, Month %d\n", cycle, months);
X if (debug >= 7)
X fprintf(stdout, " Year %d\n", year);
X switch(months) /* So what do we do with each new 'month'? */
X {
X case 1:
X dielim = 2; /* <-- Whale population tends to increase */
X movewhale();
X break;
X case 13:
X dielim = 1; /* <-- Whale population tends to decrease */
X movewhale();
X break;
X case 6:
X case 12:
X case 18:
X case 24:
X case 30:
X /* Be somewhat careful about changing the order of these
X statements. Nothing is likely to break, but output
X based on year value may not be so meaningful: check
X the functions themselves. Also, it's safest to
X call interim() before mate() to help keep within
X the maximum allowable number of whales */
X year++;
X movewhale();
X whaledie(1);
X /* Save whales to file & reallocate live ones */
X if (numwh > interlim) /* default limit about 3/5 of MAXWH */
X interim();
X mate();
X break;
X default: /* <-- All cases not specifically numbered above */
X movewhale(); /* This, then, gets called every month */
X break;
X }
X }
X if (debug >= 7)
X fprintf(stdout, "Cycle %d, Month %d\n", cycle, months);
X if (debug >= 7)
X fprintf(stdout, " Year %d\n", year);
X /* Should't remove this! Modify SAFETY in whpl.h, if necessary: */
X if (cycle >= SAFETY)
X {
X if (debug >= 2)
X fprintf(stderr,
X "\nmain(): EXIT FROM MAIN LOOP: cycle > SAFETY\n\n");
X if (debug >= 6)
X fprintf(stdout,
X "\nmain(): EXIT FROM MAIN LOOP: cycle > SAFETY\n\n");
X break;
X }
X if (year >= yearflg)
X {
X break; /* <-- NORMAL EXIT FROM MAIN DO LOOP */
X }
X } while (1); /* do-loop continues */
X /* Run whales some more to get their final energy rankings: */
X post = 12; /* <-- Remove this line to bypass the "post" loop altogether */
X if (post)
X {
X if (debug >= 5)
X fprintf(stdout, "Final whale moves for %d months\n", post);
X for (months = 1; months <= post; months++)
X {
X movewhale();
X if (months == 3 || months == 7)
X {
X for (j = 0; j < numwh; j++)
X {
X whale[j].locatn = whaleplace();
X whale[j].lastfed = 1000000;
X }
X }
X if (debug >= 5)
X if (!(months % 2))
X fprintf(stdout, " %2d\n", months);
X }
X }
X if (debug >= 5)
X fprintf(stdout, "main(): finishing run\n");
X if (debug >= 6)
X fprintf(stderr, "main(): finishing run\n");
X /* I prefer to trim the whales' numbers one last time */
X whaledie(0);
X /* Final computations and file output */
X finish(1);
X}
SHAR_EOF
if test 29028 -ne "`wc -c < 'whx.c2'`"
then
echo shar: error transmitting "'whx.c2'" '(should have been 29028 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
---
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
Bob Loy | Life is the detour you take on the
...!sun!sunburn!gtx!loy | way to where you're really going.
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
More information about the Comp.sources.misc
mailing list