just_checkers 0.3.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a652941a37584d1c3448d3a904eaf7568a96c7d
4
- data.tar.gz: 25df3f4619cefcffc64c38c6e2ccf0931d5fb4f3
3
+ metadata.gz: fabb7610908ffb7ed90de11e7a43d592b94f3855
4
+ data.tar.gz: fa87a6420ff5b3274df8d33e9de3beb7c47ed41c
5
5
  SHA512:
6
- metadata.gz: 2fc08be188d77cd15ae9e2a990e25e232cebda974ad3a5cd6ec57387878e0ec03c315e26cb18ab46e1b9923140e3ca7822c6aa6f488efb2268ac9f617aabeefd
7
- data.tar.gz: cd2b521698896e634c979d39361c81fc68dfa7f160677587945a4aa834afa2bb0d9ae6937f223d41f8be95d59aeeadb50d01aeafdd43fe5b81f4167e05909fbd
6
+ metadata.gz: 45de02e0328b9ec03bfa44e5235326abfa5bc300e056989ea1c39f1e5f4e909a6dcbf90dc174afc946b6d953055af9303b9e8aa862df82bcf0bb3b8b0d1e3f3a
7
+ data.tar.gz: e4ea11adbd062eafea5e496f639f30b7743726358be839258170b603f4d6207b9b0675cc4c9a903b1b4a0c974fe4f1cf3e73ae96fe8966aaca8d18ca285c38ce
@@ -19,9 +19,10 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.required_ruby_version = '>= 2.1'
22
+ spec.required_ruby_version = '>= 2.2'
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.11"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
26
  spec.add_development_dependency 'minitest', '~> 5.8'
27
+ spec.add_development_dependency 'board_game_grid', '~> 0.1'
27
28
  end
@@ -1,12 +1,13 @@
1
1
  require 'just_checkers/piece'
2
2
  require 'just_checkers/point'
3
+ require 'board_game_grid'
3
4
 
4
5
  module JustCheckers
5
6
 
6
7
  # = Square
7
8
  #
8
9
  # A Square on a board of checkers
9
- class Square
10
+ class Square < BoardGameGrid::Square
10
11
 
11
12
  # New objects can be instantiated by passing in a hash with
12
13
  #
@@ -41,54 +42,11 @@ module JustCheckers
41
42
  end
42
43
  end
43
44
 
44
- # @return [Fixnum] the unique identifier of the square.
45
- attr_reader :id
46
-
47
- # @return [Fixnum] the x co-ordinate of the square.
48
- attr_reader :x
49
-
50
- # @return [Fixnum] the y co-ordinate of the square.
51
- attr_reader :y
52
-
53
- # @return [Piece,NilClass] The piece on the square if any.
54
- attr_accessor :piece
55
-
56
- # checks if the square matches the attributes passed.
57
- #
58
- # @param [Symbol] attribute
59
- # the square's attribute.
60
- #
61
- # @param [Object,Hash] value
62
- # a value to match on. Can be a hash of attribute/value pairs for deep matching
63
- #
64
- # ==== Example:
65
- # # Check if square has a piece owned by player 1
66
- # square.attribute_match?(:piece, player_number: 1)
67
- def attribute_match?(attribute, value)
68
- hash_obj_matcher = lambda do |obj, k, v|
69
- value = obj.send(k)
70
- if !value.nil? && v.is_a?(Hash)
71
- v.all? { |k2,v2| hash_obj_matcher.call(value, k2, v2) }
72
- else
73
- value == v
74
- end
75
- end
76
-
77
- hash_obj_matcher.call(self, attribute, value)
78
- end
79
-
80
- # Is the square unoccupied by a piece?
81
- #
82
- # @return [Boolean]
83
- def unoccupied?
84
- piece.nil?
85
- end
86
-
87
- # A point object with the square's co-ordinates.
45
+ # A serialized version of the square as a hash
88
46
  #
89
- # @return [Point]
90
- def point
91
- Point.new(x, y)
47
+ # @return [Hash]
48
+ def as_json
49
+ { id: id, x: x, y: y, piece: piece && piece.as_json }
92
50
  end
93
51
 
94
52
  # All squares that a piece on this square could jump to, given the board.
@@ -101,7 +59,7 @@ module JustCheckers
101
59
  #
102
60
  # @return [SquareSet]
103
61
  def possible_jumps(piece, squares)
104
- squares.two_squares_away_from(self).in_direction_of(piece, self).unoccupied.select do |s|
62
+ squares.at_range(self, 2).in_direction_of(piece, self).unoccupied.select do |s|
105
63
  squares.between(self, s).occupied_by_opponent_of(piece.player_number).any?
106
64
  end
107
65
  end
@@ -116,7 +74,7 @@ module JustCheckers
116
74
  #
117
75
  # @return [SquareSet]
118
76
  def possible_moves(piece, squares)
119
- squares.one_square_away_from(self).in_direction_of(piece, self).unoccupied
77
+ squares.at_range(self, 1).in_direction_of(piece, self).unoccupied
120
78
  end
121
79
 
122
80
  # Checks if the piece on the square can promote.
@@ -139,12 +97,5 @@ module JustCheckers
139
97
  def promote
140
98
  piece && piece.promote
141
99
  end
142
-
143
- # A serialized version of the square as a hash
144
- #
145
- # @return [Hash]
146
- def as_json
147
- { id: id, x: x, y: y, piece: piece && piece.as_json }
148
- end
149
100
  end
150
101
  end
@@ -1,14 +1,12 @@
1
- require 'forwardable'
1
+ require 'board_game_grid'
2
2
  require 'just_checkers/square'
3
- require 'just_checkers/vector'
4
3
 
5
4
  module JustCheckers
6
5
 
7
6
  # = Square Set
8
7
  #
9
8
  # A collection of Squares with useful filtering functions
10
- class SquareSet
11
- extend Forwardable
9
+ class SquareSet < BoardGameGrid::SquareSet
12
10
 
13
11
  # New objects can be instantiated by passing in a hash with squares.
14
12
  # They can be square objects or hashes.
@@ -24,104 +22,15 @@ module JustCheckers
24
22
  # ]
25
23
  # })
26
24
  def initialize(squares: [])
27
- @squares = if squares.first.class == Square
25
+ @squares = if squares.all? { |element| element.instance_of?(Hash) }
26
+ squares.map { |args| JustCheckers::Square.new(args) }
27
+ elsif squares.all? { |element| element.instance_of?(JustCheckers::Square) }
28
28
  squares
29
29
  else
30
- squares.map { |s| Square.new(s) }
30
+ raise ArgumentError, "all squares must have the same class"
31
31
  end
32
32
  end
33
33
 
34
- # @return [Array<Square>] The squares in the set.
35
- attr_reader :squares
36
-
37
- def_delegator :squares, :first
38
- def_delegator :squares, :size
39
- def_delegator :squares, :include?
40
- def_delegator :squares, :any?
41
- def_delegator :squares, :none?
42
- def_delegator :squares, :empty?
43
-
44
- # Iterate over the squares with a block and behaves like Enumerable#each.
45
- #
46
- # @return [Enumerable]
47
- def each(&block)
48
- squares.each(&block)
49
- end
50
-
51
- # Filter the squares with a block and behaves like Enumerable#select.
52
- # It returns a SquareSet with the filtered squares.
53
- #
54
- # @return [SquareSet]
55
- def select(&block)
56
- self.class.new(squares: squares.select(&block))
57
- end
58
-
59
- # Filter the squares with a hash of attribute and matching values.
60
- #
61
- # @param [Hash] hash
62
- # attributes to query for.
63
- #
64
- # @return [SquareSet]
65
- #
66
- # ==== Example:
67
- # # Find all squares where piece is nil
68
- # square_set.where(piece: nil)
69
- def where(hash)
70
- res = hash.inject(squares) do |memo, (attribute, value)|
71
- memo.select { |square| square.attribute_match?(attribute, value) }
72
- end
73
- self.class.new(squares: res)
74
- end
75
-
76
- # Find the square with the matching x and y co-ordinates
77
- #
78
- # @param [Fixnum] x
79
- # the x co-ordinate.
80
- #
81
- # @param [Fixnum] y
82
- # the y co-ordinate.
83
- #
84
- # @return [Square]
85
- # ==== Example:
86
- # # Find the square at 4,2
87
- # square_set.find_by_x_and_y(4, 2)
88
- def find_by_x_and_y(x, y)
89
- select { |s| s.x == x && s.y == y }.first
90
- end
91
-
92
- # Find the square with the matching unique identifier
93
- #
94
- # @param [Fixnum] id
95
- # the unique identifier.
96
- #
97
- # @return [Square]
98
- # ==== Example:
99
- # # Find the square with id 4
100
- # square_set.find_by_id(4)
101
- def find_by_id(id)
102
- select { |s| s.id == id }.first
103
- end
104
-
105
- # Return all squares that are one square away from the passed square.
106
- #
107
- # @param [Square] square
108
- # the square in question.
109
- #
110
- # @return [SquareSet]
111
- def one_square_away_from(square)
112
- select { |s| Vector.new(square, s).magnitude == 1 }
113
- end
114
-
115
- # Return all squares that are two squares away from the passed square.
116
- #
117
- # @param [Square] square
118
- # the square in question.
119
- #
120
- # @return [SquareSet]
121
- def two_squares_away_from(square)
122
- select { |s| Vector.new(square, s).magnitude == 2 }
123
- end
124
-
125
34
  # Find squares in the direction of the piece from the square
126
35
  # If the piece is normal, it returns squares in front of it.
127
36
  # If the piece is king, it returns all squares.
@@ -139,51 +48,10 @@ module JustCheckers
139
48
  # square_set.in_direction_of(piece, square)
140
49
  def in_direction_of(piece, square)
141
50
  select do |s|
142
- piece.king? || Vector.new(square, s).direction_y == piece.direction
51
+ piece.king? || BoardGameGrid::Vector.new(square, s).direction.y == piece.direction
143
52
  end
144
53
  end
145
54
 
146
- # Find all squares without pieces on them.
147
- #
148
- # @return [SquareSet]
149
- def unoccupied
150
- select(&:unoccupied?)
151
- end
152
-
153
- # Returns squares between a and b.
154
- # Only squares that are in the same diagonal will return squares.
155
- #
156
- # @param [Square] a
157
- # a square.
158
- #
159
- # @param [Square] b
160
- # another square.
161
- #
162
- # @return [SquareSet]
163
- #
164
- # ==== Example:
165
- # # Get all squares between square_a and square_b
166
- # square_set.between(square_a, square_b)
167
- def between(a, b)
168
- vector = Vector.new(a, b)
169
- if vector.diagonal
170
- point_counter = a.point
171
- direction = vector.direction
172
- squares = []
173
-
174
- while point_counter != b.point
175
- point_counter = point_counter + direction
176
- square = find_by_x_and_y(point_counter.x, point_counter.y)
177
- if square && square.point != b.point
178
- squares.push(square)
179
- end
180
- end
181
- else
182
- squares = []
183
- end
184
- self.class.new(squares: squares)
185
- end
186
-
187
55
  # Takes a player number and returns all squares occupied by the opponent of the player
188
56
  #
189
57
  # @param [Fixnum] player_number
@@ -203,14 +71,5 @@ module JustCheckers
203
71
  def occupied_by(player_number)
204
72
  select { |s| s.piece && s.piece.player_number == player_number }
205
73
  end
206
-
207
- attr_reader :squares
208
-
209
- # serializes the squares as a hash
210
- #
211
- # @return [Hash]
212
- def as_json
213
- squares.map(&:as_json)
214
- end
215
74
  end
216
75
  end
@@ -1,4 +1,4 @@
1
1
  module JustCheckers
2
2
  # :nodoc:
3
- VERSION = "0.3.3"
3
+ VERSION = "1.0.0"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: just_checkers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Humphreys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-28 00:00:00.000000000 Z
11
+ date: 2018-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: board_game_grid
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
55
69
  description: Provides a representation of a checkers game complete with rules enforcement
56
70
  and serialisation.
57
71
  email:
@@ -70,7 +84,6 @@ files:
70
84
  - bin/setup
71
85
  - just_checkers.gemspec
72
86
  - lib/just_checkers.rb
73
- - lib/just_checkers/direction.rb
74
87
  - lib/just_checkers/errors/empty_square_error.rb
75
88
  - lib/just_checkers/errors/error.rb
76
89
  - lib/just_checkers/errors/invalid_move_error.rb
@@ -81,7 +94,6 @@ files:
81
94
  - lib/just_checkers/point.rb
82
95
  - lib/just_checkers/square.rb
83
96
  - lib/just_checkers/square_set.rb
84
- - lib/just_checkers/vector.rb
85
97
  - lib/just_checkers/version.rb
86
98
  homepage: https://github.com/mrlhumphreys/just_checkers
87
99
  licenses:
@@ -95,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
107
  requirements:
96
108
  - - ">="
97
109
  - !ruby/object:Gem::Version
98
- version: '2.1'
110
+ version: '2.2'
99
111
  required_rubygems_version: !ruby/object:Gem::Requirement
100
112
  requirements:
101
113
  - - ">="
@@ -1,42 +0,0 @@
1
- module JustCheckers
2
-
3
- # = Direction
4
- #
5
- # The Direction that something is moving on a 2d plane
6
- class Direction
7
-
8
- # New objects can be instantiated with
9
- #
10
- # @param [Fixnum] x
11
- # the x magnitude.
12
- #
13
- # @param [Fixnum] y
14
- # the y magnitude.
15
- #
16
- # ==== Example:
17
- # # Instantiates a new Direction
18
- # JustCheckers::Direction.new({
19
- # x: 1,
20
- # y: 1
21
- # })
22
- def initialize(x, y)
23
- @x, @y = x, y
24
- end
25
-
26
- # @return [Fixnum] the x magnitude.
27
- attr_reader :x
28
-
29
- # @return [Fixnum] the y magnitude.
30
- attr_reader :y
31
-
32
- # Check if directions are equal by seeing if their magnitudes are equal.
33
- #
34
- # @param [Direction] other
35
- # the other direction to compare to.
36
- #
37
- # @return [Boolean]
38
- def ==(other)
39
- self.x == other.x && self.y == other.y
40
- end
41
- end
42
- end
@@ -1,95 +0,0 @@
1
- require 'just_checkers/direction'
2
-
3
- module JustCheckers
4
-
5
- # = Vector
6
- #
7
- # An element of Vector space
8
- class Vector
9
-
10
- # New objects can be instantiated by passing in a two points with x and y co-ordinates
11
- #
12
- # @param [Point] a
13
- # the start point.
14
- #
15
- # @param [Point] b
16
- # the end point.
17
- #
18
- # ==== Example:
19
- # # Instantiates a new Vector
20
- # JustCheckers::Vector.new({
21
- # a: JustCheckers::Point.new(x: 1, y: 1),
22
- # b: JustCheckers::Point.new(x: 3, y: 3)
23
- # })
24
- def initialize(a, b)
25
- @a, @b = a, b
26
- end
27
-
28
- # @return [Point] the start point.
29
- attr_reader :a
30
-
31
- # @return [Point] the end point.
32
- attr_reader :b
33
-
34
- # How big the vector is if it's diagonal, otherwise, nil.
35
- #
36
- # @return [Fixnum,NilClass]
37
- def magnitude
38
- if diagonal
39
- dx.abs
40
- else
41
- nil
42
- end
43
- end
44
-
45
- # The direction of the vector as a object
46
- #
47
- # @return [Direction]
48
- def direction
49
- Direction.new(direction_x, direction_y)
50
- end
51
-
52
- # The x component of the direction, 1 if moving down, -1 if moving up, 0 otherwise
53
- #
54
- # @return [Fixnum]
55
- def direction_x
56
- if dx > 0
57
- 1
58
- elsif dx == 0
59
- 0
60
- else
61
- -1
62
- end
63
- end
64
-
65
- # The y component of the direction, 1 if moving right, -1 if moving left, 0 otherwise
66
- #
67
- # @return [Fixnum]
68
- def direction_y
69
- if dy > 0
70
- 1
71
- elsif dy == 0
72
- 0
73
- else
74
- -1
75
- end
76
- end
77
-
78
- # Is the vector diagonal?
79
- #
80
- # @return [Boolean]
81
- def diagonal
82
- dx.abs == dy.abs
83
- end
84
-
85
- private
86
-
87
- def dx
88
- b.x - a.x
89
- end
90
-
91
- def dy
92
- b.y - a.y
93
- end
94
- end
95
- end