interplayer.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /* $NetBSD: interplayer.c,v 1.9 2005/02/15 12:58:21 jsm Exp $ */
  2. /*
  3. * interplayer.c - player to player routines for Phantasia
  4. */
  5. #include "include.h"
  6. #undef bool
  7. #include <curses.h>
  8. void
  9. checkbattle()
  10. {
  11. long foeloc = 0L; /* location in file of person to fight */
  12. Users = 0;
  13. fseek(Playersfp, 0L, SEEK_SET);
  14. while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
  15. if (Other.p_status != S_OFF
  16. && Other.p_status != S_NOTUSED
  17. && Other.p_status != S_HUNGUP
  18. && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
  19. /* player is on and not a cloaked valar */
  20. {
  21. ++Users;
  22. if (Player.p_x == Other.p_x
  23. && Player.p_y == Other.p_y
  24. /* same coordinates */
  25. && foeloc != Fileloc
  26. /* not self */
  27. && Player.p_status == S_PLAYING
  28. && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
  29. /* both are playing */
  30. && Other.p_specialtype != SC_VALAR
  31. && Player.p_specialtype != SC_VALAR)
  32. /* neither is valar */
  33. {
  34. battleplayer(foeloc);
  35. return;
  36. }
  37. }
  38. foeloc += SZ_PLAYERSTRUCT;
  39. }
  40. }
  41. void
  42. battleplayer(foeplace)
  43. long foeplace;
  44. {
  45. double dtemp; /* for temporary calculations */
  46. double oldhits = 0.0; /* previous damage inflicted by foe */
  47. int loop; /* for timing out */
  48. int ch; /* input */
  49. short oldtampered; /* old value of foe's p_tampered */
  50. Lines = 8;
  51. Luckout = FALSE;
  52. mvaddstr(4, 0, "Preparing for battle!\n");
  53. refresh();
  54. #ifdef SYS5
  55. flushinp();
  56. #endif
  57. /* set up variables, file, etc. */
  58. Player.p_status = S_INBATTLE;
  59. Shield = Player.p_energy;
  60. /* if p_tampered is not 0, someone else may try to change it (king,
  61. * etc.) */
  62. Player.p_tampered = oldtampered = 1;
  63. Player.p_1scratch = 0.0;
  64. Player.p_istat = I_OFF;
  65. readrecord(&Other, foeplace);
  66. if (fabs(Player.p_level - Other.p_level) > 20.0)
  67. /* see if players are greatly mismatched */
  68. {
  69. dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
  70. if (dtemp < -0.5)
  71. /* foe outweighs this one */
  72. Player.p_speed *= 2.0;
  73. }
  74. writerecord(&Player, Fileloc); /* write out all our info */
  75. if (Player.p_blindness)
  76. Enemyname = "someone";
  77. else
  78. Enemyname = Other.p_name;
  79. mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level);
  80. refresh();
  81. for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
  82. /* wait for foe to respond */
  83. {
  84. readrecord(&Other, foeplace);
  85. sleep(1);
  86. }
  87. if (Other.p_status != S_INBATTLE)
  88. /* foe did not respond */
  89. {
  90. mvprintw(5, 0, "%s is not responding.\n", Enemyname);
  91. goto LEAVE;
  92. }
  93. /* else, we are ready to battle */
  94. move(4, 0);
  95. clrtoeol();
  96. /*
  97. * determine who is first master
  98. * if neither player is faster, check level
  99. * if neither level is greater, battle is not allowed
  100. * (this should never happen, but we have to handle it)
  101. */
  102. if (Player.p_speed > Other.p_speed)
  103. Foestrikes = FALSE;
  104. else
  105. if (Other.p_speed > Player.p_speed)
  106. Foestrikes = TRUE;
  107. else
  108. if (Player.p_level > Other.p_level)
  109. Foestrikes = FALSE;
  110. else
  111. if (Other.p_level > Player.p_level)
  112. Foestrikes = TRUE;
  113. else
  114. /* no one is faster */
  115. {
  116. printw("You can't fight %s yet.", Enemyname);
  117. goto LEAVE;
  118. }
  119. for (;;) {
  120. displaystats();
  121. readmessage();
  122. mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */
  123. if (!Foestrikes)
  124. /* take action against foe */
  125. myturn();
  126. else
  127. /* wait for foe to take action */
  128. {
  129. mvaddstr(4, 0, "Waiting...\n");
  130. clrtoeol();
  131. refresh();
  132. for (loop = 0; loop < 20; ++loop)
  133. /* wait for foe to act */
  134. {
  135. readrecord(&Other, foeplace);
  136. if (Other.p_1scratch != oldhits)
  137. /* p_1scratch changes to indicate
  138. * action */
  139. break;
  140. else
  141. /* wait and try again */
  142. {
  143. sleep(1);
  144. addch('.');
  145. refresh();
  146. }
  147. }
  148. if (Other.p_1scratch == oldhits) {
  149. /* timeout */
  150. mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? ");
  151. ch = getanswer("NY", FALSE);
  152. move(22, 0);
  153. clrtobot();
  154. if (ch == 'Y')
  155. continue;
  156. else
  157. break;
  158. } else
  159. /* foe took action */
  160. {
  161. switch (Other.p_istat) {
  162. case I_RAN: /* foe ran away */
  163. mvprintw(Lines++, 0, "%s ran away!", Enemyname);
  164. break;
  165. case I_STUCK: /* foe tried to run, but
  166. * couldn't */
  167. mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
  168. break;
  169. case I_BLEWIT: /* foe tried to luckout, but
  170. * didn't */
  171. mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
  172. break;
  173. default:
  174. dtemp = Other.p_1scratch - oldhits;
  175. mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
  176. Shield -= dtemp;
  177. break;
  178. }
  179. oldhits = Other.p_1scratch; /* keep track of old
  180. * hits */
  181. if (Other.p_tampered != oldtampered)
  182. /* p_tampered changes to relinquish
  183. * turn */
  184. {
  185. oldtampered = Other.p_tampered;
  186. Foestrikes = FALSE;
  187. }
  188. }
  189. }
  190. /* decide what happens next */
  191. refresh();
  192. if (Lines > LINES - 2) {
  193. more(Lines);
  194. move(Lines = 8, 0);
  195. clrtobot();
  196. }
  197. if (Other.p_istat == I_KILLED || Shield < 0.0)
  198. /* we died */
  199. {
  200. Shield = -2.0; /* insure this value is negative */
  201. break;
  202. }
  203. if (Player.p_istat == I_KILLED)
  204. /* we killed foe; award treasre */
  205. {
  206. mvprintw(Lines++, 0, "You killed %s!", Enemyname);
  207. Player.p_experience += Other.p_experience;
  208. Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
  209. Player.p_amulets += Other.p_amulets;
  210. Player.p_charms += Other.p_charms;
  211. collecttaxes(Other.p_gold, Other.p_gems);
  212. Player.p_sword = MAX(Player.p_sword, Other.p_sword);
  213. Player.p_shield = MAX(Player.p_shield, Other.p_shield);
  214. Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
  215. if (Other.p_virgin && !Player.p_virgin) {
  216. mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? ");
  217. if ((ch = getanswer("YN", FALSE)) == 'Y')
  218. Player.p_virgin = TRUE;
  219. else {
  220. ++Player.p_sin;
  221. Player.p_experience += 8000.0;
  222. }
  223. }
  224. sleep(3); /* give other person time to die */
  225. break;
  226. } else
  227. if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
  228. /* either player ran away */
  229. break;
  230. }
  231. LEAVE:
  232. /* clean up things and leave */
  233. writerecord(&Player, Fileloc); /* update a final time */
  234. altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */
  235. Player.p_energy = Shield; /* set energy to actual value */
  236. Player.p_tampered = T_OFF; /* clear p_tampered */
  237. more(Lines); /* pause */
  238. move(4, 0);
  239. clrtobot(); /* clear bottom area of screen */
  240. if (Player.p_energy < 0.0)
  241. /* we are dead */
  242. death("Interterminal battle");
  243. }
  244. void
  245. myturn()
  246. {
  247. double dtemp; /* for temporary calculations */
  248. int ch; /* input */
  249. mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast ");
  250. if (Luckout)
  251. clrtoeol();
  252. else
  253. addstr("4:Luckout ");
  254. ch = inputoption();
  255. move(Lines = 8, 0);
  256. clrtobot();
  257. switch (ch) {
  258. default: /* fight */
  259. dtemp = ROLL(2.0, Player.p_might);
  260. HIT:
  261. mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
  262. Player.p_sin += 0.5;
  263. Player.p_1scratch += dtemp;
  264. Player.p_istat = I_OFF;
  265. break;
  266. case '2': /* run away */
  267. Player.p_1scratch -= 1.0; /* change this to indicate
  268. * action */
  269. if (drandom() > 0.25) {
  270. mvaddstr(Lines++, 0, "You got away!");
  271. Player.p_istat = I_RAN;
  272. } else {
  273. mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
  274. Player.p_istat = I_STUCK;
  275. }
  276. break;
  277. case '3': /* power blast */
  278. dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
  279. Player.p_mana -= dtemp;
  280. dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
  281. mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
  282. goto HIT;
  283. case '4': /* luckout */
  284. if (Luckout || drandom() > 0.1) {
  285. if (Luckout)
  286. mvaddstr(Lines++, 0, "You already tried that!");
  287. else {
  288. mvaddstr(Lines++, 0, "Not this time . . .");
  289. Luckout = TRUE;
  290. }
  291. Player.p_1scratch -= 1.0;
  292. Player.p_istat = I_BLEWIT;
  293. } else {
  294. mvaddstr(Lines++, 0, "You just lucked out!");
  295. Player.p_1scratch = Other.p_energy * 1.1;
  296. }
  297. break;
  298. }
  299. refresh();
  300. Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */
  301. if (Player.p_1scratch > Other.p_energy)
  302. Player.p_istat = I_KILLED;
  303. else
  304. if (drandom() * Player.p_speed < drandom() * Other.p_speed)
  305. /* relinquish control */
  306. {
  307. ++Player.p_tampered;
  308. Foestrikes = TRUE;
  309. }
  310. writerecord(&Player, Fileloc); /* let foe know what we did */
  311. }
  312. void
  313. checktampered()
  314. {
  315. long loc = 0L; /* location in energy void file */
  316. /* first check for energy voids */
  317. fseek(Energyvoidfp, 0L, SEEK_SET);
  318. while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
  319. if (Enrgyvoid.ev_active
  320. && Enrgyvoid.ev_x == Player.p_x
  321. && Enrgyvoid.ev_y == Player.p_y)
  322. /* sitting on one */
  323. {
  324. if (loc > 0L)
  325. /* not the holy grail; inactivate energy void */
  326. {
  327. Enrgyvoid.ev_active = FALSE;
  328. writevoid(&Enrgyvoid, loc);
  329. tampered(T_NRGVOID, 0.0, 0.0);
  330. } else
  331. if (Player.p_status != S_CLOAKED)
  332. /* holy grail */
  333. tampered(T_GRAIL, 0.0, 0.0);
  334. break;
  335. } else
  336. loc += SZ_VOIDSTRUCT;
  337. /* now check for other things */
  338. readrecord(&Other, Fileloc);
  339. if (Other.p_tampered != T_OFF)
  340. tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
  341. }
  342. void
  343. tampered(what, arg1, arg2)
  344. int what;
  345. double arg1;
  346. double arg2;
  347. {
  348. long loc; /* location in file of other players */
  349. Changed = TRUE;
  350. move(4, 0);
  351. Player.p_tampered = T_OFF; /* no longer tampered with */
  352. switch (what) {
  353. case T_NRGVOID:
  354. addstr("You've hit an energy void !\n");
  355. Player.p_mana /= 3.0;
  356. Player.p_energy /= 2.0;
  357. Player.p_gold = floor(Player.p_gold / 1.25) + 0.1;
  358. altercoordinates(0.0, 0.0, A_NEAR);
  359. break;
  360. case T_TRANSPORT:
  361. addstr("The king transported you ! ");
  362. if (Player.p_charms > 0) {
  363. addstr("But your charm saved you. . .\n");
  364. --Player.p_charms;
  365. } else {
  366. altercoordinates(0.0, 0.0, A_FAR);
  367. addch('\n');
  368. }
  369. break;
  370. case T_BESTOW:
  371. printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
  372. Player.p_gold += arg1;
  373. break;
  374. case T_CURSED:
  375. addstr("You've been cursed ! ");
  376. if (Player.p_blessing) {
  377. addstr("But your blessing saved you. . .\n");
  378. Player.p_blessing = FALSE;
  379. } else {
  380. addch('\n');
  381. Player.p_poison += 2.0;
  382. Player.p_energy = 10.0;
  383. Player.p_maxenergy *= 0.95;
  384. Player.p_status = S_PLAYING; /* no longer cloaked */
  385. }
  386. break;
  387. case T_VAPORIZED:
  388. addstr("You have been vaporized!\n");
  389. more(7);
  390. death("Vaporization");
  391. break;
  392. case T_MONSTER:
  393. addstr("The Valar zapped you with a monster!\n");
  394. more(7);
  395. encounter((int) arg1);
  396. return;
  397. case T_BLESSED:
  398. addstr("The Valar has blessed you!\n");
  399. Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
  400. Player.p_mana += 500.0;
  401. Player.p_strength += 0.5;
  402. Player.p_brains += 0.5;
  403. Player.p_magiclvl += 0.5;
  404. Player.p_poison = MIN(0.5, Player.p_poison);
  405. break;
  406. case T_RELOCATE:
  407. addstr("You've been relocated. . .\n");
  408. altercoordinates(arg1, arg2, A_FORCED);
  409. break;
  410. case T_HEAL:
  411. addstr("You've been healed!\n");
  412. Player.p_poison -= 0.25;
  413. Player.p_energy = Player.p_maxenergy + Player.p_shield;
  414. break;
  415. case T_EXVALAR:
  416. addstr("You are no longer Valar!\n");
  417. Player.p_specialtype = SC_COUNCIL;
  418. break;
  419. case T_GRAIL:
  420. addstr("You have found The Holy Grail!!\n");
  421. if (Player.p_specialtype < SC_COUNCIL)
  422. /* must be council of wise to behold grail */
  423. {
  424. addstr("However, you are not experienced enough to behold it.\n");
  425. Player.p_sin *= Player.p_sin;
  426. Player.p_mana += 1000;
  427. } else
  428. if (Player.p_specialtype == SC_VALAR
  429. || Player.p_specialtype == SC_EXVALAR) {
  430. addstr("You have made it to the position of Valar once already.\n");
  431. addstr("The Grail is of no more use to you now.\n");
  432. } else {
  433. addstr("It is now time to see if you are worthy to behold it. . .\n");
  434. refresh();
  435. sleep(4);
  436. if (drandom() / 2.0 < Player.p_sin) {
  437. addstr("You have failed!\n");
  438. Player.p_strength =
  439. Player.p_mana =
  440. Player.p_energy =
  441. Player.p_maxenergy =
  442. Player.p_magiclvl =
  443. Player.p_brains =
  444. Player.p_experience =
  445. Player.p_quickness = 1.0;
  446. altercoordinates(1.0, 1.0, A_FORCED);
  447. Player.p_level = 0.0;
  448. } else {
  449. addstr("You made to position of Valar!\n");
  450. Player.p_specialtype = SC_VALAR;
  451. Player.p_lives = 5;
  452. fseek(Playersfp, 0L, SEEK_SET);
  453. loc = 0L;
  454. while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  455. /* search for existing valar */
  456. if (Other.p_specialtype == SC_VALAR
  457. && Other.p_status != S_NOTUSED)
  458. /* found old valar */
  459. {
  460. Other.p_tampered = T_EXVALAR;
  461. writerecord(&Other, loc);
  462. break;
  463. } else
  464. loc += SZ_PLAYERSTRUCT;
  465. }
  466. }
  467. /* move grail to new location */
  468. Enrgyvoid.ev_active = TRUE;
  469. Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
  470. Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
  471. writevoid(&Enrgyvoid, 0L);
  472. break;
  473. }
  474. refresh();
  475. sleep(2);
  476. }
  477. void
  478. userlist(ingameflag)
  479. phbool ingameflag;
  480. {
  481. int numusers = 0; /* number of users on file */
  482. if (ingameflag && Player.p_blindness) {
  483. mvaddstr(8, 0, "You cannot see anyone.\n");
  484. return;
  485. }
  486. fseek(Playersfp, 0L, SEEK_SET);
  487. mvaddstr(8, 0,
  488. "Name X Y Lvl Type Login Status\n");
  489. while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
  490. if (Other.p_status == S_NOTUSED
  491. /* record is unused */
  492. || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
  493. /* cloaked valar */
  494. {
  495. if (!Wizard)
  496. /* wizard can see everything on file */
  497. continue;
  498. }
  499. ++numusers;
  500. if (ingameflag &&
  501. /* must be playing for the rest of these conditions */
  502. (Player.p_specialtype >= SC_KING
  503. /* kings and higher can see others */
  504. || Other.p_specialtype >= SC_KING
  505. /* kings and higher can be seen by others */
  506. || Circle >= CIRCLE(Other.p_x, Other.p_y)
  507. /* those nearer the origin can be seen */
  508. || Player.p_palantir)
  509. /* palantir enables one to see others */
  510. && (Other.p_status != S_CLOAKED
  511. || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
  512. /* not cloaked; valar can see through cloak with a palantir */
  513. && Other.p_specialtype != SC_VALAR)
  514. /* not a valar */
  515. /* coordinates should be printed */
  516. printw("%-20s %8.0f %8.0f ",
  517. Other.p_name, Other.p_x, Other.p_y);
  518. else
  519. /* cannot see player's coordinates */
  520. printw("%-20s %19.19s ",
  521. Other.p_name, descrlocation(&Other, TRUE));
  522. printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
  523. Other.p_login, descrstatus(&Other));
  524. if ((numusers % (LINES - 10)) == 0) {
  525. more(LINES - 1);
  526. move(9, 0);
  527. clrtobot();
  528. }
  529. }
  530. printw("Total players on file = %d\n", numusers);
  531. refresh();
  532. }
  533. void
  534. throneroom()
  535. {
  536. FILE *fp; /* to clear energy voids */
  537. long loc = 0L; /* location of old king in player file */
  538. if (Player.p_specialtype < SC_KING)
  539. /* not already king -- assumes crown */
  540. {
  541. fseek(Playersfp, 0L, SEEK_SET);
  542. while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  543. if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
  544. /* found old king */
  545. {
  546. if (Other.p_status != S_OFF)
  547. /* old king is playing */
  548. {
  549. mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n");
  550. altercoordinates(0.0, 0.0, A_NEAR);
  551. move(6, 0);
  552. return;
  553. } else
  554. /* old king is not playing - remove
  555. * him/her */
  556. {
  557. Other.p_specialtype = SC_NONE;
  558. if (Other.p_crowns)
  559. --Other.p_crowns;
  560. writerecord(&Other, loc);
  561. break;
  562. }
  563. } else
  564. loc += SZ_PLAYERSTRUCT;
  565. /* make player new king */
  566. Changed = TRUE;
  567. Player.p_specialtype = SC_KING;
  568. mvaddstr(4, 0, "You have become king!\n");
  569. /* let everyone else know */
  570. fp = fopen(_PATH_MESS, "w");
  571. fprintf(fp, "All hail the new king!");
  572. fclose(fp);
  573. /* clear all energy voids; retain location of holy grail */
  574. fseek(Energyvoidfp, 0L, SEEK_SET);
  575. fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
  576. fp = fopen(_PATH_VOID, "w");
  577. fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
  578. fclose(fp);
  579. }
  580. mvaddstr(6, 0, "0:Decree ");
  581. }
  582. void
  583. dotampered()
  584. {
  585. short tamper; /* value for tampering with other players */
  586. const char *option; /* pointer to option description */
  587. double temp1 = 0.0, temp2 = 0.0; /* other tampering values */
  588. int ch; /* input */
  589. long loc; /* location in energy void file */
  590. FILE *fp; /* for opening gold file */
  591. move(6, 0);
  592. clrtoeol();
  593. if (Player.p_specialtype < SC_COUNCIL && !Wizard)
  594. /* king options */
  595. {
  596. addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
  597. ch = getanswer(" ", TRUE);
  598. move(6, 0);
  599. clrtoeol();
  600. move(4, 0);
  601. switch (ch) {
  602. case '1': /* transport someone */
  603. tamper = T_TRANSPORT;
  604. option = "transport";
  605. break;
  606. case '2': /* curse another */
  607. tamper = T_CURSED;
  608. option = "curse";
  609. break;
  610. case '3': /* create energy void */
  611. if ((loc = allocvoid()) > 20L * (long)SZ_VOIDSTRUCT)
  612. /* can only have 20 void active at once */
  613. mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
  614. else {
  615. addstr("Enter the X Y coordinates of void ? ");
  616. getstring(Databuf, SZ_DATABUF);
  617. sscanf(Databuf, "%lf %lf", &temp1, &temp2);
  618. Enrgyvoid.ev_x = floor(temp1);
  619. Enrgyvoid.ev_y = floor(temp2);
  620. Enrgyvoid.ev_active = TRUE;
  621. writevoid(&Enrgyvoid, loc);
  622. mvaddstr(5, 0, "It is done.\n");
  623. }
  624. return;
  625. case '4': /* bestow gold to subject */
  626. tamper = T_BESTOW;
  627. addstr("How much gold to bestow ? ");
  628. temp1 = infloat();
  629. if (temp1 > Player.p_gold || temp1 < 0) {
  630. mvaddstr(5, 0, "You don't have that !\n");
  631. return;
  632. }
  633. /* adjust gold after we are sure it will be given to
  634. * someone */
  635. option = "give gold to";
  636. break;
  637. case '5': /* collect accumulated taxes */
  638. if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
  639. /* collect taxes */
  640. {
  641. fread((char *) &temp1, sizeof(double), 1, fp);
  642. fseek(fp, 0L, SEEK_SET);
  643. /* clear out value */
  644. temp2 = 0.0;
  645. fwrite((char *) &temp2, sizeof(double), 1, fp);
  646. fclose(fp);
  647. }
  648. mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
  649. Player.p_gold += floor(temp1);
  650. return;
  651. default:
  652. return;
  653. }
  654. /* end of king options */
  655. } else
  656. /* council of wise, valar, wizard options */
  657. {
  658. addstr("1:Heal ");
  659. if (Player.p_palantir || Wizard)
  660. addstr("2:Seek Grail ");
  661. if (Player.p_specialtype == SC_VALAR || Wizard)
  662. addstr("3:Throw Monster 4:Relocate 5:Bless ");
  663. if (Wizard)
  664. addstr("6:Vaporize ");
  665. ch = getanswer(" ", TRUE);
  666. if (!Wizard) {
  667. if (ch > '2' && Player.p_specialtype != SC_VALAR) {
  668. ILLCMD();
  669. return;
  670. }
  671. if (Player.p_mana < MM_INTERVENE) {
  672. mvaddstr(5, 0, "No mana left.\n");
  673. return;
  674. } else
  675. Player.p_mana -= MM_INTERVENE;
  676. }
  677. switch (ch) {
  678. case '1': /* heal another */
  679. tamper = T_HEAL;
  680. option = "heal";
  681. break;
  682. case '2': /* seek grail */
  683. if (Player.p_palantir)
  684. /* need a palantir to seek */
  685. {
  686. fseek(Energyvoidfp, 0L, SEEK_SET);
  687. fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
  688. temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
  689. temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */
  690. mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
  691. } else
  692. /* no palantir */
  693. mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
  694. return;
  695. case '3': /* lob monster at someone */
  696. mvaddstr(4, 0, "Which monster [0-99] ? ");
  697. temp1 = infloat();
  698. temp1 = MAX(0.0, MIN(99.0, temp1));
  699. tamper = T_MONSTER;
  700. option = "throw a monster at";
  701. break;
  702. case '4': /* move another player */
  703. mvaddstr(4, 0, "New X Y coordinates ? ");
  704. getstring(Databuf, SZ_DATABUF);
  705. sscanf(Databuf, "%lf %lf", &temp1, &temp2);
  706. tamper = T_RELOCATE;
  707. option = "relocate";
  708. break;
  709. case '5': /* bless a player */
  710. tamper = T_BLESSED;
  711. option = "bless";
  712. break;
  713. case '6': /* kill off a player */
  714. if (Wizard) {
  715. tamper = T_VAPORIZED;
  716. option = "vaporize";
  717. break;
  718. } else
  719. return;
  720. default:
  721. return;
  722. }
  723. /* adjust age after we are sure intervention will be done */
  724. /* end of valar, etc. options */
  725. }
  726. for (;;)
  727. /* prompt for player to affect */
  728. {
  729. mvprintw(4, 0, "Who do you want to %s ? ", option);
  730. getstring(Databuf, SZ_DATABUF);
  731. truncstring(Databuf);
  732. if (Databuf[0] == '\0')
  733. userlist(TRUE);
  734. else
  735. break;
  736. }
  737. if (strcmp(Player.p_name, Databuf) != 0)
  738. /* name other than self */
  739. {
  740. if ((loc = findname(Databuf, &Other)) >= 0L) {
  741. if (Other.p_tampered != T_OFF) {
  742. mvaddstr(5, 0, "That person has something pending already.\n");
  743. return;
  744. } else {
  745. if (tamper == T_RELOCATE
  746. && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
  747. && !Wizard)
  748. mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
  749. else {
  750. if (tamper == T_BESTOW)
  751. Player.p_gold -= floor(temp1);
  752. if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
  753. tamper == T_RELOCATE || tamper == T_BLESSED))
  754. Player.p_age += N_AGE; /* age penalty */
  755. Other.p_tampered = tamper;
  756. Other.p_1scratch = floor(temp1);
  757. Other.p_2scratch = floor(temp2);
  758. writerecord(&Other, loc);
  759. mvaddstr(5, 0, "It is done.\n");
  760. }
  761. return;
  762. }
  763. } else
  764. /* player not found */
  765. mvaddstr(5, 0, "There is no one by that name.\n");
  766. } else
  767. /* self */
  768. mvaddstr(5, 0, "You may not do it to yourself!\n");
  769. }
  770. void
  771. writevoid(vp, loc)
  772. struct energyvoid *vp;
  773. long loc;
  774. {
  775. fseek(Energyvoidfp, loc, SEEK_SET);
  776. fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
  777. fflush(Energyvoidfp);
  778. fseek(Energyvoidfp, 0L, SEEK_SET);
  779. }
  780. long
  781. allocvoid()
  782. {
  783. long loc = 0L; /* location of new energy void */
  784. fseek(Energyvoidfp, 0L, SEEK_SET);
  785. while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
  786. if (Enrgyvoid.ev_active)
  787. loc += SZ_VOIDSTRUCT;
  788. else
  789. break;
  790. return (loc);
  791. }