rb_battleship 1.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 +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: []
|