connect_n_game 0.0.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 +7 -0
- data/.gitignore +21 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +74 -0
- data/Rakefile +48 -0
- data/bin/connect_n_game +16 -0
- data/connect_n_game.gemspec +26 -0
- data/lib/cli/cli.rb +72 -0
- data/lib/cli/cli_debug.rb +20 -0
- data/lib/cli/cli_human.rb +41 -0
- data/lib/cli/cli_rack.rb +30 -0
- data/lib/cli/process_options.rb +62 -0
- data/lib/cli/select_players.rb +54 -0
- data/lib/connect_n_game.rb +13 -0
- data/lib/connect_n_game/exceptions.rb +8 -0
- data/lib/connect_n_game/game.rb +93 -0
- data/lib/connect_n_game/game/rack.rb +180 -0
- data/lib/connect_n_game/human.rb +30 -0
- data/lib/connect_n_game/player.rb +70 -0
- data/lib/connect_n_game/players/basic.rb +39 -0
- data/lib/connect_n_game/players/echo.rb +45 -0
- data/lib/connect_n_game/players/just_random.rb +40 -0
- data/lib/connect_n_game/players/middle.rb +41 -0
- data/lib/connect_n_game/players/prudent.rb +67 -0
- data/lib/connect_n_game/ui.rb +9 -0
- data/lib/connect_n_game/util.rb +26 -0
- data/lib/connect_n_game/version.rb +5 -0
- data/tests/test_game.rb +53 -0
- data/tests/test_module.rb +20 -0
- data/tests/test_player.rb +55 -0
- data/tests/test_rack.rb +222 -0
- data/tests/test_ui.rb +15 -0
- metadata +133 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ConnectNGame
|
4
|
+
|
5
|
+
#The EchoMoves echoes moves when possible.
|
6
|
+
class BasicMoves < Player
|
7
|
+
|
8
|
+
#Build the player
|
9
|
+
def initialize(name = "Basic")
|
10
|
+
super(name, "Minimum tactical analysis.", :silicon)
|
11
|
+
end
|
12
|
+
|
13
|
+
#Make a move. This bot picks the move with the highest score.
|
14
|
+
#<br>Parameters
|
15
|
+
#* game - the game being played.
|
16
|
+
#* piece - the piece to be played, 1 or 2.
|
17
|
+
#<br>Returns
|
18
|
+
#* A move, 1 .. rack.width
|
19
|
+
def make_move(game, piece)
|
20
|
+
(game.rack.weights.each_with_index.map do |weight, index|
|
21
|
+
channel = index + 1
|
22
|
+
[weight + game.rack.score_move(channel, piece), channel]
|
23
|
+
end).sort.show_weights("Scan").last[1]
|
24
|
+
end
|
25
|
+
|
26
|
+
#The thrill of victory.
|
27
|
+
def winners_comments
|
28
|
+
"#{name} says 'A genius in my own mind!'"
|
29
|
+
end
|
30
|
+
|
31
|
+
#The agony of defeat
|
32
|
+
def losers_comments
|
33
|
+
"#{name} says 'Hmmm... What did I miss?'"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
Player.players << BasicMoves.new
|
39
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ConnectNGame
|
4
|
+
|
5
|
+
#The EchoMoves echoes moves when possible.
|
6
|
+
class EchoMoves < Player
|
7
|
+
|
8
|
+
#Build the player
|
9
|
+
def initialize(name = "Echo")
|
10
|
+
super(name, "Really unoriginal.", :silicon)
|
11
|
+
end
|
12
|
+
|
13
|
+
#Make a move. This bot parrots the previous move when it can,
|
14
|
+
#and moves randomly when it cannot.
|
15
|
+
#<br>Parameters
|
16
|
+
#* game - the game being played.
|
17
|
+
#* _piece - the piece to be played, 1 or 2. (Not used here)
|
18
|
+
#<br>Returns
|
19
|
+
#* A move, 1 .. rack.width
|
20
|
+
def make_move(game, _piece)
|
21
|
+
channel = game.last_move
|
22
|
+
|
23
|
+
unless channel && !game.rack.channel_full?(channel)
|
24
|
+
begin
|
25
|
+
channel = rand(1..(game.rack.width))
|
26
|
+
end while game.rack.channel_full?(channel)
|
27
|
+
end
|
28
|
+
|
29
|
+
channel
|
30
|
+
end
|
31
|
+
|
32
|
+
#The thrill of victory.
|
33
|
+
def winners_comments
|
34
|
+
"#{name} says 'How did this happen?'"
|
35
|
+
end
|
36
|
+
|
37
|
+
#The agony of defeat
|
38
|
+
def losers_comments
|
39
|
+
"#{name} says 'Yes! I came in second!'"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
Player.players << EchoMoves.new
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ConnectNGame
|
4
|
+
|
5
|
+
#The JustRandom player simply make random moves.
|
6
|
+
class JustRandom < Player
|
7
|
+
|
8
|
+
#Build the player
|
9
|
+
def initialize(name = "Random")
|
10
|
+
super(name, "Moves randomly.", :silicon)
|
11
|
+
end
|
12
|
+
|
13
|
+
#Make a move. This bot moves randomly.
|
14
|
+
#<br>Parameters
|
15
|
+
#* game - the game being played.
|
16
|
+
#* _piece - the piece to be played, 1 or 2. (Not used here)
|
17
|
+
#<br>Returns
|
18
|
+
#* A move, 1 .. rack.width
|
19
|
+
def make_move(game, _piece)
|
20
|
+
begin
|
21
|
+
channel = rand(1..(game.rack.width))
|
22
|
+
end while game.rack.channel_full?(channel)
|
23
|
+
|
24
|
+
channel
|
25
|
+
end
|
26
|
+
|
27
|
+
#The thrill of victory.
|
28
|
+
def winners_comments
|
29
|
+
"#{name} says 'It was all up to pure skill!'"
|
30
|
+
end
|
31
|
+
|
32
|
+
#The agony of defeat
|
33
|
+
def losers_comments
|
34
|
+
"#{name} says 'No comment.'"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
Player.players << JustRandom.new
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ConnectNGame
|
4
|
+
|
5
|
+
#The EchoMoves echoes moves when possible.
|
6
|
+
class MiddleMoves < Player
|
7
|
+
|
8
|
+
#Build the player
|
9
|
+
def initialize(name = "Middle")
|
10
|
+
super(name, "Moves toward the middle", :silicon)
|
11
|
+
end
|
12
|
+
|
13
|
+
#Make a move. This bot prefers to play the middle.
|
14
|
+
#<br>Parameters
|
15
|
+
#* game - the game being played.
|
16
|
+
#* _piece - the piece to be played, 1 or 2. (Not used here)
|
17
|
+
#<br>Returns
|
18
|
+
#* A move, 1 .. rack.width
|
19
|
+
def make_move(game, _piece)
|
20
|
+
weights = game.rack.weights.each_with_index.to_a
|
21
|
+
|
22
|
+
weights.sort.reverse_each do |weight, index|
|
23
|
+
channel = index + 1
|
24
|
+
return channel unless game.rack.channel_full?(channel)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#The thrill of victory.
|
29
|
+
def winners_comments
|
30
|
+
"#{name} says 'Slow and steady wins the race!'"
|
31
|
+
end
|
32
|
+
|
33
|
+
#The agony of defeat
|
34
|
+
def losers_comments
|
35
|
+
"#{name} says 'I lost to the lunatic fringe!'"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
Player.players << MiddleMoves.new
|
41
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ConnectNGame
|
4
|
+
|
5
|
+
#The EchoMoves echoes moves when possible.
|
6
|
+
class Prudent < Player
|
7
|
+
|
8
|
+
#Build the player
|
9
|
+
def initialize(name = "Prudent")
|
10
|
+
super(name, "Minimum tactical analysis with some defense.", :silicon)
|
11
|
+
end
|
12
|
+
|
13
|
+
#Make a move. This bot picks the move with the highest score.
|
14
|
+
#<br>Parameters
|
15
|
+
#* game - the game being played.
|
16
|
+
#* piece - the piece to be played, 1 or 2.
|
17
|
+
#<br>Returns
|
18
|
+
#* A move, 1 .. rack.width
|
19
|
+
def make_move(game, piece)
|
20
|
+
#Compute the moves of the first ply.
|
21
|
+
first_ply = (game.rack.weights.each_with_index.map do |weight, index|
|
22
|
+
channel = index + 1
|
23
|
+
[weight + game.rack.score_move(channel, piece), channel]
|
24
|
+
end).sort.show_weights("Scan 1")
|
25
|
+
|
26
|
+
#If we're done, stop.
|
27
|
+
return first_ply.last[1] if first_ply.last[0] >= game.rack.order
|
28
|
+
|
29
|
+
#Factor in the behavior of the opponent.
|
30
|
+
(0...(first_ply.length)).each do |index|
|
31
|
+
copy = game.rack.clone.deep_clone
|
32
|
+
|
33
|
+
copy.rack[first_ply[index][1]-1] << piece
|
34
|
+
first_ply[index][0] -= check_opponent(copy, (piece % 2) + 1)
|
35
|
+
end
|
36
|
+
|
37
|
+
first_ply.sort.show_weights("Scan 2").last[1]
|
38
|
+
end
|
39
|
+
|
40
|
+
#Check for the opponent's best moves at this level
|
41
|
+
def check_opponent(rack, piece)
|
42
|
+
threshold = rack.order - 1
|
43
|
+
result = 0
|
44
|
+
|
45
|
+
(1..rack.width).each do |channel|
|
46
|
+
score = rack.score_move(channel, piece)
|
47
|
+
score *= 2 if score > threshold
|
48
|
+
result += score if score >= threshold
|
49
|
+
end
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
#The thrill of victory.
|
55
|
+
def winners_comments
|
56
|
+
"#{name} says 'Good moves must give way to better!'"
|
57
|
+
end
|
58
|
+
|
59
|
+
#The agony of defeat
|
60
|
+
def losers_comments
|
61
|
+
"#{name} says 'How could I have missed this?'"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
Player.players << Prudent.new
|
67
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#A small utility module
|
4
|
+
module Utl
|
5
|
+
#An array with some letters in it and a place holder at zero.
|
6
|
+
Letters = %w(x A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
|
7
|
+
|
8
|
+
#Convert a channel name to its number.
|
9
|
+
#<br>Parameters
|
10
|
+
#* letter - the letter that was played.
|
11
|
+
#<br>Returns
|
12
|
+
#* The channel number (1..26) or nil if invalid.
|
13
|
+
def self.name_to_channel(letter)
|
14
|
+
Letters.find_index(letter[0].upcase)
|
15
|
+
end
|
16
|
+
|
17
|
+
#Convert a channel number to its name.
|
18
|
+
#<br>Parameters
|
19
|
+
#* channel - the channel number (1..26),
|
20
|
+
#<br>Returns
|
21
|
+
#* The channel letter.
|
22
|
+
def self.channel_to_name(channel)
|
23
|
+
Letters[channel]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/tests/test_game.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative '../lib/connect_n_game'
|
4
|
+
gem 'minitest'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
#Test the standard fOOrth library.
|
8
|
+
class GameTester < Minitest::Test
|
9
|
+
|
10
|
+
#Test that this test was run!
|
11
|
+
def test_dummy
|
12
|
+
assert_equal(ConnectNGame::VERSION.class, String)
|
13
|
+
end
|
14
|
+
|
15
|
+
#Test that it knows how to play.
|
16
|
+
def test_taking_turns
|
17
|
+
pl1 = ConnectNGame::Player.new("A", "OK", :silicon)
|
18
|
+
pl2 = ConnectNGame::Player.new("B", "GOOD", :carbon)
|
19
|
+
|
20
|
+
game = ConnectNGame::Game.new(pl1, pl2).game_initialize
|
21
|
+
|
22
|
+
assert_equal(4, game.rack.order)
|
23
|
+
assert_equal(pl1, game.current_player)
|
24
|
+
assert_equal(:continue, game.next_move)
|
25
|
+
assert_equal(1, game.turn)
|
26
|
+
|
27
|
+
assert_equal(pl2, game.current_player)
|
28
|
+
assert_equal(:continue, game.next_move)
|
29
|
+
assert_equal(2, game.turn)
|
30
|
+
|
31
|
+
assert_equal(pl1, game.current_player)
|
32
|
+
assert_equal(:continue, game.next_move)
|
33
|
+
assert_equal(3, game.turn)
|
34
|
+
|
35
|
+
assert_equal(pl2, game.current_player)
|
36
|
+
assert_equal(:continue, game.next_move)
|
37
|
+
assert_equal(4, game.turn)
|
38
|
+
|
39
|
+
assert_equal(pl1, game.current_player)
|
40
|
+
assert_equal(:continue, game.next_move)
|
41
|
+
assert_equal(5, game.turn)
|
42
|
+
|
43
|
+
assert_equal(pl2, game.current_player)
|
44
|
+
assert_equal(:continue, game.next_move)
|
45
|
+
assert_equal(6, game.turn)
|
46
|
+
|
47
|
+
assert_equal(pl1, game.current_player)
|
48
|
+
assert_equal(:victory, game.next_move)
|
49
|
+
assert_equal(7, game.turn)
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative '../lib/connect_n_game'
|
4
|
+
gem 'minitest'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
#Test the standard fOOrth library.
|
8
|
+
class ConnectNGameTester < Minitest::Test
|
9
|
+
|
10
|
+
#Test that all the pieces are in the box!
|
11
|
+
def test_modules_and_classes_exist
|
12
|
+
assert_equal(ConnectNGame.class, Module)
|
13
|
+
assert_equal(ConnectNGame::VERSION.class, String)
|
14
|
+
assert_equal(ConnectNGame::Game.class, Class)
|
15
|
+
assert_equal(ConnectNGame::Player.class, Class)
|
16
|
+
assert_equal(ConnectNGame::UI.class, Class)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative '../lib/connect_n_game'
|
4
|
+
gem 'minitest'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
#Test the standard fOOrth library.
|
8
|
+
class PlayerTester < Minitest::Test
|
9
|
+
|
10
|
+
#Test that this test was run!
|
11
|
+
def test_dummy
|
12
|
+
assert_equal(String, ConnectNGame::VERSION.class)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_abstract_behaviours
|
16
|
+
#It should have the attributes of name, description, and type.
|
17
|
+
atp = ConnectNGame::Player.new("Ted", "Cool", :carbon)
|
18
|
+
assert_equal("Ted", atp.name)
|
19
|
+
assert_equal("Cool", atp.description)
|
20
|
+
assert_equal(:carbon, atp.type)
|
21
|
+
assert(atp.carbon?)
|
22
|
+
refute(atp.silicon?)
|
23
|
+
|
24
|
+
#It should reject invalid player types.
|
25
|
+
assert_raises { ConnectNGame::Player.new("Ted", "Cool", :germanium) }
|
26
|
+
end
|
27
|
+
|
28
|
+
#We should be able to sort players alphabetically by name.
|
29
|
+
def test_that_it_is_sortable
|
30
|
+
aop = []
|
31
|
+
aop << ConnectNGame::Player.new("Ted", "Cool", :carbon)
|
32
|
+
aop << ConnectNGame::Player.new("apple", "Cooler", :silicon)
|
33
|
+
aop << ConnectNGame::Player.new("Ed", "Coolest", :carbon)
|
34
|
+
|
35
|
+
aop.sort! {|a,b| a.name.casecmp(b.name) }
|
36
|
+
|
37
|
+
assert_equal("apple", aop[0].name)
|
38
|
+
assert(aop[0].silicon?)
|
39
|
+
refute(aop[0].carbon?)
|
40
|
+
|
41
|
+
assert_equal("Ed", aop[1].name)
|
42
|
+
refute(aop[1].silicon?)
|
43
|
+
assert(aop[1].carbon?)
|
44
|
+
|
45
|
+
assert_equal("Ted", aop[2].name)
|
46
|
+
refute(aop[2].silicon?)
|
47
|
+
assert(aop[2].carbon?)
|
48
|
+
end
|
49
|
+
|
50
|
+
#Test that it loads up available players.
|
51
|
+
def test_player_loading
|
52
|
+
assert_equal(Array, ConnectNGame::Player.players.class)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/tests/test_rack.rb
ADDED
@@ -0,0 +1,222 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative '../lib/connect_n_game'
|
4
|
+
gem 'minitest'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
#Test the standard fOOrth library.
|
8
|
+
class RackTester < Minitest::Test
|
9
|
+
|
10
|
+
#Test that this test was run!
|
11
|
+
def test_dummy
|
12
|
+
assert_equal(ConnectNGame::VERSION.class, String)
|
13
|
+
end
|
14
|
+
|
15
|
+
#Test that we can create racks.
|
16
|
+
def test_creating_racks
|
17
|
+
assert_raises { ConnectNGame::Rack.new(3) }
|
18
|
+
|
19
|
+
tr = ConnectNGame::Rack.new(4)
|
20
|
+
assert_equal(4, tr.order)
|
21
|
+
assert_equal(6, tr.depth)
|
22
|
+
assert_equal(7, tr.width)
|
23
|
+
assert_equal([[],[],[],[],[],[],[]], tr.rack)
|
24
|
+
assert_equal(%w(A B C D E F G), tr.channel_names)
|
25
|
+
assert_equal([0.0078125, 0.03125, 0.125, 0.5, 0.25, 0.0625,
|
26
|
+
0.015625], tr.weights)
|
27
|
+
|
28
|
+
tr = ConnectNGame::Rack.new(5)
|
29
|
+
assert_equal(5, tr.order)
|
30
|
+
assert_equal(7, tr.depth)
|
31
|
+
assert_equal(9, tr.width)
|
32
|
+
assert_equal([[],[],[],[],[],[],[],[],[]], tr.rack)
|
33
|
+
assert_equal(%w(A B C D E F G H I), tr.channel_names)
|
34
|
+
assert_equal([0.001953125, 0.0078125, 0.03125, 0.125, 0.5,
|
35
|
+
0.25, 0.0625, 0.015625, 0.00390625], tr.weights)
|
36
|
+
|
37
|
+
tr = ConnectNGame::Rack.new(6)
|
38
|
+
assert_equal(6, tr.order)
|
39
|
+
assert_equal(9, tr.depth)
|
40
|
+
assert_equal(11, tr.width)
|
41
|
+
assert_equal([[],[],[],[],[],[],[],[],[],[],[]], tr.rack)
|
42
|
+
assert_equal(%w(A B C D E F G H I J K), tr.channel_names)
|
43
|
+
assert_equal([0.00048828125, 0.001953125, 0.0078125, 0.03125,
|
44
|
+
0.125, 0.5, 0.25, 0.0625, 0.015625, 0.00390625,
|
45
|
+
0.0009765625], tr.weights)
|
46
|
+
|
47
|
+
tr = ConnectNGame::Rack.new(7)
|
48
|
+
assert_equal(7, tr.order)
|
49
|
+
assert_equal(10, tr.depth)
|
50
|
+
assert_equal(11, tr.width)
|
51
|
+
assert_equal([[],[],[],[],[],[],[],[],[],[],[]], tr.rack)
|
52
|
+
assert_equal(%w(A B C D E F G H I J K), tr.channel_names)
|
53
|
+
assert_equal([0.00048828125, 0.001953125, 0.0078125, 0.03125,
|
54
|
+
0.125, 0.5, 0.25, 0.0625, 0.015625, 0.00390625,
|
55
|
+
0.0009765625], tr.weights)
|
56
|
+
|
57
|
+
tr = ConnectNGame::Rack.new(8)
|
58
|
+
assert_equal(8, tr.order)
|
59
|
+
assert_equal(12, tr.depth)
|
60
|
+
assert_equal(13, tr.width)
|
61
|
+
assert_equal([[],[],[],[],[],[],[],[],[],[],[],[],[]], tr.rack)
|
62
|
+
assert_equal(%w(A B C D E F G H I J K L M), tr.channel_names)
|
63
|
+
assert_equal([0.0001220703125, 0.00048828125, 0.001953125,
|
64
|
+
0.0078125, 0.03125, 0.125, 0.5, 0.25, 0.0625,
|
65
|
+
0.015625, 0.00390625, 0.0009765625,
|
66
|
+
0.000244140625], tr.weights)
|
67
|
+
|
68
|
+
assert_raises { ConnectNGame::Rack.new(9) }
|
69
|
+
end
|
70
|
+
|
71
|
+
#Test that it can retrieve channels
|
72
|
+
def test_get_channel
|
73
|
+
(4..8).each do |order|
|
74
|
+
tr = ConnectNGame::Rack.new(order)
|
75
|
+
|
76
|
+
(1..(tr.width)).each do |ch|
|
77
|
+
assert_equal([], tr.get_channel(ch))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
#Test that it knows when a channel is full
|
83
|
+
def test_channel_and_rack_full
|
84
|
+
(4..8).each do |order|
|
85
|
+
tr = ConnectNGame::Rack.new(order)
|
86
|
+
|
87
|
+
#The channels are being filled.
|
88
|
+
(1..tr.depth).each do | _depth |
|
89
|
+
|
90
|
+
refute(tr.rack_full?)
|
91
|
+
|
92
|
+
(1..tr.width).each do | channel |
|
93
|
+
|
94
|
+
refute(tr.channel_full?(channel))
|
95
|
+
|
96
|
+
tr.get_channel(channel) << 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
#Now all the channels should be full.
|
101
|
+
(1..tr.width).each do | channel |
|
102
|
+
assert(tr.channel_full?(channel))
|
103
|
+
end
|
104
|
+
|
105
|
+
assert(tr.rack_full?)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
#Test that we can query individual cells
|
110
|
+
def test_get_cell
|
111
|
+
tr = ConnectNGame::Rack.new(4)
|
112
|
+
assert_equal(nil, tr.get_cell(1,1))
|
113
|
+
assert_equal(nil, tr.get_cell(1,2))
|
114
|
+
assert_equal(nil, tr.get_cell(1,3))
|
115
|
+
|
116
|
+
tr.get_channel(1) << 1
|
117
|
+
assert_equal(1, tr.get_cell(1,1))
|
118
|
+
assert_equal(nil, tr.get_cell(1,2))
|
119
|
+
assert_equal(nil, tr.get_cell(1,3))
|
120
|
+
|
121
|
+
tr.get_channel(1) << 2
|
122
|
+
assert_equal(1, tr.get_cell(1,1))
|
123
|
+
assert_equal(2, tr.get_cell(1,2))
|
124
|
+
assert_equal(nil, tr.get_cell(1,3))
|
125
|
+
|
126
|
+
tr.get_channel(1) << 1
|
127
|
+
assert_equal(1, tr.get_cell(1,1))
|
128
|
+
assert_equal(2, tr.get_cell(1,2))
|
129
|
+
assert_equal(1, tr.get_cell(1,3))
|
130
|
+
end
|
131
|
+
|
132
|
+
#Test that we can play a channel.
|
133
|
+
def test_play_channel
|
134
|
+
tr = ConnectNGame::Rack.new(4)
|
135
|
+
|
136
|
+
assert_equal(1, tr.play_channel(1, 1))
|
137
|
+
assert_equal(2, tr.play_channel(1, 1))
|
138
|
+
assert_equal(3, tr.play_channel(1, 1))
|
139
|
+
assert_equal(4, tr.play_channel(1, 1))
|
140
|
+
assert_equal(5, tr.play_channel(1, 1))
|
141
|
+
assert_equal(6, tr.play_channel(1, 1))
|
142
|
+
|
143
|
+
#Playing a full channel has no effect or score.
|
144
|
+
assert_equal(6, tr.get_channel(1).length)
|
145
|
+
assert_equal(-9, tr.play_channel(1, 1))
|
146
|
+
assert_equal(6, tr.get_channel(1).length)
|
147
|
+
end
|
148
|
+
|
149
|
+
#Test getting the free row for a channel
|
150
|
+
def test_channel_to_row
|
151
|
+
tr = ConnectNGame::Rack.new(4)
|
152
|
+
|
153
|
+
assert_equal(1, tr.channel_to_row(1))
|
154
|
+
|
155
|
+
tr.play_channel(1,1)
|
156
|
+
assert_equal(2, tr.channel_to_row(1))
|
157
|
+
|
158
|
+
tr.play_channel(1,1)
|
159
|
+
assert_equal(3, tr.channel_to_row(1))
|
160
|
+
|
161
|
+
tr.play_channel(1,1)
|
162
|
+
assert_equal(4, tr.channel_to_row(1))
|
163
|
+
|
164
|
+
tr.play_channel(1,1)
|
165
|
+
assert_equal(5, tr.channel_to_row(1))
|
166
|
+
|
167
|
+
tr.play_channel(1,1)
|
168
|
+
assert_equal(6, tr.channel_to_row(1))
|
169
|
+
|
170
|
+
tr.play_channel(1,1)
|
171
|
+
assert_equal(nil, tr.channel_to_row(1))
|
172
|
+
end
|
173
|
+
|
174
|
+
#Test that we can count cells around a position.
|
175
|
+
def test_score_move
|
176
|
+
tr = ConnectNGame::Rack.new(4)
|
177
|
+
#.......
|
178
|
+
#.......
|
179
|
+
#.......
|
180
|
+
#.......
|
181
|
+
|
182
|
+
assert_equal(1, tr.play_channel(3,1))
|
183
|
+
#.......
|
184
|
+
#.......
|
185
|
+
#.......
|
186
|
+
#..X....
|
187
|
+
|
188
|
+
assert_equal(2, tr.play_channel(4,1))
|
189
|
+
#.......
|
190
|
+
#.......
|
191
|
+
#.......
|
192
|
+
#..XX...
|
193
|
+
|
194
|
+
assert_equal(2, tr.play_channel(4,1))
|
195
|
+
#.......
|
196
|
+
#.......
|
197
|
+
#...X...
|
198
|
+
#..XX...
|
199
|
+
|
200
|
+
assert_equal(2, tr.play_channel(3,1))
|
201
|
+
#.......
|
202
|
+
#.......
|
203
|
+
#..XX...
|
204
|
+
#..XX...
|
205
|
+
|
206
|
+
assert_equal(3, tr.play_channel(3,1))
|
207
|
+
#.......
|
208
|
+
#..X....
|
209
|
+
#..XX...
|
210
|
+
#..XX...
|
211
|
+
|
212
|
+
assert_equal(4, tr.play_channel(3,1))
|
213
|
+
#..X....
|
214
|
+
#..X....
|
215
|
+
#..XX...
|
216
|
+
#..XX...
|
217
|
+
|
218
|
+
#It should not hang either!
|
219
|
+
assert_raises { tr.score_move(3, nil) }
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|