1 /*- 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Timothy C. Stoehr. 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 * @(#)message.c 8.1 (Berkeley) 5/31/93 33 * $FreeBSD: src/games/rogue/message.c,v 1.7.2.1 2000/07/20 10:35:07 kris Exp $ 34 * $DragonFly: src/games/rogue/message.c,v 1.4 2006/09/02 19:31:07 pavalos Exp $ 35 */ 36 37 /* 38 * message.c 39 * 40 * This source herein may be modified and/or distributed by anybody who 41 * so desires, with the following restrictions: 42 * 1.) No portion of this notice shall be removed. 43 * 2.) Credit shall not be taken for the creation of this source. 44 * 3.) This code is not to be traded, sold, or used for personal 45 * gain or profit. 46 * 47 */ 48 49 #include <stdio.h> 50 #include "rogue.h" 51 #include "pathnames.h" 52 53 char msgs[NMESSAGES][DCOLS] = {"", "", "", "", ""}; 54 short msg_col = 0, imsg = -1; 55 boolean msg_cleared = 1, rmsg = 0; 56 char hunger_str[HUNGER_STR_LEN] = ""; 57 const char *more = "-more-"; 58 59 extern boolean cant_int, did_int, interrupted, save_is_interactive, flush; 60 extern short add_strength; 61 extern short cur_level; 62 63 static void pad(const char *, short); 64 static void save_screen(void); 65 66 void 67 message(const char *msg, boolean intrpt) 68 { 69 cant_int = 1; 70 71 if (!save_is_interactive) { 72 return; 73 } 74 if (intrpt) { 75 interrupted = 1; 76 if (flush) 77 md_slurp(); 78 } 79 80 if (!msg_cleared) { 81 mvaddstr(MIN_ROW-1, msg_col, more); 82 refresh(); 83 wait_for_ack(); 84 check_message(); 85 } 86 if (!rmsg) { 87 imsg = (imsg + 1) % NMESSAGES; 88 strcpy(msgs[imsg], msg); 89 } 90 mvaddstr(MIN_ROW-1, 0, msg); 91 addch(' '); 92 refresh(); 93 msg_cleared = 0; 94 msg_col = strlen(msg); 95 96 cant_int = 0; 97 98 if (did_int) { 99 did_int = 0; 100 onintr(); 101 } 102 } 103 104 void 105 remessage(short c) 106 { 107 if (imsg != -1) { 108 check_message(); 109 rmsg = 1; 110 while (c > imsg) { 111 c -= NMESSAGES; 112 } 113 message(msgs[((imsg - c) % NMESSAGES)], 0); 114 rmsg = 0; 115 move(rogue.row, rogue.col); 116 refresh(); 117 } 118 } 119 120 void 121 check_message(void) 122 { 123 if (msg_cleared) { 124 return; 125 } 126 move(MIN_ROW-1, 0); 127 clrtoeol(); 128 refresh(); 129 msg_cleared = 1; 130 } 131 132 short 133 get_input_line(const char *prompt, const char *insert, char *buf, 134 const char *if_cancelled, boolean add_blank, boolean do_echo) 135 { 136 short ch; 137 short i = 0, n; 138 139 message(prompt, 0); 140 n = strlen(prompt); 141 142 if (insert[0]) { 143 mvaddstr(0, n + 1, insert); 144 strcpy(buf, insert); 145 i = strlen(insert); 146 move(0, (n + i + 1)); 147 refresh(); 148 } 149 150 while (((ch = rgetchar()) != '\r') && (ch != '\n') && (ch != CANCEL)) { 151 if ((ch >= ' ') && (ch <= '~') && (i < MAX_TITLE_LENGTH-2)) { 152 if ((ch != ' ') || (i > 0)) { 153 buf[i++] = ch; 154 if (do_echo) { 155 addch(ch); 156 } 157 } 158 } 159 if ((ch == '\b') && (i > 0)) { 160 if (do_echo) { 161 mvaddch(0, i + n, ' '); 162 move(MIN_ROW-1, i+n); 163 } 164 i--; 165 } 166 refresh(); 167 } 168 check_message(); 169 if (add_blank) { 170 buf[i++] = ' '; 171 } else { 172 while ((i > 0) && (buf[i-1] == ' ')) { 173 i--; 174 } 175 } 176 177 buf[i] = 0; 178 179 if ((ch == CANCEL) || (i == 0) || ((i == 1) && add_blank)) { 180 if (if_cancelled) { 181 message(if_cancelled, 0); 182 } 183 return(0); 184 } 185 return(i); 186 } 187 188 int 189 rgetchar(void) 190 { 191 int ch; 192 193 for(;;) { 194 ch = getchar(); 195 196 switch(ch) { 197 case '\022': 198 wrefresh(curscr); 199 break; 200 #ifdef UNIX_BSD4_2 201 case '\032': 202 printf("%s", CL); 203 fflush(stdout); 204 tstp(); 205 break; 206 #endif 207 case '&': 208 save_screen(); 209 break; 210 default: 211 return(ch); 212 } 213 } 214 } 215 216 /* 217 Level: 99 Gold: 999999 Hp: 999(999) Str: 99(99) Arm: 99 Exp: 21/10000000 Hungry 218 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 219 */ 220 221 void 222 print_stats(int stat_mask) 223 { 224 char buf[16]; 225 boolean label; 226 int row = DROWS - 1; 227 228 label = (stat_mask & STAT_LABEL) ? 1 : 0; 229 230 if (stat_mask & STAT_LEVEL) { 231 if (label) { 232 mvaddstr(row, 0, "Level: "); 233 } 234 /* max level taken care of in make_level() */ 235 sprintf(buf, "%d", cur_level); 236 mvaddstr(row, 7, buf); 237 pad(buf, 2); 238 } 239 if (stat_mask & STAT_GOLD) { 240 if (label) { 241 mvaddstr(row, 10, "Gold: "); 242 } 243 if (rogue.gold > MAX_GOLD) { 244 rogue.gold = MAX_GOLD; 245 } 246 sprintf(buf, "%ld", rogue.gold); 247 mvaddstr(row, 16, buf); 248 pad(buf, 6); 249 } 250 if (stat_mask & STAT_HP) { 251 if (label) { 252 mvaddstr(row, 23, "Hp: "); 253 } 254 if (rogue.hp_max > MAX_HP) { 255 rogue.hp_current -= (rogue.hp_max - MAX_HP); 256 rogue.hp_max = MAX_HP; 257 } 258 sprintf(buf, "%d(%d)", rogue.hp_current, rogue.hp_max); 259 mvaddstr(row, 27, buf); 260 pad(buf, 8); 261 } 262 if (stat_mask & STAT_STRENGTH) { 263 if (label) { 264 mvaddstr(row, 36, "Str: "); 265 } 266 if (rogue.str_max > MAX_STRENGTH) { 267 rogue.str_current -= (rogue.str_max - MAX_STRENGTH); 268 rogue.str_max = MAX_STRENGTH; 269 } 270 sprintf(buf, "%d(%d)", (rogue.str_current + add_strength), 271 rogue.str_max); 272 mvaddstr(row, 41, buf); 273 pad(buf, 6); 274 } 275 if (stat_mask & STAT_ARMOR) { 276 if (label) { 277 mvaddstr(row, 48, "Arm: "); 278 } 279 if (rogue.armor && (rogue.armor->d_enchant > MAX_ARMOR)) { 280 rogue.armor->d_enchant = MAX_ARMOR; 281 } 282 sprintf(buf, "%d", get_armor_class(rogue.armor)); 283 mvaddstr(row, 53, buf); 284 pad(buf, 2); 285 } 286 if (stat_mask & STAT_EXP) { 287 if (label) { 288 mvaddstr(row, 56, "Exp: "); 289 } 290 if (rogue.exp_points > MAX_EXP) { 291 rogue.exp_points = MAX_EXP; 292 } 293 if (rogue.exp > MAX_EXP_LEVEL) { 294 rogue.exp = MAX_EXP_LEVEL; 295 } 296 sprintf(buf, "%d/%ld", rogue.exp, rogue.exp_points); 297 mvaddstr(row, 61, buf); 298 pad(buf, 11); 299 } 300 if (stat_mask & STAT_HUNGER) { 301 mvaddstr(row, 73, hunger_str); 302 clrtoeol(); 303 } 304 refresh(); 305 } 306 307 static void 308 pad(const char *s, short n) 309 { 310 short i; 311 312 for (i = strlen(s); i < n; i++) { 313 addch(' '); 314 } 315 } 316 317 static void 318 save_screen(void) 319 { 320 FILE *fp; 321 short i, j; 322 char buf[DCOLS+2]; 323 boolean found_non_blank; 324 325 if ((fp = fopen(_PATH_SCREENDUMP, "w")) != NULL) { 326 for (i = 0; i < DROWS; i++) { 327 found_non_blank = 0; 328 for (j = (DCOLS - 1); j >= 0; j--) { 329 buf[j] = mvinch(i, j); 330 if (!found_non_blank) { 331 if ((buf[j] != ' ') || (j == 0)) { 332 buf[j + ((j == 0) ? 0 : 1)] = 0; 333 found_non_blank = 1; 334 } 335 } 336 } 337 fputs(buf, fp); 338 putc('\n', fp); 339 } 340 fclose(fp); 341 } else { 342 sound_bell(); 343 } 344 } 345 346 void 347 sound_bell(void) 348 { 349 putchar(7); 350 fflush(stdout); 351 } 352 353 boolean 354 is_digit(short ch) 355 { 356 return((ch >= '0') && (ch <= '9')); 357 } 358 359 int 360 r_index(const char *str, int ch, boolean last) 361 { 362 int i = 0; 363 364 if (last) { 365 for (i = strlen(str) - 1; i >= 0; i--) { 366 if (str[i] == ch) { 367 return(i); 368 } 369 } 370 } else { 371 for (i = 0; str[i]; i++) { 372 if (str[i] == ch) { 373 return(i); 374 } 375 } 376 } 377 return(-1); 378 } 379