ttt 1.0.0
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.
- data/Gemfile +6 -0
- data/Gemfile.lock +51 -0
- data/MIT-License.md +8 -0
- data/Rakefile +324 -0
- data/Readme.md +35 -0
- data/bin/ttt +6 -0
- data/features/binary.feature +39 -0
- data/features/computer_player.feature +62 -0
- data/features/create_game.feature +63 -0
- data/features/finish_game.feature +53 -0
- data/features/finished_states.feature +56 -0
- data/features/mark_board.feature +24 -0
- data/features/step_definitions/binary_steps.rb +42 -0
- data/features/step_definitions/ttt_steps.rb +82 -0
- data/features/support/env.rb +8 -0
- data/features/view_board_as_developer.feature +13 -0
- data/features/view_board_as_tester.feature +9 -0
- data/lib/ttt.rb +1 -0
- data/lib/ttt/binary.rb +96 -0
- data/lib/ttt/computer_player.rb +74 -0
- data/lib/ttt/game.rb +129 -0
- data/lib/ttt/interface.rb +22 -0
- data/lib/ttt/interface/cli.rb +95 -0
- data/lib/ttt/interface/cli/players.rb +56 -0
- data/lib/ttt/interface/cli/views.rb +124 -0
- data/lib/ttt/interface/limelight.rb +18 -0
- data/lib/ttt/interface/limelight/players/restart_as_first.rb +5 -0
- data/lib/ttt/interface/limelight/players/restart_as_second.rb +6 -0
- data/lib/ttt/interface/limelight/players/square.rb +105 -0
- data/lib/ttt/interface/limelight/props.rb +10 -0
- data/lib/ttt/interface/limelight/styles.rb +101 -0
- data/lib/ttt/ratings.rb +849 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/ttt/computer_player_spec.rb +86 -0
- data/spec/ttt/game_spec.rb +294 -0
- data/spec/ttt/rating_spec.rb +75 -0
- metadata +139 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
Feature: Computer player
|
2
|
+
|
3
|
+
In order to hone my tic-tac-toe skills
|
4
|
+
As a player
|
5
|
+
I want an unbeatable computer opponent
|
6
|
+
|
7
|
+
The following scenarios should cover a sampling of possible boards. As there are
|
8
|
+
765 possible game possible congruence classes of boards, I won't attempt to cover
|
9
|
+
them all, but will verify that the computer plays optimally in a number of common
|
10
|
+
situations (two game boards are in a congruence class, such as the two below,
|
11
|
+
if one can be turned into the other by rotating or mirroring).
|
12
|
+
|
13
|
+
For a list of all congruent states, there are some rake tasks which compute them
|
14
|
+
and explore some of their properties.
|
15
|
+
|
16
|
+
Example of congruent boards (rotate the left board 90 degrees to get the right board):
|
17
|
+
|
18
|
+
1 | | | | 1
|
19
|
+
---|---|--- ---|---|---
|
20
|
+
| | | |
|
21
|
+
---|---|--- ---|---|---
|
22
|
+
| | | |
|
23
|
+
|
24
|
+
|
25
|
+
Scenario Outline: Computer's moves
|
26
|
+
When I create a game with "<configuration>"
|
27
|
+
And a computer player as player <player>
|
28
|
+
Then it is player<player>s turn
|
29
|
+
And the computer moves to one of the following: <possible boards>
|
30
|
+
|
31
|
+
Scenarios: Computer always takes a win when it is available
|
32
|
+
| configuration | player | possible boards | description |
|
33
|
+
| 110200200 | 1 | 111200200 | can win across top |
|
34
|
+
| 220000110 | 1 | 220000111 | can win across bottom and opponent can win across top |
|
35
|
+
| 201201000 | 1 | 201201001 | can win vertically on RHS opponent can win too |
|
36
|
+
| 120120000 | 1 | 120120100 | can win vertically on RHS opponent can win too |
|
37
|
+
| 102210000 | 1 | 102210001 | can win diagonally |
|
38
|
+
| 120112020 | 1 | 120112120 120112021 | can win in two positions |
|
39
|
+
| 120021001 | 2 | 120021021 | takes win when 2nd player and 1st can also win |
|
40
|
+
|
41
|
+
Scenarios: Computer blocks opponent's win
|
42
|
+
| configuration | player | possible boards | description |
|
43
|
+
| 120100000 | 2 | 120100200 | blocks lhs |
|
44
|
+
| 122110000 | 2 | 122110200 122110002 | blocks either of opponent's possible wins |
|
45
|
+
| 211200000 | 1 | 211200100 | blocks when first player |
|
46
|
+
|
47
|
+
Scenarios: Finds best moves for likely game states
|
48
|
+
| configuration | player | possible boards | description |
|
49
|
+
| 000000000 | 1 | 100000000 001000000 000000100 000000001 | makes best 1st move |
|
50
|
+
| 120000000 | 1 | 120000100 120010000 120100000 | makes move that will guarantee win in future |
|
51
|
+
| 100000002 | 1 | 101000002 100000102 | makes move that will guarantee win in future |
|
52
|
+
| 100000020 | 1 | 100000120 101000020 100010020 | makes move that will guarantee win in future |
|
53
|
+
| 102000000 | 1 | 102100000 102000100 102000001 | makes move that will guarantee win in future |
|
54
|
+
| 102100200 | 1 | 102110200 | makes move that will guarantee win next turn |
|
55
|
+
| 100020000 | 1 | 110020000 100120000 | makes move with highest probability of win in future |
|
56
|
+
| 100000000 | 2 | 100020000 | makes move with lowest probability of losing in future |
|
57
|
+
|
58
|
+
Scenario: Plays correctly for current player
|
59
|
+
Given I create a game with "000000000"
|
60
|
+
And I have a computer player
|
61
|
+
Then the computer will play for 1
|
62
|
+
Then the computer will play for 2
|
@@ -0,0 +1,63 @@
|
|
1
|
+
Feature: Create game
|
2
|
+
|
3
|
+
TTT is the core lib that underlies an interface, where the interface allows users to play the game.
|
4
|
+
|
5
|
+
In order to allow users to play the game
|
6
|
+
An interface must be able to create a game in various states.
|
7
|
+
|
8
|
+
A board can be represented as a string of 9 digits, where a 0 indicates that neither player has moved
|
9
|
+
into that position, a 1 indicates that player1 has moved there, and a 2 indicates that player2 has moved there.
|
10
|
+
The digits correspond to the board in the following manner:
|
11
|
+
|
12
|
+
abcdefghi
|
13
|
+
|
14
|
+
a | b | c
|
15
|
+
---|---|---
|
16
|
+
d | e | f
|
17
|
+
---|---|---
|
18
|
+
g | h | i
|
19
|
+
|
20
|
+
So the game board "001002100" would look like this (let "x" represent player 1 and "o" represent player2):
|
21
|
+
|
22
|
+
| | x
|
23
|
+
---|---|---
|
24
|
+
| | o
|
25
|
+
---|---|---
|
26
|
+
x | |
|
27
|
+
|
28
|
+
|
29
|
+
Scenario: Create a new game
|
30
|
+
When I create a new game
|
31
|
+
Then the game board is "000000000"
|
32
|
+
And it is player1s turn
|
33
|
+
|
34
|
+
Scenario Outline: Create an existing game
|
35
|
+
When I create a game with "<configuration>"
|
36
|
+
Then the game board is "<configuration>"
|
37
|
+
And it is player<player>s turn
|
38
|
+
|
39
|
+
Scenarios: Player1s turn
|
40
|
+
| configuration | player |
|
41
|
+
| 000000000 | 1 |
|
42
|
+
| 120000000 | 1 |
|
43
|
+
| 120120000 | 1 |
|
44
|
+
| 120120210 | 1 |
|
45
|
+
| 000010002 | 1 |
|
46
|
+
| 120221112 | 1 |
|
47
|
+
|
48
|
+
Scenarios: Player2s turn
|
49
|
+
| configuration | player |
|
50
|
+
| 100000000 | 2 |
|
51
|
+
| 012100000 | 2 |
|
52
|
+
| 001112200 | 2 |
|
53
|
+
| 100200100 | 2 |
|
54
|
+
| 120221110 | 2 |
|
55
|
+
|
56
|
+
Scenario: Know who is where
|
57
|
+
Given I create a game with "000120000"
|
58
|
+
When I ask who is at position 4, it returns 1
|
59
|
+
When I ask who is at position 5, it returns 2
|
60
|
+
When I ask who is at position 6, it returns nil
|
61
|
+
|
62
|
+
|
63
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
Feature: Finish game
|
2
|
+
|
3
|
+
In order to allow for actual gameplay
|
4
|
+
As a player
|
5
|
+
I can win, lose, and tie
|
6
|
+
|
7
|
+
Scenario: Player1 wins
|
8
|
+
Given I create a game with "120120000"
|
9
|
+
Then the game is not over
|
10
|
+
When I mark position 7
|
11
|
+
Then the game board is "120120100"
|
12
|
+
And the game is over
|
13
|
+
And player1 wins
|
14
|
+
And player2 loses
|
15
|
+
And it is no one's turn
|
16
|
+
|
17
|
+
Scenario: Player2 wins
|
18
|
+
Given I create a game with "121120000"
|
19
|
+
Then the game is not over
|
20
|
+
When I mark position 8
|
21
|
+
Then the game board is "121120020"
|
22
|
+
And the game is over
|
23
|
+
And player2 wins
|
24
|
+
And player1 loses
|
25
|
+
And it is no one's turn
|
26
|
+
|
27
|
+
Scenario: The players tie
|
28
|
+
Given I create a game with "121221012"
|
29
|
+
Then the game is not over
|
30
|
+
When I mark position 7
|
31
|
+
Then the game board is "121221112"
|
32
|
+
And the game is over
|
33
|
+
And player1 ties
|
34
|
+
And player2 ties
|
35
|
+
And it is no one's turn
|
36
|
+
|
37
|
+
Scenario Outline: I can ask which positions won
|
38
|
+
Given I create a game with "<configuration>"
|
39
|
+
When I ask what positions won
|
40
|
+
Then it tells me [<p1>, <p2>, <p3>]
|
41
|
+
|
42
|
+
Scenarios:
|
43
|
+
| configuration | p1 | p2 | p3 |
|
44
|
+
| 111220000 | 1 | 2 | 3 |
|
45
|
+
| 220111000 | 4 | 5 | 6 |
|
46
|
+
| 220000111 | 7 | 8 | 9 |
|
47
|
+
| 120120100 | 1 | 4 | 7 |
|
48
|
+
| 210210010 | 2 | 5 | 8 |
|
49
|
+
| 201201001 | 3 | 6 | 9 |
|
50
|
+
| 120210001 | 1 | 5 | 9 |
|
51
|
+
| 021210100 | 3 | 5 | 7 |
|
52
|
+
| 021210100 | 3 | 5 | 7 |
|
53
|
+
| 211210200 | 1 | 4 | 7 |
|
@@ -0,0 +1,56 @@
|
|
1
|
+
Feature: Finished states
|
2
|
+
|
3
|
+
In order to finish the game, the library must know what a finished state is.
|
4
|
+
A finished state is a state that either has no available moves left, or where
|
5
|
+
a player has won the game. A player has won the game if they have marked
|
6
|
+
three consecutive spaces in a horizontal, vertical, or diagonal direction.
|
7
|
+
|
8
|
+
Scenario: No winner, no available moves left
|
9
|
+
Given a tie game
|
10
|
+
Then the game is over
|
11
|
+
|
12
|
+
Scenario Outline: Three marks in a row
|
13
|
+
When I create a game with "<configuration>"
|
14
|
+
Then the game is over
|
15
|
+
And player<winner> wins
|
16
|
+
|
17
|
+
Scenarios: Horizontal win
|
18
|
+
| configuration | winner |
|
19
|
+
| 111000000 | 1 |
|
20
|
+
| 000111000 | 1 |
|
21
|
+
| 000000111 | 1 |
|
22
|
+
| 222000000 | 2 |
|
23
|
+
| 000222000 | 2 |
|
24
|
+
| 000000222 | 2 |
|
25
|
+
|
26
|
+
Scenarios: Vertical win
|
27
|
+
| configuration | winner |
|
28
|
+
| 100100100 | 1 |
|
29
|
+
| 010010010 | 1 |
|
30
|
+
| 001001001 | 1 |
|
31
|
+
| 200200200 | 2 |
|
32
|
+
| 020020020 | 2 |
|
33
|
+
| 002002002 | 2 |
|
34
|
+
|
35
|
+
Scenarios: Diagonal win
|
36
|
+
| configuration | winner |
|
37
|
+
| 100010001 | 1 |
|
38
|
+
| 001010100 | 1 |
|
39
|
+
| 200020002 | 2 |
|
40
|
+
| 002020200 | 2 |
|
41
|
+
|
42
|
+
Scenario Outline: Unfinished states
|
43
|
+
When I create a game with "<configuration>"
|
44
|
+
Then the game is not over
|
45
|
+
|
46
|
+
Scenarios: Playing to a tie game
|
47
|
+
| configuration |
|
48
|
+
| 000000000 |
|
49
|
+
| 100000000 |
|
50
|
+
| 100020000 |
|
51
|
+
| 101020000 |
|
52
|
+
| 121020000 |
|
53
|
+
| 121020010 |
|
54
|
+
| 121220010 |
|
55
|
+
| 121221010 |
|
56
|
+
| 121221012 |
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Mark board
|
2
|
+
|
3
|
+
In order to play the game
|
4
|
+
As a player (or, more probably, an interface translating a player's desire)
|
5
|
+
I want to mark the board
|
6
|
+
|
7
|
+
Scenario: Marking an empty board
|
8
|
+
Given I create a new game
|
9
|
+
When I mark position 1
|
10
|
+
Then the game board is "100000000"
|
11
|
+
|
12
|
+
Scenario: Marking a board when it is player1s turn
|
13
|
+
Given I create a game with "120000000"
|
14
|
+
Then it is player1s turn
|
15
|
+
When I mark position 4
|
16
|
+
Then the game board is "120100000"
|
17
|
+
And it is player2s turn
|
18
|
+
|
19
|
+
Scenario: Marking a board when it is player2s turn
|
20
|
+
Given I create a game with "120100000"
|
21
|
+
Then it is player2s turn
|
22
|
+
When I mark position 7
|
23
|
+
Then the game board is "120100200"
|
24
|
+
And it is player1s turn
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Given /^I look at (.*)$/ do |location|
|
2
|
+
@location = location
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I see it is executable$/ do
|
6
|
+
File.executable?(@location).should be
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^I pass the it "([^"]*)" on the command line$/ do |args|
|
10
|
+
pending "Yet again don't know how to test, it hangs b/c it expects input."\
|
11
|
+
"I can put it in a thread and kill it later, but inconsistent results."
|
12
|
+
require 'open3' # from stdlib
|
13
|
+
binary = Class.new Struct.new(:exitstatus, :stdout, :stderr) do
|
14
|
+
def initialize(args)
|
15
|
+
Open3.popen3 "bin/ttt #{args}" do |stdin, stdout, stderr, wait_thr|
|
16
|
+
super(wait_thr.value.exitstatus, stdout.read.strip, stderr.read.strip)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
@binary = binary.new args
|
21
|
+
end
|
22
|
+
|
23
|
+
Then %r{^it should display /([^/]*)/$} do |message|
|
24
|
+
Then "it should print /#{message}/ to stdout"
|
25
|
+
end
|
26
|
+
|
27
|
+
Then %r{^it should print /([^/]*)/ to (\w+)$} do |message, output_name|
|
28
|
+
output = @binary.send output_name
|
29
|
+
output.should match Regexp.new(message)
|
30
|
+
end
|
31
|
+
|
32
|
+
Then /^it should exit with code of (\d+)$/ do |code|
|
33
|
+
@binary.exitstatus.should be code.to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# a simple greeting we'll have the CLI write
|
38
|
+
# just to make sure everything is hooked up correctly
|
39
|
+
Then /^it should welcome me to Tic Tac Toe$/ do
|
40
|
+
Then "it should display /Welcome to Tic Tac Toe/"
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
When /^I create a new game$/ do
|
2
|
+
@game = TTT::Game.new
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^the game board is "([^"]*)"$/ do |board|
|
6
|
+
@game.board.should == board
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^it is (player(\d+)s|no one's) turn$/ do |turn, player_number|
|
10
|
+
if player_number
|
11
|
+
@game.turn.should == player_number.to_i
|
12
|
+
else
|
13
|
+
@game.turn.should be_nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I ask what positions won$/ do
|
18
|
+
@winning_positions = @game.winning_positions
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^it tells me \[(\d+), (\d+), (\d+)\]$/ do |p1, p2, p3|
|
22
|
+
@winning_positions.sort.should == [p1, p2, p3].map(&:to_i).sort
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
When /^I create a game with "([^"]*)"$/ do |configuration|
|
27
|
+
@game = TTT::Game.new configuration
|
28
|
+
end
|
29
|
+
|
30
|
+
When /^I mark position (\d+)$/ do |position|
|
31
|
+
@game.mark position.to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
Then /^board\(:ttt\) will be "([^"]*)"$/ do |board|
|
35
|
+
@game.board(:ttt).should == board.gsub('\\n', "\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
Then /^the game is (not )?over$/ do |not_over|
|
39
|
+
if not_over
|
40
|
+
@game.should_not be_over
|
41
|
+
else
|
42
|
+
@game.should be_over
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
When /^I ask who is at position (\d+), it returns (\w+)$/ do |position, player|
|
47
|
+
player = player.to_i
|
48
|
+
player = nil if player.zero?
|
49
|
+
@game[position.to_i].should == player
|
50
|
+
end
|
51
|
+
|
52
|
+
Then /^player(\d+) (wins|loses|ties)$/ do |player, status|
|
53
|
+
@game.status(player.to_i).should == status.to_sym
|
54
|
+
end
|
55
|
+
|
56
|
+
Given /^a tie game$/ do
|
57
|
+
@game = TTT::Game.new '121221112'
|
58
|
+
end
|
59
|
+
|
60
|
+
When /^a computer player as player (\d+)$/ do |current_turn|
|
61
|
+
@game.turn.should == current_turn.to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
Then /^the computer moves to one of the following: ((?:\d+ ?)+)$/ do |possible_boards|
|
65
|
+
@computer = TTT::ComputerPlayer.new @game
|
66
|
+
@computer.take_turn
|
67
|
+
possible_boards.split.should include @game.board
|
68
|
+
end
|
69
|
+
|
70
|
+
Given /^I have a computer player$/ do
|
71
|
+
@computer = TTT::ComputerPlayer.new @game
|
72
|
+
end
|
73
|
+
|
74
|
+
Then /^the computer will play for (\d+)$/ do |player_number|
|
75
|
+
player_number = player_number.to_i
|
76
|
+
@game.turn.should == player_number
|
77
|
+
@computer.player_number.should == player_number
|
78
|
+
@computer.take_turn
|
79
|
+
@game.turn.should_not == player_number
|
80
|
+
@computer.player_number.should_not == player_number.to_i
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: View board as developer
|
2
|
+
|
3
|
+
In order to be able to do exploratory testing
|
4
|
+
As a developer
|
5
|
+
I want to be able to view the board in standard tic-tac-toe format
|
6
|
+
|
7
|
+
Scenario: View board in tic-tac-toe format
|
8
|
+
Given I create a game with "abcdefghi"
|
9
|
+
Then board(:ttt) will be " a | b | c \n----|---|----\n d | e | f \n----|---|----\n g | h | i "
|
10
|
+
|
11
|
+
Scenario: Viewing a board with spaces no one has moved into
|
12
|
+
Given I create a game with "120000000"
|
13
|
+
Then board(:ttt) will be " 1 | 2 | \n----|---|----\n | | \n----|---|----\n | | "
|
data/lib/ttt.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ttt/game'
|
data/lib/ttt/binary.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
require 'ttt/interface'
|
4
|
+
|
5
|
+
module TTT
|
6
|
+
|
7
|
+
# The code for ttt/bin
|
8
|
+
class Binary
|
9
|
+
|
10
|
+
attr_accessor :filein, :fileout, :fileerr
|
11
|
+
|
12
|
+
def initialize(argv, io={})
|
13
|
+
self.fileout = io.fetch :fileout, $stdout
|
14
|
+
self.fileerr = io.fetch :fileerr, $stderr
|
15
|
+
self.filein = io.fetch :filein, $stdin
|
16
|
+
parse argv
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(argv)
|
20
|
+
argv = ['-h'] if argv.empty?
|
21
|
+
Parser.new(self).parse argv
|
22
|
+
rescue OptionParser::MissingArgument => e
|
23
|
+
fileerr.puts e.message
|
24
|
+
Kernel.exit 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_interface?(interface_name)
|
28
|
+
TTT::Interface.registered? interface_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def list_of_registered
|
32
|
+
TTT::Interface.registered_names.map(&:inspect).join(', ')
|
33
|
+
end
|
34
|
+
|
35
|
+
def interface(interface_name)
|
36
|
+
TTT::Interface.registered[interface_name]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
class Parser
|
42
|
+
|
43
|
+
attr_accessor :binary
|
44
|
+
|
45
|
+
def initialize(binary)
|
46
|
+
self.binary = binary
|
47
|
+
end
|
48
|
+
|
49
|
+
def method_missing(meth, *args, &block)
|
50
|
+
super unless binary.respond_to? meth
|
51
|
+
binary.send meth, *args, &block
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse(argv)
|
55
|
+
options.parse argv
|
56
|
+
end
|
57
|
+
|
58
|
+
def options
|
59
|
+
OptionParser.new do |options|
|
60
|
+
define_banner options
|
61
|
+
define_interface options
|
62
|
+
define_help options
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def options_for_interface
|
67
|
+
return :filein => filein, :fileout => fileout, :fileerr => fileerr
|
68
|
+
end
|
69
|
+
|
70
|
+
def define_banner(options)
|
71
|
+
options.banner = "Usage: ttt --interface interface_name\n" \
|
72
|
+
"ttt is an implementation of Tic Tac Toe by Josh Cheek\n\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
def define_interface(options)
|
76
|
+
options.on '-i', '--interface TYPE', "Specify which interface to play on. Select from: #{list_of_registered}" do |interface_name|
|
77
|
+
if interface_name.equal? true
|
78
|
+
fileerr.puts "Please supply interface type"
|
79
|
+
Kernel.exit 1
|
80
|
+
elsif has_interface? interface_name
|
81
|
+
interface(interface_name).new(options_for_interface).play
|
82
|
+
else
|
83
|
+
fileerr.puts "#{interface_name.inspect} is not a valid interface, select from: #{list_of_registered}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def define_help(options)
|
89
|
+
options.on '-h', '--help', 'Display this screen' do
|
90
|
+
fileout.puts options
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|