(linenum→info "unix/slp.c:2238")

bsd-games/2.17/phantasia/interplayer.c

    1: /*      $NetBSD: interplayer.c,v 1.9 2005/02/15 12:58:21 jsm Exp $   */
    2: 
    3: /*
    4:  * interplayer.c - player to player routines for Phantasia
    5:  */
    6: 
    7: #include "include.h"
    8: #undef bool
    9: #include <curses.h>
   10: 
   11: void
   12: checkbattle()
   13: {
   14:         long    foeloc = 0L;   /* location in file of person to fight */
   15: 
   16:         Users = 0;
   17:         fseek(Playersfp, 0L, SEEK_SET);
   18: 
   19:         while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
   20:                 if (Other.p_status != S_OFF
   21:                     && Other.p_status != S_NOTUSED
   22:                     && Other.p_status != S_HUNGUP
   23:                     && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
   24:                         /* player is on and not a cloaked valar */
   25:                 {
   26:                         ++Users;
   27: 
   28:                         if (Player.p_x == Other.p_x
   29:                             && Player.p_y == Other.p_y
   30:                         /* same coordinates */
   31:                             && foeloc != Fileloc
   32:                         /* not self */
   33:                             && Player.p_status == S_PLAYING
   34:                             && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
   35:                         /* both are playing */
   36:                             && Other.p_specialtype != SC_VALAR
   37:                             && Player.p_specialtype != SC_VALAR)
   38:                                 /* neither is valar */
   39:                         {
   40:                                 battleplayer(foeloc);
   41:                                 return;
   42:                         }
   43:                 }
   44:                 foeloc += SZ_PLAYERSTRUCT;
   45:         }
   46: }
   47: 
   48: void
   49: battleplayer(foeplace)
   50:         long    foeplace;
   51: {
   52:         double  dtemp;         /* for temporary calculations */
   53:         double  oldhits = 0.0; /* previous damage inflicted by foe */
   54:         int     loop;          /* for timing out */
   55:         int     ch;            /* input */
   56:         short   oldtampered;   /* old value of foe's p_tampered */
   57: 
   58:         Lines = 8;
   59:         Luckout = FALSE;
   60:         mvaddstr(4, 0, "Preparing for battle!\n");
   61:         refresh();
   62: 
   63: #ifdef SYS5
   64:         flushinp();
   65: #endif
   66: 
   67:         /* set up variables, file, etc. */
   68:         Player.p_status = S_INBATTLE;
   69:         Shield = Player.p_energy;
   70: 
   71:         /* if p_tampered is not 0, someone else may try to change it (king,
   72:          * etc.) */
   73:         Player.p_tampered = oldtampered = 1;
   74:         Player.p_1scratch = 0.0;
   75:         Player.p_istat = I_OFF;
   76: 
   77:         readrecord(&Other, foeplace);
   78:         if (fabs(Player.p_level - Other.p_level) > 20.0)
   79:                 /* see if players are greatly mismatched */
   80:         {
   81:                 dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
   82:                 if (dtemp < -0.5)
   83:                         /* foe outweighs this one */
   84:                         Player.p_speed *= 2.0;
   85:         }
   86:         writerecord(&Player, Fileloc); /* write out all our info */
   87: 
   88:         if (Player.p_blindness)
   89:                 Enemyname = "someone";
   90:         else
   91:                 Enemyname = Other.p_name;
   92: 
   93:         mvprintw(6, 0, "You have encountered %s   Level: %.0f\n", Enemyname, Other.p_level);
   94:         refresh();
   95: 
   96:         for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
   97:                 /* wait for foe to respond */
   98:         {
   99:                 readrecord(&Other, foeplace);
  100:                 sleep(1);
  101:         }
  102: 
  103:         if (Other.p_status != S_INBATTLE)
  104:                 /* foe did not respond */
  105:         {
  106:                 mvprintw(5, 0, "%s is not responding.\n", Enemyname);
  107:                 goto LEAVE;
  108:         }
  109:         /* else, we are ready to battle */
  110: 
  111:         move(4, 0);
  112:         clrtoeol();
  113: 
  114:         /*
  115:          * determine who is first master
  116:          * if neither player is faster, check level
  117:          * if neither level is greater, battle is not allowed
  118:          * (this should never happen, but we have to handle it)
  119:          */
  120:         if (Player.p_speed > Other.p_speed)
  121:                 Foestrikes = FALSE;
  122:         else
  123:                 if (Other.p_speed > Player.p_speed)
  124:                         Foestrikes = TRUE;
  125:                 else
  126:                         if (Player.p_level > Other.p_level)
  127:                                 Foestrikes = FALSE;
  128:                         else
  129:                                 if (Other.p_level > Player.p_level)
  130:                                         Foestrikes = TRUE;
  131:                                 else
  132:                                         /* no one is faster */
  133:                                 {
  134:                                         printw("You can't fight %s yet.", Enemyname);
  135:                                         goto LEAVE;
  136:                                 }
  137: 
  138:         for (;;) {
  139:                 displaystats();
  140:                 readmessage();
  141:                 mvprintw(1, 26, "%20.0f", Shield);    /* overprint energy */
  142: 
  143:                 if (!Foestrikes)
  144:                         /* take action against foe */
  145:                         myturn();
  146:                 else
  147:                         /* wait for foe to take action */
  148:                 {
  149:                         mvaddstr(4, 0, "Waiting...\n");
  150:                         clrtoeol();
  151:                         refresh();
  152: 
  153:                         for (loop = 0; loop < 20; ++loop)
  154:                                 /* wait for foe to act */
  155:                         {
  156:                                 readrecord(&Other, foeplace);
  157:                                 if (Other.p_1scratch != oldhits)
  158:                                         /* p_1scratch changes to indicate
  159:                                          * action */
  160:                                         break;
  161:                                 else
  162:                                         /* wait and try again */
  163:                                 {
  164:                                         sleep(1);
  165:                                         addch('.');
  166:                                         refresh();
  167:                                 }
  168:                         }
  169: 
  170:                         if (Other.p_1scratch == oldhits) {
  171:                                 /* timeout */
  172:                                 mvaddstr(22, 0, "Timeout: waiting for response.  Do you want to wait ? ");
  173:                                 ch = getanswer("NY", FALSE);
  174:                                 move(22, 0);
  175:                                 clrtobot();
  176:                                 if (ch == 'Y')
  177:                                         continue;
  178:                                 else
  179:                                         break;
  180:                         } else
  181:                                 /* foe took action */
  182:                         {
  183:                                 switch (Other.p_istat) {
  184:                                 case I_RAN: /* foe ran away */
  185:                                         mvprintw(Lines++, 0, "%s ran away!", Enemyname);
  186:                                         break;
  187: 
  188:                                 case I_STUCK:       /* foe tried to run, but
  189:                                                  * couldn't */
  190:                                         mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
  191:                                         break;
  192: 
  193:                                 case I_BLEWIT:      /* foe tried to luckout, but
  194:                                                  * didn't */
  195:                                         mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
  196:                                         break;
  197: 
  198:                                 default:
  199:                                         dtemp = Other.p_1scratch - oldhits;
  200:                                         mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
  201:                                         Shield -= dtemp;
  202:                                         break;
  203:                                 }
  204: 
  205:                                 oldhits = Other.p_1scratch; /* keep track of old
  206:                                                                  * hits */
  207: 
  208:                                 if (Other.p_tampered != oldtampered)
  209:                                         /* p_tampered changes to relinquish
  210:                                          * turn */
  211:                                 {
  212:                                         oldtampered = Other.p_tampered;
  213:                                         Foestrikes = FALSE;
  214:                                 }
  215:                         }
  216:                 }
  217: 
  218:                 /* decide what happens next */
  219:                 refresh();
  220:                 if (Lines > LINES - 2) {
  221:                         more(Lines);
  222:                         move(Lines = 8, 0);
  223:                         clrtobot();
  224:                 }
  225:                 if (Other.p_istat == I_KILLED || Shield < 0.0)
  226:                         /* we died */
  227:                 {
  228:                         Shield = -2.0;       /* insure this value is negative */
  229:                         break;
  230:                 }
  231:                 if (Player.p_istat == I_KILLED)
  232:                         /* we killed foe; award treasre */
  233:                 {
  234:                         mvprintw(Lines++, 0, "You killed %s!", Enemyname);
  235:                         Player.p_experience += Other.p_experience;
  236:                         Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
  237:                         Player.p_amulets += Other.p_amulets;
  238:                         Player.p_charms += Other.p_charms;
  239:                         collecttaxes(Other.p_gold, Other.p_gems);
  240:                         Player.p_sword = MAX(Player.p_sword, Other.p_sword);
  241:                         Player.p_shield = MAX(Player.p_shield, Other.p_shield);
  242:                         Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
  243:                         if (Other.p_virgin && !Player.p_virgin) {
  244:                                 mvaddstr(Lines++, 0, "You have rescued a virgin.  Will you be honorable ? ");
  245:                                 if ((ch = getanswer("YN", FALSE)) == 'Y')
  246:                                         Player.p_virgin = TRUE;
  247:                                 else {
  248:                                         ++Player.p_sin;
  249:                                         Player.p_experience += 8000.0;
  250:                                 }
  251:                         }
  252:                         sleep(3);    /* give other person time to die */
  253:                         break;
  254:                 } else
  255:                         if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
  256:                                 /* either player ran away */
  257:                                 break;
  258:         }
  259: 
  260: LEAVE:
  261:         /* clean up things and leave */
  262:         writerecord(&Player, Fileloc); /* update a final time */
  263:         altercoordinates(0.0, 0.0, A_NEAR);    /* move away from battle site */
  264:         Player.p_energy = Shield;      /* set energy to actual value */
  265:         Player.p_tampered = T_OFF;     /* clear p_tampered */
  266: 
  267:         more(Lines);           /* pause */
  268: 
  269:         move(4, 0);
  270:         clrtobot();            /* clear bottom area of screen */
  271: 
  272:         if (Player.p_energy < 0.0)
  273:                 /* we are dead */
  274:                 death("Interterminal battle");
  275: }
  276: 
  277: void
  278: myturn()
  279: {
  280:         double  dtemp;         /* for temporary calculations */
  281:         int     ch;            /* input */
  282: 
  283:         mvaddstr(7, 0, "1:Fight  2:Run Away!  3:Power Blast  ");
  284:         if (Luckout)
  285:                 clrtoeol();
  286:         else
  287:                 addstr("4:Luckout  ");
  288: 
  289:         ch = inputoption();
  290:         move(Lines = 8, 0);
  291:         clrtobot();
  292: 
  293:         switch (ch) {
  294:         default:               /* fight */
  295:                 dtemp = ROLL(2.0, Player.p_might);
  296: HIT:
  297:                 mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
  298:                 Player.p_sin += 0.5;
  299:                 Player.p_1scratch += dtemp;
  300:                 Player.p_istat = I_OFF;
  301:                 break;
  302: 
  303:         case '2':              /* run away */
  304:                 Player.p_1scratch -= 1.0;     /* change this to indicate
  305:                                                  * action */
  306:                 if (drandom() > 0.25) {
  307:                         mvaddstr(Lines++, 0, "You got away!");
  308:                         Player.p_istat = I_RAN;
  309:                 } else {
  310:                         mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
  311:                         Player.p_istat = I_STUCK;
  312:                 }
  313:                 break;
  314: 
  315:         case '3':              /* power blast */
  316:                 dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
  317:                 Player.p_mana -= dtemp;
  318:                 dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
  319:                 mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
  320:                 goto HIT;
  321: 
  322:         case '4':              /* luckout */
  323:                 if (Luckout || drandom() > 0.1) {
  324:                         if (Luckout)
  325:                                 mvaddstr(Lines++, 0, "You already tried that!");
  326:                         else {
  327:                                 mvaddstr(Lines++, 0, "Not this time . . .");
  328:                                 Luckout = TRUE;
  329:                         }
  330: 
  331:                         Player.p_1scratch -= 1.0;
  332:                         Player.p_istat = I_BLEWIT;
  333:                 } else {
  334:                         mvaddstr(Lines++, 0, "You just lucked out!");
  335:                         Player.p_1scratch = Other.p_energy * 1.1;
  336:                 }
  337:                 break;
  338:         }
  339: 
  340:         refresh();
  341:         Player.p_1scratch = floor(Player.p_1scratch);  /* clean up any mess */
  342: 
  343:         if (Player.p_1scratch > Other.p_energy)
  344:                 Player.p_istat = I_KILLED;
  345:         else
  346:                 if (drandom() * Player.p_speed < drandom() * Other.p_speed)
  347:                         /* relinquish control */
  348:                 {
  349:                         ++Player.p_tampered;
  350:                         Foestrikes = TRUE;
  351:                 }
  352:         writerecord(&Player, Fileloc); /* let foe know what we did */
  353: }
  354: 
  355: void
  356: checktampered()
  357: {
  358:         long    loc = 0L;      /* location in energy void file */
  359: 
  360:         /* first check for energy voids */
  361:         fseek(Energyvoidfp, 0L, SEEK_SET);
  362:         while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
  363:                 if (Enrgyvoid.ev_active
  364:                     && Enrgyvoid.ev_x == Player.p_x
  365:                     && Enrgyvoid.ev_y == Player.p_y)
  366:                         /* sitting on one */
  367:                 {
  368:                         if (loc > 0L)
  369:                                 /* not the holy grail; inactivate energy void */
  370:                         {
  371:                                 Enrgyvoid.ev_active = FALSE;
  372:                                 writevoid(&Enrgyvoid, loc);
  373:                                 tampered(T_NRGVOID, 0.0, 0.0);
  374:                         } else
  375:                                 if (Player.p_status != S_CLOAKED)
  376:                                         /* holy grail */
  377:                                         tampered(T_GRAIL, 0.0, 0.0);
  378:                         break;
  379:                 } else
  380:                         loc += SZ_VOIDSTRUCT;
  381: 
  382:         /* now check for other things */
  383:         readrecord(&Other, Fileloc);
  384:         if (Other.p_tampered != T_OFF)
  385:                 tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
  386: }
  387: 
  388: void
  389: tampered(what, arg1, arg2)
  390:         int     what;
  391:         double  arg1;
  392:         double  arg2;
  393: {
  394:         long    loc;           /* location in file of other players */
  395: 
  396:         Changed = TRUE;
  397:         move(4, 0);
  398: 
  399:         Player.p_tampered = T_OFF;     /* no longer tampered with */
  400: 
  401:         switch (what) {
  402:         case T_NRGVOID:
  403:                 addstr("You've hit an energy void !\n");
  404:                 Player.p_mana /= 3.0;
  405:                 Player.p_energy /= 2.0;
  406:                 Player.p_gold = floor(Player.p_gold / 1.25) + 0.1;
  407:                 altercoordinates(0.0, 0.0, A_NEAR);
  408:                 break;
  409: 
  410:         case T_TRANSPORT:
  411:                 addstr("The king transported you !  ");
  412:                 if (Player.p_charms > 0) {
  413:                         addstr("But your charm saved you. . .\n");
  414:                         --Player.p_charms;
  415:                 } else {
  416:                         altercoordinates(0.0, 0.0, A_FAR);
  417:                         addch('\n');
  418:                 }
  419:                 break;
  420: 
  421:         case T_BESTOW:
  422:                 printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
  423:                 Player.p_gold += arg1;
  424:                 break;
  425: 
  426:         case T_CURSED:
  427:                 addstr("You've been cursed !  ");
  428:                 if (Player.p_blessing) {
  429:                         addstr("But your blessing saved you. . .\n");
  430:                         Player.p_blessing = FALSE;
  431:                 } else {
  432:                         addch('\n');
  433:                         Player.p_poison += 2.0;
  434:                         Player.p_energy = 10.0;
  435:                         Player.p_maxenergy *= 0.95;
  436:                         Player.p_status = S_PLAYING; /* no longer cloaked */
  437:                 }
  438:                 break;
  439: 
  440:         case T_VAPORIZED:
  441:                 addstr("You have been vaporized!\n");
  442:                 more(7);
  443:                 death("Vaporization");
  444:                 break;
  445: 
  446:         case T_MONSTER:
  447:                 addstr("The Valar zapped you with a monster!\n");
  448:                 more(7);
  449:                 encounter((int) arg1);
  450:                 return;
  451: 
  452:         case T_BLESSED:
  453:                 addstr("The Valar has blessed you!\n");
  454:                 Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
  455:                 Player.p_mana += 500.0;
  456:                 Player.p_strength += 0.5;
  457:                 Player.p_brains += 0.5;
  458:                 Player.p_magiclvl += 0.5;
  459:                 Player.p_poison = MIN(0.5, Player.p_poison);
  460:                 break;
  461: 
  462:         case T_RELOCATE:
  463:                 addstr("You've been relocated. . .\n");
  464:                 altercoordinates(arg1, arg2, A_FORCED);
  465:                 break;
  466: 
  467:         case T_HEAL:
  468:                 addstr("You've been healed!\n");
  469:                 Player.p_poison -= 0.25;
  470:                 Player.p_energy = Player.p_maxenergy + Player.p_shield;
  471:                 break;
  472: 
  473:         case T_EXVALAR:
  474:                 addstr("You are no longer Valar!\n");
  475:                 Player.p_specialtype = SC_COUNCIL;
  476:                 break;
  477: 
  478:         case T_GRAIL:
  479:                 addstr("You have found The Holy Grail!!\n");
  480:                 if (Player.p_specialtype < SC_COUNCIL)
  481:                         /* must be council of wise to behold grail */
  482:                 {
  483:                         addstr("However, you are not experienced enough to behold it.\n");
  484:                         Player.p_sin *= Player.p_sin;
  485:                         Player.p_mana += 1000;
  486:                 } else
  487:                         if (Player.p_specialtype == SC_VALAR
  488:                             || Player.p_specialtype == SC_EXVALAR) {
  489:                                 addstr("You have made it to the position of Valar once already.\n");
  490:                                 addstr("The Grail is of no more use to you now.\n");
  491:                         } else {
  492:                                 addstr("It is now time to see if you are worthy to behold it. . .\n");
  493:                                 refresh();
  494:                                 sleep(4);
  495: 
  496:                                 if (drandom() / 2.0 < Player.p_sin) {
  497:                                         addstr("You have failed!\n");
  498:                                         Player.p_strength =
  499:                                             Player.p_mana =
  500:                                             Player.p_energy =
  501:                                             Player.p_maxenergy =
  502:                                             Player.p_magiclvl =
  503:                                             Player.p_brains =
  504:                                             Player.p_experience =
  505:                                             Player.p_quickness = 1.0;
  506: 
  507:                                         altercoordinates(1.0, 1.0, A_FORCED);
  508:                                         Player.p_level = 0.0;
  509:                                 } else {
  510:                                         addstr("You made to position of Valar!\n");
  511:                                         Player.p_specialtype = SC_VALAR;
  512:                                         Player.p_lives = 5;
  513:                                         fseek(Playersfp, 0L, SEEK_SET);
  514:                                         loc = 0L;
  515:                                         while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  516:                                                 /* search for existing valar */
  517:                                                 if (Other.p_specialtype == SC_VALAR
  518:                                                     && Other.p_status != S_NOTUSED)
  519:                                                         /* found old valar */
  520:                                                 {
  521:                                                         Other.p_tampered = T_EXVALAR;
  522:                                                         writerecord(&Other, loc);
  523:                                                         break;
  524:                                                 } else
  525:                                                         loc += SZ_PLAYERSTRUCT;
  526:                                 }
  527:                         }
  528: 
  529:                 /* move grail to new location */
  530:                 Enrgyvoid.ev_active = TRUE;
  531:                 Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
  532:                 Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
  533: