def players
      return @players if defined? @players
      @players = details[0].map do |player|
        { :name => player[0],
        
          # This could probably be 'unknown' in some circumstances I haven't 
          # yet checked.
          :outcome => OUTCOMES[player[8]]
        }
      end
    
      # Unlike the `replay.initData` file, this method of determining race is
      # the same across all localizations.
      attributes.each do |attr|
        case attr.id.to_i
        when 0x01f4
          @players[attr.player - 1][:type] = ATTRIBUTES[:player_type][attr.sval]
        when 0x0bb9
          @players[attr.player - 1][:race] = ATTRIBUTES[:player_race][attr.sval]
        when 0x0bba
          @players[attr.player - 1][:color] = 
            ATTRIBUTES[:player_color][attr.sval]
        end
      end
      @players
    end
def players
      return @players if defined? @players
      @players = details[0].map do |player|
        { :name => player[0],
        
          # This could probably be 'unknown' in some circumstances I haven't 
          # yet checked.
          :outcome => OUTCOMES[player[8]]
        }
      end
    
      # Unlike the `replay.initData` file, this method of determining race is
      # the same across all localizations.
      attributes.each do |attr|
        case attr.id.to_i
        when 0x01f4
          @players[attr.player - 1][:type] = ATTRIBUTES[:player_type][attr.sval]
        when 0x0bb9
          @players[attr.player - 1][:race] = ATTRIBUTES[:player_race][attr.sval]
        when 0x0bba
          @players[attr.player - 1][:color] = 
            ATTRIBUTES[:player_color][attr.sval]
        end
      end
      @players
    end
Player information is spread among a couple of files: the
 `replay.details` file and the `replay.attributes.events` file. Here we
 combine the information contained in each.