1 /*	$OpenBSD: fancy.c,v 1.10 2001/06/23 23:50:03 pjanzen Exp $	*/
2 
3 /*
4  * Copyright (c) 1980, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)fancy.c	8.1 (Berkeley) 5/31/93";
39 #else
40 static char rcsid[] = "$OpenBSD: fancy.c,v 1.10 2001/06/23 23:50:03 pjanzen Exp $";
41 #endif
42 #endif /* not lint */
43 
44 #include <err.h>
45 #include "back.h"
46 
47 int     oldb[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
48 int     oldr, oldw;
49 
50 void
51 fboard()
52 {
53 	int     i, j, k, l;
54 
55 	/* could use box() or wborder() instead of the following */
56 	move(0, 0);		/* do top line */
57 	for (i = 0; i < 53; i++)
58 		addch('_');
59 
60 	move(15, 0);		/* do bottom line */
61 	for (i = 0; i < 53; i++)
62 		addch('_');
63 
64 	l = 1;			/* do vertical lines */
65 	for (i = 52; i > -1; i -= 28) {
66 		k = (l == 1 ? 1 : 15);
67 		mvaddch(k, i, '|');
68 		for (j = 0; j < 14; j++)
69 			mvaddch(k += l, i, '|');
70 		if (i == 24)
71 			i += 32;
72 		l = -l;		/* alternate directions */
73 	}
74 
75 	/* label positions */
76 	for (i = 13; i < 19; i++)
77 		mvprintw(2, 1 + (i - 13) * 4, "%d", i);
78 	for (i = 19; i < 25; i++)
79 		mvprintw(2, 29 + (i - 19) * 4, "%d", i);
80 	for (i = 12; i > 6; i--)
81 		mvprintw(14, 1 + (12 - i) * 4, "%2d", i);
82 	for (i = 6; i > 0; i--)
83 		mvprintw(14, 30 + (6 - i) * 4, "%d", i);
84 
85 	/* print positions 12-7 */
86 	for (i = 12; i > 6; i--)
87 		if (board[i])
88 			bsect(board[i], 13, 1 + 4 * (12 - i), -1);
89 	/* print red men on bar */
90 	if (board[0])
91 		bsect(board[0], 13, 25, -1);
92 	/* print positions 6-1 */
93 	for (i = 6; i > 0; i--)
94 		if (board[i])
95 			bsect(board[i], 13, 29 + 4 * (6 - i), -1);
96 	/* print white's home */
97 	l = (off[1] < 0 ? off[1] + 15 : off[1]);
98 	bsect(l, 3, 54, 1);
99 
100 	mvaddstr(8, 25, "BAR");
101 
102 	/* print positions 13-18 */
103 	for (i = 13; i < 19; i++)
104 		if (board[i])
105 			bsect(board[i], 3, 1 + 4 * (i - 13), 1);
106 	/* print white's men on bar */
107 	if (board[25])
108 		bsect(board[25], 3, 25, 1);
109 	/* print positions 19-24 */
110 	for (i = 19; i < 25; i++)
111 		if (board[i])
112 			bsect(board[i], 3, 29 + 4 * (i - 19), 1);
113 	/* print red's home */
114 	l = (off[0] < 0 ? off[0] + 15 : off[0]);
115 	bsect(-l, 13, 54, -1);
116 
117 	for (i = 0; i < 26; i++)/* save board position for refresh later */
118 		oldb[i] = board[i];
119 	oldr = (off[1] < 0 ? off[1] + 15 : off[1]);
120 	oldw = -(off[0] < 0 ? off[0] + 15 : off[0]);
121 }
122 
123 /*
124  * bsect (b,rpos,cpos,cnext)
125  *	Print the contents of a board position.  "b" has the value of the
126  * position, "rpos" is the row to start printing, "cpos" is the column to
127  * start printing, and "cnext" is positive if the position starts at the top
128  * and negative if it starts at the bottom.  The value of "cpos" is checked
129  * to see if the position is a player's home, since those are printed
130  * differently.
131  */
132 void
133 bsect(b, rpos, cpos, cnext)
134 	int     b;		/* contents of position */
135 	int     rpos;		/* row of position */
136 	int     cpos;		/* column of position */
137 	int     cnext;		/* direction of position */
138 {
139 	int     j;		/* index */
140 	int     n;		/* number of men on position */
141 	int     bct;		/* counter */
142 	int     k;		/* index */
143 	char    pc;		/* color of men on position */
144 
145 	n = abs(b);		/* initialize n and pc */
146 	pc = (b > 0 ? 'r' : 'w');
147 
148 	if (n < 6 && cpos < 54)	/* position cursor at start */
149 		move(rpos, cpos + 1);
150 	else
151 		move(rpos, cpos);
152 
153 	for (j = 0; j < 5; j++) {	/* print position row by row */
154 
155 		for (k = 0; k < 15; k += 5)	/* print men */
156 			if (n > j + k)
157 				addch(pc);
158 
159 		if (j < 4) {	/* figure how far to back up for next row */
160 			if (n < 6) {	/* stop if none left */
161 				if (j + 1 == n)
162 					break;
163 				bct = 1;	/* single column */
164 			} else {
165 				if (n < 11) {	/* two columns */
166 					if (cpos >= 54) {	/* home pos */
167 						if (j + 5 >= n)
168 							bct = 1;
169 						else
170 							bct = 2;
171 					} else { 	/* not home */
172 						if (j + 6 >= n)
173 							bct = 1;
174 						else
175 							bct = 2;
176 					}
177 				} else {	/* three columns */
178 					if (j + 10 >= n)
179 						bct = 2;
180 					else
181 						bct = 3;
182 				}
183 			}
184 			getyx(stdscr, rpos, cpos);
185 			move(rpos + cnext, cpos - bct);
186 		}
187 	}
188 }
189 
190 void
191 moveplayers()
192 {
193 	int i, r, c;
194 
195 	getyx(stdscr, r, c);
196 	for (i = 12; i > 6; i--)/* fix positions 12-7 */
197 		if (board[i] != oldb[i]) {
198 			fixpos(oldb[i], board[i], 13, 1 + (12 - i) * 4, -1);
199 			oldb[i] = board[i];
200 		}
201 	if (board[0] != oldb[0]) {	/* fix red men on bar */
202 		fixpos(oldb[0], board[0], 13, 25, -1);
203 		oldb[0] = board[0];
204 	}
205 	for (i = 6; i > 0; i--)	/* fix positions 6-1 */
206 		if (board[i] != oldb[i]) {
207 			fixpos(oldb[i], board[i], 13, 29 + (6 - i) * 4, -1);
208 			oldb[i] = board[i];
209 		}
210 	i = -(off[0] < 0 ? off[0] + 15 : off[0]);	/* fix white's home */
211 	if (oldw != i) {
212 		fixpos(oldw, i, 13, 54, -1);
213 		oldw = i;
214 	}
215 	for (i = 13; i < 19; i++)	/* fix positions 13-18 */
216 		if (board[i] != oldb[i]) {
217 			fixpos(oldb[i], board[i], 3, 1 + (i - 13) * 4, 1);
218 			oldb[i] = board[i];
219 		}
220 	if (board[25] != oldb[25]) {	/* fix white men on bar */
221 		fixpos(oldb[25], board[25], 3, 25, 1);
222 		oldb[25] = board[25];
223 	}
224 	for (i = 19; i < 25; i++)	/* fix positions 19-24 */
225 		if (board[i] != oldb[i]) {
226 			fixpos(oldb[i], board[i], 3, 29 + (i - 19) * 4, 1);
227 			oldb[i] = board[i];
228 		}
229 	i = (off[1] < 0 ? off[1] + 15 : off[1]);	/* fix red's home */
230 	if (oldr != i) {
231 		fixpos(oldr, i, 3, 54, 1);
232 		oldr = i;
233 	}
234 	move(r, c);		/* return to saved position */
235 	refresh();
236 }
237 
238 
239 void
240 fixpos(old, new, r, c, inc)
241 	int     old, new, r, c, inc;
242 {
243 	int     o, n, nv;
244 	int     ov, nc;
245 	char    col;
246 
247 	nc = 0;
248 	if (old * new >= 0) {
249 		ov = abs(old);
250 		nv = abs(new);
251 		col = (old + new > 0 ? 'r' : 'w');
252 		o = (ov - 1) / 5;
253 		n = (nv - 1) / 5;
254 		if (o == n) {
255 			if (o == 2)
256 				nc = c + 2;
257 			if (o == 1)
258 				nc = c < 54 ? c : c + 1;
259 			if (o == 0)
260 				nc = c < 54 ? c + 1 : c;
261 			if (ov > nv)
262 				fixcol(r + inc * (nv - n * 5), nc, abs(ov - nv), ' ', inc);
263 			else
264 				fixcol(r + inc * (ov - o * 5), nc, abs(ov - nv), col, inc);
265 			return;
266 		} else {
267 			if (c < 54) {
268 				if (o + n == 1) {
269 					if (n) {
270 						fixcol(r, c, abs(nv - 5), col, inc);
271 						if (ov != 5)
272 							fixcol(r+inc*ov, c+1, abs(ov-5), col, inc);
273 					} else  {
274 						fixcol(r, c, abs(ov - 5), ' ', inc);
275 						if (nv != 5)
276 							fixcol(r+inc*nv, c+1, abs(nv-5), ' ', inc);
277 					}
278 					return;
279 				}
280 				if (n == 2) {
281 					if (ov != 10)
282 						fixcol(r+inc*(ov-5), c, abs(ov-10), col, inc);
283 					fixcol(r, c + 2, abs(nv - 10), col, inc);
284 				} else {
285 					if (nv != 10)
286 						fixcol(r+inc*(nv-5), c, abs(nv-10), ' ', inc);
287 					fixcol(r, c + 2, abs(ov - 10), ' ', inc);
288 				}
289 				return;
290 			}
291 			if (n > o) {
292 				fixcol(r+inc*(ov%5), c+o, abs(5*n-ov), col, inc);
293 				if (nv != 5 * n)
294 					fixcol(r, c+n, abs(5*n-nv), col, inc);
295 			} else {
296 				fixcol(r+inc*(nv%5), c+n, abs(5*n-nv), ' ', inc);
297 				if (ov != 5 * o)
298 					fixcol(r, c+o, abs(5*o-ov), ' ', inc);
299 			}
300 			return;
301 		}
302 	}
303 	nv = abs(new);
304 	fixcol(r, c + 1, nv, new > 0 ? 'r' : 'w', inc);
305 	if (abs(old) <= abs(new))
306 		return;
307 	fixcol(r + inc * new, c + 1, abs(old + new), ' ', inc);
308 }
309 
310 void
311 fixcol(r, c, l, ch, inc)
312 	int     r, c, l, ch, inc;
313 {
314 	int     i;
315 
316 	mvaddch(r, c, ch);
317 	for (i = 1; i < l; i++) {
318 		r += inc;
319 		mvaddch(r, c, ch);
320 	}
321 }
322 
323 
324 void
325 initcurses()
326 {
327 	initscr();
328 	cbreak();
329 	noecho();
330 	keypad(stdscr, TRUE);
331 	nl();
332 	clear();
333 
334 	if ((LINES < 24) || (COLS < 80)) {
335 		endwin();
336 		errx(1, "screen must be at least 24x80.");
337 	}
338 }
339