1 /* $OpenBSD: fancy.c,v 1.12 2009/10/27 23:59:23 deraadt 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() 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(b, rpos, cpos, cnext) 122 int b; /* contents of position */ 123 int rpos; /* row of position */ 124 int cpos; /* column of position */ 125 int cnext; /* direction of position */ 126 { 127 int j; /* index */ 128 int n; /* number of men on position */ 129 int bct; /* counter */ 130 int k; /* index */ 131 char pc; /* color of men on position */ 132 133 n = abs(b); /* initialize n and pc */ 134 pc = (b > 0 ? 'r' : 'w'); 135 136 if (n < 6 && cpos < 54) /* position cursor at start */ 137 move(rpos, cpos + 1); 138 else 139 move(rpos, cpos); 140 141 for (j = 0; j < 5; j++) { /* print position row by row */ 142 143 for (k = 0; k < 15; k += 5) /* print men */ 144 if (n > j + k) 145 addch(pc); 146 147 if (j < 4) { /* figure how far to back up for next row */ 148 if (n < 6) { /* stop if none left */ 149 if (j + 1 == n) 150 break; 151 bct = 1; /* single column */ 152 } else { 153 if (n < 11) { /* two columns */ 154 if (cpos >= 54) { /* home pos */ 155 if (j + 5 >= n) 156 bct = 1; 157 else 158 bct = 2; 159 } else { /* not home */ 160 if (j + 6 >= n) 161 bct = 1; 162 else 163 bct = 2; 164 } 165 } else { /* three columns */ 166 if (j + 10 >= n) 167 bct = 2; 168 else 169 bct = 3; 170 } 171 } 172 getyx(stdscr, rpos, cpos); 173 move(rpos + cnext, cpos - bct); 174 } 175 } 176 } 177 178 void 179 moveplayers() 180 { 181 int i, r, c; 182 183 getyx(stdscr, r, c); 184 for (i = 12; i > 6; i--)/* fix positions 12-7 */ 185 if (board[i] != oldb[i]) { 186 fixpos(oldb[i], board[i], 13, 1 + (12 - i) * 4, -1); 187 oldb[i] = board[i]; 188 } 189 if (board[0] != oldb[0]) { /* fix red men on bar */ 190 fixpos(oldb[0], board[0], 13, 25, -1); 191 oldb[0] = board[0]; 192 } 193 for (i = 6; i > 0; i--) /* fix positions 6-1 */ 194 if (board[i] != oldb[i]) { 195 fixpos(oldb[i], board[i], 13, 29 + (6 - i) * 4, -1); 196 oldb[i] = board[i]; 197 } 198 i = -(off[0] < 0 ? off[0] + 15 : off[0]); /* fix white's home */ 199 if (oldw != i) { 200 fixpos(oldw, i, 13, 54, -1); 201 oldw = i; 202 } 203 for (i = 13; i < 19; i++) /* fix positions 13-18 */ 204 if (board[i] != oldb[i]) { 205 fixpos(oldb[i], board[i], 3, 1 + (i - 13) * 4, 1); 206 oldb[i] = board[i]; 207 } 208 if (board[25] != oldb[25]) { /* fix white men on bar */ 209 fixpos(oldb[25], board[25], 3, 25, 1); 210 oldb[25] = board[25]; 211 } 212 for (i = 19; i < 25; i++) /* fix positions 19-24 */ 213 if (board[i] != oldb[i]) { 214 fixpos(oldb[i], board[i], 3, 29 + (i - 19) * 4, 1); 215 oldb[i] = board[i]; 216 } 217 i = (off[1] < 0 ? off[1] + 15 : off[1]); /* fix red's home */ 218 if (oldr != i) { 219 fixpos(oldr, i, 3, 54, 1); 220 oldr = i; 221 } 222 move(r, c); /* return to saved position */ 223 refresh(); 224 } 225 226 227 void 228 fixpos(old, new, r, c, inc) 229 int old, new, r, c, inc; 230 { 231 int o, n, nv; 232 int ov, nc; 233 char col; 234 235 nc = 0; 236 if (old * new >= 0) { 237 ov = abs(old); 238 nv = abs(new); 239 col = (old + new > 0 ? 'r' : 'w'); 240 o = (ov - 1) / 5; 241 n = (nv - 1) / 5; 242 if (o == n) { 243 if (o == 2) 244 nc = c + 2; 245 if (o == 1) 246 nc = c < 54 ? c : c + 1; 247 if (o == 0) 248 nc = c < 54 ? c + 1 : c; 249 if (ov > nv) 250 fixcol(r + inc * (nv - n * 5), nc, abs(ov - nv), ' ', inc); 251 else 252 fixcol(r + inc * (ov - o * 5), nc, abs(ov - nv), col, inc); 253 return; 254 } else { 255 if (c < 54) { 256 if (o + n == 1) { 257 if (n) { 258 fixcol(r, c, abs(nv - 5), col, inc); 259 if (ov != 5) 260 fixcol(r+inc*ov, c+1, abs(ov-5), col, inc); 261 } else { 262 fixcol(r, c, abs(ov - 5), ' ', inc); 263 if (nv != 5) 264 fixcol(r+inc*nv, c+1, abs(nv-5), ' ', inc); 265 } 266 return; 267 } 268 if (n == 2) { 269 if (ov != 10) 270 fixcol(r+inc*(ov-5), c, abs(ov-10), col, inc); 271 fixcol(r, c + 2, abs(nv - 10), col, inc); 272 } else { 273 if (nv != 10) 274 fixcol(r+inc*(nv-5), c, abs(nv-10), ' ', inc); 275 fixcol(r, c + 2, abs(ov - 10), ' ', inc); 276 } 277 return; 278 } 279 if (n > o) { 280 fixcol(r+inc*(ov%5), c+o, abs(5*n-ov), col, inc); 281 if (nv != 5 * n) 282 fixcol(r, c+n, abs(5*n-nv), col, inc); 283 } else { 284 fixcol(r+inc*(nv%5), c+n, abs(5*n-nv), ' ', inc); 285 if (ov != 5 * o) 286 fixcol(r, c+o, abs(5*o-ov), ' ', inc); 287 } 288 return; 289 } 290 } 291 nv = abs(new); 292 fixcol(r, c + 1, nv, new > 0 ? 'r' : 'w', inc); 293 if (abs(old) <= abs(new)) 294 return; 295 fixcol(r + inc * new, c + 1, abs(old + new), ' ', inc); 296 } 297 298 void 299 fixcol(r, c, l, ch, inc) 300 int r, c, l, ch, inc; 301 { 302 int i; 303 304 mvaddch(r, c, ch); 305 for (i = 1; i < l; i++) { 306 r += inc; 307 mvaddch(r, c, ch); 308 } 309 } 310 311 312 void 313 initcurses() 314 { 315 initscr(); 316 cbreak(); 317 noecho(); 318 keypad(stdscr, TRUE); 319 nl(); 320 clear(); 321 322 if ((LINES < 24) || (COLS < 80)) { 323 endwin(); 324 errx(1, "screen must be at least 24x80."); 325 } 326 } 327