just_checkers 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 404c68f0f2336d1e7082534610f59f9a82dfe427
4
- data.tar.gz: af653b067e74d1e31d4f97a5bccaef45b4c78e4a
3
+ metadata.gz: 60946aa3db499cb440fd0c2d9979c86f76d535d3
4
+ data.tar.gz: 58d674537166da0ad642230543b5911e1cfa558f
5
5
  SHA512:
6
- metadata.gz: 9088167eaa8e61a7c0fcbc2a45ecddce41c845810471fa593e3e84668e75b37a9cab2326f80fa0bd2c8cf85b1bffc01588beb802156de686ff52ef2765077a39
7
- data.tar.gz: fd1903da0c448ac2208cd44232a0722b23f0e9e7356a68039c9bb702809538a668744155bd2ba28182521ed75e9d947017e66aba914b2bd4d5ca89dcb92d481a
6
+ metadata.gz: 9a57e7a29e8e0c6f950abac5d470501fd55977c78fe502414dd78130b6957ef113df5437a3ba5f35319f6905441769fc47e75a934cd31dbba603734feec550a4
7
+ data.tar.gz: 7d6f5c656e3d79558dc7ada2ec6d442d6badc247803632a8abbb5117aaf9f01d44f7e7608e5b71afaf5f0603e11fae9dcf6a1433697e24f721665473ddad4365
data/README.md CHANGED
@@ -29,6 +29,18 @@ Moves can be made by passing in the player number, from co-ordinates and an arra
29
29
  game_state.move(1, {x: 1, y: 2}, [{x: 2, y: 3}])
30
30
  ```
31
31
 
32
+ Alternatively, moves can be made by specifying the ids of the squares.
33
+
34
+ ```ruby
35
+ game_state.move(1, 1, [2])
36
+ ```
37
+
38
+ The last change with all its details are found in the `last_change` attribute
39
+
40
+ ```ruby
41
+ game_state.last_change
42
+ ```
43
+
32
44
  If something happens errors may be found in the errors attribute
33
45
 
34
46
  ```ruby
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rake/testtask'
2
+ require 'bundler/gem_tasks'
2
3
 
3
4
  Rake::TestTask.new do |t|
4
5
  t.libs << 'test'
@@ -31,6 +31,7 @@ module JustCheckers
31
31
  @current_player_number = current_player_number
32
32
  @squares = SquareSet.new(squares: squares)
33
33
  @errors = []
34
+ @last_change = {}
34
35
  end
35
36
 
36
37
  # @return [Fixnum] who's turn it is.
@@ -42,6 +43,9 @@ module JustCheckers
42
43
  # @return [Array<Error>] errors if any.
43
44
  attr_reader :errors
44
45
 
46
+ # @return [Hash] most recent change.
47
+ attr_reader :last_change
48
+
45
49
  # Instantiates a new GameState object in the starting position
46
50
  #
47
51
  # @return [GameState]
@@ -49,45 +53,45 @@ module JustCheckers
49
53
  new({
50
54
  current_player_number: 1,
51
55
  squares: [
52
- { x: 1, y: 0, piece: { player_number: 1, direction: 1, king: false }},
53
- { x: 3, y: 0, piece: { player_number: 1, direction: 1, king: false }},
54
- { x: 5, y: 0, piece: { player_number: 1, direction: 1, king: false }},
55
- { x: 7, y: 0, piece: { player_number: 1, direction: 1, king: false }},
56
-
57
- { x: 0, y: 1, piece: { player_number: 1, direction: 1, king: false }},
58
- { x: 2, y: 1, piece: { player_number: 1, direction: 1, king: false }},
59
- { x: 4, y: 1, piece: { player_number: 1, direction: 1, king: false }},
60
- { x: 6, y: 1, piece: { player_number: 1, direction: 1, king: false }},
61
-
62
- { x: 1, y: 2, piece: { player_number: 1, direction: 1, king: false }},
63
- { x: 3, y: 2, piece: { player_number: 1, direction: 1, king: false }},
64
- { x: 5, y: 2, piece: { player_number: 1, direction: 1, king: false }},
65
- { x: 7, y: 2, piece: { player_number: 1, direction: 1, king: false }},
66
-
67
- { x: 0, y: 3, piece: nil },
68
- { x: 2, y: 3, piece: nil },
69
- { x: 4, y: 3, piece: nil },
70
- { x: 6, y: 3, piece: nil },
71
-
72
- { x: 1, y: 4, piece: nil },
73
- { x: 3, y: 4, piece: nil },
74
- { x: 5, y: 4, piece: nil },
75
- { x: 7, y: 4, piece: nil },
76
-
77
- { x: 0, y: 5, piece: { player_number: 2, direction: -1, king: false }},
78
- { x: 2, y: 5, piece: { player_number: 2, direction: -1, king: false }},
79
- { x: 4, y: 5, piece: { player_number: 2, direction: -1, king: false }},
80
- { x: 6, y: 5, piece: { player_number: 2, direction: -1, king: false }},
81
-
82
- { x: 1, y: 6, piece: { player_number: 2, direction: -1, king: false }},
83
- { x: 3, y: 6, piece: { player_number: 2, direction: -1, king: false }},
84
- { x: 5, y: 6, piece: { player_number: 2, direction: -1, king: false }},
85
- { x: 7, y: 6, piece: { player_number: 2, direction: -1, king: false }},
86
-
87
- { x: 0, y: 7, piece: { player_number: 2, direction: -1, king: false }},
88
- { x: 2, y: 7, piece: { player_number: 2, direction: -1, king: false }},
89
- { x: 4, y: 7, piece: { player_number: 2, direction: -1, king: false }},
90
- { x: 6, y: 7, piece: { player_number: 2, direction: -1, king: false }},
56
+ { id: 1, x: 1, y: 0, piece: { player_number: 1, direction: 1, king: false }},
57
+ { id: 2, x: 3, y: 0, piece: { player_number: 1, direction: 1, king: false }},
58
+ { id: 3, x: 5, y: 0, piece: { player_number: 1, direction: 1, king: false }},
59
+ { id: 4, x: 7, y: 0, piece: { player_number: 1, direction: 1, king: false }},
60
+
61
+ { id: 5, x: 0, y: 1, piece: { player_number: 1, direction: 1, king: false }},
62
+ { id: 6, x: 2, y: 1, piece: { player_number: 1, direction: 1, king: false }},
63
+ { id: 7, x: 4, y: 1, piece: { player_number: 1, direction: 1, king: false }},
64
+ { id: 8, x: 6, y: 1, piece: { player_number: 1, direction: 1, king: false }},
65
+
66
+ { id: 9, x: 1, y: 2, piece: { player_number: 1, direction: 1, king: false }},
67
+ { id: 10, x: 3, y: 2, piece: { player_number: 1, direction: 1, king: false }},
68
+ { id: 11, x: 5, y: 2, piece: { player_number: 1, direction: 1, king: false }},
69
+ { id: 12, x: 7, y: 2, piece: { player_number: 1, direction: 1, king: false }},
70
+
71
+ { id: 13, x: 0, y: 3, piece: nil },
72
+ { id: 14, x: 2, y: 3, piece: nil },
73
+ { id: 15, x: 4, y: 3, piece: nil },
74
+ { id: 16, x: 6, y: 3, piece: nil },
75
+
76
+ { id: 17, x: 1, y: 4, piece: nil },
77
+ { id: 18, x: 3, y: 4, piece: nil },
78
+ { id: 19, x: 5, y: 4, piece: nil },
79
+ { id: 20, x: 7, y: 4, piece: nil },
80
+
81
+ { id: 21, x: 0, y: 5, piece: { player_number: 2, direction: -1, king: false }},
82
+ { id: 22, x: 2, y: 5, piece: { player_number: 2, direction: -1, king: false }},
83
+ { id: 23, x: 4, y: 5, piece: { player_number: 2, direction: -1, king: false }},
84
+ { id: 24, x: 6, y: 5, piece: { player_number: 2, direction: -1, king: false }},
85
+
86
+ { id: 25, x: 1, y: 6, piece: { player_number: 2, direction: -1, king: false }},
87
+ { id: 26, x: 3, y: 6, piece: { player_number: 2, direction: -1, king: false }},
88
+ { id: 27, x: 5, y: 6, piece: { player_number: 2, direction: -1, king: false }},
89
+ { id: 28, x: 7, y: 6, piece: { player_number: 2, direction: -1, king: false }},
90
+
91
+ { id: 29, x: 0, y: 7, piece: { player_number: 2, direction: -1, king: false }},
92
+ { id: 30, x: 2, y: 7, piece: { player_number: 2, direction: -1, king: false }},
93
+ { id: 31, x: 4, y: 7, piece: { player_number: 2, direction: -1, king: false }},
94
+ { id: 32, x: 6, y: 7, piece: { player_number: 2, direction: -1, king: false }},
91
95
  ]
92
96
  })
93
97
  end
@@ -127,23 +131,34 @@ module JustCheckers
127
131
  # @param [Fixnum] player_number
128
132
  # the player number, 1 or 2.
129
133
  #
130
- # @param [Hash] from
134
+ # @param [Hash, Fixnum] from
131
135
  # where the moving piece currently is.
132
136
  #
133
- # @param [Array<Hash>] to
137
+ # @param [Array<Hash>, Array<Fixnum>] to
134
138
  # each place the piece is going to move to.
135
139
  #
136
140
  # @return [Boolean]
137
141
  def move(player_number, from, to)
138
142
  @errors = []
139
- from_square = squares.find_by_x_and_y(from[:x].to_i, from[:y].to_i)
140
- to_squares = to.map { |s| squares.find_by_x_and_y(s[:x].to_i, s[:y].to_i) }
143
+
144
+ from_square = if from.is_a?(Hash)
145
+ squares.find_by_x_and_y(from[:x].to_i, from[:y].to_i)
146
+ else
147
+ squares.find_by_id(from.to_i)
148
+ end
149
+
150
+ to_squares = if to.all? { |s| s.is_a?(Hash) }
151
+ to.map { |position| squares.find_by_x_and_y(position[:x].to_i, position[:y].to_i) }
152
+ else
153
+ to.map { |id| squares.find_by_id(id) }
154
+ end
141
155
 
142
156
  if player_number != current_player_number
143
157
  @errors.push NotPlayersTurnError.new
144
158
  elsif move_valid?(from_square, to_squares)
159
+ @last_change = { type: 'move', data: {player_number: player_number, from: from, to: to} }
145
160
  perform_move(from_square, to_squares)
146
- promote(to_squares.last) if promotable?(to_squares.last)
161
+ to_squares.last.promote if to_squares.last.promotable?
147
162
  turn
148
163
  end
149
164
 
@@ -171,14 +186,10 @@ module JustCheckers
171
186
  @errors.empty?
172
187
  end
173
188
 
174
- def promote(square) # :nodoc:
175
- square.piece.promote
176
- end
177
-
178
189
  def perform_move(from, to) # :nodoc:
179
190
  legs = to.unshift(from)
180
- legs.each_cons(2) do |a, b|
181
- between_square = squares.between(a, b).first
191
+ legs.each_cons(2) do |origin, destination|
192
+ between_square = squares.between(origin, destination).first
182
193
  between_square.piece = nil if between_square
183
194
  end
184
195
 
@@ -197,17 +208,5 @@ module JustCheckers
197
208
  def no_pieces_for_player?(player_number) # :nodoc:
198
209
  squares.occupied_by(player_number).none? { |s| s.possible_jumps(s.piece, squares).any? || s.possible_moves(s.piece, squares).any? }
199
210
  end
200
-
201
- def promotable?(square) # :nodoc:
202
- case square.piece.direction
203
- when 1
204
- square.y == 7
205
- when -1
206
- square.y == 0
207
- else
208
- false
209
- end
210
- end
211
-
212
211
  end
213
212
  end
@@ -10,6 +10,9 @@ module JustCheckers
10
10
 
11
11
  # New objects can be instantiated by passing in a hash with
12
12
  #
13
+ # @param [Fixnum] id
14
+ # the unique identifier of the square.
15
+ #
13
16
  # @param [Fixnum] x
14
17
  # the x co-ordinate of the square.
15
18
  #
@@ -22,11 +25,13 @@ module JustCheckers
22
25
  # ==== Example:
23
26
  # # Instantiates a new Square
24
27
  # JustCheckers::Square.new({
28
+ # id: 1,
25
29
  # x: 1,
26
30
  # y: 0,
27
31
  # piece: { player_number: 1, direction: 1, king: false }
28
32
  # })
29
- def initialize(x: , y: , piece: nil)
33
+ def initialize(id: , x: , y: , piece: nil)
34
+ @id = id
30
35
  @x = x
31
36
  @y = y
32
37
  @piece = if piece.is_a?(Hash)
@@ -36,6 +41,9 @@ module JustCheckers
36
41
  end
37
42
  end
38
43
 
44
+ # @return [Fixnum] the unique identifier of the square.
45
+ attr_reader :id
46
+
39
47
  # @return [Fixnum] the x co-ordinate of the square.
40
48
  attr_reader :x
41
49
 
@@ -111,11 +119,32 @@ module JustCheckers
111
119
  squares.one_square_away_from(self).in_direction_of(piece, self).unoccupied
112
120
  end
113
121
 
122
+ # Checks if the piece on the square can promote.
123
+ #
124
+ # @return [Boolean]
125
+ def promotable?
126
+ case piece && piece.direction
127
+ when 1
128
+ y == 7
129
+ when -1
130
+ y == 0
131
+ else
132
+ false
133
+ end
134
+ end
135
+
136
+ # Promotes the piece if the piece exists.
137
+ #
138
+ # @return [Boolean]
139
+ def promote
140
+ piece && piece.promote
141
+ end
142
+
114
143
  # A serialized version of the square as a hash
115
144
  #
116
145
  # @return [Hash]
117
146
  def as_json
118
- { x: x, y: y, piece: piece && piece.as_json }
147
+ { id: id, x: x, y: y, piece: piece && piece.as_json }
119
148
  end
120
149
  end
121
- end
150
+ end
@@ -67,8 +67,8 @@ module JustCheckers
67
67
  # # Find all squares where piece is nil
68
68
  # square_set.where(piece: nil)
69
69
  def where(hash)
70
- res = hash.inject(squares) do |memo, (k, v)|
71
- memo.select { |s| s.attribute_match?(k, v) }
70
+ res = hash.inject(squares) do |memo, (attribute, value)|
71
+ memo.select { |square| square.attribute_match?(attribute, value) }
72
72
  end
73
73
  self.class.new(squares: res)
74
74
  end
@@ -89,6 +89,19 @@ module JustCheckers
89
89
  select { |s| s.x == x && s.y == y }.first
90
90
  end
91
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
+
92
105
  # Return all squares that are one square away from the passed square.
93
106
  #
94
107
  # @param [Square] square
@@ -134,7 +147,7 @@ module JustCheckers
134
147
  #
135
148
  # @return [SquareSet]
136
149
  def unoccupied
137
- select { |s| s.piece.nil? }
150
+ select(&:unoccupied?)
138
151
  end
139
152
 
140
153
  # Returns squares between a and b.
@@ -1,4 +1,4 @@
1
1
  module JustCheckers
2
2
  # :nodoc:
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.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.2.0
4
+ version: 0.3.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: 2016-09-11 00:00:00.000000000 Z
11
+ date: 2016-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,4 +108,3 @@ signing_key:
108
108
  specification_version: 4
109
109
  summary: A checkers engine written in ruby
110
110
  test_files: []
111
- has_rdoc: