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