xref: /original-bsd/games/ching/phx/ching.phx.c (revision 1e82c8c9)
1 /*
2  * Copyright (c) 1988 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Guy Harris.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 char copyright[] =
13 "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
14  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)ching.phx.c	5.3 (Berkeley) 06/01/90";
19 #endif /* not lint */
20 
21 /*
22  * phx - Print NROFF/TROFF source of change, given the line values.
23  */
24 #include <stdio.h>
25 #include "ching.h"
26 #include "pathnames.h"
27 
28 struct {
29 	int	lines;		/* encoded value of lines */
30 	int	trinum;		/* trigram number */
31 } table[] = {
32 	{ 777, 0 },		/* 1 */
33 	{ 887, 1 },		/* 4 */
34 	{ 878, 2 },		/* 6 */
35 	{ 788, 3 },		/* 7 */
36 	{ 888, 4 },		/* 8 */
37 	{ 778, 5 },		/* 5 */
38 	{ 787, 6 },		/* 3 */
39 	{ 877, 7 },		/* 2 */
40 };
41 
42 /*
43  * Gives hexagram number from two component trigrams.
44  */
45 int	crosstab[8][8] = {
46 	1,  34, 5,  26, 11, 9,  14, 43,
47 	25, 51, 3,  27, 24, 42, 21, 17,
48 	6,  40, 29, 4,  7,  59, 64, 47,
49 	33, 62, 39, 52, 15, 53, 56, 31,
50 	12, 16, 8,  23, 2,  20, 35, 45,
51 	44, 32, 48, 18, 46, 57, 50, 28,
52 	13, 55, 63, 22, 36, 37, 30, 49,
53 	10, 54, 60, 41, 19, 61, 38, 58,
54 };
55 
56 int	trigrams[6];
57 int	moving[6];
58 
59 FILE	*chingf;		/* stream to read the hexagram file */
60 
61 char	*gets();
62 
63 main(argc, argv)
64 int argc;
65 char **argv;
66 {
67 	register int hexagram;		/* hexagram number */
68 	register char *hexptr;		/* pointer to string of lines */
69 	char hexstr[6+1];		/* buffer for reading lines in */
70 	register int i;
71 
72 	if (argc < 2)
73 		hexptr = gets(hexstr);
74 	else
75 		hexptr = argv[1];
76 	if (hexptr == (char *)NULL || strlen(hexptr) != 6) {
77 		fprintf(stderr, "What kind of a change is THAT?!?\n");
78 		exit(1);
79 	}
80 	for (i = 0; i < 6; i++) {
81 		trigrams[i] = hexptr[i] - '0';
82 		if (trigrams[i] == 6 || trigrams[i] == 9)
83 			moving[i] = 1;
84 		else
85 			moving[i] = 0;
86 	}
87 	if ((chingf = fopen(_PATH_HEX, "r")) == (FILE *)NULL) {
88 		fprintf(stderr, "ching: can't read %s\n", _PATH_HEX);
89 		exit(2);
90 	}
91 	phx(doahex(), 0);
92 	if (changes())
93 		phx(doahex(), 1);
94 }
95 
96 /*
97  * Compute the hexagram number, given the trigrams.
98  */
99 int
100 doahex()
101 {
102 	int lower, upper;	/* encoded values of lower and upper trigrams */
103 	int lnum, unum;		/* indices of upper and lower trigrams */
104 	register int i;
105 
106 	lower = codem(0);
107 	upper = codem(3);
108 	for (i = 0; i < 8; i++) {
109 		if (table[i].lines == lower)
110 			 lnum = table[i].trinum;
111 		if (table[i].lines == upper)
112 			 unum = table[i].trinum;
113 	}
114 	return(crosstab[lnum][unum]);
115 }
116 
117 /*
118  * Encode a trigram as a 3-digit number; the digits, from left to right,
119  * represent the lines.  7 is a solid (yang) line, 8 is a broken (yin) line.
120  */
121 codem(a)
122 int a;
123 {
124 	register int code, i;
125 	int factor[3];
126 
127 	factor[0] = 1;
128 	factor[1] = 10;
129 	factor[2] = 100;
130 	code = 0;
131 
132 	for (i = a; i < a + 3; i++) {
133 		switch(trigrams[i]) {
134 
135 		case YYANG:
136 		case OYANG:
137 			code += factor[i%3]*7;
138 			break;
139 
140 		case OYIN:
141 		case YYIN:
142 			code += factor[i%3]*8;
143 			break;
144 		}
145 	}
146 	return(code);
147 }
148 
149 /*
150  * Compute the changes based on moving lines; return 1 if any lines moved,
151  * 0 if no lines moved.
152  */
153 changes()
154 {
155 	register int cflag;
156 	register int i;
157 
158 	cflag = 0;
159 	for (i = 0; i < 6; i++) {
160 		if (trigrams[i] == OYIN) {
161 			trigrams[i] = YYANG;
162 			cflag++;
163 		} else if (trigrams[i] == OYANG) {
164 			trigrams[i] = YYIN;
165 			cflag++;
166 		}
167 	}
168 	return(cflag);
169 }
170 
171 /*
172  * Print the NROFF/TROFF source of a hexagram, given the hexagram number;
173  * if flag is 0, print the entire source; if flag is 1, ignore the meanings
174  * of the lines.
175  */
176 phx(hexagram, flag)
177 int hexagram;
178 int flag;
179 {
180 	char textln[128+1];		/* buffer for text line */
181 	register char *lp;		/* pointer into buffer */
182 	register int thishex;		/* number of hexagram just read */
183 	int lineno;			/* number of line read in */
184 	int allmoving;			/* 1 if all lines are moving */
185 	register int i;
186 
187 	/*
188 	 * Search for the hexagram; it begins with a line of the form
189 	 * .H <hexagram number> <other data>.
190 	 */
191 	rewind(chingf);
192 	for (;;) {
193 		if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
194 			fprintf(stderr, "ching: Hexagram %d missing\n",
195 			    hexagram);
196 			exit(3);
197 		}
198 		lp = &textln[0];
199 		if (*lp++ != '.' || *lp++ != 'H')
200 			continue;
201 		while (*lp++ == ' ')
202 			;
203 		lp--;
204 		thishex = atoi(lp);
205 		if (thishex < 1 || thishex > 64)
206 			continue;
207 		if (thishex == hexagram)
208 			break;
209 	}
210 
211 	/*
212 	 * Print up to the line commentary, which ends with a line of the form
213 	 * .L <position> <value>
214 	 */
215 	fputs(textln, stdout);
216 	for (;;) {
217 		if (fgets(textln, sizeof(textln), chingf) == (char *)NULL) {
218 			fprintf(stderr, "ching: Hexagram %d malformed\n",
219 			    hexagram);
220 			exit(3);
221 		}
222 		lp = &textln[0];
223 		if (*lp++ == '.') {
224 			if (*lp++ == 'L')
225 				break;
226 		}
227 		fputs(textln, stdout);
228 	}
229 
230 	/*
231 	 * Now print the line commentaries, if this is the first hexagram.
232 	 */
233 	if (flag)
234 		return;
235 
236 	/*
237 	 * If a line is moving, print its commentary.
238 	 * The text of the commentary ends with a line either of the form
239 	 * .L <position> <value>
240 	 * or of the form
241 	 * .LA <value>
242 	 * or of the form
243 	 * .H <hexagram number> <other arguments>
244 	 */
245 	allmoving = 1;
246 	for (i = 0; i < 6; i++) {
247 		while (*lp++ == ' ')
248 			;
249 		lp--;
250 		lineno = atoi(lp);
251 		if (i + 1 != lineno) {
252 			fprintf(stderr, "ching: Hexagram %d malformed\n",
253 			    hexagram);
254 			exit(3);
255 		}
256 		if (moving[i])
257 			fputs(textln, stdout);
258 		else
259 			allmoving = 0;
260 		for (;;) {
261 			if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
262 				break;
263 			lp = &textln[0];
264 			if (*lp++ == '.' && (*lp == 'L' || *lp == 'H')) {
265 				lp++;
266 				break;
267 			}
268 			if (moving[i])
269 				fputs(textln, stdout);
270 		}
271 	}
272 
273 	/*
274 	 * If all the lines are moving, print the commentary for that; it
275 	 * ends with a line of the form
276 	 * .H <hexagram number> <other arguments>
277 	 */
278 	if (*lp == 'A' && allmoving) {
279 		fputs(textln, stdout);
280 		for (;;) {
281 			if (fgets(textln, sizeof(textln), chingf) == (char *)NULL)
282 				break;
283 			lp = &textln[0];
284 			if (*lp++ == '.' || *lp++ == 'H')
285 				break;
286 			fputs(textln, stdout);
287 		}
288 	}
289 }
290