my_text_game 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.
- data/bin/player_scores.csv +3 -0
- data/bin/players.csv +3 -0
- data/bin/text_game +23 -0
- data/lib/text_game/berserk_player.rb +30 -0
- data/lib/text_game/clumsy_player.rb +26 -0
- data/lib/text_game/die.rb +7 -0
- data/lib/text_game/game.rb +91 -0
- data/lib/text_game/game_logic.rb +14 -0
- data/lib/text_game/playable.rb +19 -0
- data/lib/text_game/player.rb +63 -0
- data/lib/text_game/treasure_trove.rb +16 -0
- data/spec/text_game/berserk_player_spec.rb +32 -0
- data/spec/text_game/game_spec.rb +67 -0
- data/spec/text_game/player_spec.rb +61 -0
- metadata +78 -0
data/bin/players.csv
ADDED
data/bin/text_game
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/text_game/game'
|
3
|
+
|
4
|
+
knuckleheads = TextGame::Game.new "knuckleheads"
|
5
|
+
default_player_file = File.join File.dirname(__FILE__), 'players.csv'
|
6
|
+
knuckleheads.load(ARGV.shift || default_player_file)
|
7
|
+
|
8
|
+
loop do
|
9
|
+
puts "\nHow many rounds? ('quit' to exit)"
|
10
|
+
answer = gets.chomp.downcase
|
11
|
+
case answer
|
12
|
+
when /^\d+$/
|
13
|
+
knuckleheads.play answer.to_i
|
14
|
+
when 'quit','exit','q'
|
15
|
+
knuckleheads.print_stats
|
16
|
+
knuckleheads.print_highscores
|
17
|
+
break
|
18
|
+
else
|
19
|
+
puts "Please enter a number or 'quit'"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
knuckleheads.save
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'player'
|
2
|
+
require_relative 'treasure_trove'
|
3
|
+
|
4
|
+
class BerserkPlayer < TextGame::Player
|
5
|
+
attr_reader :berserk
|
6
|
+
def initialize name, health=100
|
7
|
+
@berserk=false
|
8
|
+
@berserk_count=0
|
9
|
+
super name, health
|
10
|
+
end
|
11
|
+
def woot
|
12
|
+
@berserk_count+=1
|
13
|
+
@berserk = true if @berserk_count >=6
|
14
|
+
super
|
15
|
+
end
|
16
|
+
def blam
|
17
|
+
if @berserk
|
18
|
+
woot
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if __FILE__ == $0
|
26
|
+
berserker = BerserkPlayer.new "berserker", 50
|
27
|
+
6.times { berserker.woot }
|
28
|
+
2.times { berserker.blam }
|
29
|
+
puts berserker.health
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'player'
|
2
|
+
require_relative 'treasure_trove'
|
3
|
+
|
4
|
+
class ClumsyPlayer < TextGame::Player
|
5
|
+
def found_treasure treasure
|
6
|
+
@treasure_points[treasure.name] += treasure.points/2
|
7
|
+
puts "#{@name} found #{treasure.name} worth #{treasure.points/2}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
if __FILE__ == $0
|
12
|
+
clumsy = ClumsyPlayer.new "klutz"
|
13
|
+
|
14
|
+
hammer = Treasure.new(:hammer,50)
|
15
|
+
clumsy.found_treasure hammer
|
16
|
+
clumsy.found_treasure hammer
|
17
|
+
clumsy.found_treasure hammer
|
18
|
+
|
19
|
+
crowbar = Treasure.new :crowbar, 400
|
20
|
+
clumsy.found_treasure crowbar
|
21
|
+
|
22
|
+
clumsy.each_treasure do |treasure|
|
23
|
+
puts "#{treasure.points} of #{treasure.name}"
|
24
|
+
end
|
25
|
+
puts "#{clumsy.points_accumulated} grand total points"
|
26
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative 'player'
|
2
|
+
require_relative 'die'
|
3
|
+
require_relative 'game_logic'
|
4
|
+
require_relative 'treasure_trove'
|
5
|
+
|
6
|
+
module TextGame
|
7
|
+
class Game
|
8
|
+
def initialize name
|
9
|
+
@name = name.capitalize
|
10
|
+
@players = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_player player
|
14
|
+
@players.push player
|
15
|
+
end
|
16
|
+
|
17
|
+
def play rounds=1
|
18
|
+
puts "There are #{@players.size} players in #{@name}"
|
19
|
+
puts @players.sort
|
20
|
+
|
21
|
+
treasures = TreasureTrove::TREASURES
|
22
|
+
puts "\nThere are #{treasures.size} treasures available in the trove"
|
23
|
+
|
24
|
+
treasures.each { |treasure| puts "#{treasure.name.capitalize} has #{treasure.points} points."}
|
25
|
+
|
26
|
+
rounds.times do |count|
|
27
|
+
puts "\nRound #{count+1}"
|
28
|
+
#game round
|
29
|
+
@players.each do |player|
|
30
|
+
GameLogic.check player
|
31
|
+
treasure = TreasureTrove.random
|
32
|
+
player.found_treasure treasure
|
33
|
+
puts player
|
34
|
+
end
|
35
|
+
#@players.each { |player| puts player}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def load file_name
|
40
|
+
File.readlines(file_name).each do |line|
|
41
|
+
add_player Player.from_csv(line)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def save to_file="player_scores.csv"
|
46
|
+
File.open(to_file,"w") do |file|
|
47
|
+
@players.sort.each do |player|
|
48
|
+
file.puts player.to_csv
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def total_points_accumulated
|
54
|
+
@players.reduce(0) { |sum, player| sum + player.points_accumulated }
|
55
|
+
end
|
56
|
+
|
57
|
+
def print_stats
|
58
|
+
puts "\n#{@name} Statistics:"
|
59
|
+
|
60
|
+
puts "#{total_points_accumulated} total points accumulated"
|
61
|
+
|
62
|
+
@players.sort.each do |player|
|
63
|
+
puts "\n#{player.name}'s point totals:"
|
64
|
+
|
65
|
+
player.each_treasure do |treasure|
|
66
|
+
puts "#{treasure.name} worth #{treasure.points} points"
|
67
|
+
end
|
68
|
+
|
69
|
+
puts "#{player.points_accumulated} grand total points"
|
70
|
+
end
|
71
|
+
|
72
|
+
strong, weak = @players.partition { |player| player.strong?}
|
73
|
+
|
74
|
+
puts "\nStrong:"
|
75
|
+
puts strong.sort
|
76
|
+
|
77
|
+
puts "\nWeak:"
|
78
|
+
puts weak.sort
|
79
|
+
end
|
80
|
+
|
81
|
+
def print_highscores
|
82
|
+
puts "\n#{@name} High Scores:"
|
83
|
+
sorted = @players.sort
|
84
|
+
|
85
|
+
sorted.each do |player|
|
86
|
+
puts "#{player.name}".ljust(30,'.')+"#{player.score}"
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Playable
|
2
|
+
def strong?
|
3
|
+
self.health >= 100
|
4
|
+
end
|
5
|
+
|
6
|
+
def <=> other
|
7
|
+
other.score <=> score
|
8
|
+
end
|
9
|
+
|
10
|
+
def blam
|
11
|
+
self.health-=10
|
12
|
+
puts "#{self.name} got blammed!"
|
13
|
+
end
|
14
|
+
|
15
|
+
def woot
|
16
|
+
self.health+=15
|
17
|
+
puts "#{self.name} got wooted!"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative 'playable'
|
2
|
+
|
3
|
+
module TextGame
|
4
|
+
class Player
|
5
|
+
include Playable
|
6
|
+
attr_reader :score
|
7
|
+
attr_accessor :health,:name
|
8
|
+
def initialize name,health=100
|
9
|
+
@name = name.capitalize
|
10
|
+
@health = health
|
11
|
+
@treasure_points = Hash.new 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_csv line
|
15
|
+
name, health = line.split(',')
|
16
|
+
Player.new name,Integer(health)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_csv
|
20
|
+
"#{@name},#{score}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def name= name
|
24
|
+
@name = name.capitalize
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"I'm #{@name} with a health of #{@health} and a score of #{score}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def score
|
32
|
+
@health+points_accumulated
|
33
|
+
end
|
34
|
+
|
35
|
+
def points_accumulated
|
36
|
+
@treasure_points.values.reduce(0,:+)
|
37
|
+
end
|
38
|
+
|
39
|
+
def each_treasure
|
40
|
+
@treasure_points.each do |name, points|
|
41
|
+
treasure = Treasure.new name, points
|
42
|
+
yield treasure
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def found_treasure treasure
|
47
|
+
@treasure_points[treasure.name] += treasure.points
|
48
|
+
puts "#{@name} found #{treasure.name} worth #{treasure.points}"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
if __FILE__ == $0
|
54
|
+
player = Player.new "mark", 100
|
55
|
+
puts player
|
56
|
+
puts player.health
|
57
|
+
puts player.score
|
58
|
+
|
59
|
+
player.name="bob"
|
60
|
+
player.blam
|
61
|
+
puts player
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Treasure = Struct.new(:name,:points)
|
2
|
+
|
3
|
+
module TreasureTrove
|
4
|
+
TREASURES = [
|
5
|
+
pie = Treasure.new(:pie,5),
|
6
|
+
bottle = Treasure.new(:bottle,25),
|
7
|
+
hammer = Treasure.new(:hammer,50),
|
8
|
+
skillet = Treasure.new(:skillet,100),
|
9
|
+
broomstick = Treasure.new(:broomstick,200),
|
10
|
+
crowbar = Treasure.new(:crowbar,400)
|
11
|
+
]
|
12
|
+
|
13
|
+
def self.random
|
14
|
+
TREASURES.sample
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'text_game/berserk_player'
|
2
|
+
|
3
|
+
#To avoid output from method invocations being displayed to console
|
4
|
+
$stdout = StringIO.new
|
5
|
+
|
6
|
+
module TextGame
|
7
|
+
describe BerserkPlayer do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@initial_health = 50
|
11
|
+
@player = BerserkPlayer.new "berserker", @initial_health
|
12
|
+
end
|
13
|
+
|
14
|
+
it "does not go berserk when wooted up to 5 times" do
|
15
|
+
5.times { @player.woot }
|
16
|
+
@player.berserk.should == false
|
17
|
+
end
|
18
|
+
|
19
|
+
it "goes berserk when wooted more than 5 times" do
|
20
|
+
6.times { @player.woot }
|
21
|
+
@player.berserk.should == true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "gets wooted instead of blammed when it's gone berserk" do
|
25
|
+
6.times { @player.woot }
|
26
|
+
@player.blam
|
27
|
+
#health should be at 155
|
28
|
+
@player.health.should == 155
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'text_game/game'
|
2
|
+
|
3
|
+
$stdout = StringIO.new
|
4
|
+
|
5
|
+
module TextGame
|
6
|
+
describe Game do
|
7
|
+
it "computes total points as the sum of all player points" do
|
8
|
+
game = Game.new("Knuckleheads")
|
9
|
+
|
10
|
+
player1 = Player.new("moe")
|
11
|
+
player2 = Player.new("larry")
|
12
|
+
|
13
|
+
game.add_player(player1)
|
14
|
+
game.add_player(player2)
|
15
|
+
|
16
|
+
player1.found_treasure(Treasure.new(:hammer, 50))
|
17
|
+
player1.found_treasure(Treasure.new(:hammer, 50))
|
18
|
+
player2.found_treasure(Treasure.new(:crowbar, 400))
|
19
|
+
|
20
|
+
game.total_points_accumulated.should == 500
|
21
|
+
end
|
22
|
+
|
23
|
+
before do
|
24
|
+
@game = Game.new "knuckleheads"
|
25
|
+
|
26
|
+
@initial_health = 100
|
27
|
+
@player = Player.new "moe", @initial_health
|
28
|
+
|
29
|
+
@game.add_player @player
|
30
|
+
end
|
31
|
+
|
32
|
+
context "is being played with one player" do
|
33
|
+
it "has blammed the player" do
|
34
|
+
Die.any_instance.stub(:roll).and_return(5)
|
35
|
+
@game.play
|
36
|
+
@player.health.should == @initial_health + 15
|
37
|
+
end
|
38
|
+
|
39
|
+
it "has skipped the player" do
|
40
|
+
Die.any_instance.stub(:roll).and_return(3)
|
41
|
+
@game.play
|
42
|
+
@player.health.should == @initial_health
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has wooted the player" do
|
46
|
+
Die.any_instance.stub(:roll).and_return(1)
|
47
|
+
@game.play
|
48
|
+
@player.health.should == @initial_health - 10
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with a collection of players" do
|
53
|
+
before do
|
54
|
+
@player1 = Player.new "moe", 100
|
55
|
+
@player2 = Player.new "larry", 200
|
56
|
+
@player3 = Player.new "curly", 300
|
57
|
+
|
58
|
+
@players = [@player1,@player2,@player3]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "is sorted by decreasing score" do
|
62
|
+
@players.sort.should == [@player3,@player2,@player1]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'text_game/player'
|
2
|
+
|
3
|
+
#To avoid output from method invocations being displayed to console
|
4
|
+
$stdout = StringIO.new
|
5
|
+
|
6
|
+
module TextGame
|
7
|
+
describe Player do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@player = Player.new "mark", 100
|
11
|
+
@initial_health = 100
|
12
|
+
end
|
13
|
+
|
14
|
+
it "has a capitalized name" do
|
15
|
+
@player.name.should == "Mark"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "has an initial health" do
|
19
|
+
@player.health.should == 100
|
20
|
+
end
|
21
|
+
|
22
|
+
it "has a string representation" do
|
23
|
+
@player.to_s == "I'm Mark with a health of 100 and a score of 104"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "computes a score as the sum of its health and length of name" do
|
27
|
+
@player.score == 104
|
28
|
+
end
|
29
|
+
|
30
|
+
it "increases health by 15 when wooted" do
|
31
|
+
@player.woot
|
32
|
+
@player.health.should == 115
|
33
|
+
end
|
34
|
+
|
35
|
+
it "decreases health by 10 when blammed" do
|
36
|
+
@player.blam
|
37
|
+
@player.health.should == 90
|
38
|
+
end
|
39
|
+
|
40
|
+
context "has a starting health of 150" do
|
41
|
+
before do
|
42
|
+
@player = Player.new "mark", 150
|
43
|
+
end
|
44
|
+
|
45
|
+
it "is strong" do
|
46
|
+
@player.should be_strong
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
context "has a starting health of 99" do
|
52
|
+
before do
|
53
|
+
@player = Player.new "mark", 99
|
54
|
+
end
|
55
|
+
|
56
|
+
it "is weak" do
|
57
|
+
@player.should_not be_strong
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: my_text_game
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mark Yanaros
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
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
|
+
description: File.read(File.join(File.dirname(__FILE__), 'README'))
|
31
|
+
email: mark.yanaros@gmail.com
|
32
|
+
executables:
|
33
|
+
- text_game
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- bin/player_scores.csv
|
38
|
+
- bin/players.csv
|
39
|
+
- bin/text_game
|
40
|
+
- lib/text_game/berserk_player.rb
|
41
|
+
- lib/text_game/clumsy_player.rb
|
42
|
+
- lib/text_game/die.rb
|
43
|
+
- lib/text_game/game.rb
|
44
|
+
- lib/text_game/game_logic.rb
|
45
|
+
- lib/text_game/playable.rb
|
46
|
+
- lib/text_game/player.rb
|
47
|
+
- lib/text_game/treasure_trove.rb
|
48
|
+
- spec/text_game/berserk_player_spec.rb
|
49
|
+
- spec/text_game/game_spec.rb
|
50
|
+
- spec/text_game/player_spec.rb
|
51
|
+
homepage: ''
|
52
|
+
licenses: []
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.9'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.25
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Plays a game and displays results.
|
75
|
+
test_files:
|
76
|
+
- spec/text_game/berserk_player_spec.rb
|
77
|
+
- spec/text_game/game_spec.rb
|
78
|
+
- spec/text_game/player_spec.rb
|