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