just_backgammon 0.1.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 +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +68 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/just_backgammon.gemspec +27 -0
- data/lib/just_backgammon/bar.rb +107 -0
- data/lib/just_backgammon/combined_move.rb +55 -0
- data/lib/just_backgammon/common.rb +38 -0
- data/lib/just_backgammon/dice_set.rb +74 -0
- data/lib/just_backgammon/die.rb +54 -0
- data/lib/just_backgammon/errors/bear_off_error.rb +20 -0
- data/lib/just_backgammon/errors/blocked_error.rb +20 -0
- data/lib/just_backgammon/errors/dice_mismatch_error.rb +20 -0
- data/lib/just_backgammon/errors/empty_bar_error.rb +20 -0
- data/lib/just_backgammon/errors/empty_point_error.rb +20 -0
- data/lib/just_backgammon/errors/moves_possible_error.rb +20 -0
- data/lib/just_backgammon/errors/not_players_turn_error.rb +20 -0
- data/lib/just_backgammon/errors/pieces_on_bar_error.rb +20 -0
- data/lib/just_backgammon/errors/point_not_found_error.rb +20 -0
- data/lib/just_backgammon/errors/point_ownership_error.rb +20 -0
- data/lib/just_backgammon/errors/wrong_direction_error.rb +20 -0
- data/lib/just_backgammon/errors/wrong_phase_error.rb +20 -0
- data/lib/just_backgammon/game_state.rb +332 -0
- data/lib/just_backgammon/move.rb +112 -0
- data/lib/just_backgammon/move_list.rb +151 -0
- data/lib/just_backgammon/off_board.rb +73 -0
- data/lib/just_backgammon/piece.rb +33 -0
- data/lib/just_backgammon/point.rb +104 -0
- data/lib/just_backgammon/point_set.rb +95 -0
- data/lib/just_backgammon/version.rb +4 -0
- data/lib/just_backgammon.rb +6 -0
- metadata +123 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = MovesPossibleError
|
4
|
+
#
|
5
|
+
# A moves possible error with a message
|
6
|
+
class MovesPossibleError
|
7
|
+
|
8
|
+
# A new instance of MovesPossibleError.
|
9
|
+
#
|
10
|
+
# @option [String] message
|
11
|
+
# the message.
|
12
|
+
#
|
13
|
+
# ==== Example:
|
14
|
+
# # Instantiates a new MovesPossibleError
|
15
|
+
# JustBackgammon::MovesPossibleError.new("Custom Message")
|
16
|
+
def initialize(message="Moves are still possible.")
|
17
|
+
@message = message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = NotPlayersTurnError
|
4
|
+
#
|
5
|
+
# A not player's turn error with a message
|
6
|
+
class NotPlayersTurnError
|
7
|
+
|
8
|
+
# A new instance of NotPlayersTurnError.
|
9
|
+
#
|
10
|
+
# @option [String] message
|
11
|
+
# the message.
|
12
|
+
#
|
13
|
+
# ==== Example:
|
14
|
+
# # Instantiates a new NotPlayersTurnError
|
15
|
+
# JustBackgammon::NotPlayersTurnError.new("Custom Message")
|
16
|
+
def initialize(message="It is not the player's turn yet.")
|
17
|
+
@message = message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = PiecesOnBarError
|
4
|
+
#
|
5
|
+
# A pieces on bar error with a message
|
6
|
+
class PiecesOnBarError
|
7
|
+
|
8
|
+
# A new instance of PiecesOnBarError.
|
9
|
+
#
|
10
|
+
# @option [String] message
|
11
|
+
# the message.
|
12
|
+
#
|
13
|
+
# ==== Example:
|
14
|
+
# # Instantiates a new PiecesOnBarError
|
15
|
+
# JustBackgammon::PiecesOnBarError.new("Custom Message")
|
16
|
+
def initialize(message="There are still pieces on the bar.")
|
17
|
+
@message = message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = PointNotFoundError
|
4
|
+
#
|
5
|
+
# A point not found error with a message
|
6
|
+
class PointNotFoundError
|
7
|
+
|
8
|
+
# A new instance of PointNotFoundError.
|
9
|
+
#
|
10
|
+
# @option [String] message
|
11
|
+
# the message.
|
12
|
+
#
|
13
|
+
# ==== Example:
|
14
|
+
# # Instantiates a new PointNotFoundError
|
15
|
+
# JustBackgammon::PointNotFoundError.new("Custom Message")
|
16
|
+
def initialize(message="Point cannot be found.")
|
17
|
+
@message = message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = PointOwnershipError
|
4
|
+
#
|
5
|
+
# A point ownership error with a message
|
6
|
+
class PointOwnershipError
|
7
|
+
|
8
|
+
# A new instance of PointOwnershipError.
|
9
|
+
#
|
10
|
+
# @option [String] message
|
11
|
+
# the message.
|
12
|
+
#
|
13
|
+
# ==== Example:
|
14
|
+
# # Instantiates a new PointOwnershipError
|
15
|
+
# JustBackgammon::PointOwnershipError.new("Custom Message")
|
16
|
+
def initialize(message="Point is not owned by player.")
|
17
|
+
@message = message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = WrongDirectionError
|
4
|
+
#
|
5
|
+
# A wrong direction error with a message
|
6
|
+
class WrongDirectionError
|
7
|
+
|
8
|
+
# A new instance of WrongDirectionError.
|
9
|
+
#
|
10
|
+
# @option [String] message
|
11
|
+
# the message.
|
12
|
+
#
|
13
|
+
# ==== Example:
|
14
|
+
# # Instantiates a new WrongDirectionError
|
15
|
+
# JustBackgammon::WrongDirectionError.new("Custom Message")
|
16
|
+
def initialize(message="A piece cannot move backwards.")
|
17
|
+
@message = message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = WrongPhaseError
|
4
|
+
#
|
5
|
+
# A wrong phase error with a message
|
6
|
+
class WrongPhaseError
|
7
|
+
|
8
|
+
# A new instance of WrongPhaseError.
|
9
|
+
#
|
10
|
+
# @option [String] message
|
11
|
+
# the message.
|
12
|
+
#
|
13
|
+
# ==== Example:
|
14
|
+
# # Instantiates a new WrongPhaseError
|
15
|
+
# JustBackgammon::WrongPhaseError.new("Custom Message")
|
16
|
+
def initialize(message="It is the wrong phase.")
|
17
|
+
@message = message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,332 @@
|
|
1
|
+
require 'just_backgammon/dice_set'
|
2
|
+
require 'just_backgammon/bar'
|
3
|
+
require 'just_backgammon/point_set'
|
4
|
+
require 'just_backgammon/off_board'
|
5
|
+
require 'just_backgammon/move'
|
6
|
+
require 'just_backgammon/move_list'
|
7
|
+
|
8
|
+
require 'just_backgammon/errors/not_players_turn_error'
|
9
|
+
require 'just_backgammon/errors/wrong_phase_error'
|
10
|
+
require 'just_backgammon/errors/point_not_found_error'
|
11
|
+
require 'just_backgammon/errors/empty_bar_error'
|
12
|
+
require 'just_backgammon/errors/empty_point_error'
|
13
|
+
require 'just_backgammon/errors/point_ownership_error'
|
14
|
+
require 'just_backgammon/errors/blocked_error'
|
15
|
+
require 'just_backgammon/errors/wrong_direction_error'
|
16
|
+
require 'just_backgammon/errors/pieces_on_bar_error'
|
17
|
+
require 'just_backgammon/errors/bear_off_error'
|
18
|
+
require 'just_backgammon/errors/dice_mismatch_error'
|
19
|
+
require 'just_backgammon/errors/moves_possible_error'
|
20
|
+
|
21
|
+
module JustBackgammon
|
22
|
+
|
23
|
+
# = Game State
|
24
|
+
#
|
25
|
+
# Represents a game of Backgammon in progress.
|
26
|
+
class GameState
|
27
|
+
|
28
|
+
# The roll phase of the turn where the players roll dice.
|
29
|
+
ROLL = 'roll'
|
30
|
+
|
31
|
+
# The move phase of the turn where the players move pieces.
|
32
|
+
MOVE = 'move'
|
33
|
+
|
34
|
+
# A new instance of GameState.
|
35
|
+
#
|
36
|
+
# @param [Fixnum] current_player_number
|
37
|
+
# Who's turn it is, 1 or 2
|
38
|
+
#
|
39
|
+
# @param [Fixnum] current_phase
|
40
|
+
# The current phase of the turn. Either move or roll.
|
41
|
+
#
|
42
|
+
# @param [Array<Hash>] dice
|
43
|
+
# An array of dice, each with a number.
|
44
|
+
#
|
45
|
+
# @param [Hash] bar
|
46
|
+
# The bar where hit pieces go. Contains an array of pieces.
|
47
|
+
#
|
48
|
+
# @param [Array<Hash>] points
|
49
|
+
# An array of points, each with a number and an array of pieces.
|
50
|
+
#
|
51
|
+
# @param [Hash] off_board
|
52
|
+
# Off the board where pieces bear off. Contains an array of pieces.
|
53
|
+
#
|
54
|
+
# ==== Example:
|
55
|
+
# # Instantiates a new Game of Backgammon
|
56
|
+
# JustBackgammon::GameState.new({
|
57
|
+
# current_player_number: 1,
|
58
|
+
# current_phase: 'move',
|
59
|
+
# dice: [
|
60
|
+
# { number: 1 },
|
61
|
+
# { number: 4 },
|
62
|
+
# ],
|
63
|
+
# bar: {
|
64
|
+
# pieces: [],
|
65
|
+
# },
|
66
|
+
# points: [
|
67
|
+
# { number: 1, pieces: [{owner: 1}, {owner: 1}] },
|
68
|
+
# { number: 2, pieces: [] }
|
69
|
+
# ],
|
70
|
+
# off_board: {
|
71
|
+
# pieces: [],
|
72
|
+
# }
|
73
|
+
# })
|
74
|
+
def initialize(current_player_number:, current_phase:, dice:, bar:, points:, off_board:)
|
75
|
+
@current_player_number = current_player_number
|
76
|
+
@current_phase = current_phase
|
77
|
+
@dice = JustBackgammon::DiceSet.load(dice: dice)
|
78
|
+
@bar = JustBackgammon::Bar.load(bar)
|
79
|
+
@points = JustBackgammon::PointSet.load(points: points)
|
80
|
+
@off_board = JustBackgammon::OffBoard.load(off_board)
|
81
|
+
@errors = []
|
82
|
+
end
|
83
|
+
|
84
|
+
# Instantiates a new GameState object in the starting position
|
85
|
+
#
|
86
|
+
# @return [GameState]
|
87
|
+
def self.default
|
88
|
+
new({
|
89
|
+
current_player_number: 1,
|
90
|
+
current_phase: ROLL,
|
91
|
+
dice: [
|
92
|
+
{ number: nil },
|
93
|
+
{ number: nil }
|
94
|
+
],
|
95
|
+
bar: { pieces: [] },
|
96
|
+
points: [
|
97
|
+
{ number: 1, pieces: [{owner: 1}, {owner: 1}] },
|
98
|
+
{ number: 2, pieces: [] },
|
99
|
+
{ number: 3, pieces: [] },
|
100
|
+
{ number: 4, pieces: [] },
|
101
|
+
{ number: 5, pieces: [] },
|
102
|
+
{ number: 6, pieces: [{owner: 2}, {owner: 2}, {owner: 2}, {owner: 2}, {owner: 2}] },
|
103
|
+
|
104
|
+
{ number: 7, pieces: [] },
|
105
|
+
{ number: 8, pieces: [{owner: 2}, {owner: 2}, {owner: 2}] },
|
106
|
+
{ number: 9, pieces: [] },
|
107
|
+
{ number: 10, pieces: [] },
|
108
|
+
{ number: 11, pieces: [] },
|
109
|
+
{ number: 12, pieces: [{owner: 1}, {owner: 1}, {owner: 1}, {owner: 1}, {owner: 1}] },
|
110
|
+
|
111
|
+
{ number: 13, pieces: [{owner: 2}, {owner: 2}, {owner: 2}, {owner: 2}, {owner: 2}] },
|
112
|
+
{ number: 14, pieces: [] },
|
113
|
+
{ number: 15, pieces: [] },
|
114
|
+
{ number: 16, pieces: [] },
|
115
|
+
{ number: 17, pieces: [{owner: 1}, {owner: 1}, {owner: 1}] },
|
116
|
+
{ number: 18, pieces: [] },
|
117
|
+
|
118
|
+
{ number: 19, pieces: [{owner: 1}, {owner: 1}, {owner: 1}, {owner: 1}, {owner: 1}] },
|
119
|
+
{ number: 20, pieces: [] },
|
120
|
+
{ number: 21, pieces: [] },
|
121
|
+
{ number: 22, pieces: [] },
|
122
|
+
{ number: 23, pieces: [] },
|
123
|
+
{ number: 24, pieces: [{owner: 2}, {owner: 2}] },
|
124
|
+
],
|
125
|
+
off_board: { pieces: [] }
|
126
|
+
})
|
127
|
+
end
|
128
|
+
|
129
|
+
# @return [Fixnum] who's turn it is
|
130
|
+
attr_reader :current_player_number
|
131
|
+
|
132
|
+
# @return [String] the current phase of the turn. Either move or roll
|
133
|
+
attr_reader :current_phase
|
134
|
+
|
135
|
+
# @return [DiceSet] an array of dice, each with a number
|
136
|
+
attr_reader :dice
|
137
|
+
|
138
|
+
# @return [Bar] the bar where hit pieces go. Contains an array of pieces
|
139
|
+
attr_reader :bar
|
140
|
+
|
141
|
+
# @return [PointSet] an array of points, each with a number and an array of pieces
|
142
|
+
attr_reader :points
|
143
|
+
|
144
|
+
# @return [Fixnum] who's turn it is.
|
145
|
+
attr_reader :off_board
|
146
|
+
|
147
|
+
# @return [Array<Error>] errors if any.
|
148
|
+
attr_reader :errors
|
149
|
+
|
150
|
+
# Rolls the dice
|
151
|
+
#
|
152
|
+
# Two dice are rolled and returns true on success.
|
153
|
+
# The results can be found on the dice attribute.
|
154
|
+
# If the dice have the same result, then the dice are duplicated.
|
155
|
+
# If it's not the player's turn or the phase is move, it will return false.
|
156
|
+
#
|
157
|
+
# ==== Example:
|
158
|
+
# # Rolls the dice for player 1
|
159
|
+
# game_state.roll(1)
|
160
|
+
#
|
161
|
+
# @param [Fixnum] player_number
|
162
|
+
# the player number, 1 or 2.
|
163
|
+
#
|
164
|
+
# @return [Boolean]
|
165
|
+
def roll(player_number)
|
166
|
+
@errors = []
|
167
|
+
|
168
|
+
if player_number != current_player_number
|
169
|
+
@errors.push JustBackgammon::NotPlayersTurnError.new
|
170
|
+
elsif current_phase != ROLL
|
171
|
+
@errors.push JustBackgammon::WrongPhaseError.new
|
172
|
+
else
|
173
|
+
@dice.roll
|
174
|
+
step
|
175
|
+
end
|
176
|
+
|
177
|
+
@errors.none?
|
178
|
+
end
|
179
|
+
|
180
|
+
# Moves each piece specified from one point, to another
|
181
|
+
#
|
182
|
+
# It moves each piece specified and returns true on success.
|
183
|
+
# It returns false if the move is invalid, it's not the player's turn or the phase is roll..
|
184
|
+
#
|
185
|
+
# ==== Example:
|
186
|
+
# # Moves two pieces for player 1
|
187
|
+
# game_state.move(1, [{from: 1, to: 2}, {from: 3, to: 4}])
|
188
|
+
#
|
189
|
+
# @param [Fixnum] player_number
|
190
|
+
# the player number, 1 or 2.
|
191
|
+
#
|
192
|
+
# @param [Array<Hash>] list
|
193
|
+
# a list of all the moves, each containing a from and to key.
|
194
|
+
#
|
195
|
+
# @return [Boolean]
|
196
|
+
def move(player_number, list)
|
197
|
+
move_list = sanitize_list(list)
|
198
|
+
|
199
|
+
@errors = []
|
200
|
+
if player_number != current_player_number
|
201
|
+
@errors.push JustBackgammon::NotPlayersTurnError.new
|
202
|
+
elsif current_phase != MOVE
|
203
|
+
@errors.push JustBackgammon::WrongPhaseError.new
|
204
|
+
elsif move_valid?(move_list)
|
205
|
+
perform_move(move_list)
|
206
|
+
step
|
207
|
+
end
|
208
|
+
|
209
|
+
@errors.none?
|
210
|
+
end
|
211
|
+
|
212
|
+
# The player number of the winner. It returns nil if there is no winner.
|
213
|
+
#
|
214
|
+
# @return [Fixnum,NilClass]
|
215
|
+
def winner
|
216
|
+
[1, 2].find { |player_number| @off_board.number_of_pieces_owned_by_player(player_number) == 15 }
|
217
|
+
end
|
218
|
+
|
219
|
+
# A hashed serialized representation of the game state
|
220
|
+
#
|
221
|
+
# @return [Hash]
|
222
|
+
def as_json
|
223
|
+
{
|
224
|
+
current_player_number: current_player_number,
|
225
|
+
current_phase: current_phase,
|
226
|
+
dice: dice.as_json,
|
227
|
+
bar: bar.as_json,
|
228
|
+
points: points.as_json,
|
229
|
+
off_board: off_board.as_json
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
private
|
234
|
+
|
235
|
+
def move_valid?(move_list) # :nodoc:
|
236
|
+
@errors = []
|
237
|
+
|
238
|
+
case
|
239
|
+
when move_list.any_missing_point?
|
240
|
+
@errors.push JustBackgammon::PointNotFoundError.new
|
241
|
+
when move_list.any_point_empty?
|
242
|
+
@errors.push JustBackgammon::EmptyPointError.new
|
243
|
+
when move_list.any_bar_empty_for_player?(current_player_number)
|
244
|
+
@errors.push JustBackgammon::EmptyBarError.new
|
245
|
+
when move_list.any_point_owned_by_opponent?(current_player_number)
|
246
|
+
@errors.push JustBackgammon::PointOwnershipError.new
|
247
|
+
when move_list.any_blocked?(current_player_number)
|
248
|
+
@errors.push JustBackgammon::BlockedError.new
|
249
|
+
when move_list.any_wrong_direction?(current_player_number)
|
250
|
+
@errors.push JustBackgammon::WrongDirectionError.new
|
251
|
+
when !move_list.all_moves_from_bar? && \
|
252
|
+
move_list.number_of_moves_from_bar != bar.number_of_pieces_owned_by_player(current_player_number) && \
|
253
|
+
points.destinations(bar, dice, current_player_number).size >= move_list.number_of_moves_from_bar
|
254
|
+
@errors.push JustBackgammon::PiecesOnBarError.new
|
255
|
+
when move_list.any_bear_off? && \
|
256
|
+
!(points.not_home(current_player_number).map(&:number) - move_list.map { |m| m.from.number }).empty?
|
257
|
+
@errors.push JustBackgammon::BearOffError.new
|
258
|
+
when current_player_has_moves? && move_list.dice_mismatch?(current_player_number, dice)
|
259
|
+
@errors.push JustBackgammon::DiceMismatchError.new
|
260
|
+
end
|
261
|
+
|
262
|
+
@errors.none?
|
263
|
+
end
|
264
|
+
|
265
|
+
def current_player_has_moves? # :nodoc:
|
266
|
+
if bar.any_pieces_for_player?(@current_player_number)
|
267
|
+
@points.destinations(bar, @dice, @current_player_number).any?
|
268
|
+
else
|
269
|
+
@points.owned_by_player(@current_player_number).any? do |p|
|
270
|
+
@points.destinations(p, @dice, @current_player_number).any?
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def perform_move(list) # :nodoc:
|
276
|
+
list.each do |move|
|
277
|
+
from = find_point(move.from.number)
|
278
|
+
to = find_point(move.to.number)
|
279
|
+
|
280
|
+
if to.is_a?(JustBackgammon::Point) && to.owned_by_opponent?(current_player_number) && to.blot?
|
281
|
+
@bar.push(to.pop)
|
282
|
+
end
|
283
|
+
|
284
|
+
popped = if from.is_a?(JustBackgammon::Bar)
|
285
|
+
from.pop_for_player(current_player_number)
|
286
|
+
else
|
287
|
+
from.pop
|
288
|
+
end
|
289
|
+
|
290
|
+
to.push(popped)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def step # :nodoc:
|
295
|
+
case current_phase
|
296
|
+
when ROLL
|
297
|
+
@current_phase = MOVE
|
298
|
+
when MOVE
|
299
|
+
@current_phase = ROLL
|
300
|
+
@dice.reset
|
301
|
+
turn
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def turn # :nodoc:
|
306
|
+
case current_player_number
|
307
|
+
when 1
|
308
|
+
@current_player_number = 2
|
309
|
+
when 2
|
310
|
+
@current_player_number = 1
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def find_point(n) # :nodoc:
|
315
|
+
case n
|
316
|
+
when 'bar'
|
317
|
+
bar
|
318
|
+
when 'off_board'
|
319
|
+
off_board
|
320
|
+
else
|
321
|
+
@points.find_by_number(n.to_i)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def sanitize_list(list) # :nodoc:
|
326
|
+
move_list = list.map do |i|
|
327
|
+
JustBackgammon::Move.new({ from: find_point(i[:from]), to: find_point(i[:to]) })
|
328
|
+
end
|
329
|
+
JustBackgammon::MoveList.new(moves: move_list)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module JustBackgammon
|
2
|
+
|
3
|
+
# = Move
|
4
|
+
#
|
5
|
+
# A move from a point to a point.
|
6
|
+
class Move
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
# A new instance of Move.
|
10
|
+
#
|
11
|
+
# @param [Point] from
|
12
|
+
# The point where the move starts.
|
13
|
+
#
|
14
|
+
# @param [Point] to
|
15
|
+
# The point where the move ends.
|
16
|
+
#
|
17
|
+
# ==== Example:
|
18
|
+
# # Instantiates a new Bar
|
19
|
+
# JustBackgammon::Move.new({from: point_a, to: point_b})
|
20
|
+
def initialize(from: , to:)
|
21
|
+
@from = from
|
22
|
+
@to = to
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Point] the point where the move starts
|
26
|
+
attr_reader :from
|
27
|
+
|
28
|
+
# @return [Point] the point where the move ends
|
29
|
+
attr_reader :to
|
30
|
+
|
31
|
+
def_delegator :from, :empty_for_player?
|
32
|
+
|
33
|
+
# The distance of the move for the specified player.
|
34
|
+
#
|
35
|
+
# @return [Fixnum]
|
36
|
+
def distance_for_player(player_number)
|
37
|
+
case player_number
|
38
|
+
when 1
|
39
|
+
from_number = from.instance_of?(Bar) ? 0 : from.number
|
40
|
+
to_number = to.instance_of?(OffBoard) ? 25 : to.number
|
41
|
+
to_number - from_number
|
42
|
+
when 2
|
43
|
+
from_number = from.instance_of?(Bar) ? 25 : from.number
|
44
|
+
to_number = to.instance_of?(OffBoard) ? 0 : to.number
|
45
|
+
to_number - from_number
|
46
|
+
else
|
47
|
+
0
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# The absolute distance of the move for the specified player.
|
52
|
+
#
|
53
|
+
# @return [Fixnum]
|
54
|
+
def absolute_distance_for_player(player_number)
|
55
|
+
distance_for_player(player_number).abs
|
56
|
+
end
|
57
|
+
|
58
|
+
# Checks if the move is in the wrong direction for the specified player.
|
59
|
+
#
|
60
|
+
# @return [Boolean]
|
61
|
+
def wrong_direction?(player_number)
|
62
|
+
case player_number
|
63
|
+
when 1
|
64
|
+
distance_for_player(player_number) < 0
|
65
|
+
when 2
|
66
|
+
distance_for_player(player_number) > 0
|
67
|
+
else
|
68
|
+
true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Checks if the move is blocked.
|
73
|
+
#
|
74
|
+
# @return [Boolean]
|
75
|
+
def blocked?(player_number)
|
76
|
+
case to
|
77
|
+
when OffBoard
|
78
|
+
false
|
79
|
+
else
|
80
|
+
to.owned_by_opponent?(player_number) && to.blocked?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Checks if the move is missing points.
|
85
|
+
#
|
86
|
+
# @return [Boolean]
|
87
|
+
def missing_point?
|
88
|
+
from.nil? || to.nil?
|
89
|
+
end
|
90
|
+
|
91
|
+
# Checks if the move is from the bar.
|
92
|
+
#
|
93
|
+
# @return [Boolean]
|
94
|
+
def from_bar?
|
95
|
+
from.instance_of?(JustBackgammon::Bar)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Checks if the move is to a point.
|
99
|
+
#
|
100
|
+
# @return [Boolean]
|
101
|
+
def to_point?
|
102
|
+
to.instance_of?(JustBackgammon::Point)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Checks if the move is bearing off.
|
106
|
+
#
|
107
|
+
# @return [Boolean]
|
108
|
+
def bear_off?
|
109
|
+
to.instance_of?(JustBackgammon::OffBoard)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|