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,10 @@
1
+ #! /usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+ $LOAD_PATH.unshift File.expand_path("../../lib/ttt/interfaces/cli/lib", __FILE__)
4
+ require 'ttt/setup'
5
+ require 'ttt/context'
6
+ require 'cli/cli_game'
7
+
8
+ context = TTT::Context.instance
9
+ context.setup = TTT::Setup
10
+ CLI::CLIGame.new(context, $stdin, $stdout).play
@@ -0,0 +1,33 @@
1
+ require 'ttt/player'
2
+ require 'ttt/minimax'
3
+
4
+ module TTT
5
+ class AI < Player
6
+ include Minimax
7
+ attr_accessor :board, :max_ply
8
+
9
+ def move(options)
10
+ self.board = (options[:board].dup)
11
+ end
12
+
13
+ def opposite_side(side)
14
+ side == "x" ? "o" : "x"
15
+ end
16
+
17
+ def available_moves
18
+ board[].each.with_index.map { |element, index| index if element == " " }.compact
19
+ end
20
+
21
+ def undo_move(index)
22
+ board[][index] = " "
23
+ end
24
+
25
+ def no_gui?
26
+ true
27
+ end
28
+
29
+ def prompt
30
+ "Computer thinking."
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ require 'ttt/ai'
2
+ module TTT
3
+ class AIEasy < AI
4
+ def move(options)
5
+ super
6
+ random_move
7
+ end
8
+
9
+ def random_move
10
+ move = nil
11
+ available_moves.each do |square|
12
+ move ||= square if Time.new.usec % 3 == 0
13
+ end
14
+ return(move ? move : available_moves.last)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'ttt/ai'
2
+ module TTT
3
+ class AIHard < AI
4
+
5
+ def move(options)
6
+ super
7
+ self.max_ply = max_ply_for(available_moves.length)
8
+ minimax
9
+ end
10
+
11
+ def max_ply_for(moves)
12
+ if moves > 16
13
+ return 7
14
+ elsif moves > 10
15
+ return 9
16
+ else
17
+ return 11
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'ttt/ai'
2
+ module TTT
3
+ class AIMedium < AI
4
+
5
+ def move(options)
6
+ super
7
+ self.max_ply = set_max_ply(available_moves.length)
8
+ minimax
9
+ end
10
+
11
+ def set_max_ply(moves)
12
+ if moves > 15
13
+ return 3
14
+ elsif moves > 5
15
+ return 5
16
+ else
17
+ return 7
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,58 @@
1
+ require 'ttt/ai'
2
+ module TTT
3
+ class AIMedium < AI
4
+ attr_accessor :max_ply, :best
5
+
6
+ def move(options)
7
+ board(options[:board].dup)
8
+ self.max_ply = set_max_ply(available_moves.length)
9
+ self.best = {}
10
+ self.best[:index] = nil
11
+ self.best[:score] = 0
12
+ minimax
13
+ end
14
+
15
+ def minimax(max_player = true, ply = 0, min_score = 1000, max_score = -1000)
16
+ if board.winner?
17
+ return(max_player ? (-1000 + ply) : (1000 - ply))
18
+ elsif board.draw_game?
19
+ return 0
20
+ end
21
+
22
+ if ply >= max_ply
23
+ return(max_player ? (max_score) : (min_score))
24
+ end
25
+
26
+ best_move = 0
27
+ score = (max_player ? max_score : min_score )
28
+ available_moves.each do |index|
29
+ board[][index] = ( max_player ? side : opposite_side(side) )
30
+ score = minimax(!max_player, ply + 1, min_score, max_score)
31
+ undo_move(index)
32
+ if max_player && score > max_score
33
+ max_score = score
34
+ best_move = index
35
+ elsif !max_player && score < min_score
36
+ min_score = score
37
+ end
38
+ break if max_min_swapped?(max_score, min_score)
39
+ end
40
+
41
+ return( ply == 0 ? best_move : ( max_player ? max_score : min_score ) )
42
+ end
43
+
44
+ def set_max_ply(moves)
45
+ if moves > 15
46
+ return 3
47
+ elsif moves > 5
48
+ return 5
49
+ else
50
+ return 7
51
+ end
52
+ end
53
+
54
+ def max_min_swapped?(max, min)
55
+ max >= min
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,37 @@
1
+ module TTT
2
+ class Board
3
+ attr_accessor :board
4
+
5
+ def []
6
+ board
7
+ end
8
+
9
+ def []=(array)
10
+ self.board = array
11
+ end
12
+
13
+ def update cell, side
14
+ self.board[cell.to_i] = side
15
+ end
16
+
17
+ def empty?
18
+ !(board.include?("x") || board.include?("o"))
19
+ end
20
+
21
+ def full?
22
+ !board.include?(" ")
23
+ end
24
+
25
+ def free?(cell)
26
+ board[cell] == " "
27
+ end
28
+
29
+ def finished?
30
+ draw_game? || winner?
31
+ end
32
+
33
+ def draw_game?
34
+ (!board.include? " ") && !winner?
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,53 @@
1
+ require 'ttt/config_options'
2
+
3
+ module TTT
4
+ class ConfigHelper
5
+ def self.player_types
6
+ ConfigOptions::HUMAN_READABLE_PLAYERS
7
+ end
8
+
9
+ def self.board_types
10
+ ConfigOptions::HUMAN_READABLE_BOARDS
11
+ end
12
+
13
+ def self.bucket
14
+ ConfigOptions::BUCKET
15
+ end
16
+
17
+ def self.port
18
+ ConfigOptions::PORT
19
+ end
20
+
21
+ def self.http_backend
22
+ ConfigOptions::HTTP_BACKEND
23
+ end
24
+
25
+ def self.get_player_const(player_type)
26
+ ConfigOptions::PLAYERS[get_player_index(player_type)]
27
+ end
28
+
29
+ def self.get_board_const(board_type)
30
+ ConfigOptions::BOARDS[get_board_index(board_type)]
31
+ end
32
+
33
+ def self.get_player_index(player_type)
34
+ ConfigOptions::HUMAN_READABLE_PLAYERS.index(player_type)
35
+ end
36
+
37
+ def self.get_board_index(board_type)
38
+ ConfigOptions::HUMAN_READABLE_BOARDS.index(board_type)
39
+ end
40
+
41
+ def self.get_db_const
42
+ ConfigOptions::DB
43
+ end
44
+
45
+ def self.get_history_const
46
+ ConfigOptions::HISTORY
47
+ end
48
+
49
+ def self.get_game_interactor_const
50
+ ConfigOptions::INTERACTOR
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,27 @@
1
+ require 'ttt/ai'
2
+ require 'ttt/ai_easy'
3
+ require 'ttt/ai_medium'
4
+ require 'ttt/ai_hard'
5
+ require 'ttt/human'
6
+ require 'ttt/board'
7
+ require 'ttt/three_by_three'
8
+ require 'ttt/four_by_four'
9
+ require 'ttt/three_by_three_by_three'
10
+ require 'ttt/game_history'
11
+ require 'ttt/riak_db'
12
+ require 'ttt/game_interactor'
13
+
14
+ module TTT
15
+ class ConfigOptions
16
+ BOARDS = [TTT::ThreeByThree, TTT::FourByFour, TTT::ThreeByThreeByThree]
17
+ HUMAN_READABLE_BOARDS = %w(3x3 4x4 3x3x3)
18
+ PLAYERS = [TTT::Human, TTT::AIEasy, TTT::AIMedium, TTT::AIHard]
19
+ HUMAN_READABLE_PLAYERS = ["Human", "AI Easy", "AI Medium", "AI Hard"]
20
+ DB = TTT::RiakDB
21
+ PORT = 8091 # 8098 is default
22
+ HTTP_BACKEND = :Excon
23
+ BUCKET = "ttt_games"
24
+ HISTORY = TTT::GameHistory
25
+ INTERACTOR = TTT::GameInteractor
26
+ end
27
+ end
@@ -0,0 +1,214 @@
1
+ require 'ttt/setup'
2
+
3
+ module TTT
4
+ class Context
5
+ class << self
6
+ def instance
7
+ @instance ||= new
8
+ end
9
+
10
+ private :new
11
+ end
12
+
13
+ def setup=(setup_const)
14
+ @setup = setup_const.new
15
+ end
16
+
17
+ def setup
18
+ @setup
19
+ end
20
+
21
+ def players
22
+ @setup.players
23
+ end
24
+
25
+ def boards
26
+ @setup.boards
27
+ end
28
+
29
+ def create_game(player1, player2, board)
30
+ game = @setup.new_game(:player1 => player1, :player2 => player2, :board => board)
31
+ add_game(game)
32
+ end
33
+
34
+ def add_game(game)
35
+ game_interactor.add_game(game)
36
+ end
37
+
38
+ def get_game(id)
39
+ game_interactor.get_game(id)
40
+ end
41
+
42
+ def save_game(id, game)
43
+ game_interactor.save_game(id, game)
44
+ end
45
+
46
+ def game_list
47
+ game_interactor.game_list
48
+ end
49
+
50
+ def delete_game(id)
51
+ game_interactor.delete_game(id)
52
+ end
53
+
54
+ def update_game(id, move, side)
55
+ if game = db_instance.get_game(id)
56
+ game_interactor.update_game(game, move, side)
57
+ game_interactor.save_game(id, game)
58
+ else
59
+ nil
60
+ end
61
+ end
62
+
63
+ def ai_move?(id)
64
+ if game = db_instance.get_game(id)
65
+ game_interactor.ai_move?(game)
66
+ else
67
+ nil
68
+ end
69
+ end
70
+
71
+ def ai_move(id)
72
+ if game = game_interactor.get_game(id)
73
+ game_interactor.ai_move(id, game)
74
+ else
75
+ nil
76
+ end
77
+ end
78
+
79
+ def finished?(id)
80
+ if game = game_interactor.get_game(id)
81
+ game_interactor.finished?(game)
82
+ else
83
+ nil
84
+ end
85
+ end
86
+
87
+ def winner(id)
88
+ if game = game_interactor.get_game(id)
89
+ game_interactor.winner(game)
90
+ else
91
+ nil
92
+ end
93
+ end
94
+
95
+ def winner?(id)
96
+ if game = game_interactor.get_game(id)
97
+ game_interactor.winner?(game)
98
+ else
99
+ nil
100
+ end
101
+ end
102
+
103
+ def draw?(id)
104
+ if game = game_interactor.get_game(id)
105
+ game_interactor.draw?(game)
106
+ else
107
+ nil
108
+ end
109
+ end
110
+
111
+ def which_board(id)
112
+ if game = game_interactor.get_game(id)
113
+ game_interactor.which_board(game)
114
+ else
115
+ nil
116
+ end
117
+ end
118
+
119
+ def valid_move?(id, move)
120
+ if game = game_interactor.get_game(id)
121
+ game_interactor.valid_move?(game, move)
122
+ else
123
+ nil
124
+ end
125
+ end
126
+
127
+ def adjust_move_index(id, value)
128
+ if game = game_interactor.get_game(id)
129
+ game_interactor.adjust_move_index(game, value)
130
+ game_interactor.save_game(id, game)
131
+ else
132
+ nil
133
+ end
134
+ end
135
+
136
+ def get_history_board(id)
137
+ if game = game_interactor.get_game(id)
138
+ game_interactor.get_history_board(game)
139
+ else
140
+ nil
141
+ end
142
+ end
143
+
144
+ def get_move_traverser(id)
145
+ if game = game_interactor.get_game(id)
146
+ game_interactor.get_move_traverser(game)
147
+ else
148
+ nil
149
+ end
150
+ end
151
+
152
+ def save_move_traverser(id, move_traverser)
153
+ if game = game_interactor.get_game(id)
154
+ game_interactor.save_move_traverser(id, game, move_traverser)
155
+ end
156
+ end
157
+
158
+ def initialize_history(id)
159
+ if game = game_interactor.get_game(id)
160
+ game_interactor.initialize_history(game)
161
+ save_game(id, game)
162
+ else
163
+ nil
164
+ end
165
+ end
166
+
167
+ def get_history_length(id)
168
+ if game = game_interactor.get_game(id)
169
+ game_interactor.get_history_length(game)
170
+ end
171
+ end
172
+
173
+ def get_move_index(id)
174
+ if game = game_interactor.get_game(id)
175
+ game_interactor.get_move_index(game)
176
+ else
177
+ nil
178
+ end
179
+ end
180
+
181
+ def get_history(id)
182
+ if game = game_interactor.get_game(id)
183
+ game_interactor.get_history(game)
184
+ else
185
+ nil
186
+ end
187
+ end
188
+
189
+ def which_current_player?(id)
190
+ if game = game_interactor.get_game(id)
191
+ game_interactor.which_current_player?(game)
192
+ else
193
+ nil
194
+ end
195
+ end
196
+
197
+ def board(id)
198
+ if game = game_interactor.get_game(id)
199
+ game_interactor.board(game)
200
+ else
201
+ nil
202
+ end
203
+ end
204
+
205
+ private
206
+ def db_instance
207
+ @db_instance ||= @setup.new_db
208
+ end
209
+
210
+ def game_interactor
211
+ @game_interactor ||= @setup.new_interactor
212
+ end
213
+ end
214
+ end