Ruby_Dice 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b9b75ef4c4911ce1114a5f5fc95bd85dedeef93c
4
+ data.tar.gz: 208d27f1d71d807e2be51f966dd2260f41da09e5
5
+ SHA512:
6
+ metadata.gz: 5df78bac00770e5ec9b1b5d7e2bbc1bdf2a10e4bc35d337a2a4794f0c703c1e36cb26f12e2b93de7d12e2682afc9f9c7225adc432a4f5c3346f898878c87fdc6
7
+ data.tar.gz: 81850e8ce27a0f54bfbf74abdf3402832faaf4eaee53a0c3b08f253ba9dec64432d9ca3609d997641406bdd3aa05bdd7f2acc258c8ce97fb1f8a7174f2bd48a1
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Mario Martinez and Zachary Perlmutter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # Ruby_Dice
2
+ A Yahtzee clone written in Ruby that runs in the terminal
3
+
4
+ This project is a personal project for educational purposes and becoming accustomed to the Ruby programming paradigm. Furthermore, it's to become accustomed to the Git workflow. Contributions are most welcome!
5
+ ## Badges
6
+ [![Inline docs](http://inch-ci.org/github/martimatix/Ruby-Dice.svg?branch=master)](http://inch-ci.org/github/martimatix/Ruby-Dice)
7
+ [![Code Climate](https://codeclimate.com/github/martimatix/Ruby-Dice/badges/gpa.svg)](https://codeclimate.com/github/martimatix/Ruby-Dice)
8
+ [![Build Status](https://travis-ci.org/martimatix/Ruby-Dice.svg)](https://travis-ci.org/martimatix/Ruby-Dice)
9
+ [![Test Coverage](https://codeclimate.com/github/martimatix/Ruby-Dice/badges/coverage.svg)](https://codeclimate.com/github/martimatix/Ruby-Dice)
10
+ ## Docs
11
+ * [rubydoc.info](http://www.rubydoc.info/github/martimatix/Ruby-Dice/master)
data/bin/Ruby_Dice ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ BEGIN {
3
+ if ARGV.include? "-h"
4
+ puts <<HELP
5
+ Usage: $ Ruby_Dice [--help]
6
+ \u00B7 --help -> Displays this help message
7
+
8
+ Gameplay:
9
+ Abbreviations:
10
+ \u00B7 1 -> Ones
11
+ \u00B7 2 -> Twos
12
+ \u00B7 3 -> Threes
13
+ \u00B7 4 -> Fours
14
+ \u00B7 5 -> Fives
15
+ \u00B7 6 -> Sixes
16
+ \u00B7 ss -> Small Straight
17
+ \u00B7 ls -> Large Straight
18
+ \u00B7 tok -> Three Of A Kind
19
+ \u00B7 fok -> Four Of A Kind
20
+ \u00B7 fh -> Full House
21
+ \u00B7 y -> Yahtzee
22
+ \u00B7 ? -> chance
23
+ HELP
24
+ exit
25
+ end
26
+ }
27
+
28
+ require "Ruby_Dice"
29
+
30
+ user = Player.new
31
+
32
+ until user.score.filled? do
33
+ puts ?\n
34
+ puts "New Turn".center(80)
35
+ puts ?\n
36
+ sleep 0.5
37
+ user.take_turn
38
+ end
data/lib/Ruby_Dice.rb ADDED
@@ -0,0 +1,4 @@
1
+ autoload :Dice, "dice"
2
+ autoload :Player, "player"
3
+ autoload :ScoreSheet, "scoresheet"
4
+ autoload :Scoring, "scoring"
data/lib/dice.rb ADDED
@@ -0,0 +1,59 @@
1
+ class Dice # Class for working with the 5 dice at the same time
2
+
3
+ attr_reader :values # @return [Array] the dice.
4
+
5
+ def initialize(values=Array.new(5) {new_dice}) # @param values [Array<Fixnum>] that contains 5 Fixnums
6
+ check_dice values
7
+ @values = values
8
+ end
9
+
10
+ # @!group Roll Methods
11
+
12
+ =begin
13
+ @raise [ArgumentError] if i element > 4
14
+ @return [void]
15
+ @param i [Array<Fixnum>] < 4
16
+ =end
17
+ def roll(dice_to_roll)
18
+ for index in dice_to_roll
19
+ raise ArgumentError, "Illegal index" if index > 4
20
+ @values[index] = new_dice
21
+ end
22
+ end
23
+
24
+ =begin
25
+ @note Rolls all the dice
26
+
27
+ @return [void]
28
+ =end
29
+ def roll_all; initialize; end
30
+
31
+ # @!endgroup
32
+
33
+ def to_s # @return [String] instance variable dice
34
+ print @values
35
+ end
36
+ alias display to_s
37
+
38
+ =begin
39
+ @param values [Array<Integer>]
40
+ @see (#check_dice)
41
+ @note setting dice for values for testing
42
+ @!parse attr_writer :values
43
+ =end
44
+ def values=(values)
45
+ check_dice values
46
+ @values = values
47
+ end
48
+
49
+ private
50
+ def new_dice; return (1..6).to_a.sample; end # @return [Fixnum] a random number between 1 and 6, inclusive
51
+ =begin
52
+ @param dice [Array<Fixnum>]
53
+ @return [void]
54
+ @raise [ArgumentError] if dice does not meet expectations
55
+ =end
56
+ def check_dice(dice)
57
+ raise(ArgumentError, "Array must have 5 Integers that are between 1 and 6") unless dice.length == 5 && dice.all? {|val| (val.is_a? Fixnum) && (val.between? 1,6)}
58
+ end
59
+ end
data/lib/player.rb ADDED
@@ -0,0 +1,90 @@
1
+ require_relative "scoresheet.rb"
2
+ require 'set'
3
+
4
+ class Player
5
+
6
+ ScoreAbbr = { # Abbreviations used in-game
7
+ ?1.to_sym => :ones,
8
+ ?2.to_sym => :twos,
9
+ ?3.to_sym => :threes,
10
+ ?4.to_sym => :fours,
11
+ ?5.to_sym => :fives,
12
+ ?6.to_sym => :sixes,
13
+ ss: :small_straight,
14
+ ls: :large_straight,
15
+ tok: :three_of_a_kind,
16
+ fok: :four_of_a_kind,
17
+ fh: :full_house,
18
+ y: :yahtzee,
19
+ "?".to_sym => :chance
20
+ }
21
+
22
+ attr_reader :score # @return [ScoreSheet]
23
+
24
+ def initialize
25
+ @score = ScoreSheet.new
26
+ end
27
+
28
+ =begin
29
+ @todo finish method
30
+ @return [void]
31
+ =end
32
+ def take_turn
33
+ turn_over = false
34
+ (1..3).each do |i|
35
+ display_dice i
36
+ turn_over = user_input i
37
+ break if turn_over
38
+ end
39
+ end
40
+
41
+ def display_dice(i)
42
+ sleep 0.5
43
+ puts String.new.center(80, ?-)
44
+ puts "Here are your dice. You have have #{3-i} #{i==2? "roll":"rolls"} remaining.\n\n"
45
+ puts "\tDice\t\tZ\tX\tC\tV\tB"
46
+ puts "\tValues\t\t" + score.dice.values.map{|value| value.to_s}.join(?\t)
47
+ puts String.new.center(80, ?-)
48
+ end
49
+
50
+ =begin
51
+ @param i [Fixnum] Amount of times rolled
52
+ @return [Boolean]
53
+ @note Gameplay
54
+ =end
55
+ def user_input(i)
56
+ if i < 3
57
+ print "Select dice to re-roll or select a score category: "
58
+ else
59
+ print "No rolls remaining. Select a score category: "
60
+ end
61
+ input = gets.chomp.downcase
62
+ input_symbol = input.to_sym
63
+ user_input = Set.new(input.split(''))
64
+ dice_controls = Set.new("zxcvb".split(''))
65
+
66
+ # If user wants to enter score
67
+ if ScoreAbbr.keys.include? input_symbol
68
+ score.enter_score ScoreAbbr[input_symbol]
69
+ puts score
70
+ @score.dice.roll_all
71
+ sleep 2
72
+ return true
73
+ # Else if user wants to roll the dice
74
+ elsif i < 3 && (user_input.subset? dice_controls)
75
+ dice_to_roll = (0..4).to_a.select { |index| input.include? dice_controls.to_a[index]}
76
+ @score.dice.roll(dice_to_roll)
77
+ sleep 0.5
78
+ 2.times {puts ?\n}
79
+ puts " Rolling Dice!\ ".center 80, "* "
80
+ sleep 1
81
+ return false
82
+ else
83
+ puts "Invalid input. Please try again."
84
+ sleep 1.5
85
+ puts ?\n
86
+ user_input i
87
+ end
88
+ end
89
+ end
90
+
data/lib/scoresheet.rb ADDED
@@ -0,0 +1,156 @@
1
+ require_relative "dice.rb"
2
+ require_relative "scoring.rb"
3
+
4
+ class ScoreSheet # Keeps score throughout the game
5
+ include Scoring
6
+
7
+ UpperScores = :ones, :twos, :threes, :fours, :fives, :sixes # The fields on the top section of the score sheet
8
+
9
+ LowerScores = :three_of_a_kind, :four_of_a_kind, :full_house, :small_straight, :large_straight, :chance, :yahtzee # The fields on the bottom section of the score sheet
10
+
11
+ attr_reader :sheet # @return [Hash] table of two element arrays where the first value is the score and the second is whether the field has been played
12
+ attr_reader :dice # @return [Dice]
13
+ attr_reader :num_yahtzees # @return [Fixnum] counter for number of yahtzees scored in the game
14
+ =begin
15
+ @param custom_dice [Array<Fixnum>] custom dice for testing
16
+ =end
17
+ def initialize(custom_dice=Array.new(5) {Dice.new.instance_eval "new_dice"})
18
+ @sheet, @dice, @num_yahtzees = Hash.new, Dice.new(custom_dice), 0
19
+ Array.new(UpperScores).concat(LowerScores).each {|s| @sheet[s] = [0, false]}
20
+ end
21
+
22
+ =begin
23
+ @param field [Symbol]
24
+ @return [void]
25
+ @raise ArgumentError
26
+ =end
27
+ def enter_score(field)
28
+ if field == :yahtzee && ((available :yahtzee) || @num_yahtzees > 0)
29
+ @sheet[field] = yahtzee, true
30
+ elsif available field
31
+ @sheet[field] = send(field, @dice.values), true
32
+ else
33
+ raise ArgumentError, "Score already entered."
34
+ end
35
+ end
36
+
37
+ =begin
38
+ @return [true] if the score sheet is completely filled and no legal moves remain
39
+ @return [false] if the score sheet is not completely filled and there are still legal moves to be made
40
+ =end
41
+ def filled?
42
+ @sheet.collect{|k,v| v[1]}.reduce{|r,e| r && e}
43
+ end
44
+
45
+ def raw_upper # @return [Fixnum]
46
+ @sheet.select{|x| UpperScores.include? x }.collect{|k,v| v[0]}.reduce :+
47
+ end
48
+
49
+ def upper_score_total # @return [Fixnum] the total score of the upper part of the ScoreSheet, including bonuses
50
+ raw_upper + upper_score_bonus
51
+ end
52
+ def lower_score_total # @return [Integer] The total score of the lower part of the ScoreSheet
53
+ @sheet.select{|x| LowerScores.include? x }.collect{|k,v| v[0]}.reduce :+
54
+ end
55
+ def total # @return [Integer] the grand total
56
+ lower_score_total + upper_score_total
57
+ end
58
+
59
+
60
+
61
+ =begin
62
+ Checks if upper score bonus can be awarded
63
+ @return [Fixnum] 0 if raw_upper < 63
64
+ @return [Fixnum] 35 if raw_upper >= 63
65
+ =end
66
+ def upper_score_bonus
67
+ if raw_upper >= 63 then 35
68
+ else
69
+ 0
70
+ end
71
+ end
72
+ =begin
73
+ @return [Fixnum]
74
+ Checks to see if you have all the of the same dice
75
+ =end
76
+ def yahtzee
77
+ if dice.values.all? {|x| x == dice.values[0]}
78
+ @num_yahtzees += 1
79
+ return sheet[:yahtzee][0] + 50 * 2 ** (@num_yahtzees - 1)
80
+ else
81
+ return 0
82
+ end
83
+ end
84
+
85
+ =begin
86
+ @todo Find a less complex way to create final string
87
+ @return [String]
88
+
89
+ =end
90
+ def to_s
91
+ ss = String.new
92
+ ss += %Q( S C O R E S H E E T ).center(80, ?=) + "\n\n"
93
+ (0..(UpperScores.length - 1)).each { |i| ss += print_score_sheet_line(i) }
94
+ ss += bonus_yahtzee_line
95
+ ss += "\n\n"
96
+ ss += "Total Score: #{total}".center(80) + ?\n
97
+ ss += (?= * 80) + ?\n
98
+ return ss
99
+ end
100
+
101
+
102
+ private # Helper methods
103
+
104
+ def available (field)
105
+ @sheet[field][1] == false
106
+ end
107
+
108
+ def score_sheet_line(left_val, right_val)
109
+ (left_val + "\t\t" + right_val).center(68) + ?\n
110
+ end
111
+ alias ssl score_sheet_line
112
+
113
+ def print_score_sheet_line(i);
114
+ upper, lower = format_score(UpperScores, i), format_score(LowerScores, i)
115
+ ssl upper, lower
116
+ end
117
+
118
+
119
+ def bonus_yahtzee_line
120
+ bonus_string, yahtzee_string = justify_score("Bonus", upper_score_bonus.to_s), format_score(LowerScores, LowerScores.length - 1)
121
+ ssl bonus_string, yahtzee_string
122
+ end
123
+ alias byl bonus_yahtzee_line
124
+ =begin
125
+ @return [String] the formatted string
126
+ @param index [Fixnum]
127
+ @param score_region [String, Array<String>]
128
+ Replace underscores with spaces
129
+ =end
130
+ def format_score(score_region, index)
131
+ score_label = "#{score_region[index]}".tr(?_, " ")
132
+ cap_label score_label
133
+ score_field = @sheet[score_region[index]]
134
+ return justify_score(score_label, "#{score_field[1]? score_field[0]:?-}")
135
+ end
136
+
137
+ def justify_score(label, score)
138
+ label.ljust(20) + score.rjust(3)
139
+ end
140
+
141
+ =begin
142
+ @param score_label [String]
143
+ @return [String]
144
+ Capitalize each letter of each word only if the score label has two words
145
+ Else only capitalize the first letter of the score label
146
+ =end
147
+ def cap_label(score_label)
148
+ if score_label.split.length == 2
149
+ score_label = score_label.split.map(&:capitalize)*' '
150
+ else
151
+ score_label.capitalize!
152
+ end
153
+ end
154
+ public
155
+ alias display to_s
156
+ end
data/lib/scoring.rb ADDED
@@ -0,0 +1,145 @@
1
+ require_relative "dice.rb"
2
+
3
+ module Scoring # methods for calculating score
4
+
5
+ UpperScores = :ones, :twos, :threes, :fours, :fives, :sixes # The fields on the top section of the score sheet
6
+
7
+ LowerScores = :three_of_a_kind, :four_of_a_kind, :full_house, :small_straight, :large_straight, :chance, :yahtzee # The fields on the bottom section of the score sheet
8
+
9
+ =begin
10
+ Checks to see if you have 3 of one kind of dice and 2 of another
11
+ @return [Fixnum] 25 if @dice.dice contains 3 of one Fixnum and 2 of another
12
+ @return [Fixnum] 0 if @dice.dice does not contain 3 of one Fixnum and 2 of another
13
+ =end
14
+ def full_house(dice)
15
+ f_table = freq dice
16
+ if (f_table.length == 2 && f_table.has_value?(3)) || f_table.length == 1 then return 25
17
+ else; return 0
18
+ end
19
+ end
20
+
21
+ =begin
22
+ Checks to see if you have 4 of the same dice
23
+ @return [Fixnum] 0 if <= 4 indices have the same value
24
+ @return [Fixnum] dice.reduce(:+) if >= 4 indices have the same value
25
+ @see (#three_of_a_kind)
26
+ =end
27
+ def four_of_a_kind(dice)
28
+ of_a_kind dice, 4
29
+ end
30
+
31
+ =begin
32
+ @param d [Array<Fixnum>] the dice to be tested
33
+ @return [Fixnum] the score
34
+ =end
35
+ def ones(d)
36
+ single_face d, 1
37
+ end
38
+
39
+ def twos(d) # @see (#ones)
40
+ single_face d, 2
41
+ end
42
+
43
+ def threes(d) # @see (#ones)
44
+ single_face d, 3
45
+ end
46
+
47
+ def fours(d) # @see (#ones)
48
+ single_face d, 4
49
+ end
50
+
51
+ def fives(d) # @see (#ones)
52
+ single_face d, 5
53
+ end
54
+
55
+ def sixes(d) # @see (#ones)
56
+ single_face d, 6
57
+ end
58
+
59
+ =begin
60
+ @see (#four_of_a_kind)
61
+ Checks to see if you have 3 of the same dice
62
+ @return [Fixnum] dice.reduce(:+) if there is <= 3 of the same value
63
+ @return [Fixnum] 0 if you do not have a three of a kind
64
+ =end
65
+ def three_of_a_kind(dice)
66
+ of_a_kind dice, 3
67
+ end
68
+
69
+ =begin
70
+ @param dice [Array<Fixnum>] the dice to be evaluated
71
+ @return [Fixnum] the sum of all the dice
72
+ =end
73
+ def chance(dice)
74
+ dice.reduce :+
75
+ end
76
+
77
+ =begin
78
+ @param dice [Array<Fixnum>] the dice to be tested
79
+ @return [Fixnum] 30 if there are 3 consecutive Fixnums in dice
80
+ @return [Fixnum] 0 if there are not three conscecutive Fixnums in dice
81
+ @see (#large_straight)
82
+ =end
83
+ def small_straight(dice)
84
+ straight dice, 4, 30
85
+ end
86
+ alias SS small_straight
87
+
88
+ =begin
89
+ @param dice [Array<Fixnum>] the dice to be tested
90
+ @return [Fixnum] 40 if there are 4 consecutive Fixnums in dice
91
+ @return [Fixnum] 0 if there are not three conscecutive Fixnums in dice
92
+ @see (#small_straight)
93
+ =end
94
+ def large_straight(dice)
95
+ straight dice, 5, 40
96
+ end
97
+ alias LS large_straight
98
+
99
+ private # Helper methods for score calculation
100
+
101
+ def single_face(dice, value)
102
+ v = dice.select{|number| number == value}.reduce :+
103
+ unless v.nil?
104
+ return v
105
+ else
106
+ return 0
107
+ end
108
+ end
109
+
110
+ def freq(dice)
111
+ dice.inject(Hash.new(0)) { |h,v| h[v] += 1; h }
112
+ end
113
+
114
+ def modal_frequency(dice)
115
+ freq(dice).max_by{|k,v| v}[1]
116
+ end
117
+
118
+ def of_a_kind(dice, limit)
119
+ if modal_frequency(dice) >= limit
120
+ dice.reduce :+
121
+ else
122
+ 0
123
+ end
124
+ end
125
+
126
+ =begin
127
+ @param dice [Fixnum] the dice to be tested
128
+ @param limit [Fixnum] = 4 for small straight
129
+ @param limit [Fixnum] = 5 for large straight
130
+ common code for both small straight (SS) and large straight (LS)
131
+ @param score [Fixnum] is the score to return
132
+ @return [Fixnum] score
133
+ =end
134
+ def straight(dice, limit, score)
135
+ #each_cons is generating every possible value for a straight of length limit
136
+ (1..6).each_cons(limit).each do |i|
137
+ # Asking if i is a subset of dice
138
+ if (i - dice).empty?
139
+ return score if (i - dice)
140
+ end
141
+ end
142
+ return 0
143
+ end
144
+
145
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Ruby_Dice
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Zachary Perlmutter
8
+ - Mario Martinez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-12-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '3.1'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '3.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec-its
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: |
43
+ This project is a personal project for educational purposes and becoming accustomed to the Ruby programming paradigm.
44
+ Furthermore, it's to become accustomed to the Git workflow.
45
+ Contributions are most welcome!
46
+ email:
47
+ - zrp200@gmail.com
48
+ - zenitram.oiram@gmail.com
49
+ executables:
50
+ - Ruby_Dice
51
+ extensions: []
52
+ extra_rdoc_files:
53
+ - LICENSE.md
54
+ - README.md
55
+ files:
56
+ - LICENSE.md
57
+ - README.md
58
+ - bin/Ruby_Dice
59
+ - lib/Ruby_Dice.rb
60
+ - lib/dice.rb
61
+ - lib/player.rb
62
+ - lib/scoresheet.rb
63
+ - lib/scoring.rb
64
+ homepage:
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements:
83
+ - terminal
84
+ rubyforge_project:
85
+ rubygems_version: 2.4.5
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: A Yahtzee clone written in Ruby that runs in the terminal
89
+ test_files: []