nounai.output(spaghetiThinking);

趣味と実益を兼ねて将棋プログラム(研究ツールなど)を作ってみたいと思う私の試行錯誤とか勉強したことを綴ってゆく予定です。 主目的はプログラミングの経験値稼ぎですが、コンピュータ将棋の製作も目指してみたいとも考えています。

csaファイルの読み込み - 改行コードとか前段階的な処理とか

改行コードの判別+各行のふるい分け(バージョン/開始局面など)を簡易的に実装してみた。

OS標準の改行コードと、棋譜データ内で使用される改行コードは必ずしも同一ではない、ってことがちょっとやっかいですね。私がコード書いてる環境はLinux(改行=LF)ですが、棋譜データはたいていwindows(改行=CR+LF)上で作成されているため、若干めんどくさいことになっていました。


コードを掲載してみます。csa ver2.0のドキュメントを参照しながらやってます。棋譜データは

    1. バージョン
    2. 棋譜情報(=メタデータ?)
    3. 開始局面+手番
    4. 指し手+消費時間
    5. コメント

    からなる、としています。ある行がどのカテゴリに属すのかは、先頭文字を調べていくことで判別可能ですので、それを基に各行をカテゴリごとに分類していく、という流れです。

    ・・・しかしながら、このコードで定義したデータ格納用クラス"csarecord"を使った場合、カテゴリの異なる2つの行の順番をチェックすることは不可能です。よって"開始局面"の前に"指し手"があってもそれは素通しです。csaの仕様上だとこれはアウトなので、全く仕様に厳密なコードではありませんPythonのことをある程度知っている人であればすぐに同等のコードは書けてしまうでしょうし、コード自体も全然美しさがありませんので今後改善していきたいとは思いますが、AI部分もやってみたいのでその辺はやるにしてもかなり後手になる気がしています。

    #/usr/bin/env/ python
    # -*- coding: utf-8 -*-
    
    import os
    import sys
    import curses.ascii
    
    class plainrecord:
            def __init__(self, fname):
                    self.lines = file(fname, "r").readlines()
                    if self.lines[0][-2:] is "\r\n":
                            self.linesep="\r\n"
                    else:
                            # "CR+LPで終わらない場合"は全て、"改行=LF"とみなす。
                            self.linesep="\n"
    
    class csarecord(plainrecord):
            def todict(self):
                    return {
                            "version"        :self.Version,
                            "meta"                :self.meta,
                            "start"                :self.start,
                            "move"                :self.move,
                            "comments"        :self.comments,
                            "linesep"        :self.linesep
                    }
    
            def __init__(self, fname):
                    """
                    Windowsで生成された棋譜ファイルのみをターゲットとするならば、
                    改行コードはCR+LFのみを考えれば良い。
                    """        
                    self.lines = file(fname, "r").readlines()
                    if self.lines[0][-2:] is "\r\n":
                            self.linesep="\r\n"
                    else:
                            # "上記ifにあてはまらないケース"の全てを、改行=LFとみなす。
                            self.linesep="\n"
    
                    for line in self.lines:
                            if(line[0]=="'"):
                                    continue
                            elif(line[0]!="V"):
                                    self.version = 1.0
                                    break
                            else:
                                    # 要改善。
                                    self.version = 2.0
                                    break
    
                    self.Version = list()
                    self.meta = list()
                    self.start = list()
                    self.move = list()
                    self.comments = list()
    
                    for line in self.lines:
                            if(line[0]=="V"):
                                    self.Version.insert(len(self.Version), line)
                            elif(line[0]=="$" or line[0]=="N"):
                                    self.meta.insert(len(self.meta), line)
                            elif(line[0]=="P" or (line[0]=="+" and not curses.ascii.isalnum(line[1])) or (line[0]=="-" and not curses.ascii.isalnum(line[1]))):
                                    self.start.insert(len(self.start), line)
                            elif(line[0]=="T" or (line[0]=="+" and curses.ascii.isalnum(line[1])) or (line[0]=="-" and curses.ascii.isalnum(line[1]))):
                                    self.move.insert(len(self.move), line)
                            elif(line[0]=="'" or line[0]=="#"):
                                    self.comments.insert(len(self.comments), line)
    
    def test():
            r = csarecord("s.csa")
            print r.version
            print r.todict()['start']
    

    P.S.

    preタグの中でなんかシングルクオートがおかしなことになってるなぁ...
    syntaxhighlighterの都合なのか??ちょっと原因が思いつかない。