studio_game_2021 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.
- checksums.yaml +7 -0
- data/LICENSE +7 -0
- data/README +136 -0
- data/bin/avatar_players.csv +7 -0
- data/bin/players.csv +6 -0
- data/bin/studio_game +29 -0
- data/lib/studio_game/auditable.rb +7 -0
- data/lib/studio_game/berserk_player.rb +33 -0
- data/lib/studio_game/clumsy_player.rb +27 -0
- data/lib/studio_game/die.rb +24 -0
- data/lib/studio_game/formatting.rb +11 -0
- data/lib/studio_game/game.rb +63 -0
- data/lib/studio_game/game_stats.rb +47 -0
- data/lib/studio_game/game_turn.rb +23 -0
- data/lib/studio_game/handle_csv.rb +19 -0
- data/lib/studio_game/loaded_die.rb +17 -0
- data/lib/studio_game/playable.rb +19 -0
- data/lib/studio_game/player.rb +72 -0
- data/lib/studio_game/printable.rb +44 -0
- data/lib/studio_game/treasure.rb +16 -0
- data/lib/studio_game/treasure_trove.rb +25 -0
- data/spec/studio_game/berserk_player_spec.rb +32 -0
- data/spec/studio_game/clumsy_player_spec.rb +33 -0
- data/spec/studio_game/game_spec.rb +168 -0
- data/spec/studio_game/player_spec.rb +165 -0
- data/spec/studio_game/treasure_spec.rb +28 -0
- data/spec/studio_game/treasure_trove_spec.rb +44 -0
- metadata +231 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module StudioGame
|
|
2
|
+
module HandleCSV
|
|
3
|
+
def load_players(from_file)
|
|
4
|
+
File.readlines(from_file).each do |line|
|
|
5
|
+
player = Player.from_csv(line)
|
|
6
|
+
add_player(player)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def save_high_scores(to_file="high_scores.txt")
|
|
11
|
+
File.open(to_file, "w") do |file|
|
|
12
|
+
file.puts "#{self.title} High Scores:"
|
|
13
|
+
self.players.sort.each do |player|
|
|
14
|
+
file.puts player.print_score
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module StudioGame
|
|
2
|
+
module Playable
|
|
3
|
+
def w00t
|
|
4
|
+
self.health += 15
|
|
5
|
+
puts "#{name} got w00ted and gained 15 health!"
|
|
6
|
+
puts print_health_status
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def blam
|
|
10
|
+
self.health -= 10
|
|
11
|
+
puts "#{name} got blammed and lost 10 health!"
|
|
12
|
+
puts print_health_status
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def strong?
|
|
16
|
+
health >= 100
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require_relative 'treasure_trove'
|
|
2
|
+
require_relative 'playable'
|
|
3
|
+
require_relative 'printable'
|
|
4
|
+
|
|
5
|
+
module StudioGame
|
|
6
|
+
class Player
|
|
7
|
+
include Playable
|
|
8
|
+
include Printable
|
|
9
|
+
|
|
10
|
+
attr_accessor :name, :health
|
|
11
|
+
attr_reader :found_treasures
|
|
12
|
+
|
|
13
|
+
def initialize(name = "Player", health = 100)
|
|
14
|
+
@name = name.capitalize
|
|
15
|
+
@health = health
|
|
16
|
+
@found_treasures = Hash.new(0)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
"#{@name}'s health = #{@health} and score = #{score}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def name=(new_name)
|
|
24
|
+
@name = new_name.capitalize
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def <=>(other)
|
|
28
|
+
other.score <=> score
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def score
|
|
32
|
+
@health + points
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def points
|
|
36
|
+
@found_treasures.values.sum
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.from_csv(string)
|
|
40
|
+
name, health = string.split(',')
|
|
41
|
+
Player.new(name, Integer(health))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def find_treasure(treasure = TreasureTrove.random_treasure)
|
|
45
|
+
@found_treasures[treasure.name] += treasure.points
|
|
46
|
+
|
|
47
|
+
"#{@name} found a #{treasure.name} worth #{treasure.points} points"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if __FILE__==$0
|
|
53
|
+
#nameless = Player.new
|
|
54
|
+
larry = Player.new("larry")
|
|
55
|
+
#curly = Player.new("curly", 200)
|
|
56
|
+
|
|
57
|
+
puts larry
|
|
58
|
+
|
|
59
|
+
puts larry.blam
|
|
60
|
+
puts larry.print_health_status
|
|
61
|
+
|
|
62
|
+
puts larry.w00t
|
|
63
|
+
puts larry.print_health_status
|
|
64
|
+
|
|
65
|
+
larry.name = "lawrence"
|
|
66
|
+
puts larry
|
|
67
|
+
|
|
68
|
+
puts "#{larry.name}'s score is #{larry.score}"
|
|
69
|
+
|
|
70
|
+
puts larry.find_treasure
|
|
71
|
+
puts "#{larry.name} has found #{larry.found_treasures.size} treasure"
|
|
72
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require_relative 'formatting'
|
|
2
|
+
require_relative 'game_stats'
|
|
3
|
+
|
|
4
|
+
module StudioGame
|
|
5
|
+
module Printable
|
|
6
|
+
include Formatting
|
|
7
|
+
include GameStats
|
|
8
|
+
|
|
9
|
+
def print_health_status
|
|
10
|
+
"#{name} (#{health} health)"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def print_score
|
|
14
|
+
format_dot_spacing(name, score)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def print_treasure_trove
|
|
18
|
+
treasures = TreasureTrove::TREASURES
|
|
19
|
+
puts "\nThere are #{treasures.size} treasures to be found:"
|
|
20
|
+
|
|
21
|
+
treasures.each_with_index do |treasure, number|
|
|
22
|
+
puts "#{number + 1}. #{treasure}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def print_player_information
|
|
27
|
+
puts "\nThere are #{players.size} players in #{title}:"
|
|
28
|
+
|
|
29
|
+
players.each do |player|
|
|
30
|
+
puts player
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def print_treasures
|
|
35
|
+
puts "\n#{name}'s treasures:"
|
|
36
|
+
|
|
37
|
+
found_treasures.each do |name, points|
|
|
38
|
+
puts "#{points} total #{name} points"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
puts "#{name}'s total treasure points: #{points}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require_relative 'treasure'
|
|
2
|
+
|
|
3
|
+
module StudioGame
|
|
4
|
+
module TreasureTrove
|
|
5
|
+
TREASURES = [
|
|
6
|
+
Treasure.new("gold", 100),
|
|
7
|
+
Treasure.new("stamp", 30),
|
|
8
|
+
Treasure.new("pickaxe", 2),
|
|
9
|
+
Treasure.new("kindle", 50),
|
|
10
|
+
Treasure.new("ruby", 300),
|
|
11
|
+
Treasure.new("gem", 100)
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
def self.random_treasure
|
|
15
|
+
TREASURES.sample
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if __FILE__==$0
|
|
21
|
+
puts "#{TreasureTrove::TREASURES.size} Treasures in treasure trove:"
|
|
22
|
+
puts TreasureTrove::TREASURES
|
|
23
|
+
|
|
24
|
+
puts TreasureTrove.random_treasure
|
|
25
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'studio_game/berserk_player'
|
|
2
|
+
|
|
3
|
+
module StudioGame
|
|
4
|
+
describe "BerserkPlayer should" do
|
|
5
|
+
before do
|
|
6
|
+
# suppress test puts output only
|
|
7
|
+
$stdout = StringIO.new
|
|
8
|
+
|
|
9
|
+
@initial_health = 50
|
|
10
|
+
@player = BerserkPlayer.new("berserker", @initial_health)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "does not go berserk when w00ted up to 5 times" do
|
|
14
|
+
1.upto(5) { @player.w00t }
|
|
15
|
+
|
|
16
|
+
expect(@player).not_to be_berserk
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "goes berserk when w00ted more than 5 times" do
|
|
20
|
+
1.upto(6) { @player.w00t }
|
|
21
|
+
|
|
22
|
+
expect(@player).to be_berserk
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "gets w00ted instead of blammed when berserk" do
|
|
26
|
+
1.upto(6) { @player.w00t }
|
|
27
|
+
1.upto(2) { @player.blam }
|
|
28
|
+
|
|
29
|
+
expect(@player.health).to eq (@initial_health + (8 * 15))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'studio_game/clumsy_player'
|
|
2
|
+
|
|
3
|
+
module StudioGame
|
|
4
|
+
describe "ClumsyPlayer should" do
|
|
5
|
+
before do
|
|
6
|
+
# suppress test puts output only
|
|
7
|
+
$stdout = StringIO.new
|
|
8
|
+
|
|
9
|
+
@player = ClumsyPlayer.new("klutz")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "only get half the point value for each treasure found" do
|
|
13
|
+
hammer = Treasure.new(:hammer, 100)
|
|
14
|
+
half_hammer_points = 50
|
|
15
|
+
half_crowbar_points = 200
|
|
16
|
+
|
|
17
|
+
expect(@player.points).to eq(0)
|
|
18
|
+
|
|
19
|
+
@player.find_treasure(hammer)
|
|
20
|
+
@player.find_treasure(hammer)
|
|
21
|
+
@player.find_treasure(hammer)
|
|
22
|
+
|
|
23
|
+
expect(@player.points).to eq(half_hammer_points * 3)
|
|
24
|
+
|
|
25
|
+
crowbar = Treasure.new(:crowbar, 400)
|
|
26
|
+
@player.find_treasure(crowbar)
|
|
27
|
+
|
|
28
|
+
expect(@player.points).to eq((half_hammer_points * 3) + (half_crowbar_points))
|
|
29
|
+
|
|
30
|
+
expect(@player.found_treasures).to eq({hammer: 150, crowbar: 200})
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
require 'studio_game/game'
|
|
2
|
+
|
|
3
|
+
module StudioGame
|
|
4
|
+
describe "Game should" do
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
# suppress test puts output only
|
|
8
|
+
$stdout = StringIO.new
|
|
9
|
+
|
|
10
|
+
@game = Game.new
|
|
11
|
+
|
|
12
|
+
@larry = Player.new("larry")
|
|
13
|
+
@curly = Player.new("curly")
|
|
14
|
+
@moe = Player.new("moe")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "have a default title of 'Game'." do
|
|
18
|
+
expect(@game.title).to eq("Game")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "accept title change requests." do
|
|
22
|
+
@game.title = "scrabble"
|
|
23
|
+
expect(@game.title).to eq("Scrabble")
|
|
24
|
+
end
|
|
25
|
+
it "start with no players." do
|
|
26
|
+
expect(@game.players.size).to eq(0)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "add" do
|
|
30
|
+
it "one new player." do
|
|
31
|
+
@game.add_player(@larry)
|
|
32
|
+
|
|
33
|
+
first_players_name = @game.players[0].name
|
|
34
|
+
|
|
35
|
+
expect(@game.players.size).to eq(1)
|
|
36
|
+
expect(first_players_name).to eq(@larry.name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "two new players." do
|
|
40
|
+
@game.add_player(@larry)
|
|
41
|
+
@game.add_player(@curly)
|
|
42
|
+
|
|
43
|
+
second_players_name = @game.players[1].name
|
|
44
|
+
|
|
45
|
+
expect(@game.players.size).to eq(2)
|
|
46
|
+
expect(second_players_name).to eq(@curly.name)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "remove" do
|
|
51
|
+
before do
|
|
52
|
+
# Setup game so there are already players
|
|
53
|
+
@game.add_player(@larry)
|
|
54
|
+
@game.add_player(@curly)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "one player." do
|
|
58
|
+
@game.remove_player(@larry)
|
|
59
|
+
|
|
60
|
+
expect(@game.players.size).to eq(1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "two players (in a different order from added)." do
|
|
64
|
+
@game.remove_player(@curly)
|
|
65
|
+
@game.remove_player(@larry)
|
|
66
|
+
|
|
67
|
+
expect(@game.players.size).to eq(0)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "decide strategy based on a die roll, for example:" do
|
|
72
|
+
before do
|
|
73
|
+
@default_health = 100
|
|
74
|
+
@game.add_player(@larry)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "blam player when a high number like 5 or 6 is rolled." do
|
|
78
|
+
Die.any_instance.stub(:roll).and_return(5,6)
|
|
79
|
+
|
|
80
|
+
@game.play
|
|
81
|
+
|
|
82
|
+
expect(@larry.health).to eq(@default_health - 10)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "w00t player when a low number like 1 or 2 is rolled." do
|
|
86
|
+
Die.any_instance.stub(:roll).and_return(1,2)
|
|
87
|
+
|
|
88
|
+
@game.play
|
|
89
|
+
|
|
90
|
+
expect(@larry.health).to eq(@default_health + 15)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "Skip player when a medium number like 3 or 4 is rolled." do
|
|
94
|
+
Die.any_instance.stub(:roll).and_return(3,4)
|
|
95
|
+
|
|
96
|
+
@game.play
|
|
97
|
+
|
|
98
|
+
expect(@larry.health).to eq(@default_health)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "play" do
|
|
104
|
+
|
|
105
|
+
before do
|
|
106
|
+
# w00ts the player each round
|
|
107
|
+
Die.any_instance.stub(:roll).and_return(2)
|
|
108
|
+
|
|
109
|
+
@default_health = 100
|
|
110
|
+
|
|
111
|
+
@game.add_player(@larry)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "one round." do
|
|
115
|
+
@game.play
|
|
116
|
+
|
|
117
|
+
expect(@larry.health).to eq(@default_health + 15)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "two rounds." do
|
|
121
|
+
@game.play(2)
|
|
122
|
+
|
|
123
|
+
expect(@larry.health).to eq(@default_health + (15 * 2))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "ten rounds." do
|
|
127
|
+
@game.play(10)
|
|
128
|
+
|
|
129
|
+
expect(@larry.health).to eq(@default_health + (15 * 10))
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context "sort players" do
|
|
134
|
+
before do
|
|
135
|
+
# Setup initial health values (determines score)
|
|
136
|
+
strongest_starting_health = 300
|
|
137
|
+
strong_starting_health = 200
|
|
138
|
+
wimpy_starting_health = 50
|
|
139
|
+
|
|
140
|
+
# Start with several players
|
|
141
|
+
@tintin = Player.new("tintin", strongest_starting_health)
|
|
142
|
+
@gummy_bear = Player.new("gummy bear", strong_starting_health)
|
|
143
|
+
@pickle_rick = Player.new("pickle rick", wimpy_starting_health)
|
|
144
|
+
|
|
145
|
+
@players = [@gummy_bear, @pickle_rick, @tintin]
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "by highest to lowest score." do
|
|
149
|
+
expect(@players.sort).to eq([@tintin, @gummy_bear, @pickle_rick])
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "keep track of total player points" do
|
|
155
|
+
TreasureTrove.stub(:random_treasure).and_return(Treasure.new("ruby", 300))
|
|
156
|
+
@default_health = 100
|
|
157
|
+
|
|
158
|
+
@game.add_player(@larry)
|
|
159
|
+
@game.add_player(@curly)
|
|
160
|
+
|
|
161
|
+
@larry.find_treasure
|
|
162
|
+
@curly.find_treasure
|
|
163
|
+
|
|
164
|
+
expect(@game.total_points).to eq(300 * 2)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
end
|