MeChallenge 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2008-12-18
2
+
3
+ * 1 First Cut
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,9 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/me_challenge
6
+ lib/me_challenge.rb
7
+ lib/middle_earth_challenge_simulator.rb
8
+ test/test_me_challenge.rb
9
+ test/test_middle_earth_challenge_simulator.rb
@@ -0,0 +1,55 @@
1
+ = MeChallenge
2
+
3
+ * http://rubyforge.org/projects/uwruby
4
+ * http://uwruby.rubyforge.org/MeChallenge
5
+
6
+ == DESCRIPTION:
7
+
8
+ This command line utility simulates n number of personal challenge combats
9
+ in the PBM game Ware in Middle Earth.
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * Specify challenge rank
14
+ * Specify health
15
+ * Specify number of simulations
16
+
17
+ == SYNOPSIS:
18
+
19
+ USAGE:
20
+ me_challenge rank1 health1 rank2 health2 rounds
21
+ EXAMPLE:
22
+ me_challenge 50 100 30 100 10000
23
+
24
+ == REQUIREMENTS:
25
+
26
+ * Ruby 1.8.6
27
+
28
+ == INSTALL:
29
+
30
+ * sudo gem install MeChallenge
31
+
32
+ == LICENSE:
33
+
34
+ (The MIT License)
35
+
36
+ Copyright (c) 2008 Chesley Coughlin
37
+
38
+ Permission is hereby granted, free of charge, to any person obtaining
39
+ a copy of this software and associated documentation files (the
40
+ 'Software'), to deal in the Software without restriction, including
41
+ without limitation the rights to use, copy, modify, merge, publish,
42
+ distribute, sublicense, and/or sell copies of the Software, and to
43
+ permit persons to whom the Software is furnished to do so, subject to
44
+ the following conditions:
45
+
46
+ The above copyright notice and this permission notice shall be
47
+ included in all copies or substantial portions of the Software.
48
+
49
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
50
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
52
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
53
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
54
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
55
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,13 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/me_challenge.rb'
6
+
7
+ Hoe.new('MeChallenge', MeChallenge::VERSION) do |p|
8
+ p.rubyforge_name = 'uwruby' # if different than lowercase project name
9
+ p.developer('Chesley Coughlin', 'chesley_coughlin@yahoo.com')
10
+
11
+ end
12
+
13
+ # vim: syntax=Ruby
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby -w
2
+ require 'rubygems'
3
+ require 'me_challenge'
4
+
5
+ MeChallenge.run(ARGV)
@@ -0,0 +1,13 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'middle_earth_challenge_simulator'
4
+
5
+ class MeChallenge
6
+ VERSION = '1.0.0'
7
+
8
+ def self.run(args)
9
+ MiddleEarthChallengeSimulator.run(args)
10
+ end
11
+ end
12
+
13
+ MeChallenge.run(ARGV) if ($0 == __FILE__ || false)
@@ -0,0 +1,187 @@
1
+ #
2
+ # Middle Earth Challenge Simulator
3
+ # Copyright (C) 2008, Chesley Coughlin
4
+ # WEEK 8 Homework
5
+
6
+ class Character
7
+ include Comparable
8
+
9
+ MAX_HEALTH = 100
10
+ attr_accessor :challenge_rank
11
+ attr_reader :name, :health
12
+
13
+ def initialize (n, c, h)
14
+ @name = n
15
+ @challenge_rank = c
16
+ @health = h
17
+ end
18
+
19
+ def health=(h)
20
+ raise ArgumentError, "Health #{h} greater than max health #{MAX_HEALTH}" if (h > MAX_HEALTH)
21
+ @health = h
22
+ end
23
+
24
+ def to_s
25
+ "Character {name: #{self.name} challenge_rank: #{self.challenge_rank} " \
26
+ "health: #{self.health}}"
27
+ end
28
+
29
+ def <=> c
30
+ return self.challenge_rank <=> c.challenge_rank
31
+ end
32
+ end
33
+
34
+ class Attack
35
+ include Comparable
36
+ CRITICAL_MISS = 5
37
+ CRITICAL_HIT = 96
38
+
39
+ attr_reader :attack_value, :critical_hit, :critical_miss, :r1, :r2,
40
+ :challenge_rank
41
+
42
+ def initialize(c, roll1 = rand(99) + 1, roll2 = rand(99)+1)
43
+ @challenge_rank = c
44
+ @r1 = roll1
45
+ @critical_miss = @r1 <= CRITICAL_MISS
46
+ @critical_hit = @r1 >= CRITICAL_HIT
47
+ @r2 = 0
48
+ @r2 = roll2 if (self.critical_hit || self.critical_miss)
49
+ @attack_value = @r1 + @challenge_rank
50
+ @attack_value = @attack_value - @r2 if self.critical_miss
51
+ @attack_value = @attack_value + @r2 if self.critical_hit
52
+ end
53
+
54
+ def <=> a
55
+ return self.attack_value <=> a.attack_value
56
+ end
57
+
58
+ def to_s
59
+ "Attack {attack_value: #{@attack_value} " \
60
+ "challenge_rank #{@challenge_rank} " \
61
+ "r1: #{@r1} " \
62
+ "critical_hit: #{@critical_hit} " \
63
+ "critical_miss: #{@critical_miss} " \
64
+ "r2: #{@r2}}"
65
+ end
66
+ end
67
+
68
+ class CombatRound
69
+ attr_reader :attack1, :attack2, :damage, :character1, :character2
70
+ def initialize(a1, a2, d, c1, c2)
71
+ @attack1 = a1
72
+ @attack2 = a2
73
+ @damage = d
74
+ @character1 = c1.dup
75
+ @character2 = c2.dup
76
+ end
77
+ end
78
+
79
+ class MiddleEarthCombat
80
+ attr_reader :character1, :character2, :results, :victor
81
+
82
+ def initialize (c1, c2)
83
+ raise ArgumentError if c1.health <= 0 || c2.health <= 0
84
+ @character1 = c1
85
+ @character2 = c2
86
+ @victor = nil
87
+ @results = []
88
+ end
89
+
90
+
91
+ def MiddleEarthCombat.get_damage(a1, a2)
92
+ #tie
93
+ return 0 if (a1 == a2)
94
+
95
+ max_damage = a1.attack_value - a2.attack_value if a1 > a2
96
+ max_damage = a2.attack_value - a1.attack_value if a2 > a1
97
+ return rand(max_damage) + 1
98
+ end
99
+
100
+ def do_round(a1 = Attack.new(@character1.challenge_rank),
101
+ a2 = Attack.new(@character2.challenge_rank),
102
+ d = MiddleEarthCombat.get_damage(a1, a2))
103
+
104
+ raise RuntimeError if @character1.health <= 0 || @character2.health <= 0
105
+ if a1 > a2
106
+ @character2.health = @character2.health - d
107
+ elsif a2 > a1
108
+ @character1.health = @character1.health - d
109
+ else
110
+ #tie
111
+ end
112
+
113
+ @results << CombatRound.new(a1, a2, d, @character1, @character2)
114
+ end
115
+
116
+ def fight
117
+ until self.character1.health <= 0 || self.character2.health <= 0
118
+ do_round
119
+ end
120
+ @victor = self.character1.health > 0 ? self.character1 : self.character2
121
+ end
122
+
123
+ def to_s
124
+ result = "============================================================\n" \
125
+ "MiddleEarthCombat\n" \
126
+ "Victor: #{@victor}\n" \
127
+ "after #{@results.size} rounds\n" \
128
+ "============================================================\n" \
129
+ "Combat Details\n"
130
+ @results.each do |r|
131
+ result << "------------------------------------------\n"
132
+ result << "Damage #{r.damage}\n"
133
+ result << "#{r.character1} attack was #{r.attack1}\n"
134
+ result << "#{r.character2} attack was #{r.attack2}\n"
135
+ end
136
+
137
+ return result
138
+ end
139
+ end
140
+
141
+ class MiddleEarthChallengeSimulator
142
+ attr_reader :character1, :character2, :character1_wins,
143
+ :character2_wins, :num_rounds
144
+
145
+ def initialize (c1, c2, rounds)
146
+ raise ArgumentError if c1.health <= 0 || c2.health <= 0
147
+
148
+ @character1 = c1.dup
149
+ @character2 = c2.dup
150
+ @num_rounds = rounds
151
+ @character1_wins = 0
152
+ @character2_wins = 0
153
+ end
154
+
155
+ def simulate
156
+ (1..@num_rounds).each do
157
+ me_combat = MiddleEarthCombat.new(@character1.dup, @character2.dup)
158
+ me_combat.fight
159
+ @character1_wins += 1 if (@character1.name == me_combat.victor.name)
160
+ @character2_wins += 1 if (@character2.name == me_combat.victor.name)
161
+
162
+ end
163
+ end
164
+
165
+ def MiddleEarthChallengeSimulator.run(args)
166
+ unless args.size == 5
167
+ puts "\nUSAGE:\n\tmiddle_earth_challenge_simulator.rb rank1 health1 rank2 health2 rounds\n"
168
+ puts "EXAMPLE:\n\tmiddle_earth_challenge_simulator.rb 50 100 30 100 10000"
169
+ return -1
170
+ end
171
+
172
+ c1 = Character.new("Character #1", args.shift.to_i, args.shift.to_i)
173
+ c2 = Character.new("Character #2", args.shift.to_i, args.shift.to_i)
174
+ rounds = args.shift.to_i
175
+
176
+ puts "Simulating #{rounds} rounds of combat between #{c1} and #{c2}\n"
177
+
178
+ mec = MiddleEarthChallengeSimulator.new(c1, c2, rounds)
179
+ mec.simulate
180
+
181
+ puts "#{mec.character1} won #{mec.character1_wins}"
182
+ puts "#{mec.character2} won #{mec.character2_wins}"
183
+
184
+ end
185
+ end
186
+
187
+ MiddleEarthChallengeSimulator.run(ARGV) if ($0 == __FILE__ || false)
File without changes
@@ -0,0 +1,224 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+
6
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
7
+
8
+ require 'test/unit'
9
+ require 'middle_earth_challenge_simulator'
10
+
11
+ class TestMiddleEarthChallengeSimulator < Test::Unit::TestCase
12
+ def setup
13
+ @c1 = Character.new("Arg the Barbarian", 30, 100)
14
+ @c2 = Character.new("Bob the Emmy", 15, 100)
15
+ @c3 = Character.new("Chester the Wounded", 15, 1)
16
+ @c4 = Character.new("Dorris the Dead", 30, 0)
17
+ @c5 = Character.new("Jason the Bold", 200, 100)
18
+ @a1 = Attack.new(50, 45, 46)
19
+ @a2 = Attack.new(50, 5, 100)
20
+ @a3 = Attack.new(10, 98, 5)
21
+ end
22
+
23
+ def test_character_health
24
+ @c1.health = Character::MAX_HEALTH
25
+
26
+ assert_equal Character::MAX_HEALTH, @c1.health
27
+ assert_raise ArgumentError do
28
+ @c1.health = Character::MAX_HEALTH + 1
29
+ end
30
+ end
31
+
32
+ def test_attack
33
+ a = Attack.new(50, 45, 46)
34
+
35
+ assert_equal 95, a.attack_value
36
+ assert_equal 45, a.r1
37
+ assert_equal 0, a.r2
38
+ assert_equal 50, a.challenge_rank
39
+ assert_equal false, a.critical_hit
40
+ assert_equal false, a.critical_miss
41
+ end
42
+
43
+ def test_attack_critical_miss
44
+ a = Attack.new(50, 5, 100)
45
+
46
+ expected_attack_value = -45 #editor was barking about -45 in the assert_equal
47
+ assert_equal expected_attack_value, a.attack_value
48
+ assert_equal 5, a.r1
49
+ assert_equal 100, a.r2
50
+ assert_equal 50, a.challenge_rank
51
+ assert_equal false, a.critical_hit
52
+ assert_equal true, a.critical_miss
53
+ end
54
+
55
+ def test_attack_critical_hit
56
+ a = Attack.new(10, 98, 5)
57
+
58
+ assert_equal 113, a.attack_value
59
+ assert_equal 98, a.r1
60
+ assert_equal 5, a.r2
61
+ assert_equal 10, a.challenge_rank
62
+ assert_equal true, a.critical_hit
63
+ assert_equal false, a.critical_miss
64
+ end
65
+
66
+ def test_middle_earth_combat_get_damage
67
+ srand(42)
68
+ d1 = MiddleEarthCombat.get_damage(@a2, @a3)
69
+ srand(42)
70
+ d2 = MiddleEarthCombat.get_damage(@a3, @a2)
71
+ expected = 103
72
+
73
+ assert_equal expected, d1
74
+ assert_equal expected, d2
75
+ end
76
+
77
+ def test_middle_earth_combat_get_damage_tie
78
+ expected = 0
79
+ d = MiddleEarthCombat.get_damage(@a1, @a1)
80
+
81
+ assert_equal expected, d
82
+ end
83
+
84
+ def test_middle_earth_combat_do_round_a1_wins
85
+ me_combat = MiddleEarthCombat.new(@c1, @c2)
86
+ me_combat.do_round(@a1, @a2, 50)
87
+
88
+ assert_equal 100, @c1.health
89
+ assert_equal 50, @c2.health
90
+ assert_equal @a1, me_combat.results[0].attack1
91
+ assert_equal @a2, me_combat.results[0].attack2
92
+ assert_equal 50, me_combat.results[0].damage
93
+ assert_equal @c1, me_combat.results[0].character1
94
+ assert_equal @c2, me_combat.results[0].character2
95
+ end
96
+
97
+ def test_middle_earth_combat_do_round_a2_wins
98
+ me_combat = MiddleEarthCombat.new(@c1, @c2)
99
+ me_combat.do_round(@a2, @a1, 75)
100
+
101
+ assert_equal 25, @c1.health
102
+ assert_equal 100, @c2.health
103
+ assert_equal @a2, me_combat.results[0].attack1
104
+ assert_equal @a1, me_combat.results[0].attack2
105
+ assert_equal 75, me_combat.results[0].damage
106
+ assert_equal @c1, me_combat.results[0].character1
107
+ assert_equal @c2, me_combat.results[0].character2
108
+
109
+ end
110
+
111
+ def test_middle_earth_combat_do_round_tie
112
+ me_combat = MiddleEarthCombat.new(@c1, @c3)
113
+ me_combat.do_round(@a1, @a1)
114
+
115
+ assert_equal 100, @c1.health
116
+ assert_equal 1, @c3.health
117
+ assert_equal @a1, me_combat.results[0].attack1
118
+ assert_equal @a1, me_combat.results[0].attack2
119
+ assert_equal 0, me_combat.results[0].damage
120
+ assert_equal @c1, me_combat.results[0].character1
121
+ assert_equal @c3, me_combat.results[0].character2
122
+
123
+ end
124
+
125
+ def test_middle_earth_combat_do_round_with_dead
126
+ me_combat = MiddleEarthCombat.new(@c1, @c3)
127
+ @c3.health = 0
128
+
129
+ assert_raise RuntimeError do
130
+ me_combat.do_round
131
+ end
132
+
133
+ end
134
+
135
+ def test_middle_earth_combat_do_round_with_nil
136
+ assert_raise NoMethodError do
137
+ MiddleEarthCombat.new(@c1, nil)
138
+ end
139
+ end
140
+
141
+ def test_middle_earth_combat_fight_c1_wins
142
+ srand(42)
143
+ me_combat = MiddleEarthCombat.new(@c1, @c3)
144
+ me_combat.fight
145
+
146
+ assert_equal @c1, me_combat.victor
147
+ assert_equal 100, @c1.health
148
+ expected_health = -20 #make the editor stop barking
149
+ assert_equal expected_health, @c3.health
150
+ assert_equal 1, me_combat.results.size
151
+ assert_equal @c1.challenge_rank, me_combat.results[0].attack1.challenge_rank
152
+ assert_equal @c3.challenge_rank, me_combat.results[0].attack2.challenge_rank
153
+ assert_equal 21, me_combat.results[0].damage
154
+ assert_equal @c1, me_combat.results[0].character1
155
+ assert_equal @c3, me_combat.results[0].character2
156
+ end
157
+
158
+ def test_middle_earth_combat_fight_c2_wins
159
+ srand(25)
160
+ me_combat = MiddleEarthCombat.new(@c1, @c2)
161
+ me_combat.fight
162
+
163
+ assert_equal @c2, me_combat.victor
164
+ assert_equal 12, @c2.health
165
+ assert_equal @c1.health, -115
166
+ assert_equal 8, me_combat.results.size
167
+ end
168
+
169
+ def test_middle_earth_combat_fight_with_dead
170
+ assert_raise ArgumentError do
171
+ MiddleEarthCombat.new(@c1, @c4)
172
+ end
173
+ end
174
+
175
+ def test_simulation
176
+ expected_rounds = 100
177
+ me_challenge = MiddleEarthChallengeSimulator.new(@c1, @c2, expected_rounds)
178
+
179
+ assert_equal @c1, me_challenge.character1
180
+ assert_equal @c2, me_challenge.character2
181
+ assert_equal expected_rounds, me_challenge.num_rounds
182
+ assert_equal 0, me_challenge.character1_wins
183
+ assert_equal 0, me_challenge.character2_wins
184
+
185
+ me_challenge.simulate
186
+
187
+ assert(me_challenge.character1_wins > expected_rounds * 0.7)
188
+ assert(me_challenge.character2_wins < expected_rounds * 0.3)
189
+ assert_equal expected_rounds, (me_challenge.character1_wins + me_challenge.character2_wins)
190
+ end
191
+
192
+ def test_simulation_c1_always_win
193
+ expected_rounds = 10000
194
+ me_challenge = MiddleEarthChallengeSimulator.new(@c5, @c3, expected_rounds)
195
+
196
+ me_challenge.simulate
197
+
198
+ assert_equal expected_rounds, me_challenge.character1_wins
199
+ assert_equal 0, me_challenge.character2_wins
200
+ end
201
+
202
+ def test_simulation_c2_always_win
203
+ expected_rounds = 10000
204
+ me_challenge = MiddleEarthChallengeSimulator.new(@c3, @c5, expected_rounds)
205
+
206
+ me_challenge.simulate
207
+
208
+ assert_equal expected_rounds, me_challenge.character2_wins
209
+ assert_equal 0, me_challenge.character1_wins
210
+ end
211
+
212
+ def test_simulation_with_dead
213
+ assert_raise ArgumentError do
214
+ MiddleEarthChallengeSimulator.new(@c1, @c4, 1)
215
+ end
216
+ end
217
+
218
+ def test_simulation_with_nil
219
+ assert_raise NoMethodError do
220
+ MiddleEarthChallengeSimulator.new(@c1, nil, 1)
221
+ end
222
+ end
223
+
224
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: MeChallenge
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Chesley Coughlin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-18 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.2
24
+ version:
25
+ description: This command line utility simulates n number of personal challenge combats in the PBM game Ware in Middle Earth.
26
+ email:
27
+ - chesley_coughlin@yahoo.com
28
+ executables:
29
+ - me_challenge
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - README.txt
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - bin/me_challenge
42
+ - lib/me_challenge.rb
43
+ - lib/middle_earth_challenge_simulator.rb
44
+ - test/test_me_challenge.rb
45
+ - test/test_middle_earth_challenge_simulator.rb
46
+ has_rdoc: true
47
+ homepage: http://rubyforge.org/projects/uwruby
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --main
51
+ - README.txt
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project: uwruby
69
+ rubygems_version: 1.2.0
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: This command line utility simulates n number of personal challenge combats in the PBM game Ware in Middle Earth.
73
+ test_files:
74
+ - test/test_me_challenge.rb
75
+ - test/test_middle_earth_challenge_simulator.rb