From 06886ba60cbe2856db1e7cc52bc9fba67693c328 Mon Sep 17 00:00:00 2001 From: midorimici <60635066+midorimici@users.noreply.github.com> Date: Wed, 7 Oct 2020 20:41:39 +0900 Subject: [PATCH] changes after 19 posts --- codes/games.py | 63 ++++++++++++- codes/main.py | 236 +++++++++++++++++++++++++++++++++------------- codes/utils.py | 13 ++- img/B/BUn.png | Bin 0 -> 661 bytes img/W/WUn.png | Bin 0 -> 1173 bytes sounds/move.wav | Bin 0 -> 13728 bytes sounds/select.wav | Bin 0 -> 11308 bytes 7 files changed, 245 insertions(+), 67 deletions(-) create mode 100644 img/B/BUn.png create mode 100644 img/W/WUn.png create mode 100644 sounds/move.wav create mode 100644 sounds/select.wav diff --git a/codes/games.py b/codes/games.py index 40f40d3..5683851 100644 --- a/codes/games.py +++ b/codes/games.py @@ -1,5 +1,7 @@ '''ゲームの種類によって変わる駒の配置や名前、画像IDを記録したモジュール''' +from random import randint + from pieces import * @@ -23,8 +25,65 @@ class Normal: ID['B' + placers[rk][fl].abbr] = -(size * rk + fl) +class Chess960: + '''チェス960''' + # 盤面のサイズ + size = 8 + # キャスリングの有無 + castling = True + # プロモーション先 + promote2 = [Knight, Bishop, Rook, Queen] + # 駒の配置 + placers = {1: [None] * size, + 2: [Pawn] * size} + + ID = {} + + def __init__(self): + # 駒の配置の決定 + pos_id = randint(0, 959) + while pos_id == 518: + pos_id = randint(0, 959) + krn = [ + [Knight, Knight, Rook, King, Rook], + [Knight, Rook, Knight, King, Rook], + [Knight, Rook, King, Knight, Rook], + [Knight, Rook, King, Rook, Knight], + [Rook, Knight, Knight, King, Rook], + [Rook, Knight, King, Knight, Rook], + [Rook, Knight, King, Rook, Knight], + [Rook, King, Knight, Knight, Rook], + [Rook, King, Knight, Rook, Knight], + [Rook, King, Rook, Knight, Knight] + ] + + q, r = pos_id//4, pos_id%4 + self.placers[1][2*r + 1] = Bishop + + q, r = q//4, q%4 + self.placers[1][2*r] = Bishop + + q, r = q//6, q%6 + for i in range(self.size): + if self.placers[1][i] is None: + if i == r: + self.placers[1][i] = Queen + break + else: r += 1 + + for piece in krn[q]: + self.placers[1][self.placers[1].index(None)] = piece + + # 画像IDの割り当て + for rk in self.placers: + for fl in range(self.size): + if self.placers[rk][fl] is not None: + self.ID['W' + self.placers[rk][fl].abbr] = self.size * rk + fl + self.ID['B' + self.placers[rk][fl].abbr] = -(self.size * rk + fl) + + class withUnicorn: - '''通常のチェス''' + '''キングサイドのナイトがユニコーンになったチェス''' # 盤面のサイズ size = 8 # キャスリングの有無 @@ -44,4 +103,4 @@ class withUnicorn: # ゲーム選択画面に表示するゲーム -game_dict = {0: (Normal, withUnicorn)} \ No newline at end of file +game_dict = {0: (Normal, Chess960, withUnicorn)} \ No newline at end of file diff --git a/codes/main.py b/codes/main.py index 049803f..3f18a64 100644 --- a/codes/main.py +++ b/codes/main.py @@ -35,6 +35,10 @@ def __init__(self): # キャスリング # キャスリングのポテンシャルが残っているか self.can_castling = {'W': [True, True], 'B': [True, True]} + # キャスリングするかどうかをプレイヤーに確認するか + self.confirm_castling = False + # キャスリングできる状態にあるか + self.do_castling = False # マウスポインタの位置 self.mousepos = [-1.0, -1.0] @@ -146,8 +150,10 @@ def valid_moves(self, piece, startpos, gameboard): for endpos in [(2, 0), (6, 0), (2, 7), (6, 7)]: if self.castling_requirements(piece, endpos, 0, gameboard): result += [endpos] + self.do_castling = True if self.castling_requirements(piece, endpos, 1, gameboard): result += [endpos] + self.do_castling = True # チェック回避のため動き縛り result_tmp = copy(result) for endpos in result_tmp: @@ -172,16 +178,14 @@ def en_passant_requirements(self, piece, startpos, endpos): ------- bool ''' - if piece.abbr == 'P': - return (self.advanced2_pos - and startpos[1] == endpos[1] - piece.direction - and startpos[1] == self.advanced2_pos[1] - and endpos[1] == self.advanced2_pos[1] + piece.direction - and abs(startpos[0] - endpos[0]) == 1 - and abs(startpos[0] - self.advanced2_pos[0]) == 1 - and endpos[0] == self.advanced2_pos[0]) - else: - return False + return (piece.abbr == 'P' + and self.advanced2_pos + and startpos[1] == endpos[1] - piece.direction + and startpos[1] == self.advanced2_pos[1] + and endpos[1] == self.advanced2_pos[1] + piece.direction + and abs(startpos[0] - endpos[0]) == 1 + and abs(startpos[0] - self.advanced2_pos[0]) == 1 + and endpos[0] == self.advanced2_pos[0]) def promotion(self, piece, endpos): ''' @@ -224,6 +228,11 @@ def castling_requirements(self, piece, endpos, side, gameboard): ------- bool ''' + size = self.kind.size + + rook_init_pos = [pos for pos, piece in enumerate(self.kind.placers[1]) if piece == Rook] + king_init_pos = self.kind.placers[1].index(King) + def create_tmp_board(startpos_y, endpos): ''' キングの通過するマスが攻撃されていないことを確認するために, @@ -242,9 +251,9 @@ def create_tmp_board(startpos_y, endpos): gameboard_tmp : dict > {(int, int): obj, ...} ''' gameboard_tmp = copy(gameboard) - if (4, startpos_y) in gameboard_tmp: - gameboard_tmp[endpos] = gameboard_tmp[(4, startpos_y)] - del gameboard_tmp[(4, startpos_y)] + if (king_init_pos, startpos_y) in gameboard_tmp: + gameboard_tmp[endpos] = gameboard_tmp[(king_init_pos, startpos_y)] + del gameboard_tmp[(king_init_pos, startpos_y)] return gameboard_tmp def path_is_not_attacked(startpos_y, king_route): @@ -272,54 +281,104 @@ def path_is_not_attacked(startpos_y, king_route): # 白のキャスリング if piece.color == 'W': piece_req = (piece.name == 'WK' - and (7*side, 0) in gameboard - and gameboard[(7*side, 0)].name == 'WR') + and (rook_init_pos[side], 0) in gameboard + and gameboard[(rook_init_pos[side], 0)].name == 'WR') + gameboard_tmp = copy(gameboard) + # キャスリングに関与するキングとルークは除外して考える + if (king_init_pos, 0) in gameboard_tmp: + del gameboard_tmp[(king_init_pos, 0)] + if (rook_init_pos[side], 0) in gameboard_tmp: + del gameboard_tmp[(rook_init_pos[side], 0)] # クイーンサイド if side == 0: + # キングとルークの通過するマス + king_route = list(range(2, king_init_pos)) + list(range(2, king_init_pos, -1)) + rook_route = list(range(3, rook_init_pos[side])) + list(range(3, rook_init_pos[side], -1)) special_req = (endpos == (2, 0) - # キングとルークの間に駒がない - and (1, 0) not in self.gameboard - and (2, 0) not in self.gameboard - and (3, 0) not in self.gameboard - # キングが通過するマスが敵に攻撃されていない - and path_is_not_attacked(0, [2, 3]) - ) + # キングとルークの通過するマスに駒がない + and not any((x, 0) in gameboard_tmp + for x in king_route + rook_route) + # キングが通過するマスが敵に攻撃されていない + and path_is_not_attacked(0, list(x for x in range(2, king_init_pos))) + ) # キングサイド if side == 1: - special_req = (endpos == (6, 0) - # キングとルークの通過するマスに駒がない - and (6, 0) not in self.gameboard - and (5, 0) not in self.gameboard - # キングが通過するマスが敵に攻撃されていない - and path_is_not_attacked(0, [6, 5]) - ) + # キングとルークの通過するマス + king_route = list(range(size - 2, king_init_pos)) + list(range(size - 2, king_init_pos, -1)) + rook_route = list(range(size - 3, rook_init_pos[side])) + list(range(size - 3, rook_init_pos[side], -1)) + special_req = (endpos == (size - 2, 0) + # キングとルークの通過するマスに駒がない + and not any((x, 0) in gameboard_tmp + for x in king_route + rook_route) + # キングが通過するマスが敵に攻撃されていない + and path_is_not_attacked(0, list(x for x in range(size - 2, king_init_pos, -1))) + ) # 黒のキャスリング if piece.color == 'B': piece_req = (piece.name == 'BK' - and (7*side, 7) in gameboard - and gameboard[(7*side, 7)].name == 'BR') + and (rook_init_pos[side], size - 1) in gameboard + and gameboard[(rook_init_pos[side], size - 1)].name == 'BR') + gameboard_tmp = copy(gameboard) + # キャスリングに関与するキングとルークは除外して考える + if (king_init_pos, size - 1) in gameboard_tmp: + del gameboard_tmp[(king_init_pos, size - 1)] + if (rook_init_pos[side], size - 1) in gameboard_tmp: + del gameboard_tmp[(rook_init_pos[side], size - 1)] # クイーンサイド if side == 0: - special_req = (endpos == (2, 7) - # キングとルークの通過するマスに駒がない - and (1, 7) not in self.gameboard - and (2, 7) not in self.gameboard - and (3, 7) not in self.gameboard - # キングが通過するマスが敵に攻撃されていない - and path_is_not_attacked(7, [2, 3]) - ) + # キングとルークの通過するマス + king_route = list(range(2, king_init_pos)) + list(range(2, king_init_pos, -1)) + rook_route = list(range(3, rook_init_pos[side])) + list(range(3, rook_init_pos[side], -1)) + special_req = (endpos == (2, size - 1) + # キングとルークの通過するマスに駒がない + and not any((x, size - 1) in gameboard_tmp + for x in king_route + rook_route) + # キングが通過するマスが敵に攻撃されていない + and path_is_not_attacked(size - 1, list(x for x in range(2, king_init_pos))) + ) # キングサイド if side == 1: - special_req = (endpos == (6, 7) - # キングとルークの通過するマスに駒がない - and (6, 7) not in self.gameboard - and (5, 7) not in self.gameboard - # キングが通過するマスが敵に攻撃されていない - and path_is_not_attacked(7, [6, 5]) - ) + # キングとルークの通過するマス + king_route = list(range(size - 2, king_init_pos)) + list(range(size - 2, king_init_pos, -1)) + rook_route = list(range(size - 3, rook_init_pos[side])) + list(range(size - 3, rook_init_pos[side], -1)) + special_req = (endpos == (size - 2, size - 1) + # キングとルークの通過するマスに駒がない + and not any((x, size - 1) in gameboard_tmp + for x in king_route + rook_route) + # キングが通過するマスが敵に攻撃されていない + and path_is_not_attacked(size - 1, list(x for x in range(size - 2, king_init_pos, -1))) + ) return common_req and piece_req and special_req + def castle_or_not(self, piece, endpos): + ''' + キャスリングするかしないかを確認するか + + Parameters + ---------- + piece : obj + 駒. + endpos : tuple > (int, int) + 終了位置.絶対座標. + + Notes + ----- + if文の条件式について. + + キングの移動終了位置が,キャスリング終了位置としてありうる4つの位置のうちのいずれかにあてはまる + and (クイーンサイドキャスリングの条件にあてはまる + or キングサイドキャスリングの条件にあてはまる) + and キングの初期位置とキャスリング終了位置のx座標の差 == 1 + and 移動先に駒がない(=キングが敵駒を取ったのではない) + ''' + if (endpos in [(2, 0), (self.kind.size - 2, 0), (2, self.kind.size - 1), (self.kind.size - 2, self.kind.size - 1)] + and (self.castling_requirements(piece, endpos, 0, self.gameboard) + or self.castling_requirements(piece, endpos, 1, self.gameboard)) + and abs(self.kind.placers[1].index(King) - endpos[0]) == 1 + and endpos not in self.gameboard): + self.confirm_castling = True + def is_check(self, color, gameboard): ''' color 側がチェックされていれば True を返す @@ -334,7 +393,7 @@ def is_check(self, color, gameboard): kingDict = {} pieceDict = {B: [], W: []} for position, piece in gameboard.items(): - if type(piece) == King: + if piece.abbr == 'K': kingDict[piece.color] = position pieceDict[piece.color].append((piece, position)) if self.can_see_king(kingDict[color], pieceDict[opponent[color]], gameboard): @@ -394,7 +453,8 @@ def renew_gameboard(self, startpos, endpos, gameboard): ''' color = gameboard[startpos].color gameboard[endpos] = gameboard[startpos] - del gameboard[startpos] + if startpos != endpos: + del gameboard[startpos] # アンパッサン if self.en_passant: if (color == W @@ -406,26 +466,51 @@ def renew_gameboard(self, startpos, endpos, gameboard): if (gameboard[endpos[0], endpos[1] + 1].name == 'WP'): del gameboard[(endpos[0], endpos[1] + 1)] # キャスリング - if (gameboard[endpos].abbr == 'K' - and abs(startpos[0] - endpos[0]) == 2): + # キャスリングできるゲームである + # キャスリング確認中でない + # キャスリングできる + # 終了位置指定がある + if (self.kind.castling + and not self.confirm_castling + and self.do_castling + and None not in endpos): + rook_init_pos = [pos for pos, piece in enumerate(self.kind.placers[1]) + if piece == Rook] + size = self.kind.size + piece = gameboard[endpos] # クイーンサイド + rook_pos = rook_init_pos[0] # 白 - if endpos == (2, 0): - del gameboard[(0, 0)] + if (endpos == (2, 0) + and piece.color == 'W' + and (rook_pos, 0) in gameboard): + if gameboard[(rook_pos, 0)].abbr == 'R': + del gameboard[(rook_pos, 0)] gameboard[(3, 0)] = Rook('W') # 黒 - if endpos == (2, 7): - del gameboard[(0, 7)] - gameboard[(3, 7)] = Rook('B') + if (endpos == (2, size - 1) + and piece.color == 'B' + and (rook_pos, size - 1) in gameboard): + if gameboard[(rook_pos, size - 1)].abbr == 'R': + del gameboard[(rook_pos, size - 1)] + gameboard[(3, size - 1)] = Rook('B') # キングサイド + rook_pos = rook_init_pos[1] # 白 - if endpos == (6, 0): - del gameboard[(7, 0)] - gameboard[(5, 0)] = Rook('W') + if (endpos == (size - 2, 0) + and piece.color == 'W' + and (rook_pos, 0) in gameboard): + if gameboard[(rook_pos, 0)].abbr == 'R': + del gameboard[(rook_pos, 0)] + gameboard[(size - 3, 0)] = Rook('W') # 黒 - if endpos == (6, 7): - del gameboard[(7, 7)] - gameboard[(5, 7)] = Rook('B') + if (endpos == (size - 2, size - 1) + and piece.color == 'B' + and (rook_pos, size - 1) in gameboard): + if gameboard[(rook_pos, size - 1)].abbr == 'R': + del gameboard[(rook_pos, size - 1)] + gameboard[(size - 3, size - 1)] = Rook('B') + def parse_mouse(self): '''マウスポインタの位置から指定したマス目を出力''' @@ -459,7 +544,7 @@ def draw(self): if self.kind == None: draw_game_menu() else: - if self.time == 1: + if self.time == 1 and not self.confirm_castling: self.main() draw_squares() @@ -476,7 +561,8 @@ def draw(self): glColor(0.82, 0.55, 0.28) else: glColor(1.00, 0.81, 0.62) - square(*self.endpos) + if None not in self.endpos: + square(*self.endpos) # 動き中の駒を描画する if self.endpos in self.gameboard: glEnable(GL_TEXTURE_2D) @@ -503,6 +589,9 @@ def draw(self): draw_img(4.0, 3.5, piece_ID[piece_color + 'R']) draw_img(5.0, 3.5, piece_ID[piece_color + 'Q']) glDisable(GL_TEXTURE_2D) + # キャスリングするかどうかの確認 + if self.confirm_castling: + draw_castling_confirmation(self.endpos) glDisable(GL_BLEND) glutSwapBuffers() @@ -552,12 +641,31 @@ def mouse(self, button, state, x, y): glutMouseFunc(None) # マウス操作の無効化 move_snd.play() # 駒選択 - elif (self.parse_mouse() in self.gameboard): + elif (self.parse_mouse() in self.gameboard + and not self.prom and not self.confirm_castling): self.startpos, self.endpos = (None, None), (None, None) self.select_dest = True self.startpos = self.parse_mouse() except KeyError: pass + # キャスリングするかしないかの確認 + if self.kind.castling: + if self.startpos in self.gameboard: + self.castle_or_not( + self.gameboard[self.startpos], self.endpos) + if self.confirm_castling: + if on_square(*self.mousepos, 1.5, 3.0, 3.0, 4.0): + self.do_castling = True + self.confirm_castling = False + self.time = 0 + self.moving = True + glutIdleFunc(self.idle_move) + if on_square(*self.mousepos, 4.0, 5.5, 3.0, 4.0): + self.do_castling = False + self.confirm_castling = False + self.time = 0 + self.moving = True + glutIdleFunc(self.idle_move) # プロモーション if self.prom: piece_color = self.gameboard[self.endpos].color diff --git a/codes/utils.py b/codes/utils.py index f9c8aba..793c143 100644 --- a/codes/utils.py +++ b/codes/utils.py @@ -244,7 +244,7 @@ def draw_button(left, right, bottom, top, # ゲーム選択画面に表示するゲーム名 -game_name_dict = {0: ('Normal Chess', 'Unicorn')} +game_name_dict = {0: ('Normal Chess', 'Chess 960', 'Unicorn')} def draw_game_menu(): @@ -298,3 +298,14 @@ def draw_available_moves(poslist, opponent=None): ''' for pos in poslist: circle(*pos, opponent) + + +def draw_castling_confirmation(endpos): + '''キャスリング確認ダイアログを表示する''' + draw_balloon(*endpos) + glColor(1.0, 1.0, 1.0) + draw_str(2.0, 4.0, 'Castling?') + draw_button(1.5, 3.0, 3.0, 3.5, 'Yes', + (1.0, 1.0, 1.0), (0.0, 0.0, 0.0)) + draw_button(4.0, 5.5, 3.0, 3.5, 'No', + (1.0, 1.0, 1.0), (0.0, 0.0, 0.0)) \ No newline at end of file diff --git a/img/B/BUn.png b/img/B/BUn.png new file mode 100644 index 0000000000000000000000000000000000000000..fbfdbb983e54249ce87e7da4b9176d189bb10b81 GIT binary patch literal 661 zcmeAS@N?(olHy`uVBq!ia0vp^DImTT$X?><>&pI^labY2`|^!gcA$`CiEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI0FOYUr!gukcwMxXFK{GG2n51yHH5{;hZ^*w$GD}Dn=-q7|l*R zK4qK9$^O6dLNd)Jt5t5jyJW2-&~PA_a?C$ZUut{*1mPtLX&WX~2MHJla0IcmuJLrd zbfD9rYsLiIpi`$`S{5wn;ImSDogc2(tk<-j`G58PlRfobs!md_-lt9kN_eQq1b3Zt z|Mc{6R_y_ELL zSF)bp-F(J>yOh!I%X?1pg?T z6jDqYCos*~`1hSi?OcvTMkN&%NhYTnSGJd435CLQe+hU#_g~j`M#s5K_R)z8(d`yS zF2xVpPM%RY9IBj>?cUjQFuU`q*}?9awQ5ryZ00mHt~S`5eW_zckjJwxCceBY6`X%< z6PFa`c5Dma<$UJ1y^X=iBXWuMMUI6NCT|j8ntVlIU$l6aKo+|uw_@nSyKzb^0!;!A s9Idj7E*uIfuD7yuTl%XY(Z}%Z1MhmDXAuSY`&>XGp00i_>zopr0I2^1H~;_u literal 0 HcmV?d00001 diff --git a/img/W/WUn.png b/img/W/WUn.png new file mode 100644 index 0000000000000000000000000000000000000000..f926fd2f137073e9fb076eeb7bb3a5de3017c8e5 GIT binary patch literal 1173 zcmV;G1Zw+e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00aF=L_t(|+U=c7Zqz^!hW~00 z4=GZl9D)S&JMWk3An>fjEGoU{(fVgQ8$o1foy`0vUp$kSy8+ z0B(a)Hb2jseH2PSaeJ$(>W*6i@V&E-Dln9H+#>*=TX0mN!PwN}m~5Q0R@~kLcmkki zW@9}$qO$ez9KZ`L1On!k0mmG-S{- z*l?~Pb;wK@vk&r+XQIk2CPf(CFcuROBM3xyfXcbyDrP7o)e$a0#8`zHX)s!`-~AUp zRAJq|g>whOQ$P^W^~4VS6qs#K7-In606arx8a1KVGqK13KC)v0_|-c89e}q&tIu#S zx=#>WgLQ?T*4%Ay~!&SgcJDG+1t!LsWVn6d#%fJ zS}WC^&M`Rzay{p~ES)=v2O`uRC4lXcb8Ucjp?Cvg7GCg9cm&vbsq;!t zbC-}gWHSRGOMuZFKZWNmi<3H8a>jpm?gSV#V#Cn!a|d$LvPDsRngC<+bWI{pB)yfr zG}OVngpsl{T=ya5VgE;EWy;QQRrU_$7N;H~v53r0@z`3?l(@F$oy0G^+K zG1&d)kUM;YtUmn(P~h-p(kw@$+Hb7kkoy~aE{vR<5faE$7%{I2juwbDSHwO!C_RUa zhLKyYkm8V(swhguA?ggFNj=LdN|Hl3A!ktR4qhV@vnX1Js1!(a{fLRl n&MK8krBbO>DwRs5QYEi{MzIqM4;#Ik00000NkvXXu0mjfAxHk_ literal 0 HcmV?d00001 diff --git a/sounds/move.wav b/sounds/move.wav new file mode 100644 index 0000000000000000000000000000000000000000..c5dd05d49a047b85bbbf14d3109c9f7ea45b129f GIT binary patch literal 13728 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