This involves changes in quite a few things, so the major savefile version is now 1, and old savefiles will not load! Lots of conditional loading code has therefore been removed. Minor savefile version dropped to 0 in everything.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@495 c06c8d41-db1a-0410-9941-cceddc491573
5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC
unsigned char par;
int pdep;
find_parent_branch(branch, 1, &par, &pdep);
if (pdep)
return true;
// Do a brute force search in the travel cache for this branch.
return travel_cache.is_known_branch(branch);
return ( stair_level.find(static_cast<branch_type>(branch)) != stair_level.end() );
// These three are defined in overmap.cc
extern FixedArray < unsigned char, MAX_LEVELS, MAX_BRANCHES > altars_present;
extern FixedVector < char, MAX_BRANCHES > stair_level;
extern FixedArray < unsigned char, MAX_LEVELS, MAX_BRANCHES > feature;
// defined in overmap.cc
extern std::map<branch_type, level_id> stair_level;
extern std::map<level_pos, shop_type> shops_present;
extern std::map<level_pos, god_type> altars_present;
extern std::map<level_pos, portal_type> portals_present;
}
template<typename T>
void marshall_as_long(struct tagHeader& th, const T& t)
{
marshallLong( th, static_cast<long>(t) );
}
template<typename key, typename value>
void marshallMap(struct tagHeader &th, const std::map<key,value>& data,
void (*key_marshall)(struct tagHeader&, const key&),
void (*value_marshall)(struct tagHeader&, const value&))
{
marshallLong( th, data.size() );
typename std::map<key,value>::const_iterator ci;
for ( ci = data.begin(); ci != data.end(); ++ci )
{
key_marshall(th, ci->first);
value_marshall(th, ci->second);
}
}
void marshall_level_id( struct tagHeader& th, const level_id& id )
{
marshallByte(th, id.branch );
marshallLong(th, id.depth );
}
void marshall_level_pos( struct tagHeader& th, const level_pos& lpos )
{
marshallLong(th, lpos.pos.x);
marshallLong(th, lpos.pos.y);
marshall_level_id(th, lpos.id);
}
template<typename key, typename value>
void unmarshallMap(struct tagHeader& th, std::map<key,value>& data,
key (*key_unmarshall) (struct tagHeader&),
value (*value_unmarshall)(struct tagHeader&) )
{
long i, len = unmarshallLong(th);
key k;
value v;
for ( i = 0; i < len; ++i )
{
k = key_unmarshall(th);
v = value_unmarshall(th);
data[k] = v;
}
}
template<typename T>
T unmarshall_long_as( struct tagHeader& th )
{
return static_cast<T>(unmarshallLong(th));
level_id unmarshall_level_id( struct tagHeader& th )
{
level_id id;
id.branch = unmarshallByte(th);
id.depth = unmarshallLong(th);
return id;
}
level_pos unmarshall_level_pos( struct tagHeader& th )
{
level_pos lpos;
lpos.pos.x = unmarshallLong(th);
lpos.pos.y = unmarshallLong(th);
lpos.id = unmarshall_level_id(th);
return lpos;
}
{
marshallByte(th,altars_present[i][j]);
marshallByte(th,feature[i][j]);
marshallBoolean(th,tmp_file_pairs[i][j]);
}
}
marshallBoolean(th, tmp_file_pairs[i][j]);
marshallMap(th, stair_level,
marshall_as_long<branch_type>, marshall_level_id);
marshallMap(th, shops_present,
marshall_level_pos, marshall_as_long<shop_type>);
marshallMap(th, altars_present,
marshall_level_pos, marshall_as_long<god_type>);
marshallMap(th, portals_present,
marshall_level_pos, marshall_as_long<portal_type>);
if (minorVersion >= 2)
{
count_c = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.spell_letter_table[i] = unmarshallByte(th);
count_c = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.spell_letter_table[i] = unmarshallByte(th);
count_c = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.ability_letter_table[i] = unmarshallShort(th);
count_c = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.ability_letter_table[i] = unmarshallShort(th);
}
else
{
for (i = 0; i < 52; i++)
{
you.spell_letter_table[i] = -1;
you.ability_letter_table[i] = ABIL_NON_ABILITY;
}
for (i = 0; i < 25; i++)
{
if (you.spells[i] != SPELL_NO_SPELL)
you.spell_letter_table[i] = i;
}
if (you.religion != GOD_NO_GOD)
set_god_ability_slots();
}
if (minorVersion >= 2)
{
count_c = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.worshipped[i] = unmarshallByte(th);
if (minorVersion >= 5)
for (i = 0; i < count_c; i++)
you.num_gifts[i] = unmarshallShort(th);
count_c = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.worshipped[i] = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.num_gifts[i] = unmarshallShort(th);
if (minorVersion >= 1)
{
// wizard mode
you.wizard = (bool) unmarshallByte(th);
// time of character creation
unmarshallString( th, buff, 20 );
you.birth_time = parse_date_string( buff );
}
if (minorVersion >= 2)
{
you.real_time = unmarshallLong(th);
you.num_turns = unmarshallLong(th);
}
else
{
you.real_time = -1;
you.num_turns = -1;
}
// you.magic_contamination 05/03/05
if (minorVersion >= 3)
{
you.magic_contamination = unmarshallShort(th);
}
}
static void tag_convert_to_4_3_item( item_def &item )
{
const unsigned char plus = item.plus;
const unsigned char plus2 = item.plus2;
const unsigned char ident = item.flags;
const unsigned char special = item.special;
if (item.quantity <= 0)
return;
// First, convert ident into flags:
item.flags = (ident == 3) ? ISFLAG_IDENT_MASK :
(ident > 0) ? ISFLAG_KNOW_CURSE
: 0;
switch (item.base_type)
{
case OBJ_ARMOUR:
if ((ident == 1 && special % 30 >= 25) || ident == 2)
item.flags |= ISFLAG_KNOW_TYPE;
// Convert special values
item.special %= 30;
if (item.special < 25)
{
if (item.sub_type == ARM_HELMET)
{
item.plus2 = plus2 % 30;
set_helmet_desc( item, (special / 30) << 8 );
}
else
{
switch (special / 30)
{
case DARM_EMBROIDERED_SHINY:
set_equip_desc( item, ISFLAG_EMBROIDERED_SHINY );
break;
case DARM_RUNED:
set_equip_desc( item, ISFLAG_RUNED );
break;
case DARM_GLOWING:
set_equip_desc( item, ISFLAG_GLOWING );
break;
case DARM_ELVEN:
set_equip_race( item, ISFLAG_ELVEN );
break;
case DARM_DWARVEN:
set_equip_race( item, ISFLAG_DWARVEN );
break;
case DARM_ORCISH:
set_equip_race( item, ISFLAG_ORCISH );
break;
default:
break;
}
}
}
else if (item.special == 25)
{
item.flags |= ISFLAG_UNRANDART;
item.special = 0;
}
else
{
item.flags |= ISFLAG_RANDART;
// calc old seed
item.special = item.base_type * special
+ item.sub_type * (plus % 100)
+ plus2 * 100;
}
break;
case OBJ_WEAPONS:
if ((ident == 1 && (special < 180 && special % 30 >= 25)) || ident == 2)
item.flags |= ISFLAG_KNOW_TYPE;
// Convert special values
if (special < 181) // don't mangle fixed artefacts
{
item.special %= 30;
if (item.special < 25)
{
switch (special / 30)
{
case DWPN_RUNED:
set_equip_desc( item, ISFLAG_RUNED );
break;
case DWPN_GLOWING:
set_equip_desc( item, ISFLAG_GLOWING );
break;
case DWPN_ORCISH:
set_equip_race( item, ISFLAG_ORCISH );
break;
case DWPN_ELVEN:
set_equip_race( item, ISFLAG_ELVEN );
break;
case DWPN_DWARVEN:
set_equip_race( item, ISFLAG_DWARVEN );
break;
default:
break;
}
}
else if (item.special == 25)
{
item.flags |= ISFLAG_UNRANDART;
item.special = 0;
}
else
{
item.flags |= ISFLAG_RANDART;
// calc old seed
item.special = item.base_type * special
+ item.sub_type * (plus % 100)
+ plus2 * 100;
}
}
break;
case OBJ_MISSILES:
// Needles were moved into the bonus eggplant spot. -- bwr
if (item.sub_type == 6)
item.sub_type = MI_NEEDLE;
if (ident == 2)
item.flags |= ISFLAG_KNOW_TYPE;
// Convert special values
item.special %= 30;
switch (special / 30)
{
case DAMMO_ORCISH:
set_equip_race( item, ISFLAG_ORCISH );
break;
case DAMMO_ELVEN:
set_equip_race( item, ISFLAG_ELVEN );
break;
case DAMMO_DWARVEN:
set_equip_race( item, ISFLAG_DWARVEN );
break;
default:
break;
}
break;
case OBJ_WANDS:
if (ident == 2)
item.flags |= ISFLAG_KNOW_PLUSES;
break;
case OBJ_JEWELLERY:
if (ident == 1 && (special == 200 || special == 201))
item.flags |= ISFLAG_KNOW_TYPE;
else if (ident == 2)
item.flags |= (ISFLAG_KNOW_TYPE | ISFLAG_KNOW_PLUSES);
if (special == 201)
{
item.flags |= ISFLAG_UNRANDART;
item.special = 0;
}
else if (special == 200)
{
item.flags |= ISFLAG_RANDART;
// calc old seed
item.special = item.base_type * special
+ item.sub_type * (plus % 100)
+ plus2 * 100;
}
break;
default:
if (ident > 0)
item.flags |= ISFLAG_KNOW_TYPE;
break;
}
// Second, convert plus and plus2
if (item.base_type == OBJ_WEAPONS
|| item.base_type == OBJ_MISSILES
|| item.base_type == OBJ_ARMOUR
|| item.base_type == OBJ_JEWELLERY)
{
item.plus = plus;
// item is cursed:
if (plus > 100)
{
item.plus -= 100;
item.flags |= ISFLAG_CURSED;
}
// time of character creation
unmarshallString( th, buff, 20 );
you.birth_time = parse_date_string( buff );
// Weapons use both as pluses.
// Non-artefact jewellery uses both as pluses.
// Artefact jewellery has literal values for both pluses.
// Armour and Missiles only use plus for their plus value.
// Armour has literal usage of plus2 for sub-subtypes.
if (item.base_type != OBJ_JEWELLERY)
{
item.plus -= 50;
you.real_time = unmarshallLong(th);
you.num_turns = unmarshallLong(th);
if (item.base_type == OBJ_WEAPONS)
item.plus2 -= 50;
}
else if (special != 200)
{
// regular jewellery & unrandarts -- unused pluses were 0s
if (item.plus)
item.plus -= 50;
if (item.plus2)
item.plus2 -= 50;
}
else if (special == 200)
{
// Randart jewellery used pluses only as seeds, right now
// they're always zero (since random artefact rings avoid
// base types with pluses).
item.plus = 0;
item.plus2 = 0;
}
}
you.magic_contamination = unmarshallShort(th);
if (minorVersion < 1)
{
you.inv[i].base_type = (unsigned char) unmarshallByte(th);
you.inv[i].sub_type = (unsigned char) unmarshallByte(th);
you.inv[i].plus = (unsigned char) unmarshallByte(th);
you.inv[i].special = (unsigned char) unmarshallByte(th);
you.inv[i].colour = (unsigned char) unmarshallByte(th);
you.inv[i].flags = (unsigned char) unmarshallByte(th);
you.inv[i].quantity = unmarshallShort(th);
you.inv[i].plus2 = (unsigned char) unmarshallByte(th);
you.inv[i].base_type = (unsigned char) unmarshallByte(th);
you.inv[i].sub_type = (unsigned char) unmarshallByte(th);
you.inv[i].plus = unmarshallShort(th);
you.inv[i].special = unmarshallLong(th);
you.inv[i].colour = (unsigned char) unmarshallByte(th);
you.inv[i].flags = (unsigned long) unmarshallLong(th);
you.inv[i].quantity = unmarshallShort(th);
you.inv[i].plus2 = unmarshallShort(th);
you.inv[i].orig_place = unmarshallShort(th);
you.inv[i].orig_monnum = unmarshallShort(th);
tag_convert_to_4_3_item( you.inv[i] );
}
else
{
you.inv[i].base_type = (unsigned char) unmarshallByte(th);
you.inv[i].sub_type = (unsigned char) unmarshallByte(th);
you.inv[i].plus = unmarshallShort(th);
you.inv[i].special = unmarshallLong(th);
you.inv[i].colour = (unsigned char) unmarshallByte(th);
you.inv[i].flags = (unsigned long) unmarshallLong(th);
you.inv[i].quantity = unmarshallShort(th);
you.inv[i].plus2 = unmarshallShort(th);
char insstring[80];
unmarshallString(th, insstring, 80);
you.inv[i].inscription = std::string(insstring);
if (minorVersion >= 4)
{
you.inv[i].orig_place = unmarshallShort(th);
you.inv[i].orig_monnum = unmarshallShort(th);
if (minorVersion >= 6)
{
/*** HP CHANGE ***/
char insstring[80];
unmarshallString(th, insstring, 80);
you.inv[i].inscription = std::string(insstring);
}
}
}
}
}
unmarshallMap(th, stair_level,
unmarshall_long_as<branch_type>, unmarshall_level_id);
unmarshallMap(th, shops_present,
unmarshall_level_pos, unmarshall_long_as<shop_type>);
unmarshallMap(th, altars_present,
unmarshall_level_pos, unmarshall_long_as<god_type>);
unmarshallMap(th, portals_present,
unmarshall_level_pos, unmarshall_long_as<portal_type>);
if (minorVersion < 3)
{
mitm[i].base_type = (unsigned char) unmarshallByte(th);
mitm[i].sub_type = (unsigned char) unmarshallByte(th);
mitm[i].plus = (unsigned char) unmarshallByte(th);
mitm[i].plus2 = (unsigned char) unmarshallByte(th);
mitm[i].special = (unsigned char) unmarshallByte(th);
mitm[i].quantity = unmarshallLong(th);
mitm[i].colour = (unsigned char) unmarshallByte(th);
mitm[i].x = (unsigned char) unmarshallByte(th);
mitm[i].y = (unsigned char) unmarshallByte(th);
mitm[i].flags = (unsigned char) unmarshallByte(th);
tag_convert_to_4_3_item( mitm[i] );
}
else
{
mitm[i].base_type = (unsigned char) unmarshallByte(th);
mitm[i].sub_type = (unsigned char) unmarshallByte(th);
mitm[i].plus = unmarshallShort(th);
mitm[i].plus2 = unmarshallShort(th);
mitm[i].special = unmarshallLong(th);
mitm[i].quantity = unmarshallShort(th);
mitm[i].colour = (unsigned char) unmarshallByte(th);
mitm[i].x = unmarshallShort(th);
mitm[i].y = unmarshallShort(th);
mitm[i].flags = (unsigned long) unmarshallLong(th);
}
mitm[i].base_type = (unsigned char) unmarshallByte(th);
mitm[i].sub_type = (unsigned char) unmarshallByte(th);
mitm[i].plus = unmarshallShort(th);
mitm[i].plus2 = unmarshallShort(th);
mitm[i].special = unmarshallLong(th);
mitm[i].quantity = unmarshallShort(th);
mitm[i].colour = (unsigned char) unmarshallByte(th);
mitm[i].x = unmarshallShort(th);
mitm[i].y = unmarshallShort(th);
mitm[i].flags = (unsigned long) unmarshallLong(th);
if (minorVersion >= 9)
{
/*** HP CHANGE ***/
char insstring[80];
unmarshallString(th, insstring, 80);
mitm[i].inscription = std::string(insstring);
}
}
else
{
mitm[i].orig_place = 0;
mitm[i].orig_monnum = 0;
}
mitm[i].orig_place = unmarshallShort(th);
mitm[i].orig_monnum = unmarshallShort(th);
char insstring[80];
unmarshallString(th, insstring, 80);
mitm[i].inscription = std::string(insstring);
if (minorVersion < 2)
{
menv[i].flags = 0;
for(j=0; j<NUM_MON_ENCHANTS; j++)
{
if (j>=ecount)
menv[i].enchantment[j] = ENCH_NONE;
else
{
if (menv[i].enchantment[j] == 71) // old ENCH_CREATED_FRIENDLY
{
menv[i].enchantment[j] = ENCH_NONE;
menv[i].flags |= MF_CREATED_FRIENDLY;
}
if (menv[i].enchantment[j] >= 65 // old ENCH_FRIEND_ABJ_I
&& menv[i].enchantment[j] <= 70) // old ENCH_FRIEND_ABJ_VI
{
menv[i].enchantment[j] -= (65 - ENCH_ABJ_I);
menv[i].flags |= MF_CREATED_FRIENDLY;
}
}
}
} // end minorversion < 2
if (minorVersion >= 10)
{
for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
menv[i].spells[j] = unmarshallShort(th);
}
else if (menv[i].type != -1)
{
const int book = obsolete_mons_spell_template_index( &menv[i] );
mons_load_spells( &menv[i], book );
}
for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
menv[i].spells[j] = unmarshallShort(th);
{
// for version 4.4 we moved from unsigned char to shorts -- bwr
if (minorVersion < 4)
ghost.values[i] = unmarshallByte(th);
else
ghost.values[i] = unmarshallShort(th);
}
if (minorVersion < 4)
{
// Getting rid 9of hopefulling the last) of this silliness -- bwr
if (ghost.values[ GVAL_RES_FIRE ] >= 97)
ghost.values[ GVAL_RES_FIRE ] -= 100;
if (ghost.values[ GVAL_RES_COLD ] >= 97)
ghost.values[ GVAL_RES_COLD ] -= 100;
}
ghost.values[i] = unmarshallShort(th);
void seen_notable_thing( int which_thing );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: view
* *********************************************************************** */
void seen_altar(unsigned char which_altar);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
void init_overmap(void);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
void display_overmap(void);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: view
* *********************************************************************** */
void seen_staircase(unsigned char which_staircase);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: view
* *********************************************************************** */
void seen_other_thing(unsigned char which_thing);
enum
{
NO_FEATURE = 0x00,
FEATURE_SHOP = 0x01,
FEATURE_LABYRINTH = 0x02,
FEATURE_HELL = 0x04,
FEATURE_ABYSS = 0x08,
FEATURE_PANDEMONIUM = 0x10
};
std::map<branch_type, level_id> stair_level;
std::map<level_pos, shop_type> shops_present;
std::map<level_pos, god_type> altars_present;
std::map<level_pos, portal_type> portals_present;
// These variables need to become part of the player struct
// and need to be stored in the .sav file:
// 0 == no altars;
// 100 == more than one altar; or
// # == which god for remaining numbers.
static void seen_altar( god_type god, const coord_def& pos );
static void seen_staircase(unsigned char which_staircase,const coord_def& pos);
static void seen_other_thing(unsigned char which_thing, const coord_def& pos);
FixedArray<unsigned char, MAX_LEVELS, MAX_BRANCHES> altars_present;
FixedVector<char, MAX_BRANCHES> stair_level;
FixedArray<unsigned char, MAX_LEVELS, MAX_BRANCHES> feature;
int map_lines = 0; //mv: number of lines already printed on "over-map" screen
//mv: prints one line in specified colour
// void print_one_map_line( const char *line, int colour );
// void print_branch_entrance_line( const char *area );
void print_one_simple_line( const char *line, int colour );
void print_one_highlighted_line( const char *pre, const char *text,
const char *post, int colour );
static void print_level_name( int branch, int depth,
bool &printed_branch, bool &printed_level );
void seen_notable_thing( int which_thing )
void seen_notable_thing( int which_thing, int x, int y )
for (int j = 0; j < MAX_BRANCHES; j++)
{
altars_present[i][j] = 0;
feature[i][j] = 0;
}
case PORTAL_LABYRINTH:
return "<cyan>Labyrinth:</cyan>";
case PORTAL_HELL:
return "<red>Hell:</red>";
case PORTAL_ABYSS:
return "<magenta>Abyss:</magenta>";
case PORTAL_PANDEMONIUM:
return "<blue>Pan:</blue>";
default:
return "<lightred>Buggy:</lightred>";
for (int i = 0; i < MAX_BRANCHES; i++)
stair_level[i] = -1;
} // end init_overmap()
static char shoptype_to_char(shop_type s)
{
switch ( s )
{
case SHOP_WEAPON:
case SHOP_WEAPON_ANTIQUE:
return '(';
case SHOP_ARMOUR:
case SHOP_ARMOUR_ANTIQUE:
return '[';
case SHOP_GENERAL_ANTIQUE:
case SHOP_GENERAL:
return '*';
case SHOP_JEWELLERY:
return '=';
case SHOP_WAND:
return '/';
case SHOP_BOOK:
return ':';
case SHOP_FOOD:
return '%';
case SHOP_DISTILLERY:
return '!';
case SHOP_SCROLL:
return '?';
default:
return 'x';
}
}
window(1, 1, 80, 25);
gettext(1, 1, 80, 25, buffer);
#endif
//mv: must be set to 0 so "More..." message appears really at the
// bottom of the screen
//Don't forget it could be changed since the last call of display_overmap
map_lines = 0;
clrscr();
bool pr_lev = false;
bool output = false;
print_one_simple_line(" Overview of the Dungeon", WHITE);
// This is a more sensible order than the order of the enums -- bwr
const int list_order[] =
// better put this somewhere central
const branch_type list_order[] =
for (int j = 0; j < MAX_LEVELS; j++)
// print branches
int branchcount = 0;
for (unsigned int i = 1; i < sizeof(list_order)/sizeof(branch_type); ++i)
{
const branch_type branch = list_order[i];
if ( stair_level.find(branch) != stair_level.end() )
bool printed_level = false;
if (altars_present[j][i] != 0)
{
print_level_name( i, j, printed_branch, printed_level );
output = true;
if (altars_present[j][i] == 100)
{
print_one_highlighted_line( " - some ",
"altars to the gods", ".",
WHITE );
}
else
{
snprintf( info, INFO_SIZE, "altar to %s",
god_name( altars_present[j][i] ) );
print_one_highlighted_line( " - an ", info, ".", WHITE );
}
}
if ( (feature[j][i] & FEATURE_SHOP) )
if ( !branchcount )
print_level_name( i, j, printed_branch, printed_level );
// print_one_simple_line(" - facilities for the purchase of goods.",LIGHTGREY);
print_one_highlighted_line( " - facilities for the ",
"purchase of goods", ".", LIGHTGREEN );
output = true;
disp += EOL "<white>Branches:</white>" EOL;
seen_anything = true;
if ( (feature[j][i] & FEATURE_ABYSS) )
{
print_level_name( i, j, printed_branch, printed_level );
// print_one_simple_line(" - a gateway into the Abyss.", LIGHTRED);
print_one_highlighted_line( " - a gateway into ",
"the Abyss", ".", MAGENTA );
output = true;
}
if ( (feature[j][i] & FEATURE_PANDEMONIUM) )
{
print_level_name( i, j, printed_branch, printed_level );
// print_one_simple_line(" - a link to Pandemonium.", LIGHTRED);
print_one_highlighted_line( " - a link to ", "Pandemonium",
".", LIGHTBLUE );
output = true;
}
if ( (feature[j][i] & FEATURE_HELL) )
{
print_level_name( i, j, printed_branch, printed_level );
// print_one_simple_line(" - a mouth of Hell.", LIGHTRED);
print_one_highlighted_line( " - a mouth of ", "Hell", ".", RED );
output = true;
}
if ( (feature[j][i] & FEATURE_LABYRINTH) )
{
print_level_name( i, j, printed_branch, printed_level );
// print_one_simple_line(" - the entrance of a Labyrinth.", LIGHTRED);
print_one_highlighted_line( " - an entrance to ",
"a Labyrinth", ".", CYAN );
output = true;
}
snprintf(buffer, sizeof buffer, "<yellow>%-6s</yellow>: %-7s",
branch_name(branch, true).c_str(),
stair_level[branch].describe(false, true).c_str());
disp += buffer;
if ( (branchcount % 4) == 0 )
disp += EOL;
else
disp += " ";
}
}
if ( branchcount && (branchcount % 4) )
disp += EOL;
// print altars
// we loop through everything a dozen times, oh well
if ( !altars_present.empty() )
{
disp += EOL "<white>Altars:</white>" EOL;
seen_anything = true;
}
level_id last_id;
std::map<level_pos, god_type>::const_iterator ci_altar;
for ( int cur_god = GOD_NO_GOD; cur_god < NUM_GODS; ++cur_god )
{
last_id.depth = 10000; // fake depth to be sure we don't match
// GOD_NO_GOD becomes your god
int real_god = (cur_god == GOD_NO_GOD ? you.religion : cur_god);
if ( cur_god == you.religion )
continue;
// NB: k starts at 1 because there aren't any staircases
// to the main dungeon
for (int k = 1; k < MAX_BRANCHES; k++)
for ( ci_altar = altars_present.begin();
ci_altar != altars_present.end();
++ci_altar )
{
if ( ci_altar->second == real_god )
switch (i)
{
case BRANCH_LAIR:
switch (k)
{
case BRANCH_SLIME_PITS:
strcat(info, "the Slime Pits");
pr_lev = true;
break;
case BRANCH_SNAKE_PIT:
strcat(info, "the Snake Pit");
pr_lev = true;
break;
case BRANCH_SWAMP:
strcat(info, "the Swamp");
pr_lev = true;
break;
}
break;
case BRANCH_VAULTS:
switch (k)
{
case BRANCH_HALL_OF_BLADES:
strcat(info, "the Hall of Blades");
pr_lev = true;
break;
case BRANCH_CRYPT:
strcat(info, "the Crypt");
pr_lev = true;
break;
}
break;
case BRANCH_CRYPT:
switch (k)
{
case BRANCH_TOMB:
strcat(info, "the Tomb");
pr_lev = true;
break;
}
break;
case BRANCH_ORCISH_MINES:
switch (k)
{
case BRANCH_ELVEN_HALLS:
strcat(info, "the Elven Halls");
pr_lev = true;
break;
}
break;
case BRANCH_MAIN_DUNGEON:
switch (k)
{
case BRANCH_ORCISH_MINES:
strcat(info, "the Orcish Mines");
pr_lev = true;
break;
case BRANCH_HIVE:
strcat(info, "the Hive");
pr_lev = true;
break;
case BRANCH_LAIR:
strcat(info, "the Lair");
pr_lev = true;
break;
case BRANCH_VAULTS:
strcat(info, "the Vaults");
pr_lev = true;
break;
case BRANCH_HALL_OF_ZOT:
strcat(info, "the Hall of Zot");
pr_lev = true;
break;
case BRANCH_ECUMENICAL_TEMPLE:
strcat(info, "the Ecumenical Temple");
pr_lev = true;
break;
}
break;
}
disp += god_name( ci_altar->second, false );
disp += ": ";
disp += ci_altar->first.id.describe(false, true);
print_level_name( i, j, printed_branch, printed_level );
print_one_highlighted_line( " - the entrance to ", info,
".", YELLOW );
output = true;
if ( last_id == ci_altar->first.id )
disp += '*';
else
{
disp += ", ";
disp += ci_altar->first.id.describe(false, true);
}
printed_branch = true;
print_one_simple_line( "", YELLOW );
print_one_simple_line(
(branch == BRANCH_MAIN_DUNGEON) ? "Main Dungeon" :
(branch == BRANCH_ORCISH_MINES) ? "The Orcish Mines" :
(branch == BRANCH_HIVE) ? "The Hive" :
(branch == BRANCH_LAIR) ? "The Lair" :
(branch == BRANCH_SLIME_PITS) ? "The Slime Pits" :
(branch == BRANCH_VAULTS) ? "The Vaults" :
(branch == BRANCH_CRYPT) ? "The Crypt" :
(branch == BRANCH_HALL_OF_BLADES) ? "The Hall of Blades" :
(branch == BRANCH_HALL_OF_ZOT) ? "The Hall of Zot" :
(branch == BRANCH_ECUMENICAL_TEMPLE) ? "The Ecumenical Temple" :
(branch == BRANCH_SNAKE_PIT) ? "The Snake Pit" :
(branch == BRANCH_ELVEN_HALLS) ? "The Elven Halls" :
(branch == BRANCH_TOMB) ? "The Tomb" :
(branch == BRANCH_SWAMP) ? "The Swamp" :
(branch == BRANCH_DIS) ? "The Iron City of Dis" :
(branch == BRANCH_GEHENNA) ? "Gehenna" :
(branch == BRANCH_VESTIBULE_OF_HELL) ? "The Vestibule of Hell" :
(branch == BRANCH_COCYTUS) ? "Cocytus" :
(branch == BRANCH_TARTARUS) ? "Tartarus"
: "Unknown Area",
YELLOW );
disp += EOL "<white>Shops:</white>" EOL;
seen_anything = true;
// these areas only have one level... let's save the space
return;
if ( placecount )
{
// there are at most 5 shops per level, plus 7 chars for
// the level name, plus 4 for the spacing; that makes
// a total of 16 chars per shop or exactly 5 per line.
if ( placecount % 5 == 0 )
disp += EOL;
else
disp += " ";
}
++placecount;
disp += "<brown>";
disp += ci_shops->first.id.describe(false, true);
disp += "</brown>";
disp += ": ";
last_id = ci_shops->first.id;
if (branch == BRANCH_MAIN_DUNGEON)
depth += 1;
else if (branch >= BRANCH_ORCISH_MINES && branch <= BRANCH_SWAMP)
depth -= you.branch_stairs[ branch - BRANCH_ORCISH_MINES ];
else // branch is in hell (all of which start at depth 28)
depth -= 26;
// print portals
if ( !portals_present.empty() )
{
disp += EOL "<white>Portals:</white>" EOL;
seen_anything = true;
}
for (int cur_portal = PORTAL_NONE; cur_portal < NUM_PORTALS; ++cur_portal)
{
last_id.depth = 10000;
std::map<level_pos, portal_type>::const_iterator ci_portals;
for ( ci_portals = portals_present.begin();
ci_portals != portals_present.end();
++ci_portals )
{
// one line per region should be enough, they're all of
// the form D:XX, except for labyrinth portals, of which
// you would need 11 (at least) to have a problem.
if ( ci_portals->second == cur_portal )
{
if ( last_id.depth == 10000 )
disp += portaltype_to_string(ci_portals->second);
snprintf( buff, INFO_SIZE, " Level %d:", depth );
print_one_simple_line( buff, LIGHTRED );
if ( ci_portals->first.id == last_id )
disp += '*';
else
{
disp += ' ';
disp += ci_portals->first.id.describe(false, true);
}
last_id = ci_portals->first.id;
}
}
if ( last_id.depth != 10000 )
disp += EOL;
// already seen
if ( altars_present[you.your_level][you.where_are_you] == which_altar )
return;
if ( altars_present[you.your_level][you.where_are_you] == 0 )
altars_present[you.your_level][you.where_are_you] = which_altar;
else
altars_present[you.your_level][you.where_are_you] = 100;
} // end seen_altar()
} // end seen_other_thing()
/* mv: this function prints one line at "Over-map screen" in specified colour.
* If map_lines = maximum number of lines (it means the screen is full) it
* prints "More..." message, read key, clear screen and after that prints new
* line
*/
void print_one_simple_line( const char *line, int colour)
{
if (map_lines == (get_number_of_lines() - 2))
{
textcolor( LIGHTGREY );
cprintf(EOL);
cprintf("More...");
getch();
clrscr();
map_lines = 0;
}
textcolor( colour );
cprintf( "%s" EOL, line );
map_lines++;
if (pre[0] != 0)
{
textcolor( LIGHTGREY );
cprintf( "%s", pre );
}
textcolor( colour );
cprintf( "%s", text );
level_pos where(level_id::get_current_level_id(), pos);
textcolor( LIGHTGREY );
cprintf( "%s", post );
case DNGN_ENTER_SHOP:
shops_present[where] =
static_cast<shop_type>(get_shop(pos.x, pos.y)->type);
break;
default:
const portal_type portal = feature_to_portal(which_thing);
if ( portal != PORTAL_NONE )
portals_present[where] = portal;
break;
}
bool single_level_branch( int branch )
{
return
branch == BRANCH_VESTIBULE_OF_HELL ||
branch == BRANCH_HALL_OF_BLADES ||
branch == BRANCH_ECUMENICAL_TEMPLE;
}
std::string branch_name( int branch, bool terse )
{
const char* names[][2] = {
{ "The Dungeon", "D" },
{ "The Iron City of Dis", "Dis" },
{ "Gehenna", "Geh" },
{ "The Vestibule of Hell", "Hell" },
{ "Cocytus", "Coc" },
{ "Tartarus", "Tar" },
{ "Inferno", "Inf" },
{ "The Pit", "Pit" },
{ "", "" },
{ "", "" },
{ "The Orcish Mines", "Orc" },
{ "The Hive", "Hive" },
{ "The Lair", "Lair" },
{ "The Slime Pits", "Slime" },
{ "The Vaults", "Vault" },
{ "The Crypt", "Crypt" },
{ "The Hall of Blades", "Blade" },
{ "The Hall of Zot", "Zot" },
{ "The Ecumenical Temple", "Temple" },
{ "The Snake Pit", "Snake" },
{ "The Elven Halls", "Elf" },
{ "The Tomb", "Tomb" },
{ "The Swamp", "Swamp" },
{ "The Caverns", "Cav" }
};
return names[branch][terse];
else
{
switch (branch)
{
case BRANCH_VESTIBULE_OF_HELL:
return ( long_name ? "The Vestibule of Hell" : "Hell" );
case BRANCH_HALL_OF_BLADES:
return ( long_name ? "The Hall of Blades" : "Blade" );
case BRANCH_ECUMENICAL_TEMPLE:
return ( long_name ? "The Ecumenical Temple" : "Temple" );
case BRANCH_DIS:
result = ( long_name ? "The Iron City of Dis" : "Dis");
break;
case BRANCH_GEHENNA:
result = ( long_name ? "Gehenna" : "Geh" );
break;
case BRANCH_COCYTUS:
result = ( long_name ? "Cocytus" : "Coc" );
break;
case BRANCH_TARTARUS:
result = ( long_name ? "Tartarus" : "Tar" );
break;
case BRANCH_ORCISH_MINES:
result = ( long_name ? "The Orcish Mines" : "Orc" );
break;
case BRANCH_HIVE:
result = ( long_name ? "The Hive" : "Hive" );
break;
case BRANCH_LAIR:
result = ( long_name ? "The Lair" : "Lair" );
break;
case BRANCH_SLIME_PITS:
result = ( long_name ? "The Slime Pits" : "Slime" );
break;
case BRANCH_VAULTS:
result = ( long_name ? "The Vaults" : "Vault" );
break;
case BRANCH_CRYPT:
result = ( long_name ? "The Crypt" : "Crypt" );
break;
case BRANCH_HALL_OF_ZOT:
result = ( long_name ? "The Hall of Zot" : "Zot" );
break;
case BRANCH_SNAKE_PIT:
result = ( long_name ? "The Snake Pit" : "Snake" );
break;
case BRANCH_ELVEN_HALLS:
result = ( long_name ? "The Elven Halls" : "Elf" );
break;
case BRANCH_TOMB:
result = ( long_name ? "The Tomb" : "Tomb" );
break;
case BRANCH_SWAMP:
result = ( long_name ? "The Swamp" : "Swamp" );
break;
default:
result = ( long_name ? "The Dungeon" : "D" );
break;
}
}
result = branch_name(branch, !long_name);
}
}
formatted_scroller::formatted_scroller(int _flags, const std::string& s) :
Menu(_flags)
{
size_t eolpos = 0;
while ( true )
{
const size_t newpos = s.find( EOL, eolpos );
add_entry(new MenuEntry(std::string(s, eolpos, newpos-eolpos)));
if ( newpos == std::string::npos )
break;
else
eolpos = newpos + strlen(EOL);
int linebreak_string( std::string& s, int wrapcol, int maxcol )
{
size_t loc = 0;
int xpos = 0;
int breakcount = 0;
while ( loc < s.size() )
{
if ( s[loc] == '<' ) // tag
{
// << escape
if ( loc + 1 < s.size() && s[loc+1] == '<' )
{
++xpos;
loc += 2;
// Um, we never break on <<. That's a feature. Right.
continue;
}
// skip tag
while ( loc < s.size() && s[loc] != '>' )
++loc;
++loc;
}
else
{
// user-forced newline
if ( s[loc] == '\n' )
xpos = 0;
// soft linebreak
else if ( s[loc] == ' ' && xpos > wrapcol )
{
s.replace(loc, 1, EOL);
xpos = 0;
++breakcount;
}
// hard linebreak
else if ( xpos > maxcol )
{
s.insert(loc, EOL);
xpos = 0;
++breakcount;
}
// bog-standard
else
++xpos;
++loc;
}
}
return breakcount;
}
// 0.0 initial genesis of saved format
// 0.1 added attitude tag
// 0.2 replaced old 'enchantment1' and with 'flags' (bitfield)
// 0.3 changes to make the item structure more sane
// 0.4 changes to the ghost save section
// 0.5 spell and ability letter arrays
// 0.6 inventory slots of items
// 0.7 origin tracking for items
// 0.8 widened env.map to 2 bytes
// 0.9 inscriptions (hp)
// 0.10 Monster colour and spells separated from mons->number.
// 0.11 env colours moved into env.mapcol
write_tagged_file( saveFile, SAVE_MAJOR_VERSION, 11, TAGTYPE_LEVEL );
write_tagged_file( saveFile, SAVE_MAJOR_VERSION, 0, TAGTYPE_LEVEL );
// 0.0 initial genesis of saved format
// 0.1 changes to make the item structure more sane
// 0.2 spell and ability tables
// 0.3 added you.magic_contamination (05/03/05)
// 0.4 added item origins
// 0.5 added num_gifts
// 0.6 inscriptions
write_tagged_file( charf, SAVE_MAJOR_VERSION, 6, TAGTYPE_PLAYER );
write_tagged_file( charf, SAVE_MAJOR_VERSION, 0, TAGTYPE_PLAYER );
/* There is now a distinction between keycodes and commands.
A keycode_type gets mapped through keycode_to_command to
become a command_type.
So a keycode_type could be something like 'H';
a command_type would be something like COMMAND_RUN_LEFT.
*/
This function handles the player's input. It's called from main(), from
inside an endless loop.
It's now undergone major refactoring. The code path is now:
1. Get next player input item (key)
2. Translate key to command
3. Execute the command
4. Update rest of world if necessary
This function handles the player's input. It's called from main(), from
inside an endless loop.