Instead of shops passing around global id_arr arrays, shops use the newly added third argument to item_def::name() which indicates whether to override item ID status. This means that the shop ID SIGHUP protection is now unnecessary; it's been removed. Hopefully I caught all the places where the stash tracker tries to get item names and fixed them, but I might have missed something.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1359 c06c8d41-db1a-0410-9941-cceddc491573
2KTJHQUX2LTU2BCLS5YXVRRKMOYKKIZAPF2LBKORFGSHEN5IO3IAC
4K4XALUPQZBXIPMPTU42DZP4Q7DDJSB6TCIWG5O5T4TX26GXIWFQC
JQ2PG3ZI7ISKGQ2BZYNIM2PEG4Z2EJHA4ZNKXEBVFBB6KDSHF7NAC
NLQFJJMMV55UZOFAKWAQ4FQSUEO5YDYF2NCUHCBPCDBLTRL776RAC
THE3KMFFWY4ZUFE3Z6RVTGPSPENYR7ULZDXPQYB3FXWPJOJ5P7WQC
PR2LVM33MZJBAOQ5ZIQNX6CH4DPPG7JJLRCFAPTPLMXSKNJAGJQAC
HYS3HXTXATFPN7GLN3WBGDCP22UT2D3JBVUS7SP5FE7L54TDCJRQC
YCL3W2PFE6ILTGBFODCSXNPDIA46KVSZP2TI7HDMYAOEJT65RIEAC
CRX4RG35C3DH57NIXCW4CG4X7SBMSX7TAJR2BAFQ4LQKCLYUNANQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
3JOOHBLF6D4362LD2TQGKYB5JVTNX34DD7DPXVJL5E2K2QN2EFLQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC
74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC
NCSALY7HYRVCKTPS5TWZBRE2C3OCANYU3LBPIZ4RRVEI6GOZL2EQC
QVVC7AYGVA6U64PTNA7L27422NLMO327P22BQKXEVIMPZHIHO7MQC
XKAJWK6MPHS3ZCZIPPLTIMOPF6AROGLRDDCS6EFE3IGE4AHT7MYQC
MOT3YZFRY3JG2MH3GN2VD6IY3IJSAXJUXMXS222TXWKRFCENOCDQC
HDLNRHAMFVDM4QCZMY6COBYZ35ODPR5PONT4UE77UAZ7GEE2FLHQC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
T7GULEUSVPY445FZAYPNTGCXYW3CKC5RQ2Q4KS7WF5W6LJV55YUQC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
WCAOZXOYYQBLVRS5FRZTP5ZFOYLQCCPWHGIFM2DLVGHIKVYSQVWQC
MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC
// this is really dumb. We copy the id[] array from itemname
// to the stack, for no good reason that I can see.
id_arr identy;
for (i = 0; i < identy.width(); ++i)
for (j = 0; j < identy.height(); ++j)
marshallByte(th, static_cast<char>(identy[i][j]));
std::string itemname = Stash::stash_item_name(si.item);
// mangle a temporary
item_def temp_item = si.item;
if ( shoptype_identifies_stock(this->shoptype) )
temp_item.flags |= ISFLAG_IDENT_MASK;
const std::string itemname = Stash::stash_item_name(temp_item);
if (is_dumpable_artifact(si.item, Options.verbose_dump))
// mangle a temporary
item_def temp_item = si.item;
if (shoptype_identifies_stock(this->shoptype))
temp_item.flags |= ISFLAG_IDENT_MASK;
if (is_dumpable_artifact(temp_item, Options.verbose_dump))
unsigned int item_value( item_def item, id_arr id, bool ident = false );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: misc
* *********************************************************************** */
void shop(void);
unsigned int item_value( item_def item, bool ident = false );
void shop();
// Protect the id array against being clobbered by a SIGHUP with the
// character in a shop.
extern id_arr shop_backup_id;
class shopping_hup_protect
{
public:
shopping_hup_protect() : shopping(crawl_state.shopping)
{
save_id(shop_backup_id);
crawl_state.shopping = true;
}
bool shoptype_identifies_stock(int shoptype);
static char in_a_shop(char shoppy, id_arr id);
static char more3(void);
static void purchase( int shop, int item_got, int cost );
static void shop_init_id(int i, id_fix_arr &shop_id);
static void shop_print(const char *shoppy, char sh_line);
static void shop_set_ident_type(int i, id_fix_arr &shop_id,
unsigned char base_type, unsigned char sub_type);
static void shop_uninit_id(int i, const id_fix_arr &shop_id);
static void in_a_shop(char shoppy);
static char more3();
static void purchase( int shop, int item_got, int cost);
static void shop_print(const char *shoppy, int sh_line);
{
shop_set_ident_type( shoppy, shop_id, mitm[shop_items[ft]].base_type,
mitm[shop_items[ft]].sub_type );
{
if ( id_stock )
{
// Identify the item and its type.
item_def& pitem = mitm[shop_items[ft]];
set_ident_type(pitem.base_type, pitem.sub_type, ID_KNOWN_TYPE);
set_ident_flags(pitem, ISFLAG_IDENT_MASK);
}
// purchase() will take the note if necessary.
return 0;
}
void shop_init_id_type(int shoptype, id_fix_arr &shop_id)
{
if (shoptype != SHOP_WEAPON_ANTIQUE
&& shoptype != SHOP_ARMOUR_ANTIQUE
&& shoptype != SHOP_GENERAL_ANTIQUE)
{
for (int j = 0; j < 50; j++)
{
shop_id[ IDTYPE_WANDS ][j] = get_ident_type(OBJ_WANDS, j);
set_ident_type(OBJ_WANDS, j, ID_KNOWN_TYPE);
shop_id[ IDTYPE_SCROLLS ][j] = get_ident_type(OBJ_SCROLLS, j);
set_ident_type(OBJ_SCROLLS, j, ID_KNOWN_TYPE);
shop_id[ IDTYPE_JEWELLERY ][j] = get_ident_type(OBJ_JEWELLERY, j);
set_ident_type(OBJ_JEWELLERY, j, ID_KNOWN_TYPE);
shop_id[ IDTYPE_POTIONS ][j] = get_ident_type(OBJ_POTIONS, j);
set_ident_type(OBJ_POTIONS, j, ID_KNOWN_TYPE);
}
}
}
static void shop_init_id(int i, id_fix_arr &shop_id)
{
shop_init_id_type( env.shop[i].type, shop_id );
}
void shop_uninit_id_type(int shoptype, const id_fix_arr &shop_id)
{
if (shoptype != SHOP_WEAPON_ANTIQUE
&& shoptype != SHOP_ARMOUR_ANTIQUE
&& shoptype != SHOP_GENERAL_ANTIQUE)
{
for (int j = 0; j < 50; j++)
{
set_ident_type( OBJ_WANDS, j,
shop_id[ IDTYPE_WANDS ][j], true );
set_ident_type( OBJ_SCROLLS, j,
shop_id[ IDTYPE_SCROLLS ][j], true );
set_ident_type( OBJ_JEWELLERY, j,
shop_id[ IDTYPE_JEWELLERY ][j], true );
set_ident_type( OBJ_POTIONS, j,
shop_id[ IDTYPE_POTIONS ][j], true );
}
}
if (env.shop[i].type != SHOP_WEAPON_ANTIQUE
&& env.shop[i].type != SHOP_ARMOUR_ANTIQUE
&& env.shop[i].type != SHOP_GENERAL_ANTIQUE)
{
switch (base_type)
{
case OBJ_WANDS:
shop_id[ IDTYPE_WANDS ][sub_type] = ID_KNOWN_TYPE;
break;
case OBJ_SCROLLS:
shop_id[ IDTYPE_SCROLLS ][sub_type] = ID_KNOWN_TYPE;
break;
case OBJ_JEWELLERY:
shop_id[ IDTYPE_JEWELLERY ][sub_type] = ID_KNOWN_TYPE;
break;
case OBJ_POTIONS:
shop_id[ IDTYPE_POTIONS ][sub_type] = ID_KNOWN_TYPE;
break;
}
}
}
void shop_print( const char *shoppy, char sh_lines )
{
if (item_type_known(item))
{
if (valued < 0)
valued = randart_value( item ) - 5;
else
valued += randart_value( item );
}
// in this branch we're guaranteed to know
// the item type!
if (valued < 0)
valued = randart_value( item ) - 5;
/* ***********************************************************************
* called from: describe - effects - item_use - shopping
* *********************************************************************** */
char get_ident_type(char cla, int ty);
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
void clear_ids(void);
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
void init_properties(void);
bool is_interesting_item( const item_def& item );
/* ***********************************************************************
* called from: files - shopping
* *********************************************************************** */
void save_id(id_arr identy, bool saving_game = false);
/* ***********************************************************************
* called from: dungeon - item_use
* *********************************************************************** */
bool hide2armour( unsigned char *which_subtype );
bool is_interesting_item( const item_def& item );
return (low == 'a' || low == 'e' || low == 'i' || low == 'o' || low == 'u');
}
item_type_id_type objtype_to_idtype(int base_type)
{
switch (base_type)
{
case OBJ_WANDS: return (IDTYPE_WANDS);
case OBJ_SCROLLS: return (IDTYPE_SCROLLS);
case OBJ_JEWELLERY: return (IDTYPE_JEWELLERY);
case OBJ_POTIONS: return (IDTYPE_POTIONS);
default: return (NUM_IDTYPE);
}
}
bool item_type_known( const item_def &item )
{
if (item_ident(item, ISFLAG_KNOW_TYPE))
return (true);
const item_type_id_type idt = objtype_to_idtype(item.base_type);
return (idt != NUM_IDTYPE? id[idt][item.sub_type] == ID_KNOWN_TYPE : false);
return (low == 'a' || low == 'e' || low == 'i' ||
low == 'o' || low == 'u');
|| (item_type_known( *this )
&& ((this->base_type == OBJ_MISCELLANY
&& this->sub_type == MISC_HORN_OF_GERYON)
|| (is_fixed_artefact( *this )
|| (is_random_artefact( *this ))))))
|| ( (ident || item_type_known( *this ))
&& ((this->base_type == OBJ_MISCELLANY
&& this->sub_type == MISC_HORN_OF_GERYON)
|| (is_fixed_artefact( *this )
|| (is_random_artefact( *this ))))))
memcpy(identy,
(!saving_game || !crawl_state.shopping)? id : shop_backup_id,
sizeof id);
} // end save_id()
switch (base_type)
{
case OBJ_WANDS: return (IDTYPE_WANDS);
case OBJ_SCROLLS: return (IDTYPE_SCROLLS);
case OBJ_JEWELLERY: return (IDTYPE_JEWELLERY);
case OBJ_POTIONS: return (IDTYPE_POTIONS);
default: return (NUM_IDTYPE);
}
}
switch (cla)
{
case OBJ_WANDS:
return id[ IDTYPE_WANDS ][ty];
const item_type_id_type idt = objtype_to_idtype(basetype);
if ( idt != NUM_IDTYPE && subtype < type_ids.height() )
return type_ids[idt][subtype];
else
return ID_UNKNOWN_TYPE;
}
int idx_to_objtype[4] = { OBJ_WANDS, OBJ_SCROLLS,
OBJ_JEWELLERY, OBJ_POTIONS };
int idx_to_maxtype[4] = { NUM_WANDS, NUM_SCROLLS,
NUM_JEWELLERY, NUM_POTIONS };
const int idx_to_objtype[4] = { OBJ_WANDS, OBJ_SCROLLS,
OBJ_JEWELLERY, OBJ_POTIONS };
const int idx_to_maxtype[4] = { NUM_WANDS, NUM_SCROLLS,
NUM_JEWELLERY, NUM_POTIONS };
snprintf( info, INFO_SIZE,
"base: %d; sub: %d; plus: %d; plus2: %d; special: %ld$"
"quant: %d; colour: %d; flags: 0x%08lx$"
"x: %d; y: %d; link: %d$ident_type: %d$$",
item.base_type, item.sub_type, item.plus, item.plus2,
item.special, item.quantity, item.colour, item.flags,
item.x, item.y, item.link,
get_ident_type( item.base_type, item.sub_type ) );
description += info;
description << std::setfill('0');
description << "base: " << static_cast<int>(item.base_type)
<< " sub: " << static_cast<int>(item.sub_type)
<< " plus: " << item.plus << " plus2: " << item.plus2
<< " special: " << item.special
<< "$"
<< "quant: " << item.quantity
<< " colour: " << static_cast<int>(item.colour)
<< " flags: " << std::hex << std::setw(8) << item.flags
<< std::dec << "$"
<< "x: " << item.x << " y: " << item.y
<< " link: " << item.link
<< "$"
<< "ident_type: "
<< get_ident_type(item.base_type, item.sub_type)
<< "$";
description += "A valuable book of magic which allows one to "
"practise a certain skill greatly. As it is used, it gradually "
"disintegrates and will eventually fall apart. ";
description << "A valuable book of magic which allows one to "
"practise a certain skill greatly. As it is used, it "
"gradually disintegrates and will eventually fall apart. ";
char item_mass[16];
itoa( mass / 10, item_mass, 10 );
for (int i = 0; i < 14; i++)
{
if (item_mass[i] == 0)
{
item_mass[i] = '.';
item_mass[i+1] = (mass % 10) + '0';
item_mass[i+2] = 0;
break;
}
}
description += item_mass;
description += " aum. "; // arbitrary unit of mass
char ch = 'x';
mpr("Press any key to start the tutorial intro, or Escape to skip it.",
MSGCH_TUTORIAL);
int ch = 'x';
mpr("Press any key to start the tutorial intro, "
"or Escape to skip it.", MSGCH_TUTORIAL);
snprintf(info, INFO_SIZE,
"%s, the %s %s, began the quest for the Orb.",
you.your_name,
species_name(you.species,you.experience_level),
you.class_name);
take_note(Note(NOTE_USER_NOTE, 0, 0, info));
snprintf(info, INFO_SIZE, "HP: %d/%d MP: %d/%d",
you.hp, you.hp_max, you.magic_points, you.max_magic_points);
take_note(Note(NOTE_XP_LEVEL_CHANGE, you.experience_level, 0, info));
std::ostringstream notestr;
notestr << you.your_name << ", the "
<< species_name(you.species,you.experience_level) << " "
<< you.class_name
<< ", began the quest for the Orb.";
take_note(Note(NOTE_USER_NOTE, 0, 0, notestr.str().c_str()));
notestr.str("");
notestr.clear();
notestr << "HP: " << you.hp << "/" << you.hp_max
<< " MP: " << you.magic_points << "/" << you.max_magic_points;
take_note(Note(NOTE_XP_LEVEL_CHANGE, you.experience_level, 0,
notestr.str().c_str()));
// ----- Access -----
TYPE& operator[](unsigned long index) {ASSERT(index < SIZE); return mData[index];}
const TYPE& operator[](unsigned long index) const {ASSERT(index < SIZE); return mData[index];}
TYPE& front() {ASSERT(SIZE > 0); return mData[0];}
const TYPE& front() const {ASSERT(SIZE > 0); return mData[0];}
// ----- Access -----
TYPE& operator[](unsigned long index) {
ASSERT(index < SIZE);
return mData[index];
}
TYPE& back() {ASSERT(SIZE > 0); return mData[SIZE - 1];}
const TYPE& back() const {ASSERT(SIZE > 0); return mData[SIZE - 1];}
TYPE* buffer() {return mData;}
const TYPE* buffer() const {return mData;}
const TYPE& operator[](unsigned long index) const {
ASSERT(index < SIZE);
return mData[index];
}
typedef FixedVector<TYPE, HEIGHT> Column; // operator[] needs to return one of these to avoid breaking client code (if inlining is on there won't be a speed hit)
// operator[] should return one of these to avoid breaking
// client code (if inlining is on there won't be a speed hit)
typedef FixedVector<TYPE, HEIGHT> Column;
bool empty() const {return WIDTH == 0 || HEIGHT == 0;}
int size() const {return WIDTH*HEIGHT;}
bool empty() const { return WIDTH == 0 || HEIGHT == 0; }
int size() const { return WIDTH*HEIGHT; }
int width() const { return WIDTH; }
int height() const { return HEIGHT; }
Column& operator[](unsigned long index) {return mData[index];}
const Column& operator[](unsigned long index) const {return mData[index];}
template<class Indexer> TYPE& operator () (const Indexer &i)
{
return mData[i.x][i.y];
}
Column& operator[](unsigned long index) { return mData[index]; }
const Column& operator[](unsigned long index) const {
return mData[index];
}
template<class Indexer> TYPE& operator () (const Indexer &i) {
return mData[i.x][i.y];
}
template<class Indexer> const TYPE& operator () (const Indexer &i) const {
return mData[i.x][i.y];
}
void init(const TYPE& def) {
for ( int i = 0; i < WIDTH; ++i )
mData[i].init(def);
}