Example #1
0
/*
 * Determine if a given grid may be "walked"
 */
static bool do_cmd_walk_test(int y, int x)
{
	/* Allow attack on visible monsters if unafraid */
	if ((cave_m_idx[y][x] > 0) && (mon_list[cave_m_idx[y][x]].ml))
	{
		/* Handle player fear */
		if(p_ptr->state.afraid)
		{
			/* Extract monster name (or "it") */
			char m_name[80];
			monster_type *m_ptr;

			m_ptr = &mon_list[cave_m_idx[y][x]];
			monster_desc(m_name, sizeof(m_name), m_ptr, 0);

			/* Message */
			message_format(MSG_AFRAID, 0,
				"You are too afraid to attack %s!", m_name);

			/* Nope */
			return (FALSE);
		}
		
		return (TRUE);
	}

	/* If we don't know the grid, allow attempts to walk into it */
	if (!(cave_info[y][x] & CAVE_MARK))
		return TRUE;

	/* Require open space or PASS_WALL/KILL_WALL flag -Simon */
	if (!cave_floor_bold(y, x) && !(player_has(PF_PASS_WALL) || player_has(PF_KILL_WALL)))
	{			
		/* Rubble */
		if (cave_feat[y][x] == FEAT_RUBBLE)
			message(MSG_HITWALL, 0, "There is a pile of rubble in the way!");
		
		/* Door */
		else if (cave_feat[y][x] < FEAT_SECRET)
			return TRUE;

		/* Wall */
		else
			message(MSG_HITWALL, 0, "There is a wall in the way!");

		/* Cancel repeat */
		disturb(0, 0);

		/* Nope */
		return (FALSE);
	}

	/* Okay */
	return (TRUE);
}
Example #2
0
/**
 * Browse the given book.
 */
void textui_spell_browse(void)
{
	int item;

	char q[80];
	char s[80];

	if (mp_ptr->spell_realm == REALM_NONE) {
		if (player_has(PF_PROBE))
			warrior_probe_desc();
		else
			msg("You cannot read books!");
		return;
	}

	strnfmt(q, sizeof(q), "Browse which %s?",
			magic_desc[mp_ptr->spell_realm][BOOK_NOUN]);
	strnfmt(s, sizeof(s), " You have no %ss that you can read.",
			magic_desc[mp_ptr->spell_realm][BOOK_LACK]);

	item_tester_hook = obj_can_browse;
	if (!get_item(&item, q, s, CMD_BROWSE_SPELL,
				  (USE_INVEN | USE_FLOOR | IS_HARMLESS)))
		return;

	/* Track the object kind */
	track_object(item);
	handle_stuff(p_ptr);

	textui_book_browse(object_from_item_idx(item));
}
Example #3
0
/* Is the player capable of casting a spell? */
bool player_can_cast(void)
{
	/* Races without Horns or Hands cannot cast arcane spells */
	if((!rp_ptr->num_rings) && p_ptr->cumber_glove) {
	    msg("You need a horn or hands to cast arcane spells.");
	    return FALSE;
	}
	
    if (player_has(PF_PROBE)) {
		if (p_ptr->lev < 35) {
			msg("You do not know how to probe monsters yet.");
			return FALSE;
		} else if ((p_ptr->timed[TMD_CONFUSED])
				   || (p_ptr->timed[TMD_IMAGE])) {
			msg("You feel awfully confused.");
			return FALSE;
		}
	}

	if (p_ptr->timed[TMD_BLIND] || no_light()) {
		msg("You cannot see!");
		return FALSE;
	}

	if (p_ptr->timed[TMD_CONFUSED]) {
		msg("You are too confused!");
		return FALSE;
	}

	return TRUE;
}
Example #4
0
/* Is the player capable of casting a spell? */
bool player_can_cast(void)
{
    if (player_has(PF_PROBE)) {
        if (p_ptr->lev < 35) {
            msg("You do not know how to probe monsters yet.");
            return FALSE;
        } else if ((p_ptr->timed[TMD_CONFUSED])
                   || (p_ptr->timed[TMD_IMAGE])) {
            msg("You feel awfully confused.");
            return FALSE;
        }
    }

    if (p_ptr->timed[TMD_BLIND] || no_light()) {
        msg("You cannot see!");
        return FALSE;
    }

    if (p_ptr->timed[TMD_CONFUSED]) {
        msg("You are too confused!");
        return FALSE;
    }

    return TRUE;
}
Example #5
0
/**
 * Display the options and redraw afterward.
 */
extern void do_cmd_reshape(void)
{
    if ((!SCHANGE) && (player_has(PF_BEARSKIN))) {
	bear_shape();
    } else
	unchange();
}
Example #6
0
static int obj_cond(int op, int obj, int arg)
{
  switch(op) {
    case 0:cret(in_scope(obj));  /* Present-- 
				      Do we want to use visible here?? */
    case 1:cret(is_within(obj,1000,1));  /* IsWearing */
    case 2:cret(is_within(obj,1,1)); 
        /* if (PURE_WEAR)  return (it_loc(obj)==1); else */
    case 3:cret(it_loc(obj)==0);  /* Nowhere */
    case 4:cret(it_loc(obj)!=0);
    case 5:cret(!player_has(obj) && in_scope(obj));
    case 6:cret(it_loc(obj)==arg);
    case 7:cret(it_on(obj));
    case 8:cret(!it_on(obj));
    case 9:cret(it_open(obj));
    case 10:cret(!it_open(obj));
    case 11:cretn(obj,locked);
    case 12:cret(!tnoun(obj) || !noun[obj-first_noun].locked);
    case 13:cretn(obj,edible);
    case 14:cretn(obj,drinkable);
    case 15:cretn(obj,poisonous);
    case 16:cretn(obj,movable);
    default:
      writeln("INTERNAL ERROR: Bad obj_cond value.");
      return 2;
  }
}
Example #7
0
/**
 * Display list of monster traps.
 */
bool trap_menu(void)
{
    menu_type menu;
    menu_iter menu_f = { trap_tag, 0, trap_display, trap_action, 0 };
    region area = { 15, 1, 48, -1 };
    ui_event_data evt = { EVT_NONE, 0, 0, 0, 0 };

    size_t i, num = 0;

    u16b *choice;

    /* See how many traps available */
    if (player_has(PF_EXTRA_TRAP))
        num = 1 + (p_ptr->lev / 4);
    else
        num = 1 + (p_ptr->lev / 6);

    /* Create the array */
    choice = C_ZNEW(num, u16b);

    /* Obvious */
    for (i = 0; i < num; i++) {
        choice[i] = i;
    }

    /* Clear space */
    area.page_rows = num + 2;

    /* Return here if there are no traps */
    if (!num) {
        FREE(choice);
        return FALSE;
    }


    /* Save the screen and clear it */
    screen_save();

    /* Help text */

    /* Set up the menu */
    WIPE(&menu, menu);
    menu_init(&menu, MN_SKIN_SCROLL, &menu_f);
    menu.title = "Choose an advanced monster trap (ESC to cancel):";
    menu_setpriv(&menu, num, choice);
    menu_layout(&menu, &area);
    prt("", area.row + 1, area.col);

    /* Select an entry */
    evt = menu_select(&menu, 0);

    /* Free memory */
    FREE(choice);

    /* Load screen */
    screen_load();
    return (evt.type != EVT_ESCAPE);
}
Example #8
0
/*
 * Obtain the "flags" for the player as if he was an item
 */
void player_flags(bitflag f[OF_SIZE])
{
	/* Add racial flags */
	memcpy(f, p_ptr->race->flags, sizeof(p_ptr->race->flags));

	/* Some classes become immune to fear at a certain plevel */
	if (player_has(PF_BRAVERY_30) && p_ptr->lev >= 30)
		of_on(f, OF_RES_FEAR);
}
Example #9
0
/**
 * Obtain object flags for the player
 */
void player_flags(struct player *p, bitflag f[OF_SIZE])
{
	/* Add racial flags */
	memcpy(f, p->race->flags, sizeof(p->race->flags));

	/* Some classes become immune to fear at a certain plevel */
	if (player_has(p, PF_BRAVERY_30) && p->lev >= 30)
		of_on(f, OF_PROT_FEAR);
}
Example #10
0
/**
 * Display the damage done with a multiplier
 */
static void output_dam(textblock * tb, player_state * state,
					   const object_type * o_ptr, int mult,
					   const char *against, bool * first,
					   oinfo_detail_t mode)
{
	int dam, die_average, add = 0, i, deadliness, crit, chance;
	bool full = mode & OINFO_FULL;

	/* Average damage for one standard side (x10) */
	die_average = (10 * (o_ptr->ds + 1)) / 2;

	/* Multiply by slay or brand (x10) */
	die_average *= mult;

	/* Record the addend */
	if (mult > MULTIPLE_BASE)
		add = (mult - MULTIPLE_BASE);

	/* Multiply by deadliness (x100) */
	deadliness = state->dis_to_d;
	if (if_has(o_ptr->id_other, IF_TO_D) || full)
		deadliness += o_ptr->to_d;
	if (deadliness > 150)
		deadliness = 150;
	if (deadliness < -150)
		deadliness = -150;
	if (deadliness >= 0)
		die_average *= (100 + deadliness_conversion[deadliness]);
	else {
		i = deadliness_conversion[ABS(deadliness)];
		if (i >= 100)
			die_average = 0;
		else
			die_average *= (100 - i);
	}

	/* Factor in criticals (x 10) */
	chance = state->skills[SKILL_TO_HIT_MELEE] + state->dis_to_h;
	if (object_known_p(o_ptr))
		chance += o_ptr->to_h;
	chance = (100 * chance) / (chance + 240);
	if (player_has(PF_ARMSMAN))
		chance = 100 - (83 * (100 - chance)) / 100;
	crit = 259 * chance;
	crit /= 1000;

	/* Multiply by number of sides */
	dam = die_average * (o_ptr->dd * 10 + crit);

	CHECK_FIRST("", *first);
	if ((dam > 50000) || (add > 0))
		textblock_append_c(tb, TERM_L_GREEN, "%d", add + dam / 100000);
	else
		textblock_append_c(tb, TERM_L_RED, "0");
	textblock_append(tb, " against %s", against);
}
Example #11
0
/**
 * Track Griffon charging
 * Based on Sil's Sprinting, combined with Sil's Charge
 */
bool charging(void)
{
    /* Always false if the player isn't a griffon */
    if (!player_has(PF_WINGED_CHARGE))
        return FALSE;

    return (similar_direction(p_ptr->previous_action[0], p_ptr->previous_action[1]) &&
            similar_direction(p_ptr->previous_action[1], p_ptr->previous_action[2]) &&
            similar_direction(p_ptr->previous_action[2], p_ptr->previous_action[3]));

}
Example #12
0
bool object_FA_would_be_obvious(const object_type *o_ptr)
{
	bitflag flags[OF_SIZE];
	
	if (!player_has(PF_CUMBER_GLOVE))
		return FALSE;

	if ((wield_slot(o_ptr) != INVEN_HANDS) || (o_ptr->sval == SV_SET_OF_ALCHEMISTS_GLOVES))
		return FALSE;

	object_flags(o_ptr, flags);
	if (of_has(flags, OF_DEX))
		return FALSE;

	return TRUE;
}
Example #13
0
void bear_shape(void)
{
    /* Sanity */
    if ((SCHANGE) || (!player_has(PF_BEARSKIN)))
	return;

    /* Confirm */
    if (!get_check("Assume the form of a bear? "))
	return;

    /* Change */
    shapechange(SHAPE_BEAR);

    /* Use some energy */
    p_ptr->energy_use = 100;
}
Example #14
0
bool player_can_fire(void)
{
	object_type *j_ptr;
	/* Get the "bow" (if any) */
	j_ptr = &p_ptr->equipment[EQUIP_BOW];

	/* Require a launcher */
	if (j_ptr->tval) {
		/* see if we have ammo for the launcher */
		if (player_has(p_ptr->ammo_tval, 0)) {
			return(TRUE);
		}
	}

	return (FALSE);
}
Example #15
0
void get_spell_info(int tval, int spell, char *p, size_t len)
{
	/* Blank 'p' first */
	p[0] = '\0';

	/* Mage spells */
	if (tval == TV_MAGIC_BOOK)
	{
		int plev = p_ptr->lev;

		/* Analyze the spell */
		switch (spell)
		{
		case SPELL_MAGIC_MISSILE:
			strnfmt(p, len, " dam %dd4", 3 + ((plev - 1) / 5));
			break;
		case SPELL_PHASE_DOOR:
			strnfmt(p, len, " range 10");
			break;
		case SPELL_LIGHT_AREA:
			strnfmt(p, len, " dam 2d%d", (plev / 2));
			break; 
		case SPELL_CURE_LIGHT_WOUNDS:
			strnfmt(p, len, " heal 15%%");
			break;
		case SPELL_STINKING_CLOUD:
			strnfmt(p, len, " dam %d", 10 + (plev / 2));
			break;
		case SPELL_LIGHTNING_BOLT:
			strnfmt(p, len, " dam %dd6", (3 + ((plev - 5) / 6)));
			break;
		case SPELL_FROST_BOLT:
			strnfmt(p, len, " dam %dd8", (5 + ((plev - 5) / 4)));
			break;
		case SPELL_ACID_BOLT:
			strnfmt(p, len, " dam %dd8", (8 + ((plev - 5) / 4)));
			break;
		case SPELL_FIRE_BOLT:
			strnfmt(p, len, " dam %dd8", (6 + ((plev - 5) / 4)));
			break;
		case SPELL_SPEAR_OF_LIGHT:
			strnfmt(p, len, " dam 6d8");
			break;
		case SPELL_HEROISM:
			strnfmt(p, len, " dur 25+d25");
			break;
		case SPELL_BERSERKER:
			strnfmt(p, len, " dur 25+d25");
			break;
		case SPELL_HASTE_SELF:
			strnfmt(p, len, " dur %d+d20", plev);
			break;
		case SPELL_TELEPORT_SELF:
			strnfmt(p, len, " range %d", plev * 5);
			break;
		case SPELL_SHOCK_WAVE:
			strnfmt(p, len, " dam %d", 10 + plev);
			break;
		case SPELL_EXPLOSION:
			strnfmt(p, len, " dam %d", 20 + plev * 2);
			break;
		case SPELL_CLOUD_KILL:
			strnfmt(p, len, " dam %d", 40 + (plev / 2));
			break;
		case SPELL_REND_SOUL:
			strnfmt(p, len, " dam 11d%d", plev);
			break;
		case SPELL_CHAOS_STRIKE:
			strnfmt(p, len, " dam 13d%d", plev);
			break;
		case SPELL_RESIST_COLD:
			strnfmt(p, len, " dur 20+d20");
			break;
		case SPELL_RESIST_FIRE:
			strnfmt(p, len, " dur 20+d20");
			break;
		case SPELL_RESIST_POISON:
			strnfmt(p, len, " dur 20+d20");
			break;
		case SPELL_RESISTANCE:
			strnfmt(p, len, " dur 20+d20");
			break;
		case SPELL_SHIELD:
			strnfmt(p, len, " dur 30+d20");
			break;
		case SPELL_FROST_BALL:
			strnfmt(p, len, " dam %d", 30 + plev);
			break;
		case SPELL_ACID_BALL:
			strnfmt(p, len, " dam %d", 40 + plev);
			break;
		case SPELL_FIRE_BALL:
			strnfmt(p, len, " dam %d", 55 + plev);
			break;
		case SPELL_ICE_STORM:
			strnfmt(p, len, " dam %d", 50 + (plev * 2));
			break;
		case SPELL_METEOR_SWARM:
			strnfmt(p, len, " dam %dx%d", 30 + plev / 2, 2 + plev / 20);
			break;
		case SPELL_RIFT:
			strnfmt(p, len, " dam 40+%dd7", plev);
			break;
		case SPELL_MANA_STORM:
			strnfmt(p, len, " dam %d", 300 + plev * 2);
			break;
		}
	}

	/* Priest spells */
	if (tval == TV_PRAYER_BOOK)
	{
		int plev = p_ptr->lev;

		/* Analyze the spell */
		switch (spell)
		{
			case PRAYER_CURE_LIGHT_WOUNDS:
				my_strcpy(p, " heal 15%", len);
				break;
			case PRAYER_BLESS:
				my_strcpy(p, " dur 12+d12", len);
				break;
			case PRAYER_CALL_LIGHT:
				strnfmt(p, len, " dam 2d%d", (plev / 2));
				break; 
			case PRAYER_PORTAL:
				strnfmt(p, len, " range %d", 3 * plev);
				break;
			case PRAYER_CURE_SERIOUS_WOUNDS:
				my_strcpy(p, " heal 20%", len);
				break;
			case PRAYER_CHANT:
				my_strcpy(p, " dur 24+d24", len);
				break;
			case PRAYER_RESIST_HEAT_COLD:
				my_strcpy(p, " dur 10+d10", len);
				break;
			case PRAYER_ORB_OF_DRAINING:
				strnfmt(p, len, " %d+3d6", plev +
				        (plev / (player_has(PF_BLESS_WEAPON) ? 2 : 4)));
				break;
			case PRAYER_CURE_CRITICAL_WOUNDS:
				my_strcpy(p, " heal 25%", len);
				break;
			case PRAYER_SENSE_INVISIBLE:
				my_strcpy(p, " dur 24+d24", len);
				break;
			case PRAYER_PROTECTION_FROM_EVIL:
				strnfmt(p, len, " dur %d+d25", 3 * plev);
				break;
			case PRAYER_CURE_MORTAL_WOUNDS:
				my_strcpy(p, " heal 30%", len);
				break;
			case PRAYER_PRAYER:
				my_strcpy(p, " dur 48+d48", len);
				break;
			case PRAYER_DISPEL_UNDEAD:
				strnfmt(p, len, " dam d%d", 3 * plev);
				break;
			case PRAYER_HEAL:
				my_strcpy(p, " heal 35%", len);
				break;
			case PRAYER_DISPEL_EVIL:
				strnfmt(p, len, " dam d%d", 3 * plev);
				break;
			case PRAYER_HOLY_WORD:
				my_strcpy(p, " heal 1000", len);
				break;
			case PRAYER_CURE_SERIOUS_WOUNDS2:
				my_strcpy(p, " heal 20%", len);
				break;
			case PRAYER_CURE_MORTAL_WOUNDS2:
				my_strcpy(p, " heal 30%", len);
				break;
			case PRAYER_HEALING:
				my_strcpy(p, " heal 2000", len);
				break;
			case PRAYER_DISPEL_UNDEAD2:
				strnfmt(p, len, " dam d%d", 4 * plev);
				break;
			case PRAYER_DISPEL_EVIL2:
				strnfmt(p, len, " dam d%d", 4 * plev);
				break;
			case PRAYER_ANNIHILATION:
				my_strcpy(p, " dam 200", len);
				break;
			case PRAYER_BLINK:
				my_strcpy(p, " range 10", len);
				break;
			case PRAYER_TELEPORT_SELF:
				strnfmt(p, len, " range %d", 8 * plev);
				break;
		}
	}

	return;
}
Example #16
0
/**
 * Add an item to the players inventory.
 *
 * If the new item can combine with an existing item in the inventory,
 * it will do so, using object_similar() and object_absorb(), else,
 * the item will be placed into the first available gear array index.
 *
 * This function can be used to "over-fill" the player's pack, but only
 * once, and such an action must trigger the "overflow" code immediately.
 * Note that when the pack is being "over-filled", the new item must be
 * placed into the "overflow" slot, and the "overflow" must take place
 * before the pack is reordered, but (optionally) after the pack is
 * combined.  This may be tricky.  See "dungeon.c" for info.
 *
 * Note that this code removes any location information from the object once
 * it is placed into the inventory, but takes no responsibility for removing
 * the object from any other pile it was in.
 */
void inven_carry(struct player *p, struct object *obj, bool absorb,
				 bool message)
{
	struct object *gear_obj;
	char o_name[80];

	/* Check for combining, if appropriate */
	if (absorb) {
		for (gear_obj = p->gear; gear_obj; gear_obj = gear_obj->next) {
			/* Can't stack equipment */
			if (object_is_equipped(p->body, gear_obj))
				continue;

			/* Check if the two items can be combined */
			if (object_similar(gear_obj, obj, OSTACK_PACK)) {
				/* Increase the weight */
				p->upkeep->total_weight += (obj->number * obj->weight);

				/* Combine the items, and their known versions */
				object_absorb(gear_obj->known, obj->known);
				obj->known = NULL;
				object_absorb(gear_obj, obj);

				/* Describe the combined object */
				object_desc(o_name, sizeof(o_name), gear_obj,
							ODESC_PREFIX | ODESC_FULL);

				/* Recalculate bonuses */
				p->upkeep->update |= (PU_BONUS | PU_INVEN);

				/* Redraw stuff */
				p->upkeep->redraw |= (PR_INVEN);

				/* Inventory will need updating */
				update_stuff(player);

				/* Optionally, display a message */
				if (message)
					msg("You have %s (%c).", o_name, gear_to_label(gear_obj));

				/* Sound for quiver objects */
				if (object_is_in_quiver(p, gear_obj))
					sound(MSG_QUIVER);

				/* Success */
				return;
			}
		}
	}

	/* Paranoia */
	assert(pack_slots_used(p) <= z_info->pack_size);

	/* Add to the end of the list */
	gear_insert_end(obj);

	/* Apply an autoinscription */
	apply_autoinscription(obj);

	/* Remove cave object details */
	obj->held_m_idx = 0;
	obj->iy = obj->ix = 0;
	obj->known->iy = obj->known->ix = 0;

	/* Update the inventory */
	p->upkeep->total_weight += (obj->number * obj->weight);
	p->upkeep->update |= (PU_BONUS | PU_INVEN);
	p->upkeep->notice |= (PN_COMBINE);
	p->upkeep->redraw |= (PR_INVEN);

	/* Inventory will need updating */
	update_stuff(player);

	/* Hobbits ID mushrooms on pickup, gnomes ID wands and staffs on pickup */
	if (!object_flavor_is_aware(obj)) {
		if (player_has(player, PF_KNOW_MUSHROOM) && tval_is_mushroom(obj)) {
			object_flavor_aware(obj);
			msg("Mushrooms for breakfast!");
		} else if (player_has(player, PF_KNOW_ZAPPER) && tval_is_zapper(obj))
			object_flavor_aware(obj);
	}

	/* Optionally, display a message */
	if (message) {
		/* Describe the object */
		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);

		/* Message */
		msg("You have %s (%c).", o_name, gear_to_label(obj));
	}

	/* Sound for quiver objects */
	if (object_is_in_quiver(p, obj))
		sound(MSG_QUIVER);
}
Example #17
0
static void exec_action(int op,int arg1,int arg2)
{
  int i, j;
  char *tmpstr;

  switch(op) 
    {
    case 1000:goto_room(arg1-first_room);break;
    case 1001:goto_room(agt_rand(arg1,arg2)-first_room);break;
    case 1002:agt_var[arg1]=loc+first_room;break;
    case 1003:agt_var[arg1]=dobj;break;
    case 1004:agt_var[arg1]=iobj;break;
    case 1005:goto_room(agt_var[arg1]-first_room);break;
    case 1006:it_move(arg1,agt_var[arg2]);break;
    case 1007:get_obj(agt_var[arg1]);break;
    case 1008:msgout(agt_var[arg1],1);break;
    case 1009:get_obj(arg1);break;
    case 1010:get_obj(arg1);it_move(arg1,1000);break;
    case 1011:drop_obj(arg1);break;
    case 1012:
      if (it_loc(arg1)==1000) {
	if (PURE_WEAR) drop_obj(arg1);
	else it_move(arg1,1);
      }
      break;
    case 1013:fontcmd(0,arg1-1);break;  /* Load font */
    case 1014:pictcmd(1,pictable[arg1-1]);break;  /* Show picture */
    case 1015:changepict(arg1,arg2);break; /* ChangePicture */
    case 1016: if (PICT_SUPPORT && 
		     yesno("Would you like to see the picture?"))
      pictcmd(1,pictable[arg1-1]);break;
    case 1017:pictcmd(2,arg1);break;  /* Show room pix */
    case 1018: if (PICT_SUPPORT && 
		   yesno("Would you like to see the picture?"))
      pictcmd(2,arg1-1);break;
    case 1019:musiccmd(1,arg1-1);break;
    case 1020:musiccmd(1,agt_rand(arg1,arg2)-1);break;
    case 1021:musiccmd(2,arg1-1);break;
    case 1022:musiccmd(3,-1); break;  /* Stop Repeat */
    case 1023:musiccmd(4,-1); break;  /* Stop song */
    case 1024:musiccmd(5,-1); break;  /* Suspend song */
    case 1025:musiccmd(6,-1);break;   /* Resume song */
    case 1026: 
      if (tnoun(dobj)) 
	noun[dobj-first_noun].movable=!noun[dobj-first_noun].movable;
      break;
    case 1027: it_newdesc(arg1,&msg_ptr[arg2-1]); break;
    case 1028: 
      if (tnoun(arg1)) noun[arg1-first_noun].points=arg2;
      else if (tcreat(arg1)) creature[arg1-first_creat].points=arg2;
      else if (troom(arg1)) room[arg1-first_room].points=arg2;
      break;
    case 1029:it_destroy(iobj);break;
    case 1030:
      tmpstr=agt_readline(3);
      i=strlen(tmpstr)-1;
      if (i>0 && tmpstr[i]=='\n') tmpstr[i]=0;
      strncpy(userstr[arg1-1],tmpstr,80);
      rfree(tmpstr);
      break;
    case 1031:agt_var[arg1]=read_number();break;
    case 1032:agt_var[arg1]=curr_time;break;
    case 1033:curr_time=normalize_time(agt_var[arg1]);break; 
    case 1034:curr_time=normalize_time(arg1); break;
    case 1035:add_time(arg1);break; 
    case 1036:delta_time=arg1;break;
      /* 1037 and 1038 are subroutine commands */
    case 1039:get_obj(dobj);break;
    case 1040:it_move(dobj,1000);break;
    case 1041:drop_obj(dobj);break;
    case 1042:
      if (it_loc(dobj)==1000) {
	if (PURE_WEAR) it_move(dobj,1);
	else drop_obj(dobj);
      }
      break;
    case 1043: /* drop all */
      safecontloop(i,j,1) drop_obj(i);
      break;
    case 1044: /* remove all */
      safecontloop(i,j,1000) drop_obj(i);
      break;
    case 1045:deadflag=1;break;
    case 1046:it_move(arg1,loc+first_room);break;
    case 1047:it_move(arg1,arg2);break;
    case 1048:it_reposition(arg1,arg2,1);break; /* RePosition */
    case 1049:it_move(dobj,loc+first_room);break;
    case 1050:it_move(dobj,arg1);break;
    case 1051:
      safecontloop(i,j,1) it_move(i,arg1);
      safecontloop(i,j,1000) it_move(i,arg1);
      break;
    case 1052:
      nounloop(i)
	if (player_has(i+first_noun) && noun[i].points>arg2)
	  it_move(i+first_noun,arg1);
      break;
    case 1053:
      safecontloop(i,j,arg1) 
	if (tnoun(i)) it_move(i,arg2);
      break;
    case 1054:it_destroy(arg1);break;
    case 1055:it_destroy(dobj);break;
    case 1056:i=it_loc(arg1);
      it_move(arg1,it_loc(arg2));
      it_move(arg2,i);
      break;
    case 1057:it_move(arg1,it_loc(arg2));break;
    case 1058:it_move(dobj,it_loc(arg2));break;
    case 1059: case 1060: /* Add to/remove from group */
      if (tcreat(arg1))
	creature[arg1-first_creat].groupmemb=(op==1059);
      break;
    case 1061:   /* Move group */
      safecontloop(i,j,loc+first_room)
	if (it_group(i)) it_move(i,arg1);
      break; 
      /* 1062 is RedirectTo */
    case 1063:msgout(agt_rand(arg1,arg2),1);break;
    case 1064:print_contents(arg1,1);break;
    case 1065: case 1066: case 1067: case 1068: 
      obj_act(op-1065,arg1);break;
    case 1069: case 1070: case 1071: case 1072: 
      obj_act(op-1069,dobj);break;
    case 1073:print_score();break;
    case 1074: tscore+=arg1;break;
    case 1075: tscore-=arg1;break;
    case 1076:v_inventory();break;
    case 1077:wait_return();break;
    case 1078:writeln("Time passes...");break;
    case 1079:agt_delay(arg1);break;
    case 1080:agt_clrscr();break;
    case 1081:it_describe(arg1);break;
    case 1082:look_room();break;   /* LOOK */
    case 1083:msgout(arg1,1);break;
    case 1084:writeln("");break;
    case 1085:if (PURE_TONE && sound_on) 
	       agt_tone(arg1,arg2);break; /* Tone */
    case 1086:agt_number=ask_for_number(arg1,arg2);break;
    case 1087:agt_answer=ask_question(arg1);break;
    case 1088:change_passage(loc,arg1,arg2);break;
    case 1089:flag[arg1]=1;break;
    case 1090:flag[arg1]=0;break;
    case 1091:flag[arg1]=!flag[arg1];break;
    case 1092:room[loc].flag_noun_bits|=(1 << (arg1-1) );
      break; /* Roomflag on */ 
    case 1093:room[loc].flag_noun_bits&=~(1 << (arg1-1) );break; /* Off */ 
    case 1094:room[loc].flag_noun_bits^=(1 << (arg1-1) );break; /* Toggle */
    case 1095: /* if (agt_counter[arg1]==-1)*/
      agt_counter[arg1]=1;break;
    case 1096:agt_counter[arg1]=-1;break;
    case 1097:agt_var[arg1]=arg2;break;
    case 1098:agt_var[arg1]+=arg2;break;
    case 1099:agt_var[arg1]-=arg2;break;
    case 1100:agt_var[arg1]+=agt_var[arg2];break;
    case 1101:agt_var[arg1]-=agt_var[arg2];break;
    case 1102:agt_var[arg1]=agt_rand(0,arg2);break;
    case 1103:agt_var[arg1]=dobj_rec->num;break;
    case 1104:agt_var[arg1]=iobj_rec->num;break;
      
      /* The following are v1.8x specific */
    case 1105:quote(arg1);break;
    case 1106:add_time(arg1);break;
    case 1107:add_time(-arg1);break;
    case 1108:curr_time=(curr_time%100)+100*arg1;break;
    case 1109:curr_time=(curr_time/100)*100+arg1;break;
    case 1110:add_time(agt_var[arg1]);break;
    case 1111:add_time(-agt_var[arg1]);break;
    case 1112:curr_time=(curr_time%100)+100*agt_var[arg1];break;
    case 1113:curr_time=(curr_time/100)*100+agt_var[arg1];break;

      /* Now for the AGX additions */
    case 1114:add_time(-arg1);break; /* ME-style SubtractFromTime */
    case 1115: disambig_score=arg1; break; /* SetDisambigPriority */
    case 1116:agt_var[arg1]=delta_time;break;
    case 1117: /* ChangeStatus */
      statusmode=arg1;
      break;
    case 1118:
      if (!mult_rangecheck(agt_var[arg1],arg2)) break;
      agt_var[arg1]*=arg2;break;
    case 1119:
      if (arg2==0) {
	if (!PURE_ERROR)
	  writeln("GAME ERROR: Division by zero.");
      } else agt_var[arg1]/=arg2;
      break;
    case 1120:
      if (arg2==0) {
	if (!PURE_ERROR)
	  writeln("GAME ERROR: Attempt to divide by zero.");
      } else agt_var[arg1]%=arg2;
      break;
    case 1121:agt_waitkey();break;
    case 1122:last_he=arg1;break;   /* SetHE */
    case 1123:last_she=arg1;break;  
    case 1124:last_it=arg1;break;
    case 1125:last_they=arg1;break;
    case 1126:msgout(arg1,0);break;
    case 1127:
      if (!PURE_ERROR)
	sysmsg(arg1,"GAME ERROR: Standard message not defined.");
      break;
    case 1128: msgout(arg1,1);break; /* FailMessage */
    case 1129:  /* StdMessage */
      sysmsg(arg1,"GAME ERROR: Standard message not defined.");
      break;
    case 1130: msgout(arg2,1);break; /* ErrMessage */
    case 1131: /* StdErrMessage */
      sysmsg(arg1,"GAME ERROR: Standard message not defined.");
      break;
    case 1132: /* AND */
      break;  /* These don't do anything under normal circumstances */
    case 1133:  /* SetClass */
      if (troom(arg1)) room[arg1-first_room].oclass=arg2;
      else if (tnoun(arg1)) noun[arg1-first_noun].oclass=arg2;
      else if (tcreat(arg1)) noun[arg1-first_creat].oclass=arg2;
      break;
    case 1134: agt_var[arg1]=it_class(arg2); break; /* SetVariableToClass */
      
      /* Stack commands */
    case 1135: push_stack(arg1); break;
    case 1136: agt_var[arg1]=pop_stack(); break;
    case 1137: case 1138: case 1139: case 1140: case 1141: 
      op_stack(op-1137); /* +,-,*, /,% * */
      break;
    case 1142: { /* DupStack */
      long n;
      n=pop_stack();
      push_stack(n);
      push_stack(n);
      break;
    }    
    case 1143: pop_stack();break; /* Discard TOS */
    case 1144: agt_var[arg1]=agt_number;break; /* SetVariableToInput */
    case 1145: setattr(arg1,arg2,1); break; /* Set */
    case 1146: setattr(arg1,arg2,0); break; /* Clear */
    case 1147: push_stack(getprop(arg1,arg2));break; /* PushProp */
    case 1148: setprop(arg1,arg2,pop_stack());break; /* PopProp */
      /* 1149, 1150 handled by run_metacommand */
      /* 1151 is EndDisambig */
      /* 1152 is XRedirect */
    case 1153: rstrncpy(userstr[arg1-1],userstr[arg2-1],81);break; 
    case 1154: setcase(userstr[arg1-1],1); break;
    case 1155: setcase(userstr[arg1-1],0);break;
    case 1156: op_objflag(1,arg1,arg2);break;
    case 1157: op_objflag(0,arg1,arg2);break;
    case 1158: op_objflag(3,arg1,arg2);break;
    case 1159: push_stack(op_objprop(2,arg1,arg2,0)); break;
    case 1160: op_objprop(1,arg1,arg2,pop_stack()); break;
    case 1161: move_in_dir(arg1,arg2); break;
    default: 
      writeln("INTERNAL ERROR: Action token not supported.");
      rprintf("Action #%d",op);   
      writeln(""); 
    }
}
Example #18
0
/**
 * Display a "tomb-stone"
 */
static void print_tomb(void)
{
    cptr p;

    int offset = 12;

    char tmp[160];

    char buf[1024];

    ang_file *fp;

#ifdef _WIN32_WCE
    time_t ct = fake_time((time_t) 0);
#else
    time_t ct = time((time_t) 0);
#endif

    bool boat = ((p_ptr->total_winner) && (player_has(PF_ELVEN)));
    bool tree = ((p_ptr->total_winner)
		 && (player_has(PF_WOODEN) || player_has(PF_DIVINE)));

    /* Clear screen */
    Term_clear();

    /* Build the filename */
    if (tree)
	path_build(buf, 1024, ANGBAND_DIR_FILE, "tree.txt");
    else if (boat)
	path_build(buf, 1024, ANGBAND_DIR_FILE, "boat.txt");
    else
	path_build(buf, 1024, ANGBAND_DIR_FILE, "dead.txt");

    /* Open the News file */
    fp = file_open(buf, MODE_READ, FTYPE_TEXT);

    /* Dump */
    if (fp) {
	int i, y, x;

	byte a = 0;
	char c = ' ';

	bool okay = TRUE;

	int len;


	/* Load the screen */
	for (y = 0; okay; y++) {
	    /* Get a line of data */
	    if (!file_getl(fp, buf, 1024))
		okay = FALSE;

	    /* Stop on blank line */
	    if (!buf[0])
		break;

	    /* Get the width */
	    len = strlen(buf);

	    /* XXX Restrict to current screen size */
	    if (len >= Term->wid)
		len = Term->wid;

	    /* Show each row */
	    for (x = 0; x < len; x++) {
		/* Put the attr/char */
		Term_draw(x, y, TERM_WHITE, buf[x]);
	    }
	}

	/* Get the blank line */
	/* if (my_fgets(fp, buf, 1024)) okay = FALSE; */


	/* Load the screen */
	for (y = 0; okay; y++) {
	    /* Get a line of data */
	    if (!file_getl(fp, buf, 1024))
		okay = FALSE;

	    /* Stop on blank line */
	    if (!buf[0])
		break;

	    /* Get the width */
	    len = strlen(buf);

	    /* XXX Restrict to current screen size */
	    if (len >= Term->wid)
		len = Term->wid;

	    /* Show each row */
	    for (x = 0; x < len; x++) {
		/* Get the attr/char */
		(void) (Term_what(x, y, &a, &c));

		/* Look up the attr */
		for (i = 0; i < 16; i++) {
		    /* Use attr matches */
		    if (hack[i] == buf[x])
			a = i;
		}

		/* Put the attr/char */
		Term_draw(x, y, a, c);
	    }

	    /* Place the cursor */
	    Term_gotoxy(x, y);

	}


	/* Get the blank line */
	/* if (my_fgets(fp, buf, 1024)) okay = FALSE; */


	/* Close it */
	file_close(fp);
    }

    /* King or Queen */
    if (p_ptr->total_winner || (p_ptr->lev > PY_MAX_LEVEL)) {
	p = "Magnificent";
    }

    /* Normal */
    else {
	p = cp_ptr->title[(p_ptr->lev - 1) / 5];
    }

    /* Set offset */
    offset = 11;

    center_string(buf, op_ptr->full_name);
    put_str(buf, 6, offset);

    center_string(buf, "the");
    put_str(buf, 7, offset);

    center_string(buf, p);
    put_str(buf, 8, offset);


    center_string(buf, cp_ptr->name);
    put_str(buf, 10, offset);

    sprintf(tmp, "Level: %d", (int) p_ptr->lev);
    center_string(buf, tmp);
    put_str(buf, 11, offset);

    sprintf(tmp, "Exp: %ld", (long) p_ptr->exp);
    center_string(buf, tmp);
    put_str(buf, 12, offset);

    sprintf(tmp, "AU: %ld", (long) p_ptr->au);
    center_string(buf, tmp);
    put_str(buf, 13, offset);

    if (p_ptr->depth)
	sprintf(tmp, "Killed in %s level %d",
		locality_name[stage_map[p_ptr->stage][LOCALITY]], p_ptr->depth);
    else if (boat)
	sprintf(tmp, "Sailed victorious to Aman.");
    else if (tree)
	sprintf(tmp, "Retired to Fangorn Forest.");
    else
	sprintf(tmp, "Killed in %s town",
		locality_name[stage_map[p_ptr->stage][LOCALITY]]);
    center_string(buf, tmp);
    put_str(buf, 14, offset);

    if (!(boat || tree)) {
	sprintf(tmp, "by %s.", p_ptr->died_from);
	center_string(buf, tmp);
	put_str(buf, 15, offset);
    }
#ifdef _WIN32_WCE
    {
	char *fake_ctime(const unsigned long *fake_time_t);
	sprintf(tmp, "%-.24s", fake_ctime(&ct));
    }
#else
    sprintf(tmp, "%-.24s", ctime(&ct));
#endif
    center_string(buf, tmp);
    put_str(buf, 17, offset);
}
Example #19
0
/* Cast the specified spell */
bool spell_cast(int spell, int dir)
{
    int chance;
    int plev = p_ptr->lev;
    bool failed = FALSE;
    int py = p_ptr->py;
    int px = p_ptr->px;

    /* Get the spell */
    const magic_type *mt_ptr = &mp_ptr->info[spell];

    /* Spell failure chance */
    chance = spell_chance(spell);

    /* Specialty Ability */
    if (player_has(PF_HEIGHTEN_MAGIC))
	plev += 1 + ((p_ptr->heighten_power + 5) / 10);
    if (player_has(PF_CHANNELING))
	plev += get_channeling_boost();

    /* Failed spell */
    if (randint0(100) < chance) {
	failed = TRUE;

	if (OPT(flush_failure))
	    flush();
	msg(magic_desc[mp_ptr->spell_realm][SPELL_FAIL]);
    }

    /* Process spell */
    else {
	/* Cast the spell */
	if (!cast_spell(mp_ptr->spell_book, mt_ptr->index, dir, plev))
	    return FALSE;

	/* A spell was cast */
	sound(MSG_SPELL);


	/* A spell was cast or a prayer prayed */
	if (!(p_ptr->spell_flags[spell] & PY_SPELL_WORKED)){
	    int e = mt_ptr->sexp;

	    /* The spell worked */
	    p_ptr->spell_flags[spell] |= PY_SPELL_WORKED;

	    /* Gain experience */
	    gain_exp(e * mt_ptr->slevel);
	    
	    /* Redraw object recall */
	    p_ptr->redraw |= (PR_OBJECT);
	}
    }

    /* Hack - simplify rune of mana calculations by fully draining the rune
     * first */
    if (cave_trap_specific(py, px, RUNE_MANA) && 
	(mana_reserve <= mt_ptr->smana)	&& (mt_ptr->index != 60)) 
    {
	p_ptr->csp += mana_reserve;
	mana_reserve = 0;
    }

    /* Rune of mana can take less mana than specified */
    if (mt_ptr->index == 60) {
	/* Standard mana amount */
	int mana = 40;

	/* Already full? */
	if (mana_reserve >= MAX_MANA_RESERVE) {
	    /* Use no mana */
	    mana = 0;
	}

	/* Don't put in more than we have */
	else if (p_ptr->csp < mana)
	    mana = p_ptr->csp;

	/* Don't put in more than it will hold */
	if (mana_reserve + mana > MAX_MANA_RESERVE)
	    mana = MAX_MANA_RESERVE - mana_reserve;

	/* Deduct */
	p_ptr->csp -= mana;
    }

    /* Use mana from a rune if possible */
    else if (cave_trap_specific(py, px, RUNE_MANA)
	     && (mana_reserve > mt_ptr->smana)) {
	mana_reserve -= mt_ptr->smana;
    }

    /* Sufficient mana */
    else if (mt_ptr->smana <= p_ptr->csp) {
	/* Use some mana */
	p_ptr->csp -= mt_ptr->smana;

	/* Specialty ability Harmony */
	if ((failed == FALSE) & (player_has(PF_HARMONY))) {
	    int frac, boost;

	    /* Percentage of max hp to be regained */
	    frac = 3 + (mt_ptr->smana / 3);

	    /* Cap at 10 % */
	    if (frac > 10)
		frac = 10;

	    /* Calculate fractional bonus */
	    boost = (frac * p_ptr->mhp) / 100;

	    /* Apply bonus */
	    (void) hp_player(boost);
	}
    }

    /* Over-exert the player */
    else {
	int oops = mt_ptr->smana - p_ptr->csp;

	/* No mana left */
	p_ptr->csp = 0;
	p_ptr->csp_frac = 0;

	/* Message */
	if (mp_ptr->spell_realm == REALM_NECROMANTIC)
	    msg("You collapse after the ritual!");
	else
	    msg("You faint from the effort!");

	/* Hack -- Bypass free action */
	(void) inc_timed(TMD_PARALYZED, randint1(5 * oops + 1), TRUE);

	/* Damage CON (possibly permanently) */
	if (randint0(100) < 50) {
	    bool perm = (randint0(100) < 25);

	    /* Message */
	    msg("You have damaged your health!");

	    /* Reduce constitution */
	    (void) dec_stat(A_CON, 15 + randint1(10), perm);
	}
    }


    /* Redraw mana */
    p_ptr->redraw |= (PR_MANA);

    return TRUE;
}
Example #20
0
/**
 * Display the ammo damage done with a multiplier
 */
static void output_ammo_dam(textblock * tb, player_state * state,
							const object_type * o_ptr, int mult,
							const char *against, bool * first,
							bool perfect, oinfo_detail_t mode)
{
	object_type *b_ptr = &p_ptr->inventory[INVEN_BOW];

	int dam, die_average, add = 0, i, deadliness, crit, chance, dice =
		o_ptr->dd;

	/* Throwing weapon, or launched missile? */
	bool thrown = !is_missile(o_ptr);
	bool full = mode & OINFO_FULL;

	/* Average damage for one standard side (x10) */
	die_average = (10 * (o_ptr->ds + 1)) / 2;

	/* Apply the launcher multiplier. */
	if (!thrown)
		die_average *= p_ptr->state.ammo_mult;

	/* Multiply by slay or brand (x10) */
	die_average *= mult;

	/* Record the addend */
	if (mult > 10)
		add = (mult - 10);

	/* Multiply by deadliness (x100) */
	deadliness = state->dis_to_d;
	if (if_has(o_ptr->id_other, IF_TO_D) || full)
		deadliness += o_ptr->to_d;
	if (if_has(b_ptr->id_other, IF_TO_D) || full)
		deadliness += b_ptr->to_d;
	if (deadliness > 150)
		deadliness = 150;
	if (deadliness < -150)
		deadliness = -150;
	if (deadliness >= 0)
		die_average *= (100 + deadliness_conversion[deadliness]);
	else {
		i = deadliness_conversion[ABS(deadliness)];
		if (i >= 100)
			die_average = 0;
		else
			die_average *= (100 - i);
	}

	/* Get critical chance (x 10) */
	chance = state->skills[SKILL_TO_HIT_BOW] + state->dis_to_h;
	if (if_has(o_ptr->id_other, IF_TO_H) || full)
		chance += o_ptr->to_h;
	if ((!thrown) && (if_has(b_ptr->id_other, IF_TO_H) || full))
		chance += b_ptr->to_h;
	if (thrown)
		chance = chance * 3 / 2;
	chance = (100 * chance) / (chance + 360);
	if (player_has(PF_MARKSMAN))
		chance = 100 - (83 * (100 - chance)) / 100;
	crit = 116 * chance;
	crit /= 1000;

	/* Increase dice */
	if (thrown && perfect)
		dice *= 2;
	dice = dice * 10 + crit;
	if (thrown)
		dice *= 2 + p_ptr->lev / 12;

	/* Multiply by number of sides */
	dam = die_average * dice;

	CHECK_FIRST("", *first);
	if ((dam > 50000) || (add > 0))
		textblock_append_c(tb, TERM_L_GREEN, "%d", add + dam / 100000);
	else
		textblock_append_c(tb, TERM_L_RED, "0");
	textblock_append(tb, " against %s", against);
}
Example #21
0
/**
 * Bring up player actions 
 */
void show_player(void)
{
    int i, j, fy, fx;
    int adj_grid[9];
    bool exist_rock = FALSE;
    bool exist_door = FALSE;
    bool exist_open_door = FALSE;
    bool exist_trap = FALSE;
    bool exist_mtrap = FALSE;
    bool exist_floor = FALSE;
    bool exist_monster = FALSE;

    feature_type *f_ptr;

    /* No commands yet */
    poss = 0;

    /* Get surroundings */
    get_feats(adj_grid);

    /* Analyze surroundings */
    for (i = 0; i < 8; i++) 
    {
	int yy = p_ptr->py + ddy_ddd[i];
	int xx = p_ptr->px + ddx_ddd[i];
	f_ptr = &f_info[adj_grid[i]];

	if (cave_visible_trap(yy, xx))
	    exist_trap = TRUE;
	if (tf_has(f_ptr->flags, TF_DOOR_CLOSED))
	    exist_door = TRUE;
	if (tf_has(f_ptr->flags, TF_ROCK))
	    exist_rock = TRUE;
	if (cave_monster_trap(yy, xx))
	    exist_mtrap = TRUE;
	if (adj_grid[i] == FEAT_OPEN)
	    exist_open_door = TRUE;
	if (cave_naked_bold(yy, xx))
	    exist_floor = TRUE;
	if (cave_m_idx[yy][xx] > 0)
	    exist_monster = TRUE;
    }

    /* In a web? */
    if (cave_web(p_ptr->py, p_ptr->px))
	exist_trap = TRUE;

    /* Alter a grid */
    if (exist_trap || exist_door || exist_rock || exist_mtrap
	|| exist_open_door || count_chests(&fy, &fx, TRUE)
	|| count_chests(&fy, &fx, FALSE) || (player_has(PF_TRAP)
					     && exist_floor)
	|| (player_has(PF_STEAL) && exist_monster && (!SCHANGE))) {
	comm[poss] = '+';
	comm_code[poss] = CMD_ALTER;
	comm_descr[poss++] = "Alter";
    }

    /* Dig a tunnel */
    if (exist_door || exist_rock) {
	comm[poss] = 'T';
	comm_code[poss] = CMD_TUNNEL;
	comm_descr[poss++] = "Tunnel";
    }

    /* Begin Running -- Arg is Max Distance */
    {
	comm[poss] = '.';
	comm_code[poss] = CMD_RUN;
	comm_descr[poss++] = "Run";
    }

    /* Hold still for a turn.  Pickup objects if auto-pickup is true. */
    {
	comm[poss] = ',';
	comm_code[poss] = CMD_HOLD;
	comm_descr[poss++] = "Stand still";
    }

    /* Pick up objects. */
    if (cave_o_idx[p_ptr->py][p_ptr->px]) {
	comm[poss] = 'g';
	comm_code[poss] = CMD_PICKUP;
	comm_descr[poss++] = "Pick up";
    }

    /* Rest -- Arg is time */
    {
	comm[poss] = 'R';
	comm_code[poss] = CMD_REST;
	comm_descr[poss++] = "Rest";
    }

    /* Search for traps/doors */
    {
	comm[poss] = 's';
	comm_code[poss] = CMD_SEARCH;
	comm_descr[poss++] = "Search";
    }

    /* Look around */
    {
	comm[poss] = 'l';
	comm_code[poss] = CMD_NULL;
	comm_descr[poss++] = "Look";
    }

    /* Scroll the map */
    {
	comm[poss] = 'L';
	comm_code[poss] = CMD_NULL;
	comm_descr[poss++] = "Scroll map";
    }

    /* Show the map */
    {
	comm[poss] = 'M';
	comm_code[poss] = CMD_NULL;
	comm_descr[poss++] = "Level map";
    }

    /* Knowledge */
    {
	comm[poss] = '~';
	comm_code[poss] = CMD_NULL;
	comm_descr[poss++] = "Knowledge";
    }

    /* Options */
    {
	comm[poss] = '=';
	comm_code[poss] = CMD_NULL;
	comm_descr[poss++] = "Options";
    }

    /* Toggle search mode */
    {
	comm[poss] = 'S';
	comm_code[poss] = CMD_TOGGLE_SEARCH;
	comm_descr[poss++] = "Toggle searching";
    }


    /* Go up staircase */
    if ((adj_grid[8] == FEAT_LESS)
	|| ((adj_grid[8] >= FEAT_LESS_NORTH) && (!(adj_grid[8] % 2)))) {
	comm[poss] = '<';
	comm_code[poss] = CMD_GO_UP;
	comm_descr[poss++] = "Take stair/path";
    }

    /* Go down staircase */
    if ((adj_grid[8] == FEAT_MORE)
	|| ((adj_grid[8] >= FEAT_LESS_NORTH) && (adj_grid[8] % 2))) {
	comm[poss] = '>';
	comm_code[poss] = CMD_GO_DOWN;
	comm_descr[poss++] = "Take stair/path";
    }

    /* Open a door or chest */
    if (exist_door || count_chests(&fy, &fx, TRUE)
	|| count_chests(&fy, &fx, FALSE)) {
	comm[poss] = 'o';
	comm_code[poss] = CMD_OPEN;
	comm_descr[poss++] = "Open";
    }

    /* Close a door */
    if (exist_open_door) {
	comm[poss] = 'c';
	comm_code[poss] = CMD_CLOSE;
	comm_descr[poss++] = "Close";
    }

    /* Jam a door with spikes */
    if (exist_door) {
	comm[poss] = 'j';
	comm_code[poss] = CMD_JAM;
	comm_descr[poss++] = "Jam";
    }

    /* Bash a door */
    if (exist_door) {
	comm[poss] = 'B';
	comm_code[poss] = CMD_BASH;
	comm_descr[poss++] = "Bash";
    }

    /* Disarm a trap or chest */
    if (count_chests(&fy, &fx, TRUE) || exist_trap || exist_mtrap) {
	comm[poss] = 'D';
	comm_code[poss] = CMD_DISARM;
	comm_descr[poss++] = "Disarm";
    }

    /* Shapechange */
    if ((SCHANGE) || (player_has(PF_BEARSKIN))) {
	comm[poss] = ']';
	comm_code[poss] = CMD_NULL;
	comm_descr[poss++] = "Shapechange";
    }

    /* Save screen */
    screen_save();

    /* Prompt */
    put_str("Choose a command, or ESC:", 0, 0);

    /* Hack - delete exact graphics rows */
    if (tile_height > 1) {
	j = poss + 1;
	while ((j % tile_height) && (j <= SCREEN_ROWS))
	    prt("", ++j, 0);
    }

    /* Get a choice */
    (void) show_cmd_menu(FALSE);

    /* Load screen */
    screen_load();
}
Example #22
0
/**
 * Process player commands from the command queue, finishing when there is a
 * command using energy (any regular game command), or we run out of commands
 * and need another from the user, or the character changes level or dies, or
 * the game is stopped.
 *
 * Notice the annoying code to handle "pack overflow", which
 * must come first just in case somebody manages to corrupt
 * the savefiles by clever use of menu commands or something. (Can go? NRM)
 *
 * Notice the annoying code to handle "monster memory" changes,
 * which allows us to avoid having to update the window flags
 * every time we change any internal monster memory field, and
 * also reduces the number of times that the recall window must
 * be redrawn.
 */
void process_player(void)
{
	/* Check for interrupts */
	player_resting_complete_special(player);
	event_signal(EVENT_CHECK_INTERRUPT);

	/* Repeat until energy is reduced */
	do {
		/* Refresh */
		notice_stuff(player);
		handle_stuff(player);
		event_signal(EVENT_REFRESH);

		/* Hack -- Pack Overflow */
		pack_overflow(NULL);

		/* Assume free turn */
		player->upkeep->energy_use = 0;

		/* Dwarves detect treasure */
		if (player_has(player, PF_SEE_ORE)) {
			/* Only if they are in good shape */
			if (!player->timed[TMD_IMAGE] &&
				!player->timed[TMD_CONFUSED] &&
				!player->timed[TMD_AMNESIA] &&
				!player->timed[TMD_STUN] &&
				!player->timed[TMD_PARALYZED] &&
				!player->timed[TMD_TERROR] &&
				!player->timed[TMD_AFRAID])
				effect_simple(EF_DETECT_GOLD, "3d3", 1, 0, 0, NULL);
		}

		/* Paralyzed or Knocked Out player gets no turn */
		if ((player->timed[TMD_PARALYZED]) || (player->timed[TMD_STUN] >= 100))
			cmdq_push(CMD_SLEEP);

		/* Prepare for the next command */
		if (cmd_get_nrepeats() > 0)
			event_signal(EVENT_COMMAND_REPEAT);
		else {
			/* Check monster recall */
			if (player->upkeep->monster_race)
				player->upkeep->redraw |= (PR_MONSTER);

			/* Place cursor on player/target */
			event_signal(EVENT_REFRESH);
		}

		/* Get a command from the queue if there is one */
		if (!cmdq_pop(CMD_GAME))
			break;

		if (!player->upkeep->playing)
			break;

		process_player_cleanup();
	} while (!player->upkeep->energy_use &&
			 !player->is_dead &&
			 !player->upkeep->generate_level);

	/* Notice stuff (if needed) */
	notice_stuff(player);
}
Example #23
0
/**
 * Carry an object and delete it.
 */
extern void py_pickup_aux(int o_idx, bool msg)
{
    int slot, quiver_slot = 0;

    char o_name[120];
    object_type *o_ptr = &o_list[o_idx];
    object_type *i_ptr = &p_ptr->inventory[INVEN_LIGHT];
    bitflag f[OF_SIZE], obvious_mask[OF_SIZE];


    flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);
    of_copy(f, o_ptr->flags_obj);
    
    /* Carry the object */
    slot = inven_carry(p_ptr, o_ptr);

    /* Handle errors (paranoia) */
    if (slot < 0) return;

    /* If we have picked up ammo which matches something in the quiver, note
     * that it so that we can wield it later (and suppress pick up message) */
    if (obj_is_quiver_obj(o_ptr)) 
    {
	int i;
	for (i = QUIVER_START; i < QUIVER_END; i++) 
	{
	    if (!p_ptr->inventory[i].k_idx) continue;
	    if (!object_similar(&p_ptr->inventory[i], o_ptr,
				OSTACK_QUIVER)) continue;
	    quiver_slot = i;
	    break;
	}
    }

    /* Get the object again */
    o_ptr = &p_ptr->inventory[slot];

    /* Set squelch status */
    p_ptr->notice |= PN_SQUELCH;

    /* Stone of Lore gives id on pickup */
    if (!object_known_p(o_ptr)) {
	if (i_ptr->sval == SV_STONE_LORE)
	    identify_object(o_ptr);

	/* Otherwise pseudo-ID */
	else {
	    bool heavy = FALSE;
	    int feel;

	    /* Heavy sensing */
	    heavy = (player_has(PF_PSEUDO_ID_HEAVY));

	    /* Type of feeling */
	    feel = (heavy ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr));

	    /* We have "felt" it */
	    o_ptr->ident |= (IDENT_SENSE);

	    /* Inscribe it textually */
	    o_ptr->feel = feel;

	    /* Set squelch flag as appropriate */
	    p_ptr->notice |= PN_SQUELCH;
	}
    }

    /* Log artifacts if found */
    if (artifact_p(o_ptr))
	history_add_artifact(o_ptr->name1, object_is_known(o_ptr), TRUE);

    /* Notice dice and other obvious stuff */
    notice_other(IF_DD_DS, slot + 1);
    (void) of_inter(f, obvious_mask);
    of_union(o_ptr->id_obj, f);

    /* Average things are average */
    if ((o_ptr->feel == FEEL_AVERAGE) && (is_weapon(o_ptr) || is_armour(o_ptr))){
	notice_other(IF_AC, slot + 1);
	notice_other(IF_TO_A, slot + 1);
	notice_other(IF_TO_H, slot + 1);
	notice_other(IF_TO_D, slot + 1);
    }

    /* Recalculate the bonuses */
    p_ptr->update |= (PU_BONUS);

    /* Optionally, display a message */
    if (msg && !quiver_slot)
    {
	/* Describe the object */
	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msg_format("You have %s (%c).", o_name, index_to_label(slot));
    }


    /* Delete the object */
    delete_object_idx(o_idx);

    /* If we have a quiver slot that this item matches, use it */
    if (quiver_slot) wield_item(o_ptr, slot, quiver_slot);
}
Example #24
0
/* pick the context menu options appropiate for the item */
int context_menu_object(const object_type *o_ptr, const int slot)
{
	menu_type *m;
	region r;
	int selected;
	char *labels;
	char header[120];

	textblock *tb;
	region area = { 0, 0, 0, 0 };

	bool allowed = TRUE;
	int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG;
	unsigned char cmdkey;

	m = menu_dynamic_new();
	if (!m || !o_ptr) {
		return 0;
	}
	object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_BASE);

	labels = string_make(lower_case);
	m->selections = labels;

	/* 'I' is used for inspect in both keymaps. */
	menu_dynamic_add_label(m, "Inspect", 'I', MENU_VALUE_INSPECT, labels);

	if (obj_can_browse(o_ptr)) {
		if (obj_can_cast_from(o_ptr) && player_can_cast(p_ptr, FALSE)) {
			ADD_LABEL("Cast", CMD_CAST, MN_ROW_VALID);
		}

		if (obj_can_study(o_ptr) && player_can_study(p_ptr, FALSE)) {
			cmd_code study_cmd = player_has(PF_CHOOSE_SPELLS) ? CMD_STUDY_SPELL : CMD_STUDY_BOOK;
			/* Hack - Use the STUDY_BOOK command key so that we get the correct command key. */
			cmdkey = cmd_lookup_key_unktrl(CMD_STUDY_BOOK, mode);
			menu_dynamic_add_label(m, "Study", cmdkey, study_cmd, labels);
		}

		if (player_can_read(p_ptr, FALSE)) {
			ADD_LABEL("Browse", CMD_BROWSE_SPELL, MN_ROW_VALID);
		}
	}
	else if (obj_is_useable(o_ptr)) {
		if (obj_is_wand(o_ptr)) {
			menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Aim", CMD_USE_WAND, valid);
		}
		else if (obj_is_rod(o_ptr)) {
			menu_row_validity_t valid = (obj_can_zap(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Zap", CMD_USE_ROD, valid);
		}
		else if (obj_is_staff(o_ptr)) {
			menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Use", CMD_USE_STAFF, valid);
		}
		else if (obj_is_scroll(o_ptr)) {
			menu_row_validity_t valid = (player_can_read(p_ptr, FALSE)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Read", CMD_READ_SCROLL, valid);
		}
		else if (obj_is_potion(o_ptr)) {
			ADD_LABEL("Quaff", CMD_QUAFF, MN_ROW_VALID);
		}
		else if (obj_is_food(o_ptr)) {
			ADD_LABEL("Eat", CMD_EAT, MN_ROW_VALID);
		}
		else if (obj_is_activatable(o_ptr)) {
			menu_row_validity_t valid = (slot >= INVEN_WIELD && obj_can_activate(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Activate", CMD_ACTIVATE, valid);
		}
		else if (obj_can_fire(o_ptr)) {
			ADD_LABEL("Fire", CMD_FIRE, MN_ROW_VALID);
		}
		else {
			ADD_LABEL("Use", CMD_USE_ANY, MN_ROW_VALID);
		}
	}

	if (obj_can_refill(o_ptr)) {
		ADD_LABEL("Refill", CMD_REFILL, MN_ROW_VALID);
	}

	if (slot >= INVEN_WIELD && obj_can_takeoff(o_ptr)) {
		ADD_LABEL("Take off", CMD_TAKEOFF, MN_ROW_VALID);
	}
	else if (slot < INVEN_WIELD && obj_can_wear(o_ptr)) {
		//if (obj_is_armor(o_ptr)) {
		//	menu_dynamic_add(m, "Wear", 2);
		//} else {
		// 	menu_dynamic_add(m, "Wield", 2);
		//}
		ADD_LABEL("Equip", CMD_WIELD, MN_ROW_VALID);
	}

	if (slot >= 0) {
		if (!store_in_store || cave_shopnum(cave, p_ptr->py, p_ptr->px) == STORE_HOME) {
			ADD_LABEL("Drop", CMD_DROP, MN_ROW_VALID);

			if (o_ptr->number > 1) {
				/* 'D' is used for squelch in rogue keymap, so we'll just swap letters. */
				cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'D' : 'k';
				menu_dynamic_add_label(m, "Drop All", cmdkey, MENU_VALUE_DROP_ALL, labels);
			}
		}
	}
	else {
		menu_row_validity_t valid = (inven_carry_okay(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
		ADD_LABEL("Pick up", CMD_PICKUP, valid);
	}

	ADD_LABEL("Throw", CMD_THROW, MN_ROW_VALID);
	ADD_LABEL("Inscribe", CMD_INSCRIBE, MN_ROW_VALID);

	if (obj_has_inscrip(o_ptr)) {
		ADD_LABEL("Uninscribe", CMD_UNINSCRIBE, MN_ROW_VALID);
	}

	ADD_LABEL( (object_is_squelched(o_ptr) ? "Unignore" : "Ignore"), CMD_DESTROY, MN_ROW_VALID);

	/* work out display region */
	r.width = (int)menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */
	r.col = Term->wid - r.width - 1;
	r.row = 1;
	r.page_rows = m->count;

	area.width = -(r.width + 2);

	/* Hack -- no flush needed */
	msg_flag = FALSE;
	screen_save();

	/* Display info */
	tb = object_info(o_ptr, OINFO_NONE);
	object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL);

	textui_textblock_place(tb, area, format("%s", header));
	textblock_free(tb);

	menu_layout(m, &r);
	region_erase_bordered(&r);

	prt(format("(Enter to select, ESC) Command for %s:", header), 0, 0);
	selected = menu_dynamic_select(m);

	menu_dynamic_free(m);
	string_free(labels);

	screen_load();

	cmdkey = cmd_lookup_key(selected, mode);

	switch (selected) {
		case -1:
			/* User cancelled the menu. */
			return 3;

		case MENU_VALUE_INSPECT:
			/* copied from textui_obj_examine */
			/* Display info */
			tb = object_info(o_ptr, OINFO_NONE);
			object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL);

			textui_textblock_show(tb, area, format("%s", header));
			textblock_free(tb);
			return 2;

		case MENU_VALUE_DROP_ALL:
			/* Drop entire stack with confirmation. */
			if (get_check(format("Drop %s? ", header))) {
				cmd_insert(store_in_store ? CMD_STASH : CMD_DROP);
				cmd_set_arg_item(cmd_get_top(), 0, slot);
				cmd_set_arg_number(cmd_get_top(), 1, o_ptr->number);
			}
			return 1;

		case CMD_STUDY_SPELL:
			/* Hack - Use the STUDY_BOOK command key so that get_item_allow() works properly. */
			cmdkey = cmd_lookup_key(CMD_STUDY_BOOK, mode);
			/* Fall through. */
		case CMD_BROWSE_SPELL:
		case CMD_STUDY_BOOK:
		case CMD_CAST:
		case CMD_DESTROY:
		case CMD_WIELD:
		case CMD_TAKEOFF:
		case CMD_INSCRIBE:
		case CMD_UNINSCRIBE:
		case CMD_PICKUP:
		case CMD_DROP:
		case CMD_REFILL:
		case CMD_THROW:
		case CMD_USE_WAND:
		case CMD_USE_ROD:
		case CMD_USE_STAFF:
		case CMD_READ_SCROLL:
		case CMD_QUAFF:
		case CMD_EAT:
		case CMD_ACTIVATE:
		case CMD_FIRE:
		case CMD_USE_ANY:
			/* Check for inscriptions that trigger confirmation. */
			allowed = key_confirm_command(cmdkey) && get_item_allow(slot, cmdkey, selected, FALSE);
			break;
		default:
			/* Invalid command; prevent anything from happening. */
			bell("Invalid context menu command.");
			allowed = FALSE;
			break;
	}

	if (!allowed)
		return 1;

	if (selected == CMD_DESTROY) {
		/* squelch or unsquelch the item */
		textui_cmd_destroy_menu(slot);
	}
	else if (selected == CMD_BROWSE_SPELL) {
		/* browse a spellbook */
		/* copied from textui_spell_browse */
		textui_book_browse(o_ptr);
		return 2;
	}
	else if (selected == CMD_STUDY_SPELL) {
		/* study a spell book */
		/* copied from textui_obj_study */
		int spell = get_spell(o_ptr, "study", spell_okay_to_study);

		if (spell >= 0) {
			cmd_insert(CMD_STUDY_SPELL);
			cmd_set_arg_choice(cmd_get_top(), 0, spell);
		}
	}
	else if (selected == CMD_CAST) {
		if (obj_can_browse(o_ptr)) {
			/* copied from textui_obj_cast */
			const char *verb = ((p_ptr->class->spell_book == TV_MAGIC_BOOK) ? "cast" : "recite");
			int spell = get_spell(o_ptr, verb, spell_okay_to_cast);

			if (spell >= 0) {
				cmd_insert(CMD_CAST);
				cmd_set_arg_choice(cmd_get_top(), 0, spell);
			}
		}
	}
	else {
Example #25
0
/**
 * Move player in the given direction, with the given "pickup" flag.
 *
 * This routine should only be called when energy has been expended.
 *
 * Note that this routine handles monsters in the destination grid,
 * and also handles attempting to move into walls/doors/etc.
 */
void move_player(int dir)
{
    int py = p_ptr->py;
    int px = p_ptr->px;

    byte str_escape, dex_escape;

    /* Permit the player to move? */
    bool can_move = FALSE;

    /* Player is jumping off a cliff */
    bool falling = FALSE;

    /* Player hits a trap (always unless flying) */
    bool trapped = TRUE;

    int temp;
    int y, x;

    /* Find the result of moving */
    y = py + ddy[dir];
    x = px + ddx[dir];


    /* Hack -- attack monsters */
    if (cave_m_idx[y][x] > 0) {
	/* Attack */
	if (py_attack(y, x, TRUE))
	    return;
    }

    /* It takes some dexterity, or failing that strength, to get out of pits */
    if (cave_feat[p_ptr->py][p_ptr->px] == (FEAT_TRAP_HEAD + 0x01)) {
	str_escape = adj_dex_dis[p_ptr->state.stat_ind[A_STR]];
	dex_escape = adj_dex_dis[p_ptr->state.stat_ind[A_DEX]];

	/* First attempt to leap out of the pit, */
	if ((dex_escape + 1) * 2 < randint1(16)) {
	    /* then attempt to climb out of the pit. */
	    if (str_escape + 3 < randint1(16)) {
		/* Failure costs a turn. */
		msg_print("You remain stuck in the pit.");
		return;
	    } else
		msg_print("You clamber out of the pit.");
	} else
	    msg_print("You leap out of the pit.");
    }


    /* Option to disarm a visible trap. -TNB- */
    /* Hack - Rogues can walk over their own trap - BR */
    if (OPT(easy_alter) && (cave_feat[y][x] >= FEAT_TRAP_HEAD)
	&& (cave_feat[y][x] <= FEAT_TRAP_TAIL)) 
    {
	bool more = FALSE;
	/* Auto-repeat if not already repeating */
	if (cmd_get_nrepeats() == 0)
	    cmd_set_repeat(99);
	
	more = do_cmd_disarm_aux(y, x);

	/* Cancel repeat unless we may continue */
	if (!more)
	    disturb(0, 0);
	return;
    }

    /* Some terrain is impassable for the player, such as stone walls. */
    else if (!cave_passable_bold(y, x)) {
	/* Disturb the player */
	disturb(0, 0);

	/* Notice unknown obstacles */
	if (!(cave_info[y][x] & (CAVE_MARK))) {
	    /* Closed door */
	    if (cave_feat[y][x] < FEAT_SECRET) {
		message(MSG_HITWALL, 0, "You feel a door blocking your way.");
		cave_info[y][x] |= (CAVE_MARK);
		light_spot(y, x);
	    }

	    /* Wall (or secret door) */
	    else {
		message(MSG_HITWALL, 0, "You feel a wall blocking your way.");
		cave_info[y][x] |= (CAVE_MARK);
		light_spot(y, x);
	    }
	}

	/* Mention known obstacles */
	else {
	    /* Closed door */
	    if (cave_feat[y][x] < FEAT_SECRET) {
		/* Option to automatically open doors. -TNB- */
		if (OPT(easy_alter)) {
		    bool more = FALSE;

		    /* Auto-repeat if not already repeating */
		    if (cmd_get_nrepeats() == 0)
			cmd_set_repeat(99);
		    
		    /* Open the door */
		    more = do_cmd_open_aux(y, x);
		    
		    /* Cancel repeat unless we may continue */
		    if (!more)
			disturb(0, 0);
		    return;
		}
		
		/* Otherwise, a message. */
		message(MSG_HITWALL, 0, "There is a door blocking your way.");
	    }

	    /* Wall (or secret door) */
	    else {
		message(MSG_HITWALL, 0, "There is a wall blocking your way.");
	    }
	}

	/* Sound */
	sound(MSG_HITWALL);
    }

    /* Normal movement */
    else 
    {
	/*** Handle traversable terrain.  ***/
	switch (cave_feat[y][x]) {
	case FEAT_RUBBLE:
	    {
		/* Dwarves move easily through rubble */
		if (player_has(PF_DWARVEN))
		    can_move = TRUE;

		/* Bats, dragons can fly */
		else if ((p_ptr->schange == SHAPE_BAT)
			 || (p_ptr->schange == SHAPE_WYRM))
		    can_move = TRUE;

		else if (player_is_crossing == dir)
		{
		    can_move = TRUE;
		    player_is_crossing = 0;
		}
		else 
		{
		    player_is_crossing = dir;
		    cmd_insert(CMD_WALK);
		}

		break;
	    }
	case FEAT_TREE:
	case FEAT_TREE2:
	    {
		/* Druids, rangers, elves and ents (SJGU) slip easily under
		 * trees */
		if (((player_has(PF_WOODSMAN)) || (player_has(PF_ELVEN)))
		    || (player_has(PF_WOODEN)))
		    can_move = TRUE;

		/* Bats, dragons can fly */
		else if ((p_ptr->schange == SHAPE_BAT)
			 || (p_ptr->schange == SHAPE_WYRM))
		    can_move = TRUE;

		/* Allow movement only if partway through already. */
		else if (player_is_crossing == dir)
		{
		    can_move = TRUE;
		    player_is_crossing = 0;
		}
		else 
		{
		    player_is_crossing = dir;
		    cmd_insert(CMD_WALK);
		}
		
		break;
	    }
	case FEAT_WATER:	/* Water now slows rather than stopping -NRM- */
	    {
		/* Stop any run. */
		disturb(0, 0);

		can_move = TRUE;

		/* Speed will need updating */
		p_ptr->update |= PU_BONUS;

		break;
	    }
	case FEAT_LAVA:
	    {
		/* Assume player will continue. */
		temp = TRUE;

		/* Smart enough to stop running. */
		if (p_ptr->running) {
		    if (!get_check("Lava blocks your path.  Step into it? ")) {
			temp = FALSE;
			p_ptr->running = 0;
		    }
		}

		/* Smart enough to sense trouble. */
		else if ((!p_resist_pos(P_RES_FIRE))
			 || (!p_resist_strong(P_RES_FIRE)
			     && (p_ptr->chp <= 100))
			 || (!p_immune(P_RES_FIRE) && (p_ptr->chp <= 30))) {
		    if (!get_check
			("The heat of the lava scalds you! Really enter? ")) {
			temp = FALSE;
		    }
		}

		/* Enter if OK or confirmed. */
		if (temp) {
		    /* Can always cross. */
		    can_move = TRUE;

		    /* Feather fall makes one lightfooted. */
		    if (p_ptr->state.ffall) {
			notice_obj(OF_FEATHER, 0);
			temp = 49 + randint1(51);
		    } else
			temp = 124 + randint1(126);

		    /* Will take serious fire damage. */
		    fire_dam(temp, "burnt to a cinder in molten lava");
		}
		break;
	    }
	case FEAT_VOID:
	    {
		/* Bats, dragons can fly */
		if ((p_ptr->schange == SHAPE_BAT)
		    || (p_ptr->schange == SHAPE_WYRM))
		    can_move = TRUE;
		else {
		    /* Assume player will continue. */
		    temp = TRUE;

		    /* Smart enough to stop running. */
		    if (p_ptr->running) {
			if (!get_check
			    ("You have come to a cliff.  Step off it? ")) {
			    temp = FALSE;
			    p_ptr->running = 0;
			}
		    }

		    /* Smart enough to sense trouble. */
		    else if (!p_ptr->timed[TMD_BLIND]) {
			if (!get_check("It's a cliff! Really step off it? ")) {
			    temp = FALSE;
			}
		    }

		    /* Step off if confirmed. */
		    if (temp) {
			/* Can always jump. */
			can_move = TRUE;

			/* Will take serious damage. */
			falling = TRUE;
		    }
		}
		break;
	    }
	default:
	    {
		/* All other terrain can be traversed normally. */
		can_move = TRUE;
	    }
	}

	/* If the player can move, handle various things. */
	if (can_move) {
	    /* Move player */
	    monster_swap(py, px, y, x);

	    /* Update speed if stepping out of water */
	    if (cave_feat[py][px] == FEAT_WATER)
		p_ptr->update |= PU_BONUS;

	    /* Update stealth for Unlight */
	    if (player_has(PF_UNLIGHT))
		p_ptr->update |= PU_BONUS;

	    /* Superstealth for ents in trees SJGU */
	    if ((player_has(PF_WOODEN))
		&&
		(tf_has
		 (f_info[cave_feat[p_ptr->py][p_ptr->px]].flags, TF_TREE))) {
		if (!(tf_has(f_info[cave_feat[py][px]].flags, TF_TREE))
		    || !(p_ptr->timed[TMD_SSTEALTH])) {
		    (void) inc_timed(TMD_SSTEALTH, 1, FALSE);
		    p_ptr->update |= (PU_BONUS);
		}
	    } else if ((player_has(PF_WOODEN))
		       && (tf_has(f_info[cave_feat[py][px]].flags, TF_TREE))) {
		if (p_ptr->timed[TMD_SSTEALTH]) {
		    (void) dec_timed(TMD_SSTEALTH, 1, FALSE);
		    p_ptr->update |= (PU_BONUS);
		}
	    }

	    /* New location */
	    y = py = p_ptr->py;
	    x = px = p_ptr->px;

	    /* No longer traversing. */
	    player_is_crossing = 0;

	    /* Fall off a cliff */
	    if (falling)
		fall_off_cliff();

	    /* Spontaneous Searching */
	    if (p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] > 49) {
		(void) search(FALSE);
	    } else if (0 == randint0(50 - p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) 
	    {
		(void) search(FALSE);
	    }

	    /* Continuous Searching */
	    if (p_ptr->searching) {
		(void) search(FALSE);
	    }

	    /* Handle "store doors" */
	    if ((cave_feat[y][x] >= FEAT_SHOP_HEAD)
		&& (cave_feat[y][x] <= FEAT_SHOP_TAIL)) {
		/* Disturb */
		disturb(0, 0);
		cmd_insert(CMD_ENTER_STORE);
	    }

	    /* All other grids (including traps) */
	    else
	    {
		/* Handle objects (later) */
		p_ptr->notice |= (PN_PICKUP);
	    }

	    /* Flying players have a chance to miss traps */
	    if ((p_ptr->schange == SHAPE_BAT) || (p_ptr->schange == SHAPE_WYRM)) {
		if (((cave_feat[y][x] == FEAT_INVIS)
		     || (cave_feat[y][x] == FEAT_GRASS_INVIS))
		    && (randint0(3) != 0))
		    trapped = FALSE;
		else if ((cave_feat[y][x] >= FEAT_TRAP_HEAD)
			 && (cave_feat[y][x] <= FEAT_TRAP_TAIL)
			 && (randint0(10) != 0))
		    trapped = FALSE;
	    }

	    /* Discover invisible traps */
	    else if (((cave_feat[y][x] == FEAT_INVIS)
		      || (cave_feat[y][x] == FEAT_GRASS_INVIS)
		      || (cave_feat[y][x] == FEAT_TREE_INVIS)
		      || (cave_feat[y][x] == FEAT_TREE2_INVIS)) && trapped) {
		/* Disturb */
		disturb(0, 0);

		/* Message */
		msg_print("You stumble upon a trap!");

		/* Pick a trap */
		pick_trap(y, x);

		/* Hit the floor trap. */
		hit_trap(y, x);
	    }

	    /* Set off a visible trap */
	    else if ((cave_feat[y][x] >= FEAT_TRAP_HEAD)
		     && (cave_feat[y][x] <= FEAT_TRAP_TAIL) && trapped) {
		/* Disturb */
		disturb(0, 0);

		/* Hit the floor trap. */
		hit_trap(y, x);
	    }

	    /* Walk on a monster trap */
	    else if ((cave_feat[y][x] >= FEAT_MTRAP_HEAD)
		     && (cave_feat[y][x] <= FEAT_MTRAP_TAIL)) {
		msg_print("You inspect your cunning trap.");
	    }
	}
    }
}
Example #26
0
/*
 * Returns chance of failure for a spell
 */
s16b spell_chance(int spell)
{
	int chance, minfail;

	const magic_type *s_ptr;


	/* Paranoia -- must be literate */
	if (!cp_ptr->spell_book) return (100);

	/* Get the spell */
	s_ptr = &mp_ptr->info[spell];

	/* Extract the base spell failure rate */
	chance = s_ptr->sfail;

	/* Reduce failure rate by "effective" level adjustment */
	chance -= 3 * (p_ptr->lev - s_ptr->slevel);

	/* Reduce failure rate by INT/WIS adjustment */
	chance -= adj_mag_stat[p_ptr->state.stat_ind[cp_ptr->spell_stat]];

	/* Not enough mana to cast */
	if (s_ptr->smana > p_ptr->csp)
	{
		chance += 5 * (s_ptr->smana - p_ptr->csp);
	}

	/* Extract the minimum failure rate */
	minfail = adj_mag_fail[p_ptr->state.stat_ind[cp_ptr->spell_stat]];

	/* Non mage/priest characters never get better than 5 percent */
	if (!player_has(PF_ZERO_FAIL) && minfail < 5)
	{
		minfail = 5;
	}

	/* Priest prayer penalty for "edged" weapons (before minfail) */
	if (p_ptr->state.icky_wield)
	{
		chance += 25;
	}

	/* Fear makes spells harder (before minfail) */
	/* Note that spells that remove fear have a much lower fail rate than
	 * surrounding spells, to make sure this doesn't cause mega fail */
	if (p_ptr->state.flags[OF_AFRAID]) chance += 20;

	/* Minimal and maximal failure rate */
	if (chance < minfail) chance = minfail;
	if (chance > 50) chance = 50;

	/* Stunning makes spells harder (after minfail) */
	if (p_ptr->timed[TMD_STUN] > 50) chance += 25;
	else if (p_ptr->timed[TMD_STUN]) chance += 15;

	/* Amnesia doubles failure change */
	if (p_ptr->timed[TMD_AMNESIA]) chance = 50 + chance / 2;

	/* Always a 5 percent chance of working */
	if (chance > 95) chance = 95;

	/* Return the chance */
	return (chance);
}
Example #27
0
static int beam_chance(void)
{
	int plev = p_ptr->lev;
	return (player_has(PF_BEAM) ? plev : (plev / 2));
}
Example #28
0
/**
 * Rogues may set traps.  Only one such trap may exist at any one time,
 * but an old trap can be disarmed to free up equipment for a new trap.
 * -LM-
 */
extern bool py_set_trap(int y, int x)
{
    int max_traps;
    s16b this_o_idx, next_o_idx = 0;
    object_type *o_ptr;
    bool destroy_message = FALSE;

    max_traps =
        1 + ((p_ptr->lev >= 25) ? 1 : 0) +
        (player_has(PF_EXTRA_TRAP) ? 1 : 0);

    if (p_ptr->timed[TMD_BLIND] || no_light()) {
        msg_print("You can not see to set a trap.");
        return FALSE;
    }

    if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) {
        msg_print("You are too confused.");
        return FALSE;
    }

    /* Paranoia -- Forbid more than max_traps being set. */
    if (num_trap_on_level >= max_traps) {
        msg_print
        ("You must disarm your existing trap to free up your equipment.");
        return FALSE;
    }

    /* No setting traps while shapeshifted */
    if (SCHANGE) {
        msg_print("You can not set traps while shapechanged.");
        msg_print("Use the ']' command to return to your normal form.");
        return FALSE;
    }

    /* Scan all objects in the grid */
    for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) {
        /* Acquire object */
        o_ptr = &o_list[this_o_idx];

        /* Acquire next object */
        next_o_idx = o_ptr->next_o_idx;

        /* Artifact */
        if (o_ptr->name1) {
            msg_print("There is an indestructible object here.");
            return FALSE;
        }

        /* Visible object to be destroyed */
        if (!squelch_hide_item(o_ptr))
            destroy_message = TRUE;
    }

    /* Verify */
    if (cave_o_idx[y][x]) {
        if (destroy_message)
            if (!get_check("Destroy all items and set a trap?"))
                return FALSE;

        for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) {
            /* Acquire object */
            o_ptr = &o_list[this_o_idx];

            /* Acquire next object */
            next_o_idx = o_ptr->next_o_idx;

            /* Delete the object */
            delete_object_idx(this_o_idx);
        }

        /* Redraw */
        light_spot(y, x);
    }

    /* Set the trap, and draw it. */
    cave_set_feat(y, x, FEAT_MTRAP_BASE);

    /* Notify the player. */
    msg_print("You set a monster trap.");

    /* Increment the number of monster traps. */
    num_trap_on_level++;

    /* A trap has been set */
    return TRUE;
}
Example #29
0
static bool cast_priest_spell(int spell, int dir)
{
	int py = p_ptr->py;
	int px = p_ptr->px;

	int plev = p_ptr->lev;

	int amt;

	switch (spell)
	{
		case PRAYER_DETECT_EVIL:
		{
			(void)detect_monsters_evil(TRUE);
			break;
		}

		case PRAYER_CURE_LIGHT_WOUNDS:
		{
			(void)heal_player(15, 15);
			(void)dec_timed(TMD_CUT, 20, TRUE);
			(void)dec_timed(TMD_CONFUSED, 20, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			break;
		}

		case PRAYER_BLESS:
		{
			(void)inc_timed(TMD_BLESSED, randint1(12) + 12, TRUE);
			break;
		}

		case PRAYER_REMOVE_FEAR:
		{
			(void)clear_timed(TMD_AFRAID, TRUE);
			break;
		}

		case PRAYER_CALL_LIGHT:
		{
			(void)light_area(damroll(2, (plev / 2)), (plev / 10) + 1);
			break;
		}

		case PRAYER_FIND_TRAPS_DOORS:
		{
			(void)detect_traps(TRUE);
			(void)detect_doorstairs(TRUE);
			break;
		}

		case PRAYER_SLOW_POISON:
		{
			(void)set_timed(TMD_POISONED, p_ptr->timed[TMD_POISONED] / 2, TRUE);
			break;
		}

		case PRAYER_SCARE_MONSTER:
		{
			(void)fear_monster(dir, plev, TRUE);
			break;
		}

		case PRAYER_PORTAL:
		{
			teleport_player(plev * 3);
			break;
		}

		case PRAYER_CURE_SERIOUS_WOUNDS:
		{
			(void)heal_player(20, 25);
			(void)clear_timed(TMD_CUT, TRUE);
			(void)clear_timed(TMD_CONFUSED, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			break;
		}

		case PRAYER_CHANT:
		{
			(void)inc_timed(TMD_BLESSED, randint1(24) + 24, TRUE);
			break;
		}

		case PRAYER_SANCTUARY:
		{
			(void)sleep_monsters_touch(TRUE);
			break;
		}

		case PRAYER_SATISFY_HUNGER:
		{
			(void)set_food(PY_FOOD_MAX - 1);
			break;
		}

		case PRAYER_REMOVE_CURSE:
		{
			remove_curse();
			break;
		}

		case PRAYER_RESIST_HEAT_COLD:
		{
			(void)inc_timed(TMD_OPP_FIRE, randint1(10) + 10, TRUE);
			(void)inc_timed(TMD_OPP_COLD, randint1(10) + 10, TRUE);
			break;
		}

		case PRAYER_NEUTRALIZE_POISON:
		{
			(void)clear_timed(TMD_POISONED, TRUE);
			break;
		}

		case PRAYER_ORB_OF_DRAINING:
		{
			fire_ball(GF_HOLY_ORB, dir,
			          (damroll(3, 6) + plev +
			           (plev / (player_has(PF_BLESS_WEAPON) ? 2 : 4))),
			          ((plev < 30) ? 2 : 3));
			break;
		}

		case PRAYER_CURE_CRITICAL_WOUNDS:
		{
			(void)heal_player(25, 30);
			(void)clear_timed(TMD_CUT, TRUE);
			(void)clear_timed(TMD_AMNESIA, TRUE);
			(void)clear_timed(TMD_CONFUSED, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)clear_timed(TMD_STUN, TRUE);
			break;
		}

		case PRAYER_SENSE_INVISIBLE:
		{
			(void)inc_timed(TMD_SINVIS, randint1(24) + 24, TRUE);
			break;
		}

		case PRAYER_PROTECTION_FROM_EVIL:
		{
			(void)inc_timed(TMD_PROTEVIL, randint1(25) + 3 * p_ptr->lev, TRUE);
			break;
		}

		case PRAYER_EARTHQUAKE:
		{
			earthquake(py, px, 10);
			break;
		}

		case PRAYER_SENSE_SURROUNDINGS:
		{
			map_area();
			break;
		}

		case PRAYER_CURE_MORTAL_WOUNDS:
		{
			(void)heal_player(30, 50);
			(void)clear_timed(TMD_CUT, TRUE);
			(void)clear_timed(TMD_AMNESIA, TRUE);
			(void)clear_timed(TMD_CONFUSED, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)clear_timed(TMD_STUN, TRUE);
			break;
		}

		case PRAYER_TURN_UNDEAD:
		{
			(void)turn_undead(TRUE);
			break;
		}

		case PRAYER_PRAYER:
		{
			(void)inc_timed(TMD_BLESSED, randint1(48) + 48, TRUE);
			break;
		}

		case PRAYER_DISPEL_UNDEAD:
		{
			(void)dispel_undead(randint1(plev * 3));
			break;
		}

		case PRAYER_HEAL:
		{
			amt = (p_ptr->mhp * 35) / 100;
                        if (amt < 300) amt = 300;
			
			(void)hp_player(amt);
			(void)clear_timed(TMD_CUT, TRUE);
			(void)clear_timed(TMD_AMNESIA, TRUE);
			(void)clear_timed(TMD_CONFUSED, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)clear_timed(TMD_STUN, TRUE);
			break;
		}

		case PRAYER_DISPEL_EVIL:
		{
			(void)dispel_evil(randint1(plev * 3));
			break;
		}

		case PRAYER_GLYPH_OF_WARDING:
		{
			warding_glyph();
			break;
		}

		case PRAYER_HOLY_WORD:
		{
			(void)dispel_evil(randint1(plev * 4));
			(void)hp_player(1000);
			(void)clear_timed(TMD_AFRAID, TRUE);
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)clear_timed(TMD_STUN, TRUE);
			(void)clear_timed(TMD_CUT, TRUE);
			break;
		}

		case PRAYER_DETECT_MONSTERS:
		{
			(void)detect_monsters_normal(TRUE);
			break;
		}

		case PRAYER_DETECTION:
		{
			(void)detect_all(TRUE);
			break;
		}

		case PRAYER_PERCEPTION:
		{
			return ident_spell();
		}

		case PRAYER_PROBING:
		{
			(void)probing();
			break;
		}

		case PRAYER_CLAIRVOYANCE:
		{
			wiz_light();
			break;
		}

		case PRAYER_CURE_SERIOUS_WOUNDS2:
		{
			(void)heal_player(20, 25);
			(void)clear_timed(TMD_CUT, TRUE);
			(void)clear_timed(TMD_CONFUSED, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			break;
		}

		case PRAYER_CURE_MORTAL_WOUNDS2:
		{
			(void)heal_player(30, 50);
			(void)clear_timed(TMD_CUT, TRUE);
			(void)clear_timed(TMD_AMNESIA, TRUE);
			(void)clear_timed(TMD_CONFUSED, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)clear_timed(TMD_STUN, TRUE);
			break;
		}

		case PRAYER_HEALING:
		{
			(void)hp_player(2000);
			(void)clear_timed(TMD_STUN, TRUE);
			(void)clear_timed(TMD_CUT, TRUE);
			break;
		}

		case PRAYER_RESTORATION:
		{
			(void)do_res_stat(A_STR);
			(void)do_res_stat(A_INT);
			(void)do_res_stat(A_WIS);
			(void)do_res_stat(A_DEX);
			(void)do_res_stat(A_CON);
			(void)do_res_stat(A_CHR);
			break;
		}

		case PRAYER_REMEMBRANCE:
		{
			(void)restore_level();
			break;
		}

		case PRAYER_DISPEL_UNDEAD2:
		{
			(void)dispel_undead(randint1(plev * 4));
			break;
		}

		case PRAYER_DISPEL_EVIL2:
		{
			(void)dispel_evil(randint1(plev * 4));
			break;
		}

		case PRAYER_BANISH_EVIL:
		{
			if (banish_evil(100))
			{
				msg("The power of your god banishes evil!");
			}
			break;
		}

		case PRAYER_WORD_OF_DESTRUCTION:
		{
			destroy_area(py, px, 15, TRUE);
			break;
		}

		case PRAYER_ANNIHILATION:
		{
			drain_life(dir, 200);
			break;
		}

		case PRAYER_UNBARRING_WAYS:
		{
			(void)destroy_doors_touch();
			break;
		}

		case PRAYER_RECHARGING:
		{
			return recharge(15);
		}

		case PRAYER_DISPEL_CURSE:
		{
			(void)remove_all_curse();
			break;
		}

		case PRAYER_ENCHANT_WEAPON:
		{
			return enchant_spell(randint0(4) + 1, randint0(4) + 1, 0);
		}

		case PRAYER_ENCHANT_ARMOUR:
		{
			return enchant_spell(0, 0, randint0(3) + 2);
		}

		case PRAYER_ELEMENTAL_BRAND:
		{
			brand_weapon();
			break;
		}

		case PRAYER_BLINK:
		{
			teleport_player(10);
			break;
		}

		case PRAYER_TELEPORT_SELF:
		{
			teleport_player(plev * 8);
			break;
		}

		case PRAYER_TELEPORT_OTHER:
		{
			(void)teleport_monster(dir);
			break;
		}

		case PRAYER_TELEPORT_LEVEL:
		{
			(void)teleport_player_level();
			break;
		}

		case PRAYER_WORD_OF_RECALL:
		{
			set_recall();
			break;
		}

		case PRAYER_ALTER_REALITY:
		{
			msg("The world changes!");

			/* Leaving */
			p_ptr->leaving = TRUE;

			break;
		}
	}

	/* Success */
	return (TRUE);
}
Example #30
0
/**
 * Outputs the damage we do/would do with the current bow and this ammo
 */
static bool describe_ammo_damage(textblock * tb, const object_type * o_ptr,
								 oinfo_detail_t mode)
{
	int i;
	object_type *i_ptr;

	bool full = mode & OINFO_FULL;
	bool terse = mode & OINFO_TERSE;
	bool first = TRUE;
	bool perfect = (of_has(o_ptr->id_obj, OF_PERFECT_BALANCE) ||
					(of_has(o_ptr->flags_obj, OF_PERFECT_BALANCE)
					 && full));

	int brand[MAX_P_BRAND], slay[MAX_P_SLAY];

	/* Extract the slays and brands */
	for (i = 0; i < MAX_P_SLAY; i++)
		slay[i] = (if_has(o_ptr->id_other, OBJECT_ID_BASE_SLAY + i)
				   || full)
			? o_ptr->multiple_slay[i] : MULTIPLE_BASE;
	for (i = 0; i < MAX_P_BRAND; i++)
		brand[i] = (if_has(o_ptr->id_other, OBJECT_ID_BASE_BRAND + i)
					|| full)
			? o_ptr->multiple_brand[i] : MULTIPLE_BASE;

	/* Hack -- paladins (and priests) cannot take advantage of temporary
	 * elemental brands to rescue their lousy shooting skill. Missile
	 * weapons are "kind of" edged, right? */
	if (!player_has(PF_BLESS_WEAPON) || (o_ptr->tval > TV_BOLT)) {
		if (p_ptr->special_attack & (ATTACK_ACID))
			brand[P_BRAND_ACID] =
				MAX(brand[P_BRAND_ACID], BRAND_BOOST_NORMAL);
		if (p_ptr->special_attack & (ATTACK_ELEC))
			brand[P_BRAND_ELEC] =
				MAX(brand[P_BRAND_ELEC], BRAND_BOOST_NORMAL);
		if (p_ptr->special_attack & (ATTACK_FIRE))
			brand[P_BRAND_FIRE] =
				MAX(brand[P_BRAND_FIRE], BRAND_BOOST_NORMAL);
		if (p_ptr->special_attack & (ATTACK_COLD))
			brand[P_BRAND_COLD] =
				MAX(brand[P_BRAND_COLD], BRAND_BOOST_NORMAL);
		if (p_ptr->special_attack & (ATTACK_POIS))
			brand[P_BRAND_POIS] =
				MAX(brand[P_BRAND_POIS], BRAND_BOOST_NORMAL);
	}
	if (p_ptr->special_attack & (ATTACK_HOLY))
		slay[P_SLAY_EVIL] = MAX(slay[P_SLAY_EVIL], 15);

	if (o_ptr->tval > TV_BOLT) {
		if (terse)
			textblock_append(tb, "Av. throwing dam. ");
		else
			textblock_append(tb,
							 "Throwing it you would do an average damage of ");
		for (i = 0; i < MAX_P_SLAY; i++)
			if (slay[i] > MULTIPLE_BASE)
				output_ammo_dam(tb, &p_ptr->state, o_ptr, slay[i],
								slayee[i], &first, perfect, mode);

		for (i = 0; i < MAX_P_BRAND; i++)
			if (brand[i] > MULTIPLE_BASE) {
				char buf[40];

				strnfmt(buf, sizeof(buf), "non %s resistant creatures",
						brandee[i]);
				output_ammo_dam(tb, &p_ptr->state, o_ptr, brand[i], buf,
								&first, perfect, mode);
			}

		output_ammo_dam(tb, &p_ptr->state, o_ptr, MULTIPLE_BASE,
						(first) ? "all monsters" : "other monsters",
						&first, perfect, mode);
		textblock_append(tb, ". ");

		return TRUE;
	} else if (p_ptr->state.ammo_tval == o_ptr->tval) {
		/* Check launcher for additional brands (slays) */
		i_ptr = &p_ptr->inventory[INVEN_BOW];

		/* If wielding a launcher - sanity check */
		if (i_ptr->k_idx) {
			/* Pick up any brands (and slays!) */
			for (i = 0; i < MAX_P_SLAY; i++)
				slay[i] =
					MAX(slay[i],
						(if_has(i_ptr->id_other, OBJECT_ID_BASE_SLAY + i)
						 || full)
						? i_ptr->multiple_slay[i] : MULTIPLE_BASE);
			for (i = 0; i < MAX_P_BRAND; i++)
				brand[i] =
					MAX(brand[i],
						(if_has(i_ptr->id_other, OBJECT_ID_BASE_BRAND + i)
						 || full)
						? i_ptr->multiple_brand[i] : MULTIPLE_BASE);
		}

		if (terse)
			textblock_append(tb, "Av shooting dam. ");
		else
			textblock_append(tb,
							 "\nUsing it with your current launcher you would do an average damage per shot of ");

		for (i = 0; i < MAX_P_SLAY; i++)
			if (slay[i] > MULTIPLE_BASE)
				output_ammo_dam(tb, &p_ptr->state, o_ptr, slay[i],
								slayee[i], &first, perfect, mode);

		for (i = 0; i < MAX_P_BRAND; i++)
			if (brand[i] > MULTIPLE_BASE) {
				char buf[40];

				strnfmt(buf, sizeof(buf), "non %s resistant creatures",
						brandee[i]);
				output_ammo_dam(tb, &p_ptr->state, o_ptr, brand[i], buf,
								&first, perfect, mode);
			}

		output_ammo_dam(tb, &p_ptr->state, o_ptr, MULTIPLE_BASE,
						(first) ? "all monsters" : "other monsters",
						&first, perfect, mode);
		textblock_append(tb, ". ");

		return TRUE;
	} else if (!terse) {
		textblock_append(tb,
						 "\nYou cannot use this missile with your current launcher. ");

		return TRUE;

	}
	return FALSE;

}