warcards 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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