/* * 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); }
/** * 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)); }
/* 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; }
/* 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; }
/** * Display the options and redraw afterward. */ extern void do_cmd_reshape(void) { if ((!SCHANGE) && (player_has(PF_BEARSKIN))) { bear_shape(); } else unchange(); }
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; } }
/** * 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); }
/* * 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); }
/** * 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); }
/** * 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); }
/** * 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])); }
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; }
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; }
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); }
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; }
/** * 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); }
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(""); } }
/** * 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); }
/* 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; }
/** * 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); }
/** * 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(); }
/** * 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); }
/** * 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); }
/* 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 {
/** * 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."); } } } }
/* * 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); }
static int beam_chance(void) { int plev = p_ptr->lev; return (player_has(PF_BEAM) ? plev : (plev / 2)); }
/** * 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; }
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); }
/** * 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; }