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