warcards 0.0.2

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/.gitattributes ADDED
@@ -0,0 +1,22 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Custom for Visual Studio
5
+ *.cs diff=csharp
6
+ *.sln merge=union
7
+ *.csproj merge=union
8
+ *.vbproj merge=union
9
+ *.fsproj merge=union
10
+ *.dbproj merge=union
11
+
12
+ # Standard to msysgit
13
+ *.doc diff=astextplain
14
+ *.DOC diff=astextplain
15
+ *.docx diff=astextplain
16
+ *.DOCX diff=astextplain
17
+ *.dot diff=astextplain
18
+ *.DOT diff=astextplain
19
+ *.pdf diff=astextplain
20
+ *.PDF diff=astextplain
21
+ *.rtf diff=astextplain
22
+ *.RTF diff=astextplain
data/.gitignore ADDED
@@ -0,0 +1,42 @@
1
+ .idea/
2
+ .bundle/
3
+
4
+ # Compiled source #
5
+ ###################
6
+ *.com
7
+ *.class
8
+ *.dll
9
+ *.exe
10
+ *.o
11
+ *.so
12
+ *.gem
13
+
14
+ # Packages #
15
+ ############
16
+ # it's better to unpack these files and commit the raw source
17
+ # git has its own built in compression methods
18
+ *.7z
19
+ *.dmg
20
+ *.gz
21
+ *.iso
22
+ *.jar
23
+ *.rar
24
+ *.tar
25
+ *.zip
26
+
27
+ # Logs and databases #
28
+ ######################
29
+ *.log
30
+ *.sql
31
+ *.sqlite
32
+
33
+ # OS generated files #
34
+ ######################
35
+ .DS_Store
36
+ .DS_Store?
37
+ ._*
38
+ .Spotlight-V100
39
+ .Trashes
40
+ Icon?
41
+ ehthumbs.db
42
+ Thumbs.db
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ # - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ # - jruby-18mode # JRuby in 1.8 mode
7
+ - jruby-19mode # JRuby in 1.9 mode
8
+ # - rbx-18mode
9
+ - rbx-19mode
10
+ # uncomment this line if your project needs to run something other than `rake`:
11
+ # script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in warcards.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,61 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ warcards (0.0.2)
5
+ bundler (~> 1.1)
6
+ querinator
7
+ rake (~> 0.9.2)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ansi (1.4.3)
13
+ builder (3.0.0)
14
+ ffi (1.1.1)
15
+ ffi (1.1.1-x86-mingw32)
16
+ growl (1.0.3)
17
+ guard (1.2.3)
18
+ listen (>= 0.4.2)
19
+ thor (>= 0.14.6)
20
+ guard-minitest (0.5.0)
21
+ guard (>= 0.4)
22
+ hashie (1.2.0)
23
+ listen (0.4.7)
24
+ rb-fchange (~> 0.0.5)
25
+ rb-fsevent (~> 0.9.1)
26
+ rb-inotify (~> 0.8.8)
27
+ minitest (3.3.0)
28
+ minitest-reporters (0.9.0)
29
+ ansi
30
+ builder
31
+ minitest (>= 2.0, < 4.0)
32
+ powerbar
33
+ minitest-spec (0.0.2.1)
34
+ minitest (>= 3.0)
35
+ powerbar (1.0.8)
36
+ ansi (~> 1.4.0)
37
+ hashie (>= 1.1.0)
38
+ querinator (0.0.1)
39
+ rake (0.9.2.2)
40
+ rb-fchange (0.0.5)
41
+ ffi
42
+ rb-fsevent (0.9.1)
43
+ rb-inotify (0.8.8)
44
+ ffi (>= 0.5.0)
45
+ thor (0.15.4)
46
+ turn (0.9.6)
47
+ ansi
48
+
49
+ PLATFORMS
50
+ ruby
51
+ x86-mingw32
52
+
53
+ DEPENDENCIES
54
+ growl (~> 1.0.3)
55
+ guard (~> 1.2.3)
56
+ guard-minitest (~> 0.5.0)
57
+ minitest-reporters (~> 0.9.0)
58
+ minitest-spec (~> 0.0.2)
59
+ rb-fsevent (~> 0.9.1)
60
+ turn (~> 0.9.6)
61
+ warcards!
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'minitest' do
5
+ watch(%r|^spec/(.*)_spec\.rb|)
6
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
7
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
8
+
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Robie Lutsey
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,49 @@
1
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/robie1373/warcards)
2
+ [![Build Status](https://secure.travis-ci.org/robie1373/warcards.png?branch=master)](http://travis-ci.org/robie1373/warcards)
3
+
4
+ # Warcards!
5
+ ## What is it?
6
+ Use a deck of flash cards to play the card game war!
7
+
8
+ Creates a deck of 52 flash cards and assigns them all suits and values.
9
+ To win a round you must have the higher card *and* answer the opponents card correctly.
10
+ Incorrect answers result in a draw.
11
+ The opponent has a scaled-by-difficulty chance to answer your card correctly if it has the higher card.
12
+
13
+ War is declared when you both have the same value card. To win War, you must answer 2 of your opponent's 3 cards
14
+ correctly.
15
+
16
+ Game ends when one of you is out of cards.
17
+
18
+ ## Implementation concepts
19
+ * Keep track of # of right and wrong answers for each flash-card.
20
+
21
+ * consider using ratio of right/wrong + #times seen to scale how often a flash-card is seen.
22
+
23
+ * You might make a pool of questions > 52 and select the question for each card out of the pool as it is 'flipped'. Decouple the flash-card from the game card. the game cards are just a token to track game progress.
24
+
25
+ ## Installation
26
+
27
+ Add this line to your application's Gemfile:
28
+
29
+ gem 'warcards'
30
+
31
+ And then execute:
32
+
33
+ $ bundle
34
+
35
+ Or install it yourself as:
36
+
37
+ $ gem install warcards
38
+
39
+ ## Usage
40
+
41
+ As of today, if you run bin/warcards it will play a game of war with you and quiz you as you play.
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ task :default => :spec
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs.push 'lib'
9
+ t.test_files = FileList['spec/**/*_spec.rb']
10
+ t.verbose = true
11
+ end
data/bin/warcards ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'warcards'
5
+
6
+
7
+
8
+ # TODO finish refactoring lib/warcards and implement here
9
+ Cardgame::Game.new.run
10
+
@@ -0,0 +1,37 @@
1
+ module Cardgame
2
+ class Ai
3
+ def initialize
4
+ @stack = Array.new
5
+ @discard = Array.new
6
+ #attr_accessor :name
7
+ @ai_name = "H.E.L.P.E.R."
8
+ # Set the game difficulty manually for now. Pick a number < 1. Higher is harder. TODO: make this a switch
9
+
10
+ end
11
+
12
+ def stack
13
+ @stack
14
+ end
15
+ #
16
+ #def stack=(card)
17
+ # @stack = Array.new
18
+ # @stack << card
19
+ #end
20
+
21
+ def discard
22
+ @discard
23
+ end
24
+
25
+ #def empty_discard
26
+ # @discard = Array.new
27
+ #end
28
+
29
+ def name
30
+ @ai_name
31
+ end
32
+
33
+ def difficulty_check?(rand_src, difficulty)
34
+ rand_src < difficulty ? TRUE : FALSE
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module Cardgame
2
+ class Card
3
+ def initialize(args)
4
+ @suit = args[:suit]
5
+ @value = args[:value]
6
+ end
7
+
8
+ def suit
9
+ @suit
10
+ end
11
+
12
+ def value
13
+ @value
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ module Cardgame
2
+ class Deck
3
+ include Enumerable
4
+
5
+ def initialize
6
+ @deck = Array.new
7
+ [:hearts, :clubs, :diamonds, :spades].each do |suit|
8
+ (1..13).each do |value|
9
+ @deck << Card.new(:suit => suit, :value => value)
10
+ end
11
+ end
12
+ end
13
+
14
+ def [](index)
15
+ @deck[index]
16
+ end
17
+
18
+ def each &block
19
+ #TODO understand this
20
+ @deck.each { |card| block.call(card) }
21
+ end
22
+
23
+ def length
24
+ @deck.length
25
+ end
26
+
27
+ def shuffle!
28
+ @deck.shuffle!
29
+ end
30
+
31
+ def pop
32
+ @deck.pop
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,103 @@
1
+ require_relative 'deck'
2
+ require_relative 'card'
3
+ require_relative 'ai'
4
+ require_relative 'player'
5
+
6
+ module Cardgame
7
+ class Gameplay
8
+ def initialize(args)
9
+ @deck = args[:deck]
10
+ @player = args[:player]
11
+ @ai = args[:ai]
12
+ @player_cards = Array.new
13
+ @ai_cards = Array.new
14
+ end
15
+
16
+ def shuffle
17
+ @deck.shuffle!
18
+ end
19
+
20
+ def deal
21
+ while @deck.length > 0
22
+ deck.length.even? ? @player.stack << @deck.pop : @ai.stack << @deck.pop
23
+ end
24
+ end
25
+
26
+ def game_over?
27
+ [@ai, @player].each_with_index do |participant, index|
28
+ if (participant.stack.length + participant.discard.length) < 1
29
+ participants = [@ai, @player]
30
+ participants.delete_at index
31
+ puts "Game over #{participants.first.name} won!"
32
+ exit
33
+ else
34
+ next
35
+ end
36
+ end
37
+ end
38
+
39
+ def rearm?
40
+ [@ai, @player].each do |participant|
41
+ if participant.stack.length < 1
42
+ participant.discard.each do |card|
43
+ participant.stack << card
44
+ end
45
+ participant.stack.flatten!
46
+ participant.discard.clear
47
+ end
48
+ end
49
+ end
50
+
51
+ def contest
52
+ if @ai_cards.last.value > @player_cards.last.value
53
+ winner = @ai
54
+ elsif @ai_cards.last.value < @player_cards.last.value
55
+ winner = @player
56
+ end
57
+
58
+ { :winner => winner, :player_cards => @player_cards, :ai_cards => @ai_cards }
59
+ end
60
+
61
+ def war?
62
+ while @ai_cards.last.value == @player_cards.last.value
63
+ rearm?
64
+ #TODO make the folling line a flag or something so the view code can decide to show it or not.
65
+ puts "WAR!!!"
66
+ show_cards
67
+ end
68
+ end
69
+
70
+ def show_cards
71
+ player_cards << @player.stack.pop
72
+ ai_cards << @ai.stack.pop
73
+ end
74
+
75
+ def discard(result)
76
+ while result[:ai_cards].size > 0
77
+ result[:winner].discard << result[:ai_cards].pop
78
+ result[:winner].discard << result[:player_cards].pop
79
+ end
80
+ end
81
+
82
+ def ai
83
+ @ai
84
+ end
85
+
86
+ def ai_cards
87
+ @ai_cards
88
+ end
89
+
90
+ def deck
91
+ @deck
92
+ end
93
+
94
+ def player
95
+ @player
96
+ end
97
+
98
+ def player_cards
99
+ @player_cards
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,30 @@
1
+ module Cardgame
2
+ class Player
3
+ def initialize
4
+ @stack = Array.new
5
+ @discard = Array.new
6
+ @player_name = "Player"
7
+ end
8
+
9
+ def stack
10
+ @stack
11
+ end
12
+
13
+ #def stack=(card)
14
+ # @stack = Array.new
15
+ # @stack << card
16
+ #end
17
+
18
+ def discard
19
+ @discard
20
+ end
21
+
22
+ #def empty_discard
23
+ # @discard = Array.new
24
+ #end
25
+
26
+ def name
27
+ @player_name
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ module Cardgame
2
+
3
+ VERSION = "0.0.2"
4
+
5
+ end
data/lib/warcards.rb ADDED
@@ -0,0 +1,96 @@
1
+ require 'bundler/setup'
2
+ Bundler.require(:default)
3
+ require_relative 'warcards/gameplay'
4
+ require 'querinator'
5
+
6
+ module Cardgame
7
+ class Game
8
+ def initialize
9
+ @questions = Querinator::Game.new.get_questions
10
+ @deck = Deck.new
11
+ @player = Player.new
12
+ @ai = Ai.new
13
+ @gameplay = Gameplay.new(:deck => @deck, :player => @player, :ai => @ai)
14
+ @gameplay.shuffle
15
+ @gameplay.deal
16
+ end
17
+
18
+ def run
19
+ loop do
20
+ @gameplay.game_over?
21
+ @gameplay.rearm?
22
+ @gameplay.show_cards
23
+ @gameplay.war?
24
+ result = @gameplay.contest
25
+
26
+ output_cli(result)
27
+
28
+ continue?
29
+ @gameplay.discard(result)
30
+ end
31
+ end
32
+
33
+ def continue?
34
+ puts "go again?\n"
35
+ next_round = gets
36
+ if next_round.downcase.chomp.include? "n"
37
+ puts "You ended the game"
38
+ exit
39
+ end
40
+ end
41
+
42
+ def output_cli(result)
43
+ puts "#{result[:winner].name} won"
44
+ puts "Player has #{player_holdings} cards.\tAI has #{ai_holdings} cards."
45
+ challenge_participants(result)
46
+ end
47
+
48
+ def player_holdings
49
+ (@gameplay.player.stack.length + @gameplay.player.discard.length + 1)
50
+ end
51
+
52
+ def ai_holdings
53
+ @gameplay.ai.stack.length + @gameplay.ai.discard.length + 1
54
+ end
55
+
56
+ def challenge_participants(result)
57
+ if result[:winner] == @gameplay.player
58
+ challenge_player(result)
59
+ else
60
+ challenge_ai(result)
61
+ end
62
+ end
63
+
64
+ def challenge_ai(result)
65
+ if test_ai
66
+ puts "Ai was correct."
67
+ else
68
+ puts "Ai was wrong. #{@gameplay.player.name} became the winner!"
69
+ result[:winner] = @gameplay.player
70
+ end
71
+ end
72
+
73
+ def challenge_player(result)
74
+ if test_player
75
+ puts "Correct! Yay!"
76
+ else
77
+ puts "Oooh. I'm sorry. The correct answer was 'TODO'. #{@gameplay.ai.name} became the winner."
78
+ result[:winner] = @gameplay.ai
79
+ end
80
+ end
81
+
82
+
83
+ def test_player
84
+ question = @questions.sample
85
+ puts question.pose
86
+ answer = gets
87
+ question.is_correct?(answer.chomp)
88
+ end
89
+
90
+ #TODO make this configurable
91
+ def test_ai
92
+ @ai.difficulty_check?(rand, 0.9)
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,57 @@
1
+ # Responsibilities
2
+
3
+ ## Ai - Describes the Ai participant
4
+ * #name - good
5
+ * #difficulty_check - Ai specific. good.
6
+ * #stack - wrapper for instance variable holding an array
7
+ * #discard - wrapper for instance variable holding an array
8
+
9
+ ## Player - Describes the player participant
10
+ * #name - good
11
+ * #stack - wrapper for instance variable holding an array
12
+ * #discard - wrapper for instance variable holding an array
13
+ * _Should this just be a Struct? There is no behavior._
14
+
15
+ ## Deck - Allows manipulation of all 52 cards.
16
+ * #[] - allows indexing. good.
17
+ * #each - good.
18
+ * #length - good
19
+ * #shuffle - good
20
+ * #pop - good
21
+
22
+ ## Card - Contains information about a card
23
+ * #suit - good.
24
+ * #value - good.
25
+ * _Should this just be a Struct? There is no behavior._
26
+
27
+ ## Gameplay - Handles logic of playing the game
28
+ * #shuffle - shuffles the deck
29
+ * #deal - distributes them between participants.
30
+ * _Is this Deck behavior?_ `@deck.shuffle.deal(@player, @ai)` _No. Some decks might not get shuffled or dealt.
31
+ Those are implementation details of various types of gameplay. This belongs in gameplay._
32
+ * #rearm? - rearms participant if required
33
+ * #winner - determines the winning package by comparing card.value
34
+ * #war? - runs a war as long as needed
35
+ * #show_cards - Pops a card from the deck of each participant into their 'hand'. Good.
36
+ * #discard - places the contested cards into the winner's discard based on the package from #winner. Good.
37
+ * #game_over? - ends game when a participant is out of cards
38
+ * #ai - Wrapper for ai attr_accessor
39
+ * #deck - wrapper for deck attr_accessor
40
+ * #player - wrapper for player attr_accessor
41
+
42
+ ## Warcards Game
43
+ * #initialize - create a new instance of game in a playable condition. This means. creating player, ai, deck and running #shuffle and #deal
44
+ * a game of war looks like this:
45
+ * #game_over?
46
+ * #rearm?
47
+ * #showcards
48
+ * #war?
49
+ * #winner
50
+ * #discard
51
+ * repeat until someone wins.
52
+ * #start - TODO
53
+ * #deal_cards - wrapper for Gameplay#deal
54
+ * #flip_cards - TODO
55
+ * #player - wrapper for attr_accessor
56
+ * #ai - wrapper for ai attr_accessor
57
+
@@ -0,0 +1,9 @@
1
+ require 'minitest/spec'
2
+ require "minitest/autorun"
3
+ require 'minitest/reporters'
4
+ require 'turn'
5
+ require 'growl'
6
+
7
+ MiniTest::Reporters.use!
8
+
9
+ require_relative '../lib/warcards'
@@ -0,0 +1,12 @@
1
+ [{"question":"Do you get Tom Servo?","answer":"Nobody does. I'm the wind baby."},
2
+ {"question":"Was there ever a monster?","answer":"We will never speak of this movie again."},
3
+ {"question":"What is 2+2","answer":"4"},
4
+ {"question":"What is the capital of Colorado?","answer":"Denver"},
5
+ {"question":"Which is more dense: lead or meatloaf?","answer":"lead"},
6
+ {"question":"What is the chemical symbol for gold?","answer":"Au"},
7
+ {"question":"Does Robie kick butt?","answer":"yes"},
8
+ {"question":"Which is better, Ruby or Python?","answer":"Ruby, duh!"},
9
+ {"question":"What does every rose have at least one of?","answer":"thorns"},
10
+ {"question":"The english word for 'azul' is...","answer":"blue"},
11
+ {"question":"This is a.) fun; b.) boring; c.) neither of the above","answer":"a"}
12
+ ]
@@ -0,0 +1,68 @@
1
+ require_relative '../spec_helper'
2
+
3
+ module Cardgame
4
+ describe Ai do
5
+ #def setup
6
+ #deck = Deck.new
7
+ #player = Player.new
8
+ #ai = Ai.new
9
+ #@gameplay = Gameplay.new(:deck => deck, :player => player, :ai => Ai.new)
10
+ #@ai = @gameplay.ai
11
+ #@gameplay.deal
12
+ #end
13
+
14
+ it "must be an instance of Ai" do
15
+ Ai.new.must_be_instance_of Ai
16
+ end
17
+
18
+ describe "#stack" do
19
+ def setup
20
+ @ai = Ai.new
21
+ card = Card.new(:suit => :spades, :value => 5)
22
+ @ai.stack << card
23
+ end
24
+
25
+ it "must have a stack of Card objects" do
26
+ @ai.stack.first.must_be_instance_of Card
27
+ end
28
+
29
+ it "must be able to append cards on the end" do
30
+ original_stack_length = @ai.stack.length
31
+ @ai.stack << Card.new(:suit => :spades, :value => 7)
32
+ @ai.stack.length.must_equal (original_stack_length + 1)
33
+ end
34
+ end
35
+
36
+ describe "#discard" do
37
+ def setup
38
+ @ai = Ai.new
39
+ @ai.discard << Card.new(:suit => :clubs, :value => 11)
40
+ end
41
+
42
+ it "must have a discard of Card objects" do
43
+ @ai.discard.first.must_be_instance_of Card
44
+ end
45
+
46
+ it "must be able to append cards on the end" do
47
+ original_discard_length = @ai.discard.length
48
+ @ai.discard << Card.new(:suit => :spades, :value => 7)
49
+ @ai.discard.length.must_equal (original_discard_length + 1)
50
+ end
51
+ end
52
+
53
+ describe "#name" do
54
+ it "must have a name" do
55
+ Ai.new.name.must_equal "H.E.L.P.E.R."
56
+ end
57
+ end
58
+
59
+ describe "#difficulty_check?" do
60
+ it "must test against the difficult level to see if it wins a round" do
61
+ rand_src = 0.1
62
+ difficulty = 0.4
63
+ Ai.new.difficulty_check?(rand_src, difficulty).must_equal TRUE
64
+ end
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ require_relative '../spec_helper'
2
+
3
+ module Cardgame
4
+ describe Card do
5
+ def setup
6
+ @card = Card.new(:suit => :hearts, :value => 10)
7
+ end
8
+
9
+ it "must be an instance of card" do
10
+ @card.must_be_instance_of Card
11
+ end
12
+
13
+ it "must be created with a given suit" do
14
+ Card.new(:suit => :clubs).suit.must_equal :clubs
15
+ end
16
+
17
+ it "must be created with a given value" do
18
+ Card.new(:value => 3).value.must_equal 3
19
+ end
20
+
21
+ describe "#suit" do
22
+ it "cards must have a suit" do
23
+ @card.suit.must_equal :hearts
24
+ end
25
+ end
26
+
27
+ describe "@value" do
28
+ it "must have a value" do
29
+ @card.value.must_equal 10
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ require_relative '../spec_helper'
2
+
3
+ module Cardgame
4
+ describe Deck do
5
+ def setup
6
+ @deck = Deck.new
7
+ end
8
+
9
+ it "must be an instance of deck" do
10
+ @deck.must_be_instance_of Deck
11
+ end
12
+
13
+ it "must have 52 cards in it" do
14
+ @deck.length.must_equal 52
15
+ end
16
+
17
+ it "must have 13 cards of each suit" do
18
+ h = Hash.new(0)
19
+ @deck.each { |card| h[card.suit] += 1 }
20
+ h.each_key do |suit|
21
+ h[suit].must_equal 13
22
+ end
23
+ end
24
+
25
+ it "must have 4 of each value" do
26
+ h = Hash.new(0)
27
+ @deck.each { |card| h[card.value] += 1 }
28
+ h.each_key do |value|
29
+ h[value].must_equal 4
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,185 @@
1
+ require_relative '../spec_helper'
2
+
3
+ module Cardgame
4
+ describe Gameplay do
5
+ def setup
6
+ @deck = Deck.new
7
+ @player = Player.new
8
+ @ai = Ai.new
9
+ @gameplay = Gameplay.new(:deck => @deck, :player => @player, :ai => @ai)
10
+ end
11
+
12
+ it "can create a new game" do
13
+ @gameplay.must_be_instance_of Gameplay
14
+ end
15
+
16
+ describe "#deck" do
17
+ it "has a deck" do
18
+ @gameplay.deck.must_be_instance_of Deck
19
+ end
20
+ end
21
+
22
+ describe "#player" do
23
+ it "has a player" do
24
+ @gameplay.player.must_be_instance_of Player
25
+ end
26
+ end
27
+
28
+ describe "#ai" do
29
+ it "has an ai" do
30
+ @gameplay.ai.must_be_instance_of Ai
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ describe "dealt deck" do
37
+ def setup
38
+ @deck = Deck.new
39
+ player = Player.new
40
+ ai = Ai.new
41
+ @gameplay = Gameplay.new(:deck => @deck, :player => player, :ai => ai)
42
+ @gameplay.shuffle
43
+ @gameplay.deal
44
+ end
45
+
46
+ it "must deal the deck to the player and ai" do
47
+ @gameplay.deck.length.must_equal 0
48
+ @gameplay.player.stack.length.must_equal 26
49
+ @gameplay.player.stack.each { |card| card.must_be_instance_of Card }
50
+ @gameplay.ai.stack.length.must_equal 26
51
+ end
52
+
53
+ it "must not duplicate cards between stacks" do
54
+ (@gameplay.ai.stack & @gameplay.player.stack).length.must_equal 0
55
+ end
56
+
57
+ it "must not duplicate cards within stacks" do
58
+ (@gameplay.ai.stack | @gameplay.player.stack).length.must_equal 52
59
+ end
60
+
61
+ # TODO refactor this test to use specified cards to ensure each case gets tested
62
+ describe "#contest" do
63
+ it "must pick the ai when it has the highest card" do
64
+ @gameplay.ai.stack.clear << (Card.new(:suit => :clubs, :value => 12))
65
+ @gameplay.player.stack.clear << (Card.new(:suit => :hearts, :value => 3))
66
+ @gameplay.show_cards
67
+ @gameplay.contest[:winner].must_equal @gameplay.ai
68
+ end
69
+
70
+ it "must pick the player when they have the highest card" do
71
+ @gameplay.ai.stack.clear << (Card.new(:suit => :clubs, :value => 1))
72
+ @gameplay.player.stack.clear << (Card.new(:suit => :hearts, :value => 6))
73
+ @gameplay.show_cards
74
+ @gameplay.contest[:winner].must_equal @gameplay.player
75
+ end
76
+ end
77
+
78
+ describe "#discard" do
79
+ it "must give the cards to the ai if it wins" do
80
+ @gameplay.ai.stack.clear << (Card.new(:suit => :clubs, :value => 12))
81
+ @gameplay.player.stack.clear << (Card.new(:suit => :hearts, :value => 3))
82
+ @gameplay.show_cards
83
+ result = @gameplay.contest
84
+ unless result[:winner] == :war
85
+ # TODO get rid of all :war references
86
+ @gameplay.discard(result)
87
+ end
88
+ @gameplay.ai.discard.length.must_equal 2
89
+ end
90
+
91
+ it "must give the cards to the player if they win" do
92
+ @gameplay.ai.stack.clear << (Card.new(:suit => :clubs, :value => 4))
93
+ @gameplay.player.stack.clear << (Card.new(:suit => :hearts, :value => 9))
94
+ @gameplay.show_cards
95
+ result = @gameplay.contest
96
+ if result[:winner] != :war
97
+ @gameplay.discard(result)
98
+ end
99
+ @gameplay.player.discard.length.must_equal 2
100
+ end
101
+ end
102
+
103
+ describe "#war" do
104
+ it "must play war when there is a draw" do
105
+ card_ai_1 = (Card.new(:suit => :clubs, :value => 5))
106
+ card_ai_2 = (Card.new(:suit => :spades, :value => 4))
107
+ card_ai_3 = (Card.new(:suit => :clubs, :value => 4))
108
+ card_player_1 = (Card.new(:suit => :hearts, :value => 4))
109
+ card_player_2 = (Card.new(:suit => :diamonds, :value => 4))
110
+ card_player_3 = (Card.new(:suit => :hearts, :value => 4))
111
+ @gameplay.ai.stack.clear << card_ai_1
112
+ @gameplay.ai.stack << card_ai_2
113
+ @gameplay.ai.stack << card_ai_3
114
+ @gameplay.player.stack.clear << card_player_1
115
+ @gameplay.player.stack << card_player_2
116
+ @gameplay.player.stack << card_player_3
117
+
118
+ @gameplay.show_cards
119
+ @gameplay.war?
120
+ result = @gameplay.contest
121
+
122
+ result[:ai_cards].must_be_instance_of Array
123
+ result[:ai_cards].last.must_be_instance_of Card
124
+ [card_ai_1, card_ai_2, card_ai_3].each { |card| result[:ai_cards].must_include card }
125
+ [card_player_1, card_player_2, card_player_3].each { |card| result[:player_cards].must_include card }
126
+ end
127
+ end
128
+
129
+ describe "#rearm" do
130
+ it "must move discard pile to stack when stack is empty" do
131
+ @gameplay.ai.stack.clear << (Card.new(:suit => :clubs, :value => 12))
132
+ @gameplay.ai.stack << (Card.new(:suit => :hearts, :value => 3))
133
+ @gameplay.player.stack.clear << (Card.new(:suit => :clubs, :value => 4))
134
+ @gameplay.player.stack << (Card.new(:suit => :hearts, :value => 11))
135
+
136
+ @gameplay.ai.stack.length.must_equal 2
137
+
138
+ 2.times do
139
+ @gameplay.show_cards
140
+ @gameplay.discard(@gameplay.contest)
141
+ end
142
+
143
+ @gameplay.ai.stack.length.must_equal 0
144
+ @gameplay.player.stack.length.must_equal 0
145
+ @gameplay.ai.discard.length.must_equal 2
146
+ @gameplay.player.discard.length.must_equal 2
147
+
148
+ @gameplay.rearm?
149
+
150
+ @gameplay.ai.stack.length.must_equal 2, "ai stack has some cards now"
151
+ @gameplay.player.stack.length.must_equal 2, "player stack has some cards now"
152
+
153
+ @gameplay.ai.stack.last.must_be_instance_of Card
154
+ @gameplay.player.stack.last.must_be_instance_of Card
155
+
156
+ @gameplay.ai.discard.length.must_equal 0
157
+ @gameplay.player.discard.length.must_equal 0
158
+ end
159
+ end
160
+
161
+ describe "#game_over?" do
162
+ def setup
163
+ @deck = Deck.new
164
+ player = Player.new
165
+ ai = Ai.new
166
+ @gameplay = Gameplay.new(:deck => @deck, :player => player, :ai => ai)
167
+ @gameplay.ai.stack.clear << (Card.new(:suit => :clubs, :value => 2))
168
+ @gameplay.ai.stack << (Card.new(:suit => :hearts, :value => 1))
169
+ @gameplay.player.stack.clear << (Card.new(:suit => :clubs, :value => 12))
170
+ @gameplay.player.stack << (Card.new(:suit => :hearts, :value => 11))
171
+ end
172
+
173
+ it "must end the game when a participant is out of cards" do
174
+ skip "you'll need to mock stdout and stderr first. Of course you'll have to learn how before doing that."
175
+ 2.times do
176
+ @gameplay.show_cards
177
+ @gameplay.discard(@gameplay.contest)
178
+ end
179
+ lambda do
180
+ @gameplay.game_over?
181
+ end.must_output(STDOUT, STDERR) {"Game Over"; exit}
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,52 @@
1
+ require_relative '../spec_helper'
2
+
3
+ module Cardgame
4
+ describe Player do
5
+ #def setup
6
+ #@deck = Deck.new
7
+ #@player = Player.new
8
+ #@player = Player.new
9
+ #@gameplay = Gameplay.new(:deck => @deck, :player => @player, :ai => @ai)
10
+ #@player = @gameplay.player
11
+ #@gameplay.deal
12
+ #end
13
+
14
+ it "must be an instance of Player" do
15
+ Player.new.must_be_instance_of Player
16
+ end
17
+
18
+ describe "#stack" do
19
+ def setup
20
+ @player = Player.new
21
+ card = Card.new(:suit => :hearts, :value => 6)
22
+ @player.stack << card
23
+ end
24
+ it "player must have a stack of cards" do
25
+ @player.stack.first.must_be_instance_of Card
26
+ end
27
+ end
28
+ describe "#discard" do
29
+ def setup
30
+ @player = Player.new
31
+ @player.discard << Card.new(:suit => :clubs, :value => 11)
32
+ end
33
+
34
+ it "must have a discard of Card objects" do
35
+ @player.discard.first.must_be_instance_of Card
36
+ end
37
+
38
+ it "must be able to append cards on the end" do
39
+ original_discard_length = @player.discard.length
40
+ @player.discard << Card.new(:suit => :spades, :value => 7)
41
+ @player.discard.length.must_equal (original_discard_length + 1)
42
+ end
43
+ end
44
+
45
+ describe "#name" do
46
+ it "player must have a name" do
47
+ Player.new.name.must_equal "Player"
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ require_relative './spec_helper'
2
+
3
+ module Cardgame
4
+ describe Game do
5
+ it "must be an instance of Game" do
6
+ Game.new.must_be_instance_of Game
7
+ end
8
+
9
+ it "must have a deck of 52 cards at all times" do
10
+
11
+ class Game
12
+
13
+ def excercise
14
+ @gameplay.game_over?
15
+ @gameplay.rearm?
16
+ @gameplay.show_cards
17
+ @gameplay.war?
18
+ result = @gameplay.contest
19
+ @gameplay.discard(result)
20
+ end
21
+
22
+ def sum_cards
23
+ (@gameplay.ai.stack.length + @gameplay.ai.discard.length + @gameplay.player.stack.length + @gameplay.player.discard.length)
24
+ end
25
+ end
26
+ game = Game.new
27
+ 50.times do
28
+ game.excercise
29
+ game.sum_cards.must_equal 52
30
+ end
31
+ end
32
+ end
33
+ end
data/warcards.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/warcards/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Robie Lutsey"]
6
+ gem.email = ["robie1373@gmail.com"]
7
+ gem.description = %q{An addictive game of War! to help slog through flash-card memorization}
8
+ gem.summary = %q{Play a game of War! against the computer. If your card is higher, you get a chance to answer the flash-card question. If you get it correct, you win the round! By the time you win the game, you should really know your stuff!}
9
+ gem.homepage = "http://robie1373.github.com/warcards"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "warcards"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Cardgame::VERSION
17
+
18
+ # specify any dependencies here
19
+ gem.add_development_dependency 'rb-fsevent', '~>0.9.1'
20
+ gem.add_development_dependency 'minitest-spec', '~>0.0.2'
21
+ gem.add_development_dependency 'minitest-reporters', '~>0.9.0'
22
+ gem.add_development_dependency 'guard', '~>1.2.3'
23
+ gem.add_development_dependency 'guard-minitest', '~>0.5.0'
24
+ gem.add_development_dependency 'growl', '~>1.0.3'
25
+ gem.add_development_dependency 'turn', '~>0.9.6'
26
+
27
+ # specify run dependencies here
28
+ gem.add_dependency 'bundler', "~>1.1"
29
+ gem.add_dependency 'querinator'
30
+ gem.add_dependency 'rake', '~>0.9.2'
31
+ end
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: warcards
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Robie Lutsey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rb-fsevent
16
+ requirement: &70228092528620 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.1
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70228092528620
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest-spec
27
+ requirement: &70228092526640 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.2
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70228092526640
36
+ - !ruby/object:Gem::Dependency
37
+ name: minitest-reporters
38
+ requirement: &70228092524740 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.9.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70228092524740
47
+ - !ruby/object:Gem::Dependency
48
+ name: guard
49
+ requirement: &70228092523220 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.3
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70228092523220
58
+ - !ruby/object:Gem::Dependency
59
+ name: guard-minitest
60
+ requirement: &70228092521400 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 0.5.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70228092521400
69
+ - !ruby/object:Gem::Dependency
70
+ name: growl
71
+ requirement: &70228092519160 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.0.3
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70228092519160
80
+ - !ruby/object:Gem::Dependency
81
+ name: turn
82
+ requirement: &70228092517300 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 0.9.6
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70228092517300
91
+ - !ruby/object:Gem::Dependency
92
+ name: bundler
93
+ requirement: &70228092516240 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: '1.1'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *70228092516240
102
+ - !ruby/object:Gem::Dependency
103
+ name: querinator
104
+ requirement: &70228092515120 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: *70228092515120
113
+ - !ruby/object:Gem::Dependency
114
+ name: rake
115
+ requirement: &70228092513820 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ~>
119
+ - !ruby/object:Gem::Version
120
+ version: 0.9.2
121
+ type: :runtime
122
+ prerelease: false
123
+ version_requirements: *70228092513820
124
+ description: An addictive game of War! to help slog through flash-card memorization
125
+ email:
126
+ - robie1373@gmail.com
127
+ executables:
128
+ - warcards
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitattributes
133
+ - .gitignore
134
+ - .travis.yml
135
+ - Gemfile
136
+ - Gemfile.lock
137
+ - Guardfile
138
+ - LICENSE
139
+ - README.markdown
140
+ - Rakefile
141
+ - bin/warcards
142
+ - lib/warcards.rb
143
+ - lib/warcards/ai.rb
144
+ - lib/warcards/card.rb
145
+ - lib/warcards/deck.rb
146
+ - lib/warcards/gameplay.rb
147
+ - lib/warcards/player.rb
148
+ - lib/warcards/version.rb
149
+ - spec/responsibilities.md
150
+ - spec/spec_helper.rb
151
+ - spec/test_question_file.txt
152
+ - spec/warcards/ai_spec.rb
153
+ - spec/warcards/card_spec.rb
154
+ - spec/warcards/deck_spec.rb
155
+ - spec/warcards/gameplay_spec.rb
156
+ - spec/warcards/player_spec.rb
157
+ - spec/warcards_spec.rb
158
+ - warcards.gemspec
159
+ homepage: http://robie1373.github.com/warcards
160
+ licenses: []
161
+ post_install_message:
162
+ rdoc_options: []
163
+ require_paths:
164
+ - lib
165
+ required_ruby_version: !ruby/object:Gem::Requirement
166
+ none: false
167
+ requirements:
168
+ - - ! '>='
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ none: false
173
+ requirements:
174
+ - - ! '>='
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 1.8.10
180
+ signing_key:
181
+ specification_version: 3
182
+ summary: Play a game of War! against the computer. If your card is higher, you get
183
+ a chance to answer the flash-card question. If you get it correct, you win the round!
184
+ By the time you win the game, you should really know your stuff!
185
+ test_files:
186
+ - spec/responsibilities.md
187
+ - spec/spec_helper.rb
188
+ - spec/test_question_file.txt
189
+ - spec/warcards/ai_spec.rb
190
+ - spec/warcards/card_spec.rb
191
+ - spec/warcards/deck_spec.rb
192
+ - spec/warcards/gameplay_spec.rb
193
+ - spec/warcards/player_spec.rb
194
+ - spec/warcards_spec.rb