Class: Sashite::Pmn::Move

Inherits:
Object
  • Object
show all
Defined in:
lib/sashite/pmn/move.rb

Overview

Represents a complete move in PMN notation.

A Move is a sequence of zero or more atomic actions described by a flat list of elements:

[]                               # pass move (empty array)
[source, destination]            # inferred piece
[source, destination, piece]     # explicit QPI piece

Valid lengths:

- 0 (pass move)
- multiple of 3 OR multiple of 3 + 2 (minimum 2 for non-pass moves)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*pmn_elements) ⇒ Move

Create a Move from PMN elements (variadic only).

Examples:

Move.new("e2","e4","C:P")    # Standard move
Move.new("e2","e4")          # Inferred piece
Move.new                     # Pass move (no arguments)

Parameters:

  • pmn_elements (Array<String>)

    passed as individual args

Raises:

  • (Error::Move)

    if called with a single Array or if invalid



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/sashite/pmn/move.rb', line 35

def initialize(*pmn_elements)
  # single-array form is intentionally not supported (entropy reduction)
  if pmn_elements.size == 1 && pmn_elements.first.is_a?(::Array)
    raise Error::Move,
          'PMN must be passed as individual arguments, e.g. Move.new("e2","e4","C:P")'
  end

  validate_array!(pmn_elements)
  @pmn_array = pmn_elements.dup.freeze
  @actions   = parse_actions(@pmn_array).freeze
  validate_actions!
  freeze
end

Instance Attribute Details

#actionsArray<Action> (readonly)

Returns ordered sequence of actions (empty for pass moves).

Returns:

  • (Array<Action>)

    ordered sequence of actions (empty for pass moves)



21
22
23
# File 'lib/sashite/pmn/move.rb', line 21

def actions
  @actions
end

#pmn_arrayArray<String> (readonly)

Returns original PMN elements (frozen, empty for pass moves).

Returns:

  • (Array<String>)

    original PMN elements (frozen, empty for pass moves)



24
25
26
# File 'lib/sashite/pmn/move.rb', line 24

def pmn_array
  @pmn_array
end

Class Method Details

.from_actions(actions) ⇒ Move

Build a move from Action objects.

Parameters:

Returns:



176
177
178
179
# File 'lib/sashite/pmn/move.rb', line 176

def self.from_actions(actions)
  pmn = actions.flat_map(&:to_a)
  new(*pmn)
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Returns equality by original PMN elements.

Parameters:

  • other (Object)

Returns:

  • (Boolean)

    equality by original PMN elements



142
143
144
145
146
# File 'lib/sashite/pmn/move.rb', line 142

def ==(other)
  return false unless other.is_a?(Move)

  pmn_array == other.pmn_array
end

#board_movesArray<Action>

Returns only board-to-board actions.

Returns:

  • (Array<Action>)

    only board-to-board actions



107
108
109
# File 'lib/sashite/pmn/move.rb', line 107

def board_moves
  actions.select(&:board_to_board?)
end

#compound?Boolean

Returns multiple actions?.

Returns:

  • (Boolean)

    multiple actions?



69
70
71
# File 'lib/sashite/pmn/move.rb', line 69

def compound?
  actions.size > 1
end

#destinationsArray<String>

Returns unique destinations.

Returns:

  • (Array<String>)

    unique destinations



117
118
119
# File 'lib/sashite/pmn/move.rb', line 117

def destinations
  actions.map(&:destination).uniq
end

#empty?Boolean

Returns true if no actions (pass move).

Returns:

  • (Boolean)

    true if no actions (pass move)



90
91
92
# File 'lib/sashite/pmn/move.rb', line 90

def empty?
  actions.empty?
end

#first_actionAction?

Returns:



74
75
76
# File 'lib/sashite/pmn/move.rb', line 74

def first_action
  actions.first
end

#has_captures?Boolean

Returns any capture?.

Returns:

  • (Boolean)

    any capture?



102
103
104
# File 'lib/sashite/pmn/move.rb', line 102

def has_captures?
  actions.any?(&:capture?)
end

#has_drops?Boolean

Returns any drop?.

Returns:

  • (Boolean)

    any drop?



97
98
99
# File 'lib/sashite/pmn/move.rb', line 97

def has_drops?
  actions.any?(&:drop?)
end

#has_inferred?Boolean

Returns true if any action has inferred piece.

Returns:

  • (Boolean)

    true if any action has inferred piece



127
128
129
# File 'lib/sashite/pmn/move.rb', line 127

def has_inferred?
  actions.any?(&:inferred?)
end

#hashInteger

Returns:

  • (Integer)


150
151
152
# File 'lib/sashite/pmn/move.rb', line 150

def hash
  pmn_array.hash
end

#inspectString

Returns:

  • (String)


155
156
157
158
159
160
161
# File 'lib/sashite/pmn/move.rb', line 155

def inspect
  if pass?
    "#<#{self.class.name} pass=true>"
  else
    "#<#{self.class.name} actions=#{actions.size} pmn=#{pmn_array.inspect}>"
  end
end

#last_actionAction?

Returns:



79
80
81
# File 'lib/sashite/pmn/move.rb', line 79

def last_action
  actions.last
end

#pass?Boolean

Returns is this a pass move (no actions)?.

Returns:

  • (Boolean)

    is this a pass move (no actions)?



59
60
61
# File 'lib/sashite/pmn/move.rb', line 59

def pass?
  actions.empty?
end

#piecesArray<String>

Returns unique specified pieces (excludes inferred).

Returns:

  • (Array<String>)

    unique specified pieces (excludes inferred)



122
123
124
# File 'lib/sashite/pmn/move.rb', line 122

def pieces
  actions.filter_map(&:piece).uniq
end

#simple?Boolean

Returns exactly one action?.

Returns:

  • (Boolean)

    exactly one action?



64
65
66
# File 'lib/sashite/pmn/move.rb', line 64

def simple?
  actions.size == 1
end

#sizeInteger Also known as: length

Returns number of actions (0 for pass moves).

Returns:

  • (Integer)

    number of actions (0 for pass moves)



84
85
86
# File 'lib/sashite/pmn/move.rb', line 84

def size
  actions.size
end

#sourcesArray<String>

Returns unique sources.

Returns:

  • (Array<String>)

    unique sources



112
113
114
# File 'lib/sashite/pmn/move.rb', line 112

def sources
  actions.map(&:source).uniq
end

#to_aArray<String>

Returns copy of original PMN elements (empty array for pass moves).

Returns:

  • (Array<String>)

    copy of original PMN elements (empty array for pass moves)



134
135
136
# File 'lib/sashite/pmn/move.rb', line 134

def to_a
  pmn_array.dup
end

#valid?Boolean

Returns true if PMN length is valid and all actions are valid.

Returns:

  • (Boolean)

    true if PMN length is valid and all actions are valid



50
51
52
53
54
# File 'lib/sashite/pmn/move.rb', line 50

def valid?
  valid_length? && actions.all?(&:valid?)
rescue ::StandardError
  false
end

#with_actions(actions_to_add) ⇒ Move

Returns new Move with appended actions.

Parameters:

  • actions_to_add (Array<Action>)

    actions to append

Returns:

  • (Move)

    new Move with appended actions



167
168
169
170
# File 'lib/sashite/pmn/move.rb', line 167

def with_actions(actions_to_add)
  combined = pmn_array + actions_to_add.flat_map(&:to_a)
  self.class.new(*combined)
end