bashrw_ttt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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