diff options
Diffstat (limited to 'src/bldg.c')
-rw-r--r-- | src/bldg.c | 2273 |
1 files changed, 2273 insertions, 0 deletions
diff --git a/src/bldg.c b/src/bldg.c new file mode 100644 index 00000000..6a10a0f2 --- /dev/null +++ b/src/bldg.c @@ -0,0 +1,2273 @@ +/* File: bldg.c */ + +/* + * Purpose: Building commands + * Created by Ken Wigle for Kangband - a variant of Angband 2.8.3 + * -KMW- + * + * Rewritten for Kangband 2.8.3i using Kamband's version of + * bldg.c as written by Ivan Tkatchev + * + * Changed for ZAngband by Robert Ruehlmann + * + * Heavily modified for ToME by DarkGod + */ + +#include "angband.h" + +/* hack as in leave_store in store.c */ +static bool leave_bldg = FALSE; + +/* remember building location */ +static int building_loc = 0; + + +/* + * A helper function for is_state + */ +bool is_state_aux(store_type *s_ptr, int state) +{ + owner_type *ow_ptr = &ow_info[s_ptr->owner]; + + + /* Check race */ + if (ow_ptr->races[state][p_ptr->prace / 32] & (1 << p_ptr->prace)) + { + return (TRUE); + } + + /* Check class */ + if (ow_ptr->classes[state][p_ptr->prace / 32] & (1 << p_ptr->pclass)) + { + return (TRUE); + } + + /* All failed */ + return (FALSE); +} + + +/* + * Test if the state accords with the player + */ +bool is_state(store_type *s_ptr, int state) +{ + if (state == STORE_NORMAL) + { + if (is_state_aux(s_ptr, STORE_LIKED)) return (FALSE); + if (is_state_aux(s_ptr, STORE_HATED)) return (FALSE); + return (TRUE); + } + + else + { + return (is_state_aux(s_ptr, state)); + } +} + + +/* + * Clear the building information + */ +static void clear_bldg(int min_row, int max_row) +{ + int i; + + + for (i = min_row; i <= max_row; i++) + { + prt("", i, 0); + } +} + + +/* + * Display a building. + */ +void show_building(store_type *s_ptr) +{ + char buff[20]; + + int i; + + byte action_color; + + char tmp_str[80]; + + store_info_type *st_ptr = &st_info[s_ptr->st_idx]; + + store_action_type *ba_ptr; + + + for (i = 0; i < 6; i++) + { + ba_ptr = &ba_info[st_ptr->actions[i]]; + + if (ba_ptr->letter != '.') + { + if (ba_ptr->action_restr == 0) + { + if ((is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) || + (is_state(s_ptr, STORE_HATED) && (ba_ptr->costs[STORE_HATED] == 0)) || + (is_state(s_ptr, STORE_NORMAL) && (ba_ptr->costs[STORE_NORMAL] == 0))) + { + action_color = TERM_WHITE; + buff[0] = '\0'; + } + else if (is_state(s_ptr, STORE_LIKED)) + { + action_color = TERM_L_GREEN; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); + } + else if (is_state(s_ptr, STORE_HATED)) + { + action_color = TERM_RED; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_HATED]); + } + else + { + action_color = TERM_YELLOW; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]); + } + } + else if (ba_ptr->action_restr == 1) + { + if ((is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) || + (is_state(s_ptr, STORE_NORMAL) && (ba_ptr->costs[STORE_NORMAL] == 0))) + { + action_color = TERM_WHITE; + buff[0] = '\0'; + } + else if (is_state(s_ptr, STORE_LIKED)) + { + action_color = TERM_L_GREEN; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); + } + else if (is_state(s_ptr, STORE_HATED)) + { + action_color = TERM_L_DARK; + strnfmt(buff, 20, "(closed)"); + } + else + { + action_color = TERM_YELLOW; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]); + } + } + else + { + if (is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) + { + action_color = TERM_WHITE; + buff[0] = '\0'; + } + else if (is_state(s_ptr, STORE_LIKED)) + { + action_color = TERM_L_GREEN; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); + } + else + { + action_color = TERM_L_DARK; + strnfmt(buff, 20, "(closed)"); + } + } + + strnfmt(tmp_str, 80, " %c", ba_ptr->letter); + c_put_str(TERM_YELLOW, tmp_str, 21 + (i / 2), 17 + (30 * (i % 2))); + + strnfmt(tmp_str, 80, ") %s %s", ba_ptr->name + ba_name, buff); + c_put_str(action_color, tmp_str, 21 + (i / 2), 2 + 17 + (30 * (i % 2))); + } + } +} + + +/* reset timed flags */ +static void reset_tim_flags() +{ + p_ptr->fast = 0; /* Timed -- Fast */ + p_ptr->slow = 0; /* Timed -- Slow */ + p_ptr->blind = 0; /* Timed -- Blindness */ + p_ptr->paralyzed = 0; /* Timed -- Paralysis */ + p_ptr->confused = 0; /* Timed -- Confusion */ + p_ptr->afraid = 0; /* Timed -- Fear */ + p_ptr->image = 0; /* Timed -- Hallucination */ + p_ptr->poisoned = 0; /* Timed -- Poisoned */ + p_ptr->cut = 0; /* Timed -- Cut */ + p_ptr->stun = 0; /* Timed -- Stun */ + + p_ptr->protevil = 0; /* Timed -- Protection */ + p_ptr->protgood = 0; /* Timed -- Protection */ + p_ptr->invuln = 0; /* Timed -- Invulnerable */ + p_ptr->hero = 0; /* Timed -- Heroism */ + p_ptr->shero = 0; /* Timed -- Super Heroism */ + p_ptr->shield = 0; /* Timed -- Shield Spell */ + p_ptr->blessed = 0; /* Timed -- Blessed */ + p_ptr->tim_invis = 0; /* Timed -- Invisibility */ + p_ptr->tim_infra = 0; /* Timed -- Infra Vision */ + + p_ptr->oppose_acid = 0; /* Timed -- oppose acid */ + p_ptr->oppose_elec = 0; /* Timed -- oppose lightning */ + p_ptr->oppose_fire = 0; /* Timed -- oppose heat */ + p_ptr->oppose_cold = 0; /* Timed -- oppose cold */ + p_ptr->oppose_pois = 0; /* Timed -- oppose poison */ + + p_ptr->confusing = 0; /* Touch of Confusion */ +} + + +/* + * arena commands + */ +static void arena_comm(int cmd) +{ + char tmp_str[80]; + + monster_race *r_ptr; + + cptr name; + + + switch (cmd) + { + case BACT_ARENA: + { + if (p_ptr->arena_number == MAX_ARENA_MONS) + { + clear_bldg(5, 19); + prt(" Arena Victor!", 5, 0); + prt("Congratulations! You have defeated all before you.", 7, 0); + prt("For that, receive the prize: 10,000 gold pieces", 8, 0); + prt("", 10, 0); + prt("", 11, 0); + p_ptr->au += 10000; + msg_print("Press the space bar to continue"); + msg_print(NULL); + p_ptr->arena_number++; + } + else if (p_ptr->arena_number > MAX_ARENA_MONS) + { + msg_print("You enter the arena briefly and bask in your glory."); + msg_print(NULL); + } + else + { + p_ptr->inside_arena = TRUE; + p_ptr->exit_bldg = FALSE; + reset_tim_flags(); + p_ptr->leaving = TRUE; + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + leave_bldg = TRUE; + } + + break; + } + + case BACT_POSTER: + { + if (p_ptr->arena_number == MAX_ARENA_MONS) + msg_print("You are victorious. Enter the arena for the ceremony."); + else if (p_ptr->arena_number > MAX_ARENA_MONS) + msg_print("You have won against all foes."); + else + { + r_ptr = &r_info[arena_monsters[p_ptr->arena_number]]; + name = (r_name + r_ptr->name); + strnfmt(tmp_str, 80, "Do I hear any challenges against: %s", name); + msg_print(tmp_str); + msg_print(NULL); + } + + break; + } + + case BACT_ARENA_RULES: + { + /* Save screen */ + screen_save(); + + /* Peruse the arena help file */ + (void)show_file("arena.txt", NULL, 0, 0); + + /* Load screen */ + screen_load(); + + break; + } + } +} + + +/* + * display fruit for dice slots + */ +static void display_fruit(int row, int col, int fruit) +{ + switch (fruit) + { + case 0: /* lemon */ + { + c_put_str(TERM_YELLOW, " ####.", row, col); + c_put_str(TERM_YELLOW, " # #", row + 1, col); + c_put_str(TERM_YELLOW, " # #", row + 2, col); + c_put_str(TERM_YELLOW, "# #", row + 3, col); + c_put_str(TERM_YELLOW, "# #", row + 4, col); + c_put_str(TERM_YELLOW, "# # ", row + 5, col); + c_put_str(TERM_YELLOW, "# # ", row + 6, col); + c_put_str(TERM_YELLOW, ".#### ", row + 7, col); + prt(" Lemon ", row + 8, col); + + break; + } + + case 1: /* orange */ + { + c_put_str(TERM_ORANGE, " ## ", row, col); + c_put_str(TERM_ORANGE, " #..# ", row + 1, col); + c_put_str(TERM_ORANGE, " #....# ", row + 2, col); + c_put_str(TERM_ORANGE, "#......#", row + 3, col); + c_put_str(TERM_ORANGE, "#......#", row + 4, col); + c_put_str(TERM_ORANGE, " #....# ", row + 5, col); + c_put_str(TERM_ORANGE, " #..# ", row + 6, col); + c_put_str(TERM_ORANGE, " ## ", row + 7, col); + prt(" Orange ", row + 8, col); + + break; + } + + case 2: /* sword */ + { + c_put_str(TERM_SLATE, " /\\ ", row, col); + c_put_str(TERM_SLATE, " ## ", row + 1, col); + c_put_str(TERM_SLATE, " ## ", row + 2, col); + c_put_str(TERM_SLATE, " ## ", row + 3, col); + c_put_str(TERM_SLATE, " ## ", row + 4, col); + c_put_str(TERM_SLATE, " ## ", row + 5, col); + c_put_str(TERM_UMBER, " ###### ", row + 6, col); + c_put_str(TERM_UMBER, " ## ", row + 7, col); + prt(" Sword ", row + 8, col); + + break; + } + + case 3: /* shield */ + { + c_put_str(TERM_SLATE, " ###### ", row, col); + c_put_str(TERM_SLATE, "# #", row + 1, col); + c_put_str(TERM_SLATE, "# ++++ #", row + 2, col); + c_put_str(TERM_SLATE, "# +==+ #", row + 3, col); + c_put_str(TERM_SLATE, "# ++ #", row + 4, col); + c_put_str(TERM_SLATE, " # # ", row + 5, col); + c_put_str(TERM_SLATE, " # # ", row + 6, col); + c_put_str(TERM_SLATE, " ## ", row + 7, col); + prt(" Shield ", row + 8, col); + + break; + } + + case 4: /* plum */ + { + c_put_str(TERM_VIOLET, " ## ", row, col); + c_put_str(TERM_VIOLET, " ###### ", row + 1, col); + c_put_str(TERM_VIOLET, "########", row + 2, col); + c_put_str(TERM_VIOLET, "########", row + 3, col); + c_put_str(TERM_VIOLET, "########", row + 4, col); + c_put_str(TERM_VIOLET, " ###### ", row + 5, col); + c_put_str(TERM_VIOLET, " #### ", row + 6, col); + c_put_str(TERM_VIOLET, " ## ", row + 7, col); + prt(" Plum ", row + 8, col); + + break; + } + + case 5: /* cherry */ + { + c_put_str(TERM_RED, " ##", row, col); + c_put_str(TERM_RED, " ### ", row + 1, col); + c_put_str(TERM_RED, " #..# ", row + 2, col); + c_put_str(TERM_RED, " #..# ", row + 3, col); + c_put_str(TERM_RED, " ###### ", row + 4, col); + c_put_str(TERM_RED, "#..##..#", row + 5, col); + c_put_str(TERM_RED, "#..##..#", row + 6, col); + c_put_str(TERM_RED, " ## ## ", row + 7, col); + prt(" Cherry ", row + 8, col); + + break; + } + } +} + + +/* + * gamble_comm + */ +static bool gamble_comm(int cmd) +{ + int roll1, roll2, roll3, choice, odds, win; + + s32b wager; + + s32b maxbet; + + s32b oldgold; + + static const char *fruit[6] = + {"Lemon", "Orange", "Sword", "Shield", "Plum", "Cherry" + }; + + char out_val[160], tmp_str[80], again; + + cptr p; + + + screen_save(); + + if (cmd == BACT_GAMBLE_RULES) + { + /* Peruse the gambling help file */ + (void)show_file("gambling.txt", NULL, 0, 0); + } + else + { + clear_bldg(5, 23); + + /* Set maximum bet */ + if (p_ptr->lev < 10) + maxbet = (p_ptr->lev * 100); + else + maxbet = (p_ptr->lev * 1000); + + /* Get the wager */ + strcpy(out_val, ""); + strnfmt(tmp_str, 80, "Your wager (1-%ld) ? ", maxbet); + get_string(tmp_str, out_val, 32); + + /* Strip spaces */ + for (p = out_val; *p == ' '; p++); + + wager = atol(p); + + if (wager > p_ptr->au) + { + msg_print("Hey! You don't have the gold - get out of here!"); + msg_print(NULL); + screen_load(); + return (FALSE); + } + else if (wager > maxbet) + { + msg_format("I'll take $%ld of that. Keep the rest.", maxbet); + wager = maxbet; + } + else if (wager < 1) + { + msg_print("Ok, we'll start with $1."); + + wager = 1; + } + msg_print(NULL); + win = FALSE; + odds = 0; + oldgold = p_ptr->au; + + strnfmt(tmp_str, 80, "Gold before game: %9ld", oldgold); + prt(tmp_str, 20, 2); + + strnfmt(tmp_str, 80, "Current Wager: %9ld", wager); + prt(tmp_str, 21, 2); + + do + { + switch (cmd) + { + case BACT_IN_BETWEEN: /* Game of In-Between */ + { + c_put_str(TERM_GREEN, "In Between", 5, 2); + odds = 3; + win = FALSE; + roll1 = randint(10); + roll2 = randint(10); + choice = randint(10); + strnfmt(tmp_str, 80, "Black die: %d Black Die: %d", + roll1, roll2); + prt(tmp_str, 8, 3); + strnfmt(tmp_str, 80, "Red die: %d", choice); + prt(tmp_str, 11, 14); + if (((choice > roll1) && (choice < roll2)) || + ((choice < roll1) && (choice > roll2))) + win = TRUE; + + break; + } + case BACT_CRAPS: /* Game of Craps */ + { + c_put_str(TERM_GREEN, "Craps", 5, 2); + win = 3; + odds = 1; + roll1 = randint(6); + roll2 = randint(6); + roll3 = roll1 + roll2; + choice = roll3; + strnfmt(tmp_str, 80, "First roll: %d %d Total: %d", roll1, + roll2, roll3); + prt(tmp_str, 7, 5); + if ((roll3 == 7) || (roll3 == 11)) + win = TRUE; + else if ((roll3 == 2) || (roll3 == 3) || (roll3 == 12)) + win = FALSE; + else + { + do + { + msg_print("Hit any key to roll again"); + msg_print(NULL); + roll1 = randint(6); + roll2 = randint(6); + roll3 = roll1 + roll2; + + strnfmt(tmp_str, 80, "Roll result: %d %d Total: %d", + roll1, roll2, roll3); + prt(tmp_str, 8, 5); + if (roll3 == choice) + win = TRUE; + else if (roll3 == 7) + win = FALSE; + } + while ((win != TRUE) && (win != FALSE)); + } + + break; + } + + case BACT_SPIN_WHEEL: /* Spin the Wheel Game */ + { + win = FALSE; + odds = 10; + c_put_str(TERM_GREEN, "Wheel", 5, 2); + prt("0 1 2 3 4 5 6 7 8 9", 7, 5); + prt("--------------------------------", 8, 3); + strcpy(out_val, ""); + get_string ("Pick a number (1-9): ", out_val, 32); + for (p = out_val; *p == ' '; p++); + choice = atol(p); + if (choice < 0) + { + msg_print("I'll put you down for 0."); + choice = 0; + } + else if (choice > 9) + { + msg_print("Ok, I'll put you down for 9."); + choice = 9; + } + msg_print(NULL); + roll1 = randint(10) - 1; + strnfmt(tmp_str, 80, "The wheel spins to a stop and the winner is %d", + roll1); + prt(tmp_str, 13, 3); + prt("", 9, 0); + prt("*", 9, (3 * roll1 + 5)); + if (roll1 == choice) + win = TRUE; + + break; + } + + case BACT_DICE_SLOTS: /* The Dice Slots */ + { + c_put_str(TERM_GREEN, "Dice Slots", 5, 2); + win = FALSE; + roll1 = randint(6); + roll2 = randint(6); + choice = randint(6); + strnfmt(tmp_str, 80, "%s %s %s", + fruit[roll1 - 1], fruit[roll2 - 1], + fruit[choice - 1]); + prt(tmp_str, 15, 37); + prt("/--------------------------\\", 7, 2); + prt("\\--------------------------/", 17, 2); + display_fruit(8, 3, roll1 - 1); + display_fruit(8, 12, roll2 - 1); + display_fruit(8, 21, choice - 1); + if ((roll1 == roll2) && (roll2 == choice)) + { + win = TRUE; + if (roll1 == 1) + odds = 4; + else if (roll1 == 2) + odds = 6; + else + odds = roll1 * roll1; + } + else if ((roll1 == 6) && (roll2 == 6)) + { + win = TRUE; + odds = choice + 1; + } + + break; + } + } + + if (win) + { + prt("YOU WON", 16, 37); + p_ptr->au = p_ptr->au + (odds * wager); + strnfmt(tmp_str, 80, "Payoff: %d", odds); + prt(tmp_str, 17, 37); + } + else + { + prt("You Lost", 16, 37); + p_ptr->au = p_ptr->au - wager; + prt("", 17, 37); + } + strnfmt(tmp_str, 80, "Current Gold: %9ld", p_ptr->au); + prt(tmp_str, 22, 2); + prt("Again(Y/N)?", 18, 37); + move_cursor(18, 49); + again = inkey(); + if (wager > p_ptr->au) + { + msg_print("Hey! You don't have the gold - get out of here!"); + msg_print(NULL); + screen_load(); + return (FALSE); + /* strnfmt(tmp_str, 80, "Current Wager: %9ld",wager); + prt(tmp_str, 17, 2); */ + } + } + while ((again == 'y') || (again == 'Y')); + + prt("", 18, 37); + if (p_ptr->au >= oldgold) + msg_print("You came out a winner! We'll win next time, I'm sure."); + else + msg_print("You lost gold! Haha, better head home."); + msg_print(NULL); + } + + screen_load(); + + return (TRUE); +} + + +/* + * inn commands + * Note that resting for the night was a perfect way to avoid player + * ghosts in the town *if* you could only make it to the inn in time (-: + * Now that the ghosts are temporarily disabled in 2.8.X, this function + * will not be that useful. I will keep it in the hopes the player + * ghost code does become a reality again. Does help to avoid filthy urchins. + * Resting at night is also a quick way to restock stores -KMW- + */ +static bool inn_comm(int cmd) +{ + bool vampire; + + + /* Extract race info */ + vampire = ((PRACE_FLAG(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire"))); + + switch (cmd) + { + case BACT_FOOD: /* Buy food & drink */ + { + if (!vampire) + { + msg_print("The barkeep gives you some gruel and a beer."); + msg_print(NULL); + (void) set_food(PY_FOOD_MAX - 1); + } + else + msg_print("You're a vampire and I don't have any food for you!"); + + break; + } + + /* + * I revamped this... Don't know why normal races didn't get + * mana regenerated. It is the grand tradition of p&p games -- pelpel + */ + case BACT_REST: /* Rest for the night */ + { + bool nighttime; + + /* Extract the current time */ + nighttime = ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18)); + + /* Normal races rest at night */ + if (!vampire && !nighttime) + { + msg_print("The rooms are available only at night."); + msg_print(NULL); + return (FALSE); + } + + /* Vampires rest during daytime */ + if (vampire && nighttime) + { + msg_print("The rooms are available only during daylight for your kind."); + msg_print(NULL); + return (FALSE); + } + + /* Must cure HP draining status first */ + if ((p_ptr->poisoned > 0) || (p_ptr->cut > 0)) + { + msg_print("You need a healer, not a room."); + msg_print(NULL); + msg_print("Sorry, but I don't want anyone dying in here."); + return (FALSE); + } + + /* Let the time pass XXX XXX XXX */ + if (vampire) + { + /* Wait for sunset */ + while ((bst(HOUR, turn) >= 6) && (bst(HOUR, turn) < 18)) + { + turn += (10L * MINUTE); + } + } + else + { + /* Wait for sunrise */ + while ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18)) + { + turn += (10L * MINUTE); + } + } + + /* Regen */ + p_ptr->chp = p_ptr->mhp; + p_ptr->csp = p_ptr->msp; + + /* Restore status */ + set_blind(0); + set_confused(0); + p_ptr->stun = 0; + + /* Message */ + if (vampire) msg_print("You awake refreshed for the new night."); + else msg_print("You awake refreshed for the new day."); + + /* Dungeon stuff */ + p_ptr->leaving = TRUE; + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + + /* Select new bounties. */ + select_bounties(); + + break; + } + + case BACT_RUMORS: /* Listen for rumors */ + { + char rumor[80]; + + get_rnd_line("rumors.txt", rumor); + msg_format("%s", rumor); + msg_print(NULL); + + break; + } + } + + return (TRUE); +} + + +#if 0 /* removes compiler warning */ + +/* + * share gold for thieves + */ +static void share_gold(void) +{ + int i; + + + i = (p_ptr->lev * 2) * 10; + msg_format("You collect %d gold pieces", i); + msg_print(NULL); + p_ptr->au += i; +} + +#endif + +/* + * Display quest information + */ +static void get_questinfo(int questnum) +{ + int i; + + + /* Print the quest info */ + prt(format("Quest Information (Danger level: %d)", quest[questnum].level), 5, 0); + + prt(quest[questnum].name, 7, 0); + + i = 0; + while ((i < 10) && (quest[questnum].desc[i][0] != '\0')) + { + c_put_str(TERM_YELLOW, quest[questnum].desc[i], i + 8, 0); + i++; + } +} + + +/* + * Request a quest from the Lord. + */ +static bool castle_quest(int y, int x) +{ + int plot = 0; + + quest_type *q_ptr; + + + clear_bldg(7, 18); + + /* Current plot of the building */ + plot = cave[y][x].special; + + /* Is there a quest available at the building? */ + if ((!plot) || (plots[plot] == QUEST_NULL)) + { + put_str("I don't have a quest for you at the moment.", 8, 0); + return FALSE; + } + + q_ptr = &quest[plots[plot]]; + + /* Quest is completed */ + if (q_ptr->status == QUEST_STATUS_COMPLETED) + { + /* Rewarded quest */ + q_ptr->status = QUEST_STATUS_FINISHED; + + process_hooks(HOOK_QUEST_FINISH, "(d)", plots[plot]); + + return (TRUE); + } + + /* Quest is still unfinished */ + else if (q_ptr->status == QUEST_STATUS_TAKEN) + { + put_str("You have not completed your current quest yet!", 8, 0); + put_str("Use CTRL-Q to check the status of your quest.", 9, 0); + put_str("Return when you have completed your quest.", 12, 0); + + return (FALSE); + } + /* Failed quest */ + else if (q_ptr->status == QUEST_STATUS_FAILED) + { + /* Mark quest as done (but failed) */ + q_ptr->status = QUEST_STATUS_FAILED_DONE; + + process_hooks(HOOK_QUEST_FAIL, "(d)", plots[plot]); + + return (FALSE); + } + /* No quest yet */ + else if (q_ptr->status == QUEST_STATUS_UNTAKEN) + { + if (process_hooks(HOOK_INIT_QUEST, "(d)", plots[plot])) return (FALSE); + + q_ptr->status = QUEST_STATUS_TAKEN; + + /* Assign a new quest */ + get_questinfo(plots[plot]); + + /* Add the hooks */ + if (quest[plots[plot]].type == HOOK_TYPE_C) quest[plots[plot]].init(plots[plot]); + + return (TRUE); + } + + return FALSE; +} + +/* + * Displaying town history -KMW- + */ +static void town_history(void) +{ + /* Save screen */ + screen_save(); + + /* Peruse the building help file */ + (void)show_file("bldg.txt", NULL, 0, 0); + + /* Load screen */ + screen_load(); +} + + +/* + * compare_weapon_aux2 -KMW- + */ +static void compare_weapon_aux2(object_type *o_ptr, int numblows, int r, int c, int mult, char attr[80], u32b f1, u32b f2, u32b f3, byte color) +{ + char tmp_str[80]; + + c_put_str(color, attr, r, c); + strnfmt(tmp_str, 80, "Attack: %d-%d damage", + numblows * ((o_ptr->dd * mult) + o_ptr->to_d), + numblows * ((o_ptr->ds * o_ptr->dd * mult) + o_ptr->to_d)); + put_str(tmp_str, r, c + 8); + r++; +} + + +/* + * compare_weapon_aux1 -KMW- + */ +static void compare_weapon_aux1(object_type *o_ptr, int col, int r) +{ + u32b f1, f2, f3, f4, f5, esp; + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + + if (f1 & (TR1_SLAY_ANIMAL)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Animals:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_EVIL)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Evil:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_UNDEAD)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Undead:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_DEMON)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Demons:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_ORC)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Orcs:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_TROLL)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Trolls:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_GIANT)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Giants:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_DRAGON)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Dragons:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_KILL_DRAGON)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 5, "Dragons:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_BRAND_ACID)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Acid:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_ELEC)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Elec:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_FIRE)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Fire:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_COLD)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Cold:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_POIS)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Poison:", + f1, f2, f3, TERM_RED); + } +} + + +/* + * list_weapon -KMW- + */ +static void list_weapon(object_type *o_ptr, int row, int col) +{ + char o_name[80]; + + char tmp_str[80]; + + + object_desc(o_name, o_ptr, TRUE, 0); + c_put_str(TERM_YELLOW, o_name, row, col); + strnfmt(tmp_str, 80, "To Hit: %d To Damage: %d", o_ptr->to_h, o_ptr->to_d); + put_str(tmp_str, row + 1, col); + strnfmt(tmp_str, 80, "Dice: %d Sides: %d", o_ptr->dd, o_ptr->ds); + put_str(tmp_str, row + 2, col); + strnfmt(tmp_str, 80, "Number of Blows: %d", p_ptr->num_blow); + put_str(tmp_str, row + 3, col); + c_put_str(TERM_YELLOW, "Possible Damage:", row + 5, col); + strnfmt(tmp_str, 80, "One Strike: %d-%d damage", o_ptr->dd + o_ptr->to_d, + (o_ptr->ds*o_ptr->dd) + o_ptr->to_d); + put_str(tmp_str, row + 6, col + 1); + strnfmt(tmp_str, 80, "One Attack: %d-%d damage", p_ptr->num_blow*(o_ptr->dd + o_ptr->to_d), + p_ptr->num_blow*(o_ptr->ds*o_ptr->dd + o_ptr->to_d)); + put_str(tmp_str, row + 7, col + 1); +} + + +/* + * Select melee weapons + */ +static bool item_tester_hook_melee_weapon(object_type *o_ptr) +{ + return (wield_slot(o_ptr) == INVEN_WIELD); +} + +/* + * compare_weapons -KMW- + */ +static bool compare_weapons(void) +{ + int item, item2, i; + + object_type *o1_ptr, *o2_ptr, *orig_ptr; + + object_type *i_ptr; + + cptr q, s; + + + clear_bldg(6, 18); + + o1_ptr = NULL; + o2_ptr = NULL; + i_ptr = NULL; + + /* Store copy of original wielded weapon in pack slot */ + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + orig_ptr = &p_ptr->inventory[INVEN_PACK]; + object_copy(orig_ptr, i_ptr); + + i = 6; + /* Get first weapon */ + /* Restrict choices to meele weapons */ + item_tester_hook = item_tester_hook_melee_weapon; + + q = "What is your first melee weapon? "; + s = "You have nothing to compare."; + if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) + { + object_wipe(orig_ptr); + return (FALSE); + } + + /* Get the item (in the pack) */ + if (item >= 0) + o1_ptr = &p_ptr->inventory[item]; + + /* Get second weapon */ + /* Restrict choices to melee weapons */ + item_tester_hook = item_tester_hook_melee_weapon; + + q = "What is your second melee weapon? "; + s = "You have nothing to compare."; + if (!get_item(&item2, q, s, (USE_EQUIP | USE_INVEN))) + { + object_wipe(orig_ptr); + return (FALSE); + } + + /* Get the item (in the pack) */ + if (item2 >= 0) o2_ptr = &p_ptr->inventory[item2]; + + put_str("Based on your current abilities, here is what your weapons will do", 4, 2); + + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + object_copy(i_ptr, o1_ptr); + calc_bonuses(TRUE); + + list_weapon(o1_ptr, i, 2); + compare_weapon_aux1(o1_ptr, 2, i + 8); + + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + if (item2 == INVEN_WIELD) + object_copy(i_ptr, orig_ptr); + else + object_copy(i_ptr, o2_ptr); + calc_bonuses(TRUE); + + list_weapon(o2_ptr, i, 40); + compare_weapon_aux1(o2_ptr, 40, i + 8); + + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + object_copy(i_ptr, orig_ptr); + calc_bonuses(TRUE); + + object_wipe(orig_ptr); + + put_str("(Only highest damage applies per monster. Special damage not cumulative)", 20, 0); + + return (TRUE); +} + + +/* + * general all-purpose fixing routine for items from building personnel + * sharpen arrows, repair armor, repair weapon + * -KMW- + */ +static bool fix_item(int istart, int iend, int ispecific, bool iac, + int ireward, bool set_reward) +{ + int i; + + int j = 9; + + int maxenchant = (p_ptr->lev / 5); + + object_type *o_ptr; + + char out_val[80], tmp_str[80]; + + bool repaired = FALSE; + +#if 0 + if (set_reward && p_ptr->rewards[ireward]) + { + msg_print("You already have been rewarded today."); + msg_print(NULL); + + return (FALSE); + } +#endif + clear_bldg(5, 18); + strnfmt(tmp_str, 80, " Based on your skill, we can improve up to +%d", maxenchant); + prt(tmp_str, 5, 0); + prt("Status", 7, 30); + + for (i = istart; i <= iend; i++) + { + o_ptr = &p_ptr->inventory[i]; + if (ispecific > 0) + { + if (o_ptr->tval != ispecific) + continue; + } + + if (o_ptr->tval) + { + object_desc(tmp_str, o_ptr, FALSE, 1); + + if ((o_ptr->name1 && (o_ptr->ident & 0x08))) + strnfmt(out_val, 80, "%-40s: beyond our skills!", tmp_str); + else if (o_ptr->name1) + strnfmt(out_val, 80, "%-40s: in fine condition", tmp_str); + else + { + if ((iac) && (o_ptr->to_a <= -3)) + { + strnfmt(out_val, 80, "%-40s: beyond repair, buy a new one", tmp_str); + } + else if ((iac) && (o_ptr->to_a < maxenchant)) + { + o_ptr->to_a++; + strnfmt(out_val, 80, "%-40s: polished -> (%d)", tmp_str, o_ptr->to_a); + repaired = TRUE; + } + else if ((!iac) && ((o_ptr->to_h <= -3) || (o_ptr->to_d <= -3))) + { + strnfmt(out_val, 80, "%-40s: beyond repair, buy a new one", tmp_str); + } + /* Sharpen a weapon */ + else if ((!iac) && ((o_ptr->to_h < maxenchant) || + (o_ptr->to_d < maxenchant))) + { + if (o_ptr->to_h < maxenchant) + o_ptr->to_h++; + if (o_ptr->to_d < maxenchant) + o_ptr->to_d++; + strnfmt(out_val, 80, "%-40s: sharpened -> (%d,%d)", tmp_str, + o_ptr->to_h, o_ptr->to_d); + repaired = TRUE; + } + else + strnfmt(out_val, 80, "%-40s: in fine condition", tmp_str); + } + prt(out_val, j++, 0); + } + } + + if (!repaired) + { + msg_print("You don't have anything appropriate."); + msg_print(NULL); + } + else + { +#if 0 + if (set_reward) + p_ptr->rewards[ireward] = TRUE; +#endif + msg_print("Press the spacebar to continue"); + msg_print(NULL); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + p_ptr->update |= (PU_BONUS); + } + clear_bldg(5, 18); + + return (repaired); +} + + +/* + * Research Item + */ +static bool research_item(void) +{ + clear_bldg(5, 18); + return (identify_fully()); +} + + +/* + * Show the current quest monster. + */ +static void show_quest_monster(void) +{ + monster_race* r_ptr = &r_info[bounties[0][0]]; + + + msg_format("Quest monster: %s. " + "Need to turn in %d corpse%s to receive reward.", + r_name + r_ptr->name, bounties[0][1], + (bounties[0][1] > 1 ? "s" : "")); + msg_print(NULL); +} + + +/* + * Show the current bounties. + */ +static void show_bounties(void) +{ + int i, j = 6; + + monster_race* r_ptr; + + char buff[80]; + + + clear_bldg(7, 18); + + c_prt(TERM_YELLOW, "Currently active bounties:", 4, 2); + + for (i = 1; i < MAX_BOUNTIES; i++, j++) + { + r_ptr = &r_info[bounties[i][0]]; + + strnfmt(buff, 80, "%-30s (%d gp)", r_name + r_ptr->name, bounties[i][1]); + + prt(buff, j, 2); + + if (j >= 17) + { + msg_print("Press space for more."); + msg_print(NULL); + + clear_bldg(7, 18); + j = 5; + } + } +} + + +/* + * Filter for corpses that currently have a bounty on them. + */ +static bool item_tester_hook_bounty(object_type* o_ptr) +{ + int i; + + + if (o_ptr->tval == TV_CORPSE) + { + for (i = 1; i < MAX_BOUNTIES; i++) + { + if (bounties[i][0] == o_ptr->pval2) return (TRUE); + } + } + + return (FALSE); +} + +/* Filter to match the quest monster's corpse. */ +static bool item_tester_hook_quest_monster(object_type* o_ptr) +{ + if ((o_ptr->tval == TV_CORPSE) && + (o_ptr->pval2 == bounties[0][0])) return (TRUE); + return (FALSE); +} + + +/* + * Return the boost in the corpse's value depending on how rare the body + * part is. + */ +static int corpse_value_boost(int sval) +{ + switch (sval) + { + case SV_CORPSE_HEAD: + case SV_CORPSE_SKULL: + { + return (1); + } + + /* Default to no boost. */ + default: + { + return (0); + } + } +} + +/* + * Sell a corpse, if there's currently a bounty on it. + */ +static void sell_corpses(void) +{ + object_type* o_ptr; + + int i, boost = 0; + + s16b value; + + int item; + + + /* Set the hook. */ + item_tester_hook = item_tester_hook_bounty; + + /* Select a corpse to sell. */ + if (!get_item(&item, "Sell which corpse", + "You have no corpses you can sell.", USE_INVEN)) return; + + o_ptr = &p_ptr->inventory[item]; + + /* Exotic body parts are worth more. */ + boost = corpse_value_boost(o_ptr->sval); + + /* Try to find a match. */ + for (i = 1; i < MAX_BOUNTIES; i++) + { + if (o_ptr->pval2 == bounties[i][0]) + { + value = bounties[i][1] + boost * (r_info[o_ptr->pval2].level); + + msg_format("Sold for %ld gold pieces.", value); + msg_print(NULL); + p_ptr->au += value; + + /* Increase the number of collected bounties */ + total_bounties++; + + inven_item_increase(item, -1); + inven_item_describe(item); + inven_item_optimize(item); + + return; + } + } + + msg_print("Sorry, but that monster does not have a bounty on it."); + msg_print(NULL); +} + + + +/* + * Hook for bounty monster selection. + */ +static bool mon_hook_bounty(int r_idx) +{ + monster_race* r_ptr = &r_info[r_idx]; + + + /* Reject uniques */ + if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE); + + /* Reject those who cannot leave anything */ + if (!(r_ptr->flags9 & RF9_DROP_CORPSE) && + !(r_ptr->flags9 & RF9_DROP_SKELETON)) return (FALSE); + + /* Reject pets */ + if (r_ptr->flags7 & RF7_PET) return (FALSE); + + /* Reject friendly creatures */ + if (r_ptr->flags7 & RF7_FRIENDLY) return (FALSE); + + /* The rest are acceptable */ + return (TRUE); +} + + +static void select_quest_monster(void) +{ + monster_race* r_ptr; + + int amt; + + + /* + * Set up the hooks -- no bounties on uniques or monsters + * with no corpses + */ + get_mon_num_hook = mon_hook_bounty; + get_mon_num_prep(); + + /* Set up the quest monster. */ + bounties[0][0] = get_mon_num(p_ptr->lev); + + r_ptr = &r_info[bounties[0][0]]; + + /* + * Select the number of monsters needed to kill. Groups and + * breeders require more + */ + amt = randnor(5, 3); + + if (amt < 2) amt = 2; + + if (r_ptr->flags1 & RF1_FRIEND) amt *= 3; amt /= 2; + if (r_ptr->flags1 & RF1_FRIENDS) amt *= 2; + if (r_ptr->flags4 & RF4_MULTIPLY) amt *= 3; + + if (r_ptr->flags7 & RF7_AQUATIC) amt /= 2; + + bounties[0][1] = amt; + + /* Undo the filters */ + get_mon_num_hook = NULL; + get_mon_num_prep(); +} + + + +/* + * Sell a corpse for a reward. + */ +static void sell_quest_monster(void) +{ + object_type* o_ptr; + + int item; + + + /* Set the hook. */ + item_tester_hook = item_tester_hook_quest_monster; + + /* Select a corpse to sell. */ + if (!get_item(&item, "Sell which corpse", + "You have no corpses you can sell.", USE_INVEN)) return; + + o_ptr = &p_ptr->inventory[item]; + + bounties[0][1] -= o_ptr->number; + + /* Completed the quest. */ + if (bounties[0][1] <= 0) + { + int m; + monster_race *r_ptr; + + cmsg_print(TERM_YELLOW, "You have completed your quest!"); + msg_print(NULL); + + /* Give full knowledge */ + + /* Hack -- Maximal info */ + r_ptr = &r_info[bounties[0][0]]; + + msg_print(format("Well done! As a reward I'll teach you everything " + "about the %s, (check your recall)", + r_name + r_ptr->name)); + + r_ptr->r_wake = r_ptr->r_ignore = MAX_UCHAR; + + /* Observe "maximal" attacks */ + for (m = 0; m < 4; m++) + { + /* Examine "actual" blows */ + if (r_ptr->blow[m].effect || r_ptr->blow[m].method) + { + /* Hack -- maximal observations */ + r_ptr->r_blows[m] = MAX_UCHAR; + } + } + + /* Hack -- maximal drops */ + r_ptr->r_drop_gold = r_ptr->r_drop_item = + (((r_ptr->flags1 & (RF1_DROP_4D2)) ? 8 : 0) + + ((r_ptr->flags1 & (RF1_DROP_3D2)) ? 6 : 0) + + ((r_ptr->flags1 & (RF1_DROP_2D2)) ? 4 : 0) + + ((r_ptr->flags1 & (RF1_DROP_1D2)) ? 2 : 0) + + ((r_ptr->flags1 & (RF1_DROP_90)) ? 1 : 0) + + ((r_ptr->flags1 & (RF1_DROP_60)) ? 1 : 0)); + + /* Hack -- but only "valid" drops */ + if (r_ptr->flags1 & (RF1_ONLY_GOLD)) r_ptr->r_drop_item = 0; + if (r_ptr->flags1 & (RF1_ONLY_ITEM)) r_ptr->r_drop_gold = 0; + + /* Hack -- observe many spells */ + r_ptr->r_cast_inate = MAX_UCHAR; + r_ptr->r_cast_spell = MAX_UCHAR; + + /* Hack -- know all the flags */ + r_ptr->r_flags1 = r_ptr->flags1; + r_ptr->r_flags2 = r_ptr->flags2; + r_ptr->r_flags3 = r_ptr->flags3; + r_ptr->r_flags4 = r_ptr->flags4; + r_ptr->r_flags5 = r_ptr->flags5; + r_ptr->r_flags6 = r_ptr->flags6; + r_ptr->r_flags4 = r_ptr->flags7; + r_ptr->r_flags5 = r_ptr->flags8; + r_ptr->r_flags6 = r_ptr->flags9; + + msg_print(NULL); + + select_quest_monster(); + + } + else + { + msg_format("Well done, only %d more to go.", bounties[0][1]); + msg_print(NULL); + } + + inven_item_increase(item, -1); + inven_item_describe(item); + inven_item_optimize(item); +} + + + +/* + * Fill the bounty list with monsters. + */ +void select_bounties(void) +{ + int i, j; + + + select_quest_monster(); + + /* + * Set up the hooks -- no bounties on uniques or monsters + * with no corpses + */ + get_mon_num_hook = mon_hook_bounty; + get_mon_num_prep(); + + for (i = 1; i < MAX_BOUNTIES; i++) + { + int lev = i * 5 + randnor(0, 2); + monster_race* r_ptr; + s16b r_idx; + s16b val; + + if (lev < 1) lev = 1; + + if (lev >= MAX_DEPTH) lev = MAX_DEPTH - 1; + + /* We don't want to duplicate entries in the list */ + while (TRUE) + { + r_idx = get_mon_num(lev); + + for (j = 0; j < i; j++) + { + if (bounties[j][0] == r_idx) continue; + } + + break; + } + + bounties[i][0] = r_idx; + + r_ptr = &r_info[r_idx]; + + val = r_ptr->mexp + r_ptr->level * 20 + randnor(0, r_ptr->level * 2); + + if (val < 1) val = 1; + + bounties[i][1] = val; + } + + /* Undo the filters. */ + get_mon_num_hook = NULL; + get_mon_num_prep(); +} + +/* + * Execute a building command + */ +bool bldg_process_command(store_type *s_ptr, int i) +{ + store_action_type *ba_ptr = &ba_info[st_info[s_ptr->st_idx].actions[i]]; + + int bact = ba_ptr->action; + + int bcost; + + bool paid = FALSE; + + bool set_reward = FALSE; + + bool recreate = FALSE; + + + if (is_state(s_ptr, STORE_LIKED)) + { + bcost = ba_ptr->costs[STORE_LIKED]; + } + else if (is_state(s_ptr, STORE_HATED)) + { + bcost = ba_ptr->costs[STORE_HATED]; + } + else + { + bcost = ba_ptr->costs[STORE_NORMAL]; + } + + /* action restrictions */ + if (((ba_ptr->action_restr == 1) && (is_state(s_ptr, STORE_LIKED))) || + ((ba_ptr->action_restr == 2) && (!is_state(s_ptr, STORE_LIKED)))) + { + msg_print("You have no right to choose that!"); + msg_print(NULL); + return FALSE; + } + + /* If player has loan and the time is out, few things work in stores */ + if (p_ptr->loan && !p_ptr->loan_time) + { + if ((bact != BACT_SELL) && (bact != BACT_VIEW_BOUNTIES) && + (bact != BACT_SELL_CORPSES) && + (bact != BACT_VIEW_QUEST_MON) && + (bact != BACT_SELL_QUEST_MON) && + (bact != BACT_EXAMINE) && (bact != BACT_STEAL) && + (bact != BACT_PAY_BACK_LOAN)) + { + msg_print("You are not allowed to do that until you have paid back your loan."); + msg_print(NULL); + return FALSE; + } + } + + /* check gold */ + if (bcost > p_ptr->au) + { + msg_print("You do not have the gold!"); + msg_print(NULL); + return FALSE; + } + + if (!bcost) set_reward = TRUE; + + switch (bact) + { + case BACT_RESEARCH_ITEM: + { + paid = research_item(); + break; + } + + case BACT_TOWN_HISTORY: + { + town_history(); + break; + } + + case BACT_RACE_LEGENDS: + { + race_legends(); + break; + } + +#if 0 + case BACT_GREET_KING: + { + castle_greet(); + break; + } + +#endif + + case BACT_QUEST1: + case BACT_QUEST2: + case BACT_QUEST3: + case BACT_QUEST4: + { + int y = 1, x = 1; + bool ok = FALSE; + + while ((x < cur_wid - 1) && !ok) + { + y = 1; + while ((y < cur_hgt - 1) && !ok) + { + /* Found the location of the quest info ? */ + if (bact - BACT_QUEST1 + FEAT_QUEST1 == cave[y][x].feat) + { + /* Stop the loop */ + ok = TRUE; + } + y++; + } + x++; + } + + if (ok) + { + recreate = castle_quest(y - 1, x - 1); + ; + } + else + { + msg_format("ERROR: no quest info feature found: %d", bact - BACT_QUEST1 + FEAT_QUEST1); + } + break; + } + + case BACT_KING_LEGENDS: + case BACT_ARENA_LEGENDS: + case BACT_LEGENDS: + { + show_highclass(building_loc); + break; + } + + case BACT_POSTER: + case BACT_ARENA_RULES: + case BACT_ARENA: + { + arena_comm(bact); + break; + } + + case BACT_IN_BETWEEN: + case BACT_CRAPS: + case BACT_SPIN_WHEEL: + case BACT_DICE_SLOTS: + case BACT_GAMBLE_RULES: + { + gamble_comm(bact); + break; + } + + case BACT_REST: + case BACT_RUMORS: + case BACT_FOOD: + { + paid = inn_comm(bact); + break; + } + + case BACT_RESEARCH_MONSTER: + { + paid = !research_mon(); + break; + } + + case BACT_COMPARE_WEAPONS: + { + paid = compare_weapons(); + break; + } + +#if 0 + + case BACT_GREET: + { + greet_char(); + break; + } + +#endif + + case BACT_ENCHANT_WEAPON: + { + paid = fix_item(INVEN_WIELD, INVEN_WIELD, 0, FALSE, + BACT_ENCHANT_WEAPON, set_reward); + break; + } + + case BACT_ENCHANT_ARMOR: + { + paid = fix_item(INVEN_BODY, INVEN_FEET, 0, TRUE, + BACT_ENCHANT_ARMOR, set_reward); + break; + } + + /* needs work */ + case BACT_RECHARGE: + { + if (recharge(80)) paid = TRUE; + break; + } + + /* needs work */ + case BACT_IDENTS: + { + identify_pack(); + msg_print("Your possessions have been identified."); + msg_print(NULL); + paid = TRUE; + break; + } + + /* needs work */ + case BACT_STAR_HEAL: + { + hp_player(200); + set_poisoned(0); + set_blind(0); + set_confused(0); + set_cut(0); + set_stun(0); + if (p_ptr->black_breath) + { + msg_print("The hold of the Black Breath on you is broken!"); + p_ptr->black_breath = FALSE; + } + paid = TRUE; + break; + } + + /* needs work */ + case BACT_HEALING: + { + hp_player(200); + set_poisoned(0); + set_blind(0); + set_confused(0); + set_cut(0); + set_stun(0); + paid = TRUE; + break; + } + + /* needs work */ + case BACT_RESTORE: + { + if (do_res_stat(A_STR, TRUE)) paid = TRUE; + if (do_res_stat(A_INT, TRUE)) paid = TRUE; + if (do_res_stat(A_WIS, TRUE)) paid = TRUE; + if (do_res_stat(A_DEX, TRUE)) paid = TRUE; + if (do_res_stat(A_CON, TRUE)) paid = TRUE; + if (do_res_stat(A_CHR, TRUE)) paid = TRUE; + break; + } + + /* set timed reward flag */ + case BACT_GOLD: + { +#if 0 + if (!p_ptr->rewards[BACT_GOLD]) + { + share_gold(); + p_ptr->rewards[BACT_GOLD] = TRUE; + } + else + { + msg_print("You just had your daily allowance!"); + msg_print(NULL); + } +#endif + break; + } + + case BACT_ENCHANT_ARROWS: + { + paid = fix_item(0, INVEN_WIELD, TV_ARROW, FALSE, + BACT_ENCHANT_ARROWS, set_reward); + break; + } + + case BACT_ENCHANT_BOW: + { + paid = fix_item(INVEN_BOW, INVEN_BOW, TV_BOW, FALSE, + BACT_ENCHANT_BOW, set_reward); + break; + } + + case BACT_RECALL: + { + p_ptr->word_recall = 1; + msg_print("The air about you becomes charged..."); + paid = TRUE; + break; + } + + case BACT_TELEPORT_LEVEL: + { + if (reset_recall(FALSE)) + { + p_ptr->word_recall = 1; + msg_print("The air about you becomes charged..."); + paid = TRUE; + } + break; + } + + case BACT_MIMIC_NORMAL: + { + set_mimic(0, 0, 0); + paid = TRUE; + break; + } + + case BACT_VIEW_BOUNTIES: + { + show_bounties(); + break; + } + + case BACT_VIEW_QUEST_MON: + { + show_quest_monster(); + break; + } + + case BACT_SELL_QUEST_MON: + { + sell_quest_monster(); + break; + } + + case BACT_SELL_CORPSES: + { + sell_corpses(); + break; + } + + case BACT_DIVINATION: + { + int i, count = 0; + bool something = FALSE; + + while (count < 1000) + { + count++; + i = rand_int(MAX_FATES); + if (!fates[i].fate) continue; + if (fates[i].know) continue; + msg_print("You know a little more of your fate."); + + fates[i].know = TRUE; + something = TRUE; + break; + } + + if (!something) msg_print("Well, you have no fate, but I'll keep your money anyway!"); + + paid = TRUE; + break; + + } + + case BACT_BUY: + { + store_purchase(); + break; + } + + case BACT_SELL: + { + store_sell(); + break; + } + + case BACT_EXAMINE: + { + store_examine(); + break; + } + + case BACT_STEAL: + { + store_stole(); + break; + } + + case BACT_REQUEST_ITEM: + { + store_request_item(); + paid = TRUE; + break; + } + + case BACT_GET_LOAN: + { + s32b i, req; + char prompt[80]; + + if (p_ptr->loan) + { + msg_print("You already have a loan!"); + break; + } + + req = p_ptr->au; + + for (i = 0; i < INVEN_TOTAL; i++) + req += object_value_real(&p_ptr->inventory[i]); + + if (req > 100000) req = 100000; + if ((req + p_ptr->au) > PY_MAX_GOLD) req = PY_MAX_GOLD - p_ptr->au; + + strnfmt(prompt, sizeof (prompt), + "How much would you like to get (0-%ld) ?", req); + + req = get_quantity(prompt, req); + + if (req) + { + p_ptr->loan += req; + p_ptr->au += req; + p_ptr->loan_time += req; + + msg_format("You receive %i gold pieces", req); + + paid = TRUE; + } + else + msg_format("You did not request any money!"); + + break; + } + + case BACT_PAY_BACK_LOAN: + { + s32b req; + char prompt[80]; + + if (p_ptr->loan) + { + msg_format("You have nothing to payback!"); + break; + } + + msg_format("You have a loan of %i.", p_ptr->loan); + + req = ((p_ptr->loan + bcost) > p_ptr->au) ? p_ptr->au - bcost : p_ptr->loan; + + strnfmt(prompt, sizeof (prompt), + "How much would you like to pay back (0-%ld) ?", req); + + req = get_quantity(prompt, req); + + p_ptr->loan -= req; + p_ptr->au -= req; + + if (!p_ptr->loan) p_ptr->loan_time = 0; + + msg_format("You pay back %i gold pieces", req); + paid = TRUE; + break; + } + + default: + { + if (process_hooks_ret(HOOK_BUILDING_ACTION, "dd", "(d)", bact)) + { + paid = process_hooks_return[0].num; + recreate = process_hooks_return[1].num; + } + break; + } + } + + if (paid) + { + p_ptr->au -= bcost; + + /* Display the current gold */ + store_prt_gold(); + } + + return (recreate); +} + + +/* + * Enter quest level + */ +void enter_quest(void) +{ + if (!(cave[p_ptr->py][p_ptr->px].feat == FEAT_QUEST_ENTER)) + { + msg_print("You see no quest level here."); + return; + } + else + { + /* Player enters a new quest */ + p_ptr->oldpy = p_ptr->py; + p_ptr->oldpx = p_ptr->px; + + leaving_quest = p_ptr->inside_quest; + + p_ptr->inside_quest = cave[p_ptr->py][p_ptr->px].special; + dun_level = 1; + p_ptr->leaving = TRUE; + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + } +} + + +/* + * Do building commands + */ +void do_cmd_bldg(void) +{ + int i, which, x = p_ptr->px, y = p_ptr->py; + + char command; + + bool validcmd; + + store_type *s_ptr; + + store_info_type *st_ptr; + + store_action_type *ba_ptr; + + + if (cave[p_ptr->py][p_ptr->px].feat != FEAT_SHOP) + { + msg_print("You see no building here."); + return; + } + + which = cave[p_ptr->py][p_ptr->px].special; + building_loc = which; + + s_ptr = &town_info[p_ptr->town_num].store[which]; + st_ptr = &st_info[which]; + + p_ptr->oldpy = p_ptr->py; + p_ptr->oldpx = p_ptr->px; + + /* Forget the lite */ + /* forget_lite(); */ + + /* Forget the view */ + forget_view(); + + /* Hack -- Increase "icky" depth */ + character_icky++; + + command_arg = 0; + command_rep = 0; + command_new = 0; + + show_building(s_ptr); + leave_bldg = FALSE; + + while (!leave_bldg) + { + validcmd = FALSE; + prt("", 1, 0); + command = inkey(); + + if (command == ESCAPE) + { + leave_bldg = TRUE; + p_ptr->inside_arena = FALSE; + break; + } + + for (i = 0; i < 6; i++) + { + ba_ptr = &ba_info[st_info->actions[i]]; + + if (ba_ptr->letter) + { + if (ba_ptr->letter == command) + { + validcmd = TRUE; + break; + } + } + if (ba_ptr->letter_aux) + { + if (ba_ptr->letter_aux == command) + { + validcmd = TRUE; + break; + } + } + } + + if (validcmd) + bldg_process_command(s_ptr, i); + + /* Notice stuff */ + notice_stuff(); + + /* Handle stuff */ + handle_stuff(); + } + + /* Flush messages XXX XXX XXX */ + msg_print(NULL); + + /* Reinit wilderness to activate quests ... */ + wilderness_gen(TRUE); + p_ptr->py = y; + p_ptr->px = x; + + /* Hack -- Decrease "icky" depth */ + character_icky--; + + /* Clear the screen */ + Term_clear(); + + /* Update the visuals */ + p_ptr->update |= (PU_VIEW | PU_MON_LITE | PU_MONSTERS | PU_BONUS); + + /* Redraw entire screen */ + p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); +} + + |