1 1.24 andvar /* $NetBSD: misc.c,v 1.24 2022/05/24 06:27:59 andvar Exp $ */ 2 1.2 cgd 3 1.1 jtc /* 4 1.1 jtc * misc.c Phantasia miscellaneous support routines 5 1.1 jtc */ 6 1.1 jtc 7 1.19 dholland #include <errno.h> 8 1.19 dholland #include <math.h> 9 1.19 dholland #include <setjmp.h> 10 1.19 dholland #include <signal.h> 11 1.19 dholland #include <stdio.h> 12 1.19 dholland #include <stdlib.h> 13 1.19 dholland #include <string.h> 14 1.19 dholland #include <unistd.h> 15 1.19 dholland 16 1.19 dholland #include "macros.h" 17 1.19 dholland #include "phantdefs.h" 18 1.19 dholland #include "phantstruct.h" 19 1.19 dholland #include "phantglobs.h" 20 1.19 dholland #include "pathnames.h" 21 1.19 dholland 22 1.12 he #undef bool 23 1.11 ross #include <curses.h> 24 1.1 jtc 25 1.1 jtc 26 1.18 dholland static double explevel(double); 27 1.18 dholland 28 1.18 dholland static void 29 1.16 dholland movelevel(void) 30 1.1 jtc { 31 1.5 jsm const struct charstats *statptr; /* for pointing into Stattable */ 32 1.3 lukem double new; /* new level */ 33 1.3 lukem double inc; /* increment between new and old levels */ 34 1.3 lukem 35 1.3 lukem Changed = TRUE; 36 1.3 lukem 37 1.3 lukem if (Player.p_type == C_EXPER) 38 1.3 lukem /* roll a type to use for increment */ 39 1.3 lukem statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)]; 40 1.3 lukem else 41 1.3 lukem statptr = Statptr; 42 1.1 jtc 43 1.3 lukem new = explevel(Player.p_experience); 44 1.3 lukem inc = new - Player.p_level; 45 1.3 lukem Player.p_level = new; 46 1.3 lukem 47 1.3 lukem /* add increments to statistics */ 48 1.3 lukem Player.p_strength += statptr->c_strength.increase * inc; 49 1.3 lukem Player.p_mana += statptr->c_mana.increase * inc; 50 1.3 lukem Player.p_brains += statptr->c_brains.increase * inc; 51 1.3 lukem Player.p_magiclvl += statptr->c_magiclvl.increase * inc; 52 1.3 lukem Player.p_maxenergy += statptr->c_energy.increase * inc; 53 1.1 jtc 54 1.3 lukem /* rest to maximum upon reaching new level */ 55 1.3 lukem Player.p_energy = Player.p_maxenergy + Player.p_shield; 56 1.3 lukem 57 1.3 lukem if (Player.p_crowns > 0 && Player.p_level >= 1000.0) 58 1.3 lukem /* no longer able to be king -- turn crowns into cash */ 59 1.1 jtc { 60 1.3 lukem Player.p_gold += ((double) Player.p_crowns) * 5000.0; 61 1.3 lukem Player.p_crowns = 0; 62 1.1 jtc } 63 1.3 lukem if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL) 64 1.3 lukem /* make a member of the council */ 65 1.1 jtc { 66 1.3 lukem mvaddstr(6, 0, "You have made it to the Council of the Wise.\n"); 67 1.3 lukem addstr("Good Luck on your search for the Holy Grail.\n"); 68 1.1 jtc 69 1.3 lukem Player.p_specialtype = SC_COUNCIL; 70 1.1 jtc 71 1.3 lukem /* no rings for council and above */ 72 1.3 lukem Player.p_ring.ring_type = R_NONE; 73 1.3 lukem Player.p_ring.ring_duration = 0; 74 1.1 jtc 75 1.3 lukem Player.p_lives = 3; /* three extra lives */ 76 1.1 jtc } 77 1.3 lukem if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR) 78 1.3 lukem death("Old age"); 79 1.1 jtc } 80 1.1 jtc 81 1.5 jsm const char * 82 1.16 dholland descrlocation(struct player *playerp, phbool shortflag) 83 1.1 jtc { 84 1.3 lukem double circle; /* corresponding circle for coordinates */ 85 1.3 lukem int quadrant; /* quandrant of grid */ 86 1.5 jsm const char *label; /* pointer to place name */ 87 1.5 jsm static const char *const nametable[4][4] = /* names of places */ 88 1.3 lukem { 89 1.3 lukem {"Anorien", "Ithilien", "Rohan", "Lorien"}, 90 1.3 lukem {"Gondor", "Mordor", "Dunland", "Rovanion"}, 91 1.3 lukem {"South Gondor", "Khand", "Eriador", "The Iron Hills"}, 92 1.3 lukem {"Far Harad", "Near Harad", "The Northern Waste", "Rhun"} 93 1.1 jtc }; 94 1.1 jtc 95 1.3 lukem if (playerp->p_specialtype == SC_VALAR) 96 1.3 lukem return (" is in Valhala"); 97 1.1 jtc else 98 1.3 lukem if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0) { 99 1.3 lukem if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND) 100 1.3 lukem label = "The Point of No Return"; 101 1.3 lukem else 102 1.3 lukem label = "The Ashen Mountains"; 103 1.3 lukem } else 104 1.3 lukem if (circle >= 55) 105 1.3 lukem label = "Morannon"; 106 1.3 lukem else 107 1.3 lukem if (circle >= 35) 108 1.3 lukem label = "Kennaquahair"; 109 1.3 lukem else 110 1.3 lukem if (circle >= 20) 111 1.3 lukem label = "The Dead Marshes"; 112 1.3 lukem else 113 1.3 lukem if (circle >= 9) 114 1.3 lukem label = "The Outer Waste"; 115 1.3 lukem else 116 1.3 lukem if (circle >= 5) 117 1.3 lukem label = "The Moors Adventurous"; 118 1.3 lukem else { 119 1.3 lukem if (playerp->p_x == 0.0 && playerp->p_y == 0.0) 120 1.3 lukem label = "The Lord's Chamber"; 121 1.3 lukem else { 122 1.3 lukem /* this 123 1.23 rillig * 124 1.3 lukem * expr 125 1.3 lukem * essi 126 1.3 lukem * on 127 1.3 lukem * is 128 1.3 lukem * spli 129 1.3 lukem * t 130 1.3 lukem * to 131 1.3 lukem * prev 132 1.3 lukem * ent 133 1.3 lukem * comp 134 1.3 lukem * iler 135 1.23 rillig * 136 1.3 lukem * loop 137 1.23 rillig * 138 1.3 lukem * with 139 1.23 rillig * 140 1.3 lukem * some 141 1.23 rillig * 142 1.3 lukem * comp 143 1.3 lukem * iler 144 1.3 lukem * s */ 145 1.3 lukem quadrant = ((playerp->p_x > 0.0) ? 1 : 0); 146 1.3 lukem quadrant += ((playerp->p_y >= 0.0) ? 2 : 0); 147 1.3 lukem label = nametable[((int) circle) - 1][quadrant]; 148 1.3 lukem } 149 1.3 lukem } 150 1.3 lukem 151 1.3 lukem if (shortflag) 152 1.17 dholland snprintf(Databuf, SZ_DATABUF, "%.29s", label); 153 1.1 jtc else 154 1.23 rillig snprintf(Databuf, SZ_DATABUF, 155 1.17 dholland " is in %s (%.0f,%.0f)", 156 1.17 dholland label, playerp->p_x, playerp->p_y); 157 1.1 jtc 158 1.3 lukem return (Databuf); 159 1.3 lukem } 160 1.1 jtc 161 1.3 lukem void 162 1.16 dholland tradingpost(void) 163 1.1 jtc { 164 1.3 lukem double numitems; /* number of items to purchase */ 165 1.3 lukem double cost; /* cost of purchase */ 166 1.3 lukem double blessingcost; /* cost of blessing */ 167 1.3 lukem int ch; /* input */ 168 1.3 lukem int size; /* size of the trading post */ 169 1.3 lukem int loop; /* loop counter */ 170 1.3 lukem int cheat = 0; /* number of times player has tried to cheat */ 171 1.3 lukem bool dishonest = FALSE; /* set when merchant is dishonest */ 172 1.1 jtc 173 1.3 lukem Player.p_status = S_TRADING; 174 1.3 lukem writerecord(&Player, Fileloc); 175 1.1 jtc 176 1.3 lukem clear(); 177 1.3 lukem addstr("You are at a trading post. All purchases must be made with gold."); 178 1.3 lukem 179 1.3 lukem size = sqrt(fabs(Player.p_x / 100)) + 1; 180 1.3 lukem size = MIN(7, size); 181 1.1 jtc 182 1.3 lukem /* set up cost of blessing */ 183 1.3 lukem blessingcost = 1000.0 * (Player.p_level + 5.0); 184 1.1 jtc 185 1.3 lukem /* print Menu */ 186 1.3 lukem move(7, 0); 187 1.3 lukem for (loop = 0; loop < size; ++loop) 188 1.3 lukem /* print Menu */ 189 1.3 lukem { 190 1.3 lukem if (loop == 6) 191 1.3 lukem cost = blessingcost; 192 1.1 jtc else 193 1.3 lukem cost = Menu[loop].cost; 194 1.3 lukem printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost); 195 1.3 lukem } 196 1.1 jtc 197 1.3 lukem mvprintw(5, 0, "L:Leave P:Purchase S:Sell Gems ? "); 198 1.1 jtc 199 1.3 lukem for (;;) { 200 1.3 lukem adjuststats(); /* truncate any bad values */ 201 1.1 jtc 202 1.3 lukem /* print some important statistics */ 203 1.3 lukem mvprintw(1, 0, "Gold: %9.0f Gems: %9.0f Level: %6.0f Charms: %6d\n", 204 1.3 lukem Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms); 205 1.3 lukem printw("Shield: %9.0f Sword: %9.0f Quicksilver:%3.0f Blessed: %s\n", 206 1.3 lukem Player.p_shield, Player.p_sword, Player.p_quksilver, 207 1.3 lukem (Player.p_blessing ? " True" : "False")); 208 1.3 lukem printw("Brains: %9.0f Mana: %9.0f", Player.p_brains, Player.p_mana); 209 1.1 jtc 210 1.3 lukem move(5, 36); 211 1.3 lukem ch = getanswer("LPS", FALSE); 212 1.3 lukem move(15, 0); 213 1.3 lukem clrtobot(); 214 1.3 lukem switch (ch) { 215 1.3 lukem case 'L': /* leave */ 216 1.3 lukem case '\n': 217 1.3 lukem altercoordinates(0.0, 0.0, A_NEAR); 218 1.3 lukem return; 219 1.3 lukem 220 1.3 lukem case 'P': /* make purchase */ 221 1.3 lukem mvaddstr(15, 0, "What what would you like to buy ? "); 222 1.3 lukem ch = getanswer(" 1234567", FALSE); 223 1.3 lukem move(15, 0); 224 1.3 lukem clrtoeol(); 225 1.3 lukem 226 1.3 lukem if (ch - '0' > size) 227 1.3 lukem addstr("Sorry, this merchant doesn't have that."); 228 1.3 lukem else 229 1.3 lukem switch (ch) { 230 1.3 lukem case '1': 231 1.3 lukem printw("Mana is one per %.0f gold piece. How many do you want (%.0f max) ? ", 232 1.3 lukem Menu[0].cost, floor(Player.p_gold / Menu[0].cost)); 233 1.3 lukem cost = (numitems = floor(infloat())) * Menu[0].cost; 234 1.3 lukem 235 1.3 lukem if (cost > Player.p_gold || numitems < 0) 236 1.3 lukem ++cheat; 237 1.3 lukem else { 238 1.3 lukem cheat = 0; 239 1.3 lukem Player.p_gold -= cost; 240 1.3 lukem if (drandom() < 0.02) 241 1.3 lukem dishonest = TRUE; 242 1.3 lukem else 243 1.3 lukem Player.p_mana += numitems; 244 1.3 lukem } 245 1.3 lukem break; 246 1.3 lukem 247 1.3 lukem case '2': 248 1.3 lukem printw("Shields are %.0f per +1. How many do you want (%.0f max) ? ", 249 1.3 lukem Menu[1].cost, floor(Player.p_gold / Menu[1].cost)); 250 1.3 lukem cost = (numitems = floor(infloat())) * Menu[1].cost; 251 1.3 lukem 252 1.3 lukem if (numitems == 0.0) 253 1.3 lukem break; 254 1.3 lukem else 255 1.3 lukem if (cost > Player.p_gold || numitems < 0) 256 1.3 lukem ++cheat; 257 1.3 lukem else 258 1.3 lukem if (numitems < Player.p_shield) 259 1.3 lukem NOBETTER(); 260 1.3 lukem else { 261 1.3 lukem cheat = 0; 262 1.3 lukem Player.p_gold -= cost; 263 1.3 lukem if (drandom() < 0.02) 264 1.3 lukem dishonest = TRUE; 265 1.3 lukem else 266 1.3 lukem Player.p_shield = numitems; 267 1.3 lukem } 268 1.3 lukem break; 269 1.3 lukem 270 1.3 lukem case '3': 271 1.3 lukem printw("A book costs %.0f gp. How many do you want (%.0f max) ? ", 272 1.3 lukem Menu[2].cost, floor(Player.p_gold / Menu[2].cost)); 273 1.3 lukem cost = (numitems = floor(infloat())) * Menu[2].cost; 274 1.3 lukem 275 1.3 lukem if (cost > Player.p_gold || numitems < 0) 276 1.3 lukem ++cheat; 277 1.3 lukem else { 278 1.3 lukem cheat = 0; 279 1.3 lukem Player.p_gold -= cost; 280 1.3 lukem if (drandom() < 0.02) 281 1.3 lukem dishonest = TRUE; 282 1.3 lukem else 283 1.3 lukem if (drandom() * numitems > Player.p_level / 10.0 284 1.3 lukem && numitems != 1) { 285 1.3 lukem printw("\nYou blew your mind!\n"); 286 1.3 lukem Player.p_brains /= 5; 287 1.3 lukem } else { 288 1.3 lukem Player.p_brains += floor(numitems) * ROLL(20, 8); 289 1.3 lukem } 290 1.3 lukem } 291 1.3 lukem break; 292 1.3 lukem 293 1.3 lukem case '4': 294 1.3 lukem printw("Swords are %.0f gp per +1. How many + do you want (%.0f max) ? ", 295 1.3 lukem Menu[3].cost, floor(Player.p_gold / Menu[3].cost)); 296 1.3 lukem cost = (numitems = floor(infloat())) * Menu[3].cost; 297 1.3 lukem 298 1.3 lukem if (numitems == 0.0) 299 1.3 lukem break; 300 1.3 lukem else 301 1.3 lukem if (cost > Player.p_gold || numitems < 0) 302 1.3 lukem ++cheat; 303 1.3 lukem else 304 1.3 lukem if (numitems < Player.p_sword) 305 1.3 lukem NOBETTER(); 306 1.3 lukem else { 307 1.3 lukem cheat = 0; 308 1.3 lukem Player.p_gold -= cost; 309 1.3 lukem if (drandom() < 0.02) 310 1.3 lukem dishonest = TRUE; 311 1.3 lukem else 312 1.3 lukem Player.p_sword = numitems; 313 1.3 lukem } 314 1.3 lukem break; 315 1.3 lukem 316 1.3 lukem case '5': 317 1.3 lukem printw("A charm costs %.0f gp. How many do you want (%.0f max) ? ", 318 1.3 lukem Menu[4].cost, floor(Player.p_gold / Menu[4].cost)); 319 1.3 lukem cost = (numitems = floor(infloat())) * Menu[4].cost; 320 1.3 lukem 321 1.3 lukem if (cost > Player.p_gold || numitems < 0) 322 1.3 lukem ++cheat; 323 1.3 lukem else { 324 1.3 lukem cheat = 0; 325 1.3 lukem Player.p_gold -= cost; 326 1.3 lukem if (drandom() < 0.02) 327 1.3 lukem dishonest = TRUE; 328 1.3 lukem else 329 1.3 lukem Player.p_charms += numitems; 330 1.3 lukem } 331 1.3 lukem break; 332 1.3 lukem 333 1.3 lukem case '6': 334 1.3 lukem printw("Quicksilver is %.0f gp per +1. How many + do you want (%.0f max) ? ", 335 1.3 lukem Menu[5].cost, floor(Player.p_gold / Menu[5].cost)); 336 1.3 lukem cost = (numitems = floor(infloat())) * Menu[5].cost; 337 1.3 lukem 338 1.3 lukem if (numitems == 0.0) 339 1.3 lukem break; 340 1.3 lukem else 341 1.3 lukem if (cost > Player.p_gold || numitems < 0) 342 1.3 lukem ++cheat; 343 1.3 lukem else 344 1.3 lukem if (numitems < Player.p_quksilver) 345 1.3 lukem NOBETTER(); 346 1.3 lukem else { 347 1.3 lukem cheat = 0; 348 1.3 lukem Player.p_gold -= cost; 349 1.3 lukem if (drandom() < 0.02) 350 1.3 lukem dishonest = TRUE; 351 1.3 lukem else 352 1.3 lukem Player.p_quksilver = numitems; 353 1.3 lukem } 354 1.3 lukem break; 355 1.3 lukem 356 1.3 lukem case '7': 357 1.3 lukem if (Player.p_blessing) { 358 1.3 lukem addstr("You already have a blessing."); 359 1.3 lukem break; 360 1.3 lukem } 361 1.3 lukem printw("A blessing requires a %.0f gp donation. Still want one ? ", blessingcost); 362 1.3 lukem ch = getanswer("NY", FALSE); 363 1.3 lukem 364 1.4 veego if (ch == 'Y') { 365 1.3 lukem if (Player.p_gold < blessingcost) 366 1.3 lukem ++cheat; 367 1.3 lukem else { 368 1.3 lukem cheat = 0; 369 1.3 lukem Player.p_gold -= blessingcost; 370 1.3 lukem if (drandom() < 0.02) 371 1.3 lukem dishonest = TRUE; 372 1.3 lukem else 373 1.3 lukem Player.p_blessing = TRUE; 374 1.3 lukem } 375 1.4 veego } 376 1.3 lukem break; 377 1.1 jtc } 378 1.3 lukem break; 379 1.1 jtc 380 1.3 lukem case 'S': /* sell gems */ 381 1.3 lukem mvprintw(15, 0, "A gem is worth %.0f gp. How many do you want to sell (%.0f max) ? ", 382 1.3 lukem (double) N_GEMVALUE, Player.p_gems); 383 1.3 lukem numitems = floor(infloat()); 384 1.1 jtc 385 1.3 lukem if (numitems > Player.p_gems || numitems < 0) 386 1.1 jtc ++cheat; 387 1.3 lukem else { 388 1.1 jtc cheat = 0; 389 1.3 lukem Player.p_gems -= numitems; 390 1.3 lukem Player.p_gold += numitems * N_GEMVALUE; 391 1.1 jtc } 392 1.3 lukem } 393 1.1 jtc 394 1.3 lukem if (cheat == 1) 395 1.3 lukem mvaddstr(17, 0, "Come on, merchants aren't stupid. Stop cheating.\n"); 396 1.1 jtc else 397 1.3 lukem if (cheat == 2) { 398 1.3 lukem mvaddstr(17, 0, "You had your chance. This merchant happens to be\n"); 399 1.3 lukem printw("a %.0f level magic user, and you made %s mad!\n", 400 1.3 lukem ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her"); 401 1.3 lukem altercoordinates(0.0, 0.0, A_FAR); 402 1.3 lukem Player.p_energy /= 2.0; 403 1.3 lukem ++Player.p_sin; 404 1.3 lukem more(23); 405 1.3 lukem return; 406 1.3 lukem } else 407 1.3 lukem if (dishonest) { 408 1.3 lukem mvaddstr(17, 0, "The merchant stole your money!"); 409 1.3 lukem refresh(); 410 1.3 lukem altercoordinates(Player.p_x - Player.p_x / 10.0, 411 1.3 lukem Player.p_y - Player.p_y / 10.0, A_SPECIFIC); 412 1.3 lukem sleep(2); 413 1.3 lukem return; 414 1.3 lukem } 415 1.1 jtc } 416 1.1 jtc } 417 1.1 jtc 418 1.3 lukem void 419 1.16 dholland displaystats(void) 420 1.1 jtc { 421 1.3 lukem mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE)); 422 1.3 lukem mvprintw(1, 0, "Level :%7.0f Energy :%9.0f(%9.0f) Mana :%9.0f Users:%3d\n", 423 1.3 lukem Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield, 424 1.3 lukem Player.p_mana, Users); 425 1.3 lukem mvprintw(2, 0, "Quick :%3.0f(%3.0f) Strength:%9.0f(%9.0f) Gold :%9.0f %s\n", 426 1.3 lukem Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might, 427 1.3 lukem Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player)); 428 1.3 lukem } 429 1.1 jtc 430 1.3 lukem void 431 1.16 dholland allstatslist(void) 432 1.1 jtc { 433 1.5 jsm static const char *const flags[] = /* to print value of some bools */ 434 1.3 lukem { 435 1.3 lukem "False", 436 1.3 lukem " True" 437 1.3 lukem }; 438 1.3 lukem 439 1.3 lukem mvprintw(8, 0, "Type: %s\n", descrtype(&Player, FALSE)); 440 1.1 jtc 441 1.3 lukem mvprintw(10, 0, "Experience: %9.0f", Player.p_experience); 442 1.3 lukem mvprintw(11, 0, "Brains : %9.0f", Player.p_brains); 443 1.3 lukem mvprintw(12, 0, "Magic Lvl : %9.0f", Player.p_magiclvl); 444 1.3 lukem mvprintw(13, 0, "Sin : %9.5f", Player.p_sin); 445 1.3 lukem mvprintw(14, 0, "Poison : %9.5f", Player.p_poison); 446 1.3 lukem mvprintw(15, 0, "Gems : %9.0f", Player.p_gems); 447 1.7 jdc mvprintw(16, 0, "Age : %9ld", Player.p_age); 448 1.3 lukem mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater); 449 1.3 lukem mvprintw(11, 40, "Amulets : %9d", Player.p_amulets); 450 1.3 lukem mvprintw(12, 40, "Charms : %9d", Player.p_charms); 451 1.3 lukem mvprintw(13, 40, "Crowns : %9d", Player.p_crowns); 452 1.3 lukem mvprintw(14, 40, "Shield : %9.0f", Player.p_shield); 453 1.3 lukem mvprintw(15, 40, "Sword : %9.0f", Player.p_sword); 454 1.3 lukem mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver); 455 1.3 lukem 456 1.3 lukem mvprintw(18, 0, "Blessing: %s Ring: %s Virgin: %s Palantir: %s", 457 1.3 lukem flags[(int)Player.p_blessing], 458 1.3 lukem flags[Player.p_ring.ring_type != R_NONE], 459 1.3 lukem flags[(int)Player.p_virgin], 460 1.3 lukem flags[(int)Player.p_palantir]); 461 1.3 lukem } 462 1.3 lukem 463 1.5 jsm const char * 464 1.16 dholland descrtype(struct player *playerp, phbool shortflag) 465 1.1 jtc { 466 1.24 andvar int type; /* for calculating result subscript */ 467 1.5 jsm static const char *const results[] =/* description table */ 468 1.3 lukem { 469 1.3 lukem " Magic User", " MU", 470 1.3 lukem " Fighter", " F ", 471 1.3 lukem " Elf", " E ", 472 1.3 lukem " Dwarf", " D ", 473 1.3 lukem " Halfling", " H ", 474 1.3 lukem " Experimento", " EX", 475 1.3 lukem " Super", " S ", 476 1.3 lukem " King", " K ", 477 1.3 lukem " Council of Wise", " CW", 478 1.3 lukem " Ex-Valar", " EV", 479 1.3 lukem " Valar", " V ", 480 1.3 lukem " ? ", " ? " 481 1.3 lukem }; 482 1.1 jtc 483 1.3 lukem type = playerp->p_type; 484 1.1 jtc 485 1.3 lukem switch (playerp->p_specialtype) { 486 1.1 jtc case SC_NONE: 487 1.3 lukem type = playerp->p_type; 488 1.3 lukem break; 489 1.1 jtc 490 1.1 jtc case SC_KING: 491 1.3 lukem type = 7; 492 1.3 lukem break; 493 1.1 jtc 494 1.1 jtc case SC_COUNCIL: 495 1.3 lukem type = 8; 496 1.3 lukem break; 497 1.1 jtc 498 1.1 jtc case SC_EXVALAR: 499 1.3 lukem type = 9; 500 1.3 lukem break; 501 1.1 jtc 502 1.1 jtc case SC_VALAR: 503 1.3 lukem type = 10; 504 1.3 lukem break; 505 1.1 jtc } 506 1.1 jtc 507 1.3 lukem type *= 2; /* calculate offset */ 508 1.1 jtc 509 1.3 lukem if (type > 20) 510 1.3 lukem /* error */ 511 1.3 lukem type = 22; 512 1.3 lukem 513 1.3 lukem if (shortflag) 514 1.3 lukem /* use short descriptions */ 515 1.3 lukem ++type; 516 1.3 lukem 517 1.3 lukem if (playerp->p_crowns > 0) { 518 1.3 lukem strcpy(Databuf, results[type]); 519 1.3 lukem Databuf[0] = '*'; 520 1.3 lukem return (Databuf); 521 1.3 lukem } else 522 1.3 lukem return (results[type]); 523 1.1 jtc } 524 1.1 jtc 525 1.1 jtc long 526 1.16 dholland findname(const char *name, struct player *playerp) 527 1.1 jtc { 528 1.3 lukem long loc = 0; /* location in the file */ 529 1.1 jtc 530 1.6 jsm fseek(Playersfp, 0L, SEEK_SET); 531 1.3 lukem while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 532 1.3 lukem if (strcmp(playerp->p_name, name) == 0) { 533 1.3 lukem if (playerp->p_status != S_NOTUSED || Wizard) 534 1.3 lukem /* found it */ 535 1.3 lukem return (loc); 536 1.3 lukem } 537 1.3 lukem loc += SZ_PLAYERSTRUCT; 538 1.1 jtc } 539 1.1 jtc 540 1.3 lukem return (-1); 541 1.1 jtc } 542 1.1 jtc 543 1.1 jtc long 544 1.16 dholland allocrecord(void) 545 1.1 jtc { 546 1.3 lukem long loc = 0L; /* location in file */ 547 1.1 jtc 548 1.6 jsm fseek(Playersfp, 0L, SEEK_SET); 549 1.3 lukem while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 550 1.3 lukem if (Other.p_status == S_NOTUSED) 551 1.3 lukem /* found an empty record */ 552 1.3 lukem return (loc); 553 1.3 lukem else 554 1.3 lukem loc += SZ_PLAYERSTRUCT; 555 1.1 jtc } 556 1.1 jtc 557 1.3 lukem /* make a new record */ 558 1.3 lukem initplayer(&Other); 559 1.3 lukem Player.p_status = S_OFF; 560 1.3 lukem writerecord(&Other, loc); 561 1.1 jtc 562 1.3 lukem return (loc); 563 1.3 lukem } 564 1.3 lukem 565 1.3 lukem void 566 1.16 dholland freerecord(struct player *playerp, long loc) 567 1.1 jtc { 568 1.3 lukem playerp->p_name[0] = CH_MARKDELETE; 569 1.3 lukem playerp->p_status = S_NOTUSED; 570 1.3 lukem writerecord(playerp, loc); 571 1.3 lukem } 572 1.1 jtc 573 1.3 lukem void 574 1.16 dholland leavegame(void) 575 1.1 jtc { 576 1.1 jtc 577 1.3 lukem if (Player.p_level < 1.0) 578 1.3 lukem /* delete character */ 579 1.3 lukem freerecord(&Player, Fileloc); 580 1.3 lukem else { 581 1.3 lukem Player.p_status = S_OFF; 582 1.3 lukem writerecord(&Player, Fileloc); 583 1.1 jtc } 584 1.1 jtc 585 1.3 lukem cleanup(TRUE); 586 1.3 lukem /* NOTREACHED */ 587 1.1 jtc } 588 1.1 jtc 589 1.3 lukem void 590 1.16 dholland death(const char *how) 591 1.1 jtc { 592 1.3 lukem FILE *fp; /* for updating various files */ 593 1.3 lukem int ch; /* input */ 594 1.5 jsm static const char *const deathmesg[] = 595 1.1 jtc /* add more messages here, if desired */ 596 1.1 jtc { 597 1.3 lukem "You have been wounded beyond repair. ", 598 1.3 lukem "You have been disemboweled. ", 599 1.3 lukem "You've been mashed, mauled, and spit upon. (You're dead.)\n", 600 1.3 lukem "You died! ", 601 1.3 lukem "You're a complete failure -- you've died!!\n", 602 1.3 lukem "You have been dealt a fatal blow! " 603 1.1 jtc }; 604 1.1 jtc 605 1.3 lukem clear(); 606 1.1 jtc 607 1.3 lukem if (strcmp(how, "Stupidity") != 0) { 608 1.3 lukem if (Player.p_level > 9999.0) 609 1.3 lukem /* old age */ 610 1.3 lukem addstr("Characters must be retired upon reaching level 10000. Sorry."); 611 1.3 lukem else 612 1.3 lukem if (Player.p_lives > 0) 613 1.3 lukem /* extra lives */ 614 1.3 lukem { 615 1.3 lukem addstr("You should be more cautious. You've been killed.\n"); 616 1.3 lukem printw("You only have %d more chance(s).\n", --Player.p_lives); 617 1.3 lukem more(3); 618 1.3 lukem Player.p_energy = Player.p_maxenergy; 619 1.3 lukem return; 620 1.3 lukem } else 621 1.3 lukem if (Player.p_specialtype == SC_VALAR) { 622 1.3 lukem addstr("You had your chances, but Valar aren't totally\n"); 623 1.3 lukem addstr("immortal. You are now left to wither and die . . .\n"); 624 1.3 lukem more(3); 625 1.3 lukem Player.p_brains = Player.p_level / 25.0; 626 1.3 lukem Player.p_energy = Player.p_maxenergy /= 5.0; 627 1.3 lukem Player.p_quksilver = Player.p_sword = 0.0; 628 1.3 lukem Player.p_specialtype = SC_COUNCIL; 629 1.3 lukem return; 630 1.3 lukem } else 631 1.3 lukem if (Player.p_ring.ring_inuse && 632 1.3 lukem (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG)) 633 1.3 lukem /* good ring in use - saved 634 1.3 lukem * from death */ 635 1.3 lukem { 636 1.3 lukem mvaddstr(4, 0, "Your ring saved you from death!\n"); 637 1.3 lukem refresh(); 638 1.3 lukem Player.p_ring.ring_type = R_NONE; 639 1.3 lukem Player.p_energy = Player.p_maxenergy / 12.0 + 1.0; 640 1.3 lukem if (Player.p_crowns > 0) 641 1.3 lukem --Player.p_crowns; 642 1.3 lukem return; 643 1.3 lukem } else 644 1.3 lukem if (Player.p_ring.ring_type == R_BAD 645 1.3 lukem || Player.p_ring.ring_type == R_SPOILED) 646 1.3 lukem /* bad ring in 647 1.3 lukem * possession; name 648 1.3 lukem * idiot after player */ 649 1.3 lukem { 650 1.3 lukem mvaddstr(4, 0, 651 1.3 lukem "Your ring has taken control of you and turned you into a monster!\n"); 652 1.6 jsm fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, SEEK_SET); 653 1.3 lukem fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp); 654 1.3 lukem strcpy(Curmonster.m_name, Player.p_name); 655 1.6 jsm fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, SEEK_SET); 656 1.3 lukem fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp); 657 1.3 lukem fflush(Monstfp); 658 1.3 lukem } 659 1.3 lukem } 660 1.3 lukem enterscore(); /* update score board */ 661 1.3 lukem 662 1.3 lukem /* put info in last dead file */ 663 1.3 lukem fp = fopen(_PATH_LASTDEAD, "w"); 664 1.3 lukem fprintf(fp, "%s (%s, run by %s, level %.0f, killed by %s)", 665 1.3 lukem Player.p_name, descrtype(&Player, TRUE), 666 1.3 lukem Player.p_login, Player.p_level, how); 667 1.3 lukem fclose(fp); 668 1.1 jtc 669 1.3 lukem /* let other players know */ 670 1.3 lukem fp = fopen(_PATH_MESS, "w"); 671 1.3 lukem fprintf(fp, "%s was killed by %s.", Player.p_name, how); 672 1.3 lukem fclose(fp); 673 1.1 jtc 674 1.3 lukem freerecord(&Player, Fileloc); 675 1.1 jtc 676 1.3 lukem clear(); 677 1.3 lukem move(10, 0); 678 1.3 lukem addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]); 679 1.3 lukem addstr("Care to give it another try ? "); 680 1.3 lukem ch = getanswer("NY", FALSE); 681 1.3 lukem 682 1.3 lukem if (ch == 'Y') { 683 1.3 lukem cleanup(FALSE); 684 1.3 lukem execl(_PATH_GAMEPROG, "phantasia", "-s", 685 1.21 plunky (Wizard ? "-S" : (char *) NULL), (char *) NULL); 686 1.3 lukem exit(0); 687 1.3 lukem /* NOTREACHED */ 688 1.1 jtc } 689 1.3 lukem cleanup(TRUE); 690 1.3 lukem /* NOTREACHED */ 691 1.1 jtc } 692 1.1 jtc 693 1.3 lukem void 694 1.16 dholland writerecord(struct player *playerp, long place) 695 1.1 jtc { 696 1.6 jsm fseek(Playersfp, place, SEEK_SET); 697 1.3 lukem fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp); 698 1.3 lukem fflush(Playersfp); 699 1.3 lukem } 700 1.1 jtc 701 1.18 dholland static double 702 1.16 dholland explevel(double experience) 703 1.1 jtc { 704 1.3 lukem if (experience < 1.1e7) 705 1.3 lukem return (floor(pow((experience / 1000.0), 0.4875))); 706 1.3 lukem else 707 1.3 lukem return (floor(pow((experience / 1250.0), 0.4865))); 708 1.3 lukem } 709 1.1 jtc 710 1.3 lukem void 711 1.16 dholland truncstring(char *string) 712 1.1 jtc { 713 1.3 lukem int length; /* length of string */ 714 1.1 jtc 715 1.3 lukem length = strlen(string); 716 1.3 lukem while (string[--length] == ' ') 717 1.3 lukem string[length] = '\0'; 718 1.3 lukem } 719 1.1 jtc 720 1.3 lukem void 721 1.16 dholland altercoordinates(double xnew, double ynew, int operation) 722 1.3 lukem { 723 1.3 lukem switch (operation) { 724 1.3 lukem case A_FORCED: /* move with no checks */ 725 1.3 lukem break; 726 1.3 lukem 727 1.3 lukem case A_NEAR: /* pick random coordinates near */ 728 1.3 lukem xnew = Player.p_x + ROLL(1.0, 5.0); 729 1.3 lukem ynew = Player.p_y - ROLL(1.0, 5.0); 730 1.3 lukem /* fall through for check */ 731 1.1 jtc 732 1.22 mrg /* FALLTHROUGH */ 733 1.1 jtc case A_SPECIFIC: /* just move player */ 734 1.3 lukem if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND) 735 1.3 lukem /* 736 1.3 lukem * cannot move back from point of no return 737 1.3 lukem * pick the largest coordinate to remain unchanged 738 1.3 lukem */ 739 1.1 jtc { 740 1.3 lukem if (fabs(xnew) > fabs(ynew)) 741 1.3 lukem xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND); 742 1.3 lukem else 743 1.3 lukem ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND); 744 1.1 jtc } 745 1.3 lukem break; 746 1.1 jtc 747 1.3 lukem case A_FAR: /* pick random coordinates far */ 748 1.3 lukem xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle); 749 1.3 lukem ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle); 750 1.3 lukem break; 751 1.1 jtc } 752 1.1 jtc 753 1.3 lukem /* now set location flags and adjust coordinates */ 754 1.3 lukem Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew)); 755 1.3 lukem 756 1.3 lukem /* set up flags based upon location */ 757 1.3 lukem Throne = Marsh = Beyond = FALSE; 758 1.3 lukem 759 1.3 lukem if (Player.p_x == 0.0 && Player.p_y == 0.0) 760 1.3 lukem Throne = TRUE; 761 1.3 lukem else 762 1.3 lukem if (Circle < 35 && Circle >= 20) 763 1.3 lukem Marsh = TRUE; 764 1.3 lukem else 765 1.3 lukem if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND) 766 1.3 lukem Beyond = TRUE; 767 1.3 lukem 768 1.3 lukem Changed = TRUE; 769 1.3 lukem } 770 1.3 lukem 771 1.3 lukem void 772 1.16 dholland readrecord(struct player *playerp, long loc) 773 1.1 jtc { 774 1.6 jsm fseek(Playersfp, loc, SEEK_SET); 775 1.3 lukem fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp); 776 1.1 jtc } 777 1.1 jtc 778 1.3 lukem void 779 1.16 dholland adjuststats(void) 780 1.1 jtc { 781 1.3 lukem double dtemp; /* for temporary calculations */ 782 1.1 jtc 783 1.3 lukem if (explevel(Player.p_experience) > Player.p_level) 784 1.3 lukem /* move one or more levels */ 785 1.1 jtc { 786 1.3 lukem movelevel(); 787 1.3 lukem if (Player.p_level > 5.0) 788 1.3 lukem Timeout = TRUE; 789 1.3 lukem } 790 1.3 lukem if (Player.p_specialtype == SC_VALAR) 791 1.3 lukem /* valar */ 792 1.3 lukem Circle = Player.p_level / 5.0; 793 1.3 lukem 794 1.3 lukem /* calculate effective quickness */ 795 1.3 lukem dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote 796 1.8 simonb - Player.p_level; 797 1.3 lukem dtemp = MAX(0.0, dtemp);/* gold slows player down */ 798 1.3 lukem Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp; 799 1.3 lukem 800 1.3 lukem /* calculate effective strength */ 801 1.3 lukem if (Player.p_poison > 0.0) 802 1.3 lukem /* poison makes player weaker */ 803 1.3 lukem { 804 1.3 lukem dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0; 805 1.3 lukem dtemp = MAX(0.1, dtemp); 806 1.3 lukem } else 807 1.3 lukem dtemp = 1.0; 808 1.3 lukem Player.p_might = dtemp * Player.p_strength + Player.p_sword; 809 1.3 lukem 810 1.3 lukem /* insure that important things are within limits */ 811 1.3 lukem Player.p_quksilver = MIN(99.0, Player.p_quksilver); 812 1.3 lukem Player.p_mana = MIN(Player.p_mana, 813 1.3 lukem Player.p_level * Statptr->c_maxmana + 1000.0); 814 1.3 lukem Player.p_brains = MIN(Player.p_brains, 815 1.3 lukem Player.p_level * Statptr->c_maxbrains + 200.0); 816 1.3 lukem Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0); 817 1.3 lukem 818 1.3 lukem /* 819 1.3 lukem * some implementations have problems with floating point compare 820 1.3 lukem * we work around it with this stuff 821 1.3 lukem */ 822 1.3 lukem Player.p_gold = floor(Player.p_gold) + 0.1; 823 1.3 lukem Player.p_gems = floor(Player.p_gems) + 0.1; 824 1.3 lukem Player.p_mana = floor(Player.p_mana) + 0.1; 825 1.3 lukem 826 1.3 lukem if (Player.p_ring.ring_type != R_NONE) 827 1.3 lukem /* do ring things */ 828 1.3 lukem { 829 1.3 lukem /* rest to max */ 830 1.3 lukem Player.p_energy = Player.p_maxenergy + Player.p_shield; 831 1.3 lukem 832 1.3 lukem if (Player.p_ring.ring_duration <= 0) 833 1.3 lukem /* clean up expired rings */ 834 1.3 lukem switch (Player.p_ring.ring_type) { 835 1.3 lukem case R_BAD: /* ring drives player crazy */ 836 1.3 lukem Player.p_ring.ring_type = R_SPOILED; 837 1.3 lukem Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0); 838 1.3 lukem break; 839 1.1 jtc 840 1.3 lukem case R_NAZREG: /* ring disappears */ 841 1.3 lukem Player.p_ring.ring_type = R_NONE; 842 1.3 lukem break; 843 1.1 jtc 844 1.3 lukem case R_SPOILED: /* ring kills player */ 845 1.3 lukem death("A cursed ring"); 846 1.3 lukem break; 847 1.1 jtc 848 1.3 lukem case R_DLREG: /* this ring doesn't expire */ 849 1.3 lukem Player.p_ring.ring_duration = 0; 850 1.3 lukem break; 851 1.3 lukem } 852 1.1 jtc } 853 1.3 lukem if (Player.p_age / N_AGE > Player.p_degenerated) 854 1.3 lukem /* age player slightly */ 855 1.1 jtc { 856 1.3 lukem ++Player.p_degenerated; 857 1.3 lukem if (Player.p_quickness > 23.0) 858 1.3 lukem Player.p_quickness *= 0.99; 859 1.3 lukem Player.p_strength *= 0.97; 860 1.3 lukem Player.p_brains *= 0.95; 861 1.3 lukem Player.p_magiclvl *= 0.97; 862 1.3 lukem Player.p_maxenergy *= 0.95; 863 1.3 lukem Player.p_quksilver *= 0.95; 864 1.3 lukem Player.p_sword *= 0.93; 865 1.3 lukem Player.p_shield *= 0.93; 866 1.1 jtc } 867 1.1 jtc } 868 1.1 jtc 869 1.3 lukem void 870 1.16 dholland initplayer(struct player *playerp) 871 1.1 jtc { 872 1.3 lukem playerp->p_experience = 873 1.3 lukem playerp->p_level = 874 1.3 lukem playerp->p_strength = 875 1.3 lukem playerp->p_sword = 876 1.3 lukem playerp->p_might = 877 1.3 lukem playerp->p_energy = 878 1.3 lukem playerp->p_maxenergy = 879 1.3 lukem playerp->p_shield = 880 1.3 lukem playerp->p_quickness = 881 1.3 lukem playerp->p_quksilver = 882 1.3 lukem playerp->p_speed = 883 1.3 lukem playerp->p_magiclvl = 884 1.3 lukem playerp->p_mana = 885 1.3 lukem playerp->p_brains = 886 1.3 lukem playerp->p_poison = 887 1.3 lukem playerp->p_gems = 888 1.3 lukem playerp->p_sin = 889 1.3 lukem playerp->p_1scratch = 890 1.3 lukem playerp->p_2scratch = 0.0; 891 1.3 lukem 892 1.3 lukem playerp->p_gold = ROLL(50.0, 75.0) + 0.1; /* give some gold */ 893 1.3 lukem 894 1.3 lukem playerp->p_x = ROLL(-125.0, 251.0); 895 1.3 lukem playerp->p_y = ROLL(-125.0, 251.0); /* give random x, y */ 896 1.3 lukem 897 1.3 lukem /* clear ring */ 898 1.3 lukem playerp->p_ring.ring_type = R_NONE; 899 1.3 lukem playerp->p_ring.ring_duration = 0; 900 1.3 lukem playerp->p_ring.ring_inuse = FALSE; 901 1.3 lukem 902 1.3 lukem playerp->p_age = 0L; 903 1.3 lukem 904 1.3 lukem playerp->p_degenerated = 1; /* don't degenerate initially */ 905 1.3 lukem 906 1.3 lukem playerp->p_type = C_FIGHTER; /* default */ 907 1.3 lukem playerp->p_specialtype = SC_NONE; 908 1.3 lukem playerp->p_lives = 909 1.3 lukem playerp->p_crowns = 910 1.3 lukem playerp->p_charms = 911 1.3 lukem playerp->p_amulets = 912 1.3 lukem playerp->p_holywater = 913 1.3 lukem playerp->p_lastused = 0; 914 1.3 lukem playerp->p_status = S_NOTUSED; 915 1.3 lukem playerp->p_tampered = T_OFF; 916 1.3 lukem playerp->p_istat = I_OFF; 917 1.3 lukem 918 1.3 lukem playerp->p_palantir = 919 1.3 lukem playerp->p_blessing = 920 1.3 lukem playerp->p_virgin = 921 1.3 lukem playerp->p_blindness = FALSE; 922 1.3 lukem 923 1.3 lukem playerp->p_name[0] = 924 1.3 lukem playerp->p_password[0] = 925 1.3 lukem playerp->p_login[0] = '\0'; 926 1.3 lukem } 927 1.1 jtc 928 1.3 lukem void 929 1.16 dholland readmessage(void) 930 1.1 jtc { 931 1.3 lukem move(3, 0); 932 1.3 lukem clrtoeol(); 933 1.6 jsm fseek(Messagefp, 0L, SEEK_SET); 934 1.3 lukem if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL) 935 1.3 lukem addstr(Databuf); 936 1.3 lukem } 937 1.1 jtc 938 1.3 lukem void 939 1.16 dholland error(const char *whichfile) 940 1.1 jtc { 941 1.9 wiz int (*funcp)(const char *,...); 942 1.1 jtc 943 1.3 lukem if (Windows) { 944 1.3 lukem funcp = printw; 945 1.3 lukem clear(); 946 1.3 lukem } else 947 1.3 lukem funcp = printf; 948 1.3 lukem 949 1.10 jsm (*funcp) ("An unrecoverable error has occurred reading %s. (%s)\n", whichfile, strerror(errno)); 950 1.3 lukem (*funcp) ("Please run 'setup' to determine the problem.\n"); 951 1.3 lukem cleanup(TRUE); 952 1.3 lukem /* NOTREACHED */ 953 1.3 lukem } 954 1.1 jtc 955 1.1 jtc double 956 1.16 dholland distance(double x_1, double x_2, double y_1, double y_2) 957 1.1 jtc { 958 1.3 lukem double deltax, deltay; 959 1.1 jtc 960 1.15 dholland deltax = x_1 - x_2; 961 1.15 dholland deltay = y_1 - y_2; 962 1.3 lukem return (sqrt(deltax * deltax + deltay * deltay)); 963 1.3 lukem } 964 1.1 jtc 965 1.3 lukem void 966 1.16 dholland ill_sig(int whichsig) 967 1.1 jtc { 968 1.3 lukem clear(); 969 1.3 lukem if (!(whichsig == SIGINT || whichsig == SIGQUIT)) 970 1.3 lukem printw("Error: caught signal # %d.\n", whichsig); 971 1.3 lukem cleanup(TRUE); 972 1.3 lukem /* NOTREACHED */ 973 1.3 lukem } 974 1.1 jtc 975 1.5 jsm const char * 976 1.16 dholland descrstatus(struct player *playerp) 977 1.1 jtc { 978 1.3 lukem switch (playerp->p_status) { 979 1.1 jtc case S_PLAYING: 980 1.3 lukem if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield)) 981 1.3 lukem return ("Low Energy"); 982 1.3 lukem else 983 1.3 lukem if (playerp->p_blindness) 984 1.3 lukem return ("Blind"); 985 1.3 lukem else 986 1.3 lukem return ("In game"); 987 1.1 jtc 988 1.1 jtc case S_CLOAKED: 989 1.3 lukem return ("Cloaked"); 990 1.1 jtc 991 1.1 jtc case S_INBATTLE: 992 1.3 lukem return ("In Battle"); 993 1.1 jtc 994 1.1 jtc case S_MONSTER: 995 1.3 lukem return ("Encounter"); 996 1.1 jtc 997 1.1 jtc case S_TRADING: 998 1.3 lukem return ("Trading"); 999 1.1 jtc 1000 1.1 jtc case S_OFF: 1001 1.3 lukem return ("Off"); 1002 1.1 jtc 1003 1.1 jtc case S_HUNGUP: 1004 1.3 lukem return ("Hung up"); 1005 1.1 jtc 1006 1.1 jtc default: 1007 1.3 lukem return (""); 1008 1.1 jtc } 1009 1.1 jtc } 1010 1.1 jtc 1011 1.1 jtc double 1012 1.16 dholland drandom(void) 1013 1.1 jtc { 1014 1.3 lukem if (sizeof(int) != 2) 1015 1.3 lukem /* use only low bits */ 1016 1.3 lukem return ((double) (random() & 0x7fff) / 32768.0); 1017 1.3 lukem else 1018 1.3 lukem return ((double) random() / 32768.0); 1019 1.3 lukem } 1020 1.1 jtc 1021 1.3 lukem void 1022 1.16 dholland collecttaxes(double gold, double gems) 1023 1.1 jtc { 1024 1.3 lukem FILE *fp; /* to update Goldfile */ 1025 1.3 lukem double dtemp; /* for temporary calculations */ 1026 1.3 lukem double taxes; /* tax liability */ 1027 1.3 lukem 1028 1.3 lukem /* add to cache */ 1029 1.3 lukem Player.p_gold += gold; 1030 1.3 lukem Player.p_gems += gems; 1031 1.1 jtc 1032 1.3 lukem /* calculate tax liability */ 1033 1.3 lukem taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold); 1034 1.1 jtc 1035 1.3 lukem if (Player.p_gold < taxes) 1036 1.3 lukem /* not enough gold to pay taxes, must convert some gems to 1037 1.3 lukem * gold */ 1038 1.1 jtc { 1039 1.3 lukem dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to 1040 1.3 lukem * convert */ 1041 1.1 jtc 1042 1.3 lukem if (Player.p_gems >= dtemp) 1043 1.3 lukem /* player has enough to convert */ 1044 1.3 lukem { 1045 1.3 lukem Player.p_gems -= dtemp; 1046 1.3 lukem Player.p_gold += dtemp * N_GEMVALUE; 1047 1.3 lukem } else 1048 1.3 lukem /* take everything; this should never happen */ 1049 1.3 lukem { 1050 1.3 lukem Player.p_gold += Player.p_gems * N_GEMVALUE; 1051 1.3 lukem Player.p_gems = 0.0; 1052 1.3 lukem taxes = Player.p_gold; 1053 1.3 lukem } 1054 1.1 jtc } 1055 1.3 lukem Player.p_gold -= taxes; 1056 1.1 jtc 1057 1.3 lukem if ((fp = fopen(_PATH_GOLD, "r+")) != NULL) 1058 1.3 lukem /* update taxes */ 1059 1.1 jtc { 1060 1.3 lukem dtemp = 0.0; 1061 1.3 lukem fread((char *) &dtemp, sizeof(double), 1, fp); 1062 1.3 lukem dtemp += floor(taxes); 1063 1.6 jsm fseek(fp, 0L, SEEK_SET); 1064 1.3 lukem fwrite((char *) &dtemp, sizeof(double), 1, fp); 1065 1.3 lukem fclose(fp); 1066 1.1 jtc } 1067 1.1 jtc } 1068