Menu

language.rb

Ray Chason

This information is preliminary and may change at any time without notice.

language.rb contains the locale-specific formatting code.

language.rb must create a class called NHLanguage, which must inherit NHLangBase, and define entry points called as below. NHLanguage may define other methods or variables, but they must not begin with NH or nh to avoid conflicts with future releases.

:::ruby
class NHLanguage < NHLangBase
    # nh_begin_format is called at the beginning of any formatting operation,
    # so that language scripts that wish to maintain state may clear such state
    # when a formatting operation begins.
    #
    # nh_begin_format may be omitted; the default action is to do nothing.

    def nh_begin_format
        # return value is ignored
    end

    # nh_format_parameter is called for any format specifier whose type
    # specification is "s" or a string enclosed in curly braces.
    #
    # spec is nil if the type specification is "s", or a String if the type
    # specification is a string enclosed in curly braces; it does not include
    # the curly braces.
    #
    # arg is the parameter from the parameter list that the format specifier
    # primarily refers to.  Its type may be Integer, String, Array,
    # NHGameState, NHMonster or NHObject.
    #
    # arglist is the list of all parameters including parameter 0.  This is
    # provided so that spec can reference more than one parameter:  "%3${ng2}"
    # might mean "parameter 3 is an adjective and needs to agree with the
    # gender and number of parameter 2".

    def nh_format_parameter(spec, arg, arglist)
        # return value is a string to be substituted for a format specifier
    end

    # nh_join is called when a new string is to be joined to the existing
    # output.  Its purpose is to implement such rules as mandatory contractions
    # and words (such as English "a"/"an") that change form according to what
    # occurs before or after them.
    #
    # nh_join may be omitted; the default action is to return the concatenation
    # of str1 and str2 without modification.

    def nh_join(str1, str2)
        # return value is a string resulting from the concatenation of str1 and
        # str2, with any modifications according to the rules of the language
    end

    # nh_end_format is called at the end of a formatting operation.  Its
    # purpose is to give the language script a last pass at the final output
    # of the formatting.
    #
    # nh_end_format may be omitted; the default action is to return str
    # unchanged.

    def nh_end_format(str)
        # return value is str with any desired transformations; this will be
        # the final formatting output
    end

    # nh_read_object is called when the user has made a wish.  str is the
    # user's input.  This function should not attempt to enforce the rules
    # limiting non-wizard-mode wishes; such limits remain in the C code.

    def nh_read_object(str)
        # return value is nil or an object of type NHWish
    end

    # nh_read_monster is called to read a monster type.  str is the user's
    # input.  It is used for non-blessed genocide and in wizard mode to create
    # monsters.

    def nh_read_monster(str)
        # return value is an object of type NHReadMonster
    end

    # nh_artifact_match matches the user-supplied name (name1) with the
    # translated name of an artifact (name2).  The match is case-insensitive if
    # ignore_case is true.
    #
    # The match should take normalization forms into account.
    #
    # nh_artifact_match may be omitted; the default action is to compare name1
    # and name2 in their entirety.  This is provided so that language scripts
    # can omit such things as articles from the match.

    def nh_artifact_match(name1, name2, ignore_case)
        # return value is true if the names match, else false
    end

    # nh_capitalize_words returns the string (str) with each word capitalized.
    #
    # nh_capitalize_words may be omitted; the default action is to capitalize
    # each word according to default Unicode rules.  Language scripts may
    # override this if the language has special capitalization rules.
    def nh_capitalize_words(str)
        # return value is the capitalized string
    end

    # nh_data_match converts a string (str) to an Array of strings that may be
    # matched to a pattern in the data file.
    #
    # nh_data_match may be omitted; the default value is to return str only,
    # with whitespace reduced to single spaces, leading and trailing whitespace
    # removed and the rest converted to normalization form C.  Language scripts
    # may use this to convert possible plurals to singulars or other such
    # variant forms.
    def nh_data_match(str)
        # return value is an Array of strings to be matched against the data
        # file
    end
end

language.rb benefits from declarations in langbase.rb and nhconst.rb, and from declarations in pline2.c and uniruby.c, which provide services as described below.

The Unicode class provides a means of looking up various character properties, as defined by the Unicode standard:

:::ruby
class Unicode
    def Unicode.cbyte?(num)
        # true if num is a UTF-8 continuation byte
    end
    def Unicode.surrogate?(num)
        # true if num is a UTF-16 surrogate
    end
    def Unicode.leading_surrogate?(num)
        # true if num is a UTF-16 leading surrogate
    end
    def Unicode.trailing_surrogate?(num)
        # true if num is a UTF-16 trailing surrogate
    end
    def Unicode.valid?(num)
        # true if num is a valid Unicode code point and not a surrogate
    end
    def Unicode.combining_class(num)
        # return value is an Integer, the canonical combining class of the code
        # point num
    end
    def Unicode.ea_width(num)
        # return value is a String, the East Asian width of the code point num
    end
    def Unicode.general_category(num)
        # return value is a String, the general category of the code point num
    end
    def Unicode.composition(num1, num2)
        # return value is an Integer, the code point that composes num1 and num2,
        # or nil if there is no composition
    end
    def Unicode.decomposition(num, compat)
        # return value is a String in the UTF-8 encoding, the decomposition of
        # the code point num; this is a compatibility decomposition if compat is
        # true, or a canonical decomposition if false
    end
    def Unicode.decimal_value(num)
        # return value is an Integer, the decimal value of the code point num, or
        # nil if it has no decimal value
    end
    def Unicode.downcase(num)
        # return value is a String in the UTF-8 encoding, the lowercase mapping of
        # the code point num.
    end
    def Unicode.capitalize(num)
        # return value is a String in the UTF-8 encoding, the titlecase mapping of
        # the code point num.
    end
    def Unicode.upcase(num)
        # return value is a String in the UTF-8 encoding, the uppercase mapping of
        # the code point num.
    end
    def Unicode.casefold(num)
        # return value is a String in the UTF-8 encoding, the casefold mapping of
        # the code point num; this is different from downcase
    end
    def Unicode.width(num)
        # return value is an Integer, an approximation of the width of the code
        # point num as displayed on a terminal window; this may be 0, 1 or 2
    end
end

The built-in String class is augmented for better Unicode support.

The case mappings implemented here are the defaults, with one-to-many mappings such as ß to SS fully supported. Final lowercase sigma is taken into account. Some languages have special capitalization rules; two examples are Turkish i -> İ and ı -> I, and the Dutch IJ digraph. For such languages, language.rb will need to take these rules into account.

downcase!, upcase! and capitalize! are not redefined, and no casefold! or normalize! methods are provided. These may be provided in a future release.

:::ruby
class String
    def downcase
        # return value is a String, the original string in lowercase
    end
    def capitalize
        # return value is a String:  the first character is titlecased and the
        # rest is converted to lowercase
    end
    def upcase
        # return value is a String, the original string in uppercase
    end
    def casefold
        # return value is a String, the original string casefolded
        # note that this is not the same as downcase
    end
    def normalize(form)
        # form is a String:  "NFC", "NFD", "NFKC" or "NFKD"
        # return value is a String, the original string normalized
    end
    def width
        # return value is an Integer, the approximate width of the string on a
        # terminal
    end
end

The built-in Array class is augmented so that to_i returns the number of elements; this will facilitate its use for forming plurals.

The NHLangBase class provides constants corresponding to those defined in pm.h and oname.h (generated by makedefs); these have the form NH_ plus the name in C, so that NHLangBase::NH_PM_BLACK_DRAGON has the same value as PM_BLACK_DRAGON in C.

The NHLangBase class also provides these methods:

:::ruby
class NHLangBase
    def NHLangBase.nh_split_words(str1, str2)
        # return value is an array of five strings:
        # prefix, word1, infix, word2, suffix
        # prefix is the part of str1 before the last word.
        # word1 is the last word in str1.
        # infix is the part of str1 after the last word, plus the part of str2
        #     before the first word.
        # word2 is the first word in str2.
        # suffix is the part of str2 after the first word.
    end
    def nh_obj_called(num)
        # return value is a String, the user-provided name by which object num is
        # called, or nil if no such name is defined
    end
    def nh_obj_name(num)
        # return value is a String, the translated real name of object num, or
        # nil if num is out of range
    end
    def nh_obj_descr(num)
        # return value is a String, the translated unidentified description of
        # object num, or nil if no such description
    end
    def nh_obj_class(oclass)
        # oclass is a String with one character, the map symbol for an object
        # class, or nil
        # return value is a Range, giving the first and last indexes of the
        # requested class, or 1...NUM_OBJECTS (all objects) if oclass is nil
    end
    def nh_mon_name(num)
        # return value is a String, the translated name of monster num, or nil if
        # num is out of range
    end
    def nh_title_to_mon(title)
        # return value is a two-element Array, containing the translated monster
        # name corresponding to the title and the name's length, or [nil, nil] if
        # no such monster
    end
    def nh_Japanese_items
        # return value is an Enumerable of two-element Arrays, each bearing a
        # Japanese item name (a String) and its object index (an Integer)
    end
    def nh_fruits
        # return value is an Enumerable of two-element Arrays, each bearing a
        # fruit name (a String) and its fruit ID number (an Integer)
    end
    def nh_artifact_name(name)
        # return value is an Array of two elements, the full name of an artifact
        # and its object index, or [nil, nil]
    end
end

The second parameter of nh_format_parameter may be any of Integer, String, Array, NHGameState, NHMonster or NHObject; any Array will contain only these six types (presently an Array contains only String or NHMonster). The third parameter of nh_format_parameter is an Array containing any of these six types. NHGameState occurs in element 0 and no other, and the rest contain the explicit parameters to the format function in the order that they were specified.

NHGameState presents this interface; the read-only attributes are set in the function game_state in src/pline2.c. The language script may add more methods or variables, but they must not begin with nh or NH to avoid conflict with future releases.

:::ruby
class NHGameState
    attr_reader :nh_gameover    # True if game has ended
    attr_reader :nh_hallu       # True if hallucinating
    attr_reader :nh_uswallow    # True if swallowed
    attr_reader :nh_blind       # True if blind
    attr_reader :nh_in_endgame  # True if in endgame
    attr_reader :nh_poly_gender # 0 if the hero is male, 1 if female, 2 if neuter
    attr_reader :nh_female      # True if the hero is female
    attr_reader :nh_humanoid    # True if the hero is humanoid in form
    attr_reader :nh_neuter      # True if the hero is neuter
    attr_reader :nh_role_en     # Untranslated male name of role
    attr_reader :nh_hand        # Translated string for the hand of the hero's
                                # current form
    attr_reader :nh_mrg_to_wielded # True if weapon picked is merged with wielded
                                   # one
    attr_reader :nh_twoweap     # True if wielding two weapons

    # For the benefit of pluralization routines
    def to_i
        1
    end
end

NHMonster presents this interface; the read-only attributes are set in the function P_m in src/pline2.c. The language script may add more methods or variables, but they must not begin with nh or NH to avoid conflict with future releases.

:::ruby
class NHMonster
    attr_reader :nh_name       # Personal name of monster (empty if none)
    attr_reader :nh_mtame      # True if monster is tame
    attr_reader :nh_minvis     # True if monster is invisible
    attr_reader :nh_canspotmon # True if monster can be seen
    attr_reader :nh_usteed     # True if monster is being ridden
    attr_reader :nh_ustuck     # True if monster is holding you
    attr_reader :nh_ispriest   # True if monster is a priest
    attr_reader :nh_isminion   # True if monster is a minion
    attr_reader :nh_mname_en   # Untranslated description of monster from monst.c
    attr_reader :nh_hname      # Random monster name if hallucinating, else same
                               # as mname
    attr_reader :nh_mname      # Translated description of monster from monst.c
    attr_reader :nh_renegade   # True if monster is renegade
    attr_reader :nh_female     # True if monster is female
    attr_reader :nh_humanoid   # True if monster is humanoid in form
    attr_reader :nh_neuter     # True if monster is neuter
    attr_reader :nh_hgname     # Random god name if hallucinating, else same as
                               # gname
    attr_reader :nh_gname      # Name of monster's actual god
    attr_reader :nh_isshk      # True if monster is a shopkeeper
    attr_reader :nh_saddle     # True if monster is wearing a saddle
    attr_reader :nh_pname      # True if monster's name is a proper name
    attr_reader :nh_mplayer    # True if monster is a player-monster
    attr_reader :nh_rank       # Rank of monster if a player-monster, else empty
    attr_reader :nh_unique     # True if monster is unique
    attr_reader :nh_pgender    # 0 for male, 1 for female, 2 for neuter
    attr_reader :nh_no_priest_name # True if allegiance of high priest should be
                               # concealed

    # For the benefit of pluralization routines
    def to_i
        1
    end
end

NHObject presents this interface; the read-only attributes are set in the functions P_oq and P_ot in src/pline2.c. The language script may add more methods or variables, but they must not begin with nh or NH to avoid conflict with future releases.

:::ruby
class NHObject
    attr_reader :nh_quan           # Number of items in this stack
    attr_reader :nh_otyp           # untranslated object name
    attr_reader :nh_oc_name_known  # true if user knows the real name
    attr_reader :nh_actualn        # translated object name
    attr_reader :nh_dn             # translated object description
    attr_reader :nh_oc_uname       # name assigned by user
    attr_reader :nh_jap_name       # Japanese item name
    attr_reader :nh_pname          # true if object name is a proper name
    attr_reader :nh_oname          # name of individual object
    attr_reader :nh_oclass         # on-screen symbol for object class
    attr_reader :nh_dknown         # true if description known
    attr_reader :nh_known          # true if identified
    attr_reader :nh_opoisoned      # true if poisoned
    attr_reader :nh_mname          # translated name of associated monster
    attr_reader :nh_vegetarian     # true if the object is vegetarian
    attr_reader :nh_m_pname        # true if the associated monster has a proper
                                   # name
    attr_reader :nh_m_unique       # true if the associated monster is unique
    attr_reader :nh_knows_egg      # true if the hero knows this type of egg
    attr_reader :nh_boots          # true if the object is a pair of boots
    attr_reader :nh_gloves         # true if the object is a pair of gloves
    attr_reader :nh_cloak          # true if the object is a cloak
    attr_reader :nh_helmet         # true if the object is a helmet
    attr_reader :nh_shield         # true if the object is a shield
    attr_reader :nh_suit           # true if the object is a suit of armor
    attr_reader :nh_fname          # name of object if it is a fruit, or nil
    attr_reader :nh_spe            # "special" number for object
    attr_reader :nh_historic       # true if the object is a historic statue
    attr_reader :nh_owt            # actual weight of object
    attr_reader :nh_oc_weight      # weight according to object class
    attr_reader :nh_odiluted       # true if the object is a diluted potion
    attr_reader :nh_bknown         # true if the b/u/c status is known
    attr_reader :nh_rknown         # true if the object is known to be rustproof
                                   # etc.
    attr_reader :nh_oerodeproof    # true if the object is rustproof etc.
    attr_reader :nh_blessed        # true if the object is blessed
    attr_reader :nh_cursed         # true if the object is cursed
    attr_reader :nh_oc_magic       # true if the object is a magical item
    attr_reader :nh_costly         # true if the object belongs to a shopkeeper
    attr_reader :nh_shopkeeper     # shopkeeper claiming this object, or nil
    attr_reader :nh_ocarry         # monster (NHMonster) carrying this object, or
                                   # nil
    attr_reader :nh_carried        # true if hero is carrying the object
    attr_reader :nh_oinvis         # true if the object is invisible
    attr_reader :nh_oc_charged     # true if the object is chargeable
    attr_reader :nh_greased        # true if the object is greased
    attr_reader :nh_w_armor        # true if the object is worn as armor
    attr_reader :nh_w_wep          # true if the object is the wielded weapon
    attr_reader :nh_w_quiver       # true if the object is in the quiver
    attr_reader :nh_w_swapwep      # true if the object is the secondary weapon
    attr_reader :nh_w_amul         # true if the object is worn as an amulet
    attr_reader :nh_w_ringl        # true if the object is the left ring
    attr_reader :nh_w_ringr        # true if the object is the right ring
    attr_reader :nh_w_tool         # true if the object is worn as eyewear
    attr_reader :nh_w_saddle       # true if the object is a worn saddle
    attr_reader :nh_w_ball         # true if the object is a punishment ball
    attr_reader :nh_w_chain        # true if the object is a punishment chain
    attr_reader :nh_fixed          # true if the object is a fixed crysknife
    attr_reader :nh_oeroded        # degree of rust or fire damage
    attr_reader :nh_oeroded2       # degree of corrosion or rotting damage
    attr_reader :nh_rustprone      # true if the object can be rusted
    attr_reader :nh_flammable      # true if the object can be burnt
    attr_reader :nh_corrodeable    # true if the object can be corroded
    attr_reader :nh_rottable       # true if the object can be rottd
    attr_reader :nh_unpaid         # true if the object is unpaid
    attr_reader :nh_quotedprice    # quoted price of the object
    attr_reader :nh_age            # obj->age; for candles, this is how long it
                                   # will burn
    attr_reader :nh_bimanual       # true if the object is a two-handed weapon
    attr_reader :nh_lamplit        # true if the object is lit
    attr_reader :nh_leashmon       # monster ID of attached pet, or nil
    attr_reader :nh_oc_cost        # base cost of object
    attr_reader :nh_oeaten         # nutrition left in food, if partly eaten, or
                                   # nil
    attr_reader :nh_recharged      # number of times the object has been recharged
    attr_reader :nh_stale_egg      # true if the object is a stale egg
    attr_reader :nh_uskin          # true if the object is armor embedded in your
                                   # skin
    attr_reader :nh_weptool        # true if the object is a weapon-tool
    attr_reader :nh_oc_unique      # true if the object is unique

    # For the benefit of pluralization routines
    def to_i
        @nh_quan
    end

    def nh_w_ring
        @nh_w_ringl || @nh_w_ringr
    end
end

The method nh_read_monster returns an object of class NHReadMonster, which presents the following interface. The language script may add more methods or variables, but they must not begin with nh or NH to avoid conflict with future releases.

:::ruby
# Class returning the monster that the user typed in
class NHReadMonster
    attr_accessor :nh_name         # string
    attr_accessor :nh_tame         # Boolean
    attr_accessor :nh_peaceful     # Boolean
    attr_accessor :nh_hostile      # Boolean
end

The method nh_read_object returns an object of class NHWish (or nil), which presents the following interface. The language script may add more methods or variables, but they must not begin with nh or NH to avoid conflict with future releases.

~~~~~~
:::ruby
class NHWish
attr_accessor :nh_cnt # integer
attr_accessor :nh_spe # integer
attr_accessor :nh_spesgn # -1, 0, +1
attr_accessor :nh_typ # integer giving object type or range of
# object types
attr_accessor :nh_very # integer: 0, 1 (very), 2 (thoroughly)
attr_accessor :nh_rechrg # integer
attr_accessor :nh_blessed # Boolean
attr_accessor :nh_uncursed # Boolean
attr_accessor :nh_iscursed # Boolean
attr_accessor :nh_ispoisoned # Boolean
attr_accessor :nh_isgreased # Boolean
attr_accessor :nh_eroded # integer
attr_accessor :nh_eroded2 # integer
attr_accessor :nh_erodeproof # Boolean
attr_accessor :nh_isinvisible # Boolean
attr_accessor :nh_halfeaten # Boolean
attr_accessor :nh_mntmp # integer giving monster, or nil
attr_accessor :nh_contents # nil, :empty, :spinach
attr_accessor :nh_islit # Boolean
attr_accessor :nh_ishistoric # Boolean
attr_accessor :nh_isdiluted # Boolean
attr_accessor :nh_ftype # integer giving fruit type, or 0
attr_accessor :nh_oclass # string giving object class, or nil
attr_accessor :nh_name # string giving name, or nil
end


Related

Wiki: Information for Developers
Wiki: messages.po
Wiki: quest.txt

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.