1 /* $NetBSD: gamesupport.c,v 1.11 2009/08/31 08:27:16 dholland Exp $ */ 2 3 /* 4 * gamesupport.c - auxiliary routines for support of Phantasia 5 */ 6 7 #include <setjmp.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <time.h> 11 12 #include "phantdefs.h" 13 #include "phantstruct.h" 14 #include "phantglobs.h" 15 #include "pathnames.h" 16 17 #undef bool 18 #include <curses.h> 19 20 void 21 changestats(phbool ingameflag) 22 { 23 static char flag[2] = /* for printing values of bools */ 24 {'F', 'T'}; 25 struct player *playerp; /* pointer to structure to alter */ 26 const char *prompt; /* pointer to prompt string */ 27 int c; /* input */ 28 int today; /* day of year of today */ 29 int temp; /* temporary variable */ 30 long loc; /* location in player file */ 31 time_t now; /* time now */ 32 double dtemp; /* temporary variable */ 33 phbool *bptr; /* pointer to bool item to change */ 34 double *dptr; /* pointer to double item to change */ 35 short *sptr; /* pointer to short item to change */ 36 37 clear(); 38 39 for (;;) 40 /* get name of player to examine/alter */ 41 { 42 mvaddstr(5, 0, "Which character do you want to look at ? "); 43 getstring(Databuf, SZ_DATABUF); 44 truncstring(Databuf); 45 46 if (Databuf[0] == '\0') 47 userlist(ingameflag); 48 else 49 break; 50 } 51 52 loc = -1L; 53 54 if (!ingameflag) 55 /* use 'Player' structure */ 56 playerp = &Player; 57 else 58 if (strcmp(Databuf, Player.p_name) == 0) 59 /* alter/examine current player */ 60 { 61 playerp = &Player; 62 loc = Fileloc; 63 } else 64 /* use 'Other' structure */ 65 playerp = &Other; 66 67 /* find player on file */ 68 if (loc < 0L && (loc = findname(Databuf, playerp)) < 0L) 69 /* didn't find player */ 70 { 71 clear(); 72 mvaddstr(11, 0, "Not found."); 73 return; 74 } 75 time(&now); 76 today = localtime(&now)->tm_yday; 77 78 clear(); 79 80 for (;;) 81 /* print player structure, and prompt for action */ 82 { 83 mvprintw(0, 0, "A:Name %s\n", playerp->p_name); 84 85 if (Wizard) 86 printw("B:Password %s\n", playerp->p_password); 87 else 88 addstr("B:Password XXXXXXXX\n"); 89 90 printw(" :Login %s\n", playerp->p_login); 91 92 printw("C:Experience %.0f\n", playerp->p_experience); 93 printw("D:Level %.0f\n", playerp->p_level); 94 printw("E:Strength %.0f\n", playerp->p_strength); 95 printw("F:Sword %.0f\n", playerp->p_sword); 96 printw(" :Might %.0f\n", playerp->p_might); 97 printw("G:Energy %.0f\n", playerp->p_energy); 98 printw("H:Max-Energy %.0f\n", playerp->p_maxenergy); 99 printw("I:Shield %.0f\n", playerp->p_shield); 100 printw("J:Quickness %.0f\n", playerp->p_quickness); 101 printw("K:Quicksilver %.0f\n", playerp->p_quksilver); 102 printw(" :Speed %.0f\n", playerp->p_speed); 103 printw("L:Magic Level %.0f\n", playerp->p_magiclvl); 104 printw("M:Mana %.0f\n", playerp->p_mana); 105 printw("N:Brains %.0f\n", playerp->p_brains); 106 107 if (Wizard || playerp->p_specialtype != SC_VALAR) 108 mvaddstr(0, 40, descrstatus(playerp)); 109 110 mvprintw(1, 40, "O:Poison %0.3f\n", playerp->p_poison); 111 mvprintw(2, 40, "P:Gold %.0f\n", playerp->p_gold); 112 mvprintw(3, 40, "Q:Gem %.0f\n", playerp->p_gems); 113 mvprintw(4, 40, "R:Sin %0.3f\n", playerp->p_sin); 114 if (Wizard) { 115 mvprintw(5, 40, "S:X-coord %.0f\n", playerp->p_x); 116 mvprintw(6, 40, "T:Y-coord %.0f\n", playerp->p_y); 117 } else { 118 mvaddstr(5, 40, "S:X-coord ?\n"); 119 mvaddstr(6, 40, "T:Y-coord ?\n"); 120 } 121 122 mvprintw(7, 40, "U:Age %ld\n", playerp->p_age); 123 mvprintw(8, 40, "V:Degenerated %d\n", playerp->p_degenerated); 124 125 mvprintw(9, 40, "W:Type %d (%s)\n", 126 playerp->p_type, descrtype(playerp, FALSE) + 1); 127 mvprintw(10, 40, "X:Special Type %d\n", playerp->p_specialtype); 128 mvprintw(11, 40, "Y:Lives %d\n", playerp->p_lives); 129 mvprintw(12, 40, "Z:Crowns %d\n", playerp->p_crowns); 130 mvprintw(13, 40, "0:Charms %d\n", playerp->p_charms); 131 mvprintw(14, 40, "1:Amulets %d\n", playerp->p_amulets); 132 mvprintw(15, 40, "2:Holy Water %d\n", playerp->p_holywater); 133 134 temp = today - playerp->p_lastused; 135 if (temp < 0) 136 /* last year */ 137 temp += 365; 138 mvprintw(16, 40, "3:Lastused %d (%d)\n", playerp->p_lastused, temp); 139 140 mvprintw(18, 8, "4:Palantir %c 5:Blessing %c 6:Virgin %c 7:Blind %c", 141 flag[(int)playerp->p_palantir], 142 flag[(int)playerp->p_blessing], 143 flag[(int)playerp->p_virgin], 144 flag[(int)playerp->p_blindness]); 145 146 if (!Wizard) 147 mvprintw(19, 8, "8:Ring %c", 148 flag[playerp->p_ring.ring_type != R_NONE]); 149 else 150 mvprintw(19, 8, "8:Ring %d 9:Duration %d", 151 playerp->p_ring.ring_type, playerp->p_ring.ring_duration); 152 153 if (!Wizard 154 /* not wizard */ 155 && (ingameflag || strcmp(Login, playerp->p_login) != 0)) 156 /* in game or not examining own character */ 157 { 158 if (ingameflag) { 159 more(LINES - 1); 160 clear(); 161 return; 162 } else 163 cleanup(TRUE); 164 /* NOTREACHED */ 165 } 166 mvaddstr(20, 0, "!:Quit ?:Delete"); 167 mvaddstr(21, 0, "What would you like to change ? "); 168 169 if (Wizard) 170 c = getanswer(" ", TRUE); 171 else 172 /* examining own player; allow to change name and 173 * password */ 174 c = getanswer("!BA", FALSE); 175 176 switch (c) { 177 case 'A': /* change name */ 178 case 'B': /* change password */ 179 if (!Wizard) 180 /* prompt for password */ 181 { 182 mvaddstr(23, 0, "Password ? "); 183 Echo = FALSE; 184 getstring(Databuf, 9); 185 Echo = TRUE; 186 if (strcmp(Databuf, playerp->p_password) != 0) 187 continue; 188 } 189 if (c == 'A') 190 /* get new name */ 191 { 192 mvaddstr(23, 0, "New name: "); 193 getstring(Databuf, SZ_NAME); 194 truncstring(Databuf); 195 if (Databuf[0] != '\0') 196 if (Wizard || findname(Databuf, &Other) < 0L) 197 strcpy(playerp->p_name, Databuf); 198 } else 199 /* get new password */ 200 { 201 if (!Wizard) 202 Echo = FALSE; 203 204 do 205 /* get two copies of new password 206 * until they match */ 207 { 208 /* get first copy */ 209 mvaddstr(23, 0, "New password ? "); 210 getstring(Databuf, SZ_PASSWORD); 211 if (Databuf[0] == '\0') 212 break; 213 214 /* get second copy */ 215 mvaddstr(23, 0, "One more time ? "); 216 getstring(playerp->p_password, SZ_PASSWORD); 217 } 218 while (strcmp(playerp->p_password, Databuf) != 0); 219 220 Echo = TRUE; 221 } 222 223 continue; 224 225 case 'C': /* change experience */ 226 prompt = "experience"; 227 dptr = &playerp->p_experience; 228 goto DALTER; 229 230 case 'D': /* change level */ 231 prompt = "level"; 232 dptr = &playerp->p_level; 233 goto DALTER; 234 235 case 'E': /* change strength */ 236 prompt = "strength"; 237 dptr = &playerp->p_strength; 238 goto DALTER; 239 240 case 'F': /* change swords */ 241 prompt = "sword"; 242 dptr = &playerp->p_sword; 243 goto DALTER; 244 245 case 'G': /* change energy */ 246 prompt = "energy"; 247 dptr = &playerp->p_energy; 248 goto DALTER; 249 250 case 'H': /* change maximum energy */ 251 prompt = "max energy"; 252 dptr = &playerp->p_maxenergy; 253 goto DALTER; 254 255 case 'I': /* change shields */ 256 prompt = "shield"; 257 dptr = &playerp->p_shield; 258 goto DALTER; 259 260 case 'J': /* change quickness */ 261 prompt = "quickness"; 262 dptr = &playerp->p_quickness; 263 goto DALTER; 264 265 case 'K': /* change quicksilver */ 266 prompt = "quicksilver"; 267 dptr = &playerp->p_quksilver; 268 goto DALTER; 269 270 case 'L': /* change magic */ 271 prompt = "magic level"; 272 dptr = &playerp->p_magiclvl; 273 goto DALTER; 274 275 case 'M': /* change mana */ 276 prompt = "mana"; 277 dptr = &playerp->p_mana; 278 goto DALTER; 279 280 case 'N': /* change brains */ 281 prompt = "brains"; 282 dptr = &playerp->p_brains; 283 goto DALTER; 284 285 case 'O': /* change poison */ 286 prompt = "poison"; 287 dptr = &playerp->p_poison; 288 goto DALTER; 289 290 case 'P': /* change gold */ 291 prompt = "gold"; 292 dptr = &playerp->p_gold; 293 goto DALTER; 294 295 case 'Q': /* change gems */ 296 prompt = "gems"; 297 dptr = &playerp->p_gems; 298 goto DALTER; 299 300 case 'R': /* change sin */ 301 prompt = "sin"; 302 dptr = &playerp->p_sin; 303 goto DALTER; 304 305 case 'S': /* change x coord */ 306 prompt = "x"; 307 dptr = &playerp->p_x; 308 goto DALTER; 309 310 case 'T': /* change y coord */ 311 prompt = "y"; 312 dptr = &playerp->p_y; 313 goto DALTER; 314 315 case 'U': /* change age */ 316 mvprintw(23, 0, "age = %ld; age = ", playerp->p_age); 317 dtemp = infloat(); 318 if (dtemp != 0.0) 319 playerp->p_age = (long) dtemp; 320 continue; 321 322 case 'V': /* change degen */ 323 mvprintw(23, 0, "degen = %d; degen = ", playerp->p_degenerated); 324 dtemp = infloat(); 325 if (dtemp != 0.0) 326 playerp->p_degenerated = (int) dtemp; 327 continue; 328 329 case 'W': /* change type */ 330 prompt = "type"; 331 sptr = &playerp->p_type; 332 goto SALTER; 333 334 case 'X': /* change special type */ 335 prompt = "special type"; 336 sptr = &playerp->p_specialtype; 337 goto SALTER; 338 339 case 'Y': /* change lives */ 340 prompt = "lives"; 341 sptr = &playerp->p_lives; 342 goto SALTER; 343 344 case 'Z': /* change crowns */ 345 prompt = "crowns"; 346 sptr = &playerp->p_crowns; 347 goto SALTER; 348 349 case '0': /* change charms */ 350 prompt = "charm"; 351 sptr = &playerp->p_charms; 352 goto SALTER; 353 354 case '1': /* change amulet */ 355 prompt = "amulet"; 356 sptr = &playerp->p_amulets; 357 goto SALTER; 358 359 case '2': /* change holy water */ 360 prompt = "holy water"; 361 sptr = &playerp->p_holywater; 362 goto SALTER; 363 364 case '3': /* change last-used */ 365 prompt = "last-used"; 366 sptr = &playerp->p_lastused; 367 goto SALTER; 368 369 case '4': /* change palantir */ 370 prompt = "palantir"; 371 bptr = &playerp->p_palantir; 372 goto BALTER; 373 374 case '5': /* change blessing */ 375 prompt = "blessing"; 376 bptr = &playerp->p_blessing; 377 goto BALTER; 378 379 case '6': /* change virgin */ 380 prompt = "virgin"; 381 bptr = &playerp->p_virgin; 382 goto BALTER; 383 384 case '7': /* change blindness */ 385 prompt = "blindness"; 386 bptr = &playerp->p_blindness; 387 goto BALTER; 388 389 case '8': /* change ring type */ 390 prompt = "ring-type"; 391 sptr = &playerp->p_ring.ring_type; 392 goto SALTER; 393 394 case '9': /* change ring duration */ 395 prompt = "ring-duration"; 396 sptr = &playerp->p_ring.ring_duration; 397 goto SALTER; 398 399 case '!': /* quit, update */ 400 if (Wizard && 401 (!ingameflag || playerp != &Player)) 402 /* turn off status if not modifying self */ 403 { 404 playerp->p_status = S_OFF; 405 playerp->p_tampered = T_OFF; 406 } 407 writerecord(playerp, loc); 408 clear(); 409 return; 410 411 case '?': /* delete player */ 412 if (ingameflag && playerp == &Player) 413 /* cannot delete self */ 414 continue; 415 416 freerecord(playerp, loc); 417 clear(); 418 return; 419 420 default: 421 continue; 422 } 423 DALTER: 424 mvprintw(23, 0, "%s = %f; %s = ", prompt, *dptr, prompt); 425 dtemp = infloat(); 426 if (dtemp != 0.0) 427 *dptr = dtemp; 428 continue; 429 430 SALTER: 431 mvprintw(23, 0, "%s = %d; %s = ", prompt, *sptr, prompt); 432 dtemp = infloat(); 433 if (dtemp != 0.0) 434 *sptr = (short) dtemp; 435 continue; 436 437 BALTER: 438 mvprintw(23, 0, "%s = %c; %s = ", prompt, flag[(int)*bptr], 439 prompt); 440 c = getanswer("\nTF", TRUE); 441 if (c == 'T') 442 *bptr = TRUE; 443 else 444 if (c == 'F') 445 *bptr = FALSE; 446 continue; 447 } 448 } 449 450 void 451 monstlist(void) 452 { 453 int count = 0; /* count in file */ 454 455 puts(" #) Name Str Brain Quick Energy Exper Treas Type Flock%\n"); 456 fseek(Monstfp, 0L, SEEK_SET); 457 while (fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp) == 1) 458 printf("%2d) %-20.20s%4.0f %4.0f %2.0f %5.0f %5.0f %2d %2d %3.0f\n", count++, 459 Curmonster.m_name, Curmonster.m_strength, Curmonster.m_brains, 460 Curmonster.m_speed, Curmonster.m_energy, Curmonster.m_experience, 461 Curmonster.m_treasuretype, Curmonster.m_type, Curmonster.m_flock); 462 } 463 464 void 465 scorelist(void) 466 { 467 struct scoreboard sbuf; /* for reading entries */ 468 FILE *fp; /* to open the file */ 469 470 if ((fp = fopen(_PATH_SCORE, "r")) != NULL) { 471 while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1) 472 printf("%-20s (%-9s) Level: %6.0f Type: %s\n", 473 sbuf.sb_name, sbuf.sb_login, sbuf.sb_level, sbuf.sb_type); 474 fclose(fp); 475 } 476 } 477 478 void 479 activelist(void) 480 { 481 fseek(Playersfp, 0L, SEEK_SET); 482 printf("Current characters on file are:\n\n"); 483 484 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 485 if (Other.p_status != S_NOTUSED) 486 printf("%-20s (%-9s) Level: %6.0f %s (%s)\n", 487 Other.p_name, Other.p_login, Other.p_level, 488 descrtype(&Other, FALSE), descrstatus(&Other)); 489 490 } 491 492 void 493 purgeoldplayers(void) 494 { 495 int today; /* day of year for today */ 496 int daysold; /* how many days since the character has been 497 * used */ 498 time_t ltime; /* time in seconds */ 499 long loc = 0L; /* location in file */ 500 501 time(<ime); 502 today = localtime(<ime)->tm_yday; 503 504 for (;;) { 505 fseek(Playersfp, loc, SEEK_SET); 506 if (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) != 1) 507 break; 508 509 daysold = today - Other.p_lastused; 510 if (daysold < 0) 511 daysold += 365; 512 513 if (daysold > N_DAYSOLD) 514 /* player hasn't been used in a while; delete */ 515 freerecord(&Other, loc); 516 517 loc += SZ_PLAYERSTRUCT; 518 } 519 } 520 521 void 522 enterscore(void) 523 { 524 struct scoreboard sbuf; /* buffer to read in scoreboard entries */ 525 FILE *fp; /* to open scoreboard file */ 526 long loc = 0L; /* location in scoreboard file */ 527 bool found = FALSE; /* set if we found an entry for this login */ 528 529 if ((fp = fopen(_PATH_SCORE, "r+")) != NULL) { 530 while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1) 531 if (strcmp(Player.p_login, sbuf.sb_login) == 0) { 532 found = TRUE; 533 break; 534 } else 535 loc += SZ_SCORESTRUCT; 536 } else { 537 error(_PATH_SCORE); 538 /* NOTREACHED */ 539 } 540 541 /* 542 * At this point, 'loc' will either indicate a point beyond 543 * the end of file, or the place where the previous entry 544 * was found. 545 */ 546 547 if ((!found) || Player.p_level > sbuf.sb_level) 548 /* put new entry in for this login */ 549 { 550 strcpy(sbuf.sb_login, Player.p_login); 551 strcpy(sbuf.sb_name, Player.p_name); 552 sbuf.sb_level = Player.p_level; 553 strcpy(sbuf.sb_type, descrtype(&Player, TRUE)); 554 } 555 /* update entry */ 556 fseek(fp, loc, SEEK_SET); 557 fwrite((char *) &sbuf, SZ_SCORESTRUCT, 1, fp); 558 fclose(fp); 559 } 560