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