rb_battleship 1.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 +3 -0
- data/Gemfile +3 -0
- data/README.md +62 -0
- data/Rakefile +10 -0
- data/battleship.gemspec +22 -0
- data/bin/battleship +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/battleship.rb +7 -0
- data/lib/battleship/coord.rb +38 -0
- data/lib/battleship/gameplay.rb +81 -0
- data/lib/battleship/grid.rb +82 -0
- data/lib/battleship/player.rb +80 -0
- data/lib/battleship/position.rb +31 -0
- data/lib/battleship/ship.rb +63 -0
- data/lib/battleship/version.rb +3 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 931cc1b1f8aa09c59792fea9b6b1b0f2a5ac44a5
|
4
|
+
data.tar.gz: ef85817e4cfe22c5e8b5c4d6e815c2b94f0c0b4e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bb0a90101f5609c42a4a8395e5525931ac8aaa0c3aa7782541cd8dc3b8b53fdb0b536742dcfb0b6dbf022fcf7d057f594932f354273925201ba8031793666315
|
7
|
+
data.tar.gz: d23cad03fc419bddd789214d16cae28c2beb925c73696ef19a328796201c23692065449c0a2c50b9a5627db9272588e28c8d71d24d6cacc5e357aa3c8d528451
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# :ship: :boom: Battleship :boom: :ship:
|
2
|
+
The objective of this task is to build a battleship game for two players in Ruby in a terminal.
|
3
|
+
|
4
|
+
## Design
|
5
|
+
|
6
|
+
### SRP
|
7
|
+
The code design follows the single responsibility principle by using a dedicated class for any specific task.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
Install the gem from your shell:
|
11
|
+
```shell
|
12
|
+
gem install battleship
|
13
|
+
```
|
14
|
+
|
15
|
+
## Gameplay
|
16
|
+
The gem includes a single binary you can use to start a new game:
|
17
|
+
```shell
|
18
|
+
battleship
|
19
|
+
******* 1° round
|
20
|
+
******* Player 1 turn
|
21
|
+
place small (3x1) ship on grid by specifying coordinates and cardinal point separated by spaces (ie 1 3 SE):
|
22
|
+
>
|
23
|
+
```
|
24
|
+
|
25
|
+
## Tests
|
26
|
+
The gem is covered, where possible, by fast, isolated unit testing:gem is covered, where possible, by fast, isolated unit testing. Execute them all by:
|
27
|
+
```shell
|
28
|
+
bundle exec rake
|
29
|
+
```
|
30
|
+
|
31
|
+
## Kata objectives
|
32
|
+
* :warning: You should not require any gems aside from ones to help you write any tests (rspec, minitest...). :warning:
|
33
|
+
* Your code must be tested as much as possible.
|
34
|
+
* Each step must be 100% done before moving to the next. We won't take into account any part done in advance.
|
35
|
+
* You should explain how to run your game (and the tests) in a README.md file in the root of your project.
|
36
|
+
|
37
|
+
## 1st step - Board setup
|
38
|
+
The game is played on 5x5 grids (one per player). Your first task is to set the game up:
|
39
|
+
* Players have 2 ships each to place on their grid. A small ship (3x1 side) and large one (4x1 size)
|
40
|
+
* Players are asked in turn to place their ships on their board (ie: interactively)
|
41
|
+
* A ship can't be placed out of bounds nor on the same space as another ship.
|
42
|
+
|
43
|
+
## 2nd step - Gameplay setup
|
44
|
+
Once all the ships are placed the game begins! Now you have to set the gameplay mechanisms up:
|
45
|
+
* Players take turns to shoot at the opponent grid one after the other by selecting coordinates.
|
46
|
+
* Each shot receives a Hit, Miss or Sink response.
|
47
|
+
* The winner is the player who sinks all of their opponent ships first
|
48
|
+
|
49
|
+
## 3rd step - Gameplay improvements
|
50
|
+
At this point the game works and we'd like some improvements of some of its mechanisms:
|
51
|
+
* Starting player is determined at random.
|
52
|
+
* If a shot attempt is made out of bounds the game offers a retry.
|
53
|
+
* When the game is finished it gives the option to play again.
|
54
|
+
|
55
|
+
## 4th step - Bonus
|
56
|
+
This part is here to spice things up! :boom: We'd like to have these features added to the game:
|
57
|
+
* Ships can now be placed diagonally.
|
58
|
+
* If a player misses a shot 3 times in a row the game gives a hint of a valid shot.
|
59
|
+
* The game now works in a "Best of 3" match mode:
|
60
|
+
> If player 1 wins the first game, the match is not over yet because player 2 can still win the 2 other games and win the match.
|
61
|
+
> If player 1 wins first 2 consecutive games, then the other player can possibly win 1 game maximum, which is not sufficient to beat the 2 games won by player 1.
|
62
|
+
> If each player won 1 of the first 2 games then the third game is played. Whoever wins the third game is declared winner of the match.
|
data/Rakefile
ADDED
data/battleship.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "battleship/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "rb_battleship"
|
8
|
+
s.version = Battleship::VERSION
|
9
|
+
s.authors = ["costajob"]
|
10
|
+
s.email = ["costajob@gmail.com"]
|
11
|
+
s.license = "MIT"
|
12
|
+
s.summary = "Implementation of the Battleship code kata"
|
13
|
+
s.homepage = "https://github.com/costajob/battleship.git"
|
14
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
15
|
+
s.bindir = "bin"
|
16
|
+
s.executables << "battleship"
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.required_ruby_version = ">= 2.3.1"
|
19
|
+
s.add_development_dependency "bundler", "~> 1.16"
|
20
|
+
s.add_development_dependency "rake", "~> 12.3"
|
21
|
+
s.add_development_dependency "minitest", "~> 5.1"
|
22
|
+
end
|
data/bin/battleship
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "battleship"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/battleship.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Battleship
|
2
|
+
class Coord
|
3
|
+
class FactoryError < StandardError; end
|
4
|
+
|
5
|
+
attr_reader :x, :y
|
6
|
+
|
7
|
+
def self.orig
|
8
|
+
@orig ||= new(0, 0)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.factory(data)
|
12
|
+
new(*data.split(" "))
|
13
|
+
rescue ArgumentError
|
14
|
+
fail FactoryError.new("coordinate must be specified as 'x y' (ie 1 2)")
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(x, y)
|
18
|
+
@x = x.to_i.abs
|
19
|
+
@y = y.to_i.abs
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"#{x} #{y}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def >=(other)
|
27
|
+
x >= other.x && y >= other.y
|
28
|
+
end
|
29
|
+
|
30
|
+
def <=(other)
|
31
|
+
x <= other.x && y <= other.y
|
32
|
+
end
|
33
|
+
|
34
|
+
def ==(other)
|
35
|
+
x == other.x && y == other.y
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "battleship/player"
|
2
|
+
|
3
|
+
module Battleship
|
4
|
+
class GamePlay
|
5
|
+
STARS = "*" * 7
|
6
|
+
START_MSG = -> (nbr) { "#{STARS} #{nbr}° round" }
|
7
|
+
TURN_MSG = -> (name) { "#{STARS} #{name} turn" }
|
8
|
+
ROUND_MSG = -> (name) { "#{STARS} #{name} wins the round" }
|
9
|
+
GAMEOVER_MSG = -> (name) { "#{STARS} #{name} wins the game" }
|
10
|
+
ANSWERS = %w[Y N y n]
|
11
|
+
MATCHES = 3
|
12
|
+
|
13
|
+
def self.call
|
14
|
+
new.call
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :matches, :output
|
18
|
+
|
19
|
+
def initialize(player_class=Player, output=STDOUT)
|
20
|
+
@player_class = player_class
|
21
|
+
@players = nil
|
22
|
+
@winner = nil
|
23
|
+
@matches = []
|
24
|
+
@output = output
|
25
|
+
end
|
26
|
+
|
27
|
+
def players
|
28
|
+
return @players if @players
|
29
|
+
p1, p2 = [1, 2].map { |i| @player_class.factory(name: "Player #{i}", output: @output) }
|
30
|
+
p1.enemy = p2
|
31
|
+
p2.enemy = p1
|
32
|
+
@players = [p1, p2]
|
33
|
+
end
|
34
|
+
|
35
|
+
def call
|
36
|
+
output.puts(GAMEOVER_MSG.call(play))
|
37
|
+
end
|
38
|
+
|
39
|
+
private def play
|
40
|
+
loop do
|
41
|
+
output.puts(START_MSG.call(matches.size+1))
|
42
|
+
setup
|
43
|
+
round
|
44
|
+
return winner.name if winner
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private def winner
|
49
|
+
@winner ||= players.detect do |player|
|
50
|
+
matches.count(player.name) > 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private def setup
|
55
|
+
players.shuffle.each do |player|
|
56
|
+
output.puts(TURN_MSG.call(player.name))
|
57
|
+
player.setup
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private def fight
|
62
|
+
loop do
|
63
|
+
players.each do |player|
|
64
|
+
output.puts(TURN_MSG.call(player.name))
|
65
|
+
player.shot
|
66
|
+
return player.name if player.enemy.gameover?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private def round
|
72
|
+
matches << fight
|
73
|
+
output.puts(ROUND_MSG.call(matches[-1]))
|
74
|
+
reset!
|
75
|
+
end
|
76
|
+
|
77
|
+
private def reset!
|
78
|
+
@players = nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "battleship/coord"
|
3
|
+
|
4
|
+
module Battleship
|
5
|
+
class Grid
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
SIZE = 4
|
9
|
+
PLACE_ERR = "ship placed ouside of grid and/or overlapping an exisitng one"
|
10
|
+
COORD_ERR = -> (grid) { "coordinate is ouside of grid (#{grid.bot_left}) - (#{grid.top_right})" }
|
11
|
+
HIT = "Hit"
|
12
|
+
MISS = "Miss"
|
13
|
+
SINK = "Sink"
|
14
|
+
|
15
|
+
class PlacingError < StandardError; end
|
16
|
+
|
17
|
+
def self.factory(coord_class=Coord)
|
18
|
+
new(coord_class.orig, coord_class.new(SIZE, SIZE))
|
19
|
+
end
|
20
|
+
|
21
|
+
def_delegators :@ships, :include?, :empty?, :size
|
22
|
+
|
23
|
+
attr_reader :bot_left, :top_right, :ships
|
24
|
+
|
25
|
+
def initialize(bot_left, top_right)
|
26
|
+
@bot_left = bot_left
|
27
|
+
@top_right = top_right
|
28
|
+
@ships = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"bot_left=#{bot_left} top_right=#{top_right} ships=#{ships.size}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def <<(ship)
|
36
|
+
fail PlacingError.new(PLACE_ERR) unless valid?(ship)
|
37
|
+
ships << ship
|
38
|
+
end
|
39
|
+
|
40
|
+
def shot(coord)
|
41
|
+
fail PlacingError.new(COORD_ERR.call(self)) unless included?(coord)
|
42
|
+
data = damages(coord)
|
43
|
+
purge!
|
44
|
+
return SINK if data.any? { |d| d < 0 }
|
45
|
+
return HIT if data.any? { |d| d > 0 }
|
46
|
+
MISS
|
47
|
+
end
|
48
|
+
|
49
|
+
def footprint
|
50
|
+
ships.map(&:footprint).flatten
|
51
|
+
end
|
52
|
+
|
53
|
+
private def damages(coord)
|
54
|
+
ships.reduce([]) do |acc, ship|
|
55
|
+
damage = ship.strike(coord)
|
56
|
+
acc << damage
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private def purge!
|
61
|
+
ships.reject!(&:empty?)
|
62
|
+
end
|
63
|
+
|
64
|
+
private def valid?(ship)
|
65
|
+
within?(ship) && !overlap?(ship)
|
66
|
+
end
|
67
|
+
|
68
|
+
private def within?(ship)
|
69
|
+
ship.footprint.all? { |coord| included?(coord) }
|
70
|
+
end
|
71
|
+
|
72
|
+
private def included?(coord)
|
73
|
+
coord >= bot_left && coord <= top_right
|
74
|
+
end
|
75
|
+
|
76
|
+
private def overlap?(ship)
|
77
|
+
footprint.any? do |coord|
|
78
|
+
ship.footprint.any? { |c| c == coord }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "battleship/grid"
|
3
|
+
require "battleship/position"
|
4
|
+
require "battleship/ship"
|
5
|
+
|
6
|
+
module Battleship
|
7
|
+
class Player
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
PLACE_MSG = -> (ship) { "place #{ship.name} ship on grid by specifying coordinates and cardinal point separated by spaces (ie 1 3 SE):" }
|
11
|
+
SHOT_MSG = "enter coordinates for shooting your enemy grid (ie 2 3):"
|
12
|
+
TIP_MSG = -> (shot, coord) { "#{shot}, you should try with the (#{coord}) coordinates next time" }
|
13
|
+
TIP_THRESHOLD = 3
|
14
|
+
|
15
|
+
class MissesError < StandardError; end
|
16
|
+
|
17
|
+
def_delegator :@grid, :empty?, :gameover?
|
18
|
+
|
19
|
+
def self.factory(name:, grid_class: Grid, output: STDOUT)
|
20
|
+
new(name: name, grid: grid_class.factory, output: output)
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :name, :grid, :ships
|
24
|
+
attr_accessor :enemy
|
25
|
+
|
26
|
+
def initialize(name:, grid:, output: STDOUT)
|
27
|
+
@name = name
|
28
|
+
@grid = grid
|
29
|
+
@misses = 0
|
30
|
+
@output = output
|
31
|
+
@pos = nil
|
32
|
+
@coord = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def setup(ships=[Ship.small, Ship.large])
|
36
|
+
Array(ships).each { |ship| place(ship) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def shot(coord_class=Coord)
|
40
|
+
@output.puts(SHOT_MSG)
|
41
|
+
@coord ||= STDIN.gets
|
42
|
+
shot = enemy.grid.shot(coord_class.factory(@coord.chomp))
|
43
|
+
@output.puts(report(shot))
|
44
|
+
@coord = nil
|
45
|
+
rescue grid.class::PlacingError, coord_class::FactoryError => e
|
46
|
+
@output.puts(e.message)
|
47
|
+
@coord = nil
|
48
|
+
retry
|
49
|
+
end
|
50
|
+
|
51
|
+
private def report(shot)
|
52
|
+
return shot unless tip?(shot)
|
53
|
+
coord = enemy.grid.footprint.sample
|
54
|
+
TIP_MSG.call(shot, coord)
|
55
|
+
end
|
56
|
+
|
57
|
+
private def tip?(shot)
|
58
|
+
return reset! unless shot == grid.class::MISS
|
59
|
+
@misses += 1
|
60
|
+
@misses >= TIP_THRESHOLD
|
61
|
+
end
|
62
|
+
|
63
|
+
private def reset!
|
64
|
+
@misses = 0
|
65
|
+
false
|
66
|
+
end
|
67
|
+
|
68
|
+
private def place(ship, pos_class=Position)
|
69
|
+
@output.puts(PLACE_MSG.call(ship))
|
70
|
+
@pos ||= STDIN.gets
|
71
|
+
ship.place(pos_class.factory(@pos.chomp))
|
72
|
+
grid << ship
|
73
|
+
@pos = nil
|
74
|
+
rescue grid.class::PlacingError, pos_class::FactoryError => e
|
75
|
+
@output.puts(e.message)
|
76
|
+
@pos = nil
|
77
|
+
retry
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "battleship/coord"
|
2
|
+
|
3
|
+
module Battleship
|
4
|
+
class Position
|
5
|
+
class CardinalError < StandardError; end
|
6
|
+
class FactoryError < StandardError; end
|
7
|
+
|
8
|
+
def self.factory(data)
|
9
|
+
new(*data.split(" "))
|
10
|
+
rescue ArgumentError
|
11
|
+
fail FactoryError.new("position must be specified as 'x y cardinal' (ie 1 2 N)")
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :coord
|
15
|
+
attr_accessor :cardinal
|
16
|
+
|
17
|
+
def initialize(x, y, cardinal, coord_class=Coord)
|
18
|
+
@coord = coord_class.new(x, y)
|
19
|
+
@cardinal = check(cardinal)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"#{coord} #{cardinal}"
|
24
|
+
end
|
25
|
+
|
26
|
+
private def check(cardinal)
|
27
|
+
return cardinal if CARDINALS.include?(cardinal)
|
28
|
+
fail CardinalError.new("#{cardinal} is not a valid cardinal point")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module Battleship
|
4
|
+
class Ship
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
SMALL_LEN = 3
|
8
|
+
LARGE_LEN = 4
|
9
|
+
WIDTH = 1
|
10
|
+
|
11
|
+
def_delegators :@footprint, :empty?
|
12
|
+
|
13
|
+
def self.small
|
14
|
+
new(SMALL_LEN, WIDTH, "small (#{SMALL_LEN}x#{WIDTH})")
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.large
|
18
|
+
new(LARGE_LEN, WIDTH, "large (#{LARGE_LEN}x#{WIDTH})")
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :name, :len, :wid, :footprint
|
22
|
+
|
23
|
+
def initialize(len, wid, name=nil)
|
24
|
+
@len = len.to_i
|
25
|
+
@wid = wid.to_i
|
26
|
+
@name = name.to_s
|
27
|
+
@footprint = []
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"len=#{len} wid=#{wid} footprint=(#{footprint.map(&:to_s).join(', ')})"
|
32
|
+
end
|
33
|
+
|
34
|
+
def place(position)
|
35
|
+
coord = position.coord
|
36
|
+
@footprint = case position.cardinal
|
37
|
+
when 'N'
|
38
|
+
len.times.map { |i| coord.class.new(coord.x, coord.y + i) }
|
39
|
+
when 'E'
|
40
|
+
len.times.map { |i| coord.class.new(coord.x + i, coord.y) }
|
41
|
+
when 'S'
|
42
|
+
len.times.map { |i| coord.class.new(coord.x, coord.y - i) }
|
43
|
+
when 'W'
|
44
|
+
len.times.map { |i| coord.class.new(coord.x - i, coord.y) }
|
45
|
+
when 'NE'
|
46
|
+
len.times.map { |i| coord.class.new(coord.x + i, coord.y + i) }
|
47
|
+
when 'NW'
|
48
|
+
len.times.map { |i| coord.class.new(coord.x - i, coord.y + i) }
|
49
|
+
when 'SE'
|
50
|
+
len.times.map { |i| coord.class.new(coord.x + i, coord.y - i) }
|
51
|
+
when 'SW'
|
52
|
+
len.times.map { |i| coord.class.new(coord.x - i, coord.y - i) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def strike(coord)
|
57
|
+
hit = @footprint.delete(coord)
|
58
|
+
return -1 if empty?
|
59
|
+
return 1 if hit
|
60
|
+
0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rb_battleship
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- costajob
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.1'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- costajob@gmail.com
|
58
|
+
executables:
|
59
|
+
- battleship
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- Gemfile
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- battleship.gemspec
|
68
|
+
- bin/battleship
|
69
|
+
- bin/console
|
70
|
+
- bin/setup
|
71
|
+
- lib/battleship.rb
|
72
|
+
- lib/battleship/coord.rb
|
73
|
+
- lib/battleship/gameplay.rb
|
74
|
+
- lib/battleship/grid.rb
|
75
|
+
- lib/battleship/player.rb
|
76
|
+
- lib/battleship/position.rb
|
77
|
+
- lib/battleship/ship.rb
|
78
|
+
- lib/battleship/version.rb
|
79
|
+
homepage: https://github.com/costajob/battleship.git
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 2.3.1
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.5.1
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Implementation of the Battleship code kata
|
103
|
+
test_files: []
|