0

したがって、これは複雑になる場合とそうでない場合があります。うまくいけば、そうではありません。いずれにせよ、私は暇なときにかなり野心的なPythonテキストゲームを書いていて、それができるかどうかを確認しています。インタラクティブフィクションエンジンやパーサーなどがたくさんあることに気づきましたが、私はそれをゼロからやっています。それは私が学ぶ方法です-難しい方法だと思います。

それで、これがどのように分解するかです:

  • engine.pyモジュールにmain()関数があります。この関数は、部屋のオブジェクトを取得して部屋の説明を表示します。次に、ユーザー入力を待機し、パーサーに送信します。
  • parser.pyモジュールのパーサーは、ユーザー入力を実行し、Sentenceオブジェクト(動詞とオブジェクトで構成されます-名詞または方向にすることができます)を構築します。Sentenceオブジェクトには、command.pyモジュール内からxxxCommandクラスを呼び出す出力関数もあります。
  • 例:「gonorth」と入力すると、パーサーはそれを適切な文として受け入れます。したがって、パーサー出力関数はGoCommandクラスを検索します。

今ここで私は問題を抱えています。続行する前に、わかりやすくするために、Engine&Sentenceクラスを貼り付けます。

class Engine(object):
    def __init__(self, start_room):
        self.L = lexi.Lexicon() #Imported earlier
        self.P = parser.Parser() #Imported earlier
        self.room = start_room

    def main(self):
        while True:
            self.room.describe() #Describes the current room.

            # Ask for user prompt
            input = raw_input(self.room.prompt)
            cmd = input.lower()

            # Scans user input & creates tokens from Lexicon table
            # For example: [('verb', 'go'), ('direction', 'north')]
            tokenizer = self.L.scan(cmd)

            # Runs through tokens and creates a sentence object
            # With noun & object attributes
            parsed_sentence = self.P.parse_sentence(tokenizer)

            # See below
            parsed_sentence.output(self.room)


class Sentence(object):

    def __init__(self, verb, noun):
        self.verb = verb[1]
        self.obj = noun[1]

    # There's a command module with different xxxCommand classes with an execute method
    # as seen on last line. So pretend the command module has already been imported.
    def output(self, current_room):
        verb = self.verb.capitalize()
        obj = self.obj
        command = getattr(commands, '%sCommand' % verb)(obj)
        command.execute(current_room)   

さて、その長い風のセットアップの後、私は次のようなGoCommandクラスを持っています:

# Subclassed from Command parent class. Has one method called execute. Does nothing else.
class GoCommand(Command):
    def __init__(self, direction):
        self.direction = direction

    def execute(self, current_room):
        # 'E' is the instantiation of the Engine class, declared within engine.py
        from engine import E

        # self.direction is 'north' in our example
        # current_room.map is a dict within any Room class named 'map'.
        # For example: Intro.map = {'north': char_intro }
        if self.direction in current_room.map:
            print "You head %s\n" % self.direction # Pretty explanatory

            # HERE'S WHERE I HAVE TROUBLE
            E.room = current_room.map[self.direction]
        else:
            print "You can't go that way."

したがって、私が達成したいと思っていたのは、ループが終了すると、E.roomはchar_introという部屋のクラスと等しくなり、ループが再び実行されると、char_introの説明が表示され、基本的に最初からやり直します。

これは何が起こっているのかではありません。それはただ最初の部屋にとどまります。GoCommand.execute()が実行されていますが、E.roomは変更されません。誰もが理由を知っていますか?

親愛なる神様、これは長いことだと思いますが、誰かが私が話していることを知っていて、私を助けてくれることを願っています。ユーザーが北に行くと言ったときに北に設定されたパスがある場合に部屋のクラスを変更するように、これをどのように修正する必要がありますか?

4

2 に答える 2

0

私自身の質問に答えるために、Engine.main()のループは想定どおりに機能しますが、whileステートメントからself.room.describe()を削除しました。

def main(self):
    self.room.describe() #Describes the current room.
    while True:
        # Ask for user prompt
        input = raw_input(self.room.prompt)
        cmd = input.lower()
        ...etc, etc, etc...

次に、GoCommandを次のように変更しました。

class GoCommand(Command):
def __init__(self, direction):
    self.direction = direction

def execute(self):
    # 'E' is the instantiation of the Engine class, declared within engine.py
    from engine import E

    # self.direction is 'north' in our example
    if self.direction in E.room.map.keys():
        print "You head %s\n" % self.direction # Pretty explanatory

        E.room = E.room.map[self.direction]
        print E.room.describe()
    else:
        print "You can't go that way."

そして、すべてが想定どおりに機能します。

于 2012-12-16T05:44:30.573 に答える
0

したがって、ゲームの状態(現在の部屋、在庫)がエンジンに保持されているように見えます。比較のために、http://www.ptmcg.com/geo/python/confs/adventureEngine.py.txtでコマンド解析演習として作成したテキストアドベンチャーゲームを確認してください。そのコードでは、現在の部屋とインベントリをPlayerインスタンスに保持しました。メインのゲームループは次のようになります。

parser = Parser()
p = Player("Joe")
p.moveTo( startRoom )
while not p.gameOver:
    cmdstr = raw_input(">> ")
    cmd = parser.parseCmd(cmdstr)
    if cmd is not None:
        cmd.command( p )

parseCmd入力文字列を解析し、有効な場合は、command(p)pがプレーヤーである場所を実装するコマンドオブジェクトを返します。コマンドは、プレーヤーを介して、現在の部屋、現在のインベントリ、および特別なプレーヤーの状態やスキルにアクセスできます(たとえば、視力が高いプレーヤーは、特定の部屋に入るときにトラップを検出する可能性が高くなります)。これにより、エンジン自体のグローバルや属性をモックする代わりに、モックプレーヤーを使用してコマンドをテストするのも簡単になります。

于 2012-12-16T09:13:24.710 に答える