Add shogi serializer.
[kaya.git] / lib / games / chess / san.rb
blob987785575ed01f5910542006a3d1799983fd291e
1 require 'strscan'
3 module Chess
5 class SAN
6   def initialize(piece_factory, size)
7     @piece_factory = piece_factory
8     @size = size
9   end
11   def from_scanner(scanner)
12     if scanner.scan(/([PRNBKQ])?([a-wyzA-Z]?\d*|x\d+)([-x@])?([a-zA-Z]\d+)(=?([RNBKQrnbkq]))?[+#]?[\?!]*/)
13       { :type => @piece_factory.type_from_symbol(scanner[1] || 'P'),
14         :drop => drop = scanner[3] == '@',
15         :src => (Point.from_coord(scanner[2], @size.y) unless drop),
16         :dst => Point.from_coord(scanner[4], @size.y),
17         :promotion => (@piece_factory.type_from_symbol(scanner[6]) if scanner[6]) }
18     elsif scanner.scan(/^[oO0]-?[oO0]-?[oO0][+#]?/)
19       { :castling => :queen }
20     elsif scanner.scan(/[oO0]-?[oO0][+#]?/)
21       { :castling => :king }
22     else
23       scanner.scan(/none/) # possibly consume 'none'
24       { }
25     end
26   end
27   
28   def from_s(str)
29     from_scanner(StringScanner.new(str))
30   end
31   
32   def read(input)
33     case input
34     when String
35       from_s(input)
36     else
37       from_scanner(input)
38     end
39   end
40   
41   def each_alternative(san)
42     # try notation without starting point
43     yield san.dup.tap{|s| s[:src] = nil }
45     # add row indication
46     yield san.dup.tap{|s| s[:src] = Point.new(s[:src].x, nil) }
47     
48     # add column indication
49     yield san.dup.tap{|s| s[:src] = Point.new(nil, s[:src].y) }
50   end
51 end
53 end