MUDスタイルのテキストベースの世界でレベル/部屋を整理する


12

私は小さなテキストベースのアドベンチャーゲームを書くことを考えていますが、技術的な観点から世界をどのように設計するべきかは特にわかりません。

私の最初の考えは、XMLでそれを行うことで、次のようなものを設計しました。XMLの膨大な山をおologiesびしますが、私が何をしているかを完全に説明することが重要だと感じました。

<level>
    <start>
        <!-- start in kitchen with empty inventory -->
        <room>Kitchen</room>
        <inventory></inventory>
    </start>
    <rooms>
        <room>
            <name>Kitchen</name>
            <description>A small kitchen that looks like it hasn't been used in a while. It has a table in the middle, and there are some cupboards. There is a door to the north, which leads to the garden.</description>
            <!-- IDs of the objects the room contains -->
            <objects>
                <object>Cupboards</object>
                <object>Knife</object>
                <object>Batteries</object>
            </objects>
            </room>
        <room>
            <name>Garden</name>
            <description>The garden is wild and full of prickly bushes. To the north there is a path, which leads into the trees. To the south there is a house.</description>
            <objects>
            </objects>
        </room>
        <room>
            <name>Woods</name>
            <description>The woods are quite dark, with little light bleeding in from the garden. It is eerily quiet.</description>
            <objects>
                <object>Trees01</object>
            </objects>
        </room>
    </rooms>
    <doors>
        <!--
            a door isn't necessarily a door.
            each door has a type, i.e. "There is a <type> leading to..."
            from and to are references the rooms that this door joins.
            direction specifies the direction (N,S,E,W,Up,Down) from <from> to <to>
        -->
        <door>
            <type>door</type>
            <direction>N</direction>
            <from>Kitchen</from>
            <to>Garden</to>
        </door>
        <door>
            <type>path</type>
            <direction>N</direction>
            <from>Garden</type>
            <to>Woods</type>
        </door>
    </doors>
    <variables>
        <!-- variables set by actions -->
        <variable name="cupboard_open">0</variable>
    </variables>
    <objects>
        <!-- definitions for objects -->
        <object>
            <name>Trees01</name>
            <displayName>Trees</displayName>
            <actions>
                <!-- any actions not defined will show the default failure message -->
                <action>
                    <command>EXAMINE</command>
                    <message>The trees are tall and thick. There aren't any low branches, so it'd be difficult to climb them.</message>
                </action>
            </actions>
        </object>
        <object>
            <name>Cupboards</name>
            <displayName>Cupboards</displayName>
            <actions>
                <action>
                    <!-- requirements make the command only work when they are met -->
                    <requirements>
                        <!-- equivilent of "if(cupboard_open == 1)" -->
                        <require operation="equal" value="1">cupboard_open</require>
                    </requirements>
                    <command>EXAMINE</command>
                    <!-- fail message is the message displayed when the requirements aren't met -->
                    <failMessage>The cupboard is closed.</failMessage>
                    <message>The cupboard contains some batteires.</message>
                </action>
                <action>
                    <requirements>
                        <require operation="equal" value="0">cupboard_open</require>
                    </requirements>
                    <command>OPEN</command>
                    <failMessage>The cupboard is already open.</failMessage>
                    <message>You open the cupboard. It contains some batteries.</message>
                    <!-- assigns is a list of operations performed on variables when the action succeeds -->
                    <assigns>
                        <assign operation="set" value="1">cupboard_open</assign>
                    </assigns>
                </action>
                <action>
                    <requirements>
                        <require operation="equal" value="1">cupboard_open</require>
                    </requirements>
                    <command>CLOSE</command>
                    <failMessage>The cupboard is already closed.</failMessage>
                    <message>You closed the cupboard./message>
                    <assigns>
                        <assign operation="set" value="0">cupboard_open</assign>
                    </assigns>
                </action>
            </actions>
        </object>
        <object>
            <name>Batteries</name>
            <displayName>Batteries</displayName>
            <!-- by setting inventory to non-zero, we can put it in our bag -->
            <inventory>1</inventory>
            <actions>
                <action>
                    <requirements>
                        <require operation="equal" value="1">cupboard_open</require>
                    </requirements>
                    <command>GET</command>
                    <!-- failMessage isn't required here, it'll just show the usual "You can't see any <blank>." message -->
                    <message>You picked up the batteries.</message>
                </action>
            </actions>
        </object>
    </objects>
</level>

明らかに、これ以上のものが必要です。人や敵との相互作用だけでなく、死や完了も必要な追加です。XMLを扱うのは非常に難しいので、おそらくある種のワールドエディターを作成します。

この方法に欠点があるかどうか、そしてそれを行うための「より良い」またはより標準的な方法があるかどうかを知りたい。


3
個人的には、XMLをシリアル化形式以外のものとしては扱いません。「どういうわけかこれをディスクに読み書きする」という質問(XML、JSON、プロトコルバッファー、カスタムバイナリ形式などを使用)を抽象化すると、質問は「どのデータを保存する必要があるか」になります。 「これは、ゲームの要件に応じて、あなただけが本当に答えることができるものです。
テトラッド

いい視点ね。しかし、私はゲームがこのようなスタイルを使用するのを見たことがあり、それらは本当に制限的であることが判明しました。ただし、この場合、ゲームのフローとロジックは非常に単純なので、うまく機能し、スクリプトエンジンを実装する手間を省くことができます。私は主に、そのような固定構造(別の部屋、ドア、オブジェクト、定義ファイル内の変数)が実行可能かどうかに関心があります。
多項式

Tetradをエコーし​​ないようにしますが、ワールドエディターの作成を計画している場合(ゲームが非常に短くなる場合を除き、これをお勧めします)、ファイル形式は作業するため、違いはありません編集者、部屋のハードコーディング。
マイク・クラック

回答:


13

C#に完全に慣れていない場合、これを行う「より標準的な」方法は、この種のゲームを作成するのに役立つ既存のテキストアドベンチャー作成ツールの1つを使用することです。これらのツールは、すでに機能しているパーサー、死の処理、保存/復元/元に戻す、キャラクターの相互作用、およびテキストアドベンチャー機能の他の同様の標準ビットを提供します。現在、最も人気のあるオーサリングシステムはInform、およびTADSです(ただし、他にも半ダースが利用可能です)

Informは、Infocomゲームで使用されるほとんどのZ Machine仮想マシン命令セット、または最新のglulx仮想マシン命令セットにコンパイルできます。一方、TADSは、独自の仮想マシンコードにコンパイルします。

どちらのタイプのバイナリも、ほとんどの最新のインタラクティブなフィクションインタープリターで実行できます(昔は、GLDSゲームのZMachineゲームとTADSゲームの別々のインタープリターが必要だったことがありました。必要なプラットフォームについて。Mac / PC / Linux / BSD / iOS / Android / Kindle / browser / etc。あなたはすでにクロスプラットフォームをうまく持っており、本当に世話をしました。

ほとんどのプラットフォームで、現在推奨されているインタープリターはGargoyleですが、他にもたくさんありますので、お気軽に実験してください。

Inform(特に最新バージョン)のコーディングは慣れるのに少し時間がかかります。なぜなら、それはエンジニアよりも作成者に向かってマーケティングを行っているからです。Inform 7の構文では、例は次のようになります。

"My Game" by Polynomial

Kitchen is a room. "A small kitchen that looks like it hasn't been used in a 
while. It has a table in the middle, and there are some cupboards. There is a 
door to the north, which leads to the garden."

In the Kitchen is a knife and some cupboards.  The cupboards are fixed in 
place and closed and openable.  In the cupboards are some batteries.

Garden is north of Kitchen. "The garden is wild and full of prickly bushes. 
To the north there is a path, which leads into the trees. To the south there 
is a house."

Woods is north of Garden.  "The woods are quite dark, with little light bleeding 
in from the garden. It is eerily quiet."  

Trees are scenery in the Woods.  "The trees are tall and thick. There aren't any 
low branches, so it'd be difficult to climb them."

TADSは従来のプログラミング言語のように見えますが、TADSの同じゲームは次のようになります。

#charset "us-ascii"
#include <adv3.h>
gameMain: GameMainDef
    initialPlayerChar = me
;
versionInfo: GameID
    name = 'My Game'
    byline = 'by Polynomial'
;
startroom: Room                  /* we could call this anything we liked */ 
    roomName = 'Kitchen'         /* the displayed "name" of the room */ 
    desc = "A small kitchen that looks like it hasn't been used 
            in a while. It has a table in the middle, and there 
            are some cupboards. There is a door to the north, 
            which leads to the garden." 
    north = garden         /* where 'north' will take us */ 
; 

+me: Actor
; 

cupboards: OpenableContainer
    vocabWords = 'cupboard/cupboards' 
    name = 'cupboards' 
    isPlural = true
    location = startroom 
; 
battery: Thing
    name = 'battery'
    location = cupboards
;
knife: Thing
    name = 'knife'
    location = startroom
;
garden: Room
    roomName = 'Garden'
    desc = "The garden is wild and full of prickly bushes. To the 
            north there is a path, which leads into the trees. To 
            the south there is a house." 
    north = woods
    south = startroom
; 
woods: Room
    roomName = 'Woods'
    desc = "The woods are quite dark, with little light bleeding 
            in from the garden. It is eerily quiet."
    south = garden
;
trees: Decoration
    desc = "The trees are tall and thick. There aren't any low 
            branches, so it'd be difficult to climb them."
    location = woods
;

両方のシステムは無料で利用でき、非常に頻繁に使用され、チュートリアルに関するドキュメントが豊富にあります(上記のリンクから入手できます)。

2つのシステムの標準動作は微妙に異なることに注意してください(ただし、両方とも変更できます)。Informソースからコンパイルされた、プレイ中のゲームのスクリーンショットを次に示します。

スクリーンショットを通知する

そして、Tadsソースからコンパイルされた、プレイ中のゲームの1つ(ターミナルの内部–タイポグラフィはこれよりもはるかに良い場合があります)です。

TADS3スクリーンショット

注意すべき興味深い点:TADSでは、デフォルトで右上に「スコア」表示があります(ただし、オフにすることができます)が、Informはありません(ただし、オンにすることはできます)。Informはデフォルトで、部屋の説明内のアイテムの開閉状態を通知しますが、Tadsは通知しません。Tadsは、プレイヤーコマンドを実行するために(ユーザーが指示しない限り)自動的にアクションを実行する傾向がありますが、Informは(ユーザーが指示しない限り)実行しない傾向があります。

どちらも任意の種類のゲームの作成に使用できます(どちらも高度に構成可能であるため)が、Informは、TADSがより構造化されたモダンなスタイルのインタラクティブフィクション(多くの場合、最小限のパズルとよりナラティブな)の生成に向けてより構造化されています古いスタイルのテキストアドベンチャーの作成に向けて(多くの場合、パズルに強く焦点を当て、ゲームの世界モデルのメカニズムを厳密に定義します)。


これは非常にクールで有益ですが、imoは質問に答えません。基本的にこれとまったく同じ質問をするつもりでした。このXMLが有効なアプローチであるかどうか、またはこのXMLが持つ落とし穴や弱点があるかどうかについて詳しく知りたいと思います。
DLeh 14

1
@DLeh質問は、「この方法に問題があるかどうか、そしてそれを行うための「より良い」またはより標準的な方法があるかどうかを知りたい」というものでした。この答えは、やっている
トレバーパウエル14

しかし、「落とし穴と弱点」について質問したので、Informの実装は19行です。TADSの例は40行です。XML実装には126行が必要です(80カラムでワードラップされ、読みやすさのために空白が含まれていた場合、InformおよびTADS実装と同じようにさらに長くなります)。
トレバーパウエル14

InformとTADSの例は、はるかに短いことに加えて、より多くの機能をサポートしています。たとえば、両方でナイフを食器棚に入れることができますが、これはXMLバージョンではまったくサポートされていません。
トレバーパウエル14

1
XMLバージョンでは、食器棚の内容が食器棚の説明に組み込まれていることにも注意してください。つまり、(開いている)食器棚を開いたり見たりするときに何を印刷するかを示すハードコード化されたメッセージがあり、電池が入っていることがわかります。しかし、プレーヤーがすでにバッテリーを使用している場合はどうなりますか?XMLバージョンでは、電池が内部にあることがわかります(表示できる文字列はそれだけなので)。一方、InformおよびTADSバージョンでは、食器棚が空であることを示します。
トレバーパウエル14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.