牌語備忘録 -pygo

あくまでもメモです。なるべくオフィシャルの情報を参照してください。

牌語備忘録 -pygo

急に将棋のアルゴリズムに興味湧いたからPythonでやってみた その1.1a[局面表示編]

将棋プログラムの作り方(サンプルはC++のコード)を参考にPythonでやってみた...い感じ?

簡単なはずの局面表示を作成中。

C/C++の知識が無いので、何の動きをするの理解するまで時間がかかる。理解できてないけど(´・ω・`)
とりあえず途中経過。

# #!/usr/bin/env python
# *-# -*- coding: utf-8 -*-

##将棋プログラムの基礎
#駒と局面の内部表現を決める
OUT_OF_BOARD = 64
EMPTY = 0
FU = 1
KY = 2
KE = 3
GI = 4
KI = 5
KA = 6
HI = 7
OU = 8
PROMOTED = 8
TO = PROMOTED + FU
NY = PROMOTED + KY
NK = PROMOTED + KE
NG = PROMOTED + GI
UM = PROMOTED + KA
RY = PROMOTED + HI
ENEMY = 16
EFU = ENEMY + FU
EKY = ENEMY + KY
EKE = ENEMY + KE
EGI = ENEMY + GI
EKI = ENEMY + KI
EKA = ENEMY + KA
EHI = ENEMY + HI
EOU = ENEMY + OU
ETO = ENEMY + TO
ENY = ENEMY + NY
ENK = ENEMY + NK
ENG = ENEMY + NG
EUM = ENEMY + UM
ERY = ENEMY + RY

komastr = [" ・","△歩","△香","△桂","△銀","△金","△角","△飛","△玉",
           "△と","△杏","△圭","△全","△金","△馬","△竜",
           " ・","▼歩","▼香","▼桂","▼銀","▼金","▼角","▼飛","▼王",
           "▼と","▼杏","▼圭","▼全","▼金","▼馬","▼竜"]

#敵味方の駒の判別?
def is_enemy_retn(koma):
    return koma + ENEMY
def is_self_retn(koma):
    return FU <= koma and koma <= RY
def is_enemy(sengo, koma):
    if sengo == 0:
        return is_enemy_retn(koma)
    return is_self_retn(koma)
def is_self(sengo, koma):
    if sengo == 0:
        return is_self_retn(koma)
    return is_enemy_retn(koma)

#局面表示
hand = [[0 for j in range(HI + 1)] for i in range(2)]
board = [[EKY,EKE,EGI,EKI,EOU,EKI,EGI,EKE,EKY],
               [EMPTY,EHI,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EKA,EMPTY],
               [EFU,EFU,EFU,EFU,EFU,EFU,EFU,EFU,EFU],
               [EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY],
               [EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY],
               [EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY],
               [FU,FU,FU,FU,FU,FU,FU,FU,FU],
               [EMPTY,KA,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,HI,EMPTY],
               [KY,KE,GI,KI,OU,KI,GI,KE,KY]]
yokosen_str = "+−−−−−−−−−−−−−−−−−−+ \n"
dan_str_list = ["一","二","三","四","五","六","七","八","九"]
suji_str = "  9 8 7 6 5 4 3 2 1 \n"

class KYOKUMEN:   
    def display(self):
        display_li_str = ["先手 持ち駒 \n"]
        for koma in range(FU, HI + 1):
            if hand[0][koma] == 1:
                display_li_str.append("%s " % komastr[koma])
            elif hand[0][koma] > 1:
                display_li_str.append("%s%d " % (komastr[koma], hand[1][koma]))
        display_li_str.append(suji_str)
        display_li_str.append(yokosen_str)
        for dan in range(0, 9):
            display_li_str.append("|")
            for suji in range(8,-1,-1):
                display_li_str.append("%s" % komastr[board[dan][suji]])
            display_li_str.append("|%s\n" % dan_str_list[dan])
        display_li_str.append(yokosen_str)
        display_li_str.append("後手 持ち駒 \n")
        for koma in range(FU, HI + 1):
            if hand[1][koma] == 1:
                display_li_str.append("%s " % komastr[koma])
            elif hand[1][koma] > 1:
                display_li_str.append("%s%d " % (komastr[koma], hand[1][koma]))

        return "".join(display_li_str)

    def te_display(self, te):
        te_str = []
        if te.from_where["suji"] != 0:
            te_str.append("%d%s" % (te.from_where["suji"],
                                    dan_str_list[te.from_where["dan"] - 1]))
        te_str.append("(%d%s)" % (te.to["suji"],
                                   dan_str_list[te.to["dan"] - 1]))
        #te_str.append("%s" % komastr[te.koma & ~ENEMY])
        te_str.append("%s" % komastr[te.koma])
        if te.from_where["suji"] == 0:
            te_str.append("打 ")
        elif te.promote:
            te_str.append("成 ")
        else:
            te_str.append("")
        return " ".join(te_str)

    def move(self, teban, te):
        capture = board[te.to["dan"]][te.to["suji"]]
        if te.from_where["suji"]:
            board[te.from_where["dan"]][te.from_where["suji"]] = EMPTY
        else:
            hand[teban][te.koma] -= 1
        if te.promote:
            board[te.to["dan"]][te.to["suji"]] = te.koma | PROMOTED
        else:
            board[te.to["dan"]][te.to["suji"]] = te.koma
        if capture != EMPTY:
            hand[teban][capture & ~ENEMY & ~PROMOTED] += 1
            
        return self.te_display(te)

class TE:
    def __init__(self,
                 fr_dan = 0, fr_suji = 0,
                 to_dan = 0, to_suji = 0,
                 koma = EMPTY,
                 promote = False):
        self.from_where =  {"dan":fr_dan - 1, "suji":fr_suji - 1}
        self.to =  {"dan":to_dan - 1, "suji":to_suji - 1}
        self.koma = koma
        self.promote = promote

    def __repr__(self):
        return "from{dan %d,suji %d}, to{dan %d,suji %d}, koma %s, promote %s"\
            % (self.from_where["dan"], self.from_where["suji"],
             self.to["dan"],  self.to["suji"], self.koma, self.promote)

    

if __name__ == "__main__":
    k = KYOKUMEN()
    print k.display()
    print k.move(0, TE(7,3,6,3,FU))
    print k.display()
    print k.move(1, TE(3,7,4,7,FU + ENEMY))
    print k.display()

とりあえずの実行結果

先手 持ち駒 
  9 8 7 6 5 4 3 2 1 
+−−−−−−−−−−−−−−−−−−+ 
|▼香▼桂▼銀▼金▼王▼金▼銀▼桂▼香|一
| ・▼角 ・ ・ ・ ・ ・▼飛 ・|二
|▼歩▼歩▼歩▼歩▼歩▼歩▼歩▼歩▼歩|三
| ・ ・ ・ ・ ・ ・ ・ ・ ・|四
| ・ ・ ・ ・ ・ ・ ・ ・ ・|五
| ・ ・ ・ ・ ・ ・ ・ ・ ・|六
|△歩△歩△歩△歩△歩△歩△歩△歩△歩|七
| ・△飛 ・ ・ ・ ・ ・△角 ・|八
|△香△桂△銀△金△玉△金△銀△桂△香|九
+−−−−−−−−−−−−−−−−−−+ 
後手 持ち駒 

2六 (2五) △歩 
先手 持ち駒 
  9 8 7 6 5 4 3 2 1 
+−−−−−−−−−−−−−−−−−−+ 
|▼香▼桂▼銀▼金▼王▼金▼銀▼桂▼香|一
| ・▼角 ・ ・ ・ ・ ・▼飛 ・|二
|▼歩▼歩▼歩▼歩▼歩▼歩▼歩▼歩▼歩|三
| ・ ・ ・ ・ ・ ・ ・ ・ ・|四
| ・ ・ ・ ・ ・ ・ ・ ・ ・|五
| ・ ・ ・ ・ ・ ・△歩 ・ ・|六
|△歩△歩△歩△歩△歩△歩 ・△歩△歩|七
| ・△飛 ・ ・ ・ ・ ・△角 ・|八
|△香△桂△銀△金△玉△金△銀△桂△香|九
+−−−−−−−−−−−−−−−−−−+ 
後手 持ち駒 

6二 (6三) ▼歩 
先手 持ち駒 
  9 8 7 6 5 4 3 2 1 
+−−−−−−−−−−−−−−−−−−+ 
|▼香▼桂▼銀▼金▼王▼金▼銀▼桂▼香|一
| ・▼角 ・ ・ ・ ・ ・▼飛 ・|二
|▼歩▼歩 ・▼歩▼歩▼歩▼歩▼歩▼歩|三
| ・ ・▼歩 ・ ・ ・ ・ ・ ・|四
| ・ ・ ・ ・ ・ ・ ・ ・ ・|五
| ・ ・ ・ ・ ・ ・△歩 ・ ・|六
|△歩△歩△歩△歩△歩△歩 ・△歩△歩|七
| ・△飛 ・ ・ ・ ・ ・△角 ・|八
|△香△桂△銀△金△玉△金△銀△桂△香|九
+−−−−−−−−−−−−−−−−−−+ 
後手 持ち駒

構造体ってのがよくわからないなぁ。Pythonでどうやるんだろ?
敵味方の駒の判別あたりもわかってないがorz


思考ルーチンに興味あるのに、それまで道のり険しそう...(´・ω・`)
時間空いたらまたやるはず...(初めからやり直すかもしんない)