1 /*- 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)misc.c 8.1 (Berkeley) 5/31/93 30 * $FreeBSD: src/games/mille/misc.c,v 1.8.2.1 2001/06/13 13:52:14 dwmalone Exp $ 31 * $DragonFly: src/games/mille/misc.c,v 1.4 2006/08/27 17:17:23 pavalos Exp $ 32 */ 33 34 #include <sys/file.h> 35 #include <stdarg.h> 36 #include <termios.h> 37 38 #include "mille.h" 39 #include <term.h> 40 41 /* 42 * @(#)misc.c 1.2 (Berkeley) 3/28/83 43 */ 44 45 #define NUMSAFE 4 46 47 bool 48 error(const char *str, ...) 49 { 50 va_list arg; 51 52 va_start(arg, str); 53 stdscr = Score; 54 move(ERR_Y, ERR_X); 55 vw_printw(stdscr, str, arg); 56 va_end(arg); 57 clrtoeol(); 58 putchar('\07'); 59 refresh(); 60 stdscr = Board; 61 return FALSE; 62 } 63 64 CARD 65 getcard(void) 66 { 67 int c, c1; 68 69 for (;;) { 70 while ((c = readch()) == '\n' || c == '\r' || c == ' ') 71 continue; 72 if (islower(c)) 73 c = toupper(c); 74 if (c == killchar() || c == erasechar()) 75 return -1; 76 addstr(unctrl(c)); 77 clrtoeol(); 78 switch (c) { 79 case '1': case '2': case '3': 80 case '4': case '5': case '6': 81 c -= '0'; 82 break; 83 case '0': case 'P': case 'p': 84 c = 0; 85 break; 86 default: 87 putchar('\07'); 88 addch('\b'); 89 if (!isprint(c)) 90 addch('\b'); 91 c = -1; 92 break; 93 } 94 refresh(); 95 if (c >= 0) { 96 while ((c1=readch()) != '\r' && c1 != '\n' && c1 != ' ') 97 if (c1 == killchar()) 98 return -1; 99 else if (c1 == erasechar()) { 100 addch('\b'); 101 clrtoeol(); 102 refresh(); 103 goto cont; 104 } 105 else 106 write(0, "\07", 1); 107 return c; 108 } 109 cont: ; 110 } 111 } 112 113 bool 114 check_ext(bool forcomp) 115 { 116 117 118 if (End == 700) 119 if (Play == PLAYER) { 120 if (getyn(EXTENSIONPROMPT)) { 121 extend: 122 if (!forcomp) 123 End = 1000; 124 return TRUE; 125 } 126 else { 127 done: 128 if (!forcomp) 129 Finished = TRUE; 130 return FALSE; 131 } 132 } 133 else { 134 PLAY *pp, *op; 135 int i, safe, miles; 136 137 pp = &Player[COMP]; 138 op = &Player[PLAYER]; 139 for (safe = 0, i = 0; i < NUMSAFE; i++) 140 if (pp->safety[i] != S_UNKNOWN) 141 safe++; 142 if (safe < 2) 143 goto done; 144 if (op->mileage == 0 || onecard(op) 145 || (op->can_go && op->mileage >= 500)) 146 goto done; 147 for (miles = 0, i = 0; i < NUMSAFE; i++) 148 if (op->safety[i] != S_PLAYED 149 && pp->safety[i] == S_UNKNOWN) 150 miles++; 151 if (miles + safe == NUMSAFE) 152 goto extend; 153 for (miles = 0, i = 0; i < HAND_SZ; i++) 154 if ((safe = pp->hand[i]) <= C_200) 155 miles += Value[safe]; 156 if (miles + (Topcard - Deck) * 3 > 1000) 157 goto extend; 158 goto done; 159 } 160 else 161 goto done; 162 } 163 164 /* 165 * Get a yes or no answer to the given question. Saves are 166 * also allowed. Return TRUE if the answer was yes, FALSE if no. 167 */ 168 bool 169 getyn(int promptno) 170 { 171 char c; 172 173 Saved = FALSE; 174 for (;;) { 175 leaveok(Board, FALSE); 176 prompt(promptno); 177 clrtoeol(); 178 refresh(); 179 switch (c = readch()) { 180 case 'n': case 'N': 181 addch('N'); 182 refresh(); 183 leaveok(Board, TRUE); 184 return FALSE; 185 case 'y': case 'Y': 186 addch('Y'); 187 refresh(); 188 leaveok(Board, TRUE); 189 return TRUE; 190 case 's': case 'S': 191 addch('S'); 192 refresh(); 193 Saved = save(); 194 continue; 195 case CTRL('L'): 196 wrefresh(curscr); 197 break; 198 default: 199 addstr(unctrl(c)); 200 refresh(); 201 putchar('\07'); 202 break; 203 } 204 } 205 } 206 207 /* 208 * Check to see if more games are desired. If not, and game 209 * came from a saved file, make sure that they don't want to restore 210 * it. Exit appropriately. 211 */ 212 void 213 check_more(void) 214 { 215 On_exit = TRUE; 216 if (Player[PLAYER].total >= 5000 || Player[COMP].total >= 5000) 217 if (getyn(ANOTHERGAMEPROMPT)) 218 return; 219 else { 220 /* 221 * must do accounting normally done in main() 222 */ 223 if (Player[PLAYER].total > Player[COMP].total) 224 Player[PLAYER].games++; 225 else if (Player[PLAYER].total < Player[COMP].total) 226 Player[COMP].games++; 227 Player[COMP].total = 0; 228 Player[PLAYER].total = 0; 229 } 230 else 231 if (getyn(ANOTHERHANDPROMPT)) 232 return; 233 if (!Saved && getyn(SAVEGAMEPROMPT)) 234 if (!save()) 235 return; 236 die(0); 237 } 238 239 char 240 readch(void) 241 { 242 int cnt; 243 static char c; 244 245 for (cnt = 0; read(0, &c, 1) <= 0; cnt++) 246 if (cnt > 100) 247 exit(1); 248 return c; 249 } 250