Module: Qi::Hands
- Defined in:
- lib/qi/hands.rb
Overview
Pure functions for player hand operations.
A hand is represented as a Hash{String => Integer} mapping each
piece to its count. An empty hand is {}. Entries whose count
reaches zero are removed from the hash.
This representation gives O(1) add, remove, and count queries per piece type, compared to O(n) scans on a flat array.
All functions are stateless and side-effect-free.
Constant Summary collapse
- MAX_PIECE_BYTESIZE =
255
Class Method Summary collapse
-
.apply_diff(hand, hand_count, changes) ⇒ Array(Hash{String => Integer}, Integer)
Applies delta changes to a hand, returning the new hash and its piece count.
Class Method Details
.apply_diff(hand, hand_count, changes) ⇒ Array(Hash{String => Integer}, Integer)
Applies delta changes to a hand, returning the new hash and its piece count.
Each change maps a piece (+String+) to an integer delta: positive to add copies, negative to remove, zero is a no-op. Entries whose count reaches zero are removed from the result.
The piece count is computed incrementally during the diff — no extra iteration over the result hash is needed.
The original hand is not modified.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/qi/hands.rb', line 63 def self.apply_diff(hand, hand_count, changes) result = hand.dup count = hand_count changes.each do |piece_key, delta| unless delta.is_a?(::Integer) raise ::ArgumentError, "delta must be an Integer, got #{delta.class} for piece #{piece_key.inspect}" end next if delta == 0 piece = piece_key.is_a?(::Symbol) ? piece_key.name : piece_key if piece.bytesize > MAX_PIECE_BYTESIZE raise ::ArgumentError, "piece exceeds #{MAX_PIECE_BYTESIZE} bytes (got #{piece.bytesize})" end current = result[piece] || 0 new_count = current + delta if new_count < 0 raise ::ArgumentError, "cannot remove #{piece.inspect}: not found in hand" end if new_count == 0 result.delete(piece) else result[piece] = new_count end count += delta end [result, count] end |