フラグを整理する
部屋中を動き回れるようになったきたので、少しソースコードのリファクタリングすることにした。まずはフラグから始める。
フラグを分類する
オリジナルのソースコードでは、すべてのフラグ値は分類されてなくて、単に列挙されている。まずはこれを分類する。
--- rogue.h ---
126: /*
127: * Various flag bits
128: */
129: #define ISDARK 0000001
130: #define ISCURSED 000001
131: #define ISBLIND 0000001
132: #define ISGONE 0000002
133: #define ISKNOW 0000002
134: #define ISRUN 0000004
135: #define ISFOUND 0000010
136: #define ISINVIS 0000020
137: #define ISMEAN 0000040
138: #define ISGREED 0000100
139: #define ISBLOCK 0000200
140: #define ISHELD 0000400
141: #define ISHUH 0001000
142: #define ISREGEN 0002000
143: #define CANHUH 0004000
144: #define CANSEE 0010000
145: #define ISMISL 0020000
146: #define ISCANC 0020000
147: #define ISMANY 0040000
148: #define ISSLOW 0040000
149: #define ISHASTE 0100000
フラグを分類していくと、5つのカテゴリに収まり、2つの系統(is系とcan系)を持つことがわかる。
分類したフラグを必要な箇所にまとめることで、ソースコードは格段に見やすくなる。
フラグの判定
オリジナルのソースコードでは、フラグの判定を行うためだけに専用のマクロが用意されている。pythonにはマクロがないので、これを関数に落とし込むのはやや抵抗がある。
--- rogue.h ---
51: #define on(thing, flag) (((thing).t_flags & flag) != 0)
52: #define off(thing, flag) (((thing).t_flags & flag) == 0)
Cにはクラスメソッドがないので、こういったマクロが必要になるのはよくわかる。可読性も悪くないし、Cでならいいのかもしれない。
しかし、折角Pythonに移植するのだから、次のようにPythonらしい書き方をしたい。
if room.isDark:
# ダークルームなら
このような書き方を許す一番簡単な方法はクラス変数としてフラグを持たせる方法だけど、一括でフラグをクリアしたい場合に対応することができない。そこで、今回はフラグを管理するためのクラスを作成することにした。
setatter組み込み関数
Pythonのことはよくわからないので調べてみると、デコレータを使って定義済みのクラスに対して後からメンバを追加するsetattr組み込み関数という便利なものがあるらしい。
setatter組み込み関数は、次のように使う。メンバがなければ追加し、メンバがあれば値を上書きしてくれる。
setattr(className, memberName, initalizeValue)
追加したフラグ名のリストをフラグを管理するクラスの初期化時に渡し、初期値をクリアするようにすればよさそう。
実装すると次のようになる。
class Flags(object):
def __init__(self, flagList):
self.flagList = flagList
self.clearAll()
def clearAll(self):
for flag in self.flagList:
setattr(self, flag, False)
さっそくテストコードを書いてみる。
if __name__ == '__main__':
flags = Flags([ "isGone", "isDark" ])
print(flags.isGone)
flags.isGone = True
print(flags.isGone)
問題なさそうだ。
--- 実行結果 ---
False
True
フラグ周りをリファクタリングすることでPythonの新しい書き方を憶えることができ、冗長な書き方をせずに済むようになった。
この記事が気に入ったらサポートをしてみませんか?