h3m 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/README.md +44 -0
- data/Rakefile +5 -0
- data/h3m.gemspec +26 -0
- data/lib/h3m.rb +7 -0
- data/lib/h3m/map.rb +77 -0
- data/lib/h3m/records.rb +49 -0
- data/lib/h3m/version.rb +3 -0
- data/spec/map_spec.rb +54 -0
- data/spec/resources/SoD_L.h3m +0 -0
- data/spec/resources/SoD_M.h3m +0 -0
- data/spec/resources/SoD_S.h3m +0 -0
- data/spec/resources/SoD_XL.h3m +0 -0
- data/spec/resources/test_1.h3m +0 -0
- data/spec/resources/test_2.h3m +0 -0
- data/spec/spec_helper.rb +15 -0
- metadata +137 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# H3m
|
2
|
+
|
3
|
+
Simple parser for Heroes of Might and Magic III map format. Currently can extract info about map name, description, difficulty, size, subterranean presence and minimal required game version (to be continued, see TODO).
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
Usage example:
|
8
|
+
|
9
|
+
>> require "h3m"
|
10
|
+
>> m = H3m::Map.new("path/to/map/file.h3m")
|
11
|
+
|
12
|
+
>> m.name
|
13
|
+
=> "Map name"
|
14
|
+
|
15
|
+
>> m.description
|
16
|
+
=> "Map description"
|
17
|
+
|
18
|
+
>> # Version can be :SoD, :AB or :RoE
|
19
|
+
>> m.version
|
20
|
+
=> :SoD
|
21
|
+
|
22
|
+
>> # Size can be :S, :M, :L and :XL
|
23
|
+
>> m.size
|
24
|
+
=> :M
|
25
|
+
|
26
|
+
>> m.has_subterranean?
|
27
|
+
=> false
|
28
|
+
|
29
|
+
>> # Difficulty can be :easy, :normal, :hard, :expert and :impossible
|
30
|
+
>> m.difficulty
|
31
|
+
=> :normal
|
32
|
+
|
33
|
+
|
34
|
+
## TODO
|
35
|
+
|
36
|
+
1. players and alliances
|
37
|
+
2. victory and lose conditions
|
38
|
+
3. minimap image generation
|
39
|
+
|
40
|
+
## License
|
41
|
+
|
42
|
+
Copyright (C) 2013 Maxim Andryunin
|
43
|
+
|
44
|
+
Released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/h3m.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'h3m/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "h3m"
|
8
|
+
spec.version = H3m::VERSION
|
9
|
+
spec.authors = ["Maxim Andryunin"]
|
10
|
+
spec.email = ["maxim.andryunin@gmail.com"]
|
11
|
+
spec.description = %q{This gem will can extract info about players, teams, map size and version, win conditions of Heroes 3 map}
|
12
|
+
spec.summary = %q{Extract some info from Heroes of Might and Magic 3 map (.h3m)}
|
13
|
+
spec.homepage = "https://github.com/andryunin/h3m"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "bindata"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rspec", ">= 2.0.0"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
end
|
data/lib/h3m.rb
ADDED
data/lib/h3m/map.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
module H3m
|
2
|
+
|
3
|
+
class MapError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class Map
|
7
|
+
# Map representation
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# >> map = H3m::Map.new("some-map-file.h3m")
|
11
|
+
# >> map.version
|
12
|
+
# => :SoD
|
13
|
+
|
14
|
+
attr_reader :path
|
15
|
+
|
16
|
+
def initialize(path)
|
17
|
+
@path = path
|
18
|
+
@gzip_file = File.new(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def file
|
22
|
+
@file ||= Zlib::GzipReader.new(@gzip_file)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get extension
|
26
|
+
# @return [Symbol] :SoD, :AB or :RoE
|
27
|
+
def version
|
28
|
+
@version ||= case record.heroes_version
|
29
|
+
when 0x0E then :RoE
|
30
|
+
when 0x15 then :AB
|
31
|
+
when 0x1C then :SoD
|
32
|
+
else
|
33
|
+
raise MapError, "unknown map version"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def size
|
38
|
+
@size ||= case record.map_size
|
39
|
+
when 36 then :S
|
40
|
+
when 72 then :M
|
41
|
+
when 108 then :L
|
42
|
+
when 144 then :XL
|
43
|
+
else
|
44
|
+
raise MapError, "unknown map size"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def name
|
49
|
+
record.map_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def description
|
53
|
+
record.map_desc
|
54
|
+
end
|
55
|
+
|
56
|
+
def difficulty
|
57
|
+
@difficulty ||= case record.map_difficulty
|
58
|
+
when 0 then :easy
|
59
|
+
when 1 then :normal
|
60
|
+
when 2 then :hard
|
61
|
+
when 3 then :expert
|
62
|
+
when 4 then :impossible
|
63
|
+
else
|
64
|
+
raise MapError, "unknown map difficulty"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def has_subterranean?
|
69
|
+
record.map_has_subterranean != 0
|
70
|
+
end
|
71
|
+
|
72
|
+
def record
|
73
|
+
@record ||= H3m::MapRecord.read(file)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/lib/h3m/records.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
module H3m
|
4
|
+
|
5
|
+
class PlayerRecord < BinData::Record
|
6
|
+
endian :little
|
7
|
+
|
8
|
+
uint8 :max_level
|
9
|
+
|
10
|
+
uint8 :can_be_human
|
11
|
+
uint8 :can_be_computer
|
12
|
+
uint8 :computer_behaviour
|
13
|
+
|
14
|
+
uint8 :has_town_on_start
|
15
|
+
uint16 :can_have_town_types
|
16
|
+
uint8 :has_random_town
|
17
|
+
uint8 :has_main_town
|
18
|
+
|
19
|
+
uint8 :main_town_has_hero, onlyif: :has_main_town?
|
20
|
+
uint8 :main_town_type, onlyif: :has_main_town?
|
21
|
+
uint8 :main_town_coord_x, onlyif: :has_main_town?
|
22
|
+
uint8 :main_town_coord_y, onlyif: :has_main_town?
|
23
|
+
uint8 :main_town_coord_z, onlyif: :has_main_town?
|
24
|
+
|
25
|
+
def has_main_town?
|
26
|
+
has_main_town.nonzero?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class MapRecord < BinData::Record
|
31
|
+
endian :little
|
32
|
+
|
33
|
+
uint32 :heroes_version
|
34
|
+
uint8 :map_has_hero
|
35
|
+
uint32 :map_size
|
36
|
+
uint8 :map_has_subterranean
|
37
|
+
|
38
|
+
uint32 :map_name_size
|
39
|
+
string :map_name, read_length: :map_name_size
|
40
|
+
|
41
|
+
uint32 :map_desc_size
|
42
|
+
string :map_desc, read_length: :map_desc_size
|
43
|
+
|
44
|
+
uint8 :map_difficulty
|
45
|
+
|
46
|
+
array :players, type: :player_record, initial_length: 8
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/h3m/version.rb
ADDED
data/spec/map_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe H3m::Map do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
@files = Dir.glob("spec/resources/SoD_*.h3m")
|
7
|
+
@params = @files.map do |path|
|
8
|
+
filename = File.basename(path, ".h3m")
|
9
|
+
version, size = filename.split("_").map(&:to_sym)
|
10
|
+
{version: version, size: size}
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return correct version" do
|
16
|
+
@files.each_with_index do |path, index|
|
17
|
+
params = @params[index]
|
18
|
+
map = H3m::Map.new(path)
|
19
|
+
map.version.should == params[:version]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return correct size" do
|
24
|
+
@files.each_with_index do |path, index|
|
25
|
+
params = @params[index]
|
26
|
+
map = H3m::Map.new(path)
|
27
|
+
map.size.should == params[:size]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return correct name and description" do
|
32
|
+
map = H3m::Map.new("spec/resources/test_1.h3m")
|
33
|
+
|
34
|
+
map.name.should == "test map name"
|
35
|
+
map.description.should == "test map desc"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should correctly determine subterranean presence" do
|
39
|
+
map = H3m::Map.new("spec/resources/test_1.h3m")
|
40
|
+
map.has_subterranean?.should == true
|
41
|
+
|
42
|
+
map = H3m::Map.new("spec/resources/test_2.h3m")
|
43
|
+
map.has_subterranean?.should == false
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should correctly determine map difficulty" do
|
47
|
+
map = H3m::Map.new("spec/resources/test_1.h3m")
|
48
|
+
map.difficulty.should == :normal
|
49
|
+
|
50
|
+
map = H3m::Map.new("spec/resources/test_2.h3m")
|
51
|
+
map.difficulty.should == :impossible
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
2
|
+
|
3
|
+
require "h3m"
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
+
config.run_all_when_everything_filtered = true
|
8
|
+
config.filter_run :focus
|
9
|
+
|
10
|
+
# Run specs in random order to surface order dependencies. If you find an
|
11
|
+
# order dependency and want to debug it, you can fix the order by providing
|
12
|
+
# the seed, which is printed after each run.
|
13
|
+
# --seed 1234
|
14
|
+
config.order = 'random'
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: h3m
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Maxim Andryunin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bindata
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.0.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.0.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: This gem will can extract info about players, teams, map size and version,
|
79
|
+
win conditions of Heroes 3 map
|
80
|
+
email:
|
81
|
+
- maxim.andryunin@gmail.com
|
82
|
+
executables: []
|
83
|
+
extensions: []
|
84
|
+
extra_rdoc_files: []
|
85
|
+
files:
|
86
|
+
- .gitignore
|
87
|
+
- .rspec
|
88
|
+
- Gemfile
|
89
|
+
- README.md
|
90
|
+
- Rakefile
|
91
|
+
- h3m.gemspec
|
92
|
+
- lib/h3m.rb
|
93
|
+
- lib/h3m/map.rb
|
94
|
+
- lib/h3m/records.rb
|
95
|
+
- lib/h3m/version.rb
|
96
|
+
- spec/map_spec.rb
|
97
|
+
- spec/resources/SoD_L.h3m
|
98
|
+
- spec/resources/SoD_M.h3m
|
99
|
+
- spec/resources/SoD_S.h3m
|
100
|
+
- spec/resources/SoD_XL.h3m
|
101
|
+
- spec/resources/test_1.h3m
|
102
|
+
- spec/resources/test_2.h3m
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
homepage: https://github.com/andryunin/h3m
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ! '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 1.8.24
|
126
|
+
signing_key:
|
127
|
+
specification_version: 3
|
128
|
+
summary: Extract some info from Heroes of Might and Magic 3 map (.h3m)
|
129
|
+
test_files:
|
130
|
+
- spec/map_spec.rb
|
131
|
+
- spec/resources/SoD_L.h3m
|
132
|
+
- spec/resources/SoD_M.h3m
|
133
|
+
- spec/resources/SoD_S.h3m
|
134
|
+
- spec/resources/SoD_XL.h3m
|
135
|
+
- spec/resources/test_1.h3m
|
136
|
+
- spec/resources/test_2.h3m
|
137
|
+
- spec/spec_helper.rb
|