Changeset 284

Show
Ignore:
Timestamp:
09/21/08 14:29:30 (2 months ago)
Author:
ged
Message:

Checkpointing after upgrading to a new build system

Location:
trunk
Files:
5 added
6 removed
8 modified

Legend:

Unmodified
Added
Removed
  • trunk

    • Property svn:ignore
      •  

        old new  
         1coverage.info 
        12test.log 
        23.glimpse* 
    • Property svn:externals set to
  • trunk/lib/fm/gameobject.rb

    r277 r284  
    2424require 'digest/md5' 
    2525require 'logger' 
    26 require 'sync' 
     26require 'monitor' 
    2727 
    2828require 'fm' 
     
    3939        FaerieMUD::HTML, 
    4040        FaerieMUD::Linguistics 
     41 
     42    include MonitorMixin 
    4143 
    4244    ### Class constants 
  • trunk/lib/fm/locus.rb

    r277 r284  
    9898# 
    9999 
    100 require 'sync' 
     100require 'monitor' 
    101101 
    102102require 'fm/entity' 
     
    151151    ### contents of the receiver. 
    152152    def add_contents( *objects ) 
    153         @mutex.synchronize( Sync::SH ) do 
     153        synchronize do 
    154154            objects.each do |obj| 
    155155                if obj.contains?( self ) 
  • trunk/lib/fm/mixins.rb

    r280 r284  
    11#!/usr/bin/ruby 
    2 #  
    3 # This file contains various mixins for use in FaerieMUD classes. 
    4 # 
    5 # Currently contains the following modules: 
    6 # 
    7 # [<tt>FaerieMUD::ArgCheckFunctions</tt>] 
    8 #   Functions for checking arguments for types, signatures, and hash members. 
    9 #  
     2 
     3require 'monitor' 
     4 
     5require 'fm/exceptions' 
     6 
    107# [<tt>FaerieMUD::Propertied</tt>] 
    118#   Adds the ability to interact with FaerieMUD::Property objects to including 
     
    5148# Please see the file COPYRIGHT in the 'docs' directory for licensing details. 
    5249# 
    53  
    54 require 'cgi' 
    55 require 'sync' 
    56  
    57 require 'fm/exceptions' 
    58  
    5950module FaerieMUD 
    60  
    61     ### Mixin that adds some type-checking functions to the current scope 
    62     module ArgCheckFunctions 
    63  
    64         ### The Ouroboros Trick 
    65         def self::included( klass ) 
    66             super 
    67             klass.extend( self ) 
    68         end 
    69  
    70  
    71         ############### 
    72         module_function 
    73         ############### 
    74  
    75         ### Check <tt>anObject</tt> to make sure it's one of the specified 
    76         ### <tt>validTypes</tt>. If the object is not one of the specified value 
    77         ### types, and an optional block is given it is called with the object being 
    78         ### tested and the array of valid types. If no handler block is given, a 
    79         ### <tt>TypeError</tt> is raised. 
    80         def check_type( anObject, *validTypes ) # :yields: object, *validTypes 
    81             warn "Deprecated method 'check_type' called from %s" % 
    82                 [ caller(1).first ] if $VERBOSE 
    83             return true 
    84         end 
    85  
    86  
    87         ### Check each object in the specified <tt>objectArray</tt> with a call 
    88         ### to #check_type with the specified validTypes array. 
    89         def check_each_type( objectArray, *validTypes, &errBlock ) # :yields: object, *validTypes 
    90             warn "Deprecated method 'check_each_type' called from %s" % 
    91                 [ caller(1).first ] if $VERBOSE 
    92             return true 
    93         end 
    94  
    95  
    96         ### Check <tt>anObject</tt> for implementations of <tt>requiredMethods</tt>. 
    97         ### If one of the methods is unimplemented, and an optional block is given it 
    98         ### is called with the method that failed the responds_to? test and the object 
    99         ### being checked. If no handler block is given, a <tt>TypeError</tt> is 
    100         ### raised. 
    101         def check_response( anObject, *requiredMethods ) # yields method, anObject 
    102             requiredMethods.flatten! 
    103             requiredMethods.compact! 
    104  
    105             if requiredMethods.size > 0 then 
    106                 requiredMethods.each do |method| 
    107                     next if anObject.respond_to?( method ) 
    108  
    109                     if block_given? then 
    110                         yield( method, anObject ) 
    111                     else 
    112                         raise TypeError, "Argument '#{anObject.inspect}' does "\ 
    113                             "not answer the '#{method}()' method", 
    114                             caller(1).find_all {|frame| frame.include?(__FILE__)} 
    115                     end 
    116                 end 
    117             end 
    118  
    119             return true 
    120         end 
    121  
    122  
    123         ### Check each object of <tt>anArray</tt> for implementations of 
    124         ### <tt>requiredMethods</tt>, calling the optional <tt>errBlock</tt> if 
    125         ### specified, or raising a <tt>TypeError</tt> if one of the methods is 
    126         ### unimplemented. 
    127         def check_each_response( anArray, *requiredMethods, &errBlock ) # :yeilds: method, object 
    128             raise ScriptError, 
    129                 "First argument must be Enumerable" unless 
    130                 anArray.is_a?( Enumerable ) 
    131  
    132             anArray.each do |anObject| 
    133                 if block_given? then 
    134                     check_response anObject, *requiredMethods, &errBlock 
    135                 else 
    136                     check_response( anObject, *requiredMethods ) {|method, object| 
    137                         raise TypeError, "Argument '#{anObject.inspect}' does "\ 
    138                             "not answer the '#{method}()' method", 
    139                             caller(1).find_all {|frame| frame.include?(__FILE__)} 
    140                     } 
    141                 end 
    142             end 
    143  
    144             return true 
    145         end 
    146  
    147  
    148         ### Check to be sure the specified +args+ object is a Hash and contains 
    149         ### the given +keys+. Each key in +keys+ can be either a Symbol, a 
    150         ### String, or an Array of either. 
    151         def check_for_hash_args( args, *keys ) 
    152             unless args.is_a?( Hash ) 
    153                 raise TypeError,  
    154                     "Arguments are not in Hash form.", 
    155                     caller(1).find_all {|frame| /#{__FILE__}/ !~ frame} 
    156             end 
    157  
    158             unless keys.empty? 
    159                 nicetrace = caller( 1 ).delete_if {|frame| 
    160                     /#{__FILE__}:\d+:in/i =~ frame 
    161                 } 
    162                 keys.each {|required| 
    163                     case required 
    164                     when Symbol 
    165                         raise ArgumentError, 
    166                             "Missing required argument :#{required}", 
    167                             nicetrace unless 
    168                             args.key?( required ) 
    169                     when String 
    170                         raise ArgumentError, 
    171                             "Missing required argument :#{required}", 
    172                             nicetrace unless 
    173                             args.key?( required.intern ) 
    174                     when Array 
    175                         raise ArgumentError, 
    176                             "Missing required argument :#{requiredKey}", 
    177                             nicetrace unless 
    178                             required. 
    179                             collect {|ak| ak.to_s.intern }. 
    180                             find {|ak| args.keys.include?(ak) } 
    181                     end 
    182  
    183                 } 
    184             end 
    185  
    186             return true 
    187         end 
    188  
    189     end # module ArgCheckFunctions 
    190  
    19151 
    19252    ### A mixin that adds logging to its including class. 
     
    648508        ### constructor private. 
    649509        def self::extend_object( obj ) 
    650             unless obj.is_a?( Class ) 
    651                 raise TypeError, 
    652                     "Can only extend Classes, not a #{obj.class.name}" 
    653             end 
    654             super 
     510            obj.extend( MonitorMixin ) 
    655511        end 
    656512 
     
    716572            attr_locked( sym, true, true ) 
    717573        end 
    718  
    719  
    720         ### Defines an attribute named +sym+ for the calling class, as well as a 
    721         ### mutator called +name=+ that is accessed through an exclusive mutex, 
    722         ### and whose argument is tested (using #kind_of?) against the specified 
    723         ### +types+. If +reader+ is +true+, a reader which accesses it through a 
    724         ### sharable mutex is also created. Depends on an instance variable 
    725         ### called '@mutex' being present in the including class which contains 
    726         ### an instance of the Sync class or a compatible replacement; one will 
    727         ### be added to the object on the first call to a method generated by 
    728         ### this function if one is not already present. 
    729         def attr_typelocked( sym, reader=true, *types ) 
    730             raise SyntaxError, "No valid types specified" if types.empty? 
    731             ivarname = "@#{sym.id2name}" 
    732  
    733             # Define the accessor 
    734             if reader 
    735                 define_method( sym ) { 
    736                     if instance_variables.include?( ivarname ) 
    737                         @mutex = Sync::new unless defined? @mutex 
    738                         @mutex.synchronize( Sync::SH ) { 
    739                             instance_variable_get( ivarname ) 
    740                         } 
    741                     else 
    742                         nil 
    743                     end 
    744                 } 
    745             end 
    746  
    747             # Define the mutator 
    748             define_method( "#{sym}=".intern ) {|arg| 
    749                 FaerieMUD::ArgCheckFunctions::check_type( arg, *types ) 
    750                 @mutex = Sync::new unless defined? @mutex 
    751                 @mutex.synchronize( Sync::EX ) { 
    752                     instance_variable_set( ivarname, arg ) 
    753                 } 
    754             } 
    755         end 
    756  
    757  
    758         ### Define a type-checked mutator via #attr_typelocked for the attribute 
    759         ### specified by +sym+ and the given +types+. 
    760         def attr_typelocked_writer( sym, *types ) 
    761             attr_typelocked( sym, false, *types ) 
    762         end 
    763  
    764  
    765         ### Define a type-checking locked accessor and mutator via 
    766         ### #attr_typelocked for the attribute specified by +sym+ and the given 
    767         ### #+types+. 
    768         def attr_typelocked_accessor( sym, *types ) 
    769             attr_typelocked( sym, true, *types ) 
    770         end 
    771  
    772574    end # module AccessorFunctions 
    773575 
  • trunk/lib/fm/organism.rb

    r283 r284  
    11#!/usr/bin/ruby 
     2 
     3require 'fm/mixins' 
     4require 'fm/exceptions' 
     5require 'fm/item' 
     6 
    27#  
    3 # This file contains the FaerieMUD::Organism class, a derivative of 
    4 # FaerieMUD::Item which has an associated Species. Derivatives of this class are naturally-occurring organic 
    5 # objects in the game world, and can be generally categorized into animal, 
    6 # vegetable, or mineral. 
     8# The FaerieMUD::Organism class, a derivative of FaerieMUD::Item which has an 
     9# associated Species. Derivatives of this class are naturally-occurring 
     10# organic objects in the game world, and can be generally categorized into 
     11# animal, vegetable, or mineral. 
    712#  
    813# == Subversion ID 
     
    2025# Please see the file COPYRIGHT in the 'docs' directory for licensing details. 
    2126# 
    22  
    23 require 'fm/mixins' 
    24 require 'fm/exceptions' 
    25 require 'fm/item' 
    26  
    27 ### Derivatives of this class are physical objects in the game world. 
    2827class FaerieMUD::Organism < FaerieMUD::Item 
    2928 
  • trunk/lib/fm/perception.rb

    r277 r284  
    11#!/usr/bin/ruby 
     2 
     3require 'fm/mixins' 
     4require 'fm/exceptions' 
     5require 'fm/gameobject' 
     6 
     7  
    28#  
    3 # This file contains the FaerieMUD::Perception class, a derivative of 
    4 # FaerieMUD::Entity. Instances of this class model a FaerieMUD::Character's 
    5 # ability and limits of perception of the world around her. 
    6 #  
     9# The FaerieMUD::Perception class, a derivative of FaerieMUD::Entity. 
     10# Instances of this class provide a perceptual model for FaerieMUD::Character 
     11# objects. This object is the entity that gathers and transmits descriptions 
     12# of all PerceptualEvents and decides whether or not each can be detected by 
     13# the character. It is also the object principally involved in active 
     14# perception (i.e., via the Verb that contains 'look', 'watch', etc.). 
     15#    
    716# == On Perception in the FaerieMUD World 
    817# 
     
    2332# Please see the file COPYRIGHT in the 'docs' directory for licensing details. 
    2433# 
    25  
    26 require 'fm/mixins' 
    27 require 'fm/exceptions' 
    28 require 'fm/gameobject' 
    29  
    30  
    31  
    32 ### A perceptual model for FaerieMUD::Character objects. This object is the 
    33 ### entity that gathers and transmits descriptions of all PerceptualEvents that 
    34 ### can be detected by the character. It is also the object principally involved 
    35 ### in active perception (i.e., via the Verb that contains 'look', 'watch', 
    36 ### etc.). 
    3734class FaerieMUD::Perception < FaerieMUD::Entity 
    3835 
     
    6663    end 
    6764 
    68  
    69  
    7065end # class FaerieMUD::Perception 
    7166 
    72  
    73 __END__ 
    74  
  • trunk/lib/fm/periodicobject.rb

    r277 r284  
    11#!/usr/bin/ruby 
    2 #  
    3 # This file contains the FaerieMUD::PeriodicObject class, a derivative of 
    4 # FaerieMUD::GameObject. PeriodicObjects are values in a periodic system. A 
    5 # periodic system is one which exhibits periodicity -- the tendency of 
    6 # sub-attributes to recur at regular intervals, sharing attributes between 
    7 # similarly-positioned elements. 
     2 
     3require 'fm/mixins' 
     4require 'fm/gameobject' 
     5 
     6#  
     7# The FaerieMUD::PeriodicObject class, a derivative of FaerieMUD::GameObject. 
     8# PeriodicObjects are values in a periodic system. A periodic system is one 
     9# which exhibits periodicity -- the tendency of sub-attributes to recur at 
     10# regular intervals, sharing attributes between similarly-positioned elements. 
    811#  
    912# In FaerieMUD, the "periodic system" you'll be dealing with is generally The 
     
    2023# differentiated self. 
    2124# 
    22 # == Synopsis 
    23 #  
    24 #    
    25 #  
    2625# == SVNId 
    2726#  
     
    4342# Please see the file COPYRIGHT in the 'docs' directory for licensing details. 
    4443# 
    45  
    46 require 'fm/mixins' 
    47 require 'fm/gameobject' 
    48  
    49 ### Periodic value datatype. 
    5044class FaerieMUD::PeriodicObject < FaerieMUD::GameObject 
    5145    include FaerieMUD::AccessorFunctions, FaerieMUD::HTML 
    5246    contributors :scotus, :ged 
    5347 
    54     # Alias the HTML module for convenience 
    55     #HTML = FaerieMUD::HTML 
    56  
    57     ### A flyweight class for elements of The Pattern, based on the periodic 
    58     ### table of elements. 
    59     class Element < FaerieMUD::GameObject 
    60         include FaerieMUD::Flyweight 
    61         contributors :scotus, :ged 
    62  
    63  
    64         ######################################################### 
    65         ### C O N S T A N T S 
    66         ######################################################### 
    67  
    68         # SVN Revision 
    69         SVNRev = %q$Rev$ 
    70  
    71         # SVN Id 
    72         SVNId = %q$Id$ 
    73  
    74         # Element chemical symbols indexed by atomic number 
    75         Symbols = [nil] + %w{H He Li Be B C N O F Ne Na Mg Al Si P S Cl Ar K 
    76            Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr Rb Sr Y Zr Nb Mo Tc 
    77            Ru Rh Pd Ag Cd In Sn Sb Te I Xe Cs Ba La Ce Pr Nd Pm Sm Eu Gd Tb Dy 
    78            Ho Er Tm Yb Lu Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn Fr Ra Ac 
    79            Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr Rf Db Sg Bh Hs Mt Ds Uuu 
    80            Uub Uut Uuq Uup Uuh Uus Uuo} 
    81  
    82         # Element names indexed by atomic number 
    83         Names = [nil] + %w{Hydrogen Helium Lithium Beryllium Boron Carbon 
    84             Nitrogen Oxygen Fluorine Neon Sodium Magnesium Aluminum Silicon 
    85             Phosphorous Sulfur Chlorine Argon Potassium Calcium Scandium 
    86             Titanium Vanadium Chromium Manganese Iron Cobalt Nickel Copper Zinc 
    87             Gallium Germanium Arsenic Selenium Bromine Krypton Rubidium 
    88             Strontium Yttrium Zirconium Niobium Molybdenum Technetium Ruthenium 
    89             Rhodium Palladium Silver Cadmium Indium Tin Antimony Tellurium 
    90             Iodine Xenon Cesium Barium Lanthanium Cerium Praeseodymium Neodymium 
    91             Promethium Samarium Europium Gadolinium Terbium Dysprosium Holmium 
    92             Erbium Thullium Ytterbium Lutetium Hafnium Tantalum Tungsten Rhenium 
    93             Osmium Iridium Platinum Gold Mercury Thallium Lead Bismuth Polonium 
    94             Astatine Radon Francium Radium Actinium Thorium Protactinium Uranium 
    95             Neptunium Plutonium Americium Curium Berkelium Californium 
    96             Einsteinium Fermium Mendelevium Nobelium Lawrencium Rutherfordium 
    97             Dubnium Seaborgium Bohrium Hassium Meitnerium Darmstadtium Unununium 
    98             Ununbium Ununtrinium Ununquadium Ununpentium Ununhexium Ununseptium 
    99             Ununoctium} 
    100  
    101         # The maximum atomic number (in this Pattern, anyway) 
    102         MaxElement = Symbols.nitems 
    103  
    104         # The periodic table, minus the rare earths, for doing period-traversal 
    105         Table = [ 
    106 [  1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,   2 ], 
    107 [  3,   4, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,   5,   6,   7,   8,   9,  10 ], 
    108 [ 11,  12, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,  13,  14,  15,  16,  17,  18 ], 
    109 [ 19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36 ], 
    110 [ 37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54 ], 
    111 [ 55,  56,  57,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86 ], 
    112 [ 87,  88,  89, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118 ], 
    113         ] 
    114  
    115         # Shift the table over and down one so we don't have to do off-by-one for everything 
    116         Table.each_index {|i| Table[i].insert(0, nil)} 
    117         Table.insert( 0, nil ) 
    118  
    119         # IUPAC group numbers -- a hash keyed by number, with an array of 
    120         # elements within that group as the value. Rare earths (Lanthanides 
    121         # and Actinides) get put in after. 
    122         Groups = Table[1..-1].inject({}) {|hash, row| 
    123  
    124             # Map rows of the table into a Hash of Arrays of elements keyed 
    125             # by group number, dropping nil elements. 
    126             row.each_with_index {|elem,i| 
    127                 next unless i.nonzero? # Skip shift 
    128                 hash[i] ||= [] 
    129                 hash[i].push( elem ) unless elem.nil? 
    130             } 
    131             hash 
    132         } 
    133  
    134         # The rare earths go in group 3 (3B). It's a slice because the first 
    135         # element in the series is already in the Table above. 
    136         Lanthanides = (57..71).to_a 
    137         Groups[3].push( *(Lanthanides[1..-1]) ) 
    138         Actinides = (89..103).to_a 
    139         Groups[3].push( *(Actinides[1..-1]) ) 
    140  
    141         # Interior groups function similarly to regular groups.  They also 
    142         # use CAS group names or can be accessed via the IUPAC number. 
    143         InteriorGroups = [ 
    144             { 
    145                 1 => (1..26).to_a, 
    146                 2 => [27], 
    147                 3 => (28..56).to_a, 
    148                 18 => (71..MaxElement).to_a 
    149             }, 
    150             { 
    151                 1 => (1..44).to_a, 
    152                 2 => [45], 
    153                 3 => (46..88).to_a, 
    154                 18 => (103..MaxElement).to_a 
    155             }, 
    156             { 
    157                 1 => (1..76).to_a, 
    158                 2 => [77], 
    159                 3 => (78..MaxElement).to_a 
    160             }, 
    161             { 
    162                 1 => (1..108).to_a, 
    163                 2 => [109], 
    164                 3 => (110..MaxElement).to_a 
    165             } 
    166         ] 
    167  
    168         ### Interior groups for rare earths 
    169         (4..17).each {|i| 
    170             ### The lanthanide series 
    171             InteriorGroups[ 0 ][ i ] = [i+53] 
    172             ### The actinide series 
    173             InteriorGroups[ 1 ][ i ] = [i+85] 
    174         } 
    175  
    176         # Hidden groups function similarly to interior groups.  They also 
    177         # use CAS group names or can be accessed via the IUPAC number. 
    178         HiddenGroups = [ 
    179             { 
    180                 1 => (1..61).to_a, 
    181                 2 => [62], 
    182                 3 => (63..MaxElement).to_a 
    183             }, 
    184             { 
    185                 1 => (1..93).to_a, 
    186                 2 => [94], 
    187                 3 => (95..MaxElement).to_a 
    188             } 
    189         ] 
    190  
    191         # Array of CAS group names indexed by IUPAC group numbers (leading 
    192         # nil to offset by one) 
    193         GroupName = [nil] + %w{1A 2A 3B 4B 5B 6B 7B 8 8 8 1B 2B 3A 4A 5A 6A 7A 8A} 
    194  
    195  
    196         ######################################################### 
    197         ### C L A S S   M E T H O D S 
    198         ######################################################### 
    199  
    200         ### This function maps element numbers to (IUPAC) Group number. 
    201         def self::number_to_group( atomic_number ) 
    202             Groups.keys.find {|num| Groups[num].include?( atomic_number )} 
    203         end 
    204  
    205  
    206         ### This function maps element numbers to (IUPAC) Interior Groups, 
    207         ### which are returned in a 3-element Array. 
    208         def self::number_to_interior_groups( atomic_number ) 
    209             return InteriorGroups.collect do |groupmap| 
    210                 group = groupmap.find {|num,elements|elements.include?( atomic_number )} 
    211                 group.first 
    212             end 
    213         end 
    214  
    215  
    216         ### This function maps element numbers to (IUPAC) Hidden Groups, 
    217         ### which are returned in a 2-element Array. 
    218         def self::number_to_hidden_groups( atomic_number ) 
    219             return HiddenGroups.collect {|groupmap| 
    220                 groupmap.find {|num,elements| 
    221                     elements.include?( atomic_number ) 
    222                 }[0] 
    223             } 
    224         end 
    225  
    226  
    227         ### This function maps element numbers to IUPAC standard period 
    228         ### numbers. 
    229         def self::number_to_period( atomic_number ) 
    230             FaerieMUD::ArgCheckFunctions::check_type( atomic_number, Integer ) 
    231  
    232             case atomic_number 
    233             when 1..2 
    234                 1 
    235             when 3..10 
    236                 2 
    237             when 11..18 
    238                 3 
    239             when 19..36 
    240                 4 
    241             when 37..54 
    242                 5 
    243             when 55..86 
    244                 6 
    245             when 87..MaxElement 
    246                 7 
    247             else 
    248                 raise RangeError, 
    249                     "No such element #{atomic_number.inspect} on this periodic table." 
    250             end 
    251         end 
    252  
    253  
    254         # Alias away the ::fetch method given to the class by the Flyweight 
    255         # mixin so it can be overridden but still be called. 
    256         alias_class_method :super_fetch, :fetch 
    257  
    258         ### Fetch a new PeriodicObject::Element object with the specified 
    259         ### atomic number or element name +elem+. 
    260         def self::fetch( elem=1 ) 
    261  
    262             # Allow elem to be an Element object for implementations of element= 
    263             # mutators. 
    264             return elem if elem.is_a?( self ) 
    265  
    266             # Attempt to convert names or chemical symbols to atomic numbers. 
    267             if elem.is_a?( String ) || elem.is_a?( Symbol ) 
    268                 name = elem.to_s.capitalize 
    269                 elem = Symbols.index(name) || Names.index(name) or 
    270                     raise ArgumentError, "No such element '#{name}'" 
    271             end 
    272  
    273             super_fetch( elem, 
    274                         number_to_period(elem), 
    275                         number_to_group(elem), 
    276                         Symbols[elem], 
    277                         Names[elem], 
    278                         number_to_hidden_groups(elem), 
    279                         number_to_interior_groups(elem) ) 
    280         end 
    281  
    282  
    283  
    284         ######################################################### 
    285         ### I N S T A N C E   M E T H O D S 
    286         ######################################################### 
    287  
    288         ### Initialize a new PeriodicObject::Element with the specified 
    289         ### atomic +number+, +period+, +group+, chemical +symbol+, +name+, 
    290         ### +hidden_groups+, and +interior_groups+. 
    291         def initialize( number, period, group, symbol, name, 
    292                         hidden_groups, interior_groups ) # :nonew: 
    293             @atomic_number  = number 
    294             @period         = period 
    295             @group          = group 
    296             @group_name     = GroupName[ @group ] 
    297             @symbol         = symbol 
    298             @name           = name 
    299             @series         = group_to_series( @group ) 
    300  
    301             @hidden_groups = hidden_groups 
    302             @hidden_group_names = @hidden_groups.collect {|gr| GroupName[gr]} 
    303             @hidden_series = @hidden_groups.collect {|gr| group_to_series( gr )} 
    304  
    305             @interior_groups = interior_groups 
    306             @interior_group_names = @interior_groups.collect {|gr| GroupName[gr]} 
    307             @interior_series = @interior_groups.collect {|gr| group_to_series( gr )} 
    308         end 
    309  
    310  
    311  
    312         ###### 
    313         public 
    314