tic_tac_toes 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77b92da0b3d048f306b6ac300f94e94fcd656ef7
4
- data.tar.gz: 10497e3ed936e362e8ae20e1e85282b8990e92f7
3
+ metadata.gz: 973d4205866381b247cee7397ef538d46d26dbd3
4
+ data.tar.gz: 8383fa3bd6d89f0e1dc082bf15d58e22315c4d16
5
5
  SHA512:
6
- metadata.gz: d33321f395dae4c693c0610a51b998d7b606bc00408ffe65cfcc305f8f06278f5bf09085ea1de4d7a4556fe80ad0a302a4c006c2a887f8b31db59dacb3ee4983
7
- data.tar.gz: 5e7f86e90489fdc057a6804b77e85ed2ba067c189585d9d813051abbc2e5d5bae2dc34a270a2b9c3d477e8a92ed20fab08d82b17c36114434eb3e5917ee10473
6
+ metadata.gz: 38e1a5192560eb071120b41079ae56a77e442b5fefe60659537868e45eb76277f05ffd74b4510c1d707009c3a5a9bb22582bd30cd66a9fdc67ec6524d471a92f
7
+ data.tar.gz: 81602fbe1f20241e27b4400815bc4ee3fdbbb1bdaa9622de099134e4b043db4dd640bb6880258b072f7d8e16b0827dc9717904749ff8ae94ca5d4518cbfa0177
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tic_tac_toes (0.1.4)
4
+ tic_tac_toes (0.1.6)
5
5
  pg
6
6
 
7
7
  GEM
data/bin/game_histories CHANGED
@@ -4,10 +4,11 @@ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../lib')
4
4
 
5
5
  require 'tic_tac_toes/database/pg_wrapper'
6
6
  require 'tic_tac_toes/command_line/history_reader'
7
+ require 'tic_tac_toes/command_line/prompt'
7
8
 
8
9
  database = 'tic_tac_toes'
9
10
 
10
11
  wrapper = TicTacToes::Database::PGWrapper.new(database)
11
12
  reader = TicTacToes::CommandLine::HistoryReader.new(wrapper)
12
13
 
13
- reader.display_game_histories
14
+ reader.game_history_strings.each { |history| TicTacToes::CommandLine::Prompt.display(history) }
@@ -29,11 +29,19 @@ module TicTacToes
29
29
  @players[1]
30
30
  end
31
31
 
32
+ def computer_player
33
+ @players.detect { |player| player.move_strategy.type == MoveStrategies::COMPUTER }
34
+ end
35
+
32
36
  def turn_over(move)
33
37
  @history.record_move(move)
34
38
  @players.rotate!
35
39
  end
36
40
 
41
+ def moves
42
+ @history.moves
43
+ end
44
+
37
45
  def end_game(winner)
38
46
  @history.record_winner(winner)
39
47
  @history.persist
@@ -54,7 +62,6 @@ module TicTacToes
54
62
  end
55
63
 
56
64
  def record_difficulty
57
- computer_player = @players.detect { |player| player.move_strategy.type == MoveStrategies::COMPUTER }
58
65
  @history.record_difficulty(computer_player.move_strategy)
59
66
  end
60
67
  end
@@ -17,7 +17,7 @@ module TicTacToes
17
17
 
18
18
  def record_move(move)
19
19
  @moves ||= []
20
- @moves << move
20
+ @moves << move unless move.nil?
21
21
  end
22
22
 
23
23
  def record_winner(winner)
@@ -1,4 +1,4 @@
1
- require 'tic_tac_toes/core/strings'
1
+ require 'tic_tac_toes/core/presenter'
2
2
 
3
3
  module TicTacToes
4
4
  module Core
@@ -27,41 +27,41 @@ module TicTacToes
27
27
  end
28
28
 
29
29
  def draw_board(board)
30
- @io_strategy.display(Strings.board(board))
30
+ @io_strategy.display(Presenter.board(board))
31
31
  end
32
32
 
33
33
  def invalid_row_size_error
34
- @io_strategy.display_red(Strings::INVALID_ROW_SIZE)
34
+ @io_strategy.display_red(Presenter::INVALID_ROW_SIZE)
35
35
  end
36
36
 
37
37
  def invalid_token_error
38
- @io_strategy.display_red(Strings::INVALID_TOKEN)
38
+ @io_strategy.display_red(Presenter::INVALID_TOKEN)
39
39
  end
40
40
 
41
41
  def invalid_difficulty_error
42
- @io_strategy.display_red(Strings::INVALID_DIFFICULTY)
42
+ @io_strategy.display_red(Presenter::INVALID_DIFFICULTY)
43
43
  end
44
44
 
45
45
  def invalid_move_error
46
- @io_strategy.display_red(Strings::INVALID_MOVE)
46
+ @io_strategy.display_red(Presenter::INVALID_MOVE)
47
47
  end
48
48
 
49
49
  def thinking_notification
50
- @io_strategy.display_red(Strings::THINKING)
50
+ @io_strategy.display_red(Presenter::THINKING)
51
51
  end
52
52
 
53
53
  def game_over_notification(winner)
54
54
  winner = "Nobody" if winner.nil?
55
55
  winner = winner.token unless winner.is_a? String
56
- @io_strategy.display(Strings.game_over_notification(winner))
56
+ @io_strategy.display(Presenter.game_over_notification(winner))
57
57
  end
58
58
 
59
59
  def move_solicitation
60
- @io_strategy.display(Strings::MOVE_SOLICITATION)
60
+ @io_strategy.display(Presenter::MOVE_SOLICITATION)
61
61
  end
62
62
 
63
63
  def not_an_integer_error
64
- @io_strategy.display_red(Strings::NOT_AN_INTEGER)
64
+ @io_strategy.display_red(Presenter::NOT_AN_INTEGER)
65
65
  end
66
66
 
67
67
  def solicit_input
@@ -79,15 +79,15 @@ module TicTacToes
79
79
  private
80
80
 
81
81
  def row_size_solicitation
82
- @io_strategy.display(Strings::ROW_SIZE_SOLICITATION)
82
+ @io_strategy.display(Presenter::ROW_SIZE_SOLICITATION)
83
83
  end
84
84
 
85
85
  def token_solicitation(player)
86
- @io_strategy.display(Strings.token_solicitation(player))
86
+ @io_strategy.display(Presenter.token_solicitation(player))
87
87
  end
88
88
 
89
89
  def difficulty_solicitation
90
- @io_strategy.display(Strings::DIFFICULTY_SOLICITATION)
90
+ @io_strategy.display(Presenter::DIFFICULTY_SOLICITATION)
91
91
  end
92
92
  end
93
93
  end
@@ -3,7 +3,7 @@ require 'tic_tac_toes/core/rules'
3
3
 
4
4
  module TicTacToes
5
5
  module Core
6
- module Strings
6
+ module Presenter
7
7
  smallest_row_size = Rules::ROW_SIZE_RANGE.min
8
8
  largest_row_size = Rules::ROW_SIZE_RANGE.max
9
9
 
@@ -101,6 +101,22 @@ module TicTacToes
101
101
  truncated_length.times { horizontal_divider << divider_unit }
102
102
  horizontal_divider
103
103
  end
104
+
105
+ def self.game_history_strings(wrapper)
106
+ game_histories = wrapper.read_game_histories
107
+ game_histories.map { |history| game_history_string(history) }
108
+ end
109
+
110
+ def self.game_history_string(history)
111
+ history_string = ''
112
+ history_string << "Board size: #{history.board_size.to_s}\n"
113
+ history_string << "Difficulty: #{history.difficulty}\n"
114
+ history_string << "Winner: #{history.winner}\n"
115
+ history_string << "Move history:\n"
116
+ history.moves.each { |move| history_string << " #{move.join(' -> ')}\n" }
117
+ history_string << "\n"
118
+ history_string
119
+ end
104
120
  end
105
121
  end
106
122
  end
@@ -1,37 +1,29 @@
1
1
  require 'tic_tac_toes/core/player_factory'
2
2
  require 'tic_tac_toes/core/move_strategies/hard_ai'
3
+ require 'tic_tac_toes/core/move_strategies/types'
3
4
 
4
5
  module TicTacToes
5
6
  module UI
6
7
  module Adapter
7
8
  def self.start_game(order, game_state, listener)
8
- case order
9
- when 'first'
10
- listener.moves_were_made(game_state)
11
- when 'second'
12
- make_move(game_state, nil, listener)
13
- end
9
+ user_is_first = order == 'first'
10
+
11
+ user_is_first ? listener.moves_were_made(game_state) : make_move(game_state, nil, listener)
14
12
  end
15
13
 
16
14
  def self.make_move(game_state, move, listener)
17
- unless move.nil?
18
- move = move.to_i
19
- game_state.place_move(move)
20
- end
21
-
22
- if game_state.game_over?
23
- tell_listener_game_is_over(game_state, listener)
24
- return
25
- end
15
+ computer_first = move.nil?
26
16
 
27
- game_state.turn_over(move)
28
- game_state.current_player.place_and_return_move(game_state)
29
-
30
- if game_state.game_over?
31
- tell_listener_game_is_over(game_state, listener)
32
- return
17
+ if computer_first
18
+ game_state.turn_over(nil)
19
+ computer_move(game_state, listener)
20
+ return game_over(game_state, listener) if game_state.game_over?
21
+ else
22
+ human_move(game_state, move, listener)
23
+ return game_over(game_state, listener) if game_state.game_over?
24
+ computer_move(game_state, listener)
25
+ return game_over(game_state, listener) if game_state.game_over?
33
26
  end
34
-
35
27
  listener.moves_were_made(game_state)
36
28
  end
37
29
 
@@ -43,7 +35,7 @@ module TicTacToes
43
35
  potential_game_state = generate_game_state(game_state, space)
44
36
  next predictions << predicted_result(potential_game_state) if potential_game_state.game_over?
45
37
 
46
- potential_game_state.turn_over([])
38
+ potential_game_state.turn_over(nil)
47
39
  potential_game_state.place_move(Core::MoveStrategies::HardAI.move(potential_game_state))
48
40
  next predictions << predicted_result(potential_game_state) if potential_game_state.game_over?
49
41
 
@@ -54,20 +46,36 @@ module TicTacToes
54
46
 
55
47
  private
56
48
 
57
- def self.tell_listener_game_is_over(game_state, listener)
49
+ def self.computer_move(game_state, listener)
50
+ computer_player = game_state.computer_player
51
+ computer_move = computer_player.place_and_return_move(game_state)
52
+ game_state.turn_over(computer_move)
53
+ end
54
+
55
+ def self.human_move(game_state, move, listener)
56
+ human_player = game_state.current_player
57
+ game_state.place_move(move.to_i)
58
+ game_state.turn_over([human_player.token, move.to_i])
59
+ end
60
+
61
+ def self.game_over(game_state, listener)
58
62
  winning_player = game_state.determine_winner
59
63
 
60
- case winning_player
61
- when nil
62
- listener.game_ended_in_draw(game_state)
63
- else
64
+ record_game_history(game_state, winning_player)
65
+ if winning_player
64
66
  listener.game_ended_in_winner(game_state, winning_player.token)
67
+ else
68
+ listener.game_ended_in_draw(game_state)
65
69
  end
66
70
  end
67
71
 
72
+ def self.record_game_history(game_state, winning_player)
73
+ game_state.start_game
74
+ game_state.end_game(winning_player)
75
+ end
76
+
68
77
  def self.generate_game_state(game_state, space)
69
78
  new_game_state = Marshal.load(Marshal.dump(game_state))
70
- new_game_state.turn_over([])
71
79
  new_game_state.place_move(space)
72
80
  new_game_state
73
81
  end
@@ -77,7 +85,7 @@ module TicTacToes
77
85
 
78
86
  if winner.nil?
79
87
  "tie"
80
- elsif winner.move_strategy.is_a? Core::MoveStrategies::Human
88
+ elsif winner.move_strategy.type == Core::MoveStrategies::HUMAN
81
89
  "win"
82
90
  else
83
91
  "loss"
@@ -1,6 +1,7 @@
1
1
  require 'tic_tac_toes/core/board'
2
2
  require 'tic_tac_toes/core/game_state'
3
3
  require 'tic_tac_toes/core/player_factory'
4
+ require 'tic_tac_toes/database/pg_wrapper'
4
5
 
5
6
  module TicTacToes
6
7
  module UI
@@ -13,30 +14,35 @@ module TicTacToes
13
14
  board.spaces
14
15
  end
15
16
 
16
- def self.game_state_from_board_structure(board_structure, computer_type)
17
+ def self.game_state(board_structure, computer_type, move_history)
17
18
  player_factory = Core::PlayerFactory.new('unused_io')
18
19
  human_player = player_factory.generate_player(X, Core::PlayerFactory::HUMAN)
19
20
  computer_player = player_factory.generate_player(O, Core::PlayerFactory.const_get(computer_type))
20
21
  players = [human_player, computer_player]
21
22
 
22
23
  board_structure_with_players = replace_tokens_with_players(board_structure, human_player, computer_player)
23
- board = board_from_structure(board_structure_with_players)
24
+ board = board(board_structure_with_players)
24
25
 
25
- Core::GameState.new(board, players, NullHistory.new)
26
+ history = history(move_history)
27
+
28
+ Core::GameState.new(board, players, history)
26
29
  end
27
30
 
28
- def self.board_structure_from_game_state(game_state)
31
+ def self.board_structure(game_state)
29
32
  structure_with_players = game_state.board.spaces
30
-
31
33
  replace_players_with_tokens(structure_with_players)
32
34
  end
33
35
 
34
- def self.ai_type_from_game_state(game_state)
36
+ def self.ai_type(game_state)
35
37
  computer = Core::MoveStrategies::COMPUTER
36
38
  computer_player = game_state.players.detect { |player| player.move_strategy.type == computer }
37
39
  computer_player.move_strategy.ai_type
38
40
  end
39
41
 
42
+ def self.move_history(game_state)
43
+ game_state.moves.flatten.join if game_state.moves
44
+ end
45
+
40
46
  private
41
47
 
42
48
  def self.replace_tokens_with_players(board_structure, human_player, computer_player)
@@ -56,7 +62,7 @@ module TicTacToes
56
62
  board_structure.map { |space| space.token unless space.nil? }
57
63
  end
58
64
 
59
- def self.board_from_structure(board_structure)
65
+ def self.board(board_structure)
60
66
  row_size = Math.sqrt(board_structure.count).to_i
61
67
  board = Core::Board.new(row_size: row_size)
62
68
 
@@ -66,6 +72,19 @@ module TicTacToes
66
72
 
67
73
  board
68
74
  end
75
+
76
+ def self.history(move_history)
77
+ storage_wrapper = Database::PGWrapper.new('tic_tac_toes')
78
+ history = Core::History.new(storage_wrapper)
79
+ if move_history
80
+ moves = move_history.split(//).each_slice(2).to_a
81
+ moves.each do |move|
82
+ move = [move.first, move.last.to_i]
83
+ history.record_move(move)
84
+ end
85
+ end
86
+ history
87
+ end
69
88
  end
70
89
 
71
90
  class NullHistory
@@ -80,6 +99,14 @@ module TicTacToes
80
99
  def record_move(move)
81
100
  nil
82
101
  end
102
+
103
+ def record_winner(winner)
104
+ nil
105
+ end
106
+
107
+ def persist
108
+ nil
109
+ end
83
110
  end
84
111
  end
85
112
  end
@@ -1,3 +1,3 @@
1
1
  module TicTacToes
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.6"
3
3
  end
@@ -88,6 +88,16 @@ describe TicTacToes::Core::GameState do
88
88
  end
89
89
  end
90
90
 
91
+ describe '#computer_player' do
92
+ it 'returns the game’s computer player' do
93
+ human_player = TicTacToes::Core::PlayerFactory.new('unused_io').generate_player('X', :human)
94
+ computer_player = TicTacToes::Core::PlayerFactory.new('unused_io').generate_player('O', :hard)
95
+ players = [human_player, computer_player]
96
+ game_state = TicTacToes::Core::GameState.new('board', players, 'history')
97
+ expect(game_state.computer_player).to eq(computer_player)
98
+ end
99
+ end
100
+
91
101
  describe '#turn_over' do
92
102
  it 'records the last move' do
93
103
  move = double
@@ -109,6 +119,15 @@ describe TicTacToes::Core::GameState do
109
119
  end
110
120
  end
111
121
 
122
+ describe '#moves' do
123
+ it 'returns it’s move history' do
124
+ moves = [['X', 0], ['O', 4]]
125
+ history = double(moves: moves)
126
+ game_state = TicTacToes::Core::GameState.new('board', 'players', history)
127
+ expect(game_state.moves).to eq(moves)
128
+ end
129
+ end
130
+
112
131
  describe '#end_game' do
113
132
  it 'records the winner' do
114
133
  winning_player = double
@@ -28,7 +28,14 @@ describe TicTacToes::Core::History do
28
28
  move = ["X", 0]
29
29
 
30
30
  history.record_move(move)
31
- expect(history.moves.first).to eql(move)
31
+ expect(history.moves.first).to eq(move)
32
+ end
33
+
34
+ it "doesn’t record anything if move is nil" do
35
+ move = nil
36
+
37
+ history.record_move(move)
38
+ expect(history.moves).to eq([])
32
39
  end
33
40
  end
34
41
 
@@ -1,9 +1,9 @@
1
1
  require 'tic_tac_toes/core/board'
2
2
  require 'tic_tac_toes/core/io'
3
- require 'tic_tac_toes/core/strings'
3
+ require 'tic_tac_toes/core/presenter'
4
4
 
5
5
  describe TicTacToes::Core::IO do
6
- let(:strings) { TicTacToes::Core::Strings }
6
+ let(:strings) { TicTacToes::Core::Presenter }
7
7
  let(:prompt) { double("prompt", solicit_input: 0, display: true, display_red: true) }
8
8
  let(:io) { TicTacToes::Core::IO.new(prompt) }
9
9
 
@@ -0,0 +1,95 @@
1
+ require 'tic_tac_toes/core/board'
2
+ require 'tic_tac_toes/core/rules'
3
+ require 'tic_tac_toes/core/presenter'
4
+
5
+ describe TicTacToes::Core::Presenter do
6
+ before do
7
+ @presenter = TicTacToes::Core::Presenter
8
+ end
9
+
10
+ describe '#invalid_row_size' do
11
+ it "returns a string containing the minimum and maximum allowed row sizes" do
12
+ smallest_row_size = TicTacToes::Core::Rules::ROW_SIZE_RANGE.min.to_s
13
+ largest_row_size = TicTacToes::Core::Rules::ROW_SIZE_RANGE.max.to_s
14
+
15
+ expect(@presenter::INVALID_ROW_SIZE).to include(smallest_row_size, largest_row_size)
16
+ end
17
+ end
18
+
19
+ describe '#token_solicitation' do
20
+ it "returns a string containing the name of the player whose token is being picked" do
21
+ player = "human"
22
+ expect(@presenter.token_solicitation(player)).to include(player)
23
+ end
24
+ end
25
+
26
+ describe '#game_over_notification' do
27
+ it "returns a string containing the name of the winner" do
28
+ winner = "X"
29
+ expect(@presenter.game_over_notification(winner)).to include(winner)
30
+ end
31
+ end
32
+
33
+ describe '#board' do
34
+ it "returns a board string" do
35
+ board = TicTacToes::Core::Board.new(row_size: 3)
36
+
37
+ leading_spaces_regexp = /^[[:blank:]]+/
38
+ board_string = <<-END.gsub(leading_spaces_regexp, '')
39
+
40
+ [0]|[1]|[2]
41
+ -----------
42
+ [3]|[4]|[5]
43
+ -----------
44
+ [6]|[7]|[8]
45
+
46
+ END
47
+
48
+ expect(@presenter.board(board)).to eql(board_string)
49
+ end
50
+ end
51
+
52
+ describe '#game_history_strings' do
53
+ it 'Returns an array with a string for each game history' do
54
+ history_double = double('history',
55
+ board_size: 9,
56
+ difficulty: 'Medium AI',
57
+ winner: 'X',
58
+ moves: [['A', 0], ['B', 4]])
59
+ histories_array = [history_double, history_double]
60
+ wrapper = double('wrapper', read_game_histories: histories_array)
61
+
62
+ expect(@presenter.game_history_strings(wrapper).count).to eq(2)
63
+ end
64
+ end
65
+
66
+ describe '#game_history_string' do
67
+ before do
68
+ @history_double = double('history',
69
+ board_size: 9,
70
+ difficulty: 'Medium AI',
71
+ winner: 'X',
72
+ moves: [['A', 0], ['B', 4]])
73
+ end
74
+
75
+ it 'Returns a string that includes the game history’s board size' do
76
+ history_string = @presenter.game_history_string(@history_double)
77
+ expect(history_string).to include('9')
78
+ end
79
+
80
+ it 'Returns a string that includes the game history’s difficulty' do
81
+ history_string = @presenter.game_history_string(@history_double)
82
+ expect(history_string).to include('Medium AI')
83
+ end
84
+
85
+ it 'Returns a string that includes the game history’s winner' do
86
+ history_string = @presenter.game_history_string(@history_double)
87
+ expect(history_string).to include('X')
88
+ end
89
+
90
+ it 'Returns a string that includes the game history’s move history' do
91
+ history_string = @presenter.game_history_string(@history_double)
92
+ expect(history_string).to include('A', '0', 'B', '4')
93
+ end
94
+ end
95
+ end
@@ -19,8 +19,8 @@ describe TicTacToes::UI::Adapter do
19
19
  context 'when passed an order of “second”' do
20
20
  it 'sends its listener #moves_were_made with the game state' do
21
21
  order = 'second'
22
- computer_player = double(place_and_return_move: 0)
23
- game_state = double(game_over?: false, turn_over: true, current_player: computer_player)
22
+ computer_player = double(place_and_return_move: 0, token: 'O')
23
+ game_state = double(game_over?: false, turn_over: true, computer_player: computer_player)
24
24
  listener = double
25
25
 
26
26
  expect(listener).to receive(:moves_were_made).with(game_state)
@@ -56,6 +56,21 @@ describe TicTacToes::UI::Adapter do
56
56
  end
57
57
  end
58
58
 
59
+ context 'when the game is over' do
60
+ it 'records the game history' do
61
+ board = TicTacToes::TestBoardGenerator.generate([ x, x, nil,
62
+ nil, nil, nil,
63
+ nil, nil, nil])
64
+ game_state = TicTacToes::Core::GameState.new(board, players, history)
65
+ move = '2'
66
+ listener = double(game_ended_in_winner: true)
67
+
68
+ expect(history).to receive(:persist)
69
+ TicTacToes::UI::Adapter.make_move(game_state, move, listener)
70
+ board.place(x, 2)
71
+ end
72
+ end
73
+
59
74
  context 'when the game has ended with a winner' do
60
75
  it 'sends its listener #game_ended_in_winner with the updated game state and the winning token' do
61
76
  board = TicTacToes::TestBoardGenerator.generate([ x, x, nil,
@@ -98,7 +113,7 @@ describe TicTacToes::UI::Adapter do
98
113
  player_factory = TicTacToes::Core::PlayerFactory.new('unused_io')
99
114
  let(:x) { player_factory.generate_player('x', TicTacToes::Core::PlayerFactory::HUMAN) }
100
115
  let(:o) { player_factory.generate_player('o', TicTacToes::Core::PlayerFactory::HARD_AI) }
101
- let(:players) { [o, x] }
116
+ let(:players) { [x, o] }
102
117
 
103
118
  it 'returns an array indicating which moves will result in a win' do
104
119
  board = TicTacToes::TestBoardGenerator.generate([ x, x, nil,
@@ -139,9 +154,9 @@ describe TicTacToes::UI::Adapter do
139
154
  nil, nil, x])
140
155
  game_state = TicTacToes::Core::GameState.new(board, players, history)
141
156
 
142
- expect(TicTacToes::UI::Adapter.predictions(game_state)).to eq([ nil, nil, nil,
143
- nil, nil, "loss",
144
- nil, "loss", nil])
157
+ expect(TicTacToes::UI::Adapter.predictions(game_state)).to eq([nil, nil, nil,
158
+ nil, nil, "loss",
159
+ nil, "loss", nil])
145
160
  end
146
161
  end
147
162
  end
@@ -11,13 +11,14 @@ describe TicTacToes::UI::Serializer do
11
11
  end
12
12
  end
13
13
 
14
- describe '#game_state_from_board_structure' do
15
- it 'returns a game state object based on a board structure and computer type' do
14
+ describe '#game_state' do
15
+ it 'returns a game state object based on a board structure and AI type' do
16
16
  board_structure = [nil, nil, nil, nil, 'X', nil, nil, nil, nil]
17
- computer_type = 'EASY_AI'
17
+ ai_type = 'EASY_AI'
18
+ move_history = 'X0O4'
18
19
  ai = TicTacToes::Core::PlayerFactory::AIS.fetch(TicTacToes::Core::PlayerFactory::EASY_AI)
19
20
 
20
- game_state = TicTacToes::UI::Serializer.game_state_from_board_structure(board_structure, computer_type)
21
+ game_state = TicTacToes::UI::Serializer.game_state(board_structure, ai_type, move_history)
21
22
  middle_space = game_state.board.space(4)
22
23
  first_player = game_state.players.first
23
24
  second_player = game_state.players.last
@@ -26,10 +27,11 @@ describe TicTacToes::UI::Serializer do
26
27
  expect(first_player.token).to eq(TicTacToes::UI::Serializer::X)
27
28
  expect(second_player.token).to eq(TicTacToes::UI::Serializer::O)
28
29
  expect(second_player.move_strategy).to eq(ai)
30
+ expect(game_state.moves).to eq([['X', 0], ['O', 4]])
29
31
  end
30
32
  end
31
33
 
32
- describe '#board_structure_from_game_state' do
34
+ describe '#board_structure' do
33
35
  it 'returns a board structure based on a game state object' do
34
36
  player_factory = TicTacToes::Core::PlayerFactory.new('unused_io')
35
37
  first_player = player_factory.generate_player(TicTacToes::UI::Serializer::X, TicTacToes::Core::PlayerFactory::HUMAN)
@@ -40,17 +42,25 @@ describe TicTacToes::UI::Serializer do
40
42
 
41
43
  game_state = TicTacToes::Core::GameState.new(board, players, TicTacToes::UI::NullHistory.new)
42
44
  board_structure = [nil, nil, nil, nil, 'X', nil, nil, nil, nil]
43
- expect(TicTacToes::UI::Serializer.board_structure_from_game_state(game_state)).to eq(board_structure)
45
+ expect(TicTacToes::UI::Serializer.board_structure(game_state)).to eq(board_structure)
44
46
  end
45
47
  end
46
48
 
47
- describe '#ai_type_from_game_state' do
49
+ describe '#ai_type' do
48
50
  it 'returns the type of a game state’s computer player' do
49
51
  move_strategy = TicTacToes::Core::PlayerFactory::AIS.fetch(TicTacToes::Core::PlayerFactory::EASY_AI)
50
52
  computer_player = double(move_strategy: move_strategy)
51
53
  players = [computer_player]
52
54
  game_state = double(players: players)
53
- expect(TicTacToes::UI::Serializer.ai_type_from_game_state(game_state)).to eq('EASY_AI')
55
+ expect(TicTacToes::UI::Serializer.ai_type(game_state)).to eq('EASY_AI')
56
+ end
57
+ end
58
+
59
+ describe '#move_history' do
60
+ it 'returns a move history structure based on a game state object' do
61
+ moves = [['X', 0], ['O', 4]]
62
+ game_state = double('game_state', moves: moves)
63
+ expect(TicTacToes::UI::Serializer.move_history(game_state)).to eq('X0O4')
54
64
  end
55
65
  end
56
66
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tic_tac_toes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Spatafora
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-26 00:00:00.000000000 Z
11
+ date: 2014-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -87,7 +87,6 @@ files:
87
87
  - bin/game_histories
88
88
  - bin/set_up_ttt_databases
89
89
  - bin/tic_tac_toes
90
- - lib/tic_tac_toes/command_line/history_reader.rb
91
90
  - lib/tic_tac_toes/command_line/menu.rb
92
91
  - lib/tic_tac_toes/command_line/prompt.rb
93
92
  - lib/tic_tac_toes/command_line/runner.rb
@@ -102,15 +101,14 @@ files:
102
101
  - lib/tic_tac_toes/core/move_strategies/types.rb
103
102
  - lib/tic_tac_toes/core/player.rb
104
103
  - lib/tic_tac_toes/core/player_factory.rb
104
+ - lib/tic_tac_toes/core/presenter.rb
105
105
  - lib/tic_tac_toes/core/rules.rb
106
- - lib/tic_tac_toes/core/strings.rb
107
106
  - lib/tic_tac_toes/database/pg_wrapper.rb
108
107
  - lib/tic_tac_toes/tasks/destroy_databases.rake
109
108
  - lib/tic_tac_toes/tasks/set_up_databases.rake
110
109
  - lib/tic_tac_toes/ui/adapter.rb
111
110
  - lib/tic_tac_toes/ui/serializer.rb
112
111
  - lib/tic_tac_toes/version.rb
113
- - spec/tic_tac_toes/command_line/history_reader_spec.rb
114
112
  - spec/tic_tac_toes/command_line/menu_spec.rb
115
113
  - spec/tic_tac_toes/core/board_spec.rb
116
114
  - spec/tic_tac_toes/core/game_state_spec.rb
@@ -122,8 +120,8 @@ files:
122
120
  - spec/tic_tac_toes/core/move_strategies/medium_ai_spec.rb
123
121
  - spec/tic_tac_toes/core/player_factory_spec.rb
124
122
  - spec/tic_tac_toes/core/player_spec.rb
123
+ - spec/tic_tac_toes/core/presenter_spec.rb
125
124
  - spec/tic_tac_toes/core/rules_spec.rb
126
- - spec/tic_tac_toes/core/strings_spec.rb
127
125
  - spec/tic_tac_toes/database/pg_wrapper_spec.rb
128
126
  - spec/tic_tac_toes/test_board_generator.rb
129
127
  - spec/tic_tac_toes/ui/adapter_spec.rb
@@ -154,7 +152,6 @@ signing_key:
154
152
  specification_version: 4
155
153
  summary: The game Tic-tac-toe, featuring an unbeatable AI
156
154
  test_files:
157
- - spec/tic_tac_toes/command_line/history_reader_spec.rb
158
155
  - spec/tic_tac_toes/command_line/menu_spec.rb
159
156
  - spec/tic_tac_toes/core/board_spec.rb
160
157
  - spec/tic_tac_toes/core/game_state_spec.rb
@@ -166,8 +163,8 @@ test_files:
166
163
  - spec/tic_tac_toes/core/move_strategies/medium_ai_spec.rb
167
164
  - spec/tic_tac_toes/core/player_factory_spec.rb
168
165
  - spec/tic_tac_toes/core/player_spec.rb
166
+ - spec/tic_tac_toes/core/presenter_spec.rb
169
167
  - spec/tic_tac_toes/core/rules_spec.rb
170
- - spec/tic_tac_toes/core/strings_spec.rb
171
168
  - spec/tic_tac_toes/database/pg_wrapper_spec.rb
172
169
  - spec/tic_tac_toes/test_board_generator.rb
173
170
  - spec/tic_tac_toes/ui/adapter_spec.rb
@@ -1,28 +0,0 @@
1
- require 'tic_tac_toes/command_line/prompt'
2
-
3
- module TicTacToes
4
- module CommandLine
5
- class HistoryReader
6
- def initialize(wrapper)
7
- @wrapper = wrapper
8
- end
9
-
10
- def display_game_histories
11
- game_histories = @wrapper.read_game_histories
12
- game_histories.each { |history| Prompt.display(game_history_string(history)) }
13
- nil
14
- end
15
-
16
- def game_history_string(history)
17
- history_string = ''
18
- history_string << "Board size: #{history.board_size.to_s}\n"
19
- history_string << "Difficulty: #{history.difficulty}\n"
20
- history_string << "Winner: #{history.winner}\n"
21
- history_string << "Move history:\n"
22
- history.moves.each { |move| history_string << " #{move.join(' -> ')}\n" }
23
- history_string << "\n"
24
- history_string
25
- end
26
- end
27
- end
28
- end
@@ -1,48 +0,0 @@
1
- require 'tic_tac_toes/command_line/history_reader'
2
-
3
- describe TicTacToes::CommandLine::HistoryReader do
4
- before do
5
- @history_double = double('history',
6
- board_size: 9,
7
- difficulty: 'Medium AI',
8
- winner: 'X',
9
- moves: [['A', 0], ['B', 4]])
10
- end
11
-
12
- describe '#display_game_histories' do
13
- it 'Displays something for each game history' do
14
- histories_array = [@history_double, @history_double]
15
- wrapper = double('wrapper', read_game_histories: histories_array)
16
-
17
- expect(TicTacToes::CommandLine::Prompt).to receive(:display).twice
18
- TicTacToes::CommandLine::HistoryReader.new(wrapper).display_game_histories
19
- end
20
- end
21
-
22
- describe '#game_history_string' do
23
- before do
24
- wrapper_double = double('wrapper')
25
- @history_reader = TicTacToes::CommandLine::HistoryReader.new(wrapper_double)
26
- end
27
-
28
- it 'Returns a string that includes the game history’s board size' do
29
- history_string = @history_reader.game_history_string(@history_double)
30
- expect(history_string).to include('9')
31
- end
32
-
33
- it 'Returns a string that includes the game history’s difficulty' do
34
- history_string = @history_reader.game_history_string(@history_double)
35
- expect(history_string).to include('Medium AI')
36
- end
37
-
38
- it 'Returns a string that includes the game history’s winner' do
39
- history_string = @history_reader.game_history_string(@history_double)
40
- expect(history_string).to include('X')
41
- end
42
-
43
- it 'Returns a string that includes the game history’s move history' do
44
- history_string = @history_reader.game_history_string(@history_double)
45
- expect(history_string).to include('A', '0', 'B', '4')
46
- end
47
- end
48
- end
@@ -1,49 +0,0 @@
1
- require 'tic_tac_toes/core/board'
2
- require 'tic_tac_toes/core/rules'
3
- require 'tic_tac_toes/core/strings'
4
-
5
- describe TicTacToes::Core::Strings do
6
- let(:strings) { TicTacToes::Core::Strings }
7
-
8
- describe '#invalid_row_size' do
9
- it "returns a string containing the minimum and maximum allowed row sizes" do
10
- smallest_row_size = TicTacToes::Core::Rules::ROW_SIZE_RANGE.min.to_s
11
- largest_row_size = TicTacToes::Core::Rules::ROW_SIZE_RANGE.max.to_s
12
-
13
- expect(strings::INVALID_ROW_SIZE).to include(smallest_row_size, largest_row_size)
14
- end
15
- end
16
-
17
- describe '#token_solicitation' do
18
- it "returns a string containing the name of the player whose token is being picked" do
19
- player = "human"
20
- expect(strings.token_solicitation(player)).to include(player)
21
- end
22
- end
23
-
24
- describe '#game_over_notification' do
25
- it "returns a string containing the name of the winner" do
26
- winner = "X"
27
- expect(strings.game_over_notification(winner)).to include(winner)
28
- end
29
- end
30
-
31
- describe '#board' do
32
- it "returns a board string" do
33
- board = TicTacToes::Core::Board.new(row_size: 3)
34
-
35
- leading_spaces_regexp = /^[[:blank:]]+/
36
- board_string = <<-END.gsub(leading_spaces_regexp, '')
37
-
38
- [0]|[1]|[2]
39
- -----------
40
- [3]|[4]|[5]
41
- -----------
42
- [6]|[7]|[8]
43
-
44
- END
45
-
46
- expect(strings.board(board)).to eql(board_string)
47
- end
48
- end
49
- end