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.
- data/bin/play.rb +10 -0
- data/lib/ttt/ai.rb +33 -0
- data/lib/ttt/ai_easy.rb +17 -0
- data/lib/ttt/ai_hard.rb +21 -0
- data/lib/ttt/ai_medium.rb +21 -0
- data/lib/ttt/ai_medium_back.rb +58 -0
- data/lib/ttt/board.rb +37 -0
- data/lib/ttt/config_helper.rb +53 -0
- data/lib/ttt/config_options.rb +27 -0
- data/lib/ttt/context.rb +214 -0
- data/lib/ttt/four_by_four.rb +62 -0
- data/lib/ttt/game.rb +94 -0
- data/lib/ttt/game_history.rb +37 -0
- data/lib/ttt/game_interactor.rb +126 -0
- data/lib/ttt/human.rb +12 -0
- data/lib/ttt/interfaces/cli/lib/cli/board_selection.rb +34 -0
- data/lib/ttt/interfaces/cli/lib/cli/cli_game.rb +186 -0
- data/lib/ttt/interfaces/cli/lib/cli/cli_presenter.rb +216 -0
- data/lib/ttt/interfaces/cli/lib/cli/clio.rb +17 -0
- data/lib/ttt/interfaces/cli/lib/cli/play_again.rb +38 -0
- data/lib/ttt/interfaces/cli/lib/cli/player_selection.rb +43 -0
- data/lib/ttt/interfaces/cli/lib/cli/selection.rb +8 -0
- data/lib/ttt/interfaces/cli/lib/cli/walk_history.rb +48 -0
- data/lib/ttt/interfaces/cli/spec/cli/board_selection_spec.rb +29 -0
- data/lib/ttt/interfaces/cli/spec/cli/cli_game_spec.rb +376 -0
- data/lib/ttt/interfaces/cli/spec/cli/cli_presenter_spec.rb +147 -0
- data/lib/ttt/interfaces/cli/spec/cli/play_again_spec.rb +39 -0
- data/lib/ttt/interfaces/cli/spec/cli/player_selection_spec.rb +62 -0
- data/lib/ttt/interfaces/cli/spec/cli/walk_history_spec.rb +115 -0
- data/lib/ttt/interfaces/cli/spec/spec_helper.rb +14 -0
- data/lib/ttt/interfaces/limelight/four_by_four/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/four_by_four/styles.rb +74 -0
- data/lib/ttt/interfaces/limelight/four_by_four_finished/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/four_by_four_finished/styles.rb +74 -0
- data/lib/ttt/interfaces/limelight/game_list/players/load_button.rb +10 -0
- data/lib/ttt/interfaces/limelight/game_list/props.rb +17 -0
- data/lib/ttt/interfaces/limelight/game_list/styles.rb +8 -0
- data/lib/ttt/interfaces/limelight/main_menu/players/exit_ttt.rb +3 -0
- data/lib/ttt/interfaces/limelight/main_menu/players/load_game.rb +3 -0
- data/lib/ttt/interfaces/limelight/main_menu/players/new_game.rb +3 -0
- data/lib/ttt/interfaces/limelight/main_menu/props.rb +17 -0
- data/lib/ttt/interfaces/limelight/new_game/players/board_type.rb +1 -0
- data/lib/ttt/interfaces/limelight/new_game/players/new_game.rb +5 -0
- data/lib/ttt/interfaces/limelight/new_game/players/player_type.rb +1 -0
- data/lib/ttt/interfaces/limelight/new_game/players/setup_button.rb +21 -0
- data/lib/ttt/interfaces/limelight/new_game/props.rb +21 -0
- data/lib/ttt/interfaces/limelight/new_game/styles.rb +23 -0
- data/lib/ttt/interfaces/limelight/partials/board_partial.rb +14 -0
- data/lib/ttt/interfaces/limelight/partials/menu_button_partial.rb +5 -0
- data/lib/ttt/interfaces/limelight/partials/move_history_partial.rb +6 -0
- data/lib/ttt/interfaces/limelight/partials/title_history_partial.rb +10 -0
- data/lib/ttt/interfaces/limelight/players/board.rb +3 -0
- data/lib/ttt/interfaces/limelight/players/game.rb +4 -0
- data/lib/ttt/interfaces/limelight/players/generic_move_history.rb +5 -0
- data/lib/ttt/interfaces/limelight/players/generic_player.rb +8 -0
- data/lib/ttt/interfaces/limelight/players/left_button.rb +3 -0
- data/lib/ttt/interfaces/limelight/players/main_menu.rb +3 -0
- data/lib/ttt/interfaces/limelight/players/right_button.rb +3 -0
- data/lib/ttt/interfaces/limelight/playscripts/game_playscript.rb +169 -0
- data/lib/ttt/interfaces/limelight/production.rb +14 -0
- data/lib/ttt/interfaces/limelight/spec/game_playscript_spec.rb +218 -0
- data/lib/ttt/interfaces/limelight/spec/main_menu/main_menu_spec.rb +38 -0
- data/lib/ttt/interfaces/limelight/spec/new_game/new_game_spec.rb +45 -0
- data/lib/ttt/interfaces/limelight/spec/spec_helper.rb +8 -0
- data/lib/ttt/interfaces/limelight/stages.rb +6 -0
- data/lib/ttt/interfaces/limelight/styles.rb +119 -0
- data/lib/ttt/interfaces/limelight/three_by_three/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three/styles.rb +39 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three/styles.rb +119 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three_finished/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three_finished/styles.rb +119 -0
- data/lib/ttt/interfaces/limelight/three_by_three_finished/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three_finished/styles.rb +39 -0
- data/lib/ttt/interfaces/rails/app/controllers/application_controller.rb +3 -0
- data/lib/ttt/interfaces/rails/app/controllers/ttt_games_controller.rb +86 -0
- data/lib/ttt/interfaces/rails/app/helpers/application_helper.rb +2 -0
- data/lib/ttt/interfaces/rails/app/models/ttt_game.rb +34 -0
- data/lib/ttt/interfaces/rails/app/presenters/web_game_presenter.rb +159 -0
- data/lib/ttt/interfaces/rails/autotest/discover.rb +1 -0
- data/lib/ttt/interfaces/rails/config/application.rb +67 -0
- data/lib/ttt/interfaces/rails/config/boot.rb +6 -0
- data/lib/ttt/interfaces/rails/config/environment.rb +5 -0
- data/lib/ttt/interfaces/rails/config/environments/development.rb +37 -0
- data/lib/ttt/interfaces/rails/config/environments/production.rb +67 -0
- data/lib/ttt/interfaces/rails/config/environments/test.rb +37 -0
- data/lib/ttt/interfaces/rails/config/initializers/backtrace_silencers.rb +7 -0
- data/lib/ttt/interfaces/rails/config/initializers/inflections.rb +15 -0
- data/lib/ttt/interfaces/rails/config/initializers/mime_types.rb +5 -0
- data/lib/ttt/interfaces/rails/config/initializers/secret_token.rb +7 -0
- data/lib/ttt/interfaces/rails/config/initializers/session_store.rb +8 -0
- data/lib/ttt/interfaces/rails/config/initializers/wrap_parameters.rb +14 -0
- data/lib/ttt/interfaces/rails/config/routes.rb +49 -0
- data/lib/ttt/interfaces/rails/db/schema.rb +28 -0
- data/lib/ttt/interfaces/rails/db/seeds.rb +7 -0
- data/lib/ttt/interfaces/rails/spec/controllers/ttt_games_controller_spec.rb +211 -0
- data/lib/ttt/interfaces/rails/spec/models/ttt_game_spec.rb +76 -0
- data/lib/ttt/interfaces/rails/spec/presenters/web_game_presenter_spec.rb +52 -0
- data/lib/ttt/interfaces/rails/spec/spec_helper.rb +13 -0
- data/lib/ttt/interfaces/web_interface/html_generator.rb +76 -0
- data/lib/ttt/interfaces/web_interface/web_game_presenter.rb +0 -0
- data/lib/ttt/minimax.rb +46 -0
- data/lib/ttt/move_history.rb +10 -0
- data/lib/ttt/move_traverser.rb +49 -0
- data/lib/ttt/player.rb +15 -0
- data/lib/ttt/riak_db.rb +53 -0
- data/lib/ttt/setup.rb +59 -0
- data/lib/ttt/three_by_three.rb +35 -0
- data/lib/ttt/three_by_three_by_three.rb +37 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/ttt/ai_easy_spec.rb +15 -0
- data/spec/ttt/ai_hard_spec.rb +76 -0
- data/spec/ttt/ai_medium_spec.rb +65 -0
- data/spec/ttt/ai_spec.rb +50 -0
- data/spec/ttt/board_spec.rb +96 -0
- data/spec/ttt/config_helper_spec.rb +54 -0
- data/spec/ttt/context_spec.rb +398 -0
- data/spec/ttt/four_by_four_spec.rb +112 -0
- data/spec/ttt/game_history_spec.rb +41 -0
- data/spec/ttt/game_interactor_spec.rb +197 -0
- data/spec/ttt/game_spec.rb +246 -0
- data/spec/ttt/human_spec.rb +18 -0
- data/spec/ttt/move_history_spec.rb +13 -0
- data/spec/ttt/move_traverser_spec.rb +75 -0
- data/spec/ttt/player_spec.rb +13 -0
- data/spec/ttt/riak_db_spec.rb +64 -0
- data/spec/ttt/setup_spec.rb +63 -0
- data/spec/ttt/three_by_three_by_three_spec.rb +130 -0
- data/spec/ttt/three_by_three_spec.rb +110 -0
- 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
|