bashrw_ttt 0.1.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.
Files changed (130) hide show
  1. data/bin/play.rb +10 -0
  2. data/lib/ttt/ai.rb +33 -0
  3. data/lib/ttt/ai_easy.rb +17 -0
  4. data/lib/ttt/ai_hard.rb +21 -0
  5. data/lib/ttt/ai_medium.rb +21 -0
  6. data/lib/ttt/ai_medium_back.rb +58 -0
  7. data/lib/ttt/board.rb +37 -0
  8. data/lib/ttt/config_helper.rb +53 -0
  9. data/lib/ttt/config_options.rb +27 -0
  10. data/lib/ttt/context.rb +214 -0
  11. data/lib/ttt/four_by_four.rb +62 -0
  12. data/lib/ttt/game.rb +94 -0
  13. data/lib/ttt/game_history.rb +37 -0
  14. data/lib/ttt/game_interactor.rb +126 -0
  15. data/lib/ttt/human.rb +12 -0
  16. data/lib/ttt/interfaces/cli/lib/cli/board_selection.rb +34 -0
  17. data/lib/ttt/interfaces/cli/lib/cli/cli_game.rb +186 -0
  18. data/lib/ttt/interfaces/cli/lib/cli/cli_presenter.rb +216 -0
  19. data/lib/ttt/interfaces/cli/lib/cli/clio.rb +17 -0
  20. data/lib/ttt/interfaces/cli/lib/cli/play_again.rb +38 -0
  21. data/lib/ttt/interfaces/cli/lib/cli/player_selection.rb +43 -0
  22. data/lib/ttt/interfaces/cli/lib/cli/selection.rb +8 -0
  23. data/lib/ttt/interfaces/cli/lib/cli/walk_history.rb +48 -0
  24. data/lib/ttt/interfaces/cli/spec/cli/board_selection_spec.rb +29 -0
  25. data/lib/ttt/interfaces/cli/spec/cli/cli_game_spec.rb +376 -0
  26. data/lib/ttt/interfaces/cli/spec/cli/cli_presenter_spec.rb +147 -0
  27. data/lib/ttt/interfaces/cli/spec/cli/play_again_spec.rb +39 -0
  28. data/lib/ttt/interfaces/cli/spec/cli/player_selection_spec.rb +62 -0
  29. data/lib/ttt/interfaces/cli/spec/cli/walk_history_spec.rb +115 -0
  30. data/lib/ttt/interfaces/cli/spec/spec_helper.rb +14 -0
  31. data/lib/ttt/interfaces/limelight/four_by_four/props.rb +1 -0
  32. data/lib/ttt/interfaces/limelight/four_by_four/styles.rb +74 -0
  33. data/lib/ttt/interfaces/limelight/four_by_four_finished/props.rb +1 -0
  34. data/lib/ttt/interfaces/limelight/four_by_four_finished/styles.rb +74 -0
  35. data/lib/ttt/interfaces/limelight/game_list/players/load_button.rb +10 -0
  36. data/lib/ttt/interfaces/limelight/game_list/props.rb +17 -0
  37. data/lib/ttt/interfaces/limelight/game_list/styles.rb +8 -0
  38. data/lib/ttt/interfaces/limelight/main_menu/players/exit_ttt.rb +3 -0
  39. data/lib/ttt/interfaces/limelight/main_menu/players/load_game.rb +3 -0
  40. data/lib/ttt/interfaces/limelight/main_menu/players/new_game.rb +3 -0
  41. data/lib/ttt/interfaces/limelight/main_menu/props.rb +17 -0
  42. data/lib/ttt/interfaces/limelight/new_game/players/board_type.rb +1 -0
  43. data/lib/ttt/interfaces/limelight/new_game/players/new_game.rb +5 -0
  44. data/lib/ttt/interfaces/limelight/new_game/players/player_type.rb +1 -0
  45. data/lib/ttt/interfaces/limelight/new_game/players/setup_button.rb +21 -0
  46. data/lib/ttt/interfaces/limelight/new_game/props.rb +21 -0
  47. data/lib/ttt/interfaces/limelight/new_game/styles.rb +23 -0
  48. data/lib/ttt/interfaces/limelight/partials/board_partial.rb +14 -0
  49. data/lib/ttt/interfaces/limelight/partials/menu_button_partial.rb +5 -0
  50. data/lib/ttt/interfaces/limelight/partials/move_history_partial.rb +6 -0
  51. data/lib/ttt/interfaces/limelight/partials/title_history_partial.rb +10 -0
  52. data/lib/ttt/interfaces/limelight/players/board.rb +3 -0
  53. data/lib/ttt/interfaces/limelight/players/game.rb +4 -0
  54. data/lib/ttt/interfaces/limelight/players/generic_move_history.rb +5 -0
  55. data/lib/ttt/interfaces/limelight/players/generic_player.rb +8 -0
  56. data/lib/ttt/interfaces/limelight/players/left_button.rb +3 -0
  57. data/lib/ttt/interfaces/limelight/players/main_menu.rb +3 -0
  58. data/lib/ttt/interfaces/limelight/players/right_button.rb +3 -0
  59. data/lib/ttt/interfaces/limelight/playscripts/game_playscript.rb +169 -0
  60. data/lib/ttt/interfaces/limelight/production.rb +14 -0
  61. data/lib/ttt/interfaces/limelight/spec/game_playscript_spec.rb +218 -0
  62. data/lib/ttt/interfaces/limelight/spec/main_menu/main_menu_spec.rb +38 -0
  63. data/lib/ttt/interfaces/limelight/spec/new_game/new_game_spec.rb +45 -0
  64. data/lib/ttt/interfaces/limelight/spec/spec_helper.rb +8 -0
  65. data/lib/ttt/interfaces/limelight/stages.rb +6 -0
  66. data/lib/ttt/interfaces/limelight/styles.rb +119 -0
  67. data/lib/ttt/interfaces/limelight/three_by_three/props.rb +1 -0
  68. data/lib/ttt/interfaces/limelight/three_by_three/styles.rb +39 -0
  69. data/lib/ttt/interfaces/limelight/three_by_three_by_three/props.rb +1 -0
  70. data/lib/ttt/interfaces/limelight/three_by_three_by_three/styles.rb +119 -0
  71. data/lib/ttt/interfaces/limelight/three_by_three_by_three_finished/props.rb +1 -0
  72. data/lib/ttt/interfaces/limelight/three_by_three_by_three_finished/styles.rb +119 -0
  73. data/lib/ttt/interfaces/limelight/three_by_three_finished/props.rb +1 -0
  74. data/lib/ttt/interfaces/limelight/three_by_three_finished/styles.rb +39 -0
  75. data/lib/ttt/interfaces/rails/app/controllers/application_controller.rb +3 -0
  76. data/lib/ttt/interfaces/rails/app/controllers/ttt_games_controller.rb +86 -0
  77. data/lib/ttt/interfaces/rails/app/helpers/application_helper.rb +2 -0
  78. data/lib/ttt/interfaces/rails/app/models/ttt_game.rb +34 -0
  79. data/lib/ttt/interfaces/rails/app/presenters/web_game_presenter.rb +159 -0
  80. data/lib/ttt/interfaces/rails/autotest/discover.rb +1 -0
  81. data/lib/ttt/interfaces/rails/config/application.rb +67 -0
  82. data/lib/ttt/interfaces/rails/config/boot.rb +6 -0
  83. data/lib/ttt/interfaces/rails/config/environment.rb +5 -0
  84. data/lib/ttt/interfaces/rails/config/environments/development.rb +37 -0
  85. data/lib/ttt/interfaces/rails/config/environments/production.rb +67 -0
  86. data/lib/ttt/interfaces/rails/config/environments/test.rb +37 -0
  87. data/lib/ttt/interfaces/rails/config/initializers/backtrace_silencers.rb +7 -0
  88. data/lib/ttt/interfaces/rails/config/initializers/inflections.rb +15 -0
  89. data/lib/ttt/interfaces/rails/config/initializers/mime_types.rb +5 -0
  90. data/lib/ttt/interfaces/rails/config/initializers/secret_token.rb +7 -0
  91. data/lib/ttt/interfaces/rails/config/initializers/session_store.rb +8 -0
  92. data/lib/ttt/interfaces/rails/config/initializers/wrap_parameters.rb +14 -0
  93. data/lib/ttt/interfaces/rails/config/routes.rb +49 -0
  94. data/lib/ttt/interfaces/rails/db/schema.rb +28 -0
  95. data/lib/ttt/interfaces/rails/db/seeds.rb +7 -0
  96. data/lib/ttt/interfaces/rails/spec/controllers/ttt_games_controller_spec.rb +211 -0
  97. data/lib/ttt/interfaces/rails/spec/models/ttt_game_spec.rb +76 -0
  98. data/lib/ttt/interfaces/rails/spec/presenters/web_game_presenter_spec.rb +52 -0
  99. data/lib/ttt/interfaces/rails/spec/spec_helper.rb +13 -0
  100. data/lib/ttt/interfaces/web_interface/html_generator.rb +76 -0
  101. data/lib/ttt/interfaces/web_interface/web_game_presenter.rb +0 -0
  102. data/lib/ttt/minimax.rb +46 -0
  103. data/lib/ttt/move_history.rb +10 -0
  104. data/lib/ttt/move_traverser.rb +49 -0
  105. data/lib/ttt/player.rb +15 -0
  106. data/lib/ttt/riak_db.rb +53 -0
  107. data/lib/ttt/setup.rb +59 -0
  108. data/lib/ttt/three_by_three.rb +35 -0
  109. data/lib/ttt/three_by_three_by_three.rb +37 -0
  110. data/spec/spec_helper.rb +22 -0
  111. data/spec/ttt/ai_easy_spec.rb +15 -0
  112. data/spec/ttt/ai_hard_spec.rb +76 -0
  113. data/spec/ttt/ai_medium_spec.rb +65 -0
  114. data/spec/ttt/ai_spec.rb +50 -0
  115. data/spec/ttt/board_spec.rb +96 -0
  116. data/spec/ttt/config_helper_spec.rb +54 -0
  117. data/spec/ttt/context_spec.rb +398 -0
  118. data/spec/ttt/four_by_four_spec.rb +112 -0
  119. data/spec/ttt/game_history_spec.rb +41 -0
  120. data/spec/ttt/game_interactor_spec.rb +197 -0
  121. data/spec/ttt/game_spec.rb +246 -0
  122. data/spec/ttt/human_spec.rb +18 -0
  123. data/spec/ttt/move_history_spec.rb +13 -0
  124. data/spec/ttt/move_traverser_spec.rb +75 -0
  125. data/spec/ttt/player_spec.rb +13 -0
  126. data/spec/ttt/riak_db_spec.rb +64 -0
  127. data/spec/ttt/setup_spec.rb +63 -0
  128. data/spec/ttt/three_by_three_by_three_spec.rb +130 -0
  129. data/spec/ttt/three_by_three_spec.rb +110 -0
  130. metadata +238 -0
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ module TTT
4
+ describe FourByFour do
5
+ let(:board) { FourByFour.new }
6
+
7
+ describe "#initialize" do
8
+ it "board has length 16" do
9
+ board[].length.should == 16
10
+ end
11
+ end
12
+
13
+ describe "#update" do
14
+ it "updates the game board after move is received" do
15
+ board.update(1, "x")
16
+ board[].should == [" ", "x", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]
17
+ end
18
+ end
19
+
20
+ describe "#empty?" do
21
+ it "returns true when board is empty" do
22
+ board.empty?.should == true
23
+ end
24
+
25
+ it "returns false when board is not empty" do
26
+ board.update(1, "x")
27
+ board.empty?.should == false
28
+ end
29
+ end
30
+
31
+ describe "#full?" do
32
+ it "returns true when board is full" do
33
+ 16.times do |n|
34
+ board.update(n, "o")
35
+ end
36
+ board.full?.should == true
37
+ end
38
+
39
+ it "returns false when board isn't full" do
40
+ board.update(1, "x")
41
+ board.full?.should == false
42
+ end
43
+ end
44
+
45
+ describe "#free?" do
46
+ it "returns false when board is occupied at a given cell" do
47
+ board.update(1, "x")
48
+ board.free?(1).should == false
49
+ end
50
+
51
+ it "returns true when board is not occupied at a given cell" do
52
+ board.free?(0).should == true
53
+ end
54
+ end
55
+
56
+ describe "#draw_game?" do
57
+ it "returns false when board is not full" do
58
+ board.draw_game?.should == false
59
+ end
60
+
61
+ it "returns true when board is full" do
62
+ board[] = ["x", "o", "x", "x", "o", "o", "o", "x", "o", "x", "o", "o", "x", "o", "x", "x"]
63
+ board.draw_game?.should == true
64
+ end
65
+ end
66
+
67
+ describe "#winner?" do
68
+ it "returns false when the board has no winner" do
69
+ board.winner?.should == false
70
+ end
71
+
72
+ it "returns true when the board has a four-in-a-row horizontal winner" do
73
+ board[] = ["x", "x", "x", "x", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]
74
+ board.winner?.should == true
75
+ end
76
+
77
+ it "returns true when the board has a four-in-a-row vertical winner" do
78
+ board[] = ["x", " ", " ", " ", "x", " ", " ", " ", "x", " ", " ", " ", "x", " ", " ", " "]
79
+ board.winner?.should == true
80
+ end
81
+
82
+ it "returns true when the board has a four-in-a-row diagonal winner" do
83
+ board[] = ["x", " ", " ", " ", " ", "x", " ", " ", " ", " ", "x", " ", " ", " ", " ", "x"]
84
+ board.winner?.should == true
85
+ end
86
+
87
+ it "returns true when the board has a 2x2 block winner" do
88
+ board[] = ["x", "x", "o", " ", "x", "x", "o", " ", " ", " ", " ", " ", " ", " ", " ", " "]
89
+ board.winner?.should == true
90
+ end
91
+ end
92
+
93
+ describe "#finished?" do
94
+ it "returns false when board is not full, no win, or no draw" do
95
+ board.finished?.should == false
96
+ end
97
+
98
+ it "returns true when board has a win" do
99
+ board.update(0, 'x')
100
+ board.update(1, 'x')
101
+ board.update(2, 'x')
102
+ board.update(3, 'x')
103
+ board.finished?.should == true
104
+ end
105
+
106
+ it "returns true when board has a draw" do
107
+ board[] = ["x", "o", "x", "o", "x", "o", "x", "o", "o", "x", "o", "x", "o", "x", "o", "x"]
108
+ board.finished?.should == true
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module TTT
4
+ describe GameHistory do
5
+ let(:setup) { Setup.new }
6
+ let(:players) { setup.players }
7
+ let(:boards) { setup.boards }
8
+ let(:game) { setup.new_game(player1: players.first, player2: players.first, board: boards.first) }
9
+ let(:history) { game.history }
10
+
11
+ describe "#new" do
12
+ it "creates a new game history object" do
13
+ history.should respond_to(:history)
14
+ history.should respond_to(:move_traverser)
15
+ end
16
+ end
17
+
18
+ describe "#record_move" do
19
+ it "records each move and side" do
20
+ game.history.should_receive(:record_move).with(0, 'x')
21
+ game.record_move(0)
22
+ end
23
+ end
24
+
25
+ describe "#show" do
26
+ it "returns the game history" do
27
+ game.show_history.should == []
28
+ game.record_move(0, 'x')
29
+ game.show_history.include? MoveHistory.new(:side => "x", :move => 0)
30
+ end
31
+ end
32
+
33
+ describe "#inc_move_index" do
34
+ it "increments the move index for the move traverser" do
35
+ game.history.move_traverser.move_index = 0
36
+ game.history.record_move(0, 'x')
37
+ game.history.move_traverser.move_index.should == 1
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,197 @@
1
+ require 'spec_helper'
2
+
3
+ module TTT
4
+ describe GameInteractor do
5
+ let(:game) { Game.new(player1: Human.new(side: "x"), player2: Human.new(side: "o"), board: ThreeByThree.new, history: GameHistory.new) }
6
+ let(:ai_game){ Game.new(player1: AIEasy.new(side: "x"), player2: AIEasy.new(side: "o"), board: ThreeByThree.new, history: GameHistory.new) }
7
+ let(:bucket) { "game_interactor_bucket" }
8
+ let(:db) { RiakDB.new(bucket: bucket, port: 8091) }
9
+ let(:gi) { GameInteractor.new(db) }
10
+
11
+ describe "#ai_move?" do
12
+ it "returns true if the next move is from an AI player" do
13
+ gi.ai_move?(ai_game).should == true
14
+ end
15
+
16
+ it "returns false if the next move is not from an AI player" do
17
+ gi.ai_move?(game).should == false
18
+ end
19
+ end
20
+
21
+ describe "#ai_move" do
22
+ it "directs the ai to move, side effect is board is updated and current player switched" do
23
+ cur_player = ai_game.current_player
24
+ board = ai_game.board.board.dup
25
+ id = gi.add_game(ai_game)
26
+ gi.ai_move(id, ai_game)
27
+ board.should_not == ai_game.board.board
28
+ cur_player.should_not.eql? ai_game.current_player
29
+ ai_game.history.history.length.should == 1
30
+ end
31
+
32
+ it "does nothing if the current player is a human player" do
33
+ cur_player = game.current_player
34
+ board = game.board.board.dup
35
+ id = gi.add_game(game)
36
+ gi.ai_move(id, game)
37
+ board.should == game.board.board
38
+ cur_player.should.eql? game.current_player
39
+ game.history.history.length.should == 0
40
+ end
41
+ end
42
+
43
+ describe "#finished?" do
44
+ it "returns true if the game is over" do
45
+ game.board.board = %w(a b c d e f g h i)
46
+ gi.finished?(game).should == true
47
+ end
48
+
49
+ it "returns false if the game is not over" do
50
+ gi.finished?(game).should == false
51
+ end
52
+ end
53
+
54
+ describe "#winner?" do
55
+ it "returns true if a winner is found" do
56
+ game.board.board = %w(x x x x x x x x x)
57
+ gi.winner?(game).should == true
58
+ end
59
+
60
+ it "returns false if a winner is not found" do
61
+ gi.winner?(game).should == false
62
+ end
63
+ end
64
+
65
+ describe "#winner" do
66
+ it "returns 'Player 1' when the current player is player 2" do
67
+ game.switch_player()
68
+ gi.winner(game).should == "Player 1"
69
+ end
70
+
71
+ it "returns 'Player 2' when the current player is player 1" do
72
+ gi.winner(game).should == "Player 2"
73
+ end
74
+ end
75
+
76
+ describe "#draw?" do
77
+ it "returns true if the game is a draw" do
78
+ game.board.board = %w(a b c d e f g h i)
79
+ gi.draw?(game).should == true
80
+ end
81
+
82
+ it "returns false if the game is not a draw" do
83
+ game.board.board = Array.new(9, " ")
84
+ gi.draw?(game).should == false
85
+ end
86
+ end
87
+
88
+ describe "#which_board" do
89
+ it "returns `three_by_three` when the board type is 3x3" do
90
+ gi.which_board(game).should == "three_by_three"
91
+ end
92
+
93
+ it "returns `four_by_four` when the board type is 4x4" do
94
+ game.board = FourByFour.new
95
+ gi.which_board(game).should == "four_by_four"
96
+ end
97
+
98
+ it "returns `three_by_three_by_three` when the board type is 3x3x3" do
99
+ game.board = ThreeByThreeByThree.new
100
+ gi.which_board(game).should == "three_by_three_by_three"
101
+ end
102
+ end
103
+
104
+ describe "#valid_move?" do
105
+ it "returns true if the move input by the user is a valid move for the current game board" do
106
+ game.board.board = Array.new(9, " ")
107
+ gi.valid_move?(game, 1).should == true
108
+ end
109
+
110
+ it "returns false if the move input by the user is not a valid move for the current game board" do
111
+ game.board.board = %w(a b c d e f g h i)
112
+ gi.valid_move?(game, 1).should == false
113
+ end
114
+ end
115
+
116
+ describe "#get_history" do
117
+ it "returns an empty array when it's a new game (no move history)" do
118
+ gi.get_history(game).should == []
119
+ end
120
+
121
+ it "returns an array with one move history object after the first move" do
122
+ game.record_move(1)
123
+ move_hist_arr = gi.get_history(game)
124
+ move_hist_arr.length.should == 1
125
+ move_hist_arr[0].side.should == "x"
126
+ move_hist_arr[0].move.should == 1
127
+ end
128
+
129
+ it "returns an array of two move history objects after the second move" do
130
+ game.record_move(1)
131
+ game.switch_player
132
+ game.record_move(2)
133
+ move_hist_arr = gi.get_history(game)
134
+ move_hist_arr.length.should == 2
135
+ move_hist_arr[0].side.should == "x"
136
+ move_hist_arr[1].side.should == "o"
137
+ move_hist_arr[0].move.should == 1
138
+ move_hist_arr[1].move.should == 2
139
+ end
140
+ end
141
+
142
+ describe "#switch_player" do
143
+ it "sets the other player as the current player" do
144
+ game.current_player = game.player1
145
+ player2 = game.player2
146
+ gi.switch_player(game)
147
+ game.current_player.eql? player2
148
+ end
149
+ end
150
+
151
+ describe "#which_current_player?" do
152
+ it "returns 'Player 1' if the current player is player 1" do
153
+ game.current_player = game.player1
154
+ gi.which_current_player?(game).should == "Player 1"
155
+ end
156
+
157
+ it "returns 'Player 2' if the current player is player 2" do
158
+ game.current_player = game.player2
159
+ gi.which_current_player?(game).should == "Player 2"
160
+ end
161
+ end
162
+
163
+ describe "#board_arr" do
164
+ it "returns the board array" do
165
+ gi.board(game).should == Array.new(9, " ")
166
+ game.board[] = %w(a b c d e f g h i)
167
+ gi.board(game).should == %w(a b c d e f g h i)
168
+ end
169
+ end
170
+
171
+ describe "#mark_move" do
172
+ it "marks a move for a game" do
173
+ game.board[] = Array.new(9, " ")
174
+ gi.mark_move(game, 0, 'x')
175
+ game.board[].should == ['x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
176
+ gi.mark_move(game, 1, 'o')
177
+ game.board[].should == ['x', 'o', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
178
+ end
179
+ end
180
+
181
+ describe "#record_move" do
182
+ it "records the move for the game" do
183
+ gi.record_move(game, 0, 'x')
184
+ gi.get_history(game)[0].move.should == 0
185
+ gi.get_history(game)[0].side.should == 'x'
186
+ end
187
+ end
188
+
189
+ describe "#not_finished" do
190
+ it "returns the opposite of #finished?" do
191
+ gi.not_finished?(game).should == true
192
+ game.board[] = %w(a b c d e f g h i)
193
+ gi.not_finished?(game).should == false
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,246 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ module TTT
5
+ describe Game do
6
+ let(:setup) { Setup.new }
7
+ let(:players) { setup.players }
8
+ let(:boards) { setup.boards }
9
+ let(:game) { setup.new_game(player1: players.first, player2: players.first, board: boards.first) }
10
+
11
+ describe "#initialize" do
12
+ it "instantiated with a player1" do
13
+ game.player1.should_not == nil
14
+ end
15
+
16
+ it "instantiaed with a player1 with side 'x'" do
17
+ game.player1.side.should == "x"
18
+ end
19
+
20
+ it "instantiated with a player2" do
21
+ game.player2.should_not == nil
22
+ end
23
+
24
+ it "instantiated with a player2 with side 'o'" do
25
+ game.player2.side.should == "o"
26
+ end
27
+
28
+ it "has an empty board" do
29
+ game.board.should be_empty
30
+ end
31
+ end
32
+
33
+ describe "#current_player" do
34
+ it "is player1 at the beginning of a game" do
35
+ game.current_player.eql? game.player1
36
+ end
37
+
38
+ it "is player2 on the next turn" do
39
+ game.switch_player
40
+ game.current_player.eql? game.player2
41
+ end
42
+ end
43
+
44
+ describe "#mark_move" do
45
+ it "marks a move on the game board" do
46
+ game.mark_move(1)
47
+ game.board[].should == [" ", "x", " ", " ", " ", " ", " ", " ", " "]
48
+ end
49
+ end
50
+
51
+ describe "#switch_player" do
52
+ it "switches current player to the opposite player" do
53
+ game.switch_player
54
+ game.current_player.eql? game.player2
55
+ game.switch_player
56
+ game.current_player.eql? game.player1
57
+ end
58
+ end
59
+
60
+ describe "#next_move" do
61
+ before(:each) do
62
+ game.player1 = AIEasy.new(side: "x")
63
+ game.current_player = game.player1
64
+ end
65
+
66
+ it "prompts the AI to move next if the AI is the current player" do
67
+ game.player1.should_receive(:move).and_return(0)
68
+ game.next_move
69
+ end
70
+
71
+ it "returns an updated board reflecting the AI's move" do
72
+ game.player1.should_receive(:move).and_return(0)
73
+ game.next_move
74
+ game.board[].should == ["x", " ", " ", " ", " ", " ", " ", " ", " "]
75
+ end
76
+ end
77
+
78
+ describe "#record_move" do
79
+ it "invokes record_move on history" do
80
+ game.history.should_receive(:record_move)
81
+ game.record_move(0)
82
+ end
83
+ end
84
+
85
+ describe "#show_history" do
86
+ it "invokes show on history" do
87
+ game.history.should_receive(:show)
88
+ game.show_history
89
+ end
90
+ end
91
+
92
+ describe "#which_board?" do
93
+ it "returns `three_by_three` when the board type is 3x3" do
94
+ game.board = ThreeByThree.new
95
+ game.which_board.should == "three_by_three"
96
+ end
97
+
98
+ it "returns `four_by_four` when the board type is 4x4" do
99
+ game.board = FourByFour.new
100
+ game.which_board.should == "four_by_four"
101
+ end
102
+
103
+ it "returns `three_by_three_by_three` when the board type is 3x3x3" do
104
+ game.board = ThreeByThreeByThree.new
105
+ game.which_board.should == "three_by_three_by_three"
106
+ end
107
+ end
108
+
109
+ describe "#which_current_player" do
110
+ it "returns the current player" do
111
+ game.which_current_player?.should == "Player 1"
112
+ game.which_current_player?.should_not == "Player 2"
113
+ end
114
+ end
115
+
116
+ describe "#last_player?" do
117
+ it "returns the previous player" do
118
+ game.last_player.should == "Player 2"
119
+ game.last_player.should_not == "Player 1"
120
+ end
121
+ end
122
+
123
+ describe "#finished?" do
124
+ it "returns true if the game board is finished" do
125
+ game.board[] = Array.new(9, 'a')
126
+ game.finished?.should == true
127
+ end
128
+
129
+ it "returns false if the game board is not finished" do
130
+ game.finished?.should == false
131
+ end
132
+ end
133
+
134
+ describe "#not_finished?" do
135
+ it "returns true if the game board is not finished" do
136
+ game.not_finished?.should == true
137
+ end
138
+
139
+ it "returns false if the game board is finished" do
140
+ game.board[] = Array.new(9, 'a')
141
+ game.not_finished?.should == false
142
+ end
143
+ end
144
+
145
+ describe "#winner?" do
146
+ it "returns true if the game board has a winner" do
147
+ game.board[] = Array.new(9, 'x')
148
+ game.winner?.should == true
149
+ end
150
+
151
+ it "returns false if the game board does not have a winner" do
152
+ game.board[] = Array.new(9, ' ')
153
+ game.winner?.should == false
154
+ end
155
+ end
156
+
157
+ describe "#draw?" do
158
+ it "returns true if the game board has a draw" do
159
+ game.board[] = %w(a b c d e f g h i)
160
+ game.draw?.should == true
161
+ end
162
+
163
+ it "returns false if the game board does not have a draw" do
164
+ game.board[] = Array.new(9, ' ')
165
+ game.draw?.should == false
166
+ end
167
+ end
168
+
169
+ describe "#board_arr" do
170
+ it "returns the board array of the current game instance" do
171
+ game.board_arr.class.should == Array
172
+ game.board[] = Array.new(9, 'a')
173
+ game.board_arr.should == Array.new(9, 'a')
174
+ end
175
+ end
176
+
177
+ describe "#adjust_move_index" do
178
+ it "adjusts the game_history#move_traverser move_index" do
179
+ game.record_move(1, 'x')
180
+ game.history.move_traverser.move_index.should == 1
181
+ game.adjust_move_index(-1)
182
+ game.history.move_traverser.move_index.should == 0
183
+ end
184
+ end
185
+
186
+ describe "#initialize_history" do
187
+ it "resets the game_history to the length of the GameHistory#history array" do
188
+ game.record_move(1, 'x')
189
+ game.history.move_traverser.move_index.should == 1
190
+ game.adjust_move_index(-1)
191
+ game.history.move_traverser.move_index.should == 0
192
+ game.initialize_history
193
+ game.history.move_traverser.move_index.should == 1
194
+ end
195
+ end
196
+
197
+ describe "#get_history_board" do
198
+ it "returns the game board at the specified move number" do
199
+ game.record_move(0, 'o')
200
+ game.record_move(1, 'x')
201
+ game.record_move(2, 'x')
202
+ game.record_move(3, 'x')
203
+ game.record_move(4, 'x')
204
+ game.record_move(5, 'o')
205
+ game.record_move(6, 'o')
206
+ game.record_move(7, 'o')
207
+ game.record_move(8, 'o')
208
+ game.get_history_board(1).should == ['o', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
209
+ game.get_history_board(2).should == ['o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
210
+ game.get_history_board(3).should == ['o', 'x', 'x', ' ', ' ', ' ', ' ', ' ', ' ']
211
+ game.get_history_board(4).should == ['o', 'x', 'x', 'x', ' ', ' ', ' ', ' ', ' ']
212
+ game.get_history_board(5).should == ['o', 'x', 'x', 'x', 'x', ' ', ' ', ' ', ' ']
213
+ game.get_history_board(6).should == ['o', 'x', 'x', 'x', 'x', 'o', ' ', ' ', ' ']
214
+ game.get_history_board(7).should == ['o', 'x', 'x', 'x', 'x', 'o', 'o', ' ', ' ']
215
+ game.get_history_board(8).should == ['o', 'x', 'x', 'x', 'x', 'o', 'o', 'o', ' ']
216
+ game.get_history_board(9).should == ['o', 'x', 'x', 'x', 'x', 'o', 'o', 'o', 'o']
217
+ end
218
+ end
219
+
220
+ describe "#valid_move" do
221
+ before(:each) do
222
+ game.board.board = ['x', 'o', 'x', 'o', ' ', ' ', ' ', ' ', ' ']
223
+ end
224
+
225
+ it "returns true when a move is possible" do
226
+ game.valid_move?(4).should == true
227
+ game.valid_move?(5).should == true
228
+ game.valid_move?(6).should == true
229
+ game.valid_move?(7).should == true
230
+ game.valid_move?(8).should == true
231
+ end
232
+
233
+ it "returns false when a move the move's intended square has already been taken" do
234
+ game.valid_move?(0).should == false
235
+ game.valid_move?(1).should == false
236
+ game.valid_move?(2).should == false
237
+ game.valid_move?(3).should == false
238
+ end
239
+
240
+ it "returns false when input is not a number within 0 and the board length" do
241
+ game.valid_move?('z').should == false
242
+ game.valid_move?(123.123).should == false
243
+ end
244
+ end
245
+ end
246
+ end