見出し画像

複数回攻撃用のパーサ実装

複数回攻撃用のパースを実装することにした。オリジナルのソースコードでは、使用するメモリ量を節約するためなのか、関数fightでダメージ文字列をリアルタイムにパースしている。

パースしている部分だけを抜粋すると次のようになっている。

--- fight.c ---
362: for (;;)
363: {

         // code

379:     ndice = atoi(cp);
380:     if ((cp = index(cp, 'd')) == NULL)
381:         break;
382:     nsides = atoi(++cp);

         // code

400:     proll = roll(ndice, nsides);

         // code

407:     if ((cp = index(cp, '/')) == NULL)
408:         break;
409:     cp++;
410: }

当時はこのようなやり方がよかったのかもしれないけれど、ソースコードも読みづらくなるし、簡素なパーサを実装して、ダメージ計算用の値を保持させたほうが良さそう。

class Rolls(object):
   def __init__(self, damageString=""):
       self.rolls = []
       if damageString != "":
           self.parse(damageString)

   def parse(self, damageString):
       self.rolls.clear()
       for damage in damageString.split("/"):
           dice, sides = damage.split("d")
           self.rolls.append(( int(dice), int(sides) ))

さっそくテストコードを書いてみる。

   rolls = Rolls("1d1/2d12")
   print(rolls.rolls)

簡単なパース処理なので問題なさそうだ。ダメージ文字列の妥当性チェックはあとから追加する。

--- 実行結果 ---
[(1, 1), (2, 12)]

オリジナルのソースコードでは、永久ループをしながら処理をしていたけれど、先にパースをしてから処理できるので、次のように書き直せる。

for r in rolls:
    // code

この調子でソースコードを整理していこう。

この記事が気に入ったらサポートをしてみませんか?