First stake at a minishogi variant.
[kaya/ydirson.git] / lib / plugins / shogi / lib / state.rb
blobf1fc10e1497adc35a08f77cf7a38faa809c884d6
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 require 'games/state_base'
9 require 'point'
10 require_bundle 'shogi', 'type'
12 module Shogi
13   class State < StateBase
14     def initialize(board, pool_factory, move_factory, piece_factory)
15       super(board, move_factory, piece_factory)
16       @pools = to_enum(:each_color).inject({}) do |res, c|
17         res[c] = pool_factory.new
18         res
19       end
20       @turn = :black
21     end
22     
23     def initialize_copy(other)
24       super
25       @pools = to_enum(:each_color).inject({}) do |res, c|
26         res[c] = other.pool(c).dup
27         res
28       end
29     end
30     
31     def pool(color)
32       @pools[color]
33     end
34     
35     def setup
36       each_color do |color|
37         (0...@board.size.x).each do |i|
38           @board[Point.new(i, row(2, color))] = piece_factory.new(color, :pawn)
39         end
40         
41         r = row(0, color)
42         set_piece = lambda do |x, type|
43           @board[Point.new(x, r)] = piece_factory.new(color, type)
44         end
45         set_piece[0, :lance]
46         set_piece[1, :horse]
47         set_piece[2, :silver]
48         set_piece[3, :gold]
49         set_piece[4, :king]
50         set_piece[5, :gold]
51         set_piece[6, :silver]
52         set_piece[7, :horse]
53         set_piece[8, :lance]
54         
55         r = row(1, color)
56         @board[Point.new(r, r)] = piece_factory.new(color, :rook)
57         @board[Point.new(@board.size.x - r - 1, r)] = piece_factory.new(color, :bishop)
58       end
59     end
60     
61     def each_color(&blk)
62       yield :black
63       yield :white
64     end
65     
66     def row(i, color)
67       color == :black ? @board.size.y - 1 - i : i
68     end
69     
70     def col(i, color)
71       color == :black ? i : @board.size.x - 1 - i
72     end
74     def opposite_color(color)
75       color == :black ? :white : :black
76     end
77     
78     def direction(color)
79       Point.new(0, color == :black ? -1 : 1)
80     end
81     
82     def perform!(move)
83       if move.dropped
84         pool(turn).remove(move.dropped)
85         board[move.dst] = move.dropped
86       else
87         captured = basic_move(move)
88         if move.promote?
89           board[move.dst] = promoted(board[move.dst])
90         end
91         
92         if captured
93           piece = piece_factory.new(turn, 
94             Promoted.demote(captured.type))
95           pool(turn).add(piece)
96         end
97       end
98       switch_turn!
99     end
100     
101     def switch_turn!
102       @turn = opposite_color(@turn)
103     end
104     
105     def in_promotion_zone?(p, color)
106       (row(6, color) <=> p.y) != (color == :black ? -1 : 1)
107     end
108     
109     def capture_square(move)
110       move.dst
111     end
112     
113     def promoted(piece)
114       piece_factory.new(
115         piece.color,
116         Promoted.promote(piece.type))
117     end
118   end
121 module MiniShogi
122   class State < Shogi::State
124     def setup
125       each_color do |color|
127         r = row(0, color)
128         set_piece = lambda do |x, type|
129           @board[Point.new(x, r)] = piece_factory.new(color, type)
130         end
131         set_piece[col(0,color), :king]
132         set_piece[col(1,color), :gold]
133         set_piece[col(2,color), :silver]
134         set_piece[col(3,color), :bishop]
135         set_piece[col(4,color), :rook]
137         r = row(1, color)
138         set_piece[col(0,color), :pawn]
139       end
140     end
142     def in_promotion_zone?(p, color)
143       (row(4, color) <=> p.y) != (color == :black ? -1 : 1)
144     end
146   end