MeChallenge 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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