Mercurial > hg > early-roguelike
diff xrogue/things.c @ 133:e6179860cb76
Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 21 Apr 2015 08:55:20 -0400 |
parents | |
children | ce0cf824c192 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xrogue/things.c Tue Apr 21 08:55:20 2015 -0400 @@ -0,0 +1,951 @@ +/* + things.c - functions for dealing with things like potions and scrolls + + XRogue: Expeditions into the Dungeons of Doom + Copyright (C) 1991 Robert Pietkivitch + All rights reserved. + + Based on "Advanced Rogue" + Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T + All rights reserved. + + Based on "Rogue: Exploring the Dungeons of Doom" + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + See the file LICENSE.TXT for full copyright and licensing information. +*/ + +#include <curses.h> +#include <ctype.h> +#include "rogue.h" + +/* + * print out the number of charges on a stick + */ + +char * +charge_str(obj) +register struct object *obj; +{ + static char buf[20]; + + if (!(obj->o_flags & ISKNOW)) + buf[0] = '\0'; + else if (terse) + sprintf(buf, " [%d]", obj->o_charges); + else + sprintf(buf, " [%d charges]", obj->o_charges); + return buf; +} + +/* + * inv_name: + * return the name of something as it would appear in an + * inventory. + */ + +char * +inv_name(obj, drop) +register struct object *obj; +bool drop; +{ + register char *pb; + + pb = prbuf; + pb[0] = '\0'; + switch(obj->o_type) { + case SCROLL: + if (obj->o_count == 1) + sprintf(pb, "A %sscroll ", blesscurse(obj->o_flags)); + else + sprintf(pb, "%d %sscrolls ", + obj->o_count, blesscurse(obj->o_flags)); + pb = &pb[strlen(pb)]; + if (s_know[obj->o_which] || (obj->o_flags & ISPOST)) + sprintf(pb, "of %s", s_magic[obj->o_which].mi_name); + else if (s_guess[obj->o_which]) + sprintf(pb, "named %s", s_guess[obj->o_which]); + else + sprintf(pb, "titled '%s'", s_names[obj->o_which]); + when POTION: + if (obj->o_count == 1) + sprintf(pb, "A %spotion ", blesscurse(obj->o_flags)); + else + sprintf(pb, "%d %spotions ", + obj->o_count, blesscurse(obj->o_flags)); + pb = &pb[strlen(pb)]; + if (p_know[obj->o_which]) + sprintf(pb, "of %s (%s)", p_magic[obj->o_which].mi_name, + p_kind(obj)); + else if (obj->o_flags & ISPOST) + sprintf(pb, "of %s", p_magic[obj->o_which].mi_name); + else if (p_guess[obj->o_which]) + sprintf(pb, "named %s (%s)", p_guess[obj->o_which], + p_colors[obj->o_which]); + else { + pb = prbuf; + if (obj->o_count == 1) + sprintf(pb, "A%s %s potion", + vowelstr(p_colors[obj->o_which]), + p_colors[obj->o_which]); + else + sprintf(pb, "%d %s potions", + obj->o_count, p_colors[obj->o_which]); + } + when FOOD: + if (obj->o_count == 1) + sprintf(pb, "A%s %s", vowelstr(foods[obj->o_which].mi_name), + foods[obj->o_which].mi_name); + else + sprintf(pb, "%d %ss", obj->o_count,foods[obj->o_which].mi_name); + when WEAPON: + if (obj->o_count > 1) + sprintf(pb, "%d ", obj->o_count); + else + strcpy(pb, "A "); + pb = &pb[strlen(pb)]; + if (obj->o_flags & ISKNOW) { + strcat(pb, num(obj->o_hplus, obj->o_dplus)); + strcat (pb, " "); + } + strcat(pb, weaps[obj->o_which].w_name); + if (obj->o_count > 1) + strcat(pb, "s"); + if (obj == cur_weapon) + strcat(pb, " (weapon in hand)"); + if (obj->o_flags & ISPOISON) + strcat(pb, " {Poisoned}"); + when ARMOR: + if (obj->o_flags & ISKNOW) { + strcat(pb, num(armors[obj->o_which].a_class - obj->o_ac, 0)); + strcat(pb, " "); + } + strcat(pb, armors[obj->o_which].a_name); + if (obj == cur_armor) + strcat(pb, " (being worn)"); + when STICK: + sprintf(pb, "A %s%s ", + blesscurse(obj->o_flags), ws_type[obj->o_which]); + pb = &pb[strlen(pb)]; + if (ws_know[obj->o_which] || obj->o_flags & ISKNOW) + sprintf(pb, "of %s%s (%s)", ws_magic[obj->o_which].mi_name, + charge_str(obj), ws_made[obj->o_which]); + else if (obj->o_flags & ISPOST) + sprintf(pb, "of %s", ws_magic[obj->o_which].mi_name); + else if (ws_guess[obj->o_which]) + sprintf(pb, "named %s (%s)", ws_guess[obj->o_which], + ws_made[obj->o_which]); + else { + pb = prbuf; + sprintf(pb, "A %s %s", ws_made[obj->o_which], + ws_type[obj->o_which]); + } + if (obj == cur_weapon) + strcat(prbuf, " (weapon in hand)"); + when RING: + if (r_know[obj->o_which] || obj->o_flags & ISKNOW) + sprintf(pb, "A%s ring of %s (%s)", ring_num(obj), + r_magic[obj->o_which].mi_name, r_stones[obj->o_which]); + else if (obj->o_flags & ISPOST) + sprintf(pb, "A ring of %s", r_magic[obj->o_which].mi_name); + else if (r_guess[obj->o_which]) + sprintf(pb, "A ring named %s (%s)", + r_guess[obj->o_which], r_stones[obj->o_which]); + else + sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]), + r_stones[obj->o_which]); + if (obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] || + obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4]) + strcat(pb, " (on left hand)"); + if (obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] || + obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4]) + strcat(pb, " (on right hand)"); + when RELIC: + if (obj->o_flags & ISKNOW) + switch(obj->o_which) { + case QUILL_NAGROM: + sprintf(pb, "%s%s", rel_magic[obj->o_which].mi_name, + charge_str(obj)); + otherwise: + strcpy(pb, rel_magic[obj->o_which].mi_name); + } + else switch(obj->o_which) { + case MUSTY_DAGGER: + strcpy(pb, "Two very fine daggers marked MDDE"); + when EMORI_CLOAK: + strcpy(pb, "A silk cloak"); + when HEIL_ANKH: + strcpy(pb, "A golden ankh"); + when MING_STAFF: + strcpy(pb, "A finely carved staff"); + when ORCUS_WAND: + strcpy(pb, "A sparkling ivory wand"); + when ASMO_ROD: + strcpy(pb, "A glistening ebony rod"); + when YENDOR_AMULET: + strcpy(pb, "A silver amulet"); + when STONEBONES_AMULET: + strcpy(pb, "A stone amulet"); + when BRIAN_MANDOLIN: + strcpy(pb, "A gleaming mandolin"); + when HRUGGEK_MSTAR: + strcpy(pb, "A silvery morning star"); + when AXE_AKLAD: + strcpy(pb, "A jewel encrusted axe"); + when QUILL_NAGROM: + strcpy(pb, "A bright white feather"); + when GERYON_HORN: + strcpy(pb, "A jet black horn"); + when YEENOGHU_FLAIL: + strcpy(pb, "A shimmering flail"); + when SURTUR_RING: + strcpy(pb, "A fiery red ring"); + when ALTERAN_CARD: + strcpy(pb, "A rectangular piece of wood"); + otherwise: + strcpy(pb, "A wholly magical item"); + } + + /* Take care of wielding and wearing */ + switch (obj->o_which) { + case EMORI_CLOAK: + if (cur_armor == NULL && cur_misc[WEAR_CLOAK] == NULL) + strcat(pb, " (being worn)"); + if (obj->o_charges) + strcat(pb, " [charged]"); + else + strcat(pb, " [discharged]"); + when HEIL_ANKH: + if (cur_relic[HEIL_ANKH]) strcat(pb, " (in palm)"); + when EYE_VECNA: + if (cur_relic[EYE_VECNA]) strcat(pb, " (in forehead)"); + when STONEBONES_AMULET: + if (cur_relic[STONEBONES_AMULET]) + strcat(pb, " (in chest)"); + when YENDOR_AMULET: + if (cur_relic[YENDOR_AMULET]) + strcat(pb, " (in chest)"); + when MUSTY_DAGGER: + case HRUGGEK_MSTAR: + case AXE_AKLAD: + case YEENOGHU_FLAIL: + case MING_STAFF: + case ASMO_ROD: + case ORCUS_WAND: + if (cur_weapon == obj) strcat(pb, " (weapon in hand)"); + when SURTUR_RING: + if (cur_relic[SURTUR_RING]) + strcat(pb, " (in nose)"); + } + when MM: + if (m_know[obj->o_which]) + { + misc_name(pb,obj); + } + else { + switch (obj->o_which) { + case MM_JUG: + case MM_BEAKER: + case MM_KEOGHTOM: + strcpy(pb, "A crystalline jar"); + when MM_BOOK: + case MM_SKILLS: + strcpy(pb, "A dusty book"); + when MM_ELF_BOOTS: + case MM_DANCE: + strcpy(pb, "A pair of old boots"); + when MM_BRACERS: + strcpy(pb, "A set of bracers"); + when MM_OPEN: + case MM_HUNGER: + strcpy(pb, "A mysterious chime"); + when MM_DISP: + case MM_R_POWERLESS: + case MM_PROTECT: + strcpy(pb, "A dark looking cloak"); + when MM_DRUMS: + strcpy(pb, "A drum set"); + when MM_DISAPPEAR: + case MM_CHOKE: + strcpy(pb, "A small pouch of dust"); + when MM_G_DEXTERITY: + case MM_G_OGRE: + case MM_FUMBLE: + strcpy(pb, "A set of gauntlets"); + when MM_ADAPTION: + case MM_JEWEL: + case MM_STRANGLE: + strcpy(pb, "A little necklace"); + when MM_CRYSTAL: + strcpy(pb, "An unusual looking rock"); + otherwise: + strcpy(pb, "A magical item"); + } + if (m_guess[obj->o_which]) { + strcat(pb, " named: "); + strcat(pb, m_guess[obj->o_which]); + } + } + if (obj == cur_misc[WEAR_BOOTS] || + obj == cur_misc[WEAR_BRACERS] || + obj == cur_misc[WEAR_CLOAK] || + obj == cur_misc[WEAR_GAUNTLET] || + obj == cur_misc[WEAR_NECKLACE] || + obj == cur_misc[WEAR_JEWEL]) + strcat(pb, " (being worn)"); + when GOLD: + sprintf(pb, "%d Pieces of Gold", obj->o_count); + otherwise: + debug("Picked up something funny"); + sprintf(pb, "Something totally bizarre %s", unctrl(obj->o_type)); + wait_for(' '); + } + + /* Is it marked? */ + if (obj->o_mark[0]) { + pb = &pb[strlen(pb)]; + sprintf(pb, " <%s>", obj->o_mark); + } + + if (obj->o_flags & ISPROT) + strcat(pb, " [protected]"); + if (drop && isupper(prbuf[0])) + prbuf[0] = tolower(prbuf[0]); + else if (!drop && islower(*prbuf)) + *prbuf = toupper(*prbuf); + if (!drop) + strcat(pb, "."); + /* + * Truncate if long. Use cols-4 to offset the "pack letter" of a normal + * inventory listing. + */ + prbuf[cols-4] = '\0'; + return prbuf; +} + +/* + * weap_name: + * Return the name of a weapon. + */ + +char * +weap_name(obj) +register struct object *obj; +{ + switch (obj->o_type) { + case WEAPON: + return(weaps[obj->o_which].w_name); + when MISSILE: + return(ws_magic[obj->o_which].mi_name); + when RELIC: + switch (obj->o_which) { + case MUSTY_DAGGER: + return("daggers"); + when YEENOGHU_FLAIL: + return("flail"); + when AXE_AKLAD: + return("axe"); + when HRUGGEK_MSTAR: + return("morning star"); + when MING_STAFF: + return("staff"); + when ORCUS_WAND: + return("wand"); + when ASMO_ROD: + return("rod"); + } + } + return("weapon"); +} + +/* + * drop: + * put something down + */ + +drop(item) +struct linked_list *item; +{ + register char ch = 0; + register struct linked_list *obj, *nobj; + register struct object *op; + + if (item == NULL) { + /* We charge 2 movement times to drop something */ + if (player.t_action == C_DROP && player.t_using != NULL) { + obj = player.t_using; + player.t_using = NULL; + player.t_action = A_NIL; + } + + /* t_action == C_DROP always when called from command() */ + else { + if ((obj = get_item(pack, "drop", ALL, FALSE, FALSE)) == NULL) { + player.t_action = A_NIL; + player.t_using = NULL; + return(FALSE); + } + if (player.t_action == C_DROP) { + player.t_using = obj; + player.t_no_move = 2 * movement(&player); + return(FALSE); /* We'll come back after we've waited */ + } + } + + switch(ch = mvwinch(stdscr, hero.y, hero.x)) { + case PASSAGE: + case SCROLL: + case POTION: + case WEAPON: + case FLOOR: + case STICK: + case ARMOR: + case POOL: + case RELIC: + case GOLD: + case FOOD: + case RING: + case MM: + break; + default: + msg("You can't leave it here"); + return(FALSE); + } + } + else { + obj = item; + } + op = OBJPTR(obj); + if (!dropcheck(op)) + return(FALSE); + + /* + * If it is a scare monster scroll, curse it + */ + if (op->o_type == SCROLL && op->o_which == S_SCARE) { + if (op->o_flags & ISBLESSED) + op->o_flags &= ~ISBLESSED; + else op->o_flags |= ISCURSED; + } + + /* + * Take it out of the pack + */ + if (op->o_count >= 2 && op->o_group == 0) + { + nobj = new_item(sizeof *op); + op->o_count--; + op = OBJPTR(nobj); + *op = *(OBJPTR(obj)); + op->o_count = 1; + obj = nobj; + } + else { + detach(pack, obj); + inpack--; + } + if(ch == POOL) { + msg("Gloop... Your %s sinks out of sight. ",inv_name(op,TRUE)); + o_discard(obj); + } + else if (levtype == POSTLEV) { + op->o_pos = hero; /* same place as hero */ + fall(obj,FALSE); + if (item == NULL) /* if item wasn't sold */ + msg("Thanks for your donation to the Fiend's flea market."); + } + else { + /* + * Link it into the level object list + */ + attach(lvl_obj, obj); + mvaddch(hero.y, hero.x, op->o_type); + op->o_pos = hero; + msg("Dropped %s", inv_name(op, TRUE)); + } + updpack(FALSE, &player); + return (TRUE); +} + +/* + * do special checks for dropping or unweilding|unwearing|unringing + */ + +dropcheck(op) +register struct object *op; +{ + int save_max; + + if (op == NULL) + return TRUE; + if (levtype == POSTLEV) { + if ((op->o_flags & ISCURSED) && (op->o_flags & ISKNOW)) { + msg("The trader does not accept shoddy merchandise."); + return(FALSE); + } + } + + /* Player will not drop a relic */ + if (op->o_type == RELIC) { + /* + * There is a 1% cumulative chance per relic that trying to get + * rid of it will cause the relic to turn on the player. + */ + if (rnd(150) < cur_relic[op->o_which]++) { + msg("The artifact turns on you! "); + msg("It crushes your mind!!! --More--"); + pstats.s_hpt = -1; + wait_for (' '); + death(D_RELIC); + } + else { + if (terse) msg("You can't release it."); + else msg("You cannot bring yourself to release it."); + return FALSE; + } + } + + /* If we aren't wearing it, we can drop it */ + if (!is_current(op)) return TRUE; + + /* At this point, we know we are wearing the item */ + if (op->o_flags & ISCURSED) { + msg("You can't. It appears to be cursed."); + return FALSE; + } + if (op->o_type == RING && cur_misc[WEAR_GAUNTLET] != NULL) { + msg ("You have to remove your gauntlets first!"); + return FALSE; + } + cur_null(op); /* set current to NULL */ + if (op->o_type == RING) { + switch (op->o_which) { + case R_ADDSTR: save_max = max_stats.s_str; + chg_str(-op->o_ac); + max_stats.s_str = save_max; + when R_ADDHIT: pstats.s_dext -= op->o_ac; + when R_ADDINTEL: pstats.s_intel -= op->o_ac; + when R_ADDWISDOM: pstats.s_wisdom -= op->o_ac; + when R_SEEINVIS: if (!ISWEARING(R_SEEINVIS) && + find_slot(unsee) == 0) { + turn_off(player, CANSEE); + msg("The tingling feeling leaves your eyes. "); + } + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + when R_WARMTH: if (!ISWEARING(R_WARMTH) && !find_slot(nocold)) + turn_off(player, NOCOLD); + when R_FIRE: if (!ISWEARING(R_FIRE) && + !cur_relic[SURTUR_RING] && + !find_slot(nofire)) + turn_off(player, NOFIRE); + when R_LIGHT: { + if(roomin(&hero) != NULL) { + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + } + when R_SEARCH: kill_daemon(ring_search); + when R_TELEPORT: kill_daemon(ring_teleport); + } + } + else if (op->o_type == MM) { + switch (op->o_which) { + case MM_ADAPTION: + turn_off(player, NOGAS); + turn_off(player, NOACID); + + when MM_STRANGLE: + msg("You can breathe again.....whew!"); + kill_daemon(strangle); + + when MM_DANCE: + turn_off(player, ISDANCE); + msg ("Your feet take a break.....whew!"); + + when MM_FUMBLE: + kill_daemon(fumble); + + when MM_G_OGRE: + case MM_G_DEXTERITY: + save_max = max_stats.s_str; + chg_str(-op->o_ac); + max_stats.s_str = save_max; + } + } + return TRUE; +} + +/* + * return a new thing + */ + +struct linked_list * +new_thing(thing_type, allow_curse) +int thing_type; +bool allow_curse; +{ + register struct linked_list *item; + register struct object *cur; + register int j; + register int blesschance, cursechance; + + item = new_item(sizeof *cur); + cur = OBJPTR(item); + cur->o_hplus = cur->o_dplus = 0; + strcpy(cur->o_damage,"0d0"); + strcpy(cur->o_hurldmg,"0d0"); + cur->o_ac = 0; + cur->o_count = 1; + cur->o_group = 0; + cur->contents = NULL; + cur->o_flags = 0;