v18i003: planet - planet generation simulator, Part03/04
Dave Allen
allen at viewlogic.com
Mon Apr 8 10:24:37 AEST 1991
Submitted-by: Dave Allen <allen at viewlogic.com>
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 <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 4)."
# Contents: src/Makefile src/clim.h src/fileio.c src/clim.c src/heat.c
# src/pressure.c src/wind.c src/rain.c src/climate.c
# Wrapped by allen at baja on Sat Mar 23 16:18:37 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f src/Makefile -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/Makefile\"
else
echo shar: Extracting \"src/Makefile\" \(1309 characters\)
sed "s/^X//" >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/Makefile`; then
echo shar: \"src/Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/clim.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/clim.h\"
else
echo shar: Extracting \"src/clim.h\" \(675 characters\)
sed "s/^X//" >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/clim.h`; then
echo shar: \"src/clim.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/fileio.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/fileio.c\"
else
echo shar: Extracting \"src/fileio.c\" \(12090 characters\)
sed "s/^X//" >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 at 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 <stdio.h>
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<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X printf ("%4d", cra[i][j]); if (++k == 15) { printf ("\n"); k = 0; } }
X else if (mode == PRINTMODE_SHORT) for (j=0; j<YSIZE; j++) {
X for (i=0; i<XSIZE; i++) printf ("%c", shortlut[cra[i][j]]);
X if (j < YSIZE-1) printf ("\n"); }
X else if (mode == PRINTMODE_SCALE) for (j=0; j<YSIZE; j++) {
X for (i=0; i<XSIZE; i++) printf ("%c", scalelut[cra[i][j]]);
X if (j < YSIZE-1) printf ("\n"); }
X printf ("))\n"); return (0); }
X
X
Xgetparams (s) char *s; {
X /* This function is called either by init() or picktype(), in main.c.
X In either case, the argument is a string which is supposed to be either
X "-", in which case stdin is opened, or a filename. If the file doesn't
X exist, the program exits via panic(). Once the file is open, the loop
X expects to find paren-delimited pairs of (name value). Value could be
X a vector, like (name (val1 val2)). After a name is found, params(),
X above, is called to recognize the parameter. If there is a syntax
X error or an unrecognized parameter, the program exits via panic().
X Each computation source file has its own parameter function; if all of
X them fail the parameter name is unknown. */
X
X int x;
X
X if (!strcmp (s, "-")) fp = stdin;
X else if (!(fp = fopen (s, "r"))) panic ("Can't find input file");
X while ((x = gettoken (getbuf)) != TOK_EOF) {
X if (x != TOK_OPEN) geterr ("expected open paren");
X if (gettoken (getbuf) != TOK_WORD) geterr ("expected param name");
X if (!mainpar (getbuf)) geterr ("unknown parameter name");
X if (gettoken (getbuf) != TOK_CLOSE) geterr ("expected close paren"); }
X fclose (fp); }
X
X
Xgettoken (s) char *s; {
X /* This is the only function which actually reads from the file. It
X maintains a one-character private unget buffer. It ignores initial
X whitespace, but counts newlines in order to maintain an accurate linecount.
X Open or close parentheses count as tokens, and so does any amount of text
X with no white space or parens. The return code indicates whether an
X open or close paren, end of file, or a word was found. If a word was
X found, it is copied into the string pointed to by s. When a word is found,
X the character which terminated it (whitespace, EOF, or paren) is put into
X the unget buffer to be read the next time gettoken() is called. */
X
X static char buf = 0; char c;
X
X white: if (buf) { c = buf; buf = 0; } else c = getc (fp);
X switch (c) {
X case '\n': linecount++;
X case '\t':
X case ' ' : goto white;
X case EOF : return (TOK_EOF);
X case '(' : return (TOK_OPEN);
X case ')' : return (TOK_CLOSE); }
X text: if ((c==' ')||(c=='\t')||(c=='\n')||(c==')')||(c=='(')||(c==EOF)) {
X buf = c; *s = 0; return (TOK_WORD); }
X else { *s++ = c; c = getc (fp); goto text; } }
X
X
Xgeterr (s) char *s; {
X /* Use panic() to print a nicely formatted message, containing the input
X file line number, describing why the program just spat up. */
X sprintf (getbuf, "Par error: %s on line %d", s, linecount);
X fclose (fp);
X panic (getbuf); }
X
X
Xgetlng (x, chg) int *x, chg; { int n;
X /* Called after reading a name associated with a single int, this
X function just reads a int from the input file and uses atoi() to
X convert it to a int, stored at the address passed in. Note that any
X text, including a string or a real, will be read in; no type checking
X is performed. If the value is different from the previous value of the
X parameter, change[chg] is set to one. */
X
X if (gettoken (getbuf) != TOK_WORD) geterr ("expected int");
X n = atoi (getbuf); if (n != *x) change[chg] = 1; *x = n; }
X
X
Xgetdbl (x, chg) double *x; int chg; { double n;
X /* This function reads in a double format number, like getlng above. If
X the value is different from the previous value, change[chg] is set to 1. */
X
X if (gettoken (getbuf) != TOK_WORD) geterr ("expected double");
X n = atof (getbuf); if (n != *x) change[chg] = 1; *x = n; }
X
X
Xgetmat (dim1, dim2, chg, m)
X int *dim1, *dim2, chg; unsigned char m[MAXX][MAXY]; {
X /* This function expects to find a vector of strings, where each string
X contains only 0-9, A-Z. The characters are converted into the numbers
X 0..36 and stored in the character array whose address is passed into the
X function. If one of the strings is too long, or if there are too many
X strings, the function spits up. Before exiting, the function sets the
X array limits passed in; dim1 is set to the length of the longest string,
X while dim2 is set to the number of strings. If any of the characters,
X or either dimension, is changed, then change[chg] is set to 1. */
X
X int x, i = 0, j = 0, imax = -1; char c;
X
X if (gettoken (getbuf) != TOK_OPEN) geterr ("expected open paren");
X while ((x = gettoken (getbuf)) == TOK_WORD) {
X if (j == *dim2) geterr ("matrix too high");
X for (i=0; getbuf[i]; i++) {
X if ((c = getbuf[i] - '0') > 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<YSIZE;j++) for (i=0; i<XSIZE; i++) {
X z = climlut[cra[i][j]];
X if (z > 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<YSIZE;j++) for (i=0; i<XSIZE; i++) {
X if (cra[i][j] == C_JUNGLE)
X printf ("%6.2f %6.2f p\n", XX(j), YY(i));
X if (cra[i][j] == C_SWAMP)
X printf ("%6.2f %6.2f x\n", XX(j), YY(i)); } }
X
X else for (j=0; j<YSIZE;j++) for (i=0; i<XSIZE; i++) {
X z = greyscale (cra[i][j]);
X if (z > 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; j<YSIZE;j++) for (i=0; i<XSIZE; i++) {
X if (lra[i][j] & LINE_0V) printf ("%6.2f %6.2f v\n", XX(j), YY(i));
X if (lra[i][j] & LINE_0H) printf ("%6.2f %6.2f h\n", XX(j), YY(i)); }
X
X printf ("1 setgray\n");
X if (lra) for (j=0; j<YSIZE;j++) for (i=0; i<XSIZE; i++) {
X if (lra[i][j] & LINE_1V) printf ("%6.2f %6.2f v\n", XX(j), YY(i));
X if (lra[i][j] & LINE_1H) printf ("%6.2f %6.2f h\n", XX(j), YY(i)); }
X
X printf ("\nshowpage\n"); }
END_OF_src/fileio.c
if test 12090 -ne `wc -c <src/fileio.c`; then
echo shar: \"src/fileio.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/clim.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/clim.c\"
else
echo shar: Extracting \"src/clim.c\" \(5481 characters\)
sed "s/^X//" >src/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 at 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<YSIZE; j++) for (i=0, x=0; i<XSIZE; i++, x=0) {
X /* Draw a white line if a mountain is present */
X if (i) if ((l[i][j] == 2) != (l[i-1][j] == 2)) x |= LINE_1V;
X if (j) if ((l[i][j] == 2) != (l[i][j-1] == 2)) x |= LINE_1H;
X
X /* Draw a black line if a coast is present */
X if (i) if ((l[i][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; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
X if (!rr[i][j]) rr[i][j] = MAXRANGE; }
X
X
Xonerange (rr) char rr[MAXX][MAXY]; {
X /* This routine consists of a loop. Each time through the loop, every
X square is checked. If the square is zero, it has not yet been updated.
X In that case, look to see if any adjacent squares were previously updated
X (or if they were initialized to -1). If so, set the square to the current
X distance value, which happens to be identical to the outer loop variable.
X If, after one loop iteration, no squares have been updated, the matrix
X must be completely updated. Stop. To keep down run-time, a maximum
X distance value, MAXRANGE, is used as the terminating loop value. */
X
X register int i, j, x, k, keepgo;
X for (k=1; k<MAXRANGE; k++) {
X checkmouse ();
X for (keepgo=0, j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
X if (!rr[i][j]) {
X keepgo = 1;
X x = rr[i ? i-1 : XSIZE-1][j]; if (x && (x != k)) rr[i][j] = k;
X x = rr[(i<XSIZE-1) ? i+1 : 0][j]; if (x && (x != k)) rr[i][j] = k;
X if (j<YSIZE-1) { x = rr[i][j+1]; if (x && (x != k)) rr[i][j] = k; }
X if (j) { x = rr[i][j-1]; if (x && (x != k)) rr[i][j] = k; } }
X if (!keepgo) return (0); } return (0); }
X
X
Xstatus (n, i) int n, i; {
X static char *title[] = { "", "Heat","Pressure","Wind","Rain","Climate" };
X char t[256];
X sprintf (t, "%s buffer %d", title[n], i); usermessage (t); }
X
X
Xdouble greyscale (x) int x; {
X /* This function just returns the 0..1 equivalent of 0..255 */
X return ((float) ((255 - x) / 320.0) + 0.1); }
END_OF_src/clim.c
if test 5481 -ne `wc -c <src/clim.c`; then
echo shar: \"src/clim.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/heat.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/heat.c\"
else
echo shar: Extracting \"src/heat.c\" \(6893 characters\)
sed "s/^X//" >src/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 at 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<BSIZE; buf++) {
X checkmouse ();
X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) {
X if (tt[buf][i][j] < tmin) tmin = tt[buf][i][j];
X if (tt[buf][i][j] > 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<BSIZE; buf++) {
X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++)
X ts[buf][i][j] = (tt[buf][i][j] - tmin) * tscale;
X checkmouse (); }
X
X if (PRINTEMP) {
X if (PRINTMODE != PRINTMODE_GREY) {
X printf ("(KEY-IN-FAREN (\n");
X for (i=0; i<8; i++) { heatlut (16 * i, s); printf (" %s", s); }
X printf ("\n");
X for (i=8; i<16; i++) { heatlut (16 * i, s); printf (" %s", s); }
X printf ("))\n"); }
X for (i=0; i<BSIZE; i++)
X putmat ("TEMPERATURE", i, PRINTMODE_SCALE, ts[i], lm); } }
X
X
Xheatdraw (n) int n; { draw (DRAW_GREY, LINE_CORN, ts[n], lm); }
X /* This function calls draw() with the right arguments to display heat */
X
X
Xgetheat () {
X /* This function does all the work for computing temperatures. The outermost
X loop goes through each row of the output array once, computing all buffers
X at the same time. The loop has two inner loops: first, tland and tsea are
X filled with the temperatures found far inland and far at sea for each buffer.
X In the second loop, the weight function for each point in the latitude line
X is computed and the temperature is found for each buffer. */
X
X register int buf, i, j;
X double lat, lscl, sscl, x, fact, theta, delth, phase;
X double tland[MAXB], tsea[MAXB];
X
X lscl = DEG2RAD * 180.0 / (90.0 + LTILT * TILT);
X sscl = DEG2RAD * 180.0 / (90.0 + OTILT * TILT);
X delth = 2.0 * PI / (double) BSIZE;
X for (j=0; j<YSIZE; j++) {
X status (M_HEAT, j); checkmouse ();
X lat = 90.0 - 180.0 * (double) j / (double) YSIZE;
X for (buf=0, theta=0; buf<BSIZE; buf++, theta+=delth) {
X phase = theta + ECCPHASE; if (phase > 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<XSIZE; i++) {
X if (!l[i][j]) x = OSMOOTH + (countland (i, j) / ODIV);
X else x = LSMOOTH + (countland (i, j) / LDIV);
X for (buf=0; buf<BSIZE; buf++)
X tt[buf][i][j] = tsea[buf] + (tland[buf] - tsea[buf]) * x; } } }
X
X
Xcountland (x, y) int x, y; {
X /* Called by getheat() for each square, this function looks in a 11 wide
X by 5 high box and counts the number of land squares found there. It
X compensates for y values off the map, and wraps x values around. The
X answer is returned. */
X
X register int sum=0; int jmin, jmax, j1, i0, i1;
X
X jmin = y - 2; if (jmin < 0) jmin = 0;
X jmax = y + 2; if (jmax >= 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/heat.c`; then
echo shar: \"src/heat.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/pressure.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/pressure.c\"
else
echo shar: Extracting \"src/pressure.c\" \(9001 characters\)
sed "s/^X//" >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 at 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<BSIZE; buf++) {
X status (M_PRESS, buf); ocean (buf); land (buf);
X checkmouse (); findheq (buf); setpm (buf); }
X if (PRINTPR) for (buf=0; buf<BSIZE; buf++) {
X if (PRINTMODE == PRINTMODE_GREY)
X putmat ("PRESSURE", buf, PRINTMODE_SHORT, l, pm[buf]);
X else putmat ("PRESSURE", buf, PRINTMODE_SHORT, pr[buf], 0); } }
X
X
Xpressdraw (n) int n; { draw (DRAW_LAND, LINE_CORN, l, pm[n]); }
X /* This function calls draw with the right arguments to display pressure */
X
X
Xocean (buf) int buf; {
X /* Determine ocean highs and lows. An ocean high or low must occur over
X ocean, far away from major land masses. Two calls to range() are made
X to find the qualifying ocean areas; then temperature criteria are used
X to select the actual pressure zones. */
X
X register int i, j; int x;
X
X /* Set r to the distance on land from the coast. */
X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) r[i][j] = l[i][j] ? 0 : -1;
X range (r);
X
X /* Initialize r to contain blobs on land which are at least OLTHRESH squares
X away from the coast. Then set r to the distance from these. The result
X in r is the distance from the nearest big piece of land (ignoring
X islands). */
X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
X r[i][j] = (r[i][j] > 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<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X pr[buf][i][j] = 0; x = ts[buf][i][j];
X if (r[i][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<YSIZE; j++) for (i=0; i<XSIZE; i++) r[i][j] = l[i][j] ? -1 : 0;
X range (r);
X
X /* Initialize r to contain blobs on ocean which are at least LOTHRESH
X squares away from the coast. Then set r to the distance from these. The
X result in r is the distance from the nearest ocean, ignoring lakes. */
X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++)
X r[i][j] = (r[i][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<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X x = ts[buf][i][j];
X if (r[i][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<XSIZE; i++) {
X /* Find the total of the temperatures in this column */
X for (sum=0, j=0; j<YSIZE; j++) sum += ts[buf][i][j];
X
X /* Step through the column again until the total so far is exactly
X half the total for the column. This is the median position. */
X for (sum>>=1, j=0; j<YSIZE && sum>0; 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; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X k = pr[buf][i][j]; col = 0;
X
X /* If not at the top edge, and if the pressure status here is not equal
X to the pressure status one square up, then put a horizontal line in
X this square. The color is zero if there is a high here; if a low or
X heat equator (a type of low) is here, the color is one. */
X if (j) if (k != pr[buf][i][j-1]) col =
X ((k == PR_HIGH) || (pr[buf][i][j-1] == PR_HIGH)) ? LINE_0H : LINE_1H;
X /* Similarly, if not at the left edge, put a vertical line in the right
X color. Notice that this color is OR'ed with the previous color. */
X if (i) if (k != pr[buf][i-1][j]) col |=
X ((k == PR_HIGH) || (pr[buf][i-1][j] == PR_HIGH)) ? LINE_0V : LINE_1V;
X
X /* Set the square in the pm array to the resultant color */
X pm[buf][i][j] = col; } }
X
END_OF_src/pressure.c
if test 9001 -ne `wc -c <src/pressure.c`; then
echo shar: \"src/pressure.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/wind.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/wind.c\"
else
echo shar: Extracting \"src/wind.c\" \(5268 characters\)
sed "s/^X//" >src/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 at 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<BSIZE; buf++) {
X status (M_WIND, buf); getpress (buf); getwind (buf);
X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X x = wd[buf][i][j];
X if (x & N) x &= (~S); if (x & E) x &= (~W);
X wd[buf][i][j] = x; } }
X
X if (PRINTWIND) for (buf=0; buf<BSIZE; buf++) {
X if (PRINTMODE == PRINTMODE_GREY)
X putmat ("WIND", buf, PRINTMODE_SHORT, l, wd[buf]);
X else putmat ("WIND", buf, PRINTMODE_SHORT, wd[buf], 0); } }
X
X
Xwindraw (n) int n; { draw (DRAW_LAND, LINE_DIAG, l, wd[n]); }
X /* This function calls draw with the right arguments to display wind */
X
X
Xgetpress (buf) int buf; {
X /* This function takes the high and low markings from pressure.c and creates
X a smoothed function. Highs turn into MAXPRESS and lows turn into 0. */
X
X register int i, j;
X
X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X /* Zero out the arrays to be used */
X wd[buf][i][j] = 0; hl[0][i][j] = 0; hl[1][i][j] = 0;
X
X /* Fill hl[0] with the low pressure zones, and hl[1] with highs */
X if (pr[buf][i][j] == PR_LOW) hl[0][i][j] = -1;
X else if (pr[buf][i][j] == PR_HIGH) hl[1][i][j] = -1;
X else if (pr[buf][i][j] == PR_HEQ) hl[0][i][j] = -1; }
X
X /* Set each square in hl[0] to the distance from that square to the */
X /* nearest low, and each square in hl[1] to the distance to a high. */
X range (hl[0]); range (hl[1]);
X
X /* The final pressure, in array p, is zero if a low is there and */
X /* MAXPRESS if a high is there. Otherwise, the pressure in a square is */
X /* proportional to the ratio of (distance from the square to the nearest */
X /* low) to (total of distance from nearest high and nearest low). This */
X /* gives a smooth curve between the extremes. */
X for (j=0; j<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X if (hl[1][i][j] == -1) p[i][j] = MAXPRESS;
X else if (hl[0][i][j] == -1) p[i][j] = 0;
X else p[i][j] = (MAXPRESS*hl[0][i][j]) / (hl[0][i][j] + hl[1][i][j]); } }
X
X
Xgetwind (buf) int buf; {
X /* This function draws isobars around the pressure map created above. These
X isobars are the directions of wind flow. The isobars are given a direction
X depending on whether the square is above or below the heat equator; north of
X the heat equator, the winds blow counterclockwise out from a low, while
X south of it, the opposite is true. */
X
X register int i, j; int a, b, e, bar;
X
X /* Step from 0 to MAXPRESS by BARSEP; bar is the pressure for which this */
X /* isobar will be drawn. */
X for (bar=BARSEP; bar<=MAXPRESS; bar+=BARSEP) {
X checkmouse ();
X for (i=0; i<XSIZE; i++) for (e=0, j=0; j<YSIZE; j++) {
X
X /* Set e if this square is south of the heat equator */
X a = p[i][j]; if (pr[buf][i][j] == 3) e = 1;
X
X /* Provided the square is not at the top of the array, compare the */
X /* pressure here to the pressure one square up. This gives the */
X /* direction of the wind in terms of east / west flow. */
X if (j) {
X b = p[i][j-1];
X if ((a < bar) && (b >= 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/wind.c`; then
echo shar: \"src/wind.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/rain.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/rain.c\"
else
echo shar: Extracting \"src/rain.c\" \(7151 characters\)
sed "s/^X//" >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 at 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<BSIZE; buf++) {
X status (M_RAIN, buf); checkmouse ();
X getfetch (buf); checkmouse (); getrain (buf); }
X
X if (PRINTRAIN) for (buf=0; buf<BSIZE; buf++)
X putmat ("RAIN", buf, PRINTMODE_SCALE, rn[buf], lm); }
X
X
Xraindraw (n) int n; { draw (DRAW_GREY, LINE_CORN, rn[n], lm); }
X /* This function calls draw with the right arguments to display rain */
X
X
Xfetchinc (x, y, dest) int x, y, dest; {
X /* This is the workhorse function for getfetch(), below. It is called
X several times per square. It changes x to account for wraparound, so it
X won't work as a macro. If y is out of range it does nothing, else it
X "marks" the new square in fr[dest] and increments fs to record the number
X of times the square has been marked. */
X
X if (x == -1) x = XSIZE-1; else if (x == XSIZE) x = 0;
X if ((y == -1) || (y == YSIZE)) return (0);
X fr[dest][x][y] = 1; fs[x][y]++; return (0); }
X
X
Xgetfetch (buf) int buf; {
X /* "Fetch" is the term that describes how many squares a given wind line
X travels over water. It measures how moist the wind is. The algorithm to
X measure fetch looks like many simultaneous tree walks, where each water
X square is a root square, and every wind edge is a tree edge. A counter
X for each square determines how many times that square is reached during
X the tree walks; that is the fetch. */
X
X register int i, j, k; int src, dest;
X
X /* Initialize the counter fs to zero. Array fr, which records the */
X /* list of active edges in the walks, is set so that all ocean squares */
X /* are active. Also, the result array rn is cleared. */
X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) {
X fr[0][i][j] = l[i][j] ? 0 : 1; fs[i][j] = 0; rn[buf][i][j] = 0; }
X
X /* Each time through the loop, each square is examined. If it's */
X /* active, disable the mark in the current time step (thus ensuring */
X /* that when the buffers are flipped, the new destination is empty). */
X /* If the square is a mountain, don't pass the mark, but instead add */
X /* some amount to the square -- implementing rain shadows and rainy */
X /* mountain squares. Finally, for each of the eight cardinal */
X /* directions, if there is wind blowing in that direction, carry a */
X /* marker to that square using fetchinc(), above. */
X
X for (k=0; k<MAXFETCH; k++) {
X src = k % 2; dest = 1 - src;
X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) if (fr[src][i][j]) {
X fr[src][i][j] = 0;
X if (l[i][j] == 2) rn[buf][i][j] += MOUNTDEL;
X else switch (wd[buf][i][j]) {
X case N|E: fetchinc (i+1, j-1, dest); break;
X case N|W: fetchinc (i-1, j-1, dest); break;
X case S|E: fetchinc (i+1, j+1, dest); break;
X case S|W: fetchinc (i-1, j+1, dest); break;
X case N: fetchinc (i, j-1, dest); break;
X case S: fetchinc (i, j+1, dest); break;
X case E: fetchinc (i+1, j, dest); break;
X case W: fetchinc (i-1, j, dest); break; } } } }
X
X
X/* This macro is called several times per square by getrain(), below. It
X simply tests the square for several conditions: if the square is on the
X heat equator, itcz is set to one; if the wind blows south in this square,
X it is on the flank of a circular wind zone (and thus less rainy); the local
X rain sum, x, is increased according to the fetch sum in the square. */
X#define RAINTEST(xx,yy) \
X if (pr[buf][xx][yy] == PR_HEQ) itcz = 1; \
X if (wd[buf][xx][yy] & S) flank = 1; \
X x += (fs[xx][yy] * NRFDEL);
X
X
Xgetrain (buf) int buf; {
X /* Once the fetch array is computed, this function looks at each square to
X determine the amount of rainfall there. The above macro is called five
X times, once for the square and each of its four neighbors; this determines
X whether the square is near the ITCZ or the flank of an air cycle. The
X sum of fetches for the neighbors is also determined. Finally, each of the
X factors is weighted and added to the rainfall value: the local fetch value,
X a land factor, the nearness of the heat equator, and the nearness of a
X flank. Note that while rn is zeroed in getfetch(), it may be increased by
X rain falling on mountains, so it is nonzero when this function is called. */
X
X register int i, j, x; int itcz, flank;
X
X for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) {
X flank = 0; itcz = 0; x = rn[buf][i][j];
X if (i < XSIZE-1) { RAINTEST (i+1, j) } else { RAINTEST (0, j) }
X if (i) { RAINTEST (i-1, j) } else { RAINTEST (XSIZE-1, j) }
X if (j < YSIZE-1) { RAINTEST (i, j+1) }
X if (j) { RAINTEST (i, j-1) }
X RAINTEST (i, j);
X
X x += (RAINCONST + FETCHDEL * fs[i][j]);
X if (l[i][j]) x += LANDEL;
X if (pr[buf][i][j] == PR_HEQ) x += HEQDEL;
X if (itcz) x += NRHEQDEL;
X if (flank) x += FLANKDEL;
X if (x < 0) x = 0; if (x> 255) x = 255;
X rn[buf][i][j] = x; } }
END_OF_src/rain.c
if test 7151 -ne `wc -c <src/rain.c`; then
echo shar: \"src/rain.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f src/climate.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"src/climate.c\"
else
echo shar: Extracting \"src/climate.c\" \(4025 characters\)
sed "s/^X//" >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 at 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<YSIZE; j++) for (i=0; i<XSIZE; i++) {
X if (!l[i][j]) { /* ocean */
X for (noice=0, buf=0; buf<BSIZE; buf++)
X noice |= (tt[buf][i][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<BSIZE; buf++) {
X averain += rn[buf][i][j]; avetemp += tt[buf][i][j]; }
X averain /= BSIZE; avetemp /= BSIZE;
X avetemp = ((double) (avetemp / TEMPSCALE) - 273.0) * 1.8 + 32.0;
X if (l[i][j] == 2) avetemp -= MTDELTA;
X ttt = 0; while ((avetemp > 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 <src/climate.c`; then
echo shar: \"src/climate.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 4 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.
More information about the Comp.sources.misc
mailing list