summaryrefslogblamecommitdiffstats
path: root/crawl-ref/source/place.cc
blob: 03fffbd3705180bb50094f857bcde6559e2091d4 (plain) (tree)
1
2
3
4
5
6
7
8
9



                                        

   

                   
                    

                   

                   




















                                                                






                                                           




                                                                  
 

                                                                                
 




                                 


                                                                                



                                              

                                                




















                                                                 



                                                                               
                                        
                                                  
             








                                                                                   




                                                               







                                                                       
                                                      
     
                      
         
                                 

                                          

                                                   

                     
                                                                
            
                                                          


















                                                                       

                                                      









                                                        
                                                                         



                                                                    
                                             



























                                                                        




                                                                




                                                            












                                                           
/*
 *  File:       place.cc
 *  Summary:    Place related functions.
 *  Written by: Linley Henzell
 */

#include "AppHdr.h"

#include "externs.h"

#include "branch.h"
#include "place.h"
#include "player.h"
#include "travel.h"

// Do not attempt to use level_id if level_type != LEVEL_DUNGEON
std::string short_place_name(level_id id)
{
    return id.describe();
}

int place_branch(unsigned short place)
{
    const unsigned branch = (unsigned) ((place >> 8) & 0xFF);
    const int lev = place & 0xFF;
    return lev == 0xFF? -1 : (int) branch;
}

int place_depth(unsigned short place)
{
    const int lev = place & 0xFF;
    return lev == 0xFF? -1 : lev;
}

int place_type(unsigned short place)
{
    const unsigned type = (unsigned) ((place >> 8) & 0xFF);
    const int lev = place & 0xFF;
    return lev == 0xFF? (int) type : (int) LEVEL_DUNGEON;
}

unsigned short get_packed_place( branch_type branch, int subdepth,
                                 level_area_type level_type )
{
    unsigned short place = (unsigned short)
        ( (static_cast<int>(branch) << 8) | (subdepth & 0xFF) );

    if (level_type != LEVEL_DUNGEON)
        place = (unsigned short) ( (static_cast<int>(level_type) << 8) | 0xFF );

    return place;
}

unsigned short get_packed_place()
{
    return get_packed_place(you.where_are_you,
                            subdungeon_depth(you.where_are_you, you.your_level),
                            you.level_type);
}

bool single_level_branch( branch_type branch )
{
    return (branch >= 0 && branch < NUM_BRANCHES
            && branches[branch].depth == 1);
}

std::string place_name( unsigned short place, bool long_name,
                        bool include_number )
{

    unsigned char branch = (unsigned char) ((place >> 8) & 0xFF);
    int lev = place & 0xFF;

    std::string result;
    if (lev == 0xFF)
    {
        switch (branch)
        {
        case LEVEL_ABYSS:
            return ( long_name ? "The Abyss" : "Abyss" );
        case LEVEL_PANDEMONIUM:
            return ( long_name ? "Pandemonium" : "Pan" );
        case LEVEL_LABYRINTH:
            return ( long_name ? "a Labyrinth" : "Lab" );
        case LEVEL_PORTAL_VAULT:
            // XXX: This was originally in misc.cc:new_level. It really makes
            // no sense for it to be there, as there are instances where portal
            // vaults can use origin elsewhere (death messages, etc), and Note
            // ::describe calls this anyway. (due)
            if (branch == you.level_type
                && !you.level_type_origin.empty())
            {
                std::string desc;

                size_t space = you.level_type_origin.find(" ");
                if (space == std::string::npos)
                    desc += you.level_type_origin;
                else
                    desc += you.level_type_origin.substr(space + 1);

                return long_name ? desc : upcase_first(you.level_type_name_abbrev);
            }
            else
            {
                return long_name ? "a Portal Chamber" : "Port";
            }
        default:
            return ( long_name ? "Buggy Badlands" : "Bug" );
        }
    }

    result = (long_name ?
              branches[branch].longname : branches[branch].abbrevname);

    if (include_number && branches[branch].depth != 1)
    {
        if (long_name)
        {
            // decapitalise 'the'
            if ( result.find("The") == 0 )
                result[0] = 't';
            result = make_stringf("Level %d of %s",
                      lev, result.c_str());
        }
        else if (lev)
            result = make_stringf("%s:%d", result.c_str(), lev);
        else
            result = make_stringf("%s:$", result.c_str());
    }
    return result;
}

// Takes a packed 'place' and returns a compact stringified place name.
// XXX: This is done in several other places; a unified function to
//      describe places would be nice.
std::string short_place_name(unsigned short place)
{
    return place_name( place, false, true );
}

// Prepositional form of branch level name.  For example, "in the
// Abyss" or "on level 3 of the Main Dungeon".
std::string prep_branch_level_name(unsigned short packed_place)
{
    std::string place = place_name( packed_place, true, true );
    if (place.length() && place != "Pandemonium")
        place[0] = tolower(place[0]);
    return (place.find("level") == 0 ? "on " + place
                                     : "in " + place);
}

// Use current branch and depth
std::string prep_branch_level_name()
{
    return prep_branch_level_name( get_packed_place() );
}

int absdungeon_depth(branch_type branch, int subdepth)
{
    if (branch >= BRANCH_VESTIBULE_OF_HELL && branch <= BRANCH_LAST_HELL)
        return subdepth + 27 - (branch == BRANCH_VESTIBULE_OF_HELL);
    else
    {
        --subdepth;
        while (branch != BRANCH_MAIN_DUNGEON)
        {
            subdepth += branches[branch].startdepth;
            branch = branches[branch].parent_branch;
        }
    }
    return subdepth;
}

int subdungeon_depth(branch_type branch, int depth)
{
    return depth - absdungeon_depth(branch, 0);
}

int player_branch_depth()
{
    return subdungeon_depth(you.where_are_you, you.your_level);
}

// Returns true if exits from this type of level involve going upstairs.
bool level_type_exits_up(level_area_type type)
{
    return (type == LEVEL_LABYRINTH || type == LEVEL_PORTAL_VAULT);
}

bool level_type_exits_down(level_area_type type)
{
    return (type == LEVEL_PANDEMONIUM || type == LEVEL_ABYSS);
}

bool level_type_allows_followers(level_area_type type)
{
    return (type == LEVEL_DUNGEON || type == LEVEL_PANDEMONIUM);
}

bool level_type_is_stash_trackable(level_area_type type)
{
    return (type != LEVEL_ABYSS && type != LEVEL_LABYRINTH);
}

std::vector<level_id> all_dungeon_ids()
{
    std::vector<level_id> out;
    for (int i = 0; i < NUM_BRANCHES; i++)
    {
        const Branch &branch = branches[i];

        for (int depth = 1; depth <= branch.depth; depth++)
            out.push_back(level_id(branch.id, depth));
    }
    return (out);
}