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,151 @@ | |
| 1 | 
            +
            require 'just_backgammon/combined_move'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module JustBackgammon
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              # = MoveList
         | 
| 6 | 
            +
              #
         | 
| 7 | 
            +
              # A list of moves.
         | 
| 8 | 
            +
              class MoveList
         | 
| 9 | 
            +
                extend Forwardable
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # A new instance of MoveList.
         | 
| 12 | 
            +
                #
         | 
| 13 | 
            +
                # @param [Array<Move>] moves
         | 
| 14 | 
            +
                #   All the moves.
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # ==== Example:
         | 
| 17 | 
            +
                #   # Instantiates a new MoveList
         | 
| 18 | 
            +
                #   JustBackgammon::MoveList.new([move_a, move_b])
         | 
| 19 | 
            +
                def initialize(moves:)
         | 
| 20 | 
            +
                  @moves = moves
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                # @return [Array<Move>] all the moves
         | 
| 24 | 
            +
                attr_reader :moves
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def_delegator :moves, :each
         | 
| 27 | 
            +
                def_delegator :moves, :map
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                # Combines moves if there are any that start where another ends.
         | 
| 30 | 
            +
                #
         | 
| 31 | 
            +
                # @return [Array<CombinedMove>]
         | 
| 32 | 
            +
                def combined_moves
         | 
| 33 | 
            +
                  combined_data = moves.inject([]) do |combined, m|
         | 
| 34 | 
            +
                    matching_move = combined.find_index { |c| c.last.number == m.from.number }
         | 
| 35 | 
            +
                    if matching_move
         | 
| 36 | 
            +
                      combined[matching_move].push(m.to)
         | 
| 37 | 
            +
                    else
         | 
| 38 | 
            +
                      combined.push([m.from, m.to])
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    combined
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  combined_data.map { |legs| JustBackgammon::CombinedMove.new(legs: legs) }
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # For any of the combined moves, checks if there is one with more two legs or more.
         | 
| 48 | 
            +
                #
         | 
| 49 | 
            +
                # @return [Boolean]
         | 
| 50 | 
            +
                def piece_moves_multiple_times?
         | 
| 51 | 
            +
                  combined_moves.any? { |c| c.size > 2 }
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # Checks if any move have no points.
         | 
| 55 | 
            +
                #
         | 
| 56 | 
            +
                # @return [Boolean]
         | 
| 57 | 
            +
                def any_missing_point?
         | 
| 58 | 
            +
                  moves.any? { |m| m.missing_point? }
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                # Checks if any move have empty points.
         | 
| 62 | 
            +
                #
         | 
| 63 | 
            +
                # @return [Boolean]
         | 
| 64 | 
            +
                def any_point_empty?
         | 
| 65 | 
            +
                  combined_moves.any? { |m| m.from_point? && m.empty? }
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                # Checks if any move have is owned by the opponent.
         | 
| 69 | 
            +
                #
         | 
| 70 | 
            +
                # @return [Boolean]
         | 
| 71 | 
            +
                def any_point_owned_by_opponent?(current_player_number)
         | 
| 72 | 
            +
                  combined_moves.any? { |m| m.from_point? && m.owned_by_opponent?(current_player_number) }
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                # Checks if any move is from an empty bar.
         | 
| 76 | 
            +
                #
         | 
| 77 | 
            +
                # @return [Boolean]
         | 
| 78 | 
            +
                def any_bar_empty_for_player?(current_player_number)
         | 
| 79 | 
            +
                  moves.any? { |m| m.from_bar? && m.empty_for_player?(current_player_number) }
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                # Checks if any move is blocked from moving.
         | 
| 83 | 
            +
                #
         | 
| 84 | 
            +
                # @return [Boolean]
         | 
| 85 | 
            +
                def any_blocked?(current_player_number)
         | 
| 86 | 
            +
                  moves.any? { |m| m.blocked?(current_player_number) }
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                # Checks if any move is going the wrong direction.
         | 
| 90 | 
            +
                #
         | 
| 91 | 
            +
                # @return [Boolean]
         | 
| 92 | 
            +
                def any_wrong_direction?(current_player_number)
         | 
| 93 | 
            +
                  moves.any? { |m| m.wrong_direction?(current_player_number) }
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                # Checks if any move is bearing off.
         | 
| 97 | 
            +
                #
         | 
| 98 | 
            +
                # @return [Boolean]
         | 
| 99 | 
            +
                def any_bear_off?
         | 
| 100 | 
            +
                  moves.any? { |m| m.bear_off? }
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                # Checks if all moves are from the bar.
         | 
| 104 | 
            +
                #
         | 
| 105 | 
            +
                # @return [Boolean]
         | 
| 106 | 
            +
                def all_moves_from_bar?
         | 
| 107 | 
            +
                  moves.all? { |m| m.from_bar? }
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                # The number of moves from the bar.
         | 
| 111 | 
            +
                #
         | 
| 112 | 
            +
                # @return [Fixnum]
         | 
| 113 | 
            +
                def number_of_moves_from_bar
         | 
| 114 | 
            +
                  moves.select { |m| m.from_bar? }.size
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                # How far each of the moves go.
         | 
| 118 | 
            +
                #
         | 
| 119 | 
            +
                # @return [Array<Fixnum>]
         | 
| 120 | 
            +
                def absolute_distances(current_player_number)
         | 
| 121 | 
            +
                  moves.map { |m| m.absolute_distance_for_player(current_player_number) }
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                # Checks if any of the moves don't match the dice rolls
         | 
| 125 | 
            +
                #
         | 
| 126 | 
            +
                # @return [Boolean]
         | 
| 127 | 
            +
                def dice_mismatch?(current_player_number, dice)
         | 
| 128 | 
            +
                  unallocated = dice.numbers
         | 
| 129 | 
            +
                  allocated = []
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                  moves.each do |m|
         | 
| 132 | 
            +
                    move_distance = m.absolute_distance_for_player(current_player_number)
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                    index = unallocated.index do |d|
         | 
| 135 | 
            +
                      if m.bear_off?
         | 
| 136 | 
            +
                        d >= move_distance
         | 
| 137 | 
            +
                      else
         | 
| 138 | 
            +
                        d == move_distance
         | 
| 139 | 
            +
                      end
         | 
| 140 | 
            +
                    end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                    if index
         | 
| 143 | 
            +
                      die = unallocated.delete_at(index)
         | 
| 144 | 
            +
                      allocated.push(die)
         | 
| 145 | 
            +
                    end
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                  allocated.size != moves.size
         | 
| 149 | 
            +
                end
         | 
| 150 | 
            +
              end
         | 
| 151 | 
            +
            end
         | 
| @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            require 'just_backgammon/off_board'
         | 
| 2 | 
            +
            require 'just_backgammon/piece'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module JustBackgammon
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # = OffBoard
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # The off board is where pieces go when bearing off. Contains an array of pieces.
         | 
| 9 | 
            +
              class OffBoard
         | 
| 10 | 
            +
                extend Common
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                # A new instance of OffBoard.
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # @param [Array<Hash>] pieces
         | 
| 15 | 
            +
                #   All the pieces off board, each piece has an owner.
         | 
| 16 | 
            +
                #
         | 
| 17 | 
            +
                # ==== Example:
         | 
| 18 | 
            +
                #   # Instantiates a new OffBoard
         | 
| 19 | 
            +
                #   JustBackgammon::OffBoard.new({
         | 
| 20 | 
            +
                #     pieces: [{owner: 1}, {owner: 1}]
         | 
| 21 | 
            +
                #   })
         | 
| 22 | 
            +
                def initialize(pieces:)
         | 
| 23 | 
            +
                  @pieces = Piece.load(pieces)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                # @return [Array<Piece>] all the pieces on the bar, each piece has an owner
         | 
| 27 | 
            +
                attr_reader :pieces
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                # The identifier of the bar, returns the string 'bar'.
         | 
| 30 | 
            +
                #
         | 
| 31 | 
            +
                # @return [String]
         | 
| 32 | 
            +
                def number
         | 
| 33 | 
            +
                  'off_board'
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                # ALl the pieces owned by the specified player.
         | 
| 37 | 
            +
                #
         | 
| 38 | 
            +
                # @param [Fixnum] player_number
         | 
| 39 | 
            +
                #   the specified player number.
         | 
| 40 | 
            +
                #
         | 
| 41 | 
            +
                # @return [Array<Piece>]
         | 
| 42 | 
            +
                def pieces_owned_by_player(player_number)
         | 
| 43 | 
            +
                  pieces.select { |p| p.owner == player_number }
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                # Number of pieces owned by the specified player.
         | 
| 47 | 
            +
                #
         | 
| 48 | 
            +
                # @param [Fixnum] player_number
         | 
| 49 | 
            +
                #   the specified player number.
         | 
| 50 | 
            +
                #
         | 
| 51 | 
            +
                # @return [Fixnum]
         | 
| 52 | 
            +
                def number_of_pieces_owned_by_player(player_number)
         | 
| 53 | 
            +
                  pieces_owned_by_player(player_number).size
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # Adds a piece off board.
         | 
| 57 | 
            +
                #
         | 
| 58 | 
            +
                # @param [Piece] piece
         | 
| 59 | 
            +
                #   the piece to push off board.
         | 
| 60 | 
            +
                #
         | 
| 61 | 
            +
                # @return [Array<Piece>]
         | 
| 62 | 
            +
                def push(piece)
         | 
| 63 | 
            +
                  @pieces.push(piece)
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                # A hashed serialized representation of off board.
         | 
| 67 | 
            +
                #
         | 
| 68 | 
            +
                # @return [Hash]
         | 
| 69 | 
            +
                def as_json
         | 
| 70 | 
            +
                  { pieces: pieces.map(&:as_json) }
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            require 'just_backgammon/common'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module JustBackgammon
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              # = Piece
         | 
| 6 | 
            +
              #
         | 
| 7 | 
            +
              # A piece owned by a player that moves around the board.
         | 
| 8 | 
            +
              class Piece
         | 
| 9 | 
            +
                extend Common
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # A new instance of Piece.
         | 
| 12 | 
            +
                #
         | 
| 13 | 
            +
                # @param [Fixnum] owner
         | 
| 14 | 
            +
                #   The owner of the piece.
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # ==== Example:
         | 
| 17 | 
            +
                #   # Instantiates a new Piece
         | 
| 18 | 
            +
                #   JustBackgammon::Piece.new(1)
         | 
| 19 | 
            +
                def initialize(owner:)
         | 
| 20 | 
            +
                  @owner = owner
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                # @return [Fixnum] the owner of the piece
         | 
| 24 | 
            +
                attr_reader :owner
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                # A hashed serialized representation of the piece.
         | 
| 27 | 
            +
                #
         | 
| 28 | 
            +
                # @return [Hash]
         | 
| 29 | 
            +
                def as_json
         | 
| 30 | 
            +
                  { owner: owner }
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            require 'just_backgammon/common'
         | 
| 2 | 
            +
            require 'just_backgammon/piece'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module JustBackgammon
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # = Point
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # A point where pieces can land on. Each one has a number.
         | 
| 9 | 
            +
              class Point
         | 
| 10 | 
            +
                extend Common
         | 
| 11 | 
            +
                extend Forwardable
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                # A new instance of Point.
         | 
| 14 | 
            +
                #
         | 
| 15 | 
            +
                # @param [Array<Hash>] pieces
         | 
| 16 | 
            +
                #   All the pieces on this point.
         | 
| 17 | 
            +
                #
         | 
| 18 | 
            +
                # @param [Fixnum] number
         | 
| 19 | 
            +
                #   The point number and identifier.
         | 
| 20 | 
            +
                #
         | 
| 21 | 
            +
                # ==== Example:
         | 
| 22 | 
            +
                #   # Instantiates a new Point
         | 
| 23 | 
            +
                #   JustBackgammon::Point.new({
         | 
| 24 | 
            +
                #     pieces: [{owner: 1}, {owner: 1}],
         | 
| 25 | 
            +
                #     number: 1
         | 
| 26 | 
            +
                #   })
         | 
| 27 | 
            +
                def initialize(pieces: , number:)
         | 
| 28 | 
            +
                  @pieces = JustBackgammon::Piece.load(pieces)
         | 
| 29 | 
            +
                  @number = number
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                # @return [Array<Piece>] all the pieces on this point
         | 
| 33 | 
            +
                attr_reader :pieces
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                # @return [Fixnum] the point number and identifier
         | 
| 36 | 
            +
                attr_reader :number
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def_delegator :pieces, :size
         | 
| 39 | 
            +
                def_delegator :pieces, :empty?
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                # Removes a piece and returns it.
         | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # @return [Piece,NilClass]
         | 
| 44 | 
            +
                def pop
         | 
| 45 | 
            +
                  @pieces.pop
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Adds a piece to the point.
         | 
| 49 | 
            +
                #
         | 
| 50 | 
            +
                # @return [Array<Piece>]
         | 
| 51 | 
            +
                def push(piece)
         | 
| 52 | 
            +
                  @pieces.push(piece)
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                # Checks if point has pieces owned by the specified player.
         | 
| 56 | 
            +
                #
         | 
| 57 | 
            +
                # @return [Boolean]
         | 
| 58 | 
            +
                def owned_by_player?(player_number)
         | 
| 59 | 
            +
                  pieces.any? { |p| p.owner == player_number }
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                # Checks if point has pieces owned by the opponent of the specified player.
         | 
| 63 | 
            +
                #
         | 
| 64 | 
            +
                # @return [Boolean]
         | 
| 65 | 
            +
                def owned_by_opponent?(player_number)
         | 
| 66 | 
            +
                  pieces.any? { |p| p.owner != player_number }
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                # Checks if point has more than one piece.
         | 
| 70 | 
            +
                #
         | 
| 71 | 
            +
                # @return [Boolean]
         | 
| 72 | 
            +
                def blocked?
         | 
| 73 | 
            +
                  size > 1
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                # Checks if point has only one piece.
         | 
| 77 | 
            +
                #
         | 
| 78 | 
            +
                # @return [Boolean]
         | 
| 79 | 
            +
                def blot?
         | 
| 80 | 
            +
                  size == 1
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                # Checks if point is a home point for specified player.
         | 
| 84 | 
            +
                #
         | 
| 85 | 
            +
                # @return [Boolean]
         | 
| 86 | 
            +
                def home?(player_number)
         | 
| 87 | 
            +
                  case player_number
         | 
| 88 | 
            +
                  when 1
         | 
| 89 | 
            +
                    (19..24).include?(number)
         | 
| 90 | 
            +
                  when 2
         | 
| 91 | 
            +
                    (1..6).include?(number)
         | 
| 92 | 
            +
                  else
         | 
| 93 | 
            +
                    true
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                # A hashed serialized representation of the bar.
         | 
| 98 | 
            +
                #
         | 
| 99 | 
            +
                # @return [Hash]
         | 
| 100 | 
            +
                def as_json
         | 
| 101 | 
            +
                  { number: number, pieces: pieces.map(&:as_json) }
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
            end
         | 
| @@ -0,0 +1,95 @@ | |
| 1 | 
            +
            require 'just_backgammon/common'
         | 
| 2 | 
            +
            require 'just_backgammon/point'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module JustBackgammon
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # = PointSet
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # A collection of points.
         | 
| 9 | 
            +
              class PointSet
         | 
| 10 | 
            +
                extend Common
         | 
| 11 | 
            +
                extend Forwardable
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                # A new instance of Bar.
         | 
| 14 | 
            +
                #
         | 
| 15 | 
            +
                # @param [Array<Hash>] points
         | 
| 16 | 
            +
                #   All the points in the set.
         | 
| 17 | 
            +
                #
         | 
| 18 | 
            +
                # ==== Example:
         | 
| 19 | 
            +
                #   # Instantiates a new PointSet
         | 
| 20 | 
            +
                #   JustBackgammon::PointSet.new({
         | 
| 21 | 
            +
                #     points: [point_a, point_b]
         | 
| 22 | 
            +
                #   })
         | 
| 23 | 
            +
                def initialize(points:)
         | 
| 24 | 
            +
                  @points = Point.load(points)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                # @return [Array<Point>] all the points in the set
         | 
| 28 | 
            +
                attr_reader :points
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def_delegator :points, :map
         | 
| 31 | 
            +
                def_delegator :points, :any?
         | 
| 32 | 
            +
                def_delegator :points, :size
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                # Finds a point with the matching number.
         | 
| 35 | 
            +
                #
         | 
| 36 | 
            +
                # @return [Point]
         | 
| 37 | 
            +
                def find_by_number(number)
         | 
| 38 | 
            +
                  points.find { |p| p.number == number }
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                # Finds all points with pieces that are not yet home for the specified player.
         | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # @return [PointSet]
         | 
| 44 | 
            +
                def not_home(player_number)
         | 
| 45 | 
            +
                  not_home_points = points.select { |p| p.owned_by_player?(player_number) && !p.home?(player_number) }
         | 
| 46 | 
            +
                  self.class.new(points: not_home_points)
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                # Checks if any pieces are not yet home for the specified player.
         | 
| 50 | 
            +
                #
         | 
| 51 | 
            +
                # @return [Boolean]
         | 
| 52 | 
            +
                def some_pieces_not_home?(player_number)
         | 
| 53 | 
            +
                  not_home(player_number).any?
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # Finds all points owned by the specified player.
         | 
| 57 | 
            +
                #
         | 
| 58 | 
            +
                # @return [PointSet]
         | 
| 59 | 
            +
                def owned_by_player(player_number)
         | 
| 60 | 
            +
                  owned = @points.select { |p| p.owned_by_player?(player_number) }
         | 
| 61 | 
            +
                  self.class.new(points: owned)
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                # Finds all destinations points from a point with a dice roll for the specified player.
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                # @return [PointSet]
         | 
| 67 | 
            +
                def destinations(from, dice, player_number)
         | 
| 68 | 
            +
                  in_range = dice.map { |d| destination(from, d, player_number) }.compact
         | 
| 69 | 
            +
                  possible = in_range.select { |p| p.empty? || p.owned_by_player?(player_number) || p.blot? }
         | 
| 70 | 
            +
                  self.class.new(points: possible)
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                # A hashed serialized representation of the bar.
         | 
| 74 | 
            +
                #
         | 
| 75 | 
            +
                # @return [Hash]
         | 
| 76 | 
            +
                def as_json
         | 
| 77 | 
            +
                  points.map(&:as_json)
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                private
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                def destination(from, die, player_number)  # :nodoc:
         | 
| 83 | 
            +
                  case player_number
         | 
| 84 | 
            +
                  when 1
         | 
| 85 | 
            +
                    from_number = from.instance_of?(Bar) ? 0 : from.number
         | 
| 86 | 
            +
                    find_by_number(from_number + die.number)
         | 
| 87 | 
            +
                  when 2
         | 
| 88 | 
            +
                    from_number = from.instance_of?(Bar) ? 25 : from.number
         | 
| 89 | 
            +
                    find_by_number(from_number - die.number)
         | 
| 90 | 
            +
                  else
         | 
| 91 | 
            +
                    nil
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,123 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: just_backgammon
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Mark Humphreys
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: exe
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2016-09-19 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.11'
         | 
| 20 | 
            +
              type: :development
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '1.11'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rake
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '10.0'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '10.0'
         | 
| 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.0'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - "~>"
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '5.0'
         | 
| 55 | 
            +
            description: Provides a representation of a backgammon game complete with rules enforcement
         | 
| 56 | 
            +
              and serialisation.
         | 
| 57 | 
            +
            email:
         | 
| 58 | 
            +
            - mark@mrlhumphreys.com
         | 
| 59 | 
            +
            executables: []
         | 
| 60 | 
            +
            extensions: []
         | 
| 61 | 
            +
            extra_rdoc_files: []
         | 
| 62 | 
            +
            files:
         | 
| 63 | 
            +
            - ".gitignore"
         | 
| 64 | 
            +
            - ".travis.yml"
         | 
| 65 | 
            +
            - CODE_OF_CONDUCT.md
         | 
| 66 | 
            +
            - Gemfile
         | 
| 67 | 
            +
            - LICENSE.txt
         | 
| 68 | 
            +
            - README.md
         | 
| 69 | 
            +
            - Rakefile
         | 
| 70 | 
            +
            - bin/console
         | 
| 71 | 
            +
            - bin/setup
         | 
| 72 | 
            +
            - just_backgammon.gemspec
         | 
| 73 | 
            +
            - lib/just_backgammon.rb
         | 
| 74 | 
            +
            - lib/just_backgammon/bar.rb
         | 
| 75 | 
            +
            - lib/just_backgammon/combined_move.rb
         | 
| 76 | 
            +
            - lib/just_backgammon/common.rb
         | 
| 77 | 
            +
            - lib/just_backgammon/dice_set.rb
         | 
| 78 | 
            +
            - lib/just_backgammon/die.rb
         | 
| 79 | 
            +
            - lib/just_backgammon/errors/bear_off_error.rb
         | 
| 80 | 
            +
            - lib/just_backgammon/errors/blocked_error.rb
         | 
| 81 | 
            +
            - lib/just_backgammon/errors/dice_mismatch_error.rb
         | 
| 82 | 
            +
            - lib/just_backgammon/errors/empty_bar_error.rb
         | 
| 83 | 
            +
            - lib/just_backgammon/errors/empty_point_error.rb
         | 
| 84 | 
            +
            - lib/just_backgammon/errors/moves_possible_error.rb
         | 
| 85 | 
            +
            - lib/just_backgammon/errors/not_players_turn_error.rb
         | 
| 86 | 
            +
            - lib/just_backgammon/errors/pieces_on_bar_error.rb
         | 
| 87 | 
            +
            - lib/just_backgammon/errors/point_not_found_error.rb
         | 
| 88 | 
            +
            - lib/just_backgammon/errors/point_ownership_error.rb
         | 
| 89 | 
            +
            - lib/just_backgammon/errors/wrong_direction_error.rb
         | 
| 90 | 
            +
            - lib/just_backgammon/errors/wrong_phase_error.rb
         | 
| 91 | 
            +
            - lib/just_backgammon/game_state.rb
         | 
| 92 | 
            +
            - lib/just_backgammon/move.rb
         | 
| 93 | 
            +
            - lib/just_backgammon/move_list.rb
         | 
| 94 | 
            +
            - lib/just_backgammon/off_board.rb
         | 
| 95 | 
            +
            - lib/just_backgammon/piece.rb
         | 
| 96 | 
            +
            - lib/just_backgammon/point.rb
         | 
| 97 | 
            +
            - lib/just_backgammon/point_set.rb
         | 
| 98 | 
            +
            - lib/just_backgammon/version.rb
         | 
| 99 | 
            +
            homepage: https://github.com/mrlhumphreys/just_backgammon
         | 
| 100 | 
            +
            licenses:
         | 
| 101 | 
            +
            - MIT
         | 
| 102 | 
            +
            metadata: {}
         | 
| 103 | 
            +
            post_install_message: 
         | 
| 104 | 
            +
            rdoc_options: []
         | 
| 105 | 
            +
            require_paths:
         | 
| 106 | 
            +
            - lib
         | 
| 107 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 108 | 
            +
              requirements:
         | 
| 109 | 
            +
              - - ">="
         | 
| 110 | 
            +
                - !ruby/object:Gem::Version
         | 
| 111 | 
            +
                  version: '2.1'
         | 
| 112 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 113 | 
            +
              requirements:
         | 
| 114 | 
            +
              - - ">="
         | 
| 115 | 
            +
                - !ruby/object:Gem::Version
         | 
| 116 | 
            +
                  version: '0'
         | 
| 117 | 
            +
            requirements: []
         | 
| 118 | 
            +
            rubyforge_project: 
         | 
| 119 | 
            +
            rubygems_version: 2.5.1
         | 
| 120 | 
            +
            signing_key: 
         | 
| 121 | 
            +
            specification_version: 4
         | 
| 122 | 
            +
            summary: A backgammon engine written in ruby
         | 
| 123 | 
            +
            test_files: []
         |