本書はTADS製作者用手引きの一部です。
Copyright © 1987 - 2000 by
Michael J. Roberts. All rights reserved.
この手引きのHTMLへの変換及び編集はN. K. Guy,tela design.が行いました。
第9章
これに先立つ数章は言語、パーサー・インタフェース、そしてオブジェクト指向プログラミングの一般原理まで含む基礎の大部分を扱ってきました。TADSはとても豊富なオプションを用意しているので、初めてTADSに取り組む場合は、なにかをしようとしても一番良い方法がなかなか分からないということが珍しくありません。
本章はTADSによってゲームを記述する過程全体を通して手助けとなるように意図されています。また、TADS言語の動作に関する基本概念を理解していることを前提とします。
筆者はいくつかのテキストアドベンチャーゲームのデザインと実現に関わってきました。ここに示したゲーム開発の過程はそれらのプロジェクトから得た経験を反映しています。
最初の一歩はゲームをデザインすることです。TADSのようなシステムを使うとゲームに取りかかることがとても楽になるので、ゲームにすぐ飛びついてプログラミングを始めたくなるかもしれませんが、むしろコンピュータを終了させてメモ帳を出してください。
私たちはDeep Space Drifterの時、この忠告に従いませんでした。ゲームの大体のプロットを考え、宇宙ステーションで起こる部分(およそゲームの前半)の計画を地図化すると、実装を始めてしまいました。ゲームの後半の基本的アイデアは持っていましたが、地図にはしませんでした。
実装はしばらくの間うまくいきましたが、進めるにしたがって、まだデザインしていない後半部分の細部に依存する前半部分の詳細にさしかかりました。私たちは一部の細部だけ間に合わせに作り、それ以外のものを後回しにしました。そのせいで、奇妙なことが起こってしまったのです。プロットの穴と、細部について考えざるをえなくなるまで私たちに起こったことがなかった奇妙でささいな矛盾の存在が分かり始めたのです。その結果、私たちは後半部分についての基本的アイデアの変更を開始しましたが、それがかえって矛盾とプロットの穴を拡大させました。まるで砂の中の穴掘りのようでした。私たちは程なく後半部分についての当初の計画をまるごと放棄して一からやり直すことを決定しました。
とはいえ、私たちは宇宙ステーションに膨大な時間と努力を費やしていたので、放棄したくはありませんでした。私たちは代わりに、すでに存在する前半部に適合する新しい後半部をデザインしようとしました。今にして思えば、この戦いは敗北でした。私たちは、一つ一つの新しいプロットをさらに大きな既存の実装に合わせる努力をしながら、本質的にゲームに関係ないプロットの連続を突っ切ったのです。わずかな計画を立てては実行し、その後でその計画がうまくいっていないこと、だから廃止しなければいけないこと―しかし自分たちが行ったプログラミング作業は維持されてしかるべきだということを悟りました。あの沼地、洞穴の迷路、シャトルは私たちがそれらの放棄に踏み切れなかったほど膨大な作業を象徴していたので、私たちが提案したものはすべてそれらをなんとか含めざるを得なかったのです。しばらくの間、私たちは実際に沼地を「沼地シミュレータ」にするつもりでした。というのはそれが沼地を適合させる唯一の方法だったのです。
結局、私たちはDeep Space Drifterの製作に完全にうんざりしてしまいましたが、精神的な理由でプロジェクトを完成させずに死なせてしまうことは拒否しました。私にとっては、この態度はゲームの後半を通じて姿を見せています。たとえば、惑星上に次のような説明を持つ部屋があったと思います:「この部屋はとっても退屈だ。あなたは北に行けます」。実際、ゲーム全体がその歴史を反映していると思います。宇宙ステーションはやることがぎっちり詰まっていて、のりのいいジョークもいくつかあり、おまけにスタイルが一貫しています。その反対に、惑星は空っぽで不毛な印象があります。間延びしていてすることがあまりありません。唯一面白い部分は概して本質的には各パート相互及びゲームに対する関連性がなく、それらが在ってしかるべきかどうかお構いなくゲームの中に押し込まれたことの反映でした。
私はDeep Space Drifterがひどいゲームだと言っているのではありません。あの宇宙ステーションはとても気に入っていますし、惑星上での謎解きはきわめて精巧かつ優雅なものです。しかし、あのゲームには深刻な欠陥がいくつかあり、私はそのほとんどはデザインと実装の長く混乱に満ちた過程のせいだと思っています。
反対にDitch Day Drifterは、デザインと実装の過程がかなり短く円滑に進み、結果としてより良いゲームになったと思います。確かに、DitchはDeepよりずいぶん小さなゲームなのですが、もしも同じデザインの過程をDeepにも適用できていたら、ずっと良いゲームができていただろうと私は確信しているのです。
Ditchのプログラミング作業が始まる前に、私は完全なゲームのマップと、ゲーム内のすべてのオブジェクトと人物の説明をそれらの振る舞いの主な要素を含めて用意していました。そのおかげで実装がとても円滑で楽なものになりました。単にルームとオブジェクトのリストを追って一つ一つ実装していくことができたからです。実装作業中にデザイン上の決定をする必要はまったくありませんでした。このことはすでに決定しているデザイン上の判断を覆えす欲望を打ち消してくれました。ゲームの実装はわずか二、三週間で済み、とても良い出来映えになりました。
もしあなたがデザインが完了する前にプログラミングを始める誘惑に抵抗するなら、あなたのゲームの実現は随分早まり、かなりより良いものになるでしょう。そして、一番重要なこととして、ゲームを完成できる可能性がとても高くなるでしょう。
ゲームの実装を始める前に、ゲーム内のすべての場所、オブジェクト、登場人物のリストを用意しなくてはいけません。ゲーム内の場所、オブジェクト、人物の一つ一つ(これ以降「ゲーム要素」と総称する)にアイテムとその基本的な振る舞いの説明を用意する必要があります。基本的に、自分のゲームについて、ゲーム全体を完了できるぐらいコマンド一つずつに通じていなければいけません。この時点でゲームの細かい部分のすべてを知っている必要はありません。しかし、ゲームを貫く「最短の道」(プレーヤーがゲームの最初から最後まで進むためにタイプする、ミスがなければバックアップを取る必要がないコマンドの連続)に沿った詳細は全部知っているべきです。残っている細部はプロットに影響を与えないので、プロットの穴や矛盾を作り出すことなく進みながら作ることが可能です。
完全なマップとオブジェクトリストはデザイン過程の結果です。そこに行くために、完全なデザインを得るまでの道すがら細部を加えつつ、おそらく多くの段階を経ることになります。ここで述べられる道程はゲームデザインの良き方法です。しかし、自分にもっと合った他の方法をあなたが見つける可能性だってあるのです。
アドベンチャーゲームには大抵、ゲーム全体の流れを左右する基本的なプロットの枠組みがあります。プロットはデザインを始める良い出発点です。
アドベンチャーゲームのプロットは通常、本や映画のような非インタラクティブ形式のフィクションほど緻密に練り上げられていませんが、それは主要人物の行動の詳細についての操作がかなり不自由だからです。このためにプロットデザインは余計に難しくなるわけですが、プレーヤーにはできるだけ操作の自由を与えるべきです。それは、アドベンチャーゲームというものが常に、プレーヤーの操作感を良くすればするほどより満足度の高いものになるからです。したがって、アドベンチャーゲームのプロットは単に、ゲーム中の行動の一般的方向を提供し、重要な出来事だけを指定する枠組みであるべきです。
基本的な背景と目的から取りかかってください。ゲームはどこで起こるのか? いつ? 主人公は誰か? ゲームが終了するまでに何が成し遂げられなければならないのか?
例えば、Ditch Day Drifterでは、その場所がキャル・テックのキャンパス(もしくは、このゲームは現実のキャルテックの厳密に正確なシミュレーションではないのでおそらくパラレル・ユニヴァースのキャルテック)であり、時間は大ざっぱに言えば現在、詳しく言えばディッチ・デーです。主要人物はキャルテックの下級生。目的はホールの向こう側の上級生が作ったディッチデーの「スタック」の解決です。
続いて、ゲームの最終目的を果たすためにたどり着かねばならない主なサブゴールを特定してください。Ditchの中で、主なサブゴールはスタックを説明するノートに列挙されていた宝物を見つけることです。
最終目的から主なサブゴール、そしてそれぞれのサブゴールのために達成しなければならないもっと小さなゴールへ...と逆にたどることでプロット細部の埋め合わせを進めることができます。
私は「プレーヤーは力の指輪を五つ見つけなければならない」といったような大きなサブゴールを持ったゲームはデザインしないように忠告申し上げます。サブゴールがこのように抽象的だと、それを達成するためにしなくてはいけないことを何も示してくれないのです。反対に、サブゴールが「プレーヤーはラジオ放送塔を破壊しなければならない」のように具体的で明確なものだと、小サブゴールはほとんど自動的に導かれます:放送塔がある構内に押し入る必要がある、そしていくらかの爆薬も必要になるだろう、感電死するのを避けるために塔への電源を切る必要もあるかもしれない。しかし、電気を切った場合、なぜ爆破する必要があるのか? たぶん数ターン経つとスタッフがやって来て電力を入れ直してしまうからでしょう。ここでスタッフをあしらうという別のパズルが出てきました。五つの力のリングを見つけるといった抽象的なサブゴールは細部の次のレベルに進む助けにほとんどなりません。具体的なサブゴールの場合、あなたの想像がほとんど自動的にプロット要素の完全なセットにまで拡張していく種をもたらしてくれることが珍しくないのです。
基本的プロットはゲームの全般的設定を提供し、プロット要素はたいてい大規模なロケーションの明確な一式を差し示してくれます。ですから、あなたは基本的なプロットをデザインすることで「低解像度の」マップから始めることになります。
次に、特定のルームを埋め始めてください。この時点で、あなたはおそらく設定の詳細を詰めると同時にプロットの詳細も埋め始めたことに気づくでしょう。設定の中のたくさんの場所は自然なパズルを提供します。例えば、銀行が出てくるとしたら、おそらく鍵の組み合わせを見つけなくてはならないような金庫もあるでしょう。もしかしたら、警報システムを克服する方法を知る必要があるかもしれません。あるいはひょっとしたら、出納係の気をそらせるなにかが必要かもしれません。セーフティー・デポジット・ボックスの鍵を見つけなければいけないかもしれません。空港があるとしたら、ひどく敏感な金属探知機を通過する方法を見つけたり、誰かの旅程を知ったり、航空券を発見したり、立ち入り禁止区域に入るためのバッジや鍵や数字の組み合わせを知る必要がおそらくあるでしょう。
デザインする場所がどんな類であるにせよ、その場所が解くべき難題の連続を暗示してくれることがよくあります。その難題の解決方法をデザインするにしたがってプロットに細かな肉付けをすることになり、それが今度は新しい場所の開発を誘導するのです。
設定に肉付けするにつれて、自分が作る場所に広大な空間を加えたくなるかもしれません。例えば、空港を組み立てている場合に、いくつもの似たり寄ったりのゲートに打ち込んでいる自分に気づくかもしれません。空間を付け加えることでゲームの設定は現実の空港に近づきますが、ゲームの遊びやすさは反対に損なわれてしまいます。あなたは空港ではなくゲームをデザインしていることを忘れないでください。一番大事なことはゲームを遊んでいて楽しいものにすることであって、「本物っぽく」することではありません。
本質に関わる利用はされない空間をたくさんゲームに加えることの主な問題点は、それがゲームを通しての細部のレベルの一貫性を低下させがちだということです。プレーヤーを苛立たせたり戸惑わせたりしないように、ゲームを通して細部のレベルをできるだけ一定にする努力をすべきです。(検査と操作が可能なたくさんのオブジェクトのような)膨大な量の細部を持った部屋がいくつか存在すれば、プレーヤーは他の部屋でも同程度の細部を予期するでしょう。ほとんど同じの空港ゲートがいくつあっても面白いことはなにもありません。
設定とプロットを紙に記す作業を通じてあなたはおそらくゲームの大部分のデザインを終えているでしょう。プロット要素を開発するに従ってそこに含まれるオブジェクトと人物を書いておく必要があります。オブジェクトと人物をマップ上のそれらが置かれる場所に書いておくのがおそらく一番簡単な方法でしょう。
一つ一つのオブジェクト及び人物について、そのゲームへの関連性とそれが行う事柄を記してください。一つの目的のために他のオブジェクトが利用されるかもしれない、または、あるオブジェクトに別の利用法があるかもしれないという問題について慎重に考える必要があります。例えば、あるドアを破壊する必要があるとしたときに、この目的のために斧を一つ用意するつもりなら、次の二つの問題を考慮すべきです: その斧は破壊以外にどんなことが合理的に期待されるか? ドアを破壊できると合理的に期待される他のものはなんだろうか?
プレーヤーは一本の斧にたくさんの使い方がある、そして多くのものがドアを壊せると合理的に予想するので、暴力及び一般的な役割を持つ力強い道具を含む謎を創る場合にはくれぐれも慎重に臨んでください。爆薬、引火性の強い液体、武器、重たい道具などはみな、物理的な障害物をなんら除去しないとなるとプレーヤーを失望させそうです。一方、労を惜しまず、斧が理屈の許すあらゆるものを壊せるように、ドアを別の合理的なものが壊せるようにして斧とドアを完全に実現すれば、とても満足度の高いものになります。
ゲームのデザインを完全に終えたのなら、実装を始める準備は整っています。このセクションでは、基本的な種類のオブジェクトを実装する方法をお目にかけます。
マップを描くこと、そして、そのマップの上にプロットの本質的詳細を説明する注釈を書き込むことから始めましょう。これにはゲーム内の主なオブジェクトの配置、プレーヤーが実行しなければならない重要な行動の説明を含めてください。
一例として、小さな空港で起こるゲームを実装してみましょう。この空港にはターミナル区域、コンコース、ゲート区域があります。ゲートの一つに停められた飛行機も一機あります。ターミナル区域にはチケットカウンタ、コンコースに通じる金属探知機があります。コンコースには、スナック・バーと、セキュリティーエリアに通じる鍵がかかったドアがあります。ゲート区域には一対のゲートに加えて鍵のかかった整備室があります。ここに私たちが実装を進めることになる基本的マップがあります。
このマップには都合良く、謎解きに使えそうな一対の錠が下ろされた区域があります。さらに、プレーヤーが何らかのオブジェクトを持って通過するのを阻止する金属探知機にもおそらくなんらかの用途を見い出せるでしょう。飛行機も謎になりえます。というのは、飛行機に搭乗するには普通チケットが要るからです。さらに操縦室は乗員以外は立ち入り出来ません。
空港部分の目的を空港から抜け出すことにしましょう。プレーヤーはメインターミナル区域から出発しますが、ターミナルの外に出ることが出来ないのです―人通りが激しいので決まってプレーヤーをターミナルの中に押し戻してしまうなどの、抜け出させない理由をいくつか考えましょう(これが実際のゲームなら、空港の外にもゲームを設けたはずなので、激しい人通りがプレーヤーを中に押し返すというような人工的な境界を用いることはしなかったでしょう。ですが、この例では問題を小さくしておきたいのです)。空港から抜け出すための外に唯一の明らかな方法は飛行機に乗って飛び出すことです。そこで、目的を飛行機を飛ばすことにします。
飛行機を空港の外に出すために、プレーヤーは操縦室に入る必要があります(私たちはこの実例をプレーヤーが操縦室に入り込むところまで実装します。完全なゲームであるならば、プレーヤーが飛行機をどこかへ飛ばすところまで続けるはずです)。ところで、操縦室へはパイロットしか行けません―客室乗務員は乗客を操縦室に行かせてくれません。ですから私たちは乗務員を突破する方法が要ります。一つの方法が素早く通り抜けるに十分なだけ乗務員の気をそらすことです。しかし、この実例では、プレーヤーにパイロットの制服を見つけることを要求することにします。
パイロットの制服はどこにあるのでしょうか? パイロットのラウンジは理にかなった場所でしょう。そこで、制服が入ったスーツケースをパイロット用ラウンジに置くことにします。幸い、ラウンジは鍵がかけられているドアの向こうですので、これは二次的な謎解きを生みます。パイロットのラウンジがある立ち入り禁止区域に入り込むために、プレーヤーは立ち入り禁止区域の外にあるスロットに差し込む磁気IDカードが必要です。
私たちはIDカードを屋外やターミナル区域のチケットカウンタの上で差し出します。しかし、IDカードを持って金属探知機を通過するのは不可能だということにしましょう。カードは金属探知機を作動させ、警備員に没収されて(プレーヤーがもう一度試せるようにさらにカウンタ上に戻されて)しまいます。カードが金属探知機をくぐり抜けるようにするには金属探知機の電源を切らなくてはなりません。
電源スイッチは鍵がかけられている整備室にあります。鍵は他の整備道具と一緒に飛行機のバスルームに置きます、それから鍵はおそらく整備室のものだろうということが連想により明らかになるよう、バケツ、スポンジ、ごみ袋も置くことにします。
飛行機のバスルームに入るには、飛行機の搭乗チケットが要ります。チケットはずいぶん見つけやすくしましょう。スナックバーにある新聞の中に潜ませるのです。新聞を手に取るだけですぐにチケットが出てくるようにしましょう。
そういうわけで、ゲーム全体は次のようになります:スナックバーに行く、新聞を取る、チケットを見つける。チケットを取り、飛行機に乗る、そして飛行機のバスルームに行って鍵を入手する。整備室の鍵を取ってドアを開け、中に入り、金属探知機の電源を切る。チケットカウンタに戻り、IDカードを取り、セキュリティードアに行き、磁気カードをスロットに入れて、立ち入り禁止区域に入る。パイロット用ラウンジに行き、スーツケースからパイロットの制服を出す、そしてそれを着る。飛行機に行き、乗員をうまくすり抜けて操縦室に行く。
ここで新しいマップを描いておきましょう。これはゲームを作る主要なオブジェクトと行動の注釈を含んでいます。
初めの一歩はマップの骨格をゲームプログラムの発端に変換することです。この時点ではマップの詳細な行動をすべて入力しようとする必要はありません。基本的なルームとルーム間のつながりだけを組み立ててください。これにより素早く実行できるゲームの原型を得て、ゲーム内を歩き回りその雰囲気を知ることが可能になります。
ゲームのソースファイルを作り、次のように基本定義ファイルを含めることから始めましょう:
#include <adv.t> #include <std.t>いつものように、#includeコマンドの前にスペースが皆無であることを絶対に確かめてください。#は行の最初の記号でなければいけません。
次に、ゲーム内の各ルームについて、ルームの名前(sdescつまり、短い説明)と長い説明(ldesc)、そしてそのルームにつながっている他のルームを記入しましょう。ここに上のサンプルマップの最初の数ルームをどう実装するのか示します。当分、長い説明を完全なものにしようと神経を使う必要はあまりありません。それらの肉付けは常に後から行えるからです。
terminal: room sdesc = "Terminal" ldesc = "You are in the airport's main terminal. To the east, you see some ticket counters; to the north is the main concourse. " east = ticketCounter north = securityGate ; ticketCounter: room sdesc = "Ticket Counter" ldesc = "You are in the ticket counter area. Ticket counters line the north wall; so many people are waiting in line that you're sure you'll never manage to get to an agent. The main terminal is back to the west. " west = terminal ; securityGate: room sdesc = "Security Gate" ldesc = "You are at the security gate leading into the main concourse and boarding gate areas. The concourse lies to the north, through a metal detector. The terminal is back to the south. " north = concourse south = terminal ; concourse: room sdesc = "Concourse" ldesc = "You are in a long hallway connecting the terminal building (which lies to the south) to the boarding gates (which are to the north). To the east is a snack bar, and a door leads west. Next to the door on the west in a small slot that looks like it accepts magnetic ID cards to operate the door lock. " north = gateArea south = securityGate east = snackBar west = securityArea ;他のルームは同じように実装されます。今はルームに含まれるアイテム、周辺の他の人々、さらに鍵のかかったドアさえ考慮しません。すべてのルームを実装し、マップを歩き回って試験できるようにするだけです。
次の段階はゲームを構成する基本的オブジェクトを実装することです。ルームと同様、現時点で一部のオブジェクトの複雑な振る舞いに注意を払う必要はありません。ゲーム内の主なアイテム用の基本的オブジェクト定義をざっと書けばいいのです。
アイテムはルームとは異なるプロパティーを持っています。アイテムの基本的プロパティーは、その名前(sdesc)、長い説明(ldesc)、ボキャブラリー・ワード(noun及びおそらくadjective)、そしてコンテナ(location、ルームあるいは別のアイテムである)です。そのアイテムがプレーヤーが持ち運べるものなら、そのオブジェクトはitemクラスに属します。そうでない場合、fixeditemクラスに属します。中には別のクラスに属するアイテムがあります。例えば、(バケツのように)他のオブジェクトを収納できるオブジェクトを作りたいときは、それをcontainerにします。オブジェクトを別のオブジェクトの上に置けるようにしたいなら、surfaceオブジェクトを使ってください。お望みなら、containerとsurfaceとfixeditemを兼ねるようなものも作れます。
ここにサンプルゲーム用の基本的オブジェクト定義の一部を示します。
counter: fixeditem, surface location = ticketCounter noun = 'counter' adjective = 'ticket' sdesc = "ticket counter" ; IDcard: item location = counter noun = 'card' adjective = 'id' 'identification' sdesc = "ID card" adesc = "an ID card" ; newspaper: readable location = snackBar noun = 'newspaper' 'paper' adjective = 'news' sdesc = "newspaper" ldesc = "It's today's copy of USA YESTERDAY. " readdesc = "You read a few articles, and promptly become depressed. The federal deficit just went up by another twenty billion dollars, but it's all \"off budget,\" so it doesn't really count. There's another White House scandal involving illegal arms sales, money laundering through Italian banks, Congressional Pages; several high-ranking federal arts critics have already resigned in disgrace. The economy had yet another downturn, but the President says he's confident that the recovery is \"just around the corner and picking up steam.\" " ; cardslot: fixeditem location = concourse noun = 'slot' adjective = 'card' sdesc = "card slot" ldesc = "The slot appears to accept special ID cards with magnetic encoding. If you had an appropriate ID card, you could put it in the slot to open the door. " ; suitcase: openable isopen = nil location = pilotsLounge noun = 'suitcase' sdesc = "suitcase" ; uniform: clothingItem location = suitcase noun = 'uniform' adjective = 'pilot' 'pilot\'s' sdesc = "pilot's uniform" ldesc = "It's a uniform for an Untied Airlines pilot. It's a little large for you, but you could probably wear it. " ;残りのオブジェクトもほとんど同じように実装します。基本的オブジェクトを実装する上で、記入が必要な主なプロパティーは、location:そのオブジェクトはゲーム内のどこかに出現します。noun:プレーヤーはそのオブジェクトに言及します。そしてsdesc:システムがメッセージ内のオブジェクトに言及するとき、システムは確かにそのオブジェクトをどう呼ぶか知っています。余計な手間をかけずにオブジェクトの基本的振る舞いを正しく得られるように、その都度適切なクラスを選ぶことも重要です。時折、adv.tを逍遙し、そこに定義されているクラスに親しむようにして、adv.tのクラスから得られるものを自然と理解するようになってください。adv.tの完全な説明は付録Aをご覧ください。
次の段階はゲームを真に動かす特別な振る舞いを全部実装することです。例えば、新聞を取り上げたプレーヤーに飛行機のチケットを発見させる単純なメカニズムを実装してみましょう。これを行うためにしなくてはいけないことは、doTakeメソッドをnewspaperオブジェクトに追加することだけです(下では新規のdoTakeメソッドだけを示しますが、オブジェクトの残りの部分は上に示したものと同じです):
doTake( actor ) = { if ( not self.foundTicket ) { "As you pick up the paper, an airline ticket that was inside falls to the floor. " ; ticket.moveInto( actor.location ); self.foundTicket := true; } pass doTake; } ;このメソッドはプレーヤーが新聞を手に取る度に実行されます。私たちが最初に行うことは、チケットが発見済みではないことの確認です。未発見だった場合、発見されたとメッセージを表示し、チケットをゲームの中に移すとともに発見の事実を記録します。最後に、私たちはnewspaperオブジェクトがpass構文の利用によってそのスーパークラス(この場合readable)から継承した既定のdoTakeをもって続行します。
航空券そのものはロケーションを持たない形で定義されるべきであることに注意してください。なぜならゲームが最初に開始されたときにそれはどこにもないからです:
ticket: item noun = 'ticket' adjective = 'airline' sdesc = "airline ticket" ldesc = "It's a one-way ticket to New York, in class C (the \"C\" probably stands for \"Cattle\"). " ;もう一つ別の例として、IDカードがドアを開けるために使用されるまでプレーヤーを立ち入り禁止区域外に留めておく謎解きを実装しましょう。まず、コンコースから立ち入り禁止区域への移動を阻止する必要があります。そのために、私たちはコンコースのルームの定義を変更し、ドアオブジェクトを一つ追加します。
concourse: room sdesc = "Concourse" ldesc = "You are in a long hallway connecting the terminal building (which lies to the south) to the boarding gates (which are to the north). To the east is a snack bar, and a door leads west. Next to the door on the west is a small slot that looks like it accepts magnetic ID cards to operate the door lock. " north = gateArea south = securityGate east = snackBar west = { if ( securityDoor.isopen ) return( securityArea ); else { "The door is closed and locked. "; return( nil ); } } ; securityDoor: fixeditem location = concourse noun = 'door' sdesc = "door" isopen = nil ldesc = { "The door has a label reading SECURITY AREA-AUTHORIZED PERSONNEL ONLY. "; if ( self.isopen ) "The door is open, which isn't very secure. "; else "The door is securely closed. "; } verDoOpen( actor ) = { "The door is securely locked. "; } verDoUnlock( actor ) = { "You should examine the slot if you want to unlock the door. "; }このドアは完全に単なる装飾品です。私たちが実装するいろんなメソッドは、プレーヤーにドアを直接操作することはできないことを知らせるためだけにあります。本当の仕事はカードスロットが果たしますから、オブジェクトに新しい振る舞いをいくつか加えることにしましょう。
cardslot: fixeditem location = concourse noun = 'slot' adjective = 'card' sdesc = "card slot" ldesc = "The slot appears to accept special ID cards with magnetic encoding. If you had an appropriate ID card, you could put it in the slot to open the door. " verIoPutIn( actor ) = {} ioPutIn( actor, dobj ) = { if ( dobj = IDcard ) { if ( securityDoor.isopen ) "あなたはカードをスロットに差し込んだ。しかし 何も起こらないのでカードを抜き取った。"; else { "You put the card in the slot. There's a click, and the security door pops open! You remove the card. "; securityDoor.isopen := true; } } else "That doesn't seem to fit in the slot. "; } ;新しい振る舞いは、プレーヤーがIDカードをスロットに差し込めるということです。これが行われると、ioPutInメソッドがIDカードを直接目的語(dobjパラメータ)にして実行されます。このメソッドはドアがまだ開いていない場合にドアを開けます。
このサンプルゲーム内の残りの謎解きのほとんどは同じように実装されます。それから、一組のアクターを実装する必要が出てくるでしょう。一つは乗員用、もう一つが金属探知機の所にいる警備員です。これに加えて、ロックされたドア数個と特別なアイテムがいくつか必要です。
他の謎解きについては、次の章がそれ以外のものも含めた実装の仕方をずっと詳しく説明しているのでここではこれ以上述べません。
このサンプルゲームに区域を足して拡張する前に、ここまでに実装したものの細部を膨らませてゲームの肉付けを行うようにしてください。追加される材料の大部分はおそらくプロットとは無関係でしょうが、ゲームをより面白く遊んで楽しいものにしてくれます。あなたは現実世界のシミュレータではなく、あくまでもゲームを作っているということを忘れずに、ゲームをもっと遊んで楽しいものにすることに集中するようにしてください。
空港の質を高める道具:スナックバーに信じられないほど高い値段をつけられた非常に怪しいスナックを加える。時々PAシステム上に、ランダムメッセージを生成して色々な人々にホワイトコーテシーテレフォンを取るように頼んだり、旅行者にレッドゾーンに留まらないように警告したりする。整備室内の他の電源スイッチに別の効果を仕込む:スナックバー、チケットカウンタ、PAシステム、自動ドアへの動力を切ったら何が起こるでしょうか。空港内を徘徊する奇妙な人達を多数登場させ、その中の一部の者は積極的にプレーヤーを邪魔する、例えば、散らしを配布しようとする宗教信者や政治的グループなど(彼らのためにめちゃくちゃな散らしを書きたいとあなたは思うことでしょう)。
代替案としては、飛んで行く先をいくつか用意することでこのゲームを拡張できます。プレーヤーは遠く離れた山や無人島に不時着してそこを探検するかもしれません。または、飛行機を他の都市に赴かせて冒険するのもいいかもしれません。
もちろん、一番の喜びは自分自身のアイデアから出発して新しいゲームを丸ごと書くことに見い出せるでしょう。難関は常に良いアイデアを見つけることです。自分のゲームの前提をいったん手に入れれば、あっという間にマップを組み立て、実装を開始できることに驚いてしまうでしょう。この章の実例を出発の手助けとして参考にしてください。あなたのゲームが形になってきて、意欲的な特徴を加えたくなったら、次章に示されたTADSの先進的プログラミング技術が役立つに違いありません。
創造における唯一の難事は始めることである。草の葉がオークよりも入手しやすいとは決して言えないのだ。
JAMES RUSSELL LOWELL, A Fable for Critics (1848)
第8章 | 目次 | 第10章 |