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
data/spec/ttt/ai_spec.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TTT
|
|
4
|
+
describe AI do
|
|
5
|
+
|
|
6
|
+
let(:ai) { AI.new(side: "x") }
|
|
7
|
+
let(:board) { ThreeByThree.new }
|
|
8
|
+
|
|
9
|
+
describe "#move" do
|
|
10
|
+
it "responds to message(:move)" do
|
|
11
|
+
ai.should respond_to(:move)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "#available_moves" do
|
|
16
|
+
it "returns an array of available moves" do
|
|
17
|
+
ai.board = board
|
|
18
|
+
ai.available_moves.should == [0,1,2,3,4,5,6,7,8]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "returns [] when no available moves are found" do
|
|
22
|
+
board[] = ["o", "x", "o", "x", "o", "x", "o", "x", "o"]
|
|
23
|
+
ai.board = board
|
|
24
|
+
ai.available_moves.should == []
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#undo_move" do
|
|
29
|
+
it "should revert the original game board back to its previous state" do
|
|
30
|
+
index = 3
|
|
31
|
+
ai.board = board
|
|
32
|
+
ai.board[][3] = "x"
|
|
33
|
+
ai.undo_move(index)
|
|
34
|
+
ai.board[][3].should == " "
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "#no_gui?" do
|
|
39
|
+
it "returns true" do
|
|
40
|
+
ai.no_gui?.should == true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#prompt" do
|
|
45
|
+
it "returns 'Computer thinking'" do
|
|
46
|
+
ai.prompt.should == "Computer thinking."
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TTT
|
|
4
|
+
describe Board do
|
|
5
|
+
let(:board) { ThreeByThree.new }
|
|
6
|
+
|
|
7
|
+
describe "#initialize" do
|
|
8
|
+
it "board has length 9" do
|
|
9
|
+
board[].length.should == 9
|
|
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
|
+
9.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"]
|
|
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 winner" do
|
|
73
|
+
board[] = ["x", "x", "x", "o", " ", "o", " ", " ", " "]
|
|
74
|
+
board.winner?.should == true
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "#finished?" do
|
|
79
|
+
it "returns false when board is not full, no win, or no draw" do
|
|
80
|
+
board.finished?.should == false
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "returns true when board has a win" do
|
|
84
|
+
board.update(0, 'x')
|
|
85
|
+
board.update(1, 'x')
|
|
86
|
+
board.update(2, 'x')
|
|
87
|
+
board.finished?.should == true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "returns true when board has a draw" do
|
|
91
|
+
board[] = ["x", "o", "x", "x", "o", "o", "o", "x", "o"]
|
|
92
|
+
board.finished?.should == true
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ttt/config_options'
|
|
3
|
+
|
|
4
|
+
module TTT
|
|
5
|
+
describe ConfigHelper do
|
|
6
|
+
describe "#self.player_types" do
|
|
7
|
+
it { described_class.player_types.should == ConfigOptions::HUMAN_READABLE_PLAYERS }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "#self.board_types" do
|
|
11
|
+
it { described_class.board_types.should == ConfigOptions::HUMAN_READABLE_BOARDS }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "#self.bucket" do
|
|
15
|
+
it { described_class.bucket.should == ConfigOptions::BUCKET }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "#self.port" do
|
|
19
|
+
it { described_class.port.should == ConfigOptions::PORT }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#self.http_backend" do
|
|
23
|
+
it { described_class.http_backend.should == ConfigOptions::HTTP_BACKEND }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe "#self.get_player_const" do
|
|
27
|
+
it { described_class.get_player_const("Human").should == Human }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "#self.get_board_const" do
|
|
31
|
+
it { described_class.get_board_const("3x3").should == ThreeByThree }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "#self.get_player_index" do
|
|
35
|
+
it { described_class.get_player_index("Human").should == ConfigOptions::HUMAN_READABLE_PLAYERS.index("Human") }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "#self.get_board_index" do
|
|
39
|
+
it { described_class.get_board_index("3x3").should == ConfigOptions::HUMAN_READABLE_BOARDS.index("3x3") }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "#self.get_db_const" do
|
|
43
|
+
it { described_class.get_db_const.should == ConfigOptions::DB }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#self.get_history_const" do
|
|
47
|
+
it { described_class.get_history_const.should == ConfigOptions::HISTORY }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "#self.get_game_interactor_const" do
|
|
51
|
+
it { described_class.get_game_interactor_const.should == ConfigOptions::INTERACTOR }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ttt/config_options'
|
|
3
|
+
|
|
4
|
+
module TTT
|
|
5
|
+
describe Context do
|
|
6
|
+
let(:context) { Context.instance }
|
|
7
|
+
let(:setup) { Setup.new }
|
|
8
|
+
let(:players) { setup.players }
|
|
9
|
+
let(:boards) { setup.boards }
|
|
10
|
+
let(:game) { setup.new_game(player1: players.first, player2: players.first, board: boards.first) }
|
|
11
|
+
|
|
12
|
+
before(:each) do
|
|
13
|
+
context.setup=(Setup)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "players" do
|
|
17
|
+
it "returns the list of player types supported by the library" do
|
|
18
|
+
context.players.should == ConfigOptions::HUMAN_READABLE_PLAYERS
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "boards" do
|
|
23
|
+
it "returns the list of board types supported by the library" do
|
|
24
|
+
context.boards.should == ConfigOptions::HUMAN_READABLE_BOARDS
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "setup" do
|
|
29
|
+
it "returns a reference to a TTT::Setup object" do
|
|
30
|
+
context.setup.class.should == TTT::Setup
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "add_game" do
|
|
35
|
+
it "adds a game to the db and returns the id" do
|
|
36
|
+
id = context.add_game(game)
|
|
37
|
+
id.should_not == nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "create_game" do
|
|
42
|
+
it "create a new game and adds it to the db, returning the id" do
|
|
43
|
+
id = context.create_game(players.first, players.first, boards.first)
|
|
44
|
+
context.get_game(id).should_not == nil
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "get_game" do
|
|
49
|
+
it "gets a game from the db and returns the game" do
|
|
50
|
+
game.player1.side = "get_game_test"
|
|
51
|
+
id = context.add_game(game)
|
|
52
|
+
retrieved_game = context.get_game(id)
|
|
53
|
+
retrieved_game.player1.side.should == game.player1.side
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "#delete_game" do
|
|
58
|
+
it "removes a game from the db" do
|
|
59
|
+
id = context.add_game(game)
|
|
60
|
+
context.delete_game(id)
|
|
61
|
+
context.get_game(id).should == nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe "#save_game" do
|
|
66
|
+
it "saves a game to the db" do
|
|
67
|
+
id = context.add_game(game)
|
|
68
|
+
added_game = context.get_game(id)
|
|
69
|
+
added_game.board[] = %w(a b c d e f g h i)
|
|
70
|
+
context.save_game(id, added_game)
|
|
71
|
+
saved_game = context.get_game(id)
|
|
72
|
+
added_game.board[].should == saved_game.board[]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "#update_game" do
|
|
77
|
+
before(:each) do
|
|
78
|
+
id = context.add_game(game)
|
|
79
|
+
context.update_game(id, 0, 'x')
|
|
80
|
+
@updated_game = context.get_game(id)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "updates a game in the db" do
|
|
84
|
+
@updated_game.board[][0].should == "x"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "records move history" do
|
|
88
|
+
@updated_game.history.history.length.should == 1
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "switches the player" do
|
|
92
|
+
@updated_game.current_player.eql? @updated_game.player2
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "returns nil if no game is associated with the id" do
|
|
96
|
+
context.update_game(10000000000, 0, 'x').should == nil
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe "#game_list" do
|
|
101
|
+
it "returns an array of game ids (Strings)" do
|
|
102
|
+
context.game_list.should_not == []
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "gets a list of all game id's from the db" do
|
|
106
|
+
id = context.add_game(game)
|
|
107
|
+
context.game_list.include? id
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe "#ai_move?" do
|
|
112
|
+
it "returns true if the next move is from an AI player" do
|
|
113
|
+
game.player1 = TTT::AIEasy.new(:side => "x")
|
|
114
|
+
game.current_player = game.player1
|
|
115
|
+
id = context.add_game(game)
|
|
116
|
+
context.ai_move?(id).should == true
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "returns false if the next move is not from an AI player" do
|
|
120
|
+
id = context.add_game(game)
|
|
121
|
+
context.ai_move?(id).should == false
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "returns nil if the game cannot be found" do
|
|
125
|
+
context.ai_move?(100000000000000).should == nil
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
describe "#ai_move" do
|
|
130
|
+
before(:each) do
|
|
131
|
+
game.player1 = AIEasy.new(:side => 'x')
|
|
132
|
+
game.current_player = game.player1
|
|
133
|
+
id = context.add_game(game)
|
|
134
|
+
context.ai_move(id)
|
|
135
|
+
@updated_game = context.get_game(id)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "gets an updated game with the board containing the ai move" do
|
|
139
|
+
@updated_game.board.empty?.should_not == true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "advances current player to the next player" do
|
|
143
|
+
@updated_game.current_player.eql? game.player2
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "records the game history for the ai move" do
|
|
147
|
+
@updated_game.history.history.length.should == 1
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe "#finished?" do
|
|
152
|
+
it "returns true if the game is over" do
|
|
153
|
+
game.board[] = %w(a b c d e f g h i)
|
|
154
|
+
id = context.add_game(game)
|
|
155
|
+
context.finished?(id).should == true
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "returns false if the game is not over" do
|
|
159
|
+
game.board[] = Array.new(9, " ")
|
|
160
|
+
id = context.add_game(game)
|
|
161
|
+
context.finished?(id).should == false
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "returns nil if the game is not found" do
|
|
165
|
+
context.finished?(100000000).should == nil
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
describe "#winner?" do
|
|
170
|
+
it "returns true if a winner is found" do
|
|
171
|
+
game.board[] = %w(x x x x x x x x x)
|
|
172
|
+
id = context.add_game(game)
|
|
173
|
+
context.winner?(id).should == true
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "returns false if a winner is not found" do
|
|
177
|
+
game.board[] = Array.new(9, " ")
|
|
178
|
+
id = context.add_game(game)
|
|
179
|
+
context.winner?(id).should == false
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "returns nil if no game exists for the provided id" do
|
|
183
|
+
context.winner?(100000000).should == nil
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
describe "#winner" do
|
|
188
|
+
it "returns the winner as a string: 'Player 1' or 'Player 2'" do
|
|
189
|
+
game.board[] = %w(x x x x x x x x x)
|
|
190
|
+
game.switch_player
|
|
191
|
+
id = context.add_game(game)
|
|
192
|
+
context.winner(id).should == "Player 1"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "returns nil if no game exists for the provided id" do
|
|
196
|
+
context.winner?(10000000000000).should == nil
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
describe "#draw?" do
|
|
201
|
+
it "returns true if the game is a draw" do
|
|
202
|
+
game.board[] = %w(a b c d e f g h i)
|
|
203
|
+
id = context.add_game(game)
|
|
204
|
+
context.draw?(id).should == true
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "returns false if the game is not a draw" do
|
|
208
|
+
game.board[] = Array.new(9, " ")
|
|
209
|
+
id = context.add_game(game)
|
|
210
|
+
context.draw?(id).should == false
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it "returns false if the game has a winner" do
|
|
214
|
+
game.board[] = %w(x x x x x x x x x)
|
|
215
|
+
id = context.add_game(game)
|
|
216
|
+
context.draw?(id).should == false
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "returns nil if there is no game for that id" do
|
|
220
|
+
context.draw?(1000000000).should == nil
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
describe "#which_board" do
|
|
225
|
+
it "returns `three_by_three` when the board type is 3x3" do
|
|
226
|
+
id = context.add_game(game)
|
|
227
|
+
context.which_board(id).should == "three_by_three"
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "returns `four_by_four` when the board type is 4x4" do
|
|
231
|
+
game.board = FourByFour.new
|
|
232
|
+
id = context.add_game(game)
|
|
233
|
+
context.which_board(id).should == "four_by_four"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it "returns `three_by_three_by_three` when the board type is 3x3x3" do
|
|
237
|
+
game.board = ThreeByThreeByThree.new
|
|
238
|
+
id = context.add_game(game)
|
|
239
|
+
context.which_board(id).should == "three_by_three_by_three"
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "returns nil if there is no game associated with the id" do
|
|
243
|
+
context.which_board(10000000000).should == nil
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
describe "#valid_move?" do
|
|
248
|
+
it "returns true if the move input by the user is a valid move for the current game board" do
|
|
249
|
+
id = context.add_game(game)
|
|
250
|
+
move = 0
|
|
251
|
+
context.valid_move?(id, move).should == true
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it "returns false if the move input by the user is not a valid move for the current game board" do
|
|
255
|
+
game.board[] = %w(x x x x x x x x x)
|
|
256
|
+
id = context.add_game(game)
|
|
257
|
+
move = 0
|
|
258
|
+
context.valid_move?(id, move).should == false
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it "returns nil if there is no game associated with the id" do
|
|
262
|
+
context.valid_move?(100000000000000, 0).should == nil
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
describe "#show_history" do
|
|
267
|
+
it "returns an array of move_history objects for the current game" do
|
|
268
|
+
id = context.add_game(game)
|
|
269
|
+
context.update_game(id, 0, 'x')
|
|
270
|
+
context.update_game(id, 1, 'o')
|
|
271
|
+
context.get_history(id).length.should == 2
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it "returns an empty array when no move has occurred" do
|
|
275
|
+
id = context.add_game(game)
|
|
276
|
+
context.get_history(id).should == []
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "returns nil if the game associated with the id doesn't exist" do
|
|
280
|
+
context.get_history(100000000000).should == nil
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
describe "#which_current_player?" do
|
|
285
|
+
it "returns a string of the current player" do
|
|
286
|
+
id = context.add_game(game)
|
|
287
|
+
context.which_current_player?(id).should == "Player 1"
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
it "returns nil if the game associated with the id doesn't exist" do
|
|
291
|
+
context.which_current_player?(100000000000000).should == nil
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
describe "#board_arr" do
|
|
296
|
+
it "returns the board array" do
|
|
297
|
+
id = context.add_game(game)
|
|
298
|
+
context.board(id).should == Array.new(9, " ")
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it "returns nil if the game associated with an id doesn't exist" do
|
|
302
|
+
context.board(10000000000).should == nil
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
describe "#adjust_move_index" do
|
|
307
|
+
before(:each) do
|
|
308
|
+
game.record_move(1, 'x')
|
|
309
|
+
game.record_move(2, 'o')
|
|
310
|
+
game.record_move(3, 'x')
|
|
311
|
+
game.record_move(4, 'o')
|
|
312
|
+
@id = context.add_game(game)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "adjusts a game's move traverser move index by -1 when it receives -1" do
|
|
316
|
+
cur_move_index = game.history.move_traverser.move_index
|
|
317
|
+
cur_move_index.should == 4
|
|
318
|
+
context.adjust_move_index(@id, -1)
|
|
319
|
+
updated_game = context.get_game(@id)
|
|
320
|
+
updated_game.history.move_traverser.move_index.should == 3
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
it "cannot move to a move index less than 0" do
|
|
324
|
+
context.adjust_move_index(@id, -4)
|
|
325
|
+
updated_game = context.get_game(@id)
|
|
326
|
+
updated_game.history.move_traverser.move_index.should == 0
|
|
327
|
+
context.adjust_move_index(@id, -3)
|
|
328
|
+
updated_game = context.get_game(@id)
|
|
329
|
+
updated_game.history.move_traverser.move_index.should == 0
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
it "cannot move to a move index greater than the max length of a game's move history" do
|
|
333
|
+
context.adjust_move_index(@id, 100)
|
|
334
|
+
updated_game = context.get_game(@id)
|
|
335
|
+
updated_game.history.move_traverser.move_index.should == 4
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it "adjusts a game's move traverser move index by 1 when it receives 1" do
|
|
339
|
+
context.adjust_move_index(@id, -2)
|
|
340
|
+
updated_game = context.get_game(@id)
|
|
341
|
+
updated_game.history.move_traverser.move_index.should == 2
|
|
342
|
+
context.adjust_move_index(@id, 1)
|
|
343
|
+
updated_game = context.get_game(@id)
|
|
344
|
+
updated_game.history.move_traverser.move_index.should == 3
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
describe "#get_history_board" do
|
|
349
|
+
it "returns the game's board as an array" do
|
|
350
|
+
id = context.add_game(game)
|
|
351
|
+
context.get_history_board(id).should == Array.new(9, " ")
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
describe "#initialize_history" do
|
|
356
|
+
before(:each) do
|
|
357
|
+
game.record_move(0, 'o')
|
|
358
|
+
game.record_move(1, 'x')
|
|
359
|
+
game.record_move(2, 'x')
|
|
360
|
+
game.record_move(3, 'x')
|
|
361
|
+
game.record_move(4, 'o')
|
|
362
|
+
game.record_move(5, 'o')
|
|
363
|
+
game.record_move(6, 'x')
|
|
364
|
+
game.record_move(7, 'o')
|
|
365
|
+
game.record_move(8, 'x')
|
|
366
|
+
@id = context.add_game(game)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it "returns the game's move history index to it the length of the number of moves made in the game" do
|
|
370
|
+
stored_game = context.get_game(@id)
|
|
371
|
+
stored_game.history.move_traverser.move_index.should == 9
|
|
372
|
+
context.adjust_move_index(@id, -9)
|
|
373
|
+
stored_game = context.get_game(@id)
|
|
374
|
+
stored_game.history.move_traverser.move_index.should == 0
|
|
375
|
+
context.initialize_history(@id)
|
|
376
|
+
stored_game = context.get_game(@id)
|
|
377
|
+
stored_game.history.move_traverser.move_index.should == 9
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
describe "#get_move_index" do
|
|
382
|
+
before(:each) do
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it "returns the current move index" do
|
|
386
|
+
id = context.add_game(game)
|
|
387
|
+
cur_game = context.get_game(id)
|
|
388
|
+
cur_game.record_move(1, 'x')
|
|
389
|
+
context.save_game(id, cur_game)
|
|
390
|
+
context.get_move_index(id).should == 1
|
|
391
|
+
cur_game = context.get_game(id)
|
|
392
|
+
cur_game.record_move(2, 'o')
|
|
393
|
+
context.save_game(id, cur_game)
|
|
394
|
+
context.get_move_index(id).should == 2
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
end
|