xref: /csrg-svn/games/ching/phx/ching.phx.c (revision 60770)
135942Sbostic /*
2*60770Sbostic  * Copyright (c) 1988, 1993
3*60770Sbostic  *	The Regents of the University of California.  All rights reserved.
435942Sbostic  *
535942Sbostic  * This code is derived from software contributed to Berkeley by
635942Sbostic  * Guy Harris.
735942Sbostic  *
842573Sbostic  * %sccs.include.redist.c%
935942Sbostic  */
1035942Sbostic 
1135942Sbostic #ifndef lint
12*60770Sbostic static char copyright[] =
13*60770Sbostic "@(#) Copyright (c) 1988, 1993\n\
14*60770Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1535942Sbostic #endif /* not lint */
1635942Sbostic 
1735942Sbostic #ifndef lint
18*60770Sbostic static char sccsid[] = "@(#)ching.phx.c	8.1 (Berkeley) 05/31/93";
1935942Sbostic #endif /* not lint */
2035942Sbostic 
2135942Sbostic /*
2235942Sbostic  * phx - Print NROFF/TROFF source of change, given the line values.
2335942Sbostic  */
2435942Sbostic #include <stdio.h>
2535942Sbostic #include "ching.h"
2641175Sbostic #include "pathnames.h"
2735942Sbostic 
2835942Sbostic struct {
2935942Sbostic 	int	lines;		/* encoded value of lines */
3035942Sbostic 	int	trinum;		/* trigram number */
3135942Sbostic } table[] = {
3235942Sbostic 	{ 777, 0 },		/* 1 */
3335942Sbostic 	{ 887, 1 },		/* 4 */
3435942Sbostic 	{ 878, 2 },		/* 6 */
3535942Sbostic 	{ 788, 3 },		/* 7 */
3635942Sbostic 	{ 888, 4 },		/* 8 */
3735942Sbostic 	{ 778, 5 },		/* 5 */
3835942Sbostic 	{ 787, 6 },		/* 3 */
3935942Sbostic 	{ 877, 7 },		/* 2 */
4035942Sbostic };
4135942Sbostic 
4235942Sbostic /*
4335942Sbostic  * Gives hexagram number from two component trigrams.
4435942Sbostic  */
4535942Sbostic int	crosstab[8][8] = {
4635942Sbostic 	1,  34, 5,  26, 11, 9,  14, 43,
4735942Sbostic 	25, 51, 3,  27, 24, 42, 21, 17,
4835942Sbostic 	6,  40, 29, 4,  7,  59, 64, 47,
4935942Sbostic 	33, 62, 39, 52, 15, 53, 56, 31,
5035942Sbostic 	12, 16, 8,  23, 2,  20, 35, 45,
5135942Sbostic 	44, 32, 48, 18, 46, 57, 50, 28,
5235942Sbostic 	13, 55, 63, 22, 36, 37, 30, 49,
5335942Sbostic 	10, 54, 60, 41, 19, 61, 38, 58,
5435942Sbostic };
5535942Sbostic 
5635942Sbostic int	trigrams[6];
5735942Sbostic int	moving[6];
5835942Sbostic 
5935942Sbostic FILE	*chingf;		/* stream to read the hexagram file */
6035942Sbostic 
6135942Sbostic char	*gets();
6235942Sbostic 
main(argc,argv)6335942Sbostic main(argc, argv)
6435942Sbostic int argc;
6535942Sbostic char **argv;
6635942Sbostic {
6735942Sbostic 	register int hexagram;		/* hexagram number */
6835942Sbostic 	register char *hexptr;		/* pointer to string of lines */
6935942Sbostic 	char hexstr[6+1];		/* buffer for reading lines in */
7035942Sbostic 	register int i;
7135942Sbostic 
7235942Sbostic 	if (argc < 2)
7335942Sbostic 		hexptr = gets(hexstr);
7435942Sbostic 	else
7535942Sbostic 		hexptr = argv[1];
7635942Sbostic 	if (hexptr == (char *)NULL || strlen(hexptr) != 6) {
7735942Sbostic 		fprintf(stderr, "What kind of a change is THAT?!?\n");
7835942Sbostic 		exit(1);
7935942Sbostic 	}
8035942Sbostic 	for (i = 0; i < 6; i++) {
8135942Sbostic 		trigrams[i] = hexptr[i] - '0';
8235942Sbostic 		if (trigrams[i] == 6 || trigrams[i] == 9)
8335942Sbostic 			moving[i] = 1;
8435942Sbostic 		else
8535942Sbostic 			moving[i] = 0;
8635942Sbostic 	}
8741175Sbostic 	if ((chingf = fopen(_PATH_HEX, "r")) == (FILE *)NULL) {
8841175Sbostic 		fprintf(stderr, "ching: can't read %s\n", _PATH_HEX);
8935942Sbostic 		exit(2);
9035942Sbostic 	}
9135942Sbostic 	phx(doahex(), 0);
9235942Sbostic 	if (changes())
9335942Sbostic 		phx(doahex(), 1);
9435942Sbostic }
9535942Sbostic 
9635942Sbostic /*
9735942Sbostic  * Compute the hexagram number, given the trigrams.
9835942Sbostic  */
9935942Sbostic int
doahex()10035942Sbostic doahex()
10135942Sbostic {
10235942Sbostic 	int lower, upper;	/* encoded values of lower and upper trigrams */
10335942Sbostic 	int lnum, unum;		/* indices of upper and lower trigrams */
10435942Sbostic 	register int i;
10535942Sbostic 
10635942Sbostic 	lower = codem(0);
10735942Sbostic 	upper = codem(3);
10835942Sbostic 	for (i = 0; i < 8; i++) {
10935942Sbostic 		if (table[i].lines == lower)
11035942Sbostic 			 lnum = table[i].trinum;
11135942Sbostic 		if (table[i].lines == upper)
11235942Sbostic 			 unum = table[i].trinum;
11335942Sbostic 	}
11435942Sbostic 	return(crosstab[lnum][unum]);
11535942Sbostic }
11635942Sbostic 
11735942Sbostic /*
11835942Sbostic  * Encode a trigram as a 3-digit number; the digits, from left to right,
11935942Sbostic  * represent the lines.  7 is a solid (yang) line, 8 is a broken (yin) line.
12035942Sbostic  */
codem(a)12135942Sbostic codem(a)
12235942Sbostic int a;
12335942Sbostic {
12435942Sbostic 	register int code, i;
12535942Sbostic 	int factor[3];
12635942Sbostic 
12735942Sbostic 	factor[0] = 1;
12835942Sbostic 	factor[1] = 10;
12935942Sbostic 	factor[2] = 100;
13035942Sbostic 	code = 0;
13135942Sbostic 
13235942Sbostic 	for (i = a; i < a + 3; i++) {
13335942Sbostic 		switch(trigrams[i]) {
13435942Sbostic 
13535942Sbostic 		case YYANG:
13635942Sbostic 		case OYANG:
13735942Sbostic 			code += factor[i%3]*7;
13835942Sbostic 			break;
13935942Sbostic 
14035942Sbostic 		case OYIN:
14135942Sbostic 		case YYIN:
14235942Sbostic 			code += factor[i%3]*8;
14335942Sbostic 			break;
14435942Sbostic 		}
14535942Sbostic 	}
14635942Sbostic 	return(code);
14735942Sbostic }
14835942Sbostic 
14935942Sbostic /*
15035942Sbostic  * Compute the changes based on moving lines; return 1 if any lines moved,
15135942Sbostic  * 0 if no lines moved.
15235942Sbostic  */
changes()15335942Sbostic changes()
15435942Sbostic {
15535942Sbostic 	register int cflag;
15635942Sbostic 	register int i;
15735942Sbostic 
15835942Sbostic 	cflag = 0;
15935942Sbostic 	for (i = 0; i < 6; i++) {
16035942Sbostic 		if (trigrams[i] == OYIN) {
16135942Sbostic 			trigrams[i] = YYANG;
16235942Sbostic 			cflag++;
16335942Sbostic 		} else if (trigrams[i] == OYANG) {
16435942Sbostic 			trigrams[i] = YYIN;
16535942Sbostic 			cflag++;
16635942Sbostic 		}
16735942Sbostic 	}
16835942Sbostic 	return(cflag);
16935942Sbostic }
17035942Sbostic 
17135942Sbostic /*
17235942Sbostic  * Print the NROFF/TROFF source of a hexagram, given the hexagram number;
17335942Sbostic  * if flag is 0, print the entire source; if flag is 1, ignore the meanings
17435942Sbostic  * of the lines.
17535942Sbostic  */
phx(hexagram,flag)17635942Sbostic phx(hexagram, flag)
17735942Sbostic int hexagram;
17835942Sbostic int flag;
17935942Sbostic {
18035942Sbostic 	char textln[128+1];		/* buffer for text line */
18135942Sbostic 	register char *lp;		/* pointer into buffer */
18235942Sbostic 	register int thishex;		/* number of hexagram just read */
18335942Sbostic 	int lineno;			/* number of line read in */
18435942Sbostic 	int allmoving;			/* 1 if all lines are moving */
18535942Sbostic 	register int i;
18635942Sbostic 
18735942Sbostic 	/*
18835942Sbostic 	 * Search for the hexagram; it begins with a line of the form
18935942Sbostic 	 * .H <hexagram number> <other data>.
19035942Sbostic 	 */
19135942Sbostic 	rewind(chingf);
19235942Sbostic 	for (;;) {
19335942Sbostic 		if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
19435942Sbostic 			fprintf(stderr, "ching: Hexagram %d missing\n",
19535942Sbostic 			    hexagram);
19635942Sbostic 			exit(3);
19735942Sbostic 		}
19835942Sbostic 		lp = &textln[0];
19935942Sbostic 		if (*lp++ != '.' || *lp++ != 'H')
20035942Sbostic 			continue;
20135942Sbostic 		while (*lp++ == ' ')
20235942Sbostic 			;
20335942Sbostic 		lp--;
20435942Sbostic 		thishex = atoi(lp);
20535942Sbostic 		if (thishex < 1 || thishex > 64)
20635942Sbostic 			continue;
20735942Sbostic 		if (thishex == hexagram)
20835942Sbostic 			break;
20935942Sbostic 	}
21035942Sbostic 
21135942Sbostic 	/*
21235942Sbostic 	 * Print up to the line commentary, which ends with a line of the form
21335942Sbostic 	 * .L <position> <value>
21435942Sbostic 	 */
21535942Sbostic 	fputs(textln, stdout);
21635942Sbostic 	for (;;) {
21735942Sbostic 		if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
21835942Sbostic 			fprintf(stderr, "ching: Hexagram %d malformed\n",
21935942Sbostic 			    hexagram);
22035942Sbostic 			exit(3);
22135942Sbostic 		}
22235942Sbostic 		lp = &textln[0];
22335942Sbostic 		if (*lp++ == '.') {
22435942Sbostic 			if (*lp++ == 'L')
22535942Sbostic 				break;
22635942Sbostic 		}
22735942Sbostic 		fputs(textln, stdout);
22835942Sbostic 	}
22935942Sbostic 
23035942Sbostic 	/*
23135942Sbostic 	 * Now print the line commentaries, if this is the first hexagram.
23235942Sbostic 	 */
23335942Sbostic 	if (flag)
23435942Sbostic 		return;
23535942Sbostic 
23635942Sbostic 	/*
23735942Sbostic 	 * If a line is moving, print its commentary.
23835942Sbostic 	 * The text of the commentary ends with a line either of the form
23935942Sbostic 	 * .L <position> <value>
24035942Sbostic 	 * or of the form
24135942Sbostic 	 * .LA <value>
24235942Sbostic 	 * or of the form
24335942Sbostic 	 * .H <hexagram number> <other arguments>
24435942Sbostic 	 */
24535942Sbostic 	allmoving = 1;
24635942Sbostic 	for (i = 0; i < 6; i++) {
24735942Sbostic 		while (*lp++ == ' ')
24835942Sbostic 			;
24935942Sbostic 		lp--;
25035942Sbostic 		lineno = atoi(lp);
25135942Sbostic 		if (i + 1 != lineno) {
25235942Sbostic 			fprintf(stderr, "ching: Hexagram %d malformed\n",
25335942Sbostic 			    hexagram);
25435942Sbostic 			exit(3);
25535942Sbostic 		}
25635942Sbostic 		if (moving[i])
25735942Sbostic 			fputs(textln, stdout);
25835942Sbostic 		else
25935942Sbostic 			allmoving = 0;
26035942Sbostic 		for (;;) {
26135942Sbostic 			if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
26235942Sbostic 				break;
26335942Sbostic 			lp = &textln[0];
26435942Sbostic 			if (*lp++ == '.' && (*lp == 'L' || *lp == 'H')) {
26535942Sbostic 				lp++;
26635942Sbostic 				break;
26735942Sbostic 			}
26835942Sbostic 			if (moving[i])
26935942Sbostic 				fputs(textln, stdout);
27035942Sbostic 		}
27135942Sbostic 	}
27235942Sbostic 
27335942Sbostic 	/*
27435942Sbostic 	 * If all the lines are moving, print the commentary for that; it
27535942Sbostic 	 * ends with a line of the form
27635942Sbostic 	 * .H <hexagram number> <other arguments>
27735942Sbostic 	 */
27835942Sbostic 	if (*lp == 'A' && allmoving) {
27935942Sbostic 		fputs(textln, stdout);
28035942Sbostic 		for (;;) {
28135942Sbostic 			if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
28235942Sbostic 				break;
28335942Sbostic 			lp = &textln[0];
28435942Sbostic 			if (*lp++ == '.' || *lp++ == 'H')
28535942Sbostic 				break;
28635942Sbostic 			fputs(textln, stdout);
28735942Sbostic 		}
28835942Sbostic 	}
28935942Sbostic }
290