dd-next-encounters 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/data/xp_difficulty_table.rb +85 -0
- data/lib/encounters/lair.rb +33 -52
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f992cf10c5edcaa924babaa9bee59310ae429d74
|
4
|
+
data.tar.gz: f0a0fa06edd5e12fb568f0678418767778e6dc57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cf3569a96c494e17fb77d80fb440756f9576643a5b6c62714d0635a486db93b980f0d63dd72652d788f33c05a5aaf4bf2cab90a447900c883161bcc6dd6d19e
|
7
|
+
data.tar.gz: 5df39fb670702c48932914959b0773876d2f274beed956896e700ecfb95e9e10fab66aaebc5e7cb54b776aa2f9549c8c0b887cc648b285d9143df6081cdbd5f9
|
@@ -20,4 +20,89 @@ module XpDifficultyTable
|
|
20
20
|
18=>{:easy=>2100, :medium=>4200, :hard=>6300, :deadly=>9500},
|
21
21
|
19=>{:easy=>2400, :medium=>4900, :hard=>7300, :deadly=>10900},
|
22
22
|
20=>{:easy=>2800, :medium=>5700, :hard=>8500, :deadly=>12700}}
|
23
|
+
REVERSED_XP_DIFFICULTY_TABLE =
|
24
|
+
{:easy=>
|
25
|
+
{25=>1,
|
26
|
+
50=>2,
|
27
|
+
75=>3,
|
28
|
+
125=>4,
|
29
|
+
250=>5,
|
30
|
+
300=>6,
|
31
|
+
350=>7,
|
32
|
+
450=>8,
|
33
|
+
550=>9,
|
34
|
+
600=>10,
|
35
|
+
800=>11,
|
36
|
+
1000=>12,
|
37
|
+
1100=>13,
|
38
|
+
1250=>14,
|
39
|
+
1400=>15,
|
40
|
+
1600=>16,
|
41
|
+
2000=>17,
|
42
|
+
2100=>18,
|
43
|
+
2400=>19,
|
44
|
+
2800=>20},
|
45
|
+
:medium=>
|
46
|
+
{50=>1,
|
47
|
+
100=>2,
|
48
|
+
150=>3,
|
49
|
+
250=>4,
|
50
|
+
500=>5,
|
51
|
+
600=>6,
|
52
|
+
750=>7,
|
53
|
+
900=>8,
|
54
|
+
1100=>9,
|
55
|
+
1200=>10,
|
56
|
+
1600=>11,
|
57
|
+
2000=>12,
|
58
|
+
2200=>13,
|
59
|
+
2500=>14,
|
60
|
+
2800=>15,
|
61
|
+
3200=>16,
|
62
|
+
3900=>17,
|
63
|
+
4200=>18,
|
64
|
+
4900=>19,
|
65
|
+
5700=>20},
|
66
|
+
:hard=>
|
67
|
+
{75=>1,
|
68
|
+
150=>2,
|
69
|
+
225=>3,
|
70
|
+
375=>4,
|
71
|
+
750=>5,
|
72
|
+
900=>6,
|
73
|
+
1100=>7,
|
74
|
+
1400=>8,
|
75
|
+
1600=>9,
|
76
|
+
1900=>10,
|
77
|
+
2400=>11,
|
78
|
+
3000=>12,
|
79
|
+
3400=>13,
|
80
|
+
3800=>14,
|
81
|
+
4300=>15,
|
82
|
+
4800=>16,
|
83
|
+
5900=>17,
|
84
|
+
6300=>18,
|
85
|
+
7300=>19,
|
86
|
+
8500=>20},
|
87
|
+
:deadly=>
|
88
|
+
{100=>1,
|
89
|
+
200=>2,
|
90
|
+
400=>3,
|
91
|
+
500=>4,
|
92
|
+
1100=>5,
|
93
|
+
1400=>6,
|
94
|
+
1700=>7,
|
95
|
+
2100=>8,
|
96
|
+
2400=>9,
|
97
|
+
2800=>10,
|
98
|
+
3600=>11,
|
99
|
+
4500=>12,
|
100
|
+
5100=>13,
|
101
|
+
5700=>14,
|
102
|
+
6400=>15,
|
103
|
+
7200=>16,
|
104
|
+
8800=>17,
|
105
|
+
9500=>18,
|
106
|
+
10900=>19,
|
107
|
+
12700=>20}}
|
23
108
|
end
|
data/lib/encounters/lair.rb
CHANGED
@@ -5,20 +5,24 @@ class Lair
|
|
5
5
|
|
6
6
|
include XpDifficultyTable
|
7
7
|
|
8
|
-
AVAILABLE_ENCOUNTER_LEVEL=
|
8
|
+
AVAILABLE_ENCOUNTER_LEVEL = REVERSED_XP_DIFFICULTY_TABLE.keys
|
9
9
|
|
10
10
|
def initialize( *encounters_types )
|
11
11
|
@monster_manual = MonstersManual.new
|
12
12
|
@monsters = nil
|
13
|
-
@xp_difficulty_table = XP_DIFFICULTY_TABLE
|
14
|
-
@encounters_types = encounters_types
|
15
|
-
@encounters={}
|
16
13
|
end
|
17
14
|
|
18
15
|
def read_manuals
|
19
16
|
read_monster_manual
|
20
17
|
end
|
21
18
|
|
19
|
+
def print_summary
|
20
|
+
p @monster_manual.sources
|
21
|
+
puts
|
22
|
+
p @monster_manual.types
|
23
|
+
puts
|
24
|
+
end
|
25
|
+
|
22
26
|
def groups
|
23
27
|
@monster_manual.validate_loaded
|
24
28
|
@monster_manual.groups.keys
|
@@ -33,42 +37,23 @@ class Lair
|
|
33
37
|
raise 'Party too weak. Minimum 3 members' if hero_level.count < 3
|
34
38
|
|
35
39
|
hero_level.each do |level|
|
40
|
+
raise "Hero level should be an integer currently : #{level.class.to_s}" unless level.class == Integer
|
36
41
|
raise "Bad hero level : #{level}. Should be between 1 .. 20" if level < 1 || level > 20
|
37
42
|
end
|
38
43
|
|
39
|
-
party_xp_level = hero_level.map{ |hl|
|
40
|
-
|
41
|
-
tested_encounters_types = []
|
42
|
-
encounter = nil
|
43
|
-
loop do
|
44
|
-
|
45
|
-
raise "Can't create an encounter for this party" if (@encounters_types-tested_encounters_types).empty?
|
46
|
-
encounter = Encounter.new( party_xp_level )
|
47
|
-
|
48
|
-
# Choose a random encounter type
|
49
|
-
encounter_type = ( @encounters_types - tested_encounters_types ).sample
|
50
|
-
bosses = @encounters[encounter_type][:bosses]
|
51
|
-
troops = @encounters[encounter_type][:troops]
|
52
|
-
|
53
|
-
# Choose a random boss
|
54
|
-
boss = bosses.sample if !bosses.empty? && rand( 1 .. 2 ) == 1
|
55
|
-
encounter.add_monster_while_possible(boss ) if boss
|
44
|
+
party_xp_level = hero_level.map{ |hl| XP_DIFFICULTY_TABLE[hl][encounter_level] }.reduce(&:+)
|
45
|
+
one_sixth_party_xp_level = party_xp_level / 6
|
56
46
|
|
57
|
-
|
58
|
-
|
59
|
-
# We couldn't get a monster of this type for this party. Probably the monsters are too hard
|
60
|
-
# Then we have to check again with another monster type
|
61
|
-
unless monster
|
62
|
-
tested_encounters_types << encounter_type
|
63
|
-
next
|
64
|
-
end
|
47
|
+
candidate_monsters = @monster_manual.select( sources: [ 'Basic Rules', 'Monster Manual' ], types: %w( Undead Fiend Giant Humanoid ) )
|
48
|
+
candidate_monsters = candidate_monsters.reject{ |m| m.xp_value > party_xp_level || m.xp_value < one_sixth_party_xp_level }
|
65
49
|
|
66
|
-
|
67
|
-
|
68
|
-
break unless encounter.add_monster_while_possible(monster )
|
69
|
-
end
|
50
|
+
choosed_monster = candidate_monsters.sample
|
51
|
+
monsters_amount = ( party_xp_level / choosed_monster.xp_value ).floor
|
70
52
|
|
71
|
-
|
53
|
+
encounter = Encounter.new( party_xp_level )
|
54
|
+
1.upto(monsters_amount).each do
|
55
|
+
# p encounter
|
56
|
+
break unless encounter.add_monster_while_possible( choosed_monster )
|
72
57
|
end
|
73
58
|
|
74
59
|
encounter
|
@@ -76,33 +61,29 @@ class Lair
|
|
76
61
|
|
77
62
|
private
|
78
63
|
|
79
|
-
def get_corresponding_monsters( troops, party_xp_level)
|
80
|
-
troops.map{ |m| m if m.xp_value < party_xp_level }.compact
|
81
|
-
end
|
82
|
-
|
83
64
|
def read_monster_manual
|
84
65
|
@monster_manual.load
|
85
|
-
validate_encounters_types
|
66
|
+
# validate_encounters_types
|
86
67
|
|
87
68
|
@monsters = @monster_manual.select( sources: [ 'Basic Rules', 'Monster Manual' ] )
|
88
69
|
|
89
|
-
@encounters_types.each do |encounter_type|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
70
|
+
# @encounters_types.each do |encounter_type|
|
71
|
+
# @encounters[encounter_type] ||= { troops: [], bosses: [] }
|
72
|
+
# @encounters[encounter_type][:troops] = @monster_manual.groups[encounter_type]&.troops
|
73
|
+
# @encounters[encounter_type][:bosses] = @monster_manual.groups[encounter_type]&.bosses
|
74
|
+
# end
|
94
75
|
end
|
95
76
|
|
96
77
|
private
|
97
78
|
|
98
|
-
def validate_encounters_types
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
79
|
+
# def validate_encounters_types
|
80
|
+
# @encounters_types.each do |encounter_type|
|
81
|
+
# unless @monster_manual.groups.include?( encounter_type )
|
82
|
+
# raise "Bad lair type : #{encounter_type.inspect}" + ". Available lairs types : #{@monster_manual.groups.keys}"
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
# @encounters_types = @monster_manual.groups.keys if @encounters_types.empty?
|
86
|
+
# end
|
106
87
|
|
107
88
|
end
|
108
89
|
|