static int _choose_spell_to_gain(object_type *o_ptr) { rect_t r = _menu_rect(); int result = -1; int cmd; bool done = FALSE; screen_save(); while (!done) { prt("Memorize which spell?", 0, 0); _display_spells_to_gain(o_ptr, r); cmd = inkey_special(FALSE); if (cmd == ESCAPE || cmd == 'q' || cmd == 'Q') done = TRUE; if ('a' <= cmd && cmd < 'a' + _SPELLS_PER_BOOK) { int spell_idx = o_ptr->sval * _SPELLS_PER_BOOK + A2I(cmd); magic_type *spell_ptr = _get_spell_info(tval2realm(o_ptr->tval), spell_idx); if (spell_ptr->slevel <= p_ptr->lev) /* Note: Illegible spells have slevel == 99 in m_info.txt */ { done = TRUE; result = spell_idx; } } } screen_load(); return result; }
/* * This function builds probability tables from a list of purely alphabetical * lower-case words, and puts them into the supplied name_probs object. * The array of names should have a NULL entry at the end of the list. * It relies on the ASCII character set (through use of A2I). */ static void build_prob(name_probs probs, cptr *learn) { int c_prev, c_cur, c_next; cptr ch; int i; /* Build raw frequencies */ for (i = 0; learn[i] != NULL; i++) { c_prev = c_cur = S_WORD; ch = learn[i]; /* Iterate over the next word */ while (*ch != '\0') { c_next = A2I(tolower((unsigned char)*ch)); probs[c_prev][c_cur][c_next]++; probs[c_prev][c_cur][TOTAL]++; /* Step on */ c_prev = c_cur; c_cur = c_next; ch++; } probs[c_prev][c_cur][E_WORD]++; probs[c_prev][c_cur][TOTAL]++; } }
U0 LogScrambleFile(U8 *name) { CDoc *doc=DocRead(name,DOCF_PLAIN_TEXT); CDocEntry *doc_e=doc->root.next; I64 i; U32 num; U8 *st,*st2; "Scrambling:%s\n",name; while (doc_e!=doc) { if (doc_e->type_u8==DOCT_TEXT) { st=MAlloc(StrLen(doc_e->tag)+1); st2=MAlloc(StrLen(doc_e->tag)+1); StrFirstRem(doc_e->tag," ",st); for (i=3;i>=0;i--) { StrFirstRem(st,".",st2); num.u8[i]=key[i][A2I(st2)&255]; } Free(st); Free(st2); st=MSPrintF("%d.%d.%d.%d %s",num.u8[3],num.u8[2],num.u8[1],num.u8[0],doc_e->tag); Free(doc_e->tag); doc_e->tag=st; } doc_e=doc_e->next; } DocWrite(doc); DocDel(doc); }
/** * Convert a label into an item in the inventory. * * Return NULL if the label does not indicate a real item. */ struct object *label_to_inven(int c) { int i; /* Convert */ i = (islower((unsigned char)c) ? A2I(c) : -1); /* Verify the index */ if ((i < 0) || (i > z_info->pack_size)) return NULL; /* Return the object */ return player->upkeep->inven[i]; }
/* * Get the choice corresponding to the character * chosen, and the number of possible choices. * * Return whether we want this choice verified or not. */ static int get_choice(char *c, int num, bool *ask) { int asked; int i; *c = inkey(); /* Handle "cancel" */ if (*c == ESCAPE) { return (-2); } if (num < 19) { if (isalpha(*c)) { /* Note verify */ asked = (isupper(*c)); /* Lowercase */ if (asked) *c = tolower(*c); *ask = (asked != FALSE); /* Extract request */ return(A2I(*c)); } /* Invalid choice */ *ask = FALSE; return (-1); } /* Else - look for a match */ for (i = 0; i < num; i++) { if (listsym[i] == *c) { /* Hack - we cannot ask if there are too many options */ *ask = FALSE; return (i); } } /* No match? */ *ask = FALSE; return (-1); }
/** * Convert a label into an item in the equipment. * * Return NULL if the label does not indicate a real item. */ struct object *label_to_equip(int c) { int i; /* Convert */ i = (islower((unsigned char)c) ? A2I(c) : -1); /* Verify the index */ if ((i < 0) || (i >= player->body.count)) return NULL; /* Return the object */ return slot_object(player, i); }
/** Adjusts heights in height map to contain required amount of water tiles */ static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new) { height_t h_min, h_max, h_avg, h_water_level; int64 water_tiles, desired_water_tiles; height_t *h; int *hist; HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg); /* Allocate histogram buffer and clear its cells */ int *hist_buf = CallocT<int>(h_max - h_min + 1); /* Fill histogram */ hist = HeightMapMakeHistogram(h_min, h_max, hist_buf); /* How many water tiles do we want? */ desired_water_tiles = A2I(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y)); /* Raise water_level and accumulate values from histogram until we reach required number of water tiles */ for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) { water_tiles += hist[h_water_level]; if (water_tiles >= desired_water_tiles) break; } /* We now have the proper water level value. * Transform the height map into new (normalized) height map: * values from range: h_min..h_water_level will become negative so it will be clamped to 0 * values from range: h_water_level..h_max are transformed into 0..h_max_new * where h_max_new is 4, 8, 12 or 16 depending on terrain type (very flat, flat, hilly, mountains) */ FOR_ALL_TILES_IN_HEIGHT(h) { /* Transform height from range h_water_level..h_max into 0..h_max_new range */ *h = (height_t)(((int)h_max_new) * (*h - h_water_level) / (h_max - h_water_level)) + I2H(1); /* Make sure all values are in the proper range (0..h_max_new) */ if (*h < 0) *h = I2H(0); if (*h >= h_max_new) *h = h_max_new - 1; } free(hist_buf); }
s32b do_cmd_activate_skill_aux(s32b type) { s32b which; s32b max = 0, i, start = 0; s32b ret = 0, x_idx; bool mode = easy_inven; s32b *p; cptr *p_desc; C_MAKE(p, max_s_idx + max_ab_idx, s32b); C_MAKE(p_desc, max_s_idx + max_ab_idx, cptr); /* Count the max */ /* More than 1 combat skill ? */ if (get_combat_num() > 1) { p_desc[max] = "Change combat mode"; p[max++] = 0; } for (i = 1; i < max_s_idx; i++) { x_idx = s_info[i].action_mkey[type]; if (x_idx && get_skill(i) && (!s_info[i].hidden)) { s32b j; bool next = FALSE; /* Already got it ? */ for (j = 0; j < max; j++) { if (x_idx == p[j]) { next = TRUE; break; } } if (next) continue; if(process_hooks(HOOK_MKEY_HIDE, "(d,d)", x_idx, type)) continue; p_desc[max] = s_info[i].action_desc[type]; p[max++] = x_idx; } } for (i = 0; i < max_ab_idx; i++) { x_idx = ab_info[i].action_mkey[type]; if (x_idx && ab_info[i].acquired) { s32b j; bool next = FALSE; /* Already got it ? */ for (j = 0; j < max; j++) { if (x_idx == p[j]) { next = TRUE; break; } } if (next) continue; if(process_hooks(HOOK_MKEY_HIDE, "(d,d)", x_idx, type)) continue; p_desc[max] = ab_info[i].action_desc[type]; p[max++] = x_idx; } } if (!max) { msg_print("You don't have any activable skills or abilities."); return -1; } character_icky++; Term_save(); while (1) { print_skill_batch(p, p_desc, start, max, mode); which = inkey(); if (which == ESCAPE) { ret = -1; break; } else if (which == '*' || which == '?' || which == ' ') { mode = (mode) ? FALSE : TRUE; Term_load(); Term_save(); } else if (which == '+') { start += 20; if (start >= max) start -= 20; Term_load(); Term_save(); } else if (which == '-') { start -= 20; if (start < 0) start += 20; Term_load(); Term_save(); } else if (which == '@') { char buf[80]; strcpy(buf, "Cast a spell"); if (!get_string("Skill action? ", buf, 79)) break; /* Find the skill it is related to */ for (i = 0; i < max; i++) { if (!strcmp(buf, p_desc[i])) break; } if ((i < max)) { ret = p[i]; break; } } else { which = tolower(which); if (start + A2I(which) >= max) { bell(); continue; } if (start + A2I(which) < 0) { bell(); continue; } ret = p[start + A2I(which)]; break; } } Term_load(); character_icky--; C_FREE(p, max_s_idx + max_ab_idx, s32b); C_FREE(p_desc, max_s_idx + max_ab_idx, cptr); return ret; }
/* * Generic "get choice from menu" function */ int get_player_choice(cptr *choices, int num, int col, int wid, cptr helpfile, void (*hook) (cptr)) { int top = 0, cur = 0; /* int bot = 13; */ int i, dir; char c; char buf[80]; bool done = FALSE; int hgt; /* Autoselect if able */ if (num == 1) done = TRUE; /* Clear */ for (i = TABLE_ROW; i < Term->hgt; i++) { /* Clear */ Term_erase(col, i, Term->wid - wid); } /* Choose */ while (TRUE) { /* * Note to Melkor: What happens when the screen is resized? * There is no 'redraw' hook at this point... * (That is why the original code restricted itself to what * would fit in the smallest possible screen.) -SF- */ hgt = Term->hgt - TABLE_ROW - 1; /* Redraw the list */ for (i = 0; ((i + top < num) && (i <= hgt)); i++) { if (i + top < 26) { strnfmt(buf, 80, "%c) %s", I2A(i + top), choices[i + top]); } else { /* ToDo: Fix the ASCII dependency */ strnfmt(buf, 80, "%c) %s", 'A' + (i + top - 26), choices[i + top]); } /* Clear */ Term_erase(col, i + TABLE_ROW, wid); /* Display */ if (i == (cur - top)) { /* Highlight the current selection */ put_fstr(col, i + TABLE_ROW, CLR_L_BLUE "%s", buf); } else { put_fstr(col, i + TABLE_ROW, buf); } } if (done) return (cur); /* Display auxiliary information if any is available. */ if (hook) hook(choices[cur]); /* Move the cursor */ Term_gotoxy(col, TABLE_ROW + cur - top); c = inkey(); if (c == KTRL('X')) { quit(NULL); } if (c == ESCAPE) { /* Mega Hack - go back. */ return (INVALID_CHOICE); } if (c == '*') { /* Select at random */ cur = randint0(num); /* Move it onto the screen */ if ((cur < top) || (cur > top + hgt)) { top = cur; } /* Done */ done = TRUE; } else if (c == '?') { (void)show_file(helpfile, NULL, 0, 0); } else if (c == '=') { do_cmd_options(OPT_FLAG_BIRTH | OPT_FLAG_SERVER | OPT_FLAG_PLAYER); } else if ((c == '\n') || (c == '\r')) { /* Done */ return (cur); } else if (isdigit(c)) { /* Get a direction from the key */ dir = get_keymap_dir(c); /* Going up? */ if (dir == 8) { if (cur != 0) { /* Move selection */ cur--; } if ((top > 0) && ((cur - top) < 4)) { /* Scroll up */ top--; } } /* Going down? */ if (dir == 2) { if (cur != (num - 1)) { /* Move selection */ cur++; } if ((top + hgt < (num - 1)) && ((top + hgt - cur) < 4)) { /* Scroll down */ top++; } } } else if (isalpha(c)) { int choice; if (islower(c)) { choice = A2I(c); } else { choice = c - 'A' + 26; } /* Validate input */ if ((choice > -1) && (choice < num)) { cur = choice; /* Move it onto the screen */ if ((cur < top) || (cur > top + hgt)) { top = cur; } /* Done */ done = TRUE; } else { /* Invalid input */ bell("Illegal birth choice!"); } } } return (INVALID_CHOICE); }
boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4 *trig_stats) { sgmnt_addrs *csa; char curr_name[MAX_MIDENT_LEN + 1]; uint4 curr_name_len, orig_name_len; mval mv_curr_nam; char *ptr; char *name_tail_ptr; char save_name[MAX_MIDENT_LEN + 1]; gv_key save_currkey[DBKEYALLOC(MAX_KEY_SZ)]; gd_region *save_gv_cur_region, *lgtrig_reg; gv_namehead *save_gv_target; sgm_info *save_sgm_info_ptr; mval trig_gbl; mval *trigger_count; char trigvn[MAX_MIDENT_LEN + 1]; int trigvn_len; int trig_indx; int badpos; boolean_t wildcard; char utilprefix[1024]; int utilprefixlen; boolean_t first_gtmio; uint4 triggers_deleted; mval trigjrec; boolean_t jnl_format_done; gd_region *reg, *reg_top; char disp_trigvn[MAX_MIDENT_LEN + SPANREG_REGION_LITLEN + MAX_RN_LEN + 1 + 1]; /* SPANREG_REGION_LITLEN for " (region ", MAX_RN_LEN for region name, * 1 for ")" and 1 for trailing '\0'. */ int disp_trigvn_len; int trig_protected_mval_push_count; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; badpos = 0; trigjrec.mvtype = MV_STR; trigjrec.str.len = trigger_name_len--; trigjrec.str.addr = trigger_name++; orig_name_len = trigger_name_len; if ((0 == trigger_name_len) || (trigger_name_len != (badpos = validate_input_trigger_name(trigger_name, trigger_name_len, &wildcard)))) { /* is the input name valid */ CONV_STR_AND_PRINT("Invalid trigger NAME string: ", orig_name_len, trigger_name); /* badpos is the string position where the bad character was found, pretty print it */ trig_stats[STATS_ERROR_TRIGFILE]++; return TRIG_FAILURE; } name_tail_ptr = trigger_name + trigger_name_len - 1; if ((TRIGNAME_SEQ_DELIM == *name_tail_ptr) || wildcard) trigger_name_len--; /* drop the trailing # sign for wildcard */ jnl_format_done = FALSE; lgtrig_reg = NULL; first_gtmio = TRUE; triggers_deleted = 0; assert(trigger_name_len < MAX_MIDENT_LEN); memcpy(save_name, trigger_name, trigger_name_len); save_name[trigger_name_len] = '\0'; utilprefixlen = ARRAYSIZE(utilprefix); trig_protected_mval_push_count = 0; INCR_AND_PUSH_MV_STENT(trigger_count); /* Protect trigger_count from garbage collection */ for (reg = gd_header->regions, reg_top = reg + gd_header->n_regions; reg < reg_top; reg++) { GVTR_SWITCH_REG_AND_HASHT_BIND_NAME(reg); csa = cs_addrs; if (NULL == csa) /* not BG or MM access method */ continue; /* gv_target now points to ^#t in region "reg" */ /* To write the LGTRIG logical jnl record, choose some region that has journaling enabled */ if (!reg->read_only && !jnl_format_done && JNL_WRITE_LOGICAL_RECS(csa)) lgtrig_reg = reg; if (!gv_target->root) continue; memcpy(curr_name, save_name, trigger_name_len); curr_name_len = trigger_name_len; do { /* GVN = $get(^#t("#TNAME",curr_name)) */ BUILD_HASHT_SUB_SUB_CURRKEY(LITERAL_HASHTNAME, STRLEN(LITERAL_HASHTNAME), curr_name, curr_name_len); if (gvcst_get(&trig_gbl)) { if (reg->read_only) rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_TRIGMODREGNOTRW, 2, REG_LEN_STR(reg)); SAVE_TRIGGER_REGION_INFO(save_currkey); ptr = trig_gbl.str.addr; trigvn_len = MIN(trig_gbl.str.len, MAX_MIDENT_LEN); STRNLEN(ptr, trigvn_len, trigvn_len); ptr += trigvn_len; if ((trig_gbl.str.len == trigvn_len) || ('\0' != *ptr)) { /* We expect $c(0) in the middle of ptr. If not found, this is a restartable situation */ if (CDB_STAGNATE > t_tries) t_retry(cdb_sc_triggermod); assert(WBTEST_HELPOUT_TRIGDEFBAD == gtm_white_box_test_case_number); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TRIGNAMBAD, 4, LEN_AND_LIT("\"#TNAME\""), curr_name_len, curr_name); } memcpy(trigvn, trig_gbl.str.addr, trigvn_len); /* the index is just beyond the length of the GVN string */ ptr++; A2I(ptr, trig_gbl.str.addr + trig_gbl.str.len, trig_indx); if (1 > trig_indx) { /* Trigger indexes start from 1 */ if (CDB_STAGNATE > t_tries) t_retry(cdb_sc_triggermod); assert(WBTEST_HELPOUT_TRIGDEFBAD == gtm_white_box_test_case_number); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TRIGNAMBAD, 4, LEN_AND_LIT("\"#TNAME\""), curr_name_len, curr_name); } SET_DISP_TRIGVN(reg, disp_trigvn, disp_trigvn_len, trigvn, trigvn_len); /* $get(^#t(GVN,"COUNT") */ BUILD_HASHT_SUB_SUB_CURRKEY(trigvn, trigvn_len, LITERAL_HASHCOUNT, STRLEN(LITERAL_HASHCOUNT)); if (!gvcst_get(trigger_count)) { UTIL_PRINT_PREFIX_IF_NEEDED(first_gtmio, utilprefix, &utilprefixlen); util_out_print_gtmio("Trigger named !AD exists in the lookup table, " "but global ^!AD has no triggers", FLUSH, curr_name_len, curr_name, disp_trigvn_len, disp_trigvn); trig_stats[STATS_ERROR_TRIGFILE]++; RETURN_AND_POP_MVALS(TRIG_FAILURE); } if (!jnl_format_done && JNL_WRITE_LOGICAL_RECS(csa)) { jnl_format(JNL_LGTRIG, NULL, &trigjrec, 0); jnl_format_done = TRUE; } /* kill the target trigger for GVN at index trig_indx */ if (PUT_SUCCESS != (trigger_delete(trigvn, trigvn_len, trigger_count, trig_indx))) { UTIL_PRINT_PREFIX_IF_NEEDED(first_gtmio, utilprefix, &utilprefixlen); util_out_print_gtmio("Trigger named !AD exists in the lookup table for global ^!AD," \ " but was not deleted!", FLUSH, orig_name_len, trigger_name, disp_trigvn_len, disp_trigvn); trig_stats[STATS_ERROR_TRIGFILE]++; RETURN_AND_POP_MVALS(TRIG_FAILURE); } else { csa->incr_db_trigger_cycle = TRUE; trigger_incr_cycle(trigvn, trigvn_len); /* ^#t records changed, increment cycle */ if (dollar_ztrigger_invoked) { /* Increment db_dztrigger_cycle so that next gvcst_put/gvcst_kill in this * transaction, on this region, will re-read triggers. See trigger_update.c * for a comment on why it is okay for db_dztrigger_cycle to be incremented * more than once in the same transaction. */ csa->db_dztrigger_cycle++; } trig_stats[STATS_DELETED]++; if (0 == trig_stats[STATS_ERROR_TRIGFILE]) { UTIL_PRINT_PREFIX_IF_NEEDED(first_gtmio, utilprefix, &utilprefixlen); util_out_print_gtmio("Deleted trigger named '!AD' for global ^!AD", FLUSH, curr_name_len, curr_name, disp_trigvn_len, disp_trigvn); } } trigger_count->mvtype = 0; /* allow stp_gcol to release the current contents if necessary */ RESTORE_TRIGGER_REGION_INFO(save_currkey); triggers_deleted++; } if (!wildcard) /* not a wild card, don't $order for the next match */ break; op_gvorder(&mv_curr_nam); if (0 == mv_curr_nam.str.len) break; assert(mv_curr_nam.str.len < MAX_MIDENT_LEN); memcpy(curr_name, mv_curr_nam.str.addr, mv_curr_nam.str.len); curr_name_len = mv_curr_nam.str.len; if (0 != memcmp(curr_name, save_name, trigger_name_len)) /* stop when gv_order returns a string that no longer starts save_name */ break; } while (TRUE); } DECR_AND_POP_MV_STENT(); if (!jnl_format_done && (NULL != lgtrig_reg)) { /* There was no journaled region that had a ^#t update, but found at least one journaled region * so write a LGTRIG logical jnl record there. */ GVTR_SWITCH_REG_AND_HASHT_BIND_NAME(lgtrig_reg); csa = cs_addrs; /* Attach to jnlpool. Normally SET or KILL of the ^#t records take care of this but in * case this is a NO-OP trigger operation that wont update any ^#t records and we still * want to write a TLGTRIG/ULGTRIG journal record. Hence the need to do this. */ JNLPOOL_INIT_IF_NEEDED(csa, csa->hdr, csa->nl); assert(dollar_tlevel); /* below is needed to set update_trans TRUE on this region even if NO db updates happen to ^#t nodes */ T_BEGIN_SETORKILL_NONTP_OR_TP(ERR_TRIGLOADFAIL); jnl_format(JNL_LGTRIG, NULL, &trigjrec, 0); jnl_format_done = TRUE; } if (wildcard) { UTIL_PRINT_PREFIX_IF_NEEDED(first_gtmio, utilprefix, &utilprefixlen); if (triggers_deleted) { trig_stats[STATS_NOERROR_TRIGFILE]++; util_out_print_gtmio("All existing triggers named !AD (count = !UL) now deleted", FLUSH, orig_name_len, trigger_name, triggers_deleted); } else { trig_stats[STATS_UNCHANGED_TRIGFILE]++; util_out_print_gtmio("No matching triggers of the form !AD found for deletion", FLUSH, orig_name_len, trigger_name); } } else if (triggers_deleted) { /* util_out_print_gtmio of "Deleted trigger named ..." already done so no need to do it again */ trig_stats[STATS_NOERROR_TRIGFILE]++; } else { /* No names match. But treat it as a no-op (i.e. success). */ UTIL_PRINT_PREFIX_IF_NEEDED(first_gtmio, utilprefix, &utilprefixlen); util_out_print_gtmio("Trigger named !AD does not exist", FLUSH, orig_name_len, trigger_name); trig_stats[STATS_UNCHANGED_TRIGFILE]++; } return TRIG_SUCCESS; }
/* Upgrade ^#t global in "reg" region */ void trigger_upgrade(gd_region *reg) { boolean_t est_first_pass, do_upgrade, is_defined; boolean_t was_null = FALSE, is_null = FALSE; int seq_num, trig_seq_num; int currlabel; mval tmpmval, xecuteimval, *gvname, *tmpmv, *tmpmv2; int4 result, tmpint4; uint4 curend, gvname_prev, xecute_curend; uint4 hash_code, kill_hash_code; int count, i, xecutei, tncount; char *trigname, *trigindex, *ptr; char name_and_index[MAX_MIDENT_LEN + 1 + MAX_DIGITS_IN_INT]; char trigvn[MAX_MIDENT_LEN + 1 + MAX_DIGITS_IN_INT], nullbyte[1]; uint4 trigname_len, name_index_len; int ilen; sgmnt_addrs *csa; jnl_private_control *jpc; uint4 sts; int close_res; hash128_state_t hash_state, kill_hash_state; uint4 hash_totlen, kill_hash_totlen; int trig_protected_mval_push_count; # ifdef DEBUG int save_dollar_tlevel; # endif DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; assert(gv_cur_region == reg); assert(!dollar_tlevel); /* caller should have ensured this. this is needed as otherwise things get complicated. */ assert(!is_replicator); /* caller should have ensured this. this is needed so we dont bump jnl_seqno (if replicating) */ csa = &FILE_INFO(reg)->s_addrs; assert(csa->hdr->hasht_upgrade_needed); /* If before-image journaling is turned on in this region (does not matter if replication is turned on or not), * once this transaction is done, we need to switch to new journal file and cut the back link because * otherwise it is possible for backward journal recovery (or rollback) or source server to encounter * the journal records generated in this ^#t-upgrade-transaction in which case they dont know to handle * it properly (e.g. rollback or backward recovery does not know to restore csa->hdr->hasht_upgrade_needed * if it rolls back this transaction). To achieve this, we set hold_onto_crit to TRUE and do the jnl link * cut AFTER the transaction commits but before anyone else can sneak in to do any more updates. * Since most often we expect databases to be journaled, we do this hold_onto_crit even for the non-journaled case. */ grab_crit(reg); csa->hold_onto_crit = TRUE; DEBUG_ONLY(save_dollar_tlevel = dollar_tlevel); assert(!donot_INVOKE_MUMTSTART); DEBUG_ONLY(donot_INVOKE_MUMTSTART = TRUE); op_tstart(IMPLICIT_TSTART, TRUE, &literal_batch, 0); /* 0 ==> save no locals but RESTART OK */ ESTABLISH_NORET(trigger_upgrade_ch, est_first_pass); /* On a TP restart anywhere down below, this line is where the restart resumes execution from */ assert(donot_INVOKE_MUMTSTART); /* Make sure still set for every try/retry of TP transaction */ change_reg(); /* TP_CHANGE_REG wont work as we need to set sgm_info_ptr */ assert(NULL != cs_addrs); assert(csa == cs_addrs); SET_GVTARGET_TO_HASHT_GBL(csa); /* sets up gv_target */ assert(NULL != gv_target); INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED; /* Needed to do every retry in case restart was due to an online rollback. * This also sets up gv_currkey */ /* Do actual upgrade of ^#t global. * * Below is a sample layout of the label 2 ^#t global * ------------------------------------------------------- * ^#t("#TNAME","x")="a"_$C(0)_"1" (present in DEFAULT only) * ^#t("#TRHASH",89771515,1)="a"_$C(0)_"1" (present in DEFAULT only) * ^#t("#TRHASH",106937755,1)="a"_$C(0)_"1" (present in DEFAULT only) * ^#t("a",1,"BHASH")="106937755" * ^#t("a",1,"CHSET")="M" * ^#t("a",1,"CMD")="S" * ^#t("a",1,"LHASH")="89771515" * ^#t("a",1,"TRIGNAME")="x#" * ^#t("a",1,"XECUTE")=" do ^twork" * ^#t("a","#COUNT")="1" * ^#t("a","#CYCLE")="1" * ^#t("a","#LABEL")="2" * * Below is a sample layout of the label 3 ^#t global * ------------------------------------------------------- * ^#t("#LABEL")="3" (present only after upgrade, not regular trigger load) * ^#t("#TNAME","x")="a"_$C(0)_"1" (present in CURRENT region) * ^#t("a",1,"BHASH")="71945627" * ^#t("a",1,"CHSET")="M" * ^#t("a",1,"CMD")="S" * ^#t("a",1,"LHASH")="71945627" * ^#t("a",1,"TRIGNAME")="x#" * ^#t("a",1,"XECUTE")=" do ^twork" * ^#t("a","#COUNT")="1" * ^#t("a","#CYCLE")="2" * ^#t("a","#LABEL")="3" * ^#t("a","#TRHASH",71945627,1)="a"_$C(0)_"1" * * Key aspects of the format change * ---------------------------------- * 1) New ^#t("#LABEL")="3" to indicate the format of the ^#t global. This is in addition to * ^#t("a","#LABEL") etc. which is already there. This way we have a #LABEL for not just the installed * triggers but also for the name information stored in the #TNAME nodes. * 2) In the BHASH and LHASH fields. The hash computation is different so there are more chances of BHASH and LHASH * matching in which case we store only one #TRHASH entry (instead of two). So thre is fewer ^#t records in the new * format in most cases. * 3) ^#t("a","#LABEL") bumps from 2 to 3. Similarly ^#t("a","#CYCLE") bumps by one (to make sure triggers for this * global get re-read if and when we implement an -ONLINE upgrade). * 4) DEFAULT used to have ^#t("#TNAME",...) nodes corresponding to triggers across ALL regions in the gbldir and * other regions used to have NO ^#t("#TNAME",...) nodes whereas after the upgrade every region have * ^#t("#TNAME",...) nodes corresponding to triggers installed in that region. So it is safer to kill ^#t("#TNAME") * nodes and add them as needed. * 5) #TRHASH has moved from ^#t() to ^#t(<gbl>). So it is safer to kill ^#t("#TRHASH") nodes and add them as needed. * * Below is a sample layout of the label 4 ^#t global * ------------------------------------------------------- * ^#t("#TNAME","x")="a"_$C(0)_"1" (present in CURRENT region) * ^#t("a",1,"BHASH")="71945627" * ^#t("a",1,"CHSET")="M" * ^#t("a",1,"CMD")="S" * ^#t("a",1,"LHASH")="71945627" * ^#t("a",1,"TRIGNAME")="x#" * ^#t("a",1,"XECUTE")=" do ^twork" * ^#t("a","#COUNT")="1" * ^#t("a","#CYCLE")="2" * ^#t("a","#LABEL")="4" * ^#t("a","#TRHASH",71945627,1)="a"_$C(0)_"1" * * Key aspects of the format change * ---------------------------------- * 1) Removed ^#t("#LABEL") as it is redundant information and trigger load does not include it * 2) Multiline triggers were incorrectly processed resulting in incorrect BHASH and LHASH values. Upgrade fixes this * 3) ^#t("a","#LABEL") bumps from 3 to 4. Similarly ^#t("a","#CYCLE") bumps by one (to make sure * triggers for this global get re-read if and when we implement an -ONLINE upgrade). */ tmpmv = &tmpmval; /* At all points maintain this relationship. The two are used interchangeably below */ if (gv_target->root) do_upgrade = TRUE; /* The below logic assumes ^#t global does not have any integrity errors */ assert(do_upgrade); /* caller should have not invoked us otherwise */ if (do_upgrade) { /* kill ^#t("#TRHASH"), ^#t("#TNAME") and ^#t("#LABEL") first. Regenerate each again as we process ^#t(<gbl>,...) */ csa->incr_db_trigger_cycle = TRUE; /* so that we increment csd->db_trigger_cycle at commit time. * this forces concurrent processes to read upgraded triggers. */ if (JNL_WRITE_LOGICAL_RECS(csa)) { /* Note that the ^#t upgrade is a physical layout change. But it has no logical change (i.e. users * see the same MUPIP TRIGGER -SELECT output as before). So write only a dummy LGTRIG journal * record for this operation. Hence write a string that starts with a trigger comment character ";". */ assert(!gv_cur_region->read_only); jnl_format(JNL_LGTRIG, NULL, (mval *)&literal_trigjnlrec, 0); } /* KILL ^#t("#LABEL") unconditionally */ BUILD_HASHT_SUB_CURRKEY(LITERAL_HASHLABEL, STRLEN(LITERAL_HASHLABEL)); if (0 != gvcst_data()) gvcst_kill(TRUE); /* KILL ^#t("#TNAME") unconditionally and regenerate */ BUILD_HASHT_SUB_CURRKEY(LITERAL_HASHTNAME, STRLEN(LITERAL_HASHTNAME)); if (0 != gvcst_data()) gvcst_kill(TRUE); /* KILL ^#t("#TRHASH") unconditionally and regenerate */ BUILD_HASHT_SUB_CURRKEY(LITERAL_HASHTRHASH, STRLEN(LITERAL_HASHTRHASH)); if (0 != gvcst_data()) gvcst_kill(TRUE); /* Loop through all global names for which ^#t(<gvn>) exists. The only first-level subscripts of ^#t starting * with # are #TNAME and #TRHASH in collation order. So after #TRHASH we expect to find subscripts that are * global names. Hence the HASHTRHASH code is placed AFTER the HASHTNAME code above. */ TREF(gd_targ_gvnh_reg) = NULL; /* needed so op_gvorder below goes through gvcst_order (i.e. focuses only * on the current region) and NOT through gvcst_spr_order (which does not * apply anyways in the case of ^#t). */ nullbyte[0] = '\0'; trig_protected_mval_push_count = 0; INCR_AND_PUSH_MV_STENT(gvname); /* Protect gvname from garbage collection */ do { op_gvorder(gvname); if (0 == gvname->str.len) break; assert(ARRAYSIZE(trigvn) > gvname->str.len); memcpy(&trigvn[0], gvname->str.addr, gvname->str.len); gvname->str.addr = &trigvn[0]; /* point away from stringpool to avoid stp_gcol issues */ /* Save gv_currkey->prev so it is restored before next call to op_gvorder (which cares about this field). * gv_currkey->prev gets tampered with in the for loop below (e.g. BUILD_HASHT_SUB_CURRKEY macro). * No need to do this for gv_currkey->end since the body of the for loop takes care of restoring it. */ gvname_prev = gv_currkey->prev; BUILD_HASHT_SUB_CURRKEY(gvname->str.addr, gvname->str.len); /* At this point, gv_currkey is ^#t(<gvn>) */ /* Increment ^#t(<gvn>,"#CYCLE") */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_hashcycle, tmpmv); assert(is_defined); tmpint4 = mval2i(tmpmv); tmpint4++; i2mval(tmpmv, tmpint4); gvtr_set_hasht_gblsubs((mval *)&literal_hashcycle, tmpmv); /* Read ^#t(<gvn>,"#COUNT") */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_hashcount, tmpmv); if (is_defined) { tmpint4 = mval2i(tmpmv); count = tmpint4; /* Get ^#t(<gvn>,"#LABEL"), error out for invalid values. Upgrade disallowed for label 1 triggers */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_hashlabel, tmpmv); assert(is_defined); currlabel = mval2i(tmpmv); if ((V19_HASHT_GBL_LABEL_INT >= currlabel) || (HASHT_GBL_CURLABEL_INT <= currlabel)) rts_error_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_TRIGUPBADLABEL, 6, currlabel, HASHT_GBL_CURLABEL_INT, gvname->str.len, gvname->str.addr, REG_LEN_STR(reg)); /* Set ^#t(<gvn>,"#LABEL")=HASHT_GBL_CURLABEL */ gvtr_set_hasht_gblsubs((mval *)&literal_hashlabel, (mval *)&literal_curlabel); } else count = 0; /* Kill ^#t(<gvn>,"#TRHASH") unconditionally and regenerate */ gvtr_kill_hasht_gblsubs((mval *)&literal_hashtrhash, TRUE); /* At this point, gv_currkey is ^#t(<gvn>) */ for (i = 1; i <= count; i++) { /* At this point, gv_currkey is ^#t(<gvn>) */ curend = gv_currkey->end; /* note gv_currkey->end before changing it so we can restore it later */ assert(KEY_DELIMITER == gv_currkey->base[curend]); assert(gv_target->gd_csa == cs_addrs); i2mval(tmpmv, i); COPY_SUBS_TO_GVCURRKEY(tmpmv, gv_cur_region, gv_currkey, was_null, is_null); /* At this point, gv_currkey is ^#t(<gvn>,i) */ /* Compute new LHASH and BHASH hash values. * LHASH uses : GVSUBS, XECUTE * BHASH uses : GVSUBS, DELIM, ZDELIM, PIECES, XECUTE * So reach each of these pieces and compute hash along the way. */ STR_PHASH_INIT(hash_state, hash_totlen); STR_PHASH_PROCESS(hash_state, hash_totlen, gvname->str.addr, gvname->str.len); STR_PHASH_PROCESS(hash_state, hash_totlen, nullbyte, 1); /* Read in ^#t(<gvn>,i,"GVSUBS") */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_gvsubs, tmpmv); if (is_defined) { STR_PHASH_PROCESS(hash_state, hash_totlen, tmpmval.str.addr, tmpmval.str.len); STR_PHASH_PROCESS(hash_state, hash_totlen, nullbyte, 1); } /* Copy over SET hash state (2-tuple <state,totlen>) to KILL hash state before adding * the PIECES, DELIM, ZDELIM portions (those are only part of the SET hash). */ kill_hash_state = hash_state; kill_hash_totlen = hash_totlen; /* Read in ^#t(<gvn>,i,"PIECES") */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_pieces, tmpmv); if (is_defined) { STR_PHASH_PROCESS(hash_state, hash_totlen, tmpmval.str.addr, tmpmval.str.len); STR_PHASH_PROCESS(hash_state, hash_totlen, nullbyte, 1); } /* Read in ^#t(<gvn>,i,"DELIM") */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_delim, tmpmv); if (is_defined) { STR_PHASH_PROCESS(hash_state, hash_totlen, tmpmval.str.addr, tmpmval.str.len); STR_PHASH_PROCESS(hash_state, hash_totlen, nullbyte, 1); } /* Read in ^#t(<gvn>,i,"ZDELIM") */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_zdelim, tmpmv); if (is_defined) { STR_PHASH_PROCESS(hash_state, hash_totlen, tmpmval.str.addr, tmpmval.str.len); STR_PHASH_PROCESS(hash_state, hash_totlen, nullbyte, 1); } /* Read in ^#t(<gvn>,i,"XECUTE"). * Note: The XECUTE portion of the trigger definition is used in SET and KILL hash. * But since we have started maintaining "hash_state" and "kill_hash_state" separately * (due to PIECES, DELIM, ZDELIM) we need to update the hash for both using same input string. */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_xecute, tmpmv); if (is_defined) { STR_PHASH_PROCESS(hash_state, hash_totlen, tmpmval.str.addr, tmpmval.str.len); STR_PHASH_PROCESS(kill_hash_state, kill_hash_totlen, tmpmval.str.addr, tmpmval.str.len); } else { /* Multi-record XECUTE string */ /* At this point, gv_currkey is ^#t(<gvn>,i) */ xecute_curend = gv_currkey->end; /* note gv_currkey->end so we can restore it later */ assert(KEY_DELIMITER == gv_currkey->base[xecute_curend]); tmpmv2 = (mval *)&literal_xecute; COPY_SUBS_TO_GVCURRKEY(tmpmv2, gv_cur_region, gv_currkey, was_null, is_null); xecutei = 1; do { i2mval(&xecuteimval, xecutei); is_defined = gvtr_get_hasht_gblsubs(&xecuteimval, tmpmv); if (!is_defined) break; STR_PHASH_PROCESS(hash_state, hash_totlen, tmpmval.str.addr, tmpmval.str.len); STR_PHASH_PROCESS(kill_hash_state, kill_hash_totlen, tmpmval.str.addr, tmpmval.str.len); xecutei++; } while (TRUE); /* Restore gv_currkey to ^#t(<gvn>,i) */ gv_currkey->end = xecute_curend; gv_currkey->base[xecute_curend] = KEY_DELIMITER; } STR_PHASH_RESULT(hash_state, hash_totlen, hash_code); STR_PHASH_RESULT(kill_hash_state, kill_hash_totlen, kill_hash_code); /* Set ^#t(<gvn>,i,"LHASH") */ MV_FORCE_UMVAL(tmpmv, kill_hash_code); gvtr_set_hasht_gblsubs((mval *)&literal_lhash, tmpmv); /* Set ^#t(<gvn>,i,"BHASH") */ MV_FORCE_UMVAL(tmpmv, hash_code); gvtr_set_hasht_gblsubs((mval *)&literal_bhash, tmpmv); /* Read in ^#t(<gvn>,i,"TRIGNAME") to determine if #SEQNUM/#TNCOUNT needs to be maintained */ is_defined = gvtr_get_hasht_gblsubs((mval *)&literal_trigname, tmpmv); assert(is_defined); assert('#' == tmpmval.str.addr[tmpmval.str.len - 1]); tmpmval.str.len--; if ((tmpmval.str.len <= ARRAYSIZE(name_and_index)) && (NULL != (ptr = memchr(tmpmval.str.addr, '#', tmpmval.str.len)))) { /* Auto-generated name. Need to maintain #SEQNUM/#TNCOUNT */ /* Take copy of trigger name into non-stringpool location to avoid stp_gcol issues */ trigname_len = ptr - tmpmval.str.addr; ptr++; name_index_len = (tmpmval.str.addr + tmpmval.str.len) - ptr; assert(ARRAYSIZE(name_and_index) >= (trigname_len + 1 + name_index_len)); trigname = &name_and_index[0]; trigindex = ptr; memcpy(trigname, tmpmval.str.addr, tmpmval.str.len); A2I(ptr, ptr + name_index_len, trig_seq_num); /* At this point, gv_currkey is ^#t(<gvn>,i) */ /* $get(^#t("#TNAME",<trigger name>,"#SEQNUM")) */ BUILD_HASHT_SUB_SUB_SUB_CURRKEY(LITERAL_HASHTNAME, STR_LIT_LEN(LITERAL_HASHTNAME), trigname, trigname_len, LITERAL_HASHSEQNUM, STR_LIT_LEN(LITERAL_HASHSEQNUM)); seq_num = gvcst_get(tmpmv) ? mval2i(tmpmv) : 0; if (trig_seq_num > seq_num) { /* Set ^#t("#TNAME",<trigger name>,"#SEQNUM") = trig_seq_num */ SET_TRIGGER_GLOBAL_SUB_SUB_SUB_STR(LITERAL_HASHTNAME, STR_LIT_LEN(LITERAL_HASHTNAME), trigname, trigname_len, LITERAL_HASHSEQNUM, STR_LIT_LEN(LITERAL_HASHSEQNUM), trigindex, name_index_len, result); assert(PUT_SUCCESS == result); } /* set ^#t("#TNAME",<trigger name>,"#TNCOUNT")++ */ BUILD_HASHT_SUB_SUB_SUB_CURRKEY(LITERAL_HASHTNAME, STR_LIT_LEN(LITERAL_HASHTNAME), trigname, trigname_len, LITERAL_HASHTNCOUNT, STR_LIT_LEN(LITERAL_HASHTNCOUNT)); tncount = gvcst_get(tmpmv) ? mval2i(tmpmv) + 1 : 1; i2mval(tmpmv, tncount); SET_TRIGGER_GLOBAL_SUB_SUB_SUB_MVAL(LITERAL_HASHTNAME, STR_LIT_LEN(LITERAL_HASHTNAME), trigname, trigname_len, LITERAL_HASHTNCOUNT, STR_LIT_LEN(LITERAL_HASHTNCOUNT), tmpmval, result); trigname_len += 1 + name_index_len; /* in preparation for ^#t("#TNAME") set below */ assert(PUT_SUCCESS == result); BUILD_HASHT_SUB_CURRKEY(gvname->str.addr, gvname->str.len); /* At this point, gv_currkey is ^#t(<gvn>) */ } else { /* Take copy of trigger name into non-stringpool location to avoid stp_gcol issues */ trigname = &name_and_index[0]; /* in preparation for ^#t("#TNAME") set below */ trigname_len = MIN(tmpmval.str.len, ARRAYSIZE(name_and_index)); assert(ARRAYSIZE(name_and_index) >= trigname_len); memcpy(trigname, tmpmval.str.addr, trigname_len); /* Restore gv_currkey to what it was at beginning of for loop iteration */ gv_currkey->end = curend; gv_currkey->base[curend] = KEY_DELIMITER; } /* At this point, gv_currkey is ^#t(<gvn>) */ if (kill_hash_code != hash_code) gvtr_set_hashtrhash(gvname->str.addr, gvname->str.len, kill_hash_code, i); /* Set ^#t(<gvn>,"#TRHASH",hash_code,i) */ gvtr_set_hashtrhash(gvname->str.addr, gvname->str.len, hash_code, i); /* Set ^#t("#TNAME",<trigname>)=<gvn>_$c(0)_<trigindx> */ /* The upgrade assumes that the region does not contain two triggers with the same name. * V62000 and before could potentially have this out of design case. Once implemented * the trigger integrity check will warn users of this edge case */ ptr = &trigvn[gvname->str.len]; *ptr++ = '\0'; ilen = 0; I2A(ptr, ilen, i); ptr += ilen; assert(ptr <= ARRAYTOP(trigvn)); SET_TRIGGER_GLOBAL_SUB_SUB_STR(LITERAL_HASHTNAME, STR_LIT_LEN(LITERAL_HASHTNAME), trigname, trigname_len, trigvn, ptr - gvname->str.addr, result); assert(PUT_SUCCESS == result); BUILD_HASHT_SUB_CURRKEY(gvname->str.addr, gvname->str.len); /* At this point, gv_currkey is ^#t(<gvn>) */ } /* At this point, gv_currkey is ^#t(<gvn>) i.e. gv_currkey->end is correct but gv_currkey->prev * might have been tampered with. Restore it to proper value first. */ gv_currkey->prev = gvname_prev; gvname->mvtype = 0; /* can now be garbage collected in the next iteration */ } while (TRUE); } op_tcommit(); REVERT; /* remove our condition handler */ DEBUG_ONLY(donot_INVOKE_MUMTSTART = FALSE;) if (csa->hold_onto_crit)
/* * Let the user select an item, save its "index" * * Return TRUE only if an acceptable item was chosen by the user. * * The selected item must satisfy the "item_tester_hook()" function, * if that hook is set, and the "item_tester_tval", if that value is set. * * All "item_tester" restrictions are cleared before this function returns. * * The user is allowed to choose acceptable items from the equipment, * inventory, or floor, respectively, if the proper flag was given, * and there are any acceptable items in that location. * * The equipment or inventory are displayed (even if no acceptable * items are in that location) if the proper flag was given. * * If there are no acceptable items available anywhere, and "str" is * not NULL, then it will be used as the text of a warning message * before the function returns. * * Note that the user must press "-" to specify the item on the floor, * and there is no way to "examine" the item on the floor, while the * use of "capital" letters will "examine" an inventory/equipment item, * and prompt for its use. * * If a legal item is selected from the inventory, we save it in "cp" * directly (0 to 35), and return TRUE. * * If a legal item is selected from the floor, we save it in "cp" as * a negative (-1 to -511), and return TRUE. * * If no item is available, we do nothing to "cp", and we display a * warning message, using "str" if available, and return FALSE. * * If no item is selected, we do nothing to "cp", and return FALSE. * * Global "p_ptr->command_wrk" is used to choose between equip/inven/floor * listings. It is equal to USE_INVEN or USE_EQUIP or USE_FLOOR, except * when this function is first called, when it is equal to zero, which will * cause it to be set to USE_INVEN. * * We always erase the prompt when we are done, leaving a blank line, * or a warning message, if appropriate, if no items are available. * * Note that only "acceptable" floor objects get indexes, so between two * commands, the indexes of floor objects may change. XXX XXX XXX */ bool get_item(int *cp, cptr pmt, cptr str, cmd_code cmd, int mode) { int py = p_ptr->py; int px = p_ptr->px; unsigned char cmdkey = cmd_lookup_key(cmd); ui_event_data which; int j, k; int i1, i2; int e1, e2; int f1, f2; bool done, item; bool oops = FALSE; bool use_inven = ((mode & USE_INVEN) ? TRUE : FALSE); bool use_equip = ((mode & USE_EQUIP) ? TRUE : FALSE); bool use_floor = ((mode & USE_FLOOR) ? TRUE : FALSE); bool use_quiver = ((mode & QUIVER_TAGS) ? TRUE : FALSE); bool is_harmless = ((mode & IS_HARMLESS) ? TRUE : FALSE); bool quiver_tags = ((mode & QUIVER_TAGS) ? TRUE : FALSE); olist_detail_t olist_mode = 0; bool allow_inven = FALSE; bool allow_equip = FALSE; bool allow_floor = FALSE; bool toggle = FALSE; char tmp_val[160]; char out_val[160]; int floor_list[MAX_FLOOR_STACK]; int floor_num; bool show_list = TRUE; /* Object list display modes */ if (mode & SHOW_FAIL) olist_mode |= (OLIST_FAIL); else olist_mode |= (OLIST_WEIGHT); if (mode & SHOW_PRICES) olist_mode |= (OLIST_PRICE); /* Paranoia XXX XXX XXX */ message_flush(); /* Not done */ done = FALSE; /* No item selected */ item = FALSE; /* Full inventory */ i1 = 0; i2 = INVEN_PACK - 1; /* Forbid inventory */ if (!use_inven) i2 = -1; /* Restrict inventory indexes */ while ((i1 <= i2) && (!get_item_okay(i1))) i1++; while ((i1 <= i2) && (!get_item_okay(i2))) i2--; /* Accept inventory */ if (i1 <= i2) allow_inven = TRUE; /* Full equipment */ e1 = INVEN_WIELD; e2 = ALL_INVEN_TOTAL - 1; /* Forbid equipment */ if (!use_equip) e2 = -1; /* Restrict equipment indexes */ while ((e1 <= e2) && (!get_item_okay(e1))) e1++; while ((e1 <= e2) && (!get_item_okay(e2))) e2--; /* Accept equipment */ if (e1 <= e2) allow_equip = TRUE; /* Scan all non-gold objects in the grid */ floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), py, px, 0x03); /* Full floor */ f1 = 0; f2 = floor_num - 1; /* Forbid floor */ if (!use_floor) f2 = -1; /* Restrict floor indexes */ while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f1]))) f1++; while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f2]))) f2--; /* Accept floor */ if (f1 <= f2) allow_floor = TRUE; /* Require at least one legal choice */ if (!allow_inven && !allow_equip && !allow_floor) { /* Oops */ oops = TRUE; done = TRUE; } /* Analyze choices */ else { /* Hack -- Start on equipment if requested */ if ((p_ptr->command_wrk == USE_EQUIP) && use_equip) p_ptr->command_wrk = USE_EQUIP; /* If we are using the quiver then start on equipment */ else if (use_quiver) p_ptr->command_wrk = USE_EQUIP; /* Use inventory if allowed */ else if (use_inven) p_ptr->command_wrk = USE_INVEN; /* Use equipment if allowed */ else if (use_equip) p_ptr->command_wrk = USE_EQUIP; /* Use floor if allowed */ else if (use_floor) p_ptr->command_wrk = USE_FLOOR; /* Hack -- Use (empty) inventory */ else p_ptr->command_wrk = USE_INVEN; } /* Start out in "display" mode */ if (show_list) { /* Save screen */ screen_save(); } /* Repeat until done */ while (!done) { int ni = 0; int ne = 0; /* Scan windows */ for (j = 0; j < REPOSBAND_TERM_MAX; j++) { /* Unused */ if (!reposband_term[j]) continue; /* Count windows displaying inven */ if (op_ptr->window_flag[j] & (PW_INVEN)) ni++; /* Count windows displaying equip */ if (op_ptr->window_flag[j] & (PW_EQUIP)) ne++; } /* Toggle if needed */ if (((p_ptr->command_wrk == USE_EQUIP) && ni && !ne) || ((p_ptr->command_wrk == USE_INVEN) && !ni && ne)) { /* Toggle */ toggle_inven_equip(); /* Track toggles */ toggle = !toggle; } /* Redraw */ p_ptr->redraw |= (PR_INVEN | PR_EQUIP); /* Redraw windows */ redraw_stuff(); /* Viewing inventory */ if (p_ptr->command_wrk == USE_INVEN) { /* Redraw if needed */ if (show_list) show_inven(olist_mode); /* Begin the prompt */ strnfmt(out_val, sizeof(out_val), "Inven:"); /* List choices */ if (i1 <= i2) { /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", index_to_label(i1), index_to_label(i2)); /* Append */ my_strcat(out_val, tmp_val, sizeof(out_val)); } /* Indicate ability to "view" */ if (!show_list) { my_strcat(out_val, " * to see,", sizeof(out_val)); button_add("[*]", '*'); } /* Indicate legality of "toggle" */ if (use_equip) { my_strcat(out_val, " / for Equip,", sizeof(out_val)); button_add("[/]", '/'); } /* Indicate legality of the "floor" */ if (allow_floor) { my_strcat(out_val, " - for floor,", sizeof(out_val)); button_add("[-]", '-'); } } /* Viewing equipment */ else if (p_ptr->command_wrk == USE_EQUIP) { /* Redraw if needed */ if (show_list) show_equip(olist_mode); /* Begin the prompt */ strnfmt(out_val, sizeof(out_val), "Equip:"); /* List choices */ if (e1 <= e2) { /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", index_to_label(e1), index_to_label(e2)); /* Append */ my_strcat(out_val, tmp_val, sizeof(out_val)); } /* Indicate ability to "view" */ if (!show_list) { my_strcat(out_val, " * to see,", sizeof(out_val)); button_add("[*]", '*'); } /* Indicate legality of "toggle" */ if (use_inven) { my_strcat(out_val, " / for Inven,", sizeof(out_val)); button_add("[/]", '/'); } /* Indicate legality of the "floor" */ if (allow_floor) { my_strcat(out_val, " - for floor,", sizeof(out_val)); button_add("[!]", '!'); } } /* Viewing floor */ else { /* Redraw if needed */ if (show_list) show_floor(floor_list, floor_num, olist_mode); /* Begin the prompt */ strnfmt(out_val, sizeof(out_val), "Floor:"); /* List choices */ if (f1 <= f2) { /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", I2A(f1), I2A(f2)); /* Append */ my_strcat(out_val, tmp_val, sizeof(out_val)); } /* Indicate ability to "view" */ if (!show_list) { my_strcat(out_val, " * to see,", sizeof(out_val)); button_add("[*]", '*'); } /* Append */ if (use_inven) { my_strcat(out_val, " / for Inven,", sizeof(out_val)); button_add("[/]", '/'); } /* Append */ else if (use_equip) { my_strcat(out_val, " / for Equip,", sizeof(out_val)); button_add("[/]", '/'); } } redraw_stuff(); /* Finish the prompt */ my_strcat(out_val, " ESC", sizeof(out_val)); /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), "(%s) %s", out_val, pmt); /* Show the prompt */ prt(tmp_val, 0, 0); /* Get a key */ which = inkey_ex(); /* Parse it */ switch (which.key) { case ESCAPE: { done = TRUE; break; } case '/': { /* Toggle to inventory */ if (use_inven && (p_ptr->command_wrk != USE_INVEN)) { p_ptr->command_wrk = USE_INVEN; } /* Toggle to equipment */ else if (use_equip && (p_ptr->command_wrk != USE_EQUIP)) { p_ptr->command_wrk = USE_EQUIP; } /* No toggle allowed */ else { bell("Cannot switch item selector!"); break; } /* Hack -- Fix screen */ if (show_list) { /* Load screen */ screen_load(); /* Save screen */ screen_save(); } /* Need to redraw */ break; } case '-': { /* Paranoia */ if (!allow_floor) { bell("Cannot select floor!"); break; } /* There is only one item */ if (floor_num == 1) { /* Auto-select */ if (p_ptr->command_wrk == (USE_FLOOR)) { /* Special index */ k = 0 - floor_list[0]; /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } } /* Hack -- Fix screen */ if (show_list) { /* Load screen */ screen_load(); /* Save screen */ screen_save(); } p_ptr->command_wrk = (USE_FLOOR); #if 0 /* Check each legal object */ for (i = 0; i < floor_num; ++i) { /* Special index */ k = 0 - floor_list[i]; /* Skip non-okay objects */ if (!get_item_okay(k)) continue; /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, is_harmless)) continue; /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } #endif break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* Look up the tag */ if (!get_tag(&k, which.key, cmd, quiver_tags)) { bell("Illegal object choice (tag)!"); break; } /* Hack -- Validate the item */ if ((k < INVEN_WIELD) ? !allow_inven : !allow_equip) { bell("Illegal object choice (tag)!"); break; } /* Validate the item */ if (!get_item_okay(k)) { bell("Illegal object choice (tag)!"); break; } /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } case '\n': case '\r': { /* Choose "default" inventory item */ if (p_ptr->command_wrk == USE_INVEN) { if (i1 != i2) { bell("Illegal object choice (default)!"); break; } k = i1; } /* Choose the "default" slot (0) of the quiver */ else if (quiver_tags) k = e1; /* Choose "default" equipment item */ else if (p_ptr->command_wrk == USE_EQUIP) { if (e1 != e2) { bell("Illegal object choice (default)!"); break; } k = e1; } /* Choose "default" floor item */ else { if (f1 != f2) { bell("Illegal object choice (default)!"); break; } k = 0 - floor_list[f1]; } /* Validate the item */ if (!get_item_okay(k)) { bell("Illegal object choice (default)!"); break; } /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } default: { bool verify; /* Note verify */ verify = (isupper((unsigned char)which.key) ? TRUE : FALSE); /* Lowercase */ which.key = tolower((unsigned char)which.key); /* Convert letter to inventory index */ if (p_ptr->command_wrk == USE_INVEN) { k = label_to_inven(which.key); if (k < 0) { bell("Illegal object choice (inven)!"); break; } } /* Convert letter to equipment index */ else if (p_ptr->command_wrk == USE_EQUIP) { k = label_to_equip(which.key); if (k < 0) { bell("Illegal object choice (equip)!"); break; } } /* Convert letter to floor index */ else { k = (islower((unsigned char)which.key) ? A2I(which.key) : -1); if (k < 0 || k >= floor_num) { bell("Illegal object choice (floor)!"); break; } /* Special index */ k = 0 - floor_list[k]; } /* Validate the item */ if (!get_item_okay(k)) { bell("Illegal object choice (normal)!"); break; } /* Verify the item */ if (verify && !verify_item("Try", k)) { done = TRUE; break; } /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } } } /* Fix the screen if necessary */ if (show_list) { /* Load screen */ screen_load(); /* Hack -- Cancel "display" */ show_list = FALSE; } /* Kill buttons */ button_kill('*'); button_kill('/'); button_kill('-'); button_kill('!'); redraw_stuff(); /* Forget the item_tester_tval restriction */ item_tester_tval = 0; /* Forget the item_tester_hook restriction */ item_tester_hook = NULL; /* Toggle again if needed */ if (toggle) toggle_inven_equip(); /* Update */ p_ptr->redraw |= (PR_INVEN | PR_EQUIP); redraw_stuff(); /* Clear the prompt line */ prt("", 0, 0); /* Warning if needed */ if (oops && str) msg_print(str); /* Result */ return (item); }
boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4 *trig_stats) { sgmnt_addrs *csa; char curr_name[MAX_MIDENT_LEN + 1]; uint4 curr_name_len, orig_name_len; mstr gbl_name; mname_entry gvent; gv_namehead *hasht_tree; int len; mval mv_curr_nam; boolean_t name_found; char *ptr; char *name_tail_ptr; char save_currkey[SIZEOF(gv_key) + DBKEYSIZE(MAX_KEY_SZ)]; gv_key *save_gv_currkey; gd_region *save_gv_cur_region; gv_namehead *save_gv_target; char save_name[MAX_MIDENT_LEN + 1]; sgm_info *save_sgm_info_ptr; mval trig_gbl; mval trig_value; mval trigger_count; char trigvn[MAX_MIDENT_LEN + 1]; int trigvn_len; int trig_indx; int badpos; boolean_t wildcard; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; badpos = 0; orig_name_len = trigger_name_len; if ((0 == trigger_name_len) || (trigger_name_len != (badpos = validate_input_trigger_name(trigger_name, trigger_name_len, &wildcard)))) { /* is the input name valid */ CONV_STR_AND_PRINT("Invalid trigger NAME string: ", orig_name_len, trigger_name); /* badpos is the string position where the bad character was found, pretty print it */ return TRIG_FAILURE; } name_tail_ptr = trigger_name + trigger_name_len - 1; if (TRIGNAME_SEQ_DELIM == *name_tail_ptr || wildcard ) /* drop the trailing # sign or wildcard */ trigger_name_len--; /* $data(^#t) */ SWITCH_TO_DEFAULT_REGION; INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED; if (0 == gv_target->root) { util_out_print_gtmio("Trigger named !AD does not exist", FLUSH, orig_name_len, trigger_name); return TRIG_FAILURE; } name_found = FALSE; assert(trigger_name_len < MAX_MIDENT_LEN); memcpy(save_name, trigger_name, trigger_name_len); save_name[trigger_name_len] = '\0'; memcpy(curr_name, save_name, trigger_name_len); curr_name_len = trigger_name_len; STR2MVAL(mv_curr_nam, trigger_name, trigger_name_len); do { /* GVN = $get(^#t("#TNAME",curr_name) */ BUILD_HASHT_SUB_SUB_CURRKEY(LITERAL_HASHTNAME, STRLEN(LITERAL_HASHTNAME), curr_name, curr_name_len); if (gvcst_get(&trig_gbl)) { SAVE_TRIGGER_REGION_INFO; ptr = trig_gbl.str.addr; trigvn_len = STRLEN(trig_gbl.str.addr); assert(MAX_MIDENT_LEN >= trigvn_len); memcpy(trigvn, ptr, trigvn_len); ptr += trigvn_len + 1; /* the index is just beyon the length of the GVN string */ A2I(ptr, trig_gbl.str.addr + trig_gbl.str.len, trig_indx); gbl_name.addr = trigvn; gbl_name.len = trigvn_len; GV_BIND_NAME_ONLY(gd_header, &gbl_name); csa = gv_target->gd_csa; SETUP_TRIGGER_GLOBAL; INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED; /* $get(^#t(GVN,"COUNT") */ BUILD_HASHT_SUB_SUB_CURRKEY(trigvn, trigvn_len, LITERAL_HASHCOUNT, STRLEN(LITERAL_HASHCOUNT)); /* if it does not exist, return false */ if (!gvcst_get(&trigger_count)) { util_out_print_gtmio("Trigger named !AD exists in the lookup table, " "but global ^!AD has no triggers", FLUSH, curr_name_len, curr_name, trigvn_len, trigvn); return TRIG_FAILURE; } /* kill the target trigger for GVN at index trig_indx */ if (PUT_SUCCESS != (trigger_delete(trigvn, trigvn_len, &trigger_count, trig_indx))) { util_out_print_gtmio("Trigger named !AD exists in the lookup table, but was not deleted!", FLUSH, orig_name_len, trigger_name); } else { csa->incr_db_trigger_cycle = TRUE; if (dollar_ztrigger_invoked) { /* increment db_dztrigger_cycle so that next gvcst_put/gvcst_kill in this transaction, * on this region, will re-read triggers. See trigger_update.c for a comment on why * it is okay for db_dztrigger_cycle to be incremented more than once in the same * transaction */ csa->db_dztrigger_cycle++; } trig_stats[STATS_DELETED]++; if (0 == trig_stats[STATS_ERROR]) util_out_print_gtmio("Deleted trigger named '!AD' for global ^!AD", FLUSH, curr_name_len, curr_name, trigvn_len, trigvn); } RESTORE_TRIGGER_REGION_INFO; name_found = TRUE; } else { /* no names match, if !wildcard report an error */ if (!wildcard) { util_out_print_gtmio("Trigger named !AD does not exist", FLUSH, orig_name_len, trigger_name); return TRIG_FAILURE; } } if (!wildcard) /* not a wild card, don't $order for the next match */ break; op_gvorder(&mv_curr_nam); if (0 == mv_curr_nam.str.len) break; assert(mv_curr_nam.str.len < MAX_MIDENT_LEN); memcpy(curr_name, mv_curr_nam.str.addr, mv_curr_nam.str.len); curr_name_len = mv_curr_nam.str.len; if (0 != memcmp(curr_name, save_name, trigger_name_len)) /* stop when gv_order returns a string that no longer starts save_name */ break; } while (wildcard); if (name_found) return TRIG_SUCCESS; util_out_print_gtmio("Trigger named !AD does not exist", FLUSH, orig_name_len, trigger_name); return TRIG_FAILURE; }
static int get_snipe_power(int *sn, bool only_browse) { int i; int num = 0; int y = 1; int x = 20; int plev = p_ptr->lev; int ask; char choice; char out_val[160]; cptr p = "power"; snipe_power spell; bool flag, redraw; #ifdef ALLOW_REPEAT /* TNB */ repeat_push(*sn); /* Assume cancelled */ *sn = (-1); /* Repeat previous command */ /* Get the spell, if available */ if (repeat_pull(sn)) { /* Verify the spell */ if ((snipe_powers[*sn].min_lev <= plev) && (snipe_powers[*sn].mana_cost <= (int)p_ptr->concent)) { /* Success */ return (TRUE); } } #endif /* ALLOW_REPEAT -- TNB */ /* Nothing chosen yet */ flag = FALSE; /* No redraw yet */ redraw = FALSE; for (i = 0; i < MAX_SNIPE_POWERS; i++) { if ((snipe_powers[i].min_lev <= plev) && ((only_browse) || (snipe_powers[i].mana_cost <= (int)p_ptr->concent))) { num = i; } } /* Build a prompt (accept all spells) */ if (only_browse) { (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) Use which %s? ", p, I2A(0), I2A(num), p); } else { (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) Use which %s? ", p, I2A(0), I2A(num), p); } /* Get a spell from the user */ choice = always_show_list ? ESCAPE : 1; while (!flag) { if(choice == ESCAPE) choice = ' '; else if( !get_com(out_val, &choice, FALSE) )break; /* Request redraw */ if ((choice == ' ') || (choice == '*') || (choice == '?')) { /* Show the list */ if (!redraw) { char psi_desc[80]; /* Show list */ redraw = TRUE; /* Save the screen */ if (!only_browse) screen_save(); /* Display a list of spells */ prt("", y, x); put_str("Name", y, x + 5); if (only_browse) put_str("Lv Pow", y, x + 35); /* Dump the spells */ for (i = 0; i < MAX_SNIPE_POWERS; i++) { Term_erase(x, y + i + 1, 255); /* Access the spell */ spell = snipe_powers[i]; if (spell.min_lev > plev) continue; if (!only_browse && (spell.mana_cost > (int)p_ptr->concent)) continue; /* Dump the spell --(-- */ if (only_browse) sprintf(psi_desc, " %c) %-30s%2d %4d", I2A(i), spell.name, spell.min_lev, spell.mana_cost); else sprintf(psi_desc, " %c) %-30s", I2A(i), spell.name); prt(psi_desc, y + i + 1, x); } /* Clear the bottom line */ prt("", y + i + 1, x); } /* Hide the list */ else { /* Hide list */ redraw = FALSE; /* Restore the screen */ if (!only_browse) screen_load(); } /* Redo asking */ continue; } /* Note verify */ ask = isupper(choice); /* Lowercase */ if (ask) choice = tolower(choice); /* Extract request */ i = (islower(choice) ? A2I(choice) : -1); /* Totally Illegal */ if ((i < 0) || (i > num) || (!only_browse &&(snipe_powers[i].mana_cost > (int)p_ptr->concent))) { bell(); continue; } /* Save the spell index */ spell = snipe_powers[i]; /* Verify it */ if (ask) { char tmp_val[160]; /* Prompt */ (void)strnfmt(tmp_val, 78, "Use %s? ", snipe_powers[i].name); /* Belay that order */ if (!get_check(tmp_val)) continue; } /* Stop the loop */ flag = TRUE; } /* Restore the screen */ if (redraw && !only_browse) screen_load(); /* Show choices */ p_ptr->window |= (PW_SPELL); /* Window stuff */ window_stuff(); /* Abort if needed */ if (!flag) return (FALSE); /* Save the choice */ (*sn) = i; #ifdef ALLOW_REPEAT /* TNB */ repeat_push(*sn); #endif /* ALLOW_REPEAT -- TNB */ /* Success */ return (TRUE); }
/* * Allow user to choose a imitation. * * If a valid spell is chosen, saves it in '*sn' and returns TRUE * If the user hits escape, returns FALSE, and set '*sn' to -1 * If there are no legal choices, returns FALSE, and sets '*sn' to -2 * * The "prompt" should be "cast", "recite", or "study" * The "known" should be TRUE for cast/pray, FALSE for study * * nb: This function has a (trivial) display bug which will be obvious * when you run it. It's probably easy to fix but I haven't tried, * sorry. */ static int get_mane_power(int *sn, bool baigaesi) { int i = 0; int num = 0; int y = 1; int x = 18; int minfail = 0; int plev = p_ptr->lev; int chance = 0; int ask; char choice; char out_val[160]; char comment[80]; #ifdef JP cptr p = "能力"; #else cptr p = "power"; #endif monster_power spell; bool flag, redraw; /* Assume cancelled */ *sn = (-1); /* Nothing chosen yet */ flag = FALSE; /* No redraw yet */ redraw = FALSE; num = p_ptr->mane_num; /* Build a prompt (accept all spells) */ (void)strnfmt(out_val, 78, #ifdef JP "(%c-%c, '*'で一覧, ESC) どの%sをまねますか?", #else "(%c-%c, *=List, ESC=exit) Use which %s? ", #endif I2A(0), I2A(num - 1), p); /* Get a spell from the user */ choice= always_show_list ? ESCAPE:1 ; while (!flag) { if(choice==ESCAPE) choice = ' '; else if( !get_com(out_val, &choice, TRUE) )break; /* Request redraw */ if ((choice == ' ') || (choice == '*') || (choice == '?')) { /* Show the list */ if (!redraw) { char psi_desc[80]; /* Show list */ redraw = TRUE; /* Save the screen */ screen_save(); /* Display a list of spells */ prt("", y, x); #ifdef JP put_str("名前", y, x + 5); #else put_str("Name", y, x + 5); #endif #ifdef JP put_str("失率 効果", y, x + 36); #else put_str("Fail Info", y, x + 35); #endif /* Dump the spells */ for (i = 0; i < num; i++) { /* Access the spell */ spell = monster_powers[p_ptr->mane_spell[i]]; chance = spell.manefail; /* Reduce failure rate by "effective" level adjustment */ if (plev > spell.level) chance -= 3 * (plev - spell.level); /* Reduce failure rate by INT/WIS adjustment */ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[spell.use_stat]] + adj_mag_stat[p_ptr->stat_ind[A_DEX]] - 2) / 2; if (spell.manedam) chance = chance * p_ptr->mane_dam[i] / spell.manedam; chance += p_ptr->to_m_chance; /* Extract the minimum failure rate */ minfail = adj_mag_fail[p_ptr->stat_ind[spell.use_stat]]; /* Minimum failure rate */ if (chance < minfail) chance = minfail; /* Stunning makes spells harder */ if (p_ptr->stun > 50) chance += 25; else if (p_ptr->stun) chance += 15; /* Always a 5 percent chance of working */ if (chance > 95) chance = 95; /* Get info */ mane_info(comment, p_ptr->mane_spell[i], (baigaesi ? p_ptr->mane_dam[i]*2 : p_ptr->mane_dam[i])); /* Dump the spell --(-- */ sprintf(psi_desc, " %c) %-30s %3d%%%s", I2A(i), spell.name, chance, comment); prt(psi_desc, y + i + 1, x); } /* Clear the bottom line */ prt("", y + i + 1, x); } /* Hide the list */ else { /* Hide list */ redraw = FALSE; /* Restore the screen */ screen_load(); } /* Redo asking */ continue; } /* Note verify */ ask = isupper(choice); /* Lowercase */ if (ask) choice = tolower(choice); /* Extract request */ i = (islower(choice) ? A2I(choice) : -1); /* Totally Illegal */ if ((i < 0) || (i >= num)) { bell(); continue; } /* Save the spell index */ spell = monster_powers[p_ptr->mane_spell[i]]; /* Verify it */ if (ask) { char tmp_val[160]; /* Prompt */ #ifdef JP (void) strnfmt(tmp_val, 78, "%sをまねますか?", monster_powers[p_ptr->mane_spell[i]].name); #else (void)strnfmt(tmp_val, 78, "Use %s? ", monster_powers[p_ptr->mane_spell[i]].name); #endif /* Belay that order */ if (!get_check(tmp_val)) continue; } /* Stop the loop */ flag = TRUE; } /* Restore the screen */ if (redraw) screen_load(); /* Show choices */ p_ptr->window |= (PW_SPELL); /* Window stuff */ window_stuff(); /* Abort if needed */ if (!flag) return (FALSE); /* Save the choice */ (*sn) = i; damage = (baigaesi ? p_ptr->mane_dam[i]*2 : p_ptr->mane_dam[i]); /* Success */ return (TRUE); }
int do_cmd_activate_skill_aux() { char which; int max = 0, i, start = 0; int ret; bool mode = FALSE; int *p; cptr *p_desc; C_MAKE(p, max_s_idx + max_ab_idx, int); C_MAKE(p_desc, max_s_idx + max_ab_idx, cptr); /* Count the max */ /* More than 1 melee skill ? */ if (get_melee_skills() > 1) { p_desc[max] = "Change melee mode"; p[max++] = 0; } for (i = 1; i < max_s_idx; i++) { if (s_info[i].action_mkey && s_info[i].value && ((!s_info[i].hidden) || (i == SKILL_LEARN))) { int j; bool next = FALSE; /* Already got it ? */ for (j = 0; j < max; j++) { if (s_info[i].action_mkey == p[j]) { next = TRUE; break; } } if (next) continue; p_desc[max] = s_text + s_info[i].action_desc; p[max++] = s_info[i].action_mkey; } } for (i = 0; i < max_ab_idx; i++) { if (ab_info[i].action_mkey && ab_info[i].acquired) { int j; bool next = FALSE; /* Already got it ? */ for (j = 0; j < max; j++) { if (ab_info[i].action_mkey == p[j]) { next = TRUE; break; } } if (next) continue; p_desc[max] = ab_text + ab_info[i].action_desc; p[max++] = ab_info[i].action_mkey; } } if (!max) { msg_print("You don't have any activable skills or abilities."); return -1; } character_icky = TRUE; Term_save(); while (1) { print_skill_batch(p, p_desc, start, max, mode); which = inkey(); if (which == ESCAPE) { ret = -1; break; } else if (which == '*' || which == '?' || which == ' ') { mode = (mode) ? FALSE : TRUE; Term_load(); character_icky = FALSE; } else if (which == '+') { start += 20; if (start >= max) start -= 20; Term_load(); character_icky = FALSE; } else if (which == '-') { start -= 20; if (start < 0) start += 20; Term_load(); character_icky = FALSE; } else if (which == '@') { char buf[80]; strcpy(buf, "Cast a spell"); if (!get_string("Skill action? ", buf, 79)) return FALSE; /* Find the skill it is related to */ for (i = 0; i < max; i++) { if (!strcmp(buf, p_desc[i])) break; } if ((i < max)) { ret = p[i]; break; } } else { which = tolower(which); if (start + A2I(which) >= max) { bell(); continue; } if (start + A2I(which) < 0) { bell(); continue; } ret = p[start + A2I(which)]; break; } } Term_load(); character_icky = FALSE; C_FREE(p, max_s_idx + max_ab_idx, int); C_FREE(p_desc, max_s_idx + max_ab_idx, cptr); return ret; }
/* * Allow user to choose a power (racial / mutation) to activate */ void do_cmd_racial_power(void) { power_desc_type power_desc[36]; int num, ask, i = 0; bool flag, redraw; char choice; char out_val[160]; const mutation_type *mut_ptr; /* Wipe desc */ for (num = 0; num < 36; num++) { strcpy(power_desc[num].name, ""); power_desc[num].number = 0; } /* Reset num */ num = 0; /* Not when we're confused */ if (p_ptr->confused) { msg_print("You are too confused to use any powers!"); p_ptr->energy_use = 0; return; } /* Look for racial powers */ for (i = 0; i < MAX_RACE_POWERS; i++) { mut_ptr = &race_powers[i]; if (mut_ptr->which == p_ptr->prace) { strcpy(power_desc[num].name, mut_ptr->name); power_desc[num].level = mut_ptr->level; power_desc[num].cost = mut_ptr->cost; power_desc[num].fail = 100 - racial_chance(mut_ptr->level, mut_ptr->stat, mut_ptr->diff); power_desc[num].number = -1; power_desc[num++].power = mut_ptr; } } /* Not if we don't have any */ if (num == 0 && !p_ptr->muta1) { msg_print("You have no powers to activate."); p_ptr->energy_use = 0; return; } /* Look for appropriate mutations */ if (p_ptr->muta1) { for (i = 0; i < MUT_PER_SET; i++) { mut_ptr = &mutations[i]; if (p_ptr->muta1 & mut_ptr->which) { strcpy(power_desc[num].name, mut_ptr->name); power_desc[num].level = mut_ptr->level; power_desc[num].cost = mut_ptr->cost; power_desc[num].fail = 100 - racial_chance(mut_ptr->level, mut_ptr->stat, mut_ptr->diff); power_desc[num].number = mut_ptr->which; power_desc[num++].power = mut_ptr; } } } /* Nothing chosen yet */ flag = FALSE; /* No redraw yet */ redraw = FALSE; /* Build a prompt */ (void)strnfmt(out_val, 78, "(Powers %c-%c, *=List, ESC=exit) Use which power? ", I2A(0), (num <= 26) ? I2A(num - 1) : '0' + num - 27); if (!repeat_pull(&i) || i<0 || i>=num) { /* Get a spell from the user */ while (!flag && get_com(out_val, &choice)) { /* Request redraw */ if ((choice == ' ') || (choice == '*') || (choice == '?')) { /* Show the list */ if (!redraw) { byte y = 1, x = 0; int ctr = 0; char dummy[80]; char letter; int x1, y1; strcpy(dummy, ""); /* Show list */ redraw = TRUE; /* Save the screen */ screen_save(); /* Print header(s) */ if (num < 17) prt(" Lv Cost Fail", y++, x); else prt(" Lv Cost Fail Lv Cost Fail", y++, x); /* Print list */ while (ctr < num) { /* letter/number for power selection */ if (ctr < 26) letter = I2A(ctr); else letter = '0' + ctr - 26; x1 = ((ctr < 17) ? x : x + 40); y1 = ((ctr < 17) ? y + ctr : y + ctr - 17); sprintf(dummy, " %c) %-23.23s %2d %4d %3d%%", letter, power_desc[ctr].name, power_desc[ctr].level, power_desc[ctr].cost, power_desc[ctr].fail); prt(dummy, y1, x1); ctr++; } } /* Hide the list */ else { /* Hide list */ redraw = FALSE; /* Restore the screen */ screen_load(); } /* Redo asking */ continue; } if (choice == '\r' && num == 1) { choice = 'a'; } if (isalpha(choice)) { /* Note verify */ ask = (isupper(choice)); /* Lowercase */ if (ask) choice = tolower(choice); /* Extract request */ i = (islower(choice) ? A2I(choice) : -1); } else { ask = FALSE; /* Can't uppercase digits */ i = choice - '0' + 26; } /* Totally Illegal */ if ((i < 0) || (i >= num)) { bell(); continue; } /* Verify it */ if (ask) { char tmp_val[160]; /* Prompt */ (void)strnfmt(tmp_val, 78, "Use %s? ", power_desc[i].name); /* Belay that order */ if (!get_check(tmp_val)) continue; } /* Stop the loop */ flag = TRUE; } /* Restore the screen */ if (redraw) screen_load(); /* Abort if needed */ if (!flag) { p_ptr->energy_use = 0; return; } repeat_push(i); } if (power_desc[i].number == -1) { cmd_racial_power_aux(power_desc[i].power); } else { mutation_power_aux(power_desc[i].power); } /* Success */ return; }
static void choose_melee() { int i, j, z = 0; character_icky = TRUE; Term_save(); Term_clear(); j = get_melee_skills(); prt("Choose a melee style:", 0, 0); for (i = 0; i < MAX_MELEE; i++) { if (melee_bool[i]) { prt(format("%c) %s", I2A(z), melee_names[i]), z + 1, 0); melee_num[z] = i; z++; } } while (TRUE) { char c = inkey(); if (c == ESCAPE) break; if (A2I(c) < 0) continue; if (A2I(c) >= j) continue; for (i = 0, z = 0; z < A2I(c); i++) if (melee_bool[i]) z++; for (i = INVEN_WIELD; p_ptr->body_parts[i - INVEN_WIELD] == INVEN_WIELD; i++) { if (p_ptr->inventory[i].k_idx) { if (cursed_p(&p_ptr->inventory[i])) { char name[80]; object_desc(name, &p_ptr->inventory[i], 0, 0); msg_format("Hmmm, your %s seems to be cursed.", name); break; } else { inven_takeoff(i, 255, FALSE); } } } p_ptr->melee_style = melee_skills[melee_num[z]]; energy_use = 100; break; } /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); /* Recalculate hitpoint */ p_ptr->update |= (PU_HP); /* Redraw monster hitpoint */ p_ptr->redraw |= (PR_MH); Term_load(); character_icky = FALSE; }
/* * Generic "get choice from menu" function */ static int get_player_choice(birth_menu *choices, int num, int def, int col, int wid, void (*hook)(birth_menu)) { int top = 0, next; int i, dir; char c; char buf[300]; bool done = FALSE; int hgt; byte attr; int cur = (def) ? def : 0; /* Autoselect if able */ //if (num == 1) done = TRUE; /* Clear */ for (i = TABLE_ROW; i < DESCRIPTION_ROW + 4; i++) { /* Clear */ Term_erase(col, i, Term->wid - wid); } /* Choose */ while (TRUE) { hgt = Term->hgt - TABLE_ROW - 1; /* Redraw the list */ for (i = 0; ((i + top < num) && (i <= hgt)); i++) { if (i + top < 26) { strnfmt(buf, sizeof(buf), "%c) %s", I2A(i + top), choices[i + top].name); } else { /* ToDo: Fix the ASCII dependency */ strnfmt(buf, sizeof(buf), "%c) %s", 'A' + (i + top - 26), choices[i + top].name); } /* Clear */ Term_erase(col, i + TABLE_ROW, wid); /* Display */ if (i == (cur - top)) { /* Highlight the current selection */ if (choices[i + top].ghost) attr = TERM_BLUE; else attr = TERM_L_BLUE; } else { if (choices[i + top].ghost) attr = TERM_SLATE; else attr = TERM_WHITE; } Term_putstr(col, i + TABLE_ROW, wid, attr, buf); } Term_erase(0, DESCRIPTION_ROW + 0, 255); Term_erase(0, DESCRIPTION_ROW + 1, 255); Term_erase(0, DESCRIPTION_ROW + 2, 255); Term_erase(0, DESCRIPTION_ROW + 3, 255); Term_erase(0, DESCRIPTION_ROW + 4, 255); if (choices[cur+top].text != NULL) { /* Indent output by 2 character, and wrap at column 70 */ text_out_wrap = 70; text_out_indent = 2; /* History */ Term_gotoxy(text_out_indent, DESCRIPTION_ROW); text_out_to_screen(TERM_L_WHITE, choices[cur+top].text); /* Reset text_out() vars */ text_out_wrap = 0; text_out_indent = 0; } else { /* Extra info */ // Term_putstr(QUESTION_COL, DESCRIPTION_ROW, -1, TERM_L_WHITE, // "Your sex has no gameplay effect."); } if (done) return (cur); /* Display auxiliary information if any is available. */ if (hook) hook(choices[cur]); /* Move the cursor */ put_str("", TABLE_ROW + cur - top, col); hide_cursor = TRUE; c = inkey(); hide_cursor = FALSE; /* Exit the game */ if ((c == 'Q') || (c == 'q')) quit(NULL); /* Hack - go back */ if ((c == ESCAPE)|| (c == '4')) return (INVALID_CHOICE); /* Make a choice */ if ((c == '\n') || (c == '\r') || (c == '6')) return (cur); /* Random choice */ if (c == '*') { /* Ensure legal choice */ do { cur = rand_int(num); } while (choices[cur].ghost); /* Done */ done = TRUE; } /* Alphabetic choice */ else if (isalpha(c)) { /* Options */ if ((c == 'O') || (c == 'o')) { do_cmd_options(); } else { int choice; if (islower(c)) choice = A2I(c); else choice = c - 'A' + 26; /* Validate input */ if ((choice > -1) && (choice < num) && !(choices[choice].ghost)) { cur = choice; /* Done */ done = TRUE; } else if (choices[choice].ghost) { bell("Your race cannot choose that house."); } else { bell("Illegal response to question!"); } } } /* Move */ else if (isdigit(c)) { /* Get a direction from the key */ dir = target_dir(c); /* Going up? */ if (dir == 8) { next = -1; for (i = 0; i < cur; i++) { if (!(choices[i].ghost)) { next = i; } } /* Move selection */ if (next != -1) cur = next; /* if (cur != 0) cur--; */ /* Scroll up */ if ((top > 0) && ((cur - top) < 4)) top--; } /* Going down? */ if (dir == 2) { next = -1; for (i = num - 1; i > cur; i--) { if (!(choices[i].ghost)) { next = i; } } /* Move selection */ if (next != -1) cur = next; /* if (cur != (num - 1)) cur++; */ /* Scroll down */ if ((top + hgt < (num - 1)) && ((top + hgt - cur) < 4)) top++; } } /* Invalid input */ else bell("Illegal response to question!"); /* If choice is off screen, move it to the top */ if ((cur < top) || (cur > top + hgt)) top = cur; } return (INVALID_CHOICE); }
/* Display possible modules and select one */ bool select_module() { s32b k, sel, max; /* Hack */ use_color = TRUE; /* Init some lua */ init_lua(); /* Some ports need to separate the module scripts from the installed mods, so we need to check for these in two different places */ if(!tome_dofile_anywhere(ANGBAND_DIR_CORE, "mods_aux.lua", FALSE)) tome_dofile_anywhere(ANGBAND_DIR_MODULES, "mods_aux.lua", TRUE); if(!tome_dofile_anywhere(ANGBAND_DIR_CORE, "modules.lua", FALSE)) tome_dofile_anywhere(ANGBAND_DIR_MODULES, "modules.lua", TRUE); /* Grab the savefiles */ call_lua("max_modules", "()", "d", &max); /* No need to bother the player if there is only one module */ sel = -1; if (force_module) call_lua("find_module", "(s)", "d", force_module, &sel); if (max == 1) sel = 0; if (sel != -1) { cptr tmp; /* Process the module */ call_lua("init_module", "(d)", "", sel); call_lua("get_module_name", "(d)", "s", sel, &tmp); game_module = string_make(tmp); activate_module(); return FALSE; } sel = 0; /* Preprocess the basic prefs, we need them to have movement keys */ process_pref_file("pref.prf"); while (TRUE) { /* Clear screen */ Term_clear(); /* Let the user choose */ c_put_str(TERM_YELLOW, "Welcome to ToME, you must select a module to play,", 1, 12); c_put_str(TERM_YELLOW, "either ToME official module or third party ones.", 2, 13); put_str("Press 8/2/4/6 to move, Return to select and Esc to quit.", 4, 3); dump_modules(sel, max); k = inkey(); if (k == ESCAPE) { quit(NULL); } if (k == '6') { sel++; if (sel >= max) sel = 0; continue; } else if (k == '4') { sel--; if (sel < 0) sel = max - 1; continue; } else if (k == '2') { sel += 4; if (sel >= max) sel = sel % max; continue; } else if (k == '8') { sel -= 4; if (sel < 0) sel = (sel + max - 1) % max; continue; } else if (k == '\r') { if (sel < 26) k = I2A(sel); else k = toupper(I2A(sel)); } { int x; cptr tmp; if (islower(k)) x = A2I(k); else x = A2I(tolower(k)) + 26; if ((x < 0) || (x >= max)) continue; /* Process the module */ call_lua("init_module", "(d)", "", x); call_lua("get_module_name", "(d)", "s", x, &tmp); game_module = string_make(tmp); activate_module(); return (FALSE); } } /* Shouldnt happen */ return (FALSE); }
/* * Let the user select an item, save its "index" * * Return TRUE only if an acceptable item was chosen by the user. * * The selected item must satisfy the "item_tester_hook()" function, * if that hook is set, and the "item_tester_tval", if that value is set. * * All "item_tester" restrictions are cleared before this function returns. * * The user is allowed to choose acceptable items from the equipment, * inventory, or floor, respectively, if the proper flag was given, * and there are any acceptable items in that location. * * The equipment or inventory are displayed (even if no acceptable * items are in that location) if the proper flag was given. * * If there are no acceptable items available anywhere, and "str" is * not NULL, then it will be used as the text of a warning message * before the function returns. * * Note that the user must press "-" to specify the item on the floor, * and there is no way to "examine" the item on the floor, while the * use of "capital" letters will "examine" an inventory/equipment item, * and prompt for its use. * * If a legal item is selected from the inventory, we save it in "cp" * directly (0 to 35), and return TRUE. * * If a legal item is selected from the floor, we save it in "cp" as * a negative (-1 to -511), and return TRUE. * * If no item is available, we do nothing to "cp", and we display a * warning message, using "str" if available, and return FALSE. * * If no item is selected, we do nothing to "cp", and return FALSE. * * Global "p_ptr->command_wrk" is used to choose between equip/inven/floor * listings. It is equal to USE_INVEN or USE_EQUIP or USE_FLOOR, except * when this function is first called, when it is equal to zero, which will * cause it to be set to USE_INVEN. * * We always erase the prompt when we are done, leaving a blank line, * or a warning message, if appropriate, if no items are available. * * Note that only "acceptable" floor objects get indexes, so between two * commands, the indexes of floor objects may change. XXX XXX XXX */ bool get_item(int *cp, const char *pmt, const char *str, cmd_code cmd, int mode) { int py = p_ptr->py; int px = p_ptr->px; unsigned char cmdkey = cmd_lookup_key(cmd, OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG); //struct keypress which; ui_event press; int j, k; int i1, i2; int e1, e2; int f1, f2; bool done, item; bool oops = FALSE; bool use_inven = ((mode & USE_INVEN) ? TRUE : FALSE); bool use_equip = ((mode & USE_EQUIP) ? TRUE : FALSE); bool use_floor = ((mode & USE_FLOOR) ? TRUE : FALSE); bool is_harmless = ((mode & IS_HARMLESS) ? TRUE : FALSE); bool quiver_tags = ((mode & QUIVER_TAGS) ? TRUE : FALSE); int olist_mode = 0; bool allow_inven = FALSE; bool allow_equip = FALSE; bool allow_floor = FALSE; bool toggle = FALSE; char tmp_val[160]; char out_val[160]; int floor_list[MAX_FLOOR_STACK]; int floor_num; bool show_list = TRUE; /* Hack - Only shift the command key if it actually needs to be shifted. */ if (cmdkey < 0x20) cmdkey = UN_KTRL(cmdkey); /* Object list display modes */ if (mode & SHOW_FAIL) olist_mode |= OLIST_FAIL; else olist_mode |= OLIST_WEIGHT; if (mode & SHOW_PRICES) olist_mode |= OLIST_PRICE; if (mode & SHOW_EMPTY) olist_mode |= OLIST_SEMPTY; /* Paranoia XXX XXX XXX */ message_flush(); /* Not done */ done = FALSE; /* No item selected */ item = FALSE; /* Full inventory */ i1 = 0; i2 = INVEN_PACK - 1; /* Forbid inventory */ if (!use_inven) i2 = -1; /* Restrict inventory indexes */ while ((i1 <= i2) && (!get_item_okay(i1))) i1++; while ((i1 <= i2) && (!get_item_okay(i2))) i2--; /* Accept inventory */ if (i1 <= i2) allow_inven = TRUE; /* Full equipment */ e1 = INVEN_WIELD; e2 = ALL_INVEN_TOTAL - 1; /* Forbid equipment */ if (!use_equip) e2 = -1; /* Restrict equipment indexes */ while ((e1 <= e2) && (!get_item_okay(e1))) e1++; while ((e1 <= e2) && (!get_item_okay(e2))) e2--; /* Accept equipment */ if (e1 <= e2) allow_equip = TRUE; /* Scan all non-gold objects in the grid */ floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), py, px, 0x0B); /* Full floor */ f1 = 0; f2 = floor_num - 1; /* Forbid floor */ if (!use_floor) f2 = -1; /* Restrict floor indexes */ while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f1]))) f1++; while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f2]))) f2--; /* Accept floor */ if (f1 <= f2) allow_floor = TRUE; /* Require at least one legal choice */ if (!allow_inven && !allow_equip && !allow_floor) { /* Oops */ oops = TRUE; done = TRUE; } /* Analyze choices */ else { /* Hack -- Start on equipment if requested */ if ((p_ptr->command_wrk == USE_EQUIP) && allow_equip) p_ptr->command_wrk = USE_EQUIP; else if ((p_ptr->command_wrk == USE_INVEN) && allow_inven) p_ptr->command_wrk = USE_INVEN; else if ((p_ptr->command_wrk == USE_FLOOR) && allow_floor) p_ptr->command_wrk = USE_FLOOR; /* If we are using the quiver then start on equipment */ else if (quiver_tags && allow_equip) p_ptr->command_wrk = USE_EQUIP; /* Use inventory if allowed */ else if (use_inven && allow_inven) p_ptr->command_wrk = USE_INVEN; /* Use equipment if allowed */ else if (use_equip && allow_equip) p_ptr->command_wrk = USE_EQUIP; /* Use floor if allowed */ else if (use_floor && allow_floor) p_ptr->command_wrk = USE_FLOOR; /* Hack -- Use (empty) inventory */ else p_ptr->command_wrk = USE_INVEN; } /* Start out in "display" mode */ if (show_list) { /* Save screen */ screen_save(); } /* Repeat until done */ while (!done) { int ni = 0; int ne = 0; /* Scan windows */ for (j = 0; j < ANGBAND_TERM_MAX; j++) { /* Unused */ if (!angband_term[j]) continue; /* Count windows displaying inven */ if (op_ptr->window_flag[j] & (PW_INVEN)) ni++; /* Count windows displaying equip */ if (op_ptr->window_flag[j] & (PW_EQUIP)) ne++; } /* Toggle if needed */ if (((p_ptr->command_wrk == USE_EQUIP) && ni && !ne) || ((p_ptr->command_wrk == USE_INVEN) && !ni && ne)) { /* Toggle */ toggle_inven_equip(); /* Track toggles */ toggle = !toggle; } /* Redraw */ p_ptr->redraw |= (PR_INVEN | PR_EQUIP); /* Redraw windows */ redraw_stuff(p_ptr); /* Viewing inventory */ if (p_ptr->command_wrk == USE_INVEN) { int nmode = olist_mode; /* Show the quiver counts in certain cases, like the 'i' command */ if (mode & SHOW_QUIVER) nmode |= OLIST_QUIVER; /* Redraw if needed */ if (show_list) show_inven(nmode); /* Begin the prompt */ strnfmt(out_val, sizeof(out_val), "Inven:"); /* List choices */ if (i1 <= i2) { /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", index_to_label(i1), index_to_label(i2)); /* Append */ my_strcat(out_val, tmp_val, sizeof(out_val)); } /* Indicate ability to "view" */ if (!show_list) { my_strcat(out_val, " * to see,", sizeof(out_val)); button_add("[*]", '*'); } /* Indicate legality of "toggle" */ if (use_equip) { my_strcat(out_val, " / for Equip,", sizeof(out_val)); button_add("[/]", '/'); } /* Indicate legality of the "floor" */ if (allow_floor) { my_strcat(out_val, " - for floor,", sizeof(out_val)); button_add("[-]", '-'); } } /* Viewing equipment */ else if (p_ptr->command_wrk == USE_EQUIP) { /* Redraw if needed */ if (show_list) show_equip(olist_mode); /* Begin the prompt */ strnfmt(out_val, sizeof(out_val), "Equip:"); /* List choices */ if (e1 <= e2) { /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", index_to_label(e1), index_to_label(e2)); /* Append */ my_strcat(out_val, tmp_val, sizeof(out_val)); } /* Indicate ability to "view" */ if (!show_list) { my_strcat(out_val, " * to see,", sizeof(out_val)); button_add("[*]", '*'); } /* Indicate legality of "toggle" */ if (use_inven) { my_strcat(out_val, " / for Inven,", sizeof(out_val)); button_add("[/]", '/'); } /* Indicate legality of the "floor" */ if (allow_floor) { my_strcat(out_val, " - for floor,", sizeof(out_val)); button_add("[!]", '!'); } } /* Viewing floor */ else { /* Redraw if needed */ if (show_list) show_floor(floor_list, floor_num, olist_mode); /* Begin the prompt */ strnfmt(out_val, sizeof(out_val), "Floor:"); /* List choices */ if (f1 <= f2) { /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", I2A(f1), I2A(f2)); /* Append */ my_strcat(out_val, tmp_val, sizeof(out_val)); } /* Indicate ability to "view" */ if (!show_list) { my_strcat(out_val, " * to see,", sizeof(out_val)); button_add("[*]", '*'); } /* Append */ if (use_inven) { my_strcat(out_val, " / for Inven,", sizeof(out_val)); button_add("[/]", '/'); } /* Append */ else if (use_equip) { my_strcat(out_val, " / for Equip,", sizeof(out_val)); button_add("[/]", '/'); } } redraw_stuff(p_ptr); /* Finish the prompt */ my_strcat(out_val, " ESC", sizeof(out_val)); /* if we have a prompt header, show the part that we just built */ if (pmt) { /* Build the prompt */ strnfmt(tmp_val, sizeof(tmp_val), "(%s) %s", out_val, pmt); /* Show the prompt */ prt(tmp_val, 0, 0); } /* Get a key */ //which = inkey(); press = inkey_m(); /* Parse it */ if (press.type == EVT_MOUSE) { if (press.mouse.button == 2) { done = TRUE; } else if (press.mouse.button == 1) { k = -1; if (p_ptr->command_wrk == USE_INVEN) { if (press.mouse.y == 0) { if (use_equip) { p_ptr->command_wrk = USE_EQUIP; } else if (allow_floor) { p_ptr->command_wrk = USE_FLOOR; } } else if ((press.mouse.y <= i2-i1+1) ){ //&& (press.mouse.x > Term->wid - 1 - max_len - ex_width)) { //k = label_to_inven(index_to_label(i1+press.mouse.y-1)); /* get the item index, allowing for skipped indices */ for (j = i1; j <= i2; j++) { if (get_item_okay(j)) { if (press.mouse.y == 1) { k = j; break; } press.mouse.y--; } } } } else if (p_ptr->command_wrk == USE_EQUIP) { if (press.mouse.y == 0) { if (allow_floor) { p_ptr->command_wrk = USE_FLOOR; } else if (use_inven) { p_ptr->command_wrk = USE_INVEN; } } else if (press.mouse.y <= e2-e1+1) { if (olist_mode & OLIST_SEMPTY) { /* If we are showing empties, just set the object (empty objects will just keep the loop going) */ k = label_to_equip(index_to_label(e1+press.mouse.y-1)); } else { /* get the item index, allowing for skipped indices */ for (j = e1; j <= e2; j++) { /* skip the quiver slot which is a blank line in the list */ if (j == 36) { press.mouse.y--; } else if (get_item_okay(j)) { if (press.mouse.y == 1) { k = j; break; } press.mouse.y--; } } } } } else if (p_ptr->command_wrk == USE_FLOOR) { if (press.mouse.y == 0) { if (use_inven) { p_ptr->command_wrk = USE_INVEN; } else if (use_equip) { p_ptr->command_wrk = USE_EQUIP; } } else if ((press.mouse.y <= floor_num) && (press.mouse.y >= 1)) { /* Special index */ k = 0 - floor_list[press.mouse.y-1]; /* get the item index, allowing for skipped indices */ for (j = f1; j <= f2; j++) { if (get_item_okay(0 - floor_list[j])) { if (press.mouse.y == 1) { k = 0 - floor_list[j]; break; } press.mouse.y--; } } /* check the bounds the item number */ if (k < 0) { /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, cmd, is_harmless)) { done = TRUE; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; } else { /* set k to a value that will be invalid below */ k = -1; } } } if (k >= 0) { /* Validate the item */ if (!get_item_okay(k)) { bell("Illegal object choice (normal)!"); } /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, cmd, is_harmless)) { done = TRUE; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; } else if (press.mouse.y == 0) { /* Hack -- Fix screen */ if (show_list) { /* Load screen */ screen_load(); /* Save screen */ screen_save(); } } } } else //switch (which.code) switch (press.key.code) { case ESCAPE: case ' ': { done = TRUE; break; } case '/': { /* Toggle to inventory */ if (use_inven && (p_ptr->command_wrk != USE_INVEN)) { p_ptr->command_wrk = USE_INVEN; } /* Toggle to equipment */ else if (use_equip && (p_ptr->command_wrk != USE_EQUIP)) { p_ptr->command_wrk = USE_EQUIP; } /* No toggle allowed */ else { bell("Cannot switch item selector!"); break; } /* Hack -- Fix screen */ if (show_list) { /* Load screen */ screen_load(); /* Save screen */ screen_save(); } /* Need to redraw */ break; } case '-': { /* Paranoia */ if (!allow_floor) { bell("Cannot select floor!"); break; } /* There is only one item */ if (floor_num == 1) { /* Auto-select */ if (p_ptr->command_wrk == (USE_FLOOR)) { /* Special index */ k = 0 - floor_list[0]; /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, cmd, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } } /* Hack -- Fix screen */ if (show_list) { /* Load screen */ screen_load(); /* Save screen */ screen_save(); } p_ptr->command_wrk = (USE_FLOOR); #if 0 /* Check each legal object */ for (i = 0; i < floor_num; ++i) { /* Special index */ k = 0 - floor_list[i]; /* Skip non-okay objects */ if (!get_item_okay(k)) continue; /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, cmd, is_harmless)) continue; /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } #endif break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* Look up the tag */ //if (!get_tag(&k, which.code, cmd, quiver_tags)) if (!get_tag(&k, press.key.code, cmd, quiver_tags)) { bell("Illegal object choice (tag)!"); break; } /* Hack -- Validate the item */ if ((k < INVEN_WIELD) ? !allow_inven : !allow_equip) { bell("Illegal object choice (tag)!"); break; } /* Validate the item */ if (!get_item_okay(k)) { bell("Illegal object choice (tag)!"); break; } /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, cmd, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } case KC_ENTER: { /* Choose "default" inventory item */ if (p_ptr->command_wrk == USE_INVEN) { if (i1 != i2) { bell("Illegal object choice (default)!"); break; } k = i1; } /* Choose the "default" slot (0) of the quiver */ else if (quiver_tags) k = e1; /* Choose "default" equipment item */ else if (p_ptr->command_wrk == USE_EQUIP) { if (e1 != e2) { bell("Illegal object choice (default)!"); break; } k = e1; } /* Choose "default" floor item */ else { if (f1 != f2) { bell("Illegal object choice (default)!"); break; } k = 0 - floor_list[f1]; } /* Validate the item */ if (!get_item_okay(k)) { bell("Illegal object choice (default)!"); break; } /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, cmd, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } default: { bool verify; /* Note verify */ //verify = (isupper((unsigned char)which.code) ? TRUE : FALSE); verify = (isupper((unsigned char)press.key.code) ? TRUE : FALSE); /* Lowercase */ //which.code = tolower((unsigned char)which.code); press.key.code = tolower((unsigned char)press.key.code); /* Convert letter to inventory index */ if (p_ptr->command_wrk == USE_INVEN) { //k = label_to_inven(which.code); k = label_to_inven(press.key.code); if (k < 0) { bell("Illegal object choice (inven)!"); break; } } /* Convert letter to equipment index */ else if (p_ptr->command_wrk == USE_EQUIP) { //k = label_to_equip(which.code); k = label_to_equip(press.key.code); if (k < 0) { bell("Illegal object choice (equip)!"); break; } } /* Convert letter to floor index */ else { //k = (islower((unsigned char)which.code) ? A2I((unsigned char)which.code) : -1); k = (islower((unsigned char)press.key.code) ? A2I((unsigned char)press.key.code) : -1); if (k < 0 || k >= floor_num) { bell("Illegal object choice (floor)!"); break; } /* Special index */ k = 0 - floor_list[k]; } /* Validate the item */ if (!get_item_okay(k)) { bell("Illegal object choice (normal)!"); break; } /* Verify the item */ if (verify && !verify_item("Try", k)) { done = TRUE; break; } /* Allow player to "refuse" certain actions */ if (!get_item_allow(k, cmdkey, cmd, is_harmless)) { done = TRUE; break; } /* Accept that choice */ (*cp) = k; item = TRUE; done = TRUE; break; } } } /* Fix the screen if necessary */ if (show_list) { /* Load screen */ screen_load(); /* Hack -- Cancel "display" */ show_list = FALSE; } /* Kill buttons */ button_kill('*'); button_kill('/'); button_kill('-'); button_kill('!'); redraw_stuff(p_ptr); /* Forget the item_tester_tval restriction */ item_tester_tval = 0; /* Forget the item_tester_hook restriction */ item_tester_hook = NULL; /* Toggle again if needed */ if (toggle) toggle_inven_equip(); /* Update */ p_ptr->redraw |= (PR_INVEN | PR_EQUIP); redraw_stuff(p_ptr); /* Clear the prompt line */ prt("", 0, 0); /* Warning if needed */ if (oops && str) msg("%s", str); /* Result */ return (item); }
boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs) { /* IMPORTANT : op_gvargs will point to static area which gets overwritten by the next call to this function. Callers should make a copy of op_gvargs if necessary */ char *p1, *p2, *c_top, *c_ref, ch, *subsc_ptr, *dstptr, *strnext; int count; mval *spt; int chcode, chtmp; mstr_len_t chlen; boolean_t naked, concat, dot_seen, dollarzch, isdolar; error_def(ERR_NOTGBL); error_def(ERR_GVINVALID); error_def(ERR_LPARENREQD); error_def(ERR_NUMUNXEOR); error_def(ERR_STRUNXEOR); error_def(ERR_DLRCUNXEOR); error_def(ERR_DLRCTOOBIG); error_def(ERR_EORNOTFND); error_def(ERR_RPARENREQD); error_def(ERR_DLRCILLEGAL); assert(SIZEOF(op_gvargs->count) == SIZEOF(op_gvargs->args[0])); naked = FALSE; concat = FALSE; c_ref = cp; c_top = cp + len; assert(0 < len); /* why is our code calling with "" string? */ if (len > subsc_buffer.len) { if (NULL != subsc_buffer.addr) free(subsc_buffer.addr); subsc_buffer.len = (ZWR_EXP_RATIO(MAX_KEY_SZ) < len ? len : ZWR_EXP_RATIO(MAX_KEY_SZ)); subsc_buffer.addr = malloc(subsc_buffer.len); } spt = subsc; count = 0; if (0 >= len || '^' != *cp++) rts_error(VARLSTCNT(4) ERR_NOTGBL, 2, (len > 0) ? len : 0, c_ref); spt->mvtype = MV_STR; spt->str.addr = cp; ch = *cp; if ('(' == ch) { spt->str.len = INTCAST(cp - spt->str.addr - 1); naked = TRUE; } else { cp++; if (!(VALFIRSTCHAR_WITH_TRIG(ch))) rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref); for ( ; cp < c_top && *cp != '('; ) { ch = *cp++; if (!ISALPHA_ASCII(ch) && !ISDIGIT_ASCII(ch)) rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref); } spt->str.len = INTCAST(cp - spt->str.addr); op_gvargs->args[count] = spt; count++; spt++; } subsc_ptr = subsc_buffer.addr; if (cp < c_top) { if ('(' != *cp++) rts_error(VARLSTCNT(4) ERR_LPARENREQD, 2, len, c_ref); for (; ;) { spt->mvtype = MV_STR; ch = *cp; if ('\"' == ch) { if (!concat) { spt->str.addr = subsc_ptr; p1 = subsc_ptr; } else p2 = p1; ++cp; for (; ;) { if (cp == c_top) rts_error(VARLSTCNT(4) ERR_STRUNXEOR, 2, len, c_ref); if ('\"' == *cp) if ('\"' != *++cp) break; *p1++ = *cp++; } if (!concat) { spt->str.len = INTCAST(p1 - spt->str.addr); subsc_ptr = p1; } else { spt->str.len += (mstr_len_t)(p1 - p2); subsc_ptr += p1 - p2; } if ('_' == *cp) { cp++; concat = TRUE; continue; } } else if ('$' == ch) { cp++; chtmp = toupper(*cp); isdolar = (3 <= c_top - cp && 'C' == chtmp || '(' == cp[1]); if (!isdolar) isdolar = (5 <= c_top - cp && 'Z' == chtmp && 'C' == cp[1] && 'H' == cp[2] && '(' == cp[3]); if (!isdolar) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); if ('Z' == chtmp) { dollarzch = TRUE; cp += 4; } else { dollarzch = FALSE; cp += 2; } for (; ;) { A2I(cp, c_top, chcode); if (0 > chcode) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); dstptr = (!concat) ? subsc_ptr : p1; if (!gtm_utf8_mode || dollarzch) { if (255 < chcode) { if (dollarzch) rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref, LEN_AND_LIT("$CHAR()")); else rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref, LEN_AND_LIT("$ZCHAR()")); } *dstptr = chcode; chlen = 1; } #ifdef UNICODE_SUPPORTED else { strnext = (char *)UTF8_WCTOMB(chcode, dstptr); chlen = INTCAST(strnext - dstptr); if (0 == chlen) rts_error(VARLSTCNT(5) ERR_DLRCILLEGAL, 3, len, c_ref, chcode); } #endif if (!concat) { spt->str.addr = subsc_ptr; spt->str.len = chlen; subsc_ptr += chlen; p1 = subsc_ptr; } else { p1 += chlen; spt->str.len += chlen; subsc_ptr += chlen; } if (',' == *cp) { concat = TRUE; if (++cp == c_top) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); continue; } if (')' != *cp) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); break; } cp++; if ('_' == *cp) { cp++; concat = TRUE; continue; } } else { dot_seen = FALSE; if (!ISDIGIT_ASCII(ch) && '.' != ch && '-' != ch && '+' != ch) rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref); if (!concat) { spt->str.addr = subsc_ptr; p1 = subsc_ptr; } else p2 = p1; *p1++ = *cp++; for (; ;) { if (cp == c_top) rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref); if (!ISDIGIT_ASCII(*cp)) { if ('.' != *cp) break; else if (!dot_seen) dot_seen = TRUE; else rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref); } *p1++ = *cp++; } if (!concat) { spt->str.len = INTCAST(p1 - spt->str.addr); subsc_ptr = p1; } else { spt->str.len += (mstr_len_t)(p1 - p2); subsc_ptr += p1 - p2; } if ('_' == *cp) { cp++; concat = TRUE; continue; } } op_gvargs->args[count] = spt; count++; spt++; if (',' != *cp) break; concat = FALSE; cp++; } if (')' != *cp++) rts_error(VARLSTCNT(4) ERR_RPARENREQD, 2, len, c_ref); if (cp < c_top) rts_error(VARLSTCNT(4) ERR_EORNOTFND, 2, len, c_ref); } op_gvargs->count = count; return naked; }
STATICFNDEF boolean_t process_pieces(char *piece_str, uint4 *piece_len) { uint bit; uint4 bitmap[MAX_PIECE_INT]; uint bitval; uint bitword; boolean_t have_low_num; boolean_t have_num; boolean_t have_num_in_str; uint i; uint4 len; int low; int num; char *ptr; char *ptr1; boolean_t have_error = FALSE; int num_len; memset((void *)bitmap, 0, MAX_PIECE_CHARS); ptr = piece_str; len = *piece_len; have_num = have_low_num = FALSE; if ('"' == *ptr) { ptr++; len--; } while ((0 < len) && !have_error) { switch (*ptr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ptr1 = ptr; A2I(ptr1, ptr + len, num); if ((0 == num) || (MAX_PIECE_VALUE < num)) { CONV_NUM_AND_STR_AND_PRINT("Invalid value !UL in PIECES - !AD", num, *piece_len, piece_str); have_error = TRUE; break; } len -= (int)(ptr1 - ptr); ptr = ptr1; bitmap[num / BITS_PER_INT] |= 1 << (num % BITS_PER_INT); have_num = TRUE; have_low_num = TRUE; break; case ';': if (!have_num) { CONV_STR_AND_PRINT("Expected an integer in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } have_num = FALSE; ptr++; len--; break; case ':': if (!have_low_num) { CONV_STR_AND_PRINT("Expected an integer for lower value in range in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } ptr++; len--; low = num; if (!ISDIGIT_ASCII(*ptr)) { CONV_STR_AND_PRINT("Expected an integer for upper value in range in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } ptr1 = ptr; A2I(ptr1, ptr + len, num); if (MAX_PIECE_VALUE < num) { CONV_NUM_AND_STR_AND_PRINT("Invalid value \"!UL\" in PIECES - !AD", num, *piece_len, piece_str); have_error = TRUE; break; } if (num <= low) { CONV_STR_AND_PRINT("Low value of range not less than high value in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } len -= (int)(ptr1 - ptr); ptr = ptr1; for (i = low + 1; i <= num; i++) bitmap[i / BITS_PER_INT] |= 1 << (i % BITS_PER_INT); have_num = TRUE; have_low_num = FALSE; break; case '"': if (1 == len) { len--; break; } default: CONV_CH_AND_STR_AND_PRINT("Invalid character !AD in PIECES - !AD", ptr, *piece_len, piece_str); have_error = TRUE; break; } } if ((0 != len) || !have_num || have_error) { if (!have_error) CONV_STR_AND_PRINT("Invalid PIECE entry - ", *piece_len, piece_str); return FALSE; } have_num = have_low_num = have_num_in_str = FALSE; ptr = piece_str; len = 0; for (i = 0; i < MAX_PIECE_INT; i++) { if ((0 == bitmap[i] && !have_low_num)) continue; bitword = bitmap[i]; bit = 0; while ((0 != bitword) || have_low_num) { bitval = bitword & 1; if (!have_low_num) { if (0 == bitval) { bitword = bitword >> 1; bit++; continue; } have_num = TRUE; have_low_num = TRUE; low = i * BITS_PER_INT + bit; if (have_num_in_str) { *ptr++ = ';'; len++; } num_len = 0; I2A(ptr, num_len, low); len += num_len; ptr += num_len; have_num_in_str = TRUE; } while ((1 == bitval) && (BITS_PER_INT > bit)) { bitword = bitword >> 1; bitval = bitword & 1; bit++; } if (BITS_PER_INT == bit) break; num = (0 == bit) ? i * BITS_PER_INT - 1 : i * BITS_PER_INT + bit - 1; have_low_num = FALSE; if (num == low) continue; *ptr++ = ':'; len++; num_len = 0; I2A(ptr, num_len, num); len += num_len; ptr += num_len; } }
/* * Recursive file perusal. * * Return FALSE on "?", otherwise TRUE. * * This function could be made much more efficient with the use of "seek" * functionality, especially when moving backwards through a file, or * forwards through a file by less than a page at a time. XXX XXX XXX */ bool show_file(const char *name, const char *what, int line, int mode) { int i, k, n; struct keypress ch; /* Number of "real" lines passed by */ int next = 0; /* Number of "real" lines in the file */ int size; /* Backup value for "line" */ int back = 0; /* This screen has sub-screens */ bool menu = FALSE; /* Case sensitive search */ bool case_sensitive = FALSE; /* Current help file */ ang_file *fff = NULL; /* Find this string (if any) */ char *find = NULL; /* Jump to this tag */ const char *tag = NULL; /* Hold a string to find */ char finder[80] = ""; /* Hold a string to show */ char shower[80] = ""; /* Filename */ char filename[1024]; /* Describe this thing */ char caption[128] = ""; /* Path buffer */ char path[1024]; /* General buffer */ char buf[1024]; /* Lower case version of the buffer, for searching */ char lc_buf[1024]; /* Sub-menu information */ char hook[26][32]; int wid, hgt; /* TRUE if we are inside a RST block that should be skipped */ bool skip_lines = FALSE; /* Wipe the hooks */ for (i = 0; i < 26; i++) hook[i][0] = '\0'; /* Get size */ Term_get_size(&wid, &hgt); /* Copy the filename */ my_strcpy(filename, name, sizeof(filename)); n = strlen(filename); /* Extract the tag from the filename */ for (i = 0; i < n; i++) { if (filename[i] == '#') { filename[i] = '\0'; tag = filename + i + 1; break; } } /* Redirect the name */ name = filename; /* Hack XXX XXX XXX */ if (what) { my_strcpy(caption, what, sizeof(caption)); my_strcpy(path, name, sizeof(path)); fff = file_open(path, MODE_READ, FTYPE_TEXT); } /* Look in "help" */ if (!fff) { strnfmt(caption, sizeof(caption), "Help file '%s'", name); path_build(path, sizeof(path), ANGBAND_DIR_HELP, name); fff = file_open(path, MODE_READ, FTYPE_TEXT); } /* Look in "info" */ if (!fff) { strnfmt(caption, sizeof(caption), "Info file '%s'", name); path_build(path, sizeof(path), ANGBAND_DIR_INFO, name); fff = file_open(path, MODE_READ, FTYPE_TEXT); } /* Oops */ if (!fff) { /* Message */ msg("Cannot open '%s'.", name); event_signal(EVENT_MESSAGE_FLUSH); /* Oops */ return (TRUE); } /* Pre-Parse the file */ while (TRUE) { /* Read a line or stop */ if (!file_getl(fff, buf, sizeof(buf))) break; /* Skip lines if we are inside a RST directive*/ if(skip_lines){ if(contains_only_spaces(buf)) skip_lines=FALSE; continue; } /* Parse a very small subset of RST */ /* TODO: should be more flexible */ if (prefix(buf, ".. ")) { /* parse ".. menu:: [x] filename.txt" (with exact spacing)*/ if(prefix(buf+strlen(".. "), "menu:: [") && buf[strlen(".. menu:: [x")]==']') { /* This is a menu file */ menu = TRUE; /* Extract the menu item */ k = A2I(buf[strlen(".. menu:: [")]); /* Store the menu item (if valid) */ if ((k >= 0) && (k < 26)) my_strcpy(hook[k], buf + strlen(".. menu:: [x] "), sizeof(hook[0])); } /* parse ".. _some_hyperlink_target:" */ else if (buf[strlen(".. ")] == '_') { if (tag) { /* Remove the closing '>' of the tag */ buf[strlen(buf) - 1] = '\0'; /* Compare with the requested tag */ if (streq(buf + strlen(".. _"), tag)) { /* Remember the tagged line */ line = next; } } } /* Skip this and enter skip mode*/ skip_lines = TRUE; continue; } /* Count the "real" lines */ next++; } /* Save the number of "real" lines */ size = next; /* Display the file */ while (TRUE) { /* Clear screen */ Term_clear(); /* Restrict the visible range */ if (line > (size - (hgt - 4))) line = size - (hgt - 4); if (line < 0) line = 0; skip_lines = FALSE; /* Re-open the file if needed */ if (next > line) { /* Close it */ file_close(fff); /* Hack -- Re-Open the file */ fff = file_open(path, MODE_READ, FTYPE_TEXT); if (!fff) return (TRUE); /* File has been restarted */ next = 0; } /* Goto the selected line */ while (next < line) { /* Get a line */ if (!file_getl(fff, buf, sizeof(buf))) break; /* Skip lines if we are inside a RST directive*/ if(skip_lines){ if(contains_only_spaces(buf)) skip_lines=FALSE; continue; } /* Skip RST directives */ if (prefix(buf, ".. ")) { skip_lines=TRUE; continue; } /* Count the lines */ next++; } /* Dump the next lines of the file */ for (i = 0; i < hgt - 4; ) { /* Hack -- track the "first" line */ if (!i) line = next; /* Get a line of the file or stop */ if (!file_getl(fff, buf, sizeof(buf))) break; /* Skip lines if we are inside a RST directive*/ if(skip_lines){ if(contains_only_spaces(buf)) skip_lines=FALSE; continue; } /* Skip RST directives */ if (prefix(buf, ".. ")) { skip_lines=TRUE; continue; } /* skip | characters */ strskip(buf,'|'); /* escape backslashes */ strescape(buf,'\\'); /* Count the "real" lines */ next++; /* Make a copy of the current line for searching */ my_strcpy(lc_buf, buf, sizeof(lc_buf)); /* Make the line lower case */ if (!case_sensitive) string_lower(lc_buf); /* Hack -- keep searching */ if (find && !i && !strstr(lc_buf, find)) continue; /* Hack -- stop searching */ find = NULL; /* Dump the line */ Term_putstr(0, i+2, -1, COLOUR_WHITE, buf); /* Highlight "shower" */ if (shower[0]) { const char *str = lc_buf; /* Display matches */ while ((str = strstr(str, shower)) != NULL) { int len = strlen(shower); /* Display the match */ Term_putstr(str-lc_buf, i+2, len, COLOUR_YELLOW, &buf[str-lc_buf]); /* Advance */ str += len; } } /* Count the printed lines */ i++; } /* Hack -- failed search */ if (find) { bell("Search string not found!"); line = back; find = NULL; continue; } /* Show a general "title" */ prt(format("[%s, %s, Line %d-%d/%d]", buildid, caption, line, line + hgt - 4, size), 0, 0); /* Prompt -- menu screen */ if (menu) { /* Wait for it */ prt("[Press a Letter, or ESC to exit.]", hgt - 1, 0); } /* Prompt -- small files */ else if (size <= hgt - 4) { /* Wait for it */ prt("[Press ESC to exit.]", hgt - 1, 0); } /* Prompt -- large files */ else { /* Wait for it */ prt("[Press Space to advance, or ESC to exit.]", hgt - 1, 0); } /* Get a keypress */ ch = inkey(); /* Exit the help */ if (ch.code == '?') break; /* Toggle case sensitive on/off */ if (ch.code == '!') { case_sensitive = !case_sensitive; } /* Try showing */ if (ch.code == '&') { /* Get "shower" */ prt("Show: ", hgt - 1, 0); (void)askfor_aux(shower, sizeof(shower), NULL); /* Make the "shower" lowercase */ if (!case_sensitive) string_lower(shower); } /* Try finding */ if (ch.code == '/') { /* Get "finder" */ prt("Find: ", hgt - 1, 0); if (askfor_aux(finder, sizeof(finder), NULL)) { /* Find it */ find = finder; back = line; line = line + 1; /* Make the "finder" lowercase */ if (!case_sensitive) string_lower(finder); /* Show it */ my_strcpy(shower, finder, sizeof(shower)); } } /* Go to a specific line */ if (ch.code == '#') { char tmp[80] = "0"; prt("Goto Line: ", hgt - 1, 0); if (askfor_aux(tmp, sizeof(tmp), NULL)) line = atoi(tmp); } /* Go to a specific file */ if (ch.code == '%') { char ftmp[80] = "help.hlp"; prt("Goto File: ", hgt - 1, 0); if (askfor_aux(ftmp, sizeof(ftmp), NULL)) { if (!show_file(ftmp, NULL, 0, mode)) ch.code = ESCAPE; } } switch (ch.code) { /* up a line */ case ARROW_UP: case '8': line--; break; /* up a page */ case KC_PGUP: case '9': case '-': line -= (hgt - 4); break; /* home */ case KC_HOME: case '7': line = 0; break; /* down a line */ case ARROW_DOWN: case '2': case KC_ENTER: line++; break; /* down a page */ case KC_PGDOWN: case '3': case ' ': line += hgt - 4; break; /* end */ case KC_END: case '1': line = size; break; } /* Recurse on letters */ if (menu && isalpha((unsigned char)ch.code)) { /* Extract the requested menu item */ k = A2I(ch.code); /* Verify the menu item */ if ((k >= 0) && (k <= 25) && hook[k][0]) { /* Recurse on that file */ if (!show_file(hook[k], NULL, 0, mode)) ch.code = ESCAPE; } } /* Exit on escape */ if (ch.code == ESCAPE) break; } /* Close the file */ file_close(fff); /* Done */ return (ch.code != '?'); }
/* * Convert a hexidecimal-digit into a decimal */ static int dehex(char c) { if (isdigit((unsigned char)c)) return (D2I(c)); if (isalpha((unsigned char)c)) return (A2I(tolower((unsigned char)c)) + 10); return (0); }
static _slot_info_ptr _choose(cptr verb, int options) { _slot_info_ptr result = NULL; int slot = 0; int cmd; rect_t r = _menu_rect(); string_ptr prompt = NULL; bool done = FALSE; bool exchange = FALSE; int slot1 = _INVALID_SLOT, slot2 = _INVALID_SLOT; if (REPEAT_PULL(&cmd)) { slot = A2I(cmd); if (0 <= slot && slot < _MAX_SLOTS) return &_spells[slot]; } prompt = string_alloc(); screen_save(); while (!done) { string_clear(prompt); if (exchange) { if (slot1 == _INVALID_SLOT) string_append_s(prompt, "Select the first spell:"); else string_append_s(prompt, "Select the second spell:"); } else { string_printf(prompt, "%s which spell", verb); if (options & _ALLOW_EXCHANGE) string_append_s(prompt, " [Press 'X' to Exchange]"); string_append_c(prompt, ':'); } prt(string_buffer(prompt), 0, 0); _display(r, options); cmd = inkey_special(FALSE); if (cmd == ESCAPE || cmd == 'q' || cmd == 'Q') done = TRUE; if (options & _ALLOW_EXCHANGE) { if (!exchange && (cmd == 'x' || cmd == 'X')) { exchange = TRUE; slot1 = slot2 = _INVALID_SLOT; } } if ('a' <= cmd && cmd < 'a' + _MAX_SLOTS) { slot = A2I(cmd); if (exchange) { if (slot1 == _INVALID_SLOT) slot1 = slot; else { slot2 = slot; if (slot1 != slot2) { _slot_info_t tmp = _spells[slot1]; _spells[slot1] = _spells[slot2]; _spells[slot2] = tmp; } exchange = FALSE; slot1 = slot2 = _INVALID_SLOT; } } else { if (_spells[slot].realm != REALM_NONE || (options & _ALLOW_EMPTY)) { result = &_spells[slot]; done = TRUE; } } } } if (result) { REPEAT_PUSH(I2A(slot)); } screen_load(); string_free(prompt); return result; }
static power_type* select_power(s32b *x_idx) { s32b which; s32b max = 0, i, start = 0; power_type* ret; bool mode = easy_inven; s32b *p; C_MAKE(p, power_max, s32b); /* Count the max */ for (i = 0; i < power_max; i++) { if (flag_get(&p_ptr->powers, i)) { p[max++] = i; } } /* Exit if there aren't powers */ if (max == 0) { *x_idx = -1; ret = NULL; msg_print("You don't have any special powers."); } else { character_icky++; Term_save(); while (1) { print_power_batch(p, start, max, mode); which = inkey(); if (which == ESCAPE) { *x_idx = -1; ret = NULL; break; } else if (which == '*' || which == '?' || which == ' ') { mode = (mode) ? FALSE : TRUE; Term_load(); character_icky--; } else if (which == '+') { start += 20; if (start >= max) start -= 20; Term_load(); character_icky--; } else if (which == '-') { start -= 20; if (start < 0) start += 20; Term_load(); character_icky--; } else { which = tolower(which); if (start + A2I(which) >= max) { bell(); continue; } if (start + A2I(which) < 0) { bell(); continue; } *x_idx = p[start + A2I(which)]; ret = &powers_type[p[start + A2I(which)]]; break; } } Term_load(); character_icky--; } C_FREE(p, power_max, s32b); return ret; }
static int get_class_power(int *sn) { int i; int num = 0; int y = 1; int x = 10; int minfail =0; int plev = p_ptr->lev; int chance; int ask; int use_mind; char choice; char out_val[160]; char comment[80]; cptr p; mind_type spell; mind_power *mind_ptr; bool flag, redraw; /* Insert if /if else statement here for classflag. */ if ((cp_ptr->flags) & CF_OFFICER) { use_mind = MIND_OFFICER; p = "commanding presence"; } else if ((cp_ptr->flags) & CF_AESTHETE) { use_mind = MIND_AESTHETE; p = "skill"; } else if ((cp_ptr->flags) & CF_EXPLORER) { use_mind = MIND_EXPLORER; p = "talent"; } else if ((cp_ptr->flags) & CF_MEDIUM) { use_mind = MIND_MEDIUM; p = "mental power"; } else if ((cp_ptr->flags) & CF_RECKONER) { use_mind = MIND_RECKONER; p = "reality alteration"; } else if ((cp_ptr->flags) & CF_TOURIST) { use_mind = MIND_TOURIST; p = "tourism dept."; } else if ((cp_ptr->flags) & CF_HUSSAR) { use_mind = MIND_HUSSAR; p = "combat techniques"; } else if ((cp_ptr->flags) & CF_NATURE) { use_mind = MIND_NATURE; p = "natural empathy"; } else if ((cp_ptr->flags) & CF_NINJA) { use_mind = MIND_NINJA; p = "ninjutsu"; } else { msg_print("You have no powers."); } mind_ptr = &mind_powers[use_mind]; /* Assume cancelled */ *sn = (-1); #ifdef ALLOW_REPEAT /* TNB */ /* Get the spell, if available */ if (repeat_pull(sn)) { /* Verify the spell */ if (mind_ptr->info[*sn].min_lev <= plev) { /* Success */ return (TRUE); } } #endif /* ALLOW_REPEAT -- TNB */ /* Nothing chosen yet */ flag = FALSE; /* No redraw yet */ redraw = FALSE; for (i = 0; i < MAX_CLASS_POWERS; i++) { if (mind_ptr->info[i].min_lev <= plev) { num++; } } /* Build a prompt (accept all spells) */ (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) Use which %s? ", p, I2A(0), I2A(num - 1), p); /* Get a spell from the user */ while (!flag && get_com(out_val, &choice)) { /* Request redraw */ if ((choice == ' ') || (choice == '*') || (choice == '?')) { /* Show the list */ if (!redraw) { char psi_desc[80]; /* Show list */ redraw = TRUE; /* Save the screen */ screen_save(); prt("", y, x); put_str("Name", y, x + 5); put_str(format("Lv MP Fail Info"), y, x + 35); /* Dump the spells */ for (i = 0; i < MAX_CLASS_POWERS; i++) { /* Access the spell */ spell = mind_ptr->info[i]; if (spell.min_lev > plev) break; chance = spell.fail; /* Reduce failure rate by "effective" level adjustment */ chance -= 3 * (plev - spell.min_lev); /* Reduce failure rate by INT/WIS adjustment */ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[cp_ptr->spell_stat]] - 1); /* Not enough mana to cast */ if (spell.mana_cost > p_ptr->csp) { chance += 5 * (spell.mana_cost - p_ptr->csp); } /* Extract the minimum failure rate */ minfail = adj_mag_fail[p_ptr->stat_ind[cp_ptr->spell_stat]]; /* Minimum failure rate */ if (chance < minfail) chance = minfail; /* Stunning makes spells harder */ if (p_ptr->stun > 50) chance += 25; else if (p_ptr->stun) chance += 15; /* Always a 5 percent chance of working */ if (chance > 95) chance = 95; /* Get info */ mindcraft_info(comment, use_mind, i); sprintf(psi_desc, " %c) ",I2A(i)); strcat(psi_desc, format("%-30s%2d %4d %3d%%%s", spell.name, spell.min_lev, spell.mana_cost, chance, comment)); prt(psi_desc, y + i + 1, x); } /* Clear the bottom line */ prt("", y + i + 1, x); } /* Hide the list */ else { /* Hide list */ redraw = FALSE; /* Restore the screen */ screen_load(); } /* Redo asking */ continue; } /* Note verify */ ask = isupper(choice); /* Lowercase */ if (ask) choice = tolower(choice); /* Extract request */ i = (islower(choice) ? A2I(choice) : -1); /* Totally Illegal */ if ((i < 0) || (i >= num)) { bell("Illegal class power choice!"); continue; } /* Save the spell index */ spell = mind_ptr->info[i]; /* Verify it */ if (ask) { char tmp_val[160]; /* Prompt */ (void)strnfmt(tmp_val, 78, "Use %s? ", spell.name); /* Belay that order */ if (!get_check(tmp_val)) continue; } /* Stop the loop */ flag = TRUE; } /* Restore the screen */ if (redraw) screen_load(); /* Show choices */ /* Update */ p_ptr->window |= (PW_OVERHEAD); /* Window stuff */ window_stuff(); /* Abort if needed */ if (!flag) return (FALSE); /* Save the choice */ (*sn) = i; #ifdef ALLOW_REPEAT /* TNB */ repeat_push(*sn); #endif /* ALLOW_REPEAT -- TNB */ /* Success */ return (TRUE); }
/*! * @brief プレイヤーが詠唱中の呪術から一つを選んで停止する * @return なし */ bool stop_hex_spell(void) { int spell; char choice; char out_val[160]; bool flag = FALSE; int y = 1; int x = 20; int sp[MAX_KEEP]; if (!hex_spelling_any()) { #ifdef JP msg_print("呪文を詠唱していません。"); #else msg_print("You are casting no spell."); #endif return FALSE; } /* Stop all spells */ else if ((p_ptr->magic_num2[0] == 1) || (p_ptr->lev < 35)) { return stop_hex_spell_all(); } else { #ifdef JP strnfmt(out_val, 78, "どの呪文の詠唱を中断しますか?(呪文 %c-%c, 'l'全て, ESC)", I2A(0), I2A(p_ptr->magic_num2[0] - 1)); #else strnfmt(out_val, 78, "Which spell do you stop casting? (Spell %c-%c, 'l' to all, ESC)", I2A(0), I2A(p_ptr->magic_num2[0] - 1)); #endif screen_save(); while (!flag) { int n = 0; Term_erase(x, y, 255); prt(" 名前", y, x + 5); for (spell = 0; spell < 32; spell++) { if (hex_spelling(spell)) { Term_erase(x, y + n + 1, 255); put_str(format("%c) %s", I2A(n), do_spell(REALM_HEX, spell, SPELL_NAME)), y + n + 1, x + 2); sp[n++] = spell; } } if (!get_com(out_val, &choice, TRUE)) break; if (isupper(choice)) choice = tolower(choice); if (choice == 'l') /* All */ { screen_load(); return stop_hex_spell_all(); } if ((choice < I2A(0)) || (choice > I2A(p_ptr->magic_num2[0] - 1))) continue; flag = TRUE; } } screen_load(); if (flag) { int n = sp[A2I(choice)]; do_spell(REALM_HEX, n, SPELL_STOP); p_ptr->magic_num1[0] &= ~(1L << n); p_ptr->magic_num2[0]--; } /* Redraw status */ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); p_ptr->redraw |= (PR_EXTRA | PR_HP | PR_MANA); return flag; }
/*! * @brief 使用可能な青魔法を選択する / * Allow user to choose a imitation. * @param sn 選択したモンスター攻撃ID、キャンセルの場合-1、不正な選択の場合-2を返す * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。 * @details * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n * If the user hits escape, returns FALSE, and set '*sn' to -1\n * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n *\n * The "prompt" should be "cast", "recite", or "study"\n * The "known" should be TRUE for cast/pray, FALSE for study\n *\n * nb: This function has a (trivial) display bug which will be obvious\n * when you run it. It's probably easy to fix but I haven't tried,\n * sorry.\n */ static int get_learned_power(int *sn) { int i = 0; int num = 0; int y = 1; int x = 18; int minfail = 0; int plev = p_ptr->lev; int chance = 0; int ask = TRUE, mode = 0; int spellnum[MAX_MONSPELLS]; char ch; char choice; char out_val[160]; char comment[80]; s32b f4 = 0, f5 = 0, f6 = 0; cptr p = _("魔法", "magic"); monster_power spell; bool flag, redraw; int menu_line = (use_menu ? 1 : 0); /* Assume cancelled */ *sn = (-1); /* Nothing chosen yet */ flag = FALSE; /* No redraw yet */ redraw = FALSE; #ifdef ALLOW_REPEAT /* TNB */ /* Get the spell, if available */ if (repeat_pull(sn)) { /* Success */ return (TRUE); } #endif /* ALLOW_REPEAT -- TNB */ if (use_menu) { screen_save(); while(!mode) { #ifdef JP prt(format(" %s ボルト", (menu_line == 1) ? "》" : " "), 2, 14); prt(format(" %s ボール", (menu_line == 2) ? "》" : " "), 3, 14); prt(format(" %s ブレス", (menu_line == 3) ? "》" : " "), 4, 14); prt(format(" %s 召喚", (menu_line == 4) ? "》" : " "), 5, 14); prt(format(" %s その他", (menu_line == 5) ? "》" : " "), 6, 14); prt("どの種類の魔法を使いますか?", 0, 0); #else prt(format(" %s bolt", (menu_line == 1) ? "> " : " "), 2, 14); prt(format(" %s ball", (menu_line == 2) ? "> " : " "), 3, 14); prt(format(" %s breath", (menu_line == 3) ? "> " : " "), 4, 14); prt(format(" %s sommoning", (menu_line == 4) ? "> " : " "), 5, 14); prt(format(" %s others", (menu_line == 5) ? "> " : " "), 6, 14); prt("use which type of magic? ", 0, 0); #endif choice = inkey(); switch(choice) { case ESCAPE: case 'z': case 'Z': screen_load(); return FALSE; case '2': case 'j': case 'J': menu_line++; break; case '8': case 'k': case 'K': menu_line+= 4; break; case '\r': case 'x': case 'X': mode = menu_line; break; } if (menu_line > 5) menu_line -= 5; } screen_load(); } else { sprintf(comment, _("[A]ボルト, [B]ボール, [C]ブレス, [D]召喚, [E]その他:", "[A] bolt, [B] ball, [C] breath, [D] summoning, [E] others:")); while (TRUE) { if (!get_com(comment, &ch, TRUE)) { return FALSE; } if (ch == 'A' || ch == 'a') { mode = 1; break; } if (ch == 'B' || ch == 'b') { mode = 2; break; } if (ch == 'C' || ch == 'c') { mode = 3; break; } if (ch == 'D' || ch == 'd') { mode = 4; break; } if (ch == 'E' || ch == 'e') { mode = 5; break; } } } set_rf_masks(&f4, &f5, &f6, mode); for (i = 0, num = 0; i < 32; i++) { if ((0x00000001 << i) & f4) spellnum[num++] = i; } for (; i < 64; i++) { if ((0x00000001 << (i - 32)) & f5) spellnum[num++] = i; } for (; i < 96; i++) { if ((0x00000001 << (i - 64)) & f6) spellnum[num++] = i; } for (i = 0; i < num; i++) { if (p_ptr->magic_num2[spellnum[i]]) { if (use_menu) menu_line = i+1; break; } } if (i == num) { msg_print(_("その種類の魔法は覚えていない!", "You don't know any spell of this type.")); return (FALSE); } /* Build a prompt (accept all spells) */ (void)strnfmt(out_val, 78, _("(%c-%c, '*'で一覧, ESC) どの%sを唱えますか?", "(%c-%c, *=List, ESC=exit) Use which %s? "), I2A(0), I2A(num - 1), p); if (use_menu) screen_save(); /* Get a spell from the user */ choice= (always_show_list || use_menu) ? ESCAPE:1 ; while (!flag) { if(choice==ESCAPE) choice = ' '; else if( !get_com(out_val, &choice, TRUE) )break; if (use_menu && choice != ' ') { switch(choice) { case '0': { screen_load(); return (FALSE); } case '8': case 'k': case 'K': { do { menu_line += (num-1); if (menu_line > num) menu_line -= num; } while(!p_ptr->magic_num2[spellnum[menu_line-1]]); break; } case '2': case 'j': case 'J': { do { menu_line++; if (menu_line > num) menu_line -= num; } while(!p_ptr->magic_num2[spellnum[menu_line-1]]); break; } case '6': case 'l': case 'L': { menu_line=num; while(!p_ptr->magic_num2[spellnum[menu_line-1]]) menu_line--; break; } case '4': case 'h': case 'H': { menu_line=1; while(!p_ptr->magic_num2[spellnum[menu_line-1]]) menu_line++; break; } case 'x': case 'X': case '\r': { i = menu_line - 1; ask = FALSE; break; } } } /* Request redraw */ if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) { /* Show the list */ if (!redraw || use_menu) { char psi_desc[80]; /* Show list */ redraw = TRUE; /* Save the screen */ if (!use_menu) screen_save(); /* Display a list of spells */ prt("", y, x); put_str(_("名前", "Name"), y, x + 5); put_str(_("MP 失率 効果", "SP Fail Info"), y, x + 33); /* Dump the spells */ for (i = 0; i < num; i++) { int need_mana; prt("", y + i + 1, x); if (!p_ptr->magic_num2[spellnum[i]]) continue; /* Access the spell */ spell = monster_powers[spellnum[i]]; chance = spell.fail; /* Reduce failure rate by "effective" level adjustment */ if (plev > spell.level) chance -= 3 * (plev - spell.level); else chance += (spell.level - plev); /* Reduce failure rate by INT/WIS adjustment */ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); chance = mod_spell_chance_1(chance); need_mana = mod_need_mana(monster_powers[spellnum[i]].smana, 0, REALM_NONE); /* Not enough mana to cast */ if (need_mana > p_ptr->csp) { chance += 5 * (need_mana - p_ptr->csp); } /* Extract the minimum failure rate */ minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]]; /* Minimum failure rate */ if (chance < minfail) chance = minfail; /* Stunning makes spells harder */ if (p_ptr->stun > 50) chance += 25; else if (p_ptr->stun) chance += 15; /* Always a 5 percent chance of working */ if (chance > 95) chance = 95; chance = mod_spell_chance_2(chance); /* Get info */ learned_info(comment, spellnum[i]); if (use_menu) { if (i == (menu_line-1)) strcpy(psi_desc, _(" 》", " > ")); else strcpy(psi_desc, " "); } else sprintf(psi_desc, " %c)", I2A(i)); /* Dump the spell --(-- */ strcat(psi_desc, format(" %-26s %3d %3d%%%s", spell.name, need_mana, chance, comment)); prt(psi_desc, y + i + 1, x); } /* Clear the bottom line */ if (y < 22) prt("", y + i + 1, x); } /* Hide the list */ else { /* Hide list */ redraw = FALSE; /* Restore the screen */ screen_load(); } /* Redo asking */ continue; } if (!use_menu) { /* Note verify */ ask = isupper(choice); /* Lowercase */ if (ask) choice = tolower(choice); /* Extract request */ i = (islower(choice) ? A2I(choice) : -1); } /* Totally Illegal */ if ((i < 0) || (i >= num) || !p_ptr->magic_num2[spellnum[i]]) { bell(); continue; } /* Save the spell index */ spell = monster_powers[spellnum[i]]; /* Verify it */ if (ask) { char tmp_val[160]; /* Prompt */ (void) strnfmt(tmp_val, 78, _("%sの魔法を唱えますか?", "Use %s? "), monster_powers[spellnum[i]].name); /* Belay that order */ if (!get_check(tmp_val)) continue; } /* Stop the loop */ flag = TRUE; } /* Restore the screen */ if (redraw) screen_load(); /* Show choices */ p_ptr->window |= (PW_SPELL); /* Window stuff */ window_stuff(); /* Abort if needed */ if (!flag) return (FALSE); /* Save the choice */ (*sn) = spellnum[i]; #ifdef ALLOW_REPEAT /* TNB */ repeat_push(*sn); #endif /* ALLOW_REPEAT -- TNB */ /* Success */ return (TRUE); }