Python プログラムで動かすフェアリーチェスアプリ開発、連載第 20 回です。
でフェアリーチェスへのキャスリングの拡張が完了しました。今回はポーンのプロモーションの拡張をしていきます。
拡張前のプロモーションの実装は第11回に載せています。
ゲーム毎にプロモーション先候補を指定
まずはゲームによって異なるプロモーション先候補を、各ゲームクラスの
として定義することが必要です。games.py1class Normal:2'''通常のチェス'''3# 盤面のサイズ4size = 85# キャスリングの有無6castling = True7# プロモーション先8promote2 = [Knight, Bishop, Rook, Queen]9# 駒の配置10placers = {1: [Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook],112: [Pawn] * size}12# 画像IDの割り当て13ID = {}14for rk in placers:15for fl in range(size):16if placers[rk][fl] is not None:17ID['W' + placers[rk][fl].abbr] = size * rk + fl18ID['B' + placers[rk][fl].abbr] = -(size * rk + fl)
promote2
というリストの中からポーンのプロモーション先が選択されます。
プロモーション時に表示する選択肢を一般化
次にプロモーションの選択肢として表示される駒を、このリストに合わせて変更しなければなりません。
現在プロモーション選択肢の表示部分のコードは次のようになっています。
main.py1...2class Game:3...4def draw(self):5'''描画コールバック'''6...7# プロモーション8if self.prom:9draw_balloon(*self.endpos)10piece_color = self.gameboard[self.endpos].color11glEnable(GL_TEXTURE_2D)12draw_img(2.0, 3.5, piece_ID[piece_color + 'N'])13draw_img(3.0, 3.5, piece_ID[piece_color + 'B'])14draw_img(4.0, 3.5, piece_ID[piece_color + 'R'])15draw_img(5.0, 3.5, piece_ID[piece_color + 'Q'])16glDisable(GL_TEXTURE_2D)17...
12-15行目がプロモーション先を固定してしまっているので、この部分を変更します。
どの位置座標にどの駒の画像を配置するかもゲームによって変化しますので、
表示幅は 4 列までとして行を増やしていく形で描画します。
main.py1# プロモーション2if self.prom:3draw_balloon(*self.endpos)4piece_color = self.gameboard[self.endpos].color5glEnable(GL_TEXTURE_2D)6draw_img(2.0, 3.5, piece_ID[piece_color + 'N'])7draw_img(3.0, 3.5, piece_ID[piece_color + 'B'])8draw_img(4.0, 3.5, piece_ID[piece_color + 'R'])9draw_img(5.0, 3.5, piece_ID[piece_color + 'Q'])10for i in range(len(self.kind.promote2)):11draw_img(2.0 + i % 4,123.5 + ((len(self.kind.promote2) - 1)//4)/2 - i//4,13self.kind.ID[piece_color +14self.kind.promote2[i].abbr])15glDisable(GL_TEXTURE_2D)
また、それに伴って吹き出しの縦幅も増やす必要があります。
吹き出しはdraw_balloon
関数が描画していますので、そちらの中身を書き換えます。
utils.py1def draw_balloon(x, y):2def draw_balloon(x, y, num=4):3'''4プロモーションのときの吹き出しを描画する56Parameters7----------8x, y : int9駒の座標.10num : int, default 411プロモーション選択肢数.12'''13glColor(0.5, 0.5, 0.5) # 色の指定14glBegin(GL_QUADS) # 四角形を描画15glVertex(1.0, 2.5)16glVertex(1.0, 4.5)17glVertex(6.0, 4.5)18glVertex(6.0, 2.5)19glVertex(1.0, 2.5 - ((num - 1) // 4) / 2)20glVertex(1.0, 4.5 + ((num - 1) // 4) / 2)21glVertex(2.0 + num if num <= 4 else 6.0, 4.5 + ((num - 1) // 4) / 2)22glVertex(2.0 + num if num <= 4 else 6.0, 2.5 - ((num - 1) // 4) / 2)23glEnd()24glBegin(GL_TRIANGLES) # 三角形を描画25glVertex(3.0, 3.5)26glVertex(4.0, 3.5)27glVertex(x, y)28glEnd()
glBegin
からglEnd
までの間の4つのglVertex
が四角形の各頂点の位置を指定しています。
新たに追加いた引数num
=プロモーション選択肢の数によってこの座標を調整しています。
(num - 1) // 4
はnum
が4
までのとき0
、8
までのとき1
というように増えていくので、
縦方向の座標2.5
と4.5
を基準に縦幅が増えていくことになります。
横幅は2.0 + num if num <= 4 else 6.0
というふうに、選択肢が4つ以下かどうかで変えています。
吹き出し描画部分のコードも変更します。
main.py1# プロモーション2if self.prom:3draw_balloon(*self.endpos)4draw_balloon(*self.endpos, num=len(self.kind.promote2))5piece_color = self.gameboard[self.endpos].color6glEnable(GL_TEXTURE_2D)7for i in range(len(self.kind.promote2)):8draw_img(2.0 + i % 4,93.5 + ((len(self.kind.promote2) - 1)//4)/2 - i//4,10self.kind.ID[piece_color +11self.kind.promote2[i].abbr])12glDisable(GL_TEXTURE_2D)
これで通常のゲームのプロモーションでは下のようになり、
ユニコーンが加わったゲーム(promote2 = [Knight, Bishop, Rook, Queen, Unicorn]
)では下のようになります。
縦幅が大きくなりました。
マウスクリックを調整
マウスクリックでこの選択肢の中から駒を選択するわけですが、今のコードは次のようになっています。
main.py1...2class Game:3...4def mouse(self, button, state, x, y):5'''6マウス入力コールバック7'''8...9# プロモーション10if self.prom:11piece_color = self.gameboard[self.endpos].color12if on_square(*self.mousepos, 1.5, 2.5, 3.0, 4.0):13self.gameboard[self.endpos] = Knight(piece_color)14self.prom = False15if on_square(*self.mousepos, 2.5, 3.5, 3.0, 4.0):16self.gameboard[self.endpos] = Bishop(piece_color)17self.prom = False18if on_square(*self.mousepos, 3.5, 4.5, 3.0, 4.0):19self.gameboard[self.endpos] = Rook(piece_color)20self.prom = False21if on_square(*self.mousepos, 4.5, 5.5, 3.0, 4.0):22self.gameboard[self.endpos] = Queen(piece_color)23self.prom = False24...
座標も駒も固定になっていますので、これを変更します。
main.py1# プロモーション2if self.prom:3piece_color = self.gameboard[self.endpos].color4for i in range(len(self.kind.promote2)):5if on_square(*self.mousepos,61.5 + i % 4,72.5 + i % 4,83.0 + ((len(self.kind.promote2) - 1)//4)/2 - i//4,94.0 + ((len(self.kind.promote2) - 1)//4)/2 - i//4):10self.gameboard[self.endpos] = self.kind.promote2[i](piece_color)11self.prom = False
on_square
関数の最後の4つの引数left, right, bottom, top
が有効範囲を指定しています。
この範囲内にself.mousepos
=クリック時のマウスカーソル位置があれば、ポーンが指定の駒に置き換わります。
これでプロモーションの拡張が完了しました!
今回の変更も GitHub に上げておきます。
これまで20回かけてチェスのコードの編集やフェアリーチェスへの拡張をやってきました。
これにさらにチェックやメイトを知らせるダイアログを表示したり、手数を戻せるようにしたり、
あるいはコンピュータ対戦を導入しても面白いでしょう。
が、いったんこのシリーズは一区切りついたことにしたいと思います。
お読みいただきありがとうございました~
では