Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!apple!olivea!uunet!sparky!kent From: allen@viewlogic.com (Dave Allen) Newsgroups: comp.sources.misc Subject: v18i003: planet - planet generation simulator, Part03/04 Message-ID: <1991Apr8.002437.9756@sparky.IMD.Sterling.COM> Date: 8 Apr 91 00:24:37 GMT Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield) Organization: Sterling Software, IMD Lines: 1365 Approved: kent@sparky.imd.sterling.com X-Checksum-Snefru: 83dce486 fb347f82 d35ee257 adf373f8 Submitted-by: Dave Allen Posting-number: Volume 18, Issue 3 Archive-name: planet/part03 Supersedes: tec: Volume 10, Issue 77-78 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh src/Makefile <<'END_OF_src/Makefile' XLIBS = -lm -lXaw -lXt -lXmu -lX11 -lXext XFLAGS = XCOBJ = clim.o heat.o pressure.o wind.o rain.o climate.o fileio.o XTOBJ = tec1.o tec2.o tec3.o fileio.o XGOBJ = globe.o fileio.o XGRAF = x X X# Change GRAF from x to unix to produce text-only versions X Xall: clim tec globe X Xclim: $(COBJ) $(GRAF).o; cc $(FLAGS) -o clim $(COBJ) $(GRAF).o $(LIBS) Xtec: $(TOBJ) $(GRAF).o; cc $(FLAGS) -o tec $(TOBJ) $(GRAF).o $(LIBS) Xglobe: $(GOBJ) $(GRAF).o; cc $(FLAGS) -o globe $(GOBJ) $(GRAF).o $(LIBS) X Xtec1.o: tec1.c const.h tec.h; cc $(FLAGS) -c tec1.c Xtec2.o: tec2.c const.h tec.h; cc $(FLAGS) -c tec2.c Xtec3.o: tec3.c const.h tec.h; cc $(FLAGS) -c tec3.c X Xglobe.o: globe.c const.h; cc $(FLAGS) -c globe.c X Xclim.o: clim.c const.h clim.h; cc $(FLAGS) -c clim.c Xheat.o: heat.c const.h clim.h; cc $(FLAGS) -c heat.c Xpressure.o: pressure.c const.h clim.h; cc $(FLAGS) -c pressure.c Xwind.o: wind.c const.h clim.h; cc $(FLAGS) -c wind.c Xrain.o: rain.c const.h clim.h; cc $(FLAGS) -c rain.c Xclimate.o: climate.c const.h clim.h; cc $(FLAGS) -c climate.c X Xfileio.o: fileio.c const.h clim.h; cc $(FLAGS) -c fileio.c Xunix.o: unix.c const.h; cc $(FLAGS) -c unix.c Xx.o: x.c const.h clim.h; cc $(FLAGS) -c x.c END_OF_src/Makefile if test 1309 -ne `wc -c src/clim.h <<'END_OF_src/clim.h' X#define MAXB 4 X#define LINE_DIAG 1 X#define LINE_CORN 2 X#define LINE_0V 1 X#define LINE_1V 2 X#define LINE_0H 4 X#define LINE_1H 8 X#define N LINE_0V X#define S LINE_1V X#define E LINE_0H X#define W LINE_1H X#define PR_LOW 1 X#define PR_HIGH 2 X#define PR_HEQ 3 X#define M_MAIN 0 X#define M_HEAT 1 X#define M_PRESS 2 X#define M_WIND 3 X#define M_RAIN 4 X#define M_CLIM 5 X#define C_OCEAN 0 X#define C_BARELAND 1 X#define C_MOUNTAIN 2 X#define C_OCEANICE 3 X#define C_TUNDRA 4 X#define C_STEPPE 5 X#define C_DESERT 6 X#define C_SAVANA 7 X#define C_DECID 8 X#define C_JUNGLE 9 X#define C_SWAMP 10 END_OF_src/clim.h if test 675 -ne `wc -c src/fileio.c <<'END_OF_src/fileio.c' X/* This program is Copyright (c) 1991 David Allen. It may be freely X distributed as long as you leave my name and copyright notice on it. X I'd really like your comments and feedback; send e-mail to X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore X Avenue, Maynard, MA 01754. */ X X/* This file contains all of the file input and output routines; putmat() X is the output routine. The function getparam() is called to start the X parameter file input; the routines to read in the parameters follow. */ X X#include "const.h" X#include "clim.h" X#include X X/* The input is handled by one function, gettoken(), which returns one X of the following codes each time it is called. */ X#define TOK_EOF 0 X#define TOK_OPEN 1 X#define TOK_CLOSE 2 X#define TOK_WORD 3 X X X/* These parameters are needed by every source file; they are defined X in main.c and described in params.doc */ X Xextern int XSIZE, YSIZE, BSIZE, ZCOAST, PRINTMODE; X X/* The file pointer is used to read the parameters from a file. Linecount X is incremented each time a newline is read from the file, so error X messages can refer to a line number. Getbuf is the buffer each word X is read into. Getfname is a private copy of the filename used, so it X can be reread if needed. The two lookup tables are used by putmat(); X scalelut is set up by init(). Change is set by any of the parameter X input routines which change a parameter. */ Xstatic FILE *fp; Xstatic int linecount = 1; Xstatic char getbuf [256]; Xchar scalelut[256], shortlut[] = "0123456789ABCDEF"; Xextern int change[]; X X Xusermessage (s) char *s; { fprintf (stderr, "%s\n", s); } X X Xfileinit () { int i; for (i=0; i<256; i++) scalelut[i] = shortlut[i>>4]; } X X Xputmat (s, buf, mode, cra, lra) X char *s; int buf, mode; unsigned char cra[MAXX][MAXY], lra[MAXX][MAXY]; { X register int i, j, k; X X if (mode == PRINTMODE_CLIM) { psprint (cra, lra, 1); return (0); } X else if (PRINTMODE == PRINTMODE_GREY) { X psprint (cra, lra, 0); return (0); } X X if (buf > -1) printf ("(%s %d (\n", s, buf); X else printf ("(%s (\n", s); X X if (PRINTMODE == PRINTMODE_LONG) X for (j=0, k=0; j 9) c = 10 + getbuf[i] - 'A'; X if (c != m[i][j]) change[chg] = 1; m[i][j] = c; } X if (i > *dim1) geterr ("string too long"); X if (i > imax) imax = i; j++; } X if (x != TOK_CLOSE) geterr ("expected close paren"); X if ((*dim1 != imax) || (*dim2 != j)) change[chg] = 1; X *dim1 = imax; *dim2 = j; } X X Xgetlvec (dim, v, chg) int *dim, *v, chg; { X /* This function expects to find a list of ints, starting with an open X paren and ending with a close paren. The parameter dim should contain the X compiled-in array limit; if the input file contains more than this number X of entries, the function spits up. No type checking is done; atoi() is X used to convert any text to an int. On exit, the dimension is set to X the right value. If either the dimension, or any of the elements, have X changed from the previous values, change[chg] is set to one. */ X X int x, i = 0, n; X X if (gettoken (getbuf) != TOK_OPEN) geterr ("expected open paren"); X while ((x = gettoken (getbuf)) == TOK_WORD) { X if (i == *dim) geterr ("vector too long"); X n = atoi (getbuf); X if (n != v[i]) change[chg] = 1; v[i++] = n; } X if (x != TOK_CLOSE) geterr ("expected close paren"); X if (i != *dim) change[chg] = 1; *dim = i; } X X Xgetdim (x, chg) int *x, chg; { int y; X /* Called right after reading a name associated with an array bound, X this function reads one int from the input file; if the value is X greater than the default value assigned above, the user is trying X to exceed a compiled-in limit. That's an error. */ X X if (gettoken (getbuf) != TOK_WORD) geterr ("expected int"); X y = atoi (getbuf); X if (y > *x) geterr ("dimension exceeds reserved space"); X *x = y; change[chg] = 1; } X X Xgetdvec (dim, v, chg) int *dim; double *v; int chg; { X /* Called right after reading a name associated with a one-dimensional X array of doubles, this function expects to find a list of doubles X starting with an open paren and ended by a closing paren. The parameter X dim contains the compiled-in array limit; if the input file contains X more than this number of entries, the function complains. No type checking X is done; atof() is used to convert any text to a double. On exit, the X dimension is set to the correct value. */ X X int x, i = 0; X X if (gettoken (getbuf) != TOK_OPEN) X geterr ("expected open paren"); X while ((x = gettoken (getbuf)) == TOK_WORD) { X if (i == *dim) geterr ("vector is too long"); X v[i++] = atof (getbuf); } X if (x != TOK_CLOSE) geterr ("expected close paren"); X *dim = i; change[chg] = 1; } X X X#define D ((double) 648 / XSIZE) X#define XX(x) (72 + ((x) * D)) X#define YY(y) (72 + ((y) * D)) X Xstatic char *psdef[] = { X "/b { setgray moveto d 0 rlineto 0 d rlineto d neg 0 rlineto fill", X "/v { moveto d 0 rlineto stroke", X "/h { moveto 0 d rlineto stroke", X "/x { moveto d d rlineto d neg 0 rmoveto d d neg rlineto stroke", X "/p { moveto e 0 rmoveto 0 d rlineto e neg dup rmoveto d 0 rlineto stroke", X 0 }; Xstatic double climlut[] = { 0.00, 0.00, 0.00, 0.95, 0.95, 0.85, 0.70, 0.55, X 0.40, 0.70, 0.70 }; Xextern double greyscale (); X X Xpsprint (cra, lra, doclim) X unsigned char cra[MAXX][MAXY], lra[MAXX][MAXY]; int doclim; { X register int i, j, k; double z; X static int firstpage = 1; X X if (firstpage) { X printf ("%%!PS-Adobe-1.0\n/d %4.2f def /e %4.2f def\n", D, D/2); X firstpage = 0; X for (i=0; psdef[i]; i++) printf ("%s } bind def\n", psdef[i]); } X printf ("%6.2f %6.2f moveto\n", XX(-0.25), YY(-0.25)); X printf ("%6.2f %6.2f lineto\n", XX(YSIZE+0.25), YY(-0.25)); X printf ("%6.2f %6.2f lineto\n", XX(YSIZE+0.25), YY(XSIZE+0.25)); X printf ("%6.2f %6.2f lineto\n", XX(-0.25), YY(XSIZE+0.25)); X printf ("%6.2f %6.2f lineto\nstroke\n", XX(-0.25), YY(-0.25)); X X if (doclim) { X for (j=0; j 0.0) printf ("%6.2f %6.2f %5.4f b\n", XX(j), YY(i), z); } X printf ("0 setgray\n"); X for (j=0; j 0.0) printf ("%6.2f %6.2f %5.4f b\n", XX(j), YY(i), z); } X X printf ("0 setgray\n"); X if (lra) for (j=0; jsrc/clim.c <<'END_OF_src/clim.c' X/* This program is Copyright (c) 1991 David Allen. It may be freely X distributed as long as you leave my name and copyright notice on it. X I'd really like your comments and feedback; send e-mail to X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore X Avenue, Maynard, MA 01754. */ X X/* This file contains all of the general-purpose routines which are not X machine specific: init, mainpar (called by fileio), onestep (called X by the machine-specific control routine), and the range-finding X function called by several computation routines. */ X X#include "const.h" X#include "clim.h" X X/* L holds the land values everybody starts with; lm is an edge map with X continents outlined in black and mountains outlined in white. */ Xunsigned char l[MAXX][MAXY], lm[MAXX][MAXY]; X X X/* These are the parameters used by all of the climate functions. They are X described in params.doc. */ Xint XSIZE = MAXX, YSIZE = MAXY, BSIZE = MAXB; Xint PRINTMODE = PRINTMODE_SHORT, MAXRANGE = 15; Xint MAXSTEP = 10000, ZCOAST = 0; X Xint change[] = { 1, 1, 1, 1, 1, 1 }, step = 0; Xextern int picktype; X X Xinit (s) char *s; { X if (s && *s) getparams (s); X fileinit (); X heatcomp (); presscomp (); windcomp (); X raincomp (); climcomp (); } X X Xonestep () { X switch (picktype) { X case M_HEAT: heatdraw (step % MAXB); break; X case M_PRESS: pressdraw (step % MAXB); break; X case M_WIND: windraw (step % MAXB); break; X case M_RAIN: raindraw (step % MAXB); break; X case M_CLIM: climdraw (); break; } } X X Xmainpar (s) char *s; { X /* This function is called by getparams() in fileio.c; it looks at each X parameter name read from the input file. If it recognizes the name, X the right function is called to set that parameter. The function X returns true if it recognizes the parameter name, and false otherwise. */ X X if (CMP ("LAND")) getland (); X else if (CMP ("BSIZE")) getlng (&BSIZE, M_MAIN); X else if (CMP ("MAXRANGE")) getlng (&MAXRANGE, M_MAIN); X else if (CMP ("PRINTMODE")) getlng (&PRINTMODE, M_MAIN); X else if (heatpar (s)) { } X else if (presspar (s)) { } X else if (windpar (s)) { } X else if (rainpar (s)) { } X else if (climpar (s)) { } X else return (0); X return (1); } X X Xgetland () { register int i, j, x; X /* This function is called by mainpar, above, when the LAND parameter X is encountered. It just calls getmat in fileio.c to do the work, but X then it also creates an edge map lm; this is used by a couple of the X drawing routines as background. */ X X getmat (&XSIZE, &YSIZE, M_MAIN, l); X X for (j=0; j 0) != (l[i-1][j] > 0)) x |= LINE_0V; X if (j) if ((l[i][j] > 0) != (l[i][j-1] > 0)) x |= LINE_0H; X X /* If both black and white lines are present, white wins */ X if ((x & LINE_0V) && (x & LINE_1V)) x &= (~LINE_0V); X if ((x & LINE_0H) && (x & LINE_1H)) x &= (~LINE_0H); X lm[i][j] = x; } } X X Xrange (rr) char rr[MAXX][MAXY]; { X /* This function is called by a number of climate routines. It takes an X input array with blobs of -1's on a background of 0's. The function winds X up replacing each 0 with the distance from that square to the nearest -1. X The function onerange() does all the work, but it will not compute ranges X greater than MAXRANGE. Therefore, after onerange() is called, any remaining X 0 values must be replaced with MAXRANGE, indicating that that square is X "very far" from any -1 value. */ X X register int i, j; X X onerange (rr); checkmouse (); X for (j=0; jsrc/heat.c <<'END_OF_src/heat.c' X/* This program is Copyright (c) 1991 David Allen. It may be freely X distributed as long as you leave my name and copyright notice on it. X I'd really like your comments and feedback; send e-mail to X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore X Avenue, Maynard, MA 01754. */ X X/* This file contains the routines that compute local temperatures */ X X#include "const.h" X#include "clim.h" X X/* Some private defines. FREEZING is 0 degrees C in Kelvin; DEG2RAD is the X conversion factor from angular degrees to radians. */ X X#define FREEZING 273.0 X#define PI 3.14159 X#define DEG2RAD (PI / 180) X X/* The input array is l, from main.c; lm is used by heatdraw(). The output X array is ts, containing temperatures. Array t is an unscaled copy of the X temperatures; tmin and tmax are used for scaling, and tscale is the X computed scale factor. To convert the unscaled temperatures to degrees K, X divide by TEMPSCALE. */ X Xextern unsigned char l[MAXX][MAXY], lm[MAXX][MAXY]; Xunsigned char ts[MAXB][MAXX][MAXY]; Xint tt[MAXB][MAXX][MAXY], tmax, tmin; Xdouble tscale; int TEMPSCALE = 10; X X/* These parameters are defined in main.c */ X Xextern int BSIZE, XSIZE, YSIZE, PRINTMODE; X X/* These parameters are used here, and are described in params.doc */ X Xint PRINTEMP = 0; Xdouble TILT = 23.0, ECCENT = 0.0, ECCPHASE = 0.0; Xdouble LCOS = 45.0, LCONST = 275.0, LTILT = 1.0, LSMOOTH = 0.6, LDIV = 180.0; Xdouble OCOS = 30.0, OCONST = 275.0, OTILT = 0.2, OSMOOTH = 0.2, ODIV = 250.0; X X Xheatpar (s) char *s; { X /* This function is called by mainpar() in main.c; it simply tests input X parameter names to see if they are defined in this file. Each of the X above ints are defined in this file. If the input string matches here, X the function returns true. */ X if (CMP ("TILT")) getdbl (&TILT, M_HEAT); X else if (CMP ("ECCENT")) getdbl (&ECCENT, M_HEAT); X else if (CMP ("ECCPHASE")) getdbl (&ECCPHASE, M_HEAT); X X else if (CMP ("LCOS")) getdbl (&LCOS, M_HEAT); X else if (CMP ("LCONST")) getdbl (&LCONST, M_HEAT); X else if (CMP ("LTILT")) getdbl (<ILT, M_HEAT); X else if (CMP ("LSMOOTH")) getdbl (&LSMOOTH, M_HEAT); X else if (CMP ("LDIV")) getdbl (&LDIV, M_HEAT); X X else if (CMP ("OCOS")) getdbl (&OCOS, M_HEAT); X else if (CMP ("OCONST")) getdbl (&OCONST, M_HEAT); X else if (CMP ("OTILT")) getdbl (&OTILT, M_HEAT); X else if (CMP ("OSMOOTH")) getdbl (&OSMOOTH, M_HEAT); X else if (CMP ("ODIV")) getdbl (&ODIV, M_HEAT); X X else if (CMP ("PRINTEMP")) getlng (&PRINTEMP, M_HEAT); X else return (0); X return (1); } X X Xheatlut (x, s) int x; char *s; { X /* After the heatcomp routine is finished, a scale factor is computed X for converting degrees K to 0..255; this routine converts back. Functions X in the machine-dependent code can call here to print map keys. The caller X must provide a char buffer; a string containing degrees F is put there. */ X X double temp; X X temp = (((double) x / tscale) + (double) tmin) / TEMPSCALE; X temp = (temp - FREEZING) * 1.8 + 32; X sprintf (s, "%6.1f", temp); } X X Xheatcomp () { X /* This is the main routine for computing temperatures. After getheat() X is called to do all the work, this routine takes the ints from t and X finds the smallest and largest values. These are used to compute a scale X factor, tscale; the arrays ts are then filled with scaled values. Finally, X putmat() from main.c is called if needed to print results. */ X X register int i, j, buf; char s[20]; X X getheat (); tmin = 32000; tmax = 0; X X usermessage ("Scaling heat"); X /* Find minimum and maximum across all buffers */ X for (buf=0; buf tmax) tmax = tt[buf][i][j]; } } X X /* Compute scale; for every buffer, fill ts from t */ X tscale = 254.0 / ((double) (tmax - tmin)); X for (buf=0; buf 2.0 * PI) phase -= (2 * PI); X fact = (1.0 + ECCENT * cos (phase)) * TEMPSCALE; X x = (lat + cos (theta) * TILT * LTILT) * lscl; X tland[buf] = (LCONST + LCOS * cos (x)) * fact; X x = (lat + cos (theta) * TILT * OTILT) * sscl; X tsea[buf] = (OCONST + OCOS * cos (x)) * fact; } X for (i=0; i= YSIZE) jmax = YSIZE-1; X for (j1=jmin; j1<=jmax; j1++) for (i0=-5; i0<6; i0++) { X i1 = i0 + x; if (i1 < 0) i1 += XSIZE; X if (i1 >= XSIZE) i1 -= XSIZE; X sum += l[i1][j1]; } X return (sum); } END_OF_src/heat.c if test 6893 -ne `wc -c src/pressure.c <<'END_OF_src/pressure.c' X/* This program is Copyright (c) 1991 David Allen. It may be freely X distributed as long as you leave my name and copyright notice on it. X I'd really like your comments and feedback; send e-mail to X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore X Avenue, Maynard, MA 01754. */ X X/* This file contains the routines to compute global high and low X pressure areas. */ X X#include "const.h" X#include "clim.h" X X/* These are the data arrays required: l is an input array defining the X ocean, land and mountain areas; ts is the temperature array computed X by the functions in heat.c. Array pr is filled by ocean(), land() and X heateq(), below; PR_HIGH indicates a high pressure zone, PR_LOW indicates X a low, and PR_HEQ indicates the heat equator, a low zone. Array pm is X the output array for this file, and it contains an edge map which has X edges in color 1 surrounding lows and color 0 around highs. Array r is X temporary storage for local calls to range() in main.c. */ X Xextern unsigned char l[MAXX][MAXY], ts[MAXB][MAXX][MAXY]; Xstatic char r[MAXX][MAXY]; Xstatic unsigned char pm[MAXB][MAXX][MAXY]; Xunsigned char pr[MAXB][MAXX][MAXY]; X X X/* The externs below are declared in main.c; they represent global parameters. X The ints are described in params.doc. */ X Xextern int BSIZE, XSIZE, YSIZE, PRINTMODE; Xint OOTHRESH = 5, OLTHRESH = 1, LOTHRESH = 3, LLTHRESH = 7; Xint OHMIN = 130, OHMAX = 180, OLMIN = 40, OLMAX = 65; Xint LHMIN = 0, LHMAX = 20, LLMIN = 220, LLMAX = 255; Xint PRINTPR = 0; X X Xpresspar (s) char *s; { X /* This function is called by mainpar() in main.c; it simply tests input X parameters to see if they are defined in this file. Each of the above X ints is referred to in this function. If an input string matches here, X the function returns true. */ X if (CMP ("OOTHRESH")) getlng (&OOTHRESH, M_PRESS); X else if (CMP ("OLTHRESH")) getlng (&OLTHRESH, M_PRESS); X else if (CMP ("OHMIN")) getlng (&OHMIN, M_PRESS); X else if (CMP ("OHMAX")) getlng (&OHMAX, M_PRESS); X else if (CMP ("OLMIN")) getlng (&OLMIN, M_PRESS); X else if (CMP ("OLMAX")) getlng (&OLMAX, M_PRESS); X X else if (CMP ("LOTHRESH")) getlng (&LOTHRESH, M_PRESS); X else if (CMP ("LLTHRESH")) getlng (&LLTHRESH, M_PRESS); X else if (CMP ("LHMIN")) getlng (&LHMIN, M_PRESS); X else if (CMP ("LHMAX")) getlng (&LHMAX, M_PRESS); X else if (CMP ("LLMIN")) getlng (&LLMIN, M_PRESS); X else if (CMP ("LLMAX")) getlng (&LLMAX, M_PRESS); X X else if (CMP ("PRINTPR")) getlng (&PRINTPR, M_PRESS); X else return (0); X return (1); } X X Xpresscomp () { X /* The main routine for this file. It just calls the four routines X which do all the work. Ocean() finds pressure extremes on the ocean; X land() does the same for land; heateq() defines the heat equator, and X setpm() computes pm[][] from pr[][]. */ X X int buf; X X for (buf=0; buf OLTHRESH) ? -1 : 0; X range (r); X X /* For each array element, if it is at least OOTHRESH squares from the X nearest big piece of land, it might be the center of an ocean pressure X zone. The pressure zones are defined by temperature ranges; if the X temperature in ts is between OLMIN and OLMAX, a low is recorded, while X if the temperature is between OHMIN and OHMAX, a high is recorded. */ X for (j=0; j OOTHRESH) { X if ((x >= OLMIN) && (x <= OLMAX)) pr[buf][i][j] = PR_LOW; X if ((x >= OHMIN) && (x <= OHMAX)) pr[buf][i][j] = PR_HIGH; } } } X X Xland (buf) int buf; { X /* This function is simply the complement of ocean(): it finds land highs X and lows. A land high or low must occur over land, far from major oceans. X Two calls to range() are made to find the qualifying land areas; then X temperature criteria are used to select the actual pressure zones. */ X X register int i, j; int x; X X /* Set r to distance on water from coast. */ X for (j=0; j LOTHRESH) ? -1 : 0; X range (r); X X /* For each array element, if it is at least LLTHRESH squares from the X nearest large ocean, it might be the center of a land pressure zone. X The pressure zones are defined by temperature ranges; if the temperature X in ts is between LLMIN and LLMAX, a low is recorded, while if the X temperature is between LHMIN and LHMAX, a high is recorded. */ X for (j=0; j LLTHRESH) { X if ((x >= LLMIN) && (x <= LLMAX)) pr[buf][i][j] = PR_LOW; X if ((x >= LHMIN) && (x <= LHMAX)) pr[buf][i][j] = PR_HIGH; } } } X X Xfindheq (buf) int buf; { X /* This function finds the heat equator and marks it in pr. For each X vertical column of ts, the median position is found and marked. To X make the heat equator continuous, jlast is set to the position of the X heat equator in the previous column; a connection is made in the present X column to ensure continuity. */ X X register int i, j; int sum, jlast = 0, jnext; X X for (i=0; i>=1, j=0; j0; j++) sum -= ts[buf][i][j]; X X /* Mark this position and remember it with jnext */ X pr[buf][i][j] = PR_HEQ; jnext = j; X X /* For each column except the first (where i = 0), if the last heat X equator is above this one, move upwards to it, marking each square, X to ensure continuity; if below this one, move downwards to it. */ X X if (i && (j > jlast)) for (; j>=jlast; j--) pr[buf][i][j] = PR_HEQ; X else if (i && (j < jlast)) for (; j<=jlast; j++) pr[buf][i][j] = PR_HEQ; X X /* Remember this position for the next column. Note that no check is X done to ensure continuity at the wraparound point; this is bad. */ X jlast = jnext; } } X X Xsetpm (buf) int buf; { X /* Setpm() is called after the above three functions have filled pr with X the codes for high, low and heat equator. The purpose of this function X is to create an edge map surrounding lows with color 1 and highs with X color 0. */ X X register int i, j, k; int col; X X for (j=0; jsrc/wind.c <<'END_OF_src/wind.c' X/* This program is Copyright (c) 1991 David Allen. It may be freely X distributed as long as you leave my name and copyright notice on it. X I'd really like your comments and feedback; send e-mail to X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore X Avenue, Maynard, MA 01754. */ X X/* This file contains the wind computation routines. */ X X#include "const.h" X#include "clim.h" X#define MAXPRESS 255 X X/* Input arrays are pr, from pressure.c, and l, from main.c. The array X hl is used as temporary storage for highs and lows, while p is used X to store the smoothed pressure map. The output array, wd, contains X an edge map with wind directions. */ X Xextern unsigned char pr[MAXB][MAXX][MAXY], l[MAXX][MAXY]; Xunsigned char wd[MAXB][MAXX][MAXY]; Xstatic char hl[2][MAXX][MAXY]; Xstatic unsigned char p[MAXX][MAXY]; X X/* The externs below are parameters defined in main.c. The other two ints X are parameters described in params.doc. */ X Xextern int XSIZE, YSIZE, BSIZE, PRINTMODE; Xint BARSEP = 16, PRINTWIND = 0; X X Xwindpar (s) char *s; { X /* This function is called by mainpar() in main.c; it simply checks to X see if the parameter is defined in this file. If so, it returns true. */ X if (CMP ("BARSEP")) getlng (&BARSEP, M_WIND); X else if (CMP ("PRINTWIND")) getlng (&PRINTWIND, M_WIND); X else return (0); X return (1); } X X Xwindcomp () { X /* This is the main function in this file; it calls getpress() to create X a smoothed pressure map, then getwind() to put isobars (wind lines) on X the output map. The last step makes sure that contradictory winds are X removed, such as N and S winds in the same square. */ X X register int i, j, x, buf; X X for (buf=0; buf= bar)) wd[buf][i][j] |= (e ? E : W); X if ((a >= bar) && (b < bar)) wd[buf][i][j] |= (e ? W : E); } X X /* Compare the pressure here to the pressure one square to the left */ X /* (including wraparound); this gives the wind direction in terms */ X /* of north / south flow. */ X b = i ? p[i-1][j] : p[XSIZE-1][j]; X if ((a < bar) && (b >= bar)) wd[buf][i][j] |= (e ? N : S); X if ((a >= bar) && (b < bar)) wd[buf][i][j] |= (e ? S : N); } } } END_OF_src/wind.c if test 5268 -ne `wc -c src/rain.c <<'END_OF_src/rain.c' X/* This program is Copyright (c) 1991 David Allen. It may be freely X distributed as long as you leave my name and copyright notice on it. X I'd really like your comments and feedback; send e-mail to X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore X Avenue, Maynard, MA 01754. */ X X/* This file contains the routines to compute rainfall. */ X X#include "const.h" X#include "clim.h" X X/* The input data arrays are l and lm, from main.c, wd, from wind.c, X and pr, from pressure.c. Output arrays are rm and rn; fr and fs are X used as temporary storage. */ X Xextern unsigned char l[MAXX][MAXY], lm[MAXX][MAXY], wd[MAXB][MAXX][MAXY]; Xextern unsigned char pr[MAXB][MAXX][MAXY]; Xunsigned char rn[MAXB][MAXX][MAXY]; Xstatic unsigned char fr[2][MAXX][MAXY], fs[MAXX][MAXY]; X X X/* The externs below are parameters defined in main.c; the ints are X parameters defined here. */ X Xextern int BSIZE, XSIZE, YSIZE; Xint MAXFETCH = 5, RAINCONST = 32, LANDEL = 10, MOUNTDEL = 32, FETCHDEL = 4; Xint NRFDEL = 3, HEQDEL = 32, NRHEQDEL = 24, FLANKDEL = -24, PRINTRAIN = 0; X X Xrainpar (s) char *s; { X /* This function is called by mainpar() in main.c; it simply tests input X parameter names to see if they are defined in this file. Each of the X above ints are defined in this file. If the input string matches here, X the function returns true. */ X X if (CMP ("MAXFETCH")) getlng (&MAXFETCH, M_RAIN); X else if (CMP ("RAINCONST")) getlng (&RAINCONST, M_RAIN); X else if (CMP ("LANDEL")) getlng (&LANDEL, M_RAIN); X else if (CMP ("MOUNTDEL")) getlng (&MOUNTDEL, M_RAIN); X else if (CMP ("FETCHDEL")) getlng (&FETCHDEL, M_RAIN); X else if (CMP ("HEQDEL")) getlng (&HEQDEL, M_RAIN); X else if (CMP ("NRHEQDEL")) getlng (&NRHEQDEL, M_RAIN); X else if (CMP ("FLANKDEL")) getlng (&FLANKDEL, M_RAIN); X else if (CMP ("NRFDEL")) getlng (&NRFDEL, M_RAIN); X else if (CMP ("PRINTRAIN")) getlng (&PRINTRAIN, M_RAIN); X else return (0); X return (1); } X X Xraincomp () { X /* This is the main rain computation function. It calls the functions X getfetch () and getrain () to do all the work for each buffer, then X prints out the results if needed. */ X X register int buf; X X for (buf=0; buf 255) x = 255; X rn[buf][i][j] = x; } } END_OF_src/rain.c if test 7151 -ne `wc -c src/climate.c <<'END_OF_src/climate.c' X/* This program is Copyright (c) 1991 David Allen. It may be freely X distributed as long as you leave my name and copyright notice on it. X I'd really like your comments and feedback; send e-mail to X allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore X Avenue, Maynard, MA 01754. */ X X/* This file contains the routines that compute local climate */ X X#include "const.h" X#include "clim.h" X X X/* Input arrays are l from main.c, rn from rain.c, and t from heat.c. Note X that the unscaled temperatures are used. The output array is cl. Array X lm (from main.c) is used by the drawing routine.*/ X Xextern unsigned char l[MAXX][MAXY], lm[MAXX][MAXY], rn[MAXB][MAXX][MAXY]; Xextern int tt[MAXB][MAXX][MAXY]; Xunsigned char cl[MAXX][MAXY]; X X X/* These parameters are defined in main.c or heat.c */ Xextern int BSIZE, XSIZE, YSIZE, TEMPSCALE, PRINTMODE; X X/* These parameters are used here, and are described in params.doc */ Xint tempcut[] = { 0, 40, 90, 120 }, raincut[] = { 40, 60, 110, 160, 180 }; Xint PRINTCLIM = 0, MTDELTA = 20, TCSIZE = 4, RCSIZE = 5; Xdouble ICEBERGK = 263.0; X X X/* This array is the heart of the climate routine; temperature increases X going down the array, and rainfall increases going from left to right. */ X Xstatic unsigned char climkey[4][5] = { X { C_TUNDRA, C_TUNDRA, C_TUNDRA, C_TUNDRA, C_TUNDRA }, X { C_STEPPE, C_STEPPE, C_DECID, C_DECID, C_DECID }, X { C_DESERT, C_SAVANA, C_DECID, C_JUNGLE, C_SWAMP }, X { C_DESERT, C_SAVANA, C_JUNGLE, C_SWAMP, C_SWAMP } }; X X Xclimpar (s) char *s; { X /* This function is called by mainpar() in main.c; it simply tests input X parameter names to see if they are defined in this file. Each of the X above ints are defined in this file. If the input string matches here, X the function returns true. */ X if (CMP ("ICEBERGK")) getdbl (&ICEBERGK, M_CLIM); X else if (CMP ("PRINTCLIM")) getlng (&PRINTCLIM, M_CLIM); X else if (CMP ("TEMPCUT")) getlvec (&TCSIZE, tempcut, M_CLIM); X else if (CMP ("RAINCUT")) getlvec (&RCSIZE, raincut, M_CLIM); X else if (CMP ("MTDELTA")) getlng (&MTDELTA, M_CLIM); X else if (CMP ("PRINTCLIM")) getlng (&PRINTCLIM, M_CLIM); X else return (0); X return (1); } X X Xclimdraw () { draw (DRAW_CLIM, LINE_CORN, cl, lm); } X /* This routine calls draw with the proper arguments to display climate */ X X Xclimcomp () { X /* The outer loop looks at each square. If it is ocean, the climate will X be ocean unless the temperature is below ICEBREGK degrees all year round. X If it is land, then the average rainfall and temperature (in Farenheit) are X computed for the square. If the square is mountain, it is colder; the X temperature is decreased. These two figures are then turned into array X indices by using the tempcut and raincut parameter vectors. The climate X for the square is then simply a table lookup. Finally, the array is printed X if desired. */ X X register int i, j, buf; X int noice, avetemp, averain, ttt, r; X X usermessage ("Computing climate"); checkmouse (); X for (j=0; j TEMPSCALE * ICEBERGK); X cl[i][j] = noice ? C_OCEAN : C_OCEANICE; } X else { /* land or mountain */ X for (averain=0, avetemp=0, buf=0; buf tempcut[ttt]) && (ttt < TCSIZE-1)) ttt++; X r = 0; while ((averain > raincut[r]) && (r < RCSIZE-1)) r++; X cl[i][j] = climkey[ttt][r]; } } X if (PRINTCLIM) { X if (PRINTMODE == PRINTMODE_GREY) X putmat ("CLIMATE", -1, PRINTMODE_CLIM, cl, lm); X else putmat ("CLIMATE", -1, PRINTMODE_SHORT, cl, lm); } } END_OF_src/climate.c if test 4025 -ne `wc -c