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