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