tic_tac_toes 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/tic_tac_toes/command_line/menu.rb +3 -2
- data/lib/tic_tac_toes/core/player_factory.rb +18 -12
- data/lib/tic_tac_toes/ui/adapter.rb +9 -0
- data/lib/tic_tac_toes/ui/serializer.rb +20 -4
- data/lib/tic_tac_toes/version.rb +1 -1
- data/spec/tic_tac_toes/core/move_strategies/easy_ai_spec.rb +2 -2
- data/spec/tic_tac_toes/core/move_strategies/medium_ai_spec.rb +2 -2
- data/spec/tic_tac_toes/core/player_factory_spec.rb +14 -18
- data/spec/tic_tac_toes/ui/adapter_spec.rb +27 -2
- data/spec/tic_tac_toes/ui/serializer_spec.rb +19 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e7b4f6653858ee05ee85a0ad10f519879bed750
|
4
|
+
data.tar.gz: e5aaea09afc5342b96fb823881ba26ef691f00af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49287beb325485b2b1affb085f082f03804f8c0a9a21bd761ca8bddca64e681fb98be844dac1c6ec0d1f3df58ee96e7e23518b18351c06b021838c5cbf05cb19
|
7
|
+
data.tar.gz: 0874989c2aaf4f7dd1712266303fbad25c4f911507c158b65d0e1ae72b94605e842366b708485f21f51420cb99823e7bd403f8ada58b58cb947783e377cc310b
|
data/Gemfile.lock
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'tic_tac_toes/core/board'
|
2
2
|
require 'tic_tac_toes/core/rules'
|
3
|
+
require 'tic_tac_toes/core/player_factory'
|
3
4
|
|
4
5
|
module TicTacToes
|
5
6
|
module CommandLine
|
@@ -20,8 +21,8 @@ module TicTacToes
|
|
20
21
|
computer_token = get_token(:computer, taken_tokens)
|
21
22
|
difficulty = get_difficulty
|
22
23
|
|
23
|
-
human_player = @player_factory.
|
24
|
-
computer_player = @player_factory.
|
24
|
+
human_player = @player_factory.generate_player(human_token, Core::PlayerFactory::HUMAN)
|
25
|
+
computer_player = @player_factory.generate_player(computer_token, difficulty)
|
25
26
|
[human_player, computer_player]
|
26
27
|
end
|
27
28
|
|
@@ -7,23 +7,29 @@ require 'tic_tac_toes/core/player'
|
|
7
7
|
module TicTacToes
|
8
8
|
module Core
|
9
9
|
class PlayerFactory
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
|
11
|
+
HUMAN = :human
|
12
|
+
EASY_AI = :easy
|
13
|
+
MEDIUM_AI = :medium
|
14
|
+
HARD_AI = :hard
|
13
15
|
|
14
16
|
AIS = {
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
EASY_AI => MoveStrategies::EasyAI,
|
18
|
+
MEDIUM_AI => MoveStrategies::MediumAI,
|
19
|
+
HARD_AI => MoveStrategies::HardAI
|
20
|
+
}
|
18
21
|
|
19
|
-
def
|
20
|
-
|
21
|
-
Player.new(TicTacToes::Core::MoveStrategies::Human.new(@io), token, needs_to_think, @io)
|
22
|
+
def initialize(io)
|
23
|
+
@io = io
|
22
24
|
end
|
23
25
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
26
|
+
def generate_player(token, type)
|
27
|
+
case type
|
28
|
+
when HUMAN
|
29
|
+
Player.new(MoveStrategies::Human.new(@io), token, false, @io)
|
30
|
+
else
|
31
|
+
Player.new(AIS.fetch(type), token, true, @io)
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -1,6 +1,15 @@
|
|
1
1
|
module TicTacToes
|
2
2
|
module UI
|
3
3
|
module Adapter
|
4
|
+
def self.start_game(order, game_state, listener)
|
5
|
+
case order
|
6
|
+
when 'first'
|
7
|
+
listener.moves_were_made(game_state)
|
8
|
+
when 'second'
|
9
|
+
make_move(game_state, nil, listener)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
4
13
|
def self.make_move(game_state, move, listener)
|
5
14
|
unless move.nil?
|
6
15
|
move = move.to_i
|
@@ -13,10 +13,10 @@ module TicTacToes
|
|
13
13
|
board.spaces
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.game_state_from_board_structure(board_structure)
|
16
|
+
def self.game_state_from_board_structure(board_structure, computer_type)
|
17
17
|
player_factory = Core::PlayerFactory.new('unused_io')
|
18
|
-
human_player = player_factory.
|
19
|
-
computer_player = player_factory.
|
18
|
+
human_player = player_factory.generate_player(X, Core::PlayerFactory::HUMAN)
|
19
|
+
computer_player = player_factory.generate_player(O, Core::PlayerFactory.const_get(computer_type))
|
20
20
|
players = [human_player, computer_player]
|
21
21
|
|
22
22
|
board_structure_with_players = replace_tokens_with_players(board_structure, human_player, computer_player)
|
@@ -25,12 +25,28 @@ module TicTacToes
|
|
25
25
|
Core::GameState.new(board, players, NullHistory.new)
|
26
26
|
end
|
27
27
|
|
28
|
-
def self.
|
28
|
+
def self.board_structure_from_game_state(game_state)
|
29
29
|
structure_with_players = game_state.board.spaces
|
30
30
|
|
31
31
|
replace_players_with_tokens(structure_with_players)
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.computer_type_from_game_state(game_state)
|
35
|
+
type = nil
|
36
|
+
|
37
|
+
game_state.players.each do |player|
|
38
|
+
if player.move_strategy == Core::PlayerFactory::AIS.fetch(Core::PlayerFactory::EASY_AI)
|
39
|
+
type = 'EASY_AI'
|
40
|
+
elsif player.move_strategy == Core::PlayerFactory::AIS.fetch(Core::PlayerFactory::MEDIUM_AI)
|
41
|
+
type = 'MEDIUM_AI'
|
42
|
+
elsif player.move_strategy == Core::PlayerFactory::AIS.fetch(Core::PlayerFactory::HARD_AI)
|
43
|
+
type = 'HARD_AI'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
type
|
48
|
+
end
|
49
|
+
|
34
50
|
private
|
35
51
|
|
36
52
|
def self.replace_tokens_with_players(board_structure, human_player, computer_player)
|
data/lib/tic_tac_toes/version.rb
CHANGED
@@ -7,8 +7,8 @@ describe TicTacToes::Core::MoveStrategies::EasyAI do
|
|
7
7
|
describe '#move' do
|
8
8
|
it "returns a randomly-selected valid move" do
|
9
9
|
player_factory = TicTacToes::Core::PlayerFactory.new('unused_io')
|
10
|
-
x = player_factory.
|
11
|
-
o = player_factory.
|
10
|
+
x = player_factory.generate_player('x', TicTacToes::Core::PlayerFactory::HUMAN)
|
11
|
+
o = player_factory.generate_player('o', TicTacToes::Core::PlayerFactory::EASY_AI)
|
12
12
|
players = [x, o]
|
13
13
|
|
14
14
|
board = TicTacToes::TestBoardGenerator.generate([ o, nil, nil,
|
@@ -7,8 +7,8 @@ describe TicTacToes::Core::MoveStrategies::MediumAI do
|
|
7
7
|
describe '#move' do
|
8
8
|
it "returns a valid move (based on either EasyAI or HardAI)" do
|
9
9
|
player_factory = TicTacToes::Core::PlayerFactory.new('unused_io')
|
10
|
-
x = player_factory.
|
11
|
-
o = player_factory.
|
10
|
+
x = player_factory.generate_player('x', TicTacToes::Core::PlayerFactory::HUMAN)
|
11
|
+
o = player_factory.generate_player('o', TicTacToes::Core::PlayerFactory::MEDIUM_AI)
|
12
12
|
players = [x, o]
|
13
13
|
|
14
14
|
board = TicTacToes::TestBoardGenerator.generate([ o, o, x,
|
@@ -3,29 +3,25 @@ require 'tic_tac_toes/core/move_strategies/medium_ai'
|
|
3
3
|
require 'tic_tac_toes/core/player_factory'
|
4
4
|
|
5
5
|
describe TicTacToes::Core::PlayerFactory do
|
6
|
-
|
6
|
+
describe '#generate_player' do
|
7
|
+
before { @player_factory = TicTacToes::Core::PlayerFactory.new('io') }
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
token = 'X'
|
9
|
+
context 'when passed HUMAN' do
|
10
|
+
it "returns a player with the correct token and a Human move strategy" do
|
11
|
+
human_player = @player_factory.generate_player('X', TicTacToes::Core::PlayerFactory::HUMAN)
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
expect(human_player.token).to eq('X')
|
14
|
+
expect(human_player.move_strategy).to be_a TicTacToes::Core::MoveStrategies::Human
|
15
|
+
end
|
16
16
|
end
|
17
|
-
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
difficulty = :medium
|
23
|
-
strategy = TicTacToes::Core::MoveStrategies::MediumAI
|
18
|
+
context 'when passed EASY_AI, MEDIUM_AI, or HARD_AI' do
|
19
|
+
it 'returns a player with the correct token and correct AI move strategy' do
|
20
|
+
computer_player = @player_factory.generate_player('O', TicTacToes::Core::PlayerFactory::MEDIUM_AI)
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
expect(computer_player.token).to eq(token)
|
22
|
+
expect(computer_player.move_strategy).to eq(TicTacToes::Core::MoveStrategies::MediumAI)
|
23
|
+
expect(computer_player.token).to eq('O')
|
24
|
+
end
|
29
25
|
end
|
30
26
|
end
|
31
27
|
end
|
@@ -4,12 +4,37 @@ require 'tic_tac_toes/test_board_generator'
|
|
4
4
|
require 'tic_tac_toes/ui/adapter'
|
5
5
|
|
6
6
|
describe TicTacToes::UI::Adapter do
|
7
|
+
describe '#start_game' do
|
8
|
+
context 'when passed an order of “first”' do
|
9
|
+
it 'sends its listener #moves_were_made with the game state' do
|
10
|
+
order = 'first'
|
11
|
+
game_state = double
|
12
|
+
listener = double
|
13
|
+
|
14
|
+
expect(listener).to receive(:moves_were_made).with(game_state)
|
15
|
+
TicTacToes::UI::Adapter.start_game(order, game_state, listener)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when passed an order of “second”' do
|
20
|
+
it 'sends its listener #moves_were_made with the game state' do
|
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)
|
24
|
+
listener = double
|
25
|
+
|
26
|
+
expect(listener).to receive(:moves_were_made).with(game_state)
|
27
|
+
TicTacToes::UI::Adapter.start_game(order, game_state, listener)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
7
32
|
describe '#make_move' do
|
8
33
|
let(:history) { TicTacToes::UI::NullHistory.new }
|
9
34
|
|
10
35
|
player_factory = TicTacToes::Core::PlayerFactory.new('unused_io')
|
11
|
-
let(:x) { player_factory.
|
12
|
-
let(:o) { player_factory.
|
36
|
+
let(:x) { player_factory.generate_player('x', TicTacToes::Core::PlayerFactory::HUMAN) }
|
37
|
+
let(:o) { player_factory.generate_player('o', TicTacToes::Core::PlayerFactory::HARD_AI) }
|
13
38
|
let(:players) { [x, o] }
|
14
39
|
|
15
40
|
context 'when the game is still in progress' do
|
@@ -12,10 +12,12 @@ describe TicTacToes::UI::Serializer do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
describe '#game_state_from_board_structure' do
|
15
|
-
it 'returns a game state object based on a board structure' do
|
15
|
+
it 'returns a game state object based on a board structure and computer type' do
|
16
16
|
board_structure = [nil, nil, nil, nil, 'X', nil, nil, nil, nil]
|
17
|
+
computer_type = 'EASY_AI'
|
18
|
+
ai = TicTacToes::Core::PlayerFactory::AIS.fetch(TicTacToes::Core::PlayerFactory::EASY_AI)
|
17
19
|
|
18
|
-
game_state = TicTacToes::UI::Serializer.game_state_from_board_structure(board_structure)
|
20
|
+
game_state = TicTacToes::UI::Serializer.game_state_from_board_structure(board_structure, computer_type)
|
19
21
|
middle_space = game_state.board.space(4)
|
20
22
|
first_player = game_state.players.first
|
21
23
|
second_player = game_state.players.last
|
@@ -23,21 +25,32 @@ describe TicTacToes::UI::Serializer do
|
|
23
25
|
expect(middle_space.token).to eq(TicTacToes::UI::Serializer::X)
|
24
26
|
expect(first_player.token).to eq(TicTacToes::UI::Serializer::X)
|
25
27
|
expect(second_player.token).to eq(TicTacToes::UI::Serializer::O)
|
28
|
+
expect(second_player.move_strategy).to eq(ai)
|
26
29
|
end
|
27
30
|
end
|
28
31
|
|
29
|
-
describe '#
|
32
|
+
describe '#board_structure_from_game_state' do
|
30
33
|
it 'returns a board structure based on a game state object' do
|
31
34
|
player_factory = TicTacToes::Core::PlayerFactory.new('unused_io')
|
32
|
-
first_player = player_factory.
|
33
|
-
second_player = player_factory.
|
35
|
+
first_player = player_factory.generate_player(TicTacToes::UI::Serializer::X, TicTacToes::Core::PlayerFactory::HUMAN)
|
36
|
+
second_player = player_factory.generate_player(TicTacToes::UI::Serializer::O, TicTacToes::Core::PlayerFactory::HARD_AI)
|
34
37
|
players = [first_player, second_player]
|
35
38
|
board = TicTacToes::Core::Board.new
|
36
39
|
board.place(first_player, 4)
|
37
40
|
|
38
41
|
game_state = TicTacToes::Core::GameState.new(board, players, TicTacToes::UI::NullHistory.new)
|
39
42
|
board_structure = [nil, nil, nil, nil, 'X', nil, nil, nil, nil]
|
40
|
-
expect(TicTacToes::UI::Serializer.
|
43
|
+
expect(TicTacToes::UI::Serializer.board_structure_from_game_state(game_state)).to eq(board_structure)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#computer_type_from_game_state' do
|
48
|
+
it 'returns the type of a game state’s computer player' do
|
49
|
+
move_strategy = TicTacToes::Core::PlayerFactory::AIS.fetch(TicTacToes::Core::PlayerFactory::EASY_AI)
|
50
|
+
computer_player = double(move_strategy: move_strategy)
|
51
|
+
players = [computer_player]
|
52
|
+
game_state = double(players: players)
|
53
|
+
expect(TicTacToes::UI::Serializer.computer_type_from_game_state(game_state)).to eq('EASY_AI')
|
41
54
|
end
|
42
55
|
end
|
43
56
|
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
|
+
version: 0.1.1
|
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-
|
11
|
+
date: 2014-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|