📄 misc.c
字号:
/* * misc.c Phantasia miscellaneous support routines */#include "include.h"/************************************************************************// FUNCTION NAME: movelevel()// FUNCTION: move player to new level// AUTHOR: E. A. Estes, 12/4/85// ARGUMENTS: none// RETURN VALUE: none// MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()// GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]// GLOBAL OUTPUTS: Player, Changed// DESCRIPTION:/ Use lookup table to increment important statistics when/ progressing to new experience level./ Players are rested to maximum as a bonus for making a new/ level./ Check for council of wise, and being too big to be king.//************************************************************************/movelevel(){register struct charstats *statptr; /* for pointing into Stattable */double new; /* new level */double inc; /* increment between new and old levels */ Changed = TRUE; if (Player.p_type == C_EXPER) /* roll a type to use for increment */ statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)]; else statptr = Statptr; new = explevel(Player.p_experience); inc = new - Player.p_level; Player.p_level = new; /* add increments to statistics */ Player.p_strength += statptr->c_strength.increase * inc; Player.p_mana += statptr->c_mana.increase * inc; Player.p_brains += statptr->c_brains.increase * inc; Player.p_magiclvl += statptr->c_magiclvl.increase * inc; Player.p_maxenergy += statptr->c_energy.increase * inc; /* rest to maximum upon reaching new level */ Player.p_energy = Player.p_maxenergy + Player.p_shield; if (Player.p_crowns > 0 && Player.p_level >= 1000.0) /* no longer able to be king -- turn crowns into cash */ { Player.p_gold += ((double) Player.p_crowns) * 5000.0; Player.p_crowns = 0; } if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL) /* make a member of the council */ { mvaddstr(6, 0, "You have made it to the Council of the Wise.\n"); addstr("Good Luck on your search for the Holy Grail.\n"); Player.p_specialtype = SC_COUNCIL; /* no rings for council and above */ Player.p_ring.ring_type = R_NONE; Player.p_ring.ring_duration = 0; Player.p_lives = 3; /* three extra lives */ } if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR) death("Old age");}/**//************************************************************************// FUNCTION NAME: descrlocation()// FUNCTION: return a formatted description of location// AUTHOR: E. A. Estes, 12/4/85// ARGUMENTS:/ struct player playerp - pointer to player structure/ bool shortflag - set if short form is desired// RETURN VALUE: pointer to string containing result// MODULES CALLED: fabs(), floor(), sprintf(), distance()// GLOBAL INPUTS: Databuf[]// GLOBAL OUTPUTS: none// DESCRIPTION:/ Look at coordinates and return an appropriately formatted/ string.//************************************************************************/char *descrlocation(playerp, shortflag)struct player *playerp;bool shortflag;{double circle; /* corresponding circle for coordinates */register int quadrant; /* quandrant of grid */register char *label; /* pointer to place name */static char *nametable[4][4] = /* names of places */ { "Anorien", "Ithilien", "Rohan", "Lorien", "Gondor", "Mordor", "Dunland", "Rovanion", "South Gondor", "Khand", "Eriador", "The Iron Hills", "Far Harad", "Near Harad", "The Northern Waste", "Rhun" }; if (playerp->p_specialtype == SC_VALAR) return(" is in Valhala"); else if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0) { if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND) label = "The Point of No Return"; else label = "The Ashen Mountains"; } else if (circle >= 55) label = "Morannon"; else if (circle >= 35) label = "Kennaquahair"; else if (circle >= 20) label = "The Dead Marshes"; else if (circle >= 9) label = "The Outer Waste"; else if (circle >= 5) label = "The Moors Adventurous"; else { if (playerp->p_x == 0.0 && playerp->p_y == 0.0) label = "The Lord's Chamber"; else { /* this expression is split to prevent compiler loop with some compilers */ quadrant = ((playerp->p_x > 0.0) ? 1 : 0); quadrant += ((playerp->p_y >= 0.0) ? 2 : 0); label = nametable[((int) circle) - 1][quadrant]; } } if (shortflag) sprintf(Databuf, "%.29s", label); else sprintf(Databuf, " is in %s (%.0f,%.0f)", label, playerp->p_x, playerp->p_y); return(Databuf);}/**//************************************************************************// FUNCTION NAME: tradingpost()// FUNCTION: do trading post stuff// AUTHOR: E. A. Estes, 12/4/85// ARGUMENTS: none// RETURN VALUE: none// MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(), / sleep(), floor(), wmove(), drandom(), wclear(), printw(), / altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(), / wclrtoeol(), wclrtobot()// GLOBAL INPUTS: Menu[], Circle, Player, *stdscr, Fileloc, Nobetter[]// GLOBAL OUTPUTS: Player// DESCRIPTION:/ Different trading posts have different items./ Merchants cannot be cheated, but they can be dishonest/ themselves.// Shields, swords, and quicksilver are not cumulative. This is/ one major area of complaint, but there are two reasons for this:/ 1) It becomes MUCH too easy to make very large versions/ of these items./ 2) In the real world, one cannot simply weld two swords/ together to make a bigger one.// At one time, it was possible to sell old weapons at half the purchase/ price. This resulted in huge amounts of gold floating around,/ and the game lost much of its challenge.// Also, purchasing gems defeats the whole purpose of gold. Gold/ is small change for lower level players. They really shouldn't/ be able to accumulate more than enough gold for a small sword or/ a few books. Higher level players shouldn't even bother to pick/ up gold, except maybe to buy mana once in a while.//************************************************************************/tradingpost(){double numitems; /* number of items to purchase */double cost; /* cost of purchase */double blessingcost; /* cost of blessing */int ch; /* input */register int size; /* size of the trading post */register int loop; /* loop counter */int cheat = 0; /* number of times player has tried to cheat */bool dishonest = FALSE;/* set when merchant is dishonest */ Player.p_status = S_TRADING; writerecord(&Player, Fileloc); clear(); addstr("You are at a trading post. All purchases must be made with gold."); size = sqrt(fabs(Player.p_x / 100)) + 1; size = MIN(7, size); /* set up cost of blessing */ blessingcost = 1000.0 * (Player.p_level + 5.0); /* print Menu */ move(7, 0); for (loop = 0; loop < size; ++loop) /* print Menu */ { if (loop == 6) cost = blessingcost; else cost = Menu[loop].cost; printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost); } mvprintw(5, 0, "L:Leave P:Purchase S:Sell Gems ? "); for (;;) { adjuststats(); /* truncate any bad values */ /* print some important statistics */ mvprintw(1, 0, "Gold: %9.0f Gems: %9.0f Level: %6.0f Charms: %6d\n", Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms); printw("Shield: %9.0f Sword: %9.0f Quicksilver:%3.0f Blessed: %s\n", Player.p_shield, Player.p_sword, Player.p_quksilver, (Player.p_blessing ? " True" : "False")); printw("Brains: %9.0f Mana: %9.0f", Player.p_brains, Player.p_mana); move(5, 36); ch = getanswer("LPS", FALSE); move(15, 0); clrtobot(); switch(ch) { case 'L': /* leave */ case '\n': altercoordinates(0.0, 0.0, A_NEAR); return; case 'P': /* make purchase */ mvaddstr(15, 0, "What what would you like to buy ? "); ch = getanswer(" 1234567", FALSE); move(15, 0); clrtoeol(); if (ch - '0' > size) addstr("Sorry, this merchant doesn't have that."); else switch (ch) { case '1': printw("Mana is one per %.0f gold piece. How many do you want (%.0f max) ? ", Menu[0].cost, floor(Player.p_gold / Menu[0].cost)); cost = (numitems = floor(infloat())) * Menu[0].cost; if (cost > Player.p_gold || numitems < 0) ++cheat; else { cheat = 0; Player.p_gold -= cost; if (drandom() < 0.02) dishonest = TRUE; else Player.p_mana += numitems; } break; case '2': printw("Shields are %.0f per +1. How many do you want (%.0f max) ? ", Menu[1].cost, floor(Player.p_gold / Menu[1].cost)); cost = (numitems = floor(infloat())) * Menu[1].cost; if (numitems == 0.0) break; else if (cost > Player.p_gold || numitems < 0) ++cheat; else if (numitems < Player.p_shield) NOBETTER(); else { cheat = 0; Player.p_gold -= cost; if (drandom() < 0.02) dishonest = TRUE; else Player.p_shield = numitems; } break; case '3': printw("A book costs %.0f gp. How many do you want (%.0f max) ? ", Menu[2].cost, floor(Player.p_gold / Menu[2].cost)); cost = (numitems = floor(infloat())) * Menu[2].cost; if (cost > Player.p_gold || numitems < 0) ++cheat; else { cheat = 0; Player.p_gold -= cost; if (drandom() < 0.02) dishonest = TRUE; else if (drandom() * numitems > Player.p_level / 10.0 && numitems != 1) { printw("\nYou blew your mind!\n"); Player.p_brains /= 5; } else { Player.p_brains += floor(numitems) * ROLL(20, 8); } } break; case '4': printw("Swords are %.0f gp per +1. How many + do you want (%.0f max) ? ", Menu[3].cost, floor(Player.p_gold / Menu[3].cost)); cost = (numitems = floor(infloat())) * Menu[3].cost; if (numitems == 0.0) break; else if (cost > Player.p_gold || numitems < 0) ++cheat; else if (numitems < Player.p_sword) NOBETTER(); else { cheat = 0; Player.p_gold -= cost; if (drandom() < 0.02) dishonest = TRUE; else Player.p_sword = numitems; } break; case '5': printw("A charm costs %.0f gp. How many do you want (%.0f max) ? ", Menu[4].cost, floor(Player.p_gold / Menu[4].cost)); cost = (numitems = floor(infloat())) * Menu[4].cost; if (cost > Player.p_gold || numitems < 0) ++cheat; else { cheat = 0; Player.p_gold -= cost; if (drandom() < 0.02) dishonest = TRUE; else Player.p_charms += numitems; } break; case '6': printw("Quicksilver is %.0f gp per +1. How many + do you want (%.0f max) ? ", Menu[5].cost, floor(Player.p_gold / Menu[5].cost)); cost = (numitems = floor(infloat())) * Menu[5].cost; if (numitems == 0.0) break; else if (cost > Player.p_gold || numitems < 0) ++cheat; else if (numitems < Player.p_quksilver) NOBETTER(); else { cheat = 0; Player.p_gold -= cost; if (drandom() < 0.02) dishonest = TRUE; else Player.p_quksilver = numitems; } break; case '7': if (Player.p_blessing) { addstr("You already have a blessing."); break; } printw("A blessing requires a %.0f gp donation. Still want one ? ", blessingcost); ch = getanswer("NY", FALSE); if (ch == 'Y') if (Player.p_gold < blessingcost) ++cheat; else { cheat = 0; Player.p_gold -= blessingcost; if (drandom() < 0.02) dishonest = TRUE; else Player.p_blessing = TRUE; } break; } break; case 'S': /* sell gems */ mvprintw(15, 0, "A gem is worth %.0f gp. How many do you want to sell (%.0f max) ? ", (double) N_GEMVALUE, Player.p_gems); numitems = floor(infloat()); if (numitems > Player.p_gems || numitems < 0) ++cheat; else { cheat = 0; Player.p_gems -= numitems; Player.p_gold += numitems * N_GEMVALUE; } } if (cheat == 1) mvaddstr(17, 0, "Come on, merchants aren't stupid. Stop cheating.\n"); else if (cheat == 2) { mvaddstr(17, 0, "You had your chance. This merchant happens to be\n"); printw("a %.0f level magic user, and you made %s mad!\n", ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her"); altercoordinates(0.0, 0.0, A_FAR); Player.p_energy /= 2.0; ++Player.p_sin; more(23); return; } else if (dishonest) { mvaddstr(17, 0, "The merchant stole your money!"); refresh(); altercoordinates(Player.p_x - Player.p_x / 10.0, Player.p_y - Player.p_y / 10.0, A_SPECIFIC); sleep(2); return; } }}/**//************************************************************************// FUNCTION NAME: displaystats()// FUNCTION: print out important player statistics// AUTHOR: E. A. Estes, 12/4/85// ARGUMENTS: none// RETURN VALUE: none// MODULES CALLED: descrstatus(), descrlocation(), mvprintw()// GLOBAL INPUTS: Users, Player// GLOBAL OUTPUTS: none// DESCRIPTION:/ Important player statistics are printed on the screen.//************************************************************************/displaystats(){ mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE)); mvprintw(1, 0, "Level :%7.0f Energy :%9.0f(%9.0f) Mana :%9.0f Users:%3d\n", Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield, Player.p_mana, Users); mvprintw(2, 0, "Quick :%3.0f(%3.0f) Strength:%9.0f(%9.0f) Gold :%9.0f %s\n", Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might, Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));}/**//************************************************************************// FUNCTION NAME: allstatslist()// FUNCTION: show player items// AUTHOR: E. A. Estes, 12/4/85// ARGUMENTS: none// RETURN VALUE: none// MODULES CALLED: mvprintw(), descrtype()// GLOBAL INPUTS: Player// GLOBAL OUTPUTS: none// DESCRIPTION:/ Print out some player statistics of lesser importance.//************************************************************************/allstatslist(){static char *flags[] = /* to print value of some bools */ { "False", " True" }; mvprintw( 8, 0, "Type: %s\n", descrtype(&Player, FALSE)); mvprintw(10, 0, "Experience: %9.0f", Player.p_experience); mvprintw(11, 0, "Brains : %9.0f", Player.p_brains); mvprintw(12, 0, "Magic Lvl : %9.0f", Player.p_magiclvl); mvprintw(13, 0, "Sin : %9.5f", Player.p_sin); mvprintw(14, 0, "Poison : %9.5f", Player.p_poison); mvprintw(15, 0, "Gems : %9.0f", Player.p_gems); mvprintw(16, 0, "Age : %9d", Player.p_age); mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater); mvprintw(11, 40, "Amulets : %9d", Player.p_amulets); mvprintw(12, 40, "Charms : %9d", Player.p_charms); mvprintw(13, 40, "Crowns : %9d", Player.p_crowns); mvprintw(14, 40, "Shield : %9.0f", Player.p_shield); mvprintw(15, 40, "Sword : %9.0f", Player.p_sword); mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver); mvprintw(18, 0, "Blessing: %s Ring: %s Virgin: %s Palantir: %s", flags[Player.p_blessing], flags[Player.p_ring.ring_type != R_NONE], flags[Player.p_virgin], flags[Player.p_palantir]);}/**//************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -