rpg_tools 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0316fd1f6aea96942849150e125d95ea05a96411
4
+ data.tar.gz: 47f8012ecda7a42111f22a6bac44d65b5bb9016c
5
+ SHA512:
6
+ metadata.gz: 556a6f049b6cbc5139c7ce4e56afd80efe981041534bfca5fb6a0fbfcdec5fb14efed10a477d3900c8b322f2121c2c2042cfa35e9817ff413fe12a48581ae0dc
7
+ data.tar.gz: 47dcde8a0c5227093b35e8c421e3a2958eff4beee3c94e21a94be3dd8ff1500a808e2c313dfcec4834d85cce1b8b6a8fe6367a6e56f2047eb70a46093ab67d14
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Yohan Piron
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,58 @@
1
+ rpg_tools [![Dependency Status](https://gemnasium.com/Yinfei/rpg_tools.svg)](https://gemnasium.com/Yinfei/rpg_tools) ![](https://circleci.com/gh/Yinfei/rpg_tools.svg?&style=shield&circle-token=f5153100f0a56438602b915cf95d80f1e6e0edca)
2
+ =======
3
+
4
+ A gem that gives you tools for your RPGs : dices, coins and playing cards !
5
+
6
+ ## Usage
7
+
8
+ ### Coins
9
+
10
+ `RpgTools::Coin.new`
11
+
12
+ * The `flip` method set its value to a `heads` or `tails` string.
13
+
14
+ ### Dices
15
+
16
+ `RpgTools.roll_dice(arg)` <i>(`arg` is case insensitive)</i>.
17
+
18
+ This returns a plain integer result based on the `arg` parameter.
19
+
20
+ * It can be a stardard dice like `"1dX"` for a X sided dice.
21
+
22
+ * It can be a fudge dice `"df"` : a three sided dice (-1, 0, +1).
23
+
24
+ * It can also be a percentile dice `"d%"` : a ten sided dice (from 10 to 100).
25
+
26
+ You can also add multiple chained modifiers like "+X", "-X", "*X" or "/X", to alter the roll result. `RpgTools.roll_dice("4d6+2")` will create 4 6-sided dices, roll them and add 2 to the sum of the roll result.
27
+
28
+ You can also manipulate all those dice types as objects :
29
+
30
+ * `RpgTools::Dice::Numerical`
31
+ * `RpgTools::Dice::Fudge`
32
+ * `RpgTools::Dice::Percentile`
33
+
34
+ All those classes take two args: a mandatory side number and an optional modifier.
35
+ They respond to the `.roll` or `.roll!` methods to update their `value` to the result of the roll.
36
+
37
+ `RpgTools::Dice::Numerical.new(6, '+4').roll` will roll a six sided dice and add 4 to the roll result.
38
+
39
+ ### Dice Bags
40
+
41
+ `RpgTools::Dice::Bag.new(arg)` <i>(`arg` is case insensitive)</i>.
42
+
43
+ * It works the same way `RpgTools.roll_dice` does but will give you a `RpgTools::Dice::Bag` object instead of a plain integer. `RpgTools::Dice::Bag.new("4d6-2")` will create a bag of four 6 sided dices with a -2 modifier to the sum of all rolls.
44
+
45
+ ### Playing card deck
46
+ `RpgTools::PlayingCardDeck.new(arg)` <i>(`arg` can only be 32 or 52)</i>.
47
+
48
+ * The `card` method returns a card of a 32 or 52 cards deck + 2 jokers, depending
49
+ of `arg` value.
50
+ * The `hand` method return an array of 5 `card` calls.
51
+
52
+ ## Contributing
53
+
54
+ 1. Fork it
55
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
56
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
57
+ 4. Push to the branch (`git push origin my-new-feature`)
58
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new('spec')
@@ -0,0 +1,32 @@
1
+ module RpgTools
2
+ class Coin
3
+ attr_accessor :value, :flips, :heads, :tails
4
+
5
+ def initialize
6
+ @value, @flips, @heads, @tails = nil, 0, 0, 0
7
+ end
8
+
9
+ def flip
10
+ @flips += 1
11
+ @value = rand(2) == 1 ? 'Heads' : 'Tails'
12
+ save_result
13
+ @value
14
+ end
15
+ alias_method :flip!, :flip
16
+
17
+ private
18
+
19
+ def save_result
20
+ @heads += 1 if heads?
21
+ @tails += 1 if tails?
22
+ end
23
+
24
+ def heads?
25
+ @value == 'Heads'
26
+ end
27
+
28
+ def tails?
29
+ @value == 'Tails'
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,65 @@
1
+ module RpgTools
2
+ module Dice
3
+ class Bag
4
+ NOTATIONS ||= {
5
+ 'D' => Numerical,
6
+ 'D%' => Percentile,
7
+ 'DF' => Fudge
8
+ }.freeze
9
+
10
+ attr_accessor :dice_hash, :content, :modifiers, :value
11
+
12
+ def initialize(base)
13
+ @dice_hash = Utils::Parser.new(base).handle
14
+ @content = []
15
+ @modifiers = dice_hash[:modifiers]
16
+ @value = 0
17
+ end
18
+
19
+ def roll
20
+ invalid_dice! if dice_klass.nil?
21
+
22
+ fill_bag!
23
+
24
+ roll_bag_content!
25
+
26
+ return @total if modifiers.empty?
27
+
28
+ @total = Utils::ModifierCalculator.new(@total, modifiers).recalculate
29
+ end
30
+ alias roll! roll
31
+
32
+ private
33
+
34
+ def fill_bag!
35
+ quantity.times { @content << dice_klass.new(sides) }
36
+ end
37
+
38
+ def roll_bag_content!
39
+ @content.map(&:roll)
40
+
41
+ @total = @content.map(&:value).inject(0, :+)
42
+ end
43
+
44
+ def dice_klass
45
+ NOTATIONS[type]
46
+ end
47
+
48
+ def type
49
+ dice_hash[:type]
50
+ end
51
+
52
+ def sides
53
+ dice_hash[:sides]
54
+ end
55
+
56
+ def quantity
57
+ dice_hash[:quantity]
58
+ end
59
+
60
+ def invalid_dice!
61
+ raise ArgumentError, 'Unsupported dice type.'
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,52 @@
1
+ module RpgTools
2
+ module Dice
3
+ class Base
4
+ attr_accessor :sides, :modifiers, :value, :rolls
5
+
6
+ def initialize(sides = 0, modifiers = '')
7
+ @sides = sides.zero? ? sides_count : sides
8
+ @modifiers = modifiers
9
+ @value = 0
10
+ @rolls = 0
11
+
12
+ check_sides
13
+ end
14
+
15
+ def roll
16
+ @rolls += 1
17
+
18
+ @value = perform_roll
19
+ end
20
+
21
+ private
22
+
23
+ def perform_roll
24
+ return roll_calculation if @modifiers.empty?
25
+
26
+ roll_with_modifiers
27
+ end
28
+
29
+ def roll_with_modifiers
30
+ Utils::ModifierCalculator.new(roll_calculation, @modifiers).recalculate
31
+ end
32
+
33
+ def roll_calculation
34
+ raise NotImplementedError
35
+ end
36
+
37
+ def sides_count
38
+ 0
39
+ end
40
+
41
+ def check_sides
42
+ if not_enough_sides
43
+ raise ArgumentError, 'Your dice must have at least three sides.'
44
+ end
45
+ end
46
+
47
+ def not_enough_sides
48
+ @sides < 3
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,15 @@
1
+ module RpgTools
2
+ module Dice
3
+ class Fudge < Base
4
+ def roll_calculation
5
+ rand(-1..1)
6
+ end
7
+
8
+ private
9
+
10
+ def sides_count
11
+ 3
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module RpgTools
2
+ module Dice
3
+ class Numerical < Base
4
+ def roll_calculation
5
+ rand(1..sides)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ module RpgTools
2
+ module Dice
3
+ class Percentile < Base
4
+ def roll_calculation
5
+ (rand(1..10) * 10)
6
+ end
7
+
8
+ private
9
+
10
+ def sides_count
11
+ 10
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ module RpgTools
2
+ module Dice
3
+ module Utils
4
+ class ModifierCalculator
5
+ attr_accessor :total, :modifiers
6
+
7
+ def initialize(total, modifiers)
8
+ @total = total
9
+ @modifiers = modifiers
10
+
11
+ unprocessable_modifiers if malformed_modifiers?
12
+ end
13
+
14
+ def recalculate
15
+ modifier_operations.each do |operator, value|
16
+ @total = @total.send(operator, value.to_i)
17
+ end
18
+
19
+ @total
20
+ end
21
+
22
+ private
23
+
24
+ def modifier_operations
25
+ @modifiers.scan(/(\D)(\d+)/)
26
+ end
27
+
28
+ def unprocessable_modifiers
29
+ raise ArgumentError,
30
+ 'Modifiers require both an operator and a numerical value.'
31
+ end
32
+
33
+ def malformed_modifiers?
34
+ no_operator_at_modifier_beginning? ||
35
+ no_number_at_modifier_end? ||
36
+ multiple_successive_operators?
37
+ end
38
+
39
+ def no_operator_at_modifier_beginning?
40
+ @modifiers.match(/^\D/).nil?
41
+ end
42
+
43
+ def no_number_at_modifier_end?
44
+ @modifiers.match(/\d+$/).nil?
45
+ end
46
+
47
+ def multiple_successive_operators?
48
+ !@modifiers.match(/\d?([^0-9]{2,})\d?$/).nil?
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,46 @@
1
+ module RpgTools
2
+ module Dice
3
+ module Utils
4
+ class Parser
5
+ attr_reader :dice
6
+
7
+ def initialize(dice)
8
+ @dice = dice.upcase.match(/^(\d+)([A-Z%]+)(\d*)(.*)$/)
9
+
10
+ quantity_error! if @dice.nil?
11
+ end
12
+
13
+ def handle
14
+ {
15
+ quantity: quantity,
16
+ type: type,
17
+ sides: sides,
18
+ modifiers: modifiers
19
+ }
20
+ end
21
+
22
+ private
23
+
24
+ def quantity
25
+ @dice[1].to_i
26
+ end
27
+
28
+ def type
29
+ @dice[2]
30
+ end
31
+
32
+ def sides
33
+ @dice[3].to_i
34
+ end
35
+
36
+ def modifiers
37
+ @dice[4]
38
+ end
39
+
40
+ def quantity_error!
41
+ raise ArgumentError, 'You must specify a dice quantity.'
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ require 'rpg_tools/dice/utils/modifier_calculator'
2
+ require 'rpg_tools/dice/utils/parser'
3
+
4
+ require 'rpg_tools/dice/base'
5
+ require 'rpg_tools/dice/fudge'
6
+ require 'rpg_tools/dice/numerical'
7
+ require 'rpg_tools/dice/percentile'
8
+ require 'rpg_tools/dice/bag'
@@ -0,0 +1,64 @@
1
+ module RpgTools
2
+ class PlayingCardDeck
3
+ attr_accessor :type, :card_picks, :value
4
+
5
+ def initialize(type)
6
+ @type = type
7
+ type_check
8
+ @card_picks = 0
9
+ @value = nil
10
+ end
11
+
12
+ def card
13
+ @card_picks += 1
14
+
15
+ @value =
16
+ if @type == 52
17
+ joker_picked? ? 'Joker' : standard_card
18
+ else
19
+ standard_card
20
+ end
21
+ end
22
+
23
+ def hand
24
+ [].tap do |hand|
25
+ until hand.count == 5
26
+ card = standard_card
27
+
28
+ unless hand.include?(card) || hand.count('Joker') == 2
29
+ hand << card
30
+ @card_picks += 1
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def type_check
39
+ unless [32, 52].include?(@type)
40
+ raise ArgumentError.new('A playing card deck contains 32 or 52 cards only.')
41
+ end
42
+ end
43
+
44
+ def joker_picked?
45
+ [0, 1].include?((0..54).to_a.sample(1).first)
46
+ end
47
+
48
+ def number
49
+ if @type == 32
50
+ [(7..10).to_a, 'Jack', 'Queen', 'King'].flatten.sample(1)
51
+ else
52
+ [(1..10).to_a, 'Jack', 'Queen', 'King'].flatten.sample(1)
53
+ end
54
+ end
55
+
56
+ def color
57
+ ['Clubs', 'Hearts', 'Diamonds', 'Spades'].sample(1)
58
+ end
59
+
60
+ def standard_card
61
+ @value = [number, color].join(' of ')
62
+ end
63
+ end
64
+ end
data/lib/rpg_tools.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rpg_tools/coin'
2
+ require 'rpg_tools/dice'
3
+ require 'rpg_tools/playing_card_deck'
4
+
5
+ module RpgTools
6
+ def roll_dice(dice)
7
+ Dice::Bag.new(dice).roll
8
+ end
9
+ module_function :roll_dice
10
+ end
data/rpg_tools.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{rpg_tools}
3
+ s.version = '1.0.0'
4
+ s.author = 'Yohan Piron'
5
+ s.email = 'yinfei84@gmail.com'
6
+ s.date = '2015-08-03'
7
+ s.summary = 'rpg_tools is a toolbox for tabletop games and RPGs'
8
+ s.description = 'rpg_tools gives you tools for your RPGs : dices, coins, cards...'
9
+ s.homepage = 'https://github.com/Yinfei/rpg_tools.git'
10
+ s.license = 'MIT'
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = s.files.grep(%r{^(spec)/})
13
+ s.require_paths = ['lib']
14
+ s.add_development_dependency 'rake', '~> 10.4'
15
+ s.add_development_dependency 'rspec', '~> 3.0'
16
+ end
data/spec/coin_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Coin do
5
+ it "can't return anything else than 'Heads' or 'Tails'" do
6
+ expect(['Heads', 'Tails'].include?(described_class.new.flip)).to eq(true)
7
+ end
8
+ end
@@ -0,0 +1,59 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Dice::Bag do
5
+ describe '#roll' do
6
+ it "doesn't roll a dice without quantity" do
7
+ expect { described_class.new('d10').roll }.to raise_error(ArgumentError)
8
+ end
9
+
10
+ it "doesn't roll a 'd0' dice" do
11
+ expect { described_class.new('1d0').roll }.to raise_error(ArgumentError)
12
+ end
13
+
14
+ it "doesn't roll a 'd1' dice" do
15
+ expect { described_class.new('1d1').roll }.to raise_error(ArgumentError)
16
+ end
17
+
18
+ it "doesn't roll a 'd2' dice" do
19
+ expect { described_class.new('1d2').roll }.to raise_error(ArgumentError)
20
+ end
21
+
22
+ it 'rolls fudge dices' do
23
+ expect { described_class.new('1df').roll }.not_to raise_error
24
+ end
25
+
26
+ it "rolls a dice may the 'd' char be capitalized or not" do
27
+ expect { described_class.new('1d6').roll }.not_to raise_error
28
+ expect { described_class.new('1D6').roll }.not_to raise_error
29
+ end
30
+
31
+ it "rolls a dice may the 'f' char be capitalized or not" do
32
+ expect { described_class.new('1dF').roll }.not_to raise_error
33
+ expect { described_class.new('1Df').roll }.not_to raise_error
34
+ end
35
+
36
+ it 'rolls a dice with a bonus' do
37
+ expect { described_class.new('1d6+2').roll }.not_to raise_error
38
+ end
39
+
40
+ it 'rolls a dice with a malus' do
41
+ expect { described_class.new('1D6-2').roll }.not_to raise_error
42
+ end
43
+
44
+ it 'rolls a dice with a multiple modifiers' do
45
+ expect { described_class.new('1D6-2+4/8').roll }.not_to raise_error
46
+ end
47
+
48
+ it 'does not roll a dice with bad modifiers' do
49
+ expect { described_class.new('1D6-+2').roll }.to raise_error(ArgumentError)
50
+ expect { described_class.new('1D6-+2+').roll }.to raise_error(ArgumentError)
51
+ end
52
+
53
+ it "doesn't roll very odd dices" do
54
+ expect { described_class.new('1dDOGE').roll }.to raise_error(ArgumentError)
55
+ expect { described_class.new('1dfoo').roll }.to raise_error(ArgumentError)
56
+ expect { described_class.new('1foobarbaz').roll }.to raise_error(ArgumentError)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,96 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Dice::Base do
5
+ let(:dice) { described_class.new(10) }
6
+ let(:dice_with_modifier) { described_class.new(10, '+2') }
7
+
8
+ describe '#initialize' do
9
+ it 'creates a basic dice' do
10
+ expect { described_class.new(10) }.not_to raise_error
11
+ end
12
+
13
+ it 'creates a basic dice with a modifier' do
14
+ expect { described_class.new(10, '+2') }.not_to raise_error
15
+ end
16
+
17
+ it 'falls back on sides_count method if no sides arg is provided' do
18
+ allow_any_instance_of(described_class).to receive(:sides_count).and_return(7)
19
+
20
+ new_dice = described_class.new
21
+
22
+ expect(new_dice.sides).to eq(7)
23
+ end
24
+ end
25
+
26
+ describe '#roll' do
27
+ before do
28
+ allow(dice).to receive(:roll_calculation).and_return(10)
29
+ allow(dice_with_modifier).to receive(:roll_calculation).and_return(10)
30
+ end
31
+
32
+ context 'no modifier' do
33
+ it 'returns an integer based on a basic roll calculation' do
34
+ expect(dice.roll).to eq(10)
35
+ end
36
+
37
+ it 'does not call the #roll_with_modifiers method' do
38
+ expect(dice).not_to receive(:roll_with_modifiers)
39
+
40
+ dice.roll
41
+ end
42
+ end
43
+
44
+ context 'modifier present' do
45
+ it 'returns an integer based on a roll calulation plus modifier applied' do
46
+ expect(dice_with_modifier.roll).to eq(12)
47
+ end
48
+
49
+ it 'calls the #roll_with_modifiers method' do
50
+ expect(dice_with_modifier).to receive(:roll_with_modifiers)
51
+
52
+ dice_with_modifier.roll
53
+ end
54
+ end
55
+
56
+ it 'updates a dice value attribute' do
57
+ dice.roll
58
+
59
+ expect(dice.value).to eq(10)
60
+ end
61
+
62
+ it 'increments to dice roll count' do
63
+ dice.roll
64
+
65
+ expect(dice.rolls).to eq(1)
66
+
67
+ dice.roll
68
+
69
+ expect(dice.rolls).to eq(2)
70
+ end
71
+ end
72
+
73
+ describe '#sides_count' do
74
+ it 'returns zero' do
75
+ expect(dice.send(:sides_count)).to eq(0)
76
+ end
77
+ end
78
+
79
+ describe '#roll_calculation' do
80
+ it 'raises a NotImplementedError' do
81
+ expect { dice.send(:roll_calculation) }.to raise_error(NotImplementedError)
82
+ end
83
+ end
84
+
85
+ describe 'not_enough_sides' do
86
+ it 'returns true if dice sides is less than three' do
87
+ dice.sides = 2
88
+
89
+ expect(dice.send(:not_enough_sides)).to be(true)
90
+ end
91
+
92
+ it 'returns false otherwise' do
93
+ expect(dice.send(:not_enough_sides)).to be(false)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,22 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Dice::Fudge do
5
+ let(:dice) { described_class.new }
6
+
7
+ describe '#roll_calculation' do
8
+ it 'rolls a value between -1 and 1' do
9
+ 10.times do
10
+ dice.roll
11
+
12
+ expect(dice.value.between?(-1, 1)).to be(true)
13
+ end
14
+ end
15
+ end
16
+
17
+ describe '#sides_count' do
18
+ it 'returns 3' do
19
+ expect(dice.send(:sides_count)).to eq(3)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Dice::Numerical do
5
+ let(:dice) { described_class.new(10) }
6
+
7
+ describe '#roll_calculation' do
8
+ it 'rolls a value between 1 and the sides value' do
9
+ 10.times do
10
+ dice.roll
11
+
12
+ expect(dice.value.between?(1, dice.sides)).to be(true)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Dice::Percentile do
5
+ let(:dice) { described_class.new }
6
+
7
+ describe '#roll_calculation' do
8
+ it 'rolls a value between 10 and 100' do
9
+ 10.times do
10
+ dice.roll
11
+
12
+ expect(dice.value.between?(10, 100)).to be(true)
13
+ end
14
+ end
15
+
16
+ it 'rolls only round values' do
17
+ 10.times do
18
+ dice.roll
19
+
20
+ expect(dice.value[-1]).to eq(0)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#sides_count' do
26
+ it 'returns 10' do
27
+ expect(dice.send(:sides_count)).to eq(10)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,96 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Dice::Utils::ModifierCalculator do
5
+ let(:dice) { described_class.new(10, '+1') }
6
+
7
+ describe '#initialize' do
8
+ it 'raises an error for malformed modifiers' do
9
+ expect { described_class.new(10, '+3+') }.to raise_error(ArgumentError)
10
+ end
11
+
12
+ it 'does not otherwise' do
13
+ expect { described_class.new(10, '+5-3/10') }.not_to raise_error
14
+ end
15
+ end
16
+
17
+ describe '#recalculate' do
18
+ it 'applies a simple modifier to the total attribute' do
19
+ dice = described_class.new(10, '+5')
20
+
21
+ dice.recalculate
22
+
23
+ expect(dice.total).to eq(15)
24
+ end
25
+
26
+ it 'applies multiple modifiers to the total attribute' do
27
+ dice = described_class.new(10, '+5-1/2')
28
+
29
+ dice.recalculate
30
+
31
+ expect(dice.total).to eq(7)
32
+ end
33
+ end
34
+
35
+ describe '#malformed_modifiers?' do
36
+ it 'returns true if there is not operator at modifiers beginning' do
37
+ dice.modifiers = '4'
38
+
39
+ expect(dice.send(:malformed_modifiers?)).to be(true)
40
+ end
41
+
42
+ it 'returns true if there is no number at modifiers end' do
43
+ dice.modifiers = '+3-'
44
+
45
+ expect(dice.send(:malformed_modifiers?)).to be(true)
46
+ end
47
+
48
+ it 'returns true if multiple succesive operators are present in the modifiers' do
49
+ dice.modifiers = '+-3'
50
+
51
+ expect(dice.send(:malformed_modifiers?)).to be(true)
52
+ end
53
+
54
+ it 'returns false otherwise' do
55
+ dice.modifiers = '+4-5/8'
56
+
57
+ expect(dice.send(:malformed_modifiers?)).to be(false)
58
+ end
59
+ end
60
+
61
+ describe '#no_operator_at_modifier_beginning?' do
62
+ it 'returns true if there is not operator at modifiers beginning' do
63
+ dice.modifiers = '4'
64
+
65
+ expect(dice.send(:no_operator_at_modifier_beginning?)).to be(true)
66
+ end
67
+
68
+ it 'returs false otherwise' do
69
+ expect(dice.send(:no_operator_at_modifier_beginning?)).to be(false)
70
+ end
71
+ end
72
+
73
+ describe '#no_number_at_modifier_end?' do
74
+ it 'returns true if there is no number at modifiers end' do
75
+ dice.modifiers = '+3-'
76
+
77
+ expect(dice.send(:no_number_at_modifier_end?)).to be(true)
78
+ end
79
+
80
+ it 'returs false otherwise' do
81
+ expect(dice.send(:no_number_at_modifier_end?)).to be(false)
82
+ end
83
+ end
84
+
85
+ describe '#multiple_successive_operators?' do
86
+ it 'returns true if multiple succesive operators are present in the modifiers' do
87
+ dice.modifiers = '+-3'
88
+
89
+ expect(dice.send(:multiple_successive_operators?)).to be(true)
90
+ end
91
+
92
+ it 'returs false otherwise' do
93
+ expect(dice.send(:multiple_successive_operators?)).to be(false)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,28 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::Dice::Utils::Parser do
5
+ describe '#initialize' do
6
+ it 'raises an error when no matching pattern is found' do
7
+ expect { described_class.new('DOGE') }.to raise_error(ArgumentError)
8
+ end
9
+
10
+ it 'does not otherwise' do
11
+ expect { described_class.new('1DF') }.not_to raise_error
12
+ expect { described_class.new('1D10') }.not_to raise_error
13
+ expect { described_class.new('1D10+12') }.not_to raise_error
14
+ expect { described_class.new('1D%') }.not_to raise_error
15
+ end
16
+ end
17
+
18
+ describe '#handle' do
19
+ it 'builds a hash based on a matching pattern' do
20
+ hash = described_class.new('3DF+4').handle
21
+
22
+ expect(hash[:quantity]).to eq(3)
23
+ expect(hash[:type]).to eq('DF')
24
+ expect(hash[:sides]).to eq(0)
25
+ expect(hash[:modifiers]).to eq('+4')
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require 'rpg_tools'
2
+ require 'spec_helper'
3
+
4
+ describe RpgTools::PlayingCardDeck do
5
+ it 'must return a card name' do
6
+ expect(described_class.new(32).card).not_to eq(true)
7
+ expect(described_class.new(32).card).not_to eq(false)
8
+ expect(described_class.new(32).card).not_to eq(nil)
9
+ expect(described_class.new(52).card).not_to eq(true)
10
+ expect(described_class.new(52).card).not_to eq(false)
11
+ expect(described_class.new(52).card).not_to eq(nil)
12
+ end
13
+
14
+ it 'must return 5 cards for a full hand' do
15
+ expect(described_class.new(32).hand.count).to eq(5)
16
+ expect(described_class.new(52).hand.count).to eq(5)
17
+ end
18
+
19
+ it "can't pick the same card twice" do
20
+ expect(described_class.new(32).hand.uniq.count).to eq(5)
21
+ expect(described_class.new(52).hand.uniq.count).to eq(5)
22
+ end
23
+
24
+ it "can't use anything else than a 32 or 52 cards deck" do
25
+ expect { described_class.new(42) }.to raise_error(ArgumentError)
26
+ expect { described_class.new(666) }.to raise_error(ArgumentError)
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ RSpec.configure do |config|
2
+ config.color = true
3
+ config.tty = true
4
+ config.formatter = :documentation
5
+
6
+ config.mock_with :rspec do |c|
7
+ c.syntax = [:should, :expect]
8
+ end
9
+
10
+ config.expect_with :rspec do |c|
11
+ c.syntax = [:should, :expect]
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rpg_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Yohan Piron
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.4'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ description: 'rpg_tools gives you tools for your RPGs : dices, coins, cards...'
42
+ email: yinfei84@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.md
49
+ - Rakefile
50
+ - lib/rpg_tools.rb
51
+ - lib/rpg_tools/coin.rb
52
+ - lib/rpg_tools/dice.rb
53
+ - lib/rpg_tools/dice/bag.rb
54
+ - lib/rpg_tools/dice/base.rb
55
+ - lib/rpg_tools/dice/fudge.rb
56
+ - lib/rpg_tools/dice/numerical.rb
57
+ - lib/rpg_tools/dice/percentile.rb
58
+ - lib/rpg_tools/dice/utils/modifier_calculator.rb
59
+ - lib/rpg_tools/dice/utils/parser.rb
60
+ - lib/rpg_tools/playing_card_deck.rb
61
+ - rpg_tools.gemspec
62
+ - spec/coin_spec.rb
63
+ - spec/dice/bag_spec.rb
64
+ - spec/dice/base_spec.rb
65
+ - spec/dice/fudge_spec.rb
66
+ - spec/dice/numerical_spec.rb
67
+ - spec/dice/percentile_spec.rb
68
+ - spec/dice/utils/modifier_calculator_spec.rb
69
+ - spec/dice/utils/parser_spec.rb
70
+ - spec/playing_card_deck_spec.rb
71
+ - spec/spec_helper.rb
72
+ homepage: https://github.com/Yinfei/rpg_tools.git
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.6.8
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: rpg_tools is a toolbox for tabletop games and RPGs
96
+ test_files:
97
+ - spec/coin_spec.rb
98
+ - spec/dice/bag_spec.rb
99
+ - spec/dice/base_spec.rb
100
+ - spec/dice/fudge_spec.rb
101
+ - spec/dice/numerical_spec.rb
102
+ - spec/dice/percentile_spec.rb
103
+ - spec/dice/utils/modifier_calculator_spec.rb
104
+ - spec/dice/utils/parser_spec.rb
105
+ - spec/playing_card_deck_spec.rb
106
+ - spec/spec_helper.rb