1 require 'games/validator_base'
4 class Validator < ValidatorBase
15 def validate(move, target = nil)
16 return false unless move.dropped || @state.board.valid?(move.src)
17 return false unless @state.board.valid? move.dst
21 return false unless piece.color == @state.turn
22 return false unless @state.pool(piece.color).has_piece?(piece)
23 return false if @state.board[move.dst]
24 if piece.type == :pawn
25 # pawns cannot be dropped on the last rank
27 move.dst.y == @state.row(@state.board.size.y - 1, piece.color)
28 # do not allow two pawns on the same column
29 return false if (0..@state.board.size.y).
30 map{|y| Point.new(move.dst.x, y) }.
31 any?{|p| @state.board[p]. == piece }
32 elsif piece.type == :horse
33 # horses cannot be dropped on the last or last-but-one rank
35 move.dst.y == @state.row(@state.board.size.y - 1, piece.color) ||
36 move.dst.y == @state.row(@state.board.size.y - 2, piece.color)
39 piece = @state.board[move.src]
40 return false unless piece and piece.color == @state.turn
41 return false unless check_pseudolegality(piece, target, move)
45 @state.try(move) do |tmp|
46 validator = self.class.new(tmp)
47 legal = validator.check_legality(piece, target, move)
48 return false unless legal
54 def validator_method(type)
56 if @state.promoted_type?(type)
57 m = super(:gold) unless respond_to?(m)
64 def check_pseudolegality(piece, target, move)
66 return false if piece.type == :king or piece.type == :gold
68 @state.in_promotion_zone?(move.src, piece.color) ||
69 @state.in_promotion_zone?(move.dst, piece.color)
71 return false if @state.promoted?(piece)
73 # check for cases when it is mandatory to promote
76 return false if move.dst.y == @state.row(@state.board.size.y - 1, piece.color)
79 move.dst.y == @state.row(@state.board.size.y - 1, piece.color) ||
80 move.dst.y == @state.row(@state.board.size.y - 2, piece.color)
83 super(piece, target, move)
86 def validate_pawn(piece, target, move)
87 move.delta == @state.direction(piece.color)
90 def validate_lance(piece, target, move)
92 move.delta.y.unit == @state.direction(piece.color).y and
93 @state.board.clear_path? move.range
96 def validate_horse(piece, target, move)
97 move.delta.x.abs == 1 and
98 move.delta.y == 2 * @state.direction(piece.color).y
101 def validate_silver(piece, target, move)
102 dir = @state.direction(piece.color).y
103 (move.delta.y == dir and move.delta.x.abs <= 1) or
104 (move.delta.x.abs == 1 and move.delta.y == -dir)
107 def validate_gold(piece, target, move)
108 dir = @state.direction(piece.color).y
109 (move.delta.y == dir and move.delta.x.abs <= 1) or
110 move.delta.x.abs + move.delta.y.abs == 1
113 def validate_king(piece, target, move)
114 move.delta.x.abs <= 1 and
115 move.delta.y.abs <= 1
118 def validate_bishop(piece, target, move)
121 @state.board.clear_path? range
124 def validate_rook(piece, target, move)
127 @state.board.clear_path? range
130 def validate_promoted_rook(piece, target, move)
131 validate_king(piece, target, move) ||
132 validate_rook(piece, target, move)
135 def validate_promoted_bishop(piece, target, move)
136 validate_king(piece, target, move) ||
137 validate_bishop(piece, target, move)
140 def each_move(src, dst, target)
141 piece = @state.board[src]
143 moves = [@state.move_factory.new(src, dst)]
144 if @state.in_promotion_zone?(dst, piece.color)
145 moves << @state.move_factory.new(src, dst, :promotion => true)
148 yield m if check_pseudolegality(piece, target, m)