1 require 'games/chess/san'
7 def initialize(rep, validator_factory,
8 move_factory, piece_factory,
11 @validator = validator_factory
13 @piece = piece_factory
17 def serialize(move, ref)
20 ysize = ref.board.size.y
21 result = move.src.to_coord(ysize) + move.dst.to_coord(ysize)
22 result += '=' + @piece.symbol(move.promotion) if move.promotion
25 san move, ref, lambda{|t| @piece.symbol(t) }
27 san move, ref, lambda{|t| "{#{t.to_s}}" }
31 def deserialize(s, ref)
32 notation = @notation.read(s)
33 read_san ref, notation if notation
36 def read_san(ref, san)
38 return candidate unless san[:dst] or san[:castling]
39 validate = @validator.new(ref)
42 # find king starting position
43 src = Point.new(ref.board.size.x / 2, ref.row(0, ref.turn))
44 dst = src + (san[:castling] == :king ? Point.new(2, 0) : Point.new(-2, 0))
46 return candidate unless king.type == :king
47 candidate = @move.new(src, dst)
48 candidate if validate[candidate]
49 elsif san[:src] and san[:src].x and san[:src].y
50 mv = @move.new(san[:src], san[:dst], :promotion => san[:promotion])
53 ref.board.each_square do |p|
54 mv = @move.new(p, san[:dst], :promotion => san[:promotion])
56 if p =~ san[:src] and piece and
57 piece.type == san[:type] and
58 piece.color == ref.turn
73 def san(move, ref, sym)
74 piece = ref.board[move.src]
76 return "" unless piece
77 return "0-0" if move.type == :king_side_castling
78 return "0-0-0" if move.type == :queen_side_castling
80 capture_square = ref.capture_square(move)
81 captured = ref.board[capture_square]
84 ysize = ref.board.size.y
86 if piece.type == :pawn
88 result = Point.new(move.src.x, nil).to_coord(ysize) + 'x'
92 result += move.dst.to_coord(ysize)
94 result = sym[piece.type]
95 san = minimal_notation ref,
100 result += san[:src].to_coord(ysize) if san[:src]
101 result += 'x' if captured
102 result += san[:dst].to_coord(ysize)
106 result += '=' + sym[move.promotion]
112 def minimal_notation(ref, san)
113 @notation.each_alternative(san) do |alternative|
114 return alternative if read_san(ref, alternative)