Class: Tak::PTN

Inherits:
Object
  • Object
show all
Defined in:
lib/tak/ptn.rb

Constant Summary collapse

NOTATION_REGEX =
/
  (?<number>\d+)?
  (?<special_piece>[CS])?
  (?<position>[a-h][1-8])
  (
    (?<direction>[<>+-])
    (?<stack>\d+)?
  )?
/xi
KTN_SPECIAL_TO_PTN =
{
  'C' => 'C',
  'W' => 'S',
  nil => ''
}
KTN_PLACEMENT =
'P'
KTN_MOVEMENT =
'M'
PTN_NORTH =
'+'
PTN_SOUTH =
'-'
PTN_RIGHT =
'>'
PTN_LEFT =
'<'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(notation, board_size = 5) ⇒ PTN

Returns a new instance of PTN.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/tak/ptn.rb', line 29

def initialize(notation, board_size = 5)
  @ptn_match  = NOTATION_REGEX.match(notation)
  @board_size = board_size
  @notation   = notation

  if @ptn_match
    @number        = @ptn_match[:number]
    @special_piece = @ptn_match[:special_piece]
    @position      = @ptn_match[:position]
    @direction     = @ptn_match[:direction]
    @stack         = @ptn_match[:stack]
  end

  @errors = []
end

Instance Attribute Details

#directionObject (readonly)

Returns the value of attribute direction.



27
28
29
# File 'lib/tak/ptn.rb', line 27

def direction
  @direction
end

#errorsObject (readonly)

Returns the value of attribute errors.



27
28
29
# File 'lib/tak/ptn.rb', line 27

def errors
  @errors
end

#ptn_matchObject (readonly)

Returns the value of attribute ptn_match.



27
28
29
# File 'lib/tak/ptn.rb', line 27

def ptn_match
  @ptn_match
end

#special_pieceObject (readonly)

Returns the value of attribute special_piece.



27
28
29
# File 'lib/tak/ptn.rb', line 27

def special_piece
  @special_piece
end

Class Method Details

.from_ktn(move) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/tak/ptn.rb', line 123

def self.from_ktn(move)
  move_type, *remainder = move.split(' ')

  ptn_string =
    case move_type
    when KTN_PLACEMENT
      square, special_piece = remainder
      stone = KTN_SPECIAL_TO_PTN[special_piece]

      "#{stone}#{square.downcase}"
    when KTN_MOVEMENT
      from_square, to_square, *distribution = remainder

      from_square_col, from_square_row = from_square.chars
      to_square_col,   to_square_row   = to_square.chars

      direction = if from_square_col == to_square_col
        to_square_row > from_square_row ? PTN_NORTH : PTN_SOUTH
      else
        to_square_col > from_square_col ? PTN_RIGHT : PTN_LEFT
      end

      hand_size = distribution.map(&:to_i).sum

      "#{hand_size}#{from_square.downcase}#{direction}#{distribution.join}"
    else
      ''
    end

  new(ptn_string)
end

Instance Method Details

#above_handsize?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/tak/ptn.rb', line 90

def above_handsize?
  stack_total > @board_size || @number.to_i > @board_size
end

#alpha_rangeObject



119
120
121
# File 'lib/tak/ptn.rb', line 119

def alpha_range
  @alpha_range ||= ('a'..'h').each.with_index(1).zip.flatten(1).to_h
end

#distrubutes_out_of_bounds?Boolean

Returns:

  • (Boolean)


98
99
100
101
# File 'lib/tak/ptn.rb', line 98

def distrubutes_out_of_bounds?
  x + stack_total > @board_size ||
  y.to_i + stack_total > @board_size
end

#error(msg) ⇒ Object



73
74
75
# File 'lib/tak/ptn.rb', line 73

def error(msg)
  @errors << msg
end

#movement_and_placement?Boolean

Placement of a special piece (Capstone or Standing) cannot also be a move

Returns:

  • (Boolean)


78
79
80
# File 'lib/tak/ptn.rb', line 78

def movement_and_placement?
  !!(@special_piece && @number || @direction || @stack)
end

#out_of_bounds?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/tak/ptn.rb', line 94

def out_of_bounds?
  x > @board_size || y.to_i > @board_size
end

#over_stack?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/tak/ptn.rb', line 82

def over_stack?
  stack_total > @number.to_i
end

#positionObject



53
54
55
# File 'lib/tak/ptn.rb', line 53

def position
  [x, y]
end

#sizeObject



69
70
71
# File 'lib/tak/ptn.rb', line 69

def size
  stack_total
end

#stack_totalObject



65
66
67
# File 'lib/tak/ptn.rb', line 65

def stack_total
  @stack_total ||= @stack ? @stack.chars.sum(&:to_i) : 0
end

#to_sObject



45
46
47
# File 'lib/tak/ptn.rb', line 45

def to_s
  "#{@number}#{@special_piece}#{@position}#{@direction}#{@stack}"
end

#typeObject



49
50
51
# File 'lib/tak/ptn.rb', line 49

def type
  @direction ? 'movement' : 'placement'
end

#under_stack?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/tak/ptn.rb', line 86

def under_stack?
  stack_total < @number.to_i
end

#valid?Boolean

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/tak/ptn.rb', line 103

def valid?
  @valid ||= begin
    # Break before we do anything else here.
    error 'Did not match PTN Format' and return false unless @ptn_match

    error 'Cannot move more pieces than the board size!'      if above_handsize?
    error 'Cannot distribute more pieces than were picked up' if over_stack?
    error 'Cannot distribute less pieces than were picked up' if under_stack?
    error 'Cannot move and place a piece'                     if movement_and_placement?
    error 'Cannot place or move a piece out of bounds'        if out_of_bounds?
    error 'Cannot distribute pieces out of bounds'            if distrubutes_out_of_bounds?

    @errors.none?
  end
end

#xObject



61
62
63
# File 'lib/tak/ptn.rb', line 61

def x
  @position.chars.last.to_i - 1
end

#yObject



57
58
59
# File 'lib/tak/ptn.rb', line 57

def y
  alpha_range[@position.chars.first] - 1
end