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,62 @@
|
|
|
1
|
+
require 'ttt/board'
|
|
2
|
+
module TTT
|
|
3
|
+
class FourByFour < Board
|
|
4
|
+
attr_accessor :x_arr, :diag_arr, :block_arr
|
|
5
|
+
def initialize
|
|
6
|
+
self.board = Array.new(16, " ")
|
|
7
|
+
self.x_arr = [[0,1,2,3], [4,5,6,7], [8,9,10,11], [12,13,14,15]]
|
|
8
|
+
self.diag_arr = [[0, 5, 10, 15], [3, 6, 9, 12]]
|
|
9
|
+
self.block_arr = [[0,1,4,5], [1,2,5,6], [2,3,6,7], [4,5,8,9], [5,6,9,10], [6,7,10,11], [8,9,12,13], [9,10,13,14], [10,11,14,15]]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def winner?
|
|
13
|
+
horizontal_winner? || vertical_winner? || diag_winner? || block_winner?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def horizontal_winner?
|
|
17
|
+
x_arr.each do |x_win|
|
|
18
|
+
return true if board[x_win[0]] != " " &&
|
|
19
|
+
board[x_win[0]] == board[x_win[1]] &&
|
|
20
|
+
board[x_win[1]] == board[x_win[2]] &&
|
|
21
|
+
board[x_win[2]] == board[x_win[3]]
|
|
22
|
+
end
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def vertical_winner?
|
|
27
|
+
x_arr.transpose.each do |y_win|
|
|
28
|
+
return true if board[y_win[0]] != " " &&
|
|
29
|
+
board[y_win[0]] == board[y_win[1]] &&
|
|
30
|
+
board[y_win[1]] == board[y_win[2]] &&
|
|
31
|
+
board[y_win[2]] == board[y_win[3]]
|
|
32
|
+
end
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def diag_winner?
|
|
37
|
+
diag_arr.each do |diag_win|
|
|
38
|
+
return true if board[diag_win[0]] != " " &&
|
|
39
|
+
board[diag_win[0]] == board[diag_win[1]] &&
|
|
40
|
+
board[diag_win[1]] == board[diag_win[2]] &&
|
|
41
|
+
board[diag_win[2]] == board[diag_win[3]]
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def block_winner?
|
|
48
|
+
block_arr.each do |block_win|
|
|
49
|
+
return true if board[block_win[0]] != " " &&
|
|
50
|
+
board[block_win[0]] == board[block_win[1]] &&
|
|
51
|
+
board[block_win[1]] == board[block_win[2]] &&
|
|
52
|
+
board[block_win[2]] == board[block_win[3]]
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def board_type
|
|
59
|
+
"four_by_four"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/ttt/game.rb
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module TTT
|
|
2
|
+
class Game
|
|
3
|
+
attr_accessor :board, :player1, :player2, :current_player, :history, :db
|
|
4
|
+
|
|
5
|
+
def initialize(options)
|
|
6
|
+
self.board = options[:board]
|
|
7
|
+
self.player1 = options[:player1]
|
|
8
|
+
self.player2 = options[:player2]
|
|
9
|
+
self.current_player = self.player1
|
|
10
|
+
self.history = options.fetch(:history)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def ai_move?
|
|
14
|
+
current_player.no_gui?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def which_board
|
|
18
|
+
board.board_type
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def next_move
|
|
22
|
+
return nil unless ai_move?
|
|
23
|
+
input = current_player.move(:board => board)
|
|
24
|
+
mark_move(input)
|
|
25
|
+
record_move(input)
|
|
26
|
+
switch_player
|
|
27
|
+
input
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def valid_move?(input)
|
|
31
|
+
input.class == Fixnum && 0 <= input && input <= (board[].length - 1) && board.free?(input.to_i)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def mark_move(cell, side = current_player.side)
|
|
35
|
+
board.update(cell, side)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def record_move(cell, side = current_player.side)
|
|
39
|
+
history.record_move(cell, side)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def show_history
|
|
43
|
+
history.show
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def adjust_move_index(index_diff)
|
|
47
|
+
history.adjust_move_index(index_diff)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get_history_board(move_number_limit = history.move_traverser.move_index)
|
|
51
|
+
history.get_history_board(board, move_number_limit)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def initialize_history
|
|
55
|
+
history.initialize_history
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def switch_player
|
|
59
|
+
if player1.side == current_player.side
|
|
60
|
+
self.current_player = self.player2
|
|
61
|
+
else
|
|
62
|
+
self.current_player = self.player1
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def which_current_player?
|
|
67
|
+
current_player.equal?(player1) ? "Player 1" : "Player 2"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def last_player
|
|
71
|
+
current_player == player1 ? "Player 2" : "Player 1"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def finished?
|
|
75
|
+
board.finished?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def not_finished?
|
|
79
|
+
!board.finished?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def winner?
|
|
83
|
+
board.winner?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def draw?
|
|
87
|
+
board.draw_game?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def board_arr
|
|
91
|
+
board[]
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'ttt/move_history'
|
|
2
|
+
require 'ttt/move_traverser'
|
|
3
|
+
|
|
4
|
+
module TTT
|
|
5
|
+
class GameHistory
|
|
6
|
+
attr_accessor :history, :move_traverser
|
|
7
|
+
def initialize
|
|
8
|
+
self.history = []
|
|
9
|
+
self.move_traverser = MoveTraverser.new(self)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def record_move(cell, side)
|
|
13
|
+
self.history << MoveHistory.new(:move => cell, :side => side)
|
|
14
|
+
inc_move_index
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def inc_move_index
|
|
18
|
+
self.move_traverser.move_index = history.length
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def show
|
|
22
|
+
self.history
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def adjust_move_index(index_diff)
|
|
26
|
+
move_traverser.adjust_move_index(index_diff)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def get_history_board(board, move_number_limit = move_traverser.move_index)
|
|
30
|
+
move_traverser.history_board_builder(board, move_number_limit)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def initialize_history
|
|
34
|
+
move_traverser.initialize_history
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
module TTT
|
|
2
|
+
class GameInteractor
|
|
3
|
+
def initialize(db)
|
|
4
|
+
self.db = db
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def add_game(game)
|
|
8
|
+
db.add_game(game)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def get_game(id)
|
|
12
|
+
db.get_game(id)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def game_list
|
|
16
|
+
db.game_list
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def save_game(id, game)
|
|
20
|
+
db.save_game(id, game)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def delete_game(id)
|
|
24
|
+
db.delete_game(id)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ai_move?(game)
|
|
28
|
+
game.ai_move?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ai_move(id, game)
|
|
32
|
+
game.next_move
|
|
33
|
+
save_game(id, game)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def finished?(game)
|
|
37
|
+
game.finished?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def not_finished?(game)
|
|
41
|
+
!game.finished?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def winner?(game)
|
|
45
|
+
game.winner?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def winner(game)
|
|
49
|
+
game.last_player
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def draw?(game)
|
|
53
|
+
game.draw?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def which_board(game)
|
|
57
|
+
game.which_board
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def valid_move?(game, move)
|
|
61
|
+
game.valid_move?(move)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def get_history(game)
|
|
65
|
+
game.show_history
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def get_move_traverser(game)
|
|
69
|
+
game.history.move_traverser
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def save_move_traverser(id, game, move_traverser)
|
|
73
|
+
game.history.move_traverser = move_traverser
|
|
74
|
+
save_game(id, game)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def get_history_board(game)
|
|
78
|
+
game.get_history_board
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def initialize_history(game)
|
|
82
|
+
game.initialize_history
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def get_history_length(game)
|
|
86
|
+
game.show_history.length
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def switch_player(game)
|
|
90
|
+
game.switch_player
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def which_current_player?(game)
|
|
94
|
+
game.which_current_player?
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def board(game)
|
|
98
|
+
game.board[]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def update_game(game, cell, side)
|
|
102
|
+
mark_move(game, cell, side)
|
|
103
|
+
record_move(game, cell, side)
|
|
104
|
+
switch_player(game)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def mark_move(game, cell, side)
|
|
108
|
+
game.mark_move(cell, side)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def record_move(game, cell, side)
|
|
112
|
+
game.record_move(cell, side)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def adjust_move_index(game, value)
|
|
116
|
+
game.history.move_traverser.adjust_move_index(value)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def get_move_index(game)
|
|
120
|
+
game.history.move_traverser.move_index
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
attr_accessor :db
|
|
125
|
+
end
|
|
126
|
+
end
|
data/lib/ttt/human.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module CLI
|
|
2
|
+
class BoardSelection < Selection
|
|
3
|
+
attr_accessor :board, :boards, :presenter
|
|
4
|
+
|
|
5
|
+
def initialize(boards, presenter)
|
|
6
|
+
self.boards = boards
|
|
7
|
+
self.presenter = presenter
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def process
|
|
11
|
+
presenter.board_selection_prompt(boards)
|
|
12
|
+
process_board_selection(presenter.input.chomp.to_i)
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def process_board_selection(selection)
|
|
17
|
+
if board_selection_input_valid?(selection)
|
|
18
|
+
set_board_string(selection)
|
|
19
|
+
else
|
|
20
|
+
presenter.error
|
|
21
|
+
process
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def board_selection_input_valid?(selection)
|
|
26
|
+
return false if selection.class == Float
|
|
27
|
+
0 < selection && selection <= boards.length
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def set_board_string(selection)
|
|
31
|
+
self.board = boards[selection - 1]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require 'cli/player_selection'
|
|
2
|
+
require 'cli/board_selection'
|
|
3
|
+
require 'cli/clio'
|
|
4
|
+
require 'cli/play_again'
|
|
5
|
+
require 'cli/cli_presenter'
|
|
6
|
+
require 'cli/walk_history'
|
|
7
|
+
|
|
8
|
+
module CLI
|
|
9
|
+
class CLIGame
|
|
10
|
+
attr_accessor :context, :presenter, :id, :games
|
|
11
|
+
def initialize(context, input, output)
|
|
12
|
+
self.context = context
|
|
13
|
+
self.presenter = CLIPresenter.new(input, output)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def play
|
|
17
|
+
user_selection = @presenter.menu
|
|
18
|
+
process_command(user_selection)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def process_command(selection)
|
|
22
|
+
case selection.chomp
|
|
23
|
+
when "1" then init_game
|
|
24
|
+
when "2" then game_list
|
|
25
|
+
when "3" then exit
|
|
26
|
+
else
|
|
27
|
+
play
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def init_game
|
|
32
|
+
@presenter.welcome_prompt
|
|
33
|
+
player_select = get_player_selection
|
|
34
|
+
board_select = get_board_selection
|
|
35
|
+
new_game = build_game(player_select, board_select)
|
|
36
|
+
@id = @context.add_game(new_game)
|
|
37
|
+
play_game
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_player_selection
|
|
41
|
+
PlayerSelection.new(@context.players, @presenter).process
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def get_board_selection
|
|
45
|
+
BoardSelection.new(@context.boards, @presenter).process
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def build_game(pselect, bselect)
|
|
49
|
+
@context.setup.new_game(player1: pselect.player1, player2: pselect.player2, board: bselect.board)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def play_game
|
|
53
|
+
while game.not_finished?
|
|
54
|
+
move_cycle
|
|
55
|
+
end
|
|
56
|
+
game_over
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def game_over
|
|
60
|
+
walk_history
|
|
61
|
+
play_again
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def game
|
|
65
|
+
@context.get_game(@id)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def move_cycle
|
|
69
|
+
cur_game = game
|
|
70
|
+
player_prompt(cur_game)
|
|
71
|
+
process_next_move
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def player_prompt(cur_game)
|
|
75
|
+
@presenter.player_prompt(cur_game.board.board, cur_game.show_history, cur_game.current_player)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def process_next_move
|
|
79
|
+
if @context.ai_move?(@id)
|
|
80
|
+
@context.ai_move(@id)
|
|
81
|
+
else
|
|
82
|
+
move = get_next_move
|
|
83
|
+
if validate_move(move)
|
|
84
|
+
update_move(move)
|
|
85
|
+
else
|
|
86
|
+
move_cycle
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
eval_board_state
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def get_next_move
|
|
93
|
+
if game.ai_move?
|
|
94
|
+
@context.ai_move(@id)
|
|
95
|
+
else
|
|
96
|
+
@presenter.input
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def validate_move(move)
|
|
101
|
+
@context.valid_move?(@id, move.to_i)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def update_move(move)
|
|
105
|
+
@context.update_game(@id, move.to_i, game.current_player.side)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def eval_board_state
|
|
109
|
+
@presenter.process_winner(game.board_arr, game.show_history, game.last_player) if game.winner?
|
|
110
|
+
@presenter.process_draw(game.board_arr, game.show_history) if game.finished? && !game.winner?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def game_list
|
|
114
|
+
get_games
|
|
115
|
+
if @games
|
|
116
|
+
load_game
|
|
117
|
+
else
|
|
118
|
+
no_games
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def get_games
|
|
123
|
+
@games = @context.game_list
|
|
124
|
+
@games = nil if @games.length == 0
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def no_games
|
|
128
|
+
@presenter.no_games
|
|
129
|
+
sleep 1
|
|
130
|
+
play
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def load_game
|
|
134
|
+
selection = @presenter.process_game_list(@games)
|
|
135
|
+
if @context.get_game(selection.chomp)
|
|
136
|
+
@id = selection.chomp
|
|
137
|
+
resume_game
|
|
138
|
+
else
|
|
139
|
+
game_list
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def no_games
|
|
144
|
+
@presenter.no_games
|
|
145
|
+
sleep 1
|
|
146
|
+
play
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def resume_game
|
|
150
|
+
@presenter.player_prompt(game.board[], game.show_history, game.current_player)
|
|
151
|
+
eval_board_state
|
|
152
|
+
play_game
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def game
|
|
156
|
+
@context.get_game(@id)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def presenter=(args)
|
|
160
|
+
@presenter = args
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def presenter
|
|
164
|
+
@presenter
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def context=(args)
|
|
168
|
+
@context = args
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def context
|
|
172
|
+
@context
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def play_again
|
|
176
|
+
exit unless PlayAgain.new(@presenter).play_again?
|
|
177
|
+
play
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def walk_history
|
|
181
|
+
@walk_history = WalkHistory.new(@presenter, game)
|
|
182
|
+
@walk_history.post_game_msg
|
|
183
|
+
play_again
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|