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 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 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 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 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 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 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