Add licence and installation instructions.
[kaya.git] / lib / games / shogi / serializer.rb
blobdef4786bffee8cab8a17d9f561a08b399436f6ac
1 # Copyright (c) 2009 Paolo Capriotti <p.capriotti@gmail.com>
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 module Shogi
10 class Serializer
11   def initialize(rep, validator_factory, 
12                  move_factory, piece_factory, notation)
13     @rep = rep
14     @validator = validator_factory
15     @move = move_factory
16     @piece = piece_factory
17     @notation = notation
18   end
19   
20   def serialize(move, ref)
21     case @rep
22     when :simple
23       dst = @notation.point_to_coord(move.dst)
24       result = if move.dropped
25         @piece.symbol(move.dropped.type) + '*' + dst
26       else
27         @notation.point_to_coord(move.src) + dst
28       end
29       result += '+' if move.promote?
30       result
31     when :compact
32       compact move, ref, lambda{|t| @piece.symbol(t) }
33     when :decorated
34       compact move, ref, lambda{|t| "{#{t.to_s}}" }
35     end
36   end
37   
38   def deserialize(s, ref)
39     notation = @notation.read(s)
40     read_notation ref, notation if notation
41   end
42   
43   def compact(move, ref, sym)
44     result = nil
45     if move.dropped
46       result = sym[move.dropped.type] + '*' + 
47       @notation.point_to_coord(move.dst)
48     else
49       piece = ref.board[move.src]
50       
51       capture_square = ref.capture_square(move)
52       captured = ref.board[capture_square]
53     
54       result = sym[piece.type]
55       notation = minimal_notation ref,
56         :src => move.src,
57         :dst => move.dst,
58         :type => piece.type,
59         :promote => move.promote?
60       
61       result += @notation.point_to_coord(notation[:src]) if notation[:src]
62       result += (captured ? 'x' : '-')
63       result += @notation.point_to_coord(notation[:dst])
64       result
65     end
66     
67     if move.promote?
68       result += '+'
69     else
70       validate = @validator.new(ref)
71       alt = @move.new(move.src, move.dst, :promote => true)
72       if validate[alt]
73         result += '='
74       end
75     end
76     
77     result
78   end
79   
80   def read_notation(ref, san)
81     candidate = nil
82     validate = @validator.new(ref)
84     if san[:src]
85       mv = @move.new(san[:src], san[:dst], :promote => san[:promote])
86       mv if validate[mv]
87     elsif san[:drop]
88       mv = @move.drop(@piece.new(ref.turn, san[:type]), san[:dst])
89       mv if validate[mv]
90     else
91       ref.board.each_square do |p|
92         mv = @move.new(p, san[:dst], :promote => san[:promote])
93         piece = ref.board[p]
94         if piece and 
95            piece.type == san[:type] and
96            piece.color == ref.turn
97           if validate[mv]
98             if candidate
99               # ambiguous!
100               return nil
101             else
102               candidate = mv
103             end
104           end
105         end
106       end
107       candidate
108     end
109   end
110   
111   def minimal_notation(ref, notation)
112     @notation.each_alternative(notation) do |alternative|
113       return alternative if read_notation(ref, alternative)
114     end
115     
116     notation
117   end