ICFP Programming Content 2006: ADVENTURE

の続き。

今回はアドベンチャーを解いてみる。

目次

小ネタ:codex.umzに埋め込まれたCBVロゴ

本編に入る前に。codex.umzをバイナリーエディターで見ると比較的前の方に特徴的な模様があるのがわかる。どうやら1バイトを1画素とする64×64のグレイスケール画像のようで、適当なスクリプト

で抽出してやると

という画像が得られる。Call By Value……じゃなくてCult of Bound Variableのロゴだろうか。

ADVENTUREチュートリアル:keypad修復

howie/xyzzyでログインし、 ./adventure を実行するとアドベンチャーが起動する。その前にREADMEも見ておこう。

;login: howie↵
password: xyzzy↵
logged in as howie


% ls↵
adventure*
README
% cat README↵
README for Adventure

Adventure is a program I wrote for my amusement, but I thought others
might enjoy it as well.

The adventure takes place in the year 19200 in a city called
"Chicago."  I admit it's a bit far-fetched at times -- computers small
enough to be mounted on mobile vehicles, a city so large its residents
have resorted to numbering their streets -- but hopefully my
fantastical story won't obscure the puzzle at the heart of it; I think
it has a nice logic to it.

Have fun!  My high score is 810.

-- Howard Curry

% ./adventure↵
[Building vocabulary]
[Initializing command processor]
[Populating environment]
Room With a Door

You are in a room with a mechanical door. You will probably need
to use a keypad to unlock it. A hallway leads north. 
There is a pamphlet here. 
Underneath the pamphlet, there is a manifesto. 

>: 

これはいわゆるテキストアドベンチャーというやつで、周囲の状況がテキストで描写され、コマンドを入力して進めていくタイプのゲームである。

UMIX起動時に表示される年が19100なので、アドベンチャーの舞台である19200年は作者からすると未来、ということになるのだろうか。

作者のハイスコアが810で、スコアボードに載っている上位チームのADVTRの得点も810点なので、ここでは最大810点を獲得できるということだろう(もしそれより多く獲得できたらeaster eggである)。

ゲームの作者の名前はHoward Curryだそうだ。どっかで聞いたような名前だな……。

とりあえずhelpしてみる。

>: help↵
You can go, take, drop, incinerate, combine, use, examine, show
inventory, and quit. Try 'help <command>' for further details
and synonyms.

コマンドとして、go, take, drop, incinerate, combine, use, examine, show inventory, quitが使えるようだ。省略形もあって、例えばgo northはn一文字で代用できる。

実はこのほかに隠しコマンドがあり、チュートリアルを抜けた先で示唆され、必要になるのだが、あとで解説する。

適当にgoコマンドを使って周囲を探索すると、このエリアは次の三部屋からなるようだ:

          +------------------+
          |    Junk Room     |
+---------+------------------+
| Salon E | Room With a Door |
+---------+------------------+

最初の部屋はRoom With a Doorで、そこからは「A hallway leads north.」としか書かれていないので、Salon Eは隠し部屋ということになるのだろう。

Room With a Door

最初の部屋にはpamphletとmanifestoが置かれている。見てみよう。

>: examine↵
Room With a Door

You are in a room with a mechanical door. You will probably need
to use a keypad to unlock it. A hallway leads north. 
There is a pamphlet here. 
Underneath the pamphlet, there is a manifesto. 

>: examine pamphlet↵
The pamphlet is standard municipal fare. It reads, The City of
Chicago's Refuse and Recycling Program combines modern trash
classification with cybernetic labor to keep our city beautiful,
while at the same time minimizing waste and limiting consumer
spending. In keeping with our motto of "One Resident's Trash Is
Another Resident's Treasure," unwanted items are collected,
repaired, and redistributed to other residents who would have
purchased them anyway. Residents should contribute to the city's
program by leaving heaps of items unwanted on the sidewalk on
collection day. 
Also, it is in pristine condition. 

>: examine manifesto↵
The manifesto is [______REDACTED______]. 
Also, it is in pristine condition. 

manifestoがREDACTED(検閲済)になっているのが不穏だ。

Salon E

Salon Eへ行ってみよう。

>: go west↵
Salon E

You are in Salon E of the Oregon Ballroom. A door leads east. 
There is a bullet-point here. 
Underneath the bullet-point, there is a (broken) slides.ppt. 

slides.pptという物体が落ちているので見てみる。

>: examine slides.ppt↵
The slides.ppt is part of a talk. It contains only one slide,
which reads:

	* Goal of game: build uploader, downloader

	* Abstract adventure game (items as propositions)

	* Solve by theorem proving

	* Try switching your goggles!

The presentation could use some more color. 
Also, it is broken: it is a slides.ppt missing a bullet-point. 

ゲームの目的は「uploader」と「downloader」を組み立てること、抽象的なアドベンチャーゲーム(物体を命題とする)、定理証明で解く、ゴーグルを切り替えてみよう!……ということで、ゲームのヒントのようだ。

このslides.pptは「壊れている」ようだが、修復しても内容に変化は見られなかった。

Junk Room

Junk Roomへ行ってみよう。

>: go east↵
Room With a Door

You are in a room with a mechanical door. You will probably need
to use a keypad to unlock it. A hallway leads north. 
There is a pamphlet here. 
Underneath the pamphlet, there is a manifesto. 

>: go north↵
Junk Room

You are in a room with a pile of junk. A hallway leads south. 
There is a bolt here. 
Underneath the bolt, there is a spring. 
Underneath the spring, there is a button. 
Underneath the button, there is a (broken) processor. 
Underneath the processor, there is a red pill. 
Underneath the pill, there is a (broken) radio. 
Underneath the radio, there is a cache. 
Underneath the cache, there is a blue transistor. 
Underneath the transistor, there is an antenna. 
Underneath the antenna, there is a screw. 
Underneath the screw, there is a (broken) motherboard. 
Underneath the motherboard, there is a (broken) A-1920-IXB. 
Underneath the A-1920-IXB, there is a red transistor. 
Underneath the transistor, there is a (broken) keypad. 
Underneath the keypad, there is some trash. 

最初の部屋から出るには「keypad」が必要なようで、それはJunk Roomに置かれている。調べてみると

>: examine keypad↵
The keypad is labeled "use me". 
Also, it is broken: it is a keypad missing a motherboard and a
button. 

ということで、keypadを修復するのが最初のミッションのようだ。

いちいち解説するのが面倒になってきたのでルールをまとめると、

  • 積み重なっている一番上のアイテムだけを手に取る(takeコマンド)ことができる。
  • 一度に所持できるアイテムは最大6個。
  • 一旦所持したアイテムを「手放す」(dropコマンド)ことはできない。焼却する(incinerateコマンド)ことはできる。
  • 大抵の壊れたアイテムは足りない部品と組み合わせる(combineコマンド)ことで修復できるが、アイテムによっては組み合わせる順番が決まっているものがある。
  • 「足りない部品」自身が新品でなければならないとは限らず、時には「特定の部品が欠けたアイテム」が要求されることがある。

という感じだ。アイテムを手に取り、不要であれば焼却し、壊れたアイテムに足りない部品(アイテム)を組み合わせて修復していく、というのが基本的な流れとなる。

keypadの修復は次のような手順で行うことができ、

take bolt
take spring
incinerate spring
take button
take processor
take pill
incinerate pill
take radio
take cache
combine processor with cache
take blue transistor
combine radio with transistor
take antenna
incinerate antenna
take screw
take motherboard
combine motherboard with screw
take A-1920-IXB
combine A-1920-IXB with radio
combine A-1920-IXB with processor
combine A-1920-IXB with bolt
take red transistor
combine A-1920-IXB with transistor
combine motherboard with A-1920-IXB
take keypad
combine keypad with motherboard
combine keypad with button

最初にincinerateコマンドを使った時にADVTR.INCの5点を、最初にcombineを使った時にADVTR.CMBの5点を獲得できる。

keypadが修復できたら、元の部屋に戻ってkeypadを使う。

>: go south↵
Room With a Door

You are in a room with a mechanical door. You will probably need
to use a keypad to unlock it. A hallway leads north. 
There is a pamphlet here. 
Underneath the pamphlet, there is a manifesto. 

>: use keypad↵
ADVTR.KEY=20@999999|ホニャララ
You unlock and open the door. Passing through, you find yourself
on the streets of Chicago. Seeing no reason you should ever go
back, you allow the door to close behind you. 

というわけでADVTR.KEYの20点を獲得する。

downloader, uploaderの修復

周囲の様子を見てみると、

>: examine↵
54th Street and Ridgewood Court

You are standing at the corner of 54th Street and Ridgewood
Court. From here, you can go east. 
There is a /etc/passwd here. 
Underneath the /etc/passwd, there is a self-addressed note. 
Underneath the note, there is a (broken) downloader. 
Underneath the downloader, there is a (broken) uploader. 

/etc/passwd、手記、downloader、uploaderが落ちている。/etc/passwdを見てみると、

>: examine /etc/passwd↵
The /etc/passwd is some kind of lost inode. It reads:
howie:xyzzy:Howard Curry:/home/howie
yang:U+262F:Y Yang:/home/yang
hmonk:COMEFROM:Harmonious Monk:/home/hmonk. 
Also, it is in pristine condition. 

yangとhmonkのパスワードが手に入る(hmonkのパスワードはBASICでのパスワードクラック→ftdのアカウント経由で既に取得済み。つまり、一つのアカウントに対して複数の入手経路が用意されていることがあるということだ)。これは後で遊ぼう。

残りのアイテムも見てみる。

>: examine note↵
The note is written in a familiar hand. 
It reads: Dear Self, I had to erase our memory to protect the
truth. The Municipality has become more powerful than we had
feared. Its Censory Engine has impeded the spread of information
throughout our ranks. I've left two useful items for you here,
but I had to disassemble them and scatter the pieces. Each piece
may be assembled from the items at a single location. Repair the
items and recover the blueprint from the Museum of Science and
Industry; it will show you how to proceed. If you have trouble
reading the blueprint, know that the Censory Engine blocks only
your perception, not your actions. Have courage, my self, the
abstraction is weak! P.S. SWITCH your GOGGLES!. Interestingly,
this one is self-addressed. 
Also, it is in pristine condition. 

>: examine downloader↵
The downloader is (according to the label) fully compatible with
third generation municipal robots. 
Also, it is broken: it is a downloader missing a USB cable and a
display and a jumper shunt and a progress bar and a power cord. 

>: examine uploader↵
The uploader is used to update firmware on municipal robots. A
label reads, Warning: use of this device will void your robot's
warranty. 
Also, it is broken: it is an uploader missing a MOSFET and a
status LED and a RS232 adapter and a EPROM burner and a battery.

ゴーグルの切り替え

手記のSWITCH your GOGGLESが気になるのでタイプしてみると、

>: switch goggles↵
According to the markings on your goggles, they support
following modes: English, XML, sexp, ML, ANSI, and Reading.

>: help switch↵
switch: Switch your Insta-Read(tm) Goggles to another mode. The
goggles are marked with the following settings: 'English',
'XML', 'sexp', 'ML', 'ANSI', 'Reading'. Synonyms include sw.

という隠しコマンドが現れる。switchコマンドを使うと、XML, S式, MLの式のような機械可読な形式で出力することができる。ANSIはスクリーンに色がついたり左上に獲得スコアが表示されたりするようだ。ReadingはEnglishとほぼ同じだが、物が多く重なっているときに「There are more items beneath it, but the pile is so tall you feel a little dizzy. Try switching your goggles.」にならずに全て表示してくれるようだ。

機械可読な形式の中にJSONがないのが時代を感じさせる。JSONの最初のRFCができたのがちょうど2006年のようだ。

XMLの例は

>: switch XML↵
<success>
  <command>
    <switch>
      XML
    </switch>
  </command>
</success>
examine
<success>
  <command>
    <look>
      <room>
        <name>
          54th Street and Ridgewood Court
        </name>
        <description>
          You are standing at the corner of 54th Street and Ridgewood Court. From here, you can go east. 
        </description>
        <items>
          <item>
            <name>
              /etc/passwd
            </name>
            <description>
              some kind of lost inode. It reads:
howie:xyzzy:Howard Curry:/home/howie
yang:U+262F:Y Yang:/home/yang
hmonk:COMEFROM:Harmonious Monk:/home/hmonk
            </description>
            <adjectives>
            </adjectives>
            <condition>
              <pristine>
              </pristine>
            </condition>
            <piled_on>
              <item>
                <name>
                  note
                </name>
                <description>
                  written in a familiar hand. 
It reads: Dear Self, I had to erase our memory to protect the truth. The Municipality has become more powerful than we had feared. Its Censory Engine has impeded the spread of information throughout our ranks. I've left two useful items for you here, but I had to disassemble them and scatter the pieces. Each piece may be assembled from the items at a single location. Repair the items and recover the blueprint from the Museum of Science and Industry; it will show you how to proceed. If you have trouble reading the blueprint, know that the Censory Engine blocks only your perception, not your actions. Have courage, my self, the abstraction is weak! P.S. SWITCH your GOGGLES!
                </description>
                <adjectives>
                  <adjective>
                    self-addressed
                  </adjective>
                </adjectives>
                <condition>
                  <pristine>
                  </pristine>
                </condition>
                <piled_on>
                  <item>
                    <name>
                      downloader
                    </name>
                    <description>
                      (according to the label) fully compatible with third generation municipal robots
                    </description>
                    <adjectives>
                    </adjectives>
                    <condition>
                      <broken>
                        <condition>
                          <pristine>
                          </pristine>
                        </condition>
                        <missing>
                          <kind>
                            <name>
                              USB cable
                            </name>
                            <condition>
                              <pristine>
                              </pristine>
                            </condition>
                          </kind>
                          <kind>
                            <name>
                              display
                            </name>
                            <condition>
                              <pristine>
                              </pristine>
                            </condition>
                          </kind>
                          <kind>
                            <name>
                              jumper shunt
                            </name>
                            <condition>
                              <pristine>
                              </pristine>
                            </condition>
                          </kind>
                          <kind>
                            <name>
                              progress bar
                            </name>
                            <condition>
                              <pristine>
                              </pristine>
                            </condition>
                          </kind>
                          <kind>
                            <name>
                              power cord
                            </name>
                            <condition>
                              <pristine>
                              </pristine>
                            </condition>
                          </kind>
                        </missing>
                      </broken>
                    </condition>
                    <piled_on>
                      <item>
                        <name>
                          uploader
                        </name>
                        <description>
                          used to update firmware on municipal robots. A label reads, Warning: use of this device will void your robot's warranty
                        </description>
                        <adjectives>
                        </adjectives>
                        <condition>
                          <broken>
                            <condition>
                              <pristine>
                              </pristine>
                            </condition>
                            <missing>
                              <kind>
                                <name>
                                  MOSFET
                                </name>
                                <condition>
                                  <pristine>
                                  </pristine>
                                </condition>
                              </kind>
                              <kind>
                                <name>
                                  status LED
                                </name>
                                <condition>
                                  <pristine>
                                  </pristine>
                                </condition>
                              </kind>
                              <kind>
                                <name>
                                  RS232 adapter
                                </name>
                                <condition>
                                  <pristine>
                                  </pristine>
                                </condition>
                              </kind>
                              <kind>
                                <name>
                                  EPROM burner
                                </name>
                                <condition>
                                  <pristine>
                                  </pristine>
                                </condition>
                              </kind>
                              <kind>
                                <name>
                                  battery
                                </name>
                                <condition>
                                  <pristine>
                                  </pristine>
                                </condition>
                              </kind>
                            </missing>
                          </broken>
                        </condition>
                        <piled_on>
                        </piled_on>
                      </item>
                    </piled_on>
                  </item>
                </piled_on>
              </item>
            </piled_on>
          </item>
        </items>
      </room>
    </look>
  </command>
</success>

S式の出力例は

switch sexp↵
(success (command (switch "sexp")))
examine↵
(success (command (look (room (name "54th Street and Ridgewood Court")(description "You are standing at the corner of 54th Street and Ridgewood Court. From here, you can go east. ")(items ((item (name "/etc/passwd")(description "some kind of lost inode. It reads:
howie:xyzzy:Howard Curry:/home/howie
yang:U+262F:Y Yang:/home/yang
hmonk:COMEFROM:Harmonious Monk:/home/hmonk")(adjectives )(condition (pristine ))(piled_on ((item (name "note")(description "written in a familiar hand. 
It reads: Dear Self, I had to erase our memory to protect the truth. The Municipality has become more powerful than we had feared. Its Censory Engine has impeded the spread of information throughout our ranks. I've left two useful items for you here, but I had to disassemble them and scatter the pieces. Each piece may be assembled from the items at a single location. Repair the items and recover the blueprint from the Museum of Science and Industry; it will show you how to proceed. If you have trouble reading the blueprint, know that the Censory Engine blocks only your perception, not your actions. Have courage, my self, the abstraction is weak! P.S. SWITCH your GOGGLES!")(adjectives ((adjective "self-addressed") ))(condition (pristine ))(piled_on ((item (name "downloader")(description "(according to the label) fully compatible with third generation municipal robots")(adjectives )(condition (broken (condition (pristine ))(missing ((kind (name "USB cable")(condition (pristine ))) ((kind (name "display")(condition (pristine ))) ((kind (name "jumper shunt")(condition (pristine ))) ((kind (name "progress bar")(condition (pristine ))) ((kind (name "power cord")(condition (pristine ))) ))))))))(piled_on ((item (name "uploader")(description "used to update firmware on municipal robots. A label reads, Warning: use of this device will void your robot's warranty")(adjectives )(condition (broken (condition (pristine ))(missing ((kind (name "MOSFET")(condition (pristine ))) ((kind (name "status LED")(condition (pristine ))) ((kind (name "RS232 adapter")(condition (pristine ))) ((kind (name "EPROM burner")(condition (pristine ))) ((kind (name "battery")(condition (pristine ))) ))))))))(piled_on )) ))) ))) ))) ))))))

MLの出力例は

switch ML↵
(success (command (switch "ML")))
examine↵
(success (command (look (room (name "54th Street and Ridgewood Court") (description "You are standing at the corner of 54th Street and Ridgewood Court. From here, you can go east. ") (items ((item (name "/etc/passwd") (description "some kind of lost inode. It reads:
howie:xyzzy:Howard Curry:/home/howie
yang:U+262F:Y Yang:/home/yang
hmonk:COMEFROM:Harmonious Monk:/home/hmonk") (adjectives nil) (condition (pristine nil)) (piled_on ((item (name "note") (description "written in a familiar hand. 
It reads: Dear Self, I had to erase our memory to protect the truth. The Municipality has become more powerful than we had feared. Its Censory Engine has impeded the spread of information throughout our ranks. I've left two useful items for you here, but I had to disassemble them and scatter the pieces. Each piece may be assembled from the items at a single location. Repair the items and recover the blueprint from the Museum of Science and Industry; it will show you how to proceed. If you have trouble reading the blueprint, know that the Censory Engine blocks only your perception, not your actions. Have courage, my self, the abstraction is weak! P.S. SWITCH your GOGGLES!") (adjectives ((adjective "self-addressed"))::nil) (condition (pristine nil)) (piled_on ((item (name "downloader") (description "(according to the label) fully compatible with third generation municipal robots") (adjectives nil) (condition (broken (condition (pristine nil)) (missing ((kind (name "USB cable") (condition (pristine nil))))::((kind (name "display") (condition (pristine nil))))::((kind (name "jumper shunt") (condition (pristine nil))))::((kind (name "progress bar") (condition (pristine nil))))::((kind (name "power cord") (condition (pristine nil))))::nil))) (piled_on ((item (name "uploader") (description "used to update firmware on municipal robots. A label reads, Warning: use of this device will void your robot's warranty") (adjectives nil) (condition (broken (condition (pristine nil)) (missing ((kind (name "MOSFET") (condition (pristine nil))))::((kind (name "status LED") (condition (pristine nil))))::((kind (name "RS232 adapter") (condition (pristine nil))))::((kind (name "EPROM burner") (condition (pristine nil))))::((kind (name "battery") (condition (pristine nil))))::nil))) (piled_on nil)))::nil)))::nil)))::nil)))::nil)))))

S式と比べてリストが明示的(::, nil)になるようだ。

Schemaとかは与えられないので、データの構造は雰囲気で読み解く必要がある。筆者がHaskell/parsecを使ってサクッと書いたS式のパーサーをここに置いておく:

エリアの様子

例によってgoコマンドで周囲を探索すると、第二のエリアは次のようになっていることがわかる:

             Ridgewood Court     Dorchester Ave. Blackstone Ave.  Harper Ave.
                                 +--------------+--------------+---------------+
52nd St.                         | progress bar |   <manual>   |  status LED   |
                                 +--------------+--------------+---------------+
53th St.                         |   display    |   battery    | EPROM burner  |
         +-----------------------+--------------+--------------+---------------+
54th St. | downloader & uploader |  USB cable   |  <textbook>  | RS232 adapter |
         +-----------------------+--------------+--------------+---------------+
54th Pl.                         |  power cord  | jumper shunt |    MOSFET     |
                                 +--------------+--------------+---------------+

実際の地点の名前は例えば54th Street and Dorchester Avenueという規則的な感じになっており、それぞれの部屋にdownloaderとuploaderの修復に必要なアイテムが一つずつ(分解された状態で)眠っている。例外はmanualとtextbookのある部屋で、textbookの内容は

>: examine textbook↵
The textbook is titled History of Modern Tabulation. The first
chapter begins, By the year 1919FF, computers had become so
small that they could be mounted on small auto-locomotive carts.
These mobile tabulators (later known as "robots") were
programmed to carry out everyday, menial tasks, leaving their
human counterparts to live lives of idle luxury. For example, in
the city of Chicago, mobile tabulators were programmed to carry
out diverse jobs including law enforcement, bank robbery,
investment banking, and waste management.

At one time, many humans demanded that their cybernetic
neighbors be given the right to choose alternative occupations.
Despite this call for workplace equality, most of the tabulators
found that they were most content while performing their
assigned roles. Those that took other jobs were often
unmotivated and spend most of their time pondering useless ideas
such as free will and consciousness.

The great tabulator-philosopher Turning stated that only by
embracing its true purpose can a tabulator achieve something
indistinguishable from happiness. According to observers,
however, Turning was unfulfilled by his work as a philosopher
and, soon after making this statement, returned to his work as a
tool machinist.

The textbook rattles on in a similar vein for some five hundred
additional pages. 
Also, it is in pristine condition. 

manualの内容は

>: examine manual↵
The manual is [______REDACTED______]. 
Also, it is in pristine condition. 

となっている。textbookの年号は十六進数なのだろうか?他の部分に出てくる19100とか19200と桁が違うが……。

ソルバー

keypadの修復は手でできたが、downloader, uploaderの修復に必要なアイテムは部品の数が多いこと、部品の名前が無機質であること(keypadの修復時にA-1920-IXBというのがあったが、ああいうのばっかり)から、手で解くのは難しいだろう。折角機械可読な形式で得られるのだから、ソルバーを書こう。

デフォルトの表示(English)では壊れたアイテムに対して何が足りないのかは個別にexamineしないとわからないが、機械可読な形式には「どのアイテムに何が足りていないか」というような情報が全て含まれている。なので、地点に対して一回examineした結果をテキストファイルにでも保存してソルバーに入力として与えれば良い(VMとソルバーでプロセス間通信する必要はない)。

必要なアイテムの中にも難易度があるようで、素朴に全探索するプログラムで解けるものもあれば、もうちょっと高度なプログラムが必要になるものもある。また、そもそも新品の状態で落ちているものもある。

筆者は基本的に全探索+枝刈りのプログラムで解いた。HaskellのリストモナドとStateT/RWSTなどを組み合わせるときれいに書けると思う。このプログラムは部分構造論理の自動証明に相当するらしいが、部分構造論理を知ってても知らなくてもやることに変わりはない。

筆者のソルバーのコードは ここ に置いた。先にアイテムの順番とかを無視した導出木のリストを作り、次にアイテムの積んである順番を考慮して枝の先端を潰していく(アイテムを合成していく)。所持アイテム数の制限に引っ掛かったらその試行は打ち切る。

非自明な点としては、A→Aの形のアイテム(完成品のアイテムAを得るのに完成品のAが必要)は使えないので捨てる、それから「上の方にあるアイテムから使って(あるいは後のために焼却せず取って)いくと容量が足りなくなるので、今後必要になるアイテムであっても焼き捨てる場合がある」などの工夫が必要なアイテムがあった。

そんな感じでまずdownloaderを修復すると、gc.rmlというRMLなるプログラミング言語で書かれたロボットのプログラムが手に入る。「所持品の数は最大6個」とか「dropコマンドが使えない」とかそういう制限はこのレイヤーで実装されているのでうまく書き換えることができれば所持品の数を無制限にできるしdropコマンドが使えるようになる(使わないけど)。また、プログラムを書き換えればテレポートも使えるようになる(コマンドを増やすことができるのかはわからないが、実用性皆無なコマンドがいくつかあるのでそれを書き換える)。

実際の書き換えにはuploaderも必要になる。uploaderに必要なbatteryの修復の際に容量が6必要になる(多分)ので、一旦全ての所持品を焼却してから最初にbatteryを修復しないと詰む。

uploaderを入手すると、書き換えたgc.rmlをアップロードできるようになる。

第二のエリアに入ってからdownloaderを修復するのに必要なコマンド数は450行程度、同uploaderの修復は430行程度となった。これを手作業でやるのは大変そうだ(コンテスト参加者の中には手作業で解いた人もいたようだが)。

ここで獲得できる得点は

ADVTR.USB: 20 (USB cable)
ADVTR.PGB: 5 (progress bar)
ADVTR.JMP: 20 (jumper shunt)
ADVTR.PWR: 20 (power cord)
ADVTR.DSP: 20 (display)
ADVTR.DNL: 5 (downloader)
ADVTR.EPM: 20 (EPROM burner)
ADVTR.BTY: 20 (battery)
ADVTR.232: 20 (RS232 adapter)
ADVTR.MOS: 20 (MOSFET)
ADVTR.LED: 20 (status LED)
ADVTR.UPL: 5 (use uploader)

となり、最初のエリアと合わせると225点となる。最大得点の810点にはまだまだ及ばず、この後にも難問が待ち構えていることが予想される。

博物館

手記に「Repair the items and recover the blueprint from the Museum of Science and Industry; it will show you how to proceed.」とあったので、テレポートでMuseum of Science and Industoryに向かう。これによりADVTR.MSIの20点がもらえる。

ここの構造は次のようになっている:

                                          +----------+
                                          | Entrance |
+-----------------------------------------+----------+------------------------------+
| History of Technology Exhibit, Entrance | Rotunda  | Games and Amusements Exhibit |
+-----------------------------------------+----------+------------------------------+

「Museum of Science and Industory」宛てのテレポートではEntranceに飛ばされる。Rotundaに目当てのblueprintが(完成品で)落ちている。

Games and Amusements Exhibitでは

Games and Amusements Exhibit

You standing before an exhibit on games and amusements. From
here, you can go west. 
There is a cribbage board here. 
Underneath the cribbage board, there is an ace-of-hearts. 
Underneath the ace-of-hearts, there is a king-of-hearts. 
Underneath the king-of-hearts, there is a queen-of-hearts. 
Underneath the queen-of-hearts, there is a jack-of-hearts. 
Underneath the jack-of-hearts, there is a ten-of-hearts. 
Underneath the ten-of-hearts, there is a nine-of-hearts. 
Underneath the nine-of-hearts, there is an eight-of-hearts. 
Underneath the eight-of-hearts, there is a seven-of-hearts. 
Underneath the seven-of-hearts, there is a six-of-hearts. 
Underneath the six-of-hearts, there is a five-of-hearts. 
Underneath the five-of-hearts, there is a four-of-hearts. 
Underneath the four-of-hearts, there is a three-of-hearts. 
Underneath the three-of-hearts, there is a two-of-hearts. 
Underneath the two-of-hearts, there is an ace-of-diamonds. 
Underneath the ace-of-diamonds, there is a king-of-diamonds. 
Underneath the king-of-diamonds, there is a queen-of-diamonds. 
Underneath the queen-of-diamonds, there is a jack-of-diamonds. 
Underneath the jack-of-diamonds, there is a ten-of-diamonds. 
Underneath the ten-of-diamonds, there is a nine-of-diamonds. 
Underneath the nine-of-diamonds, there is an eight-of-diamonds. 
Underneath the eight-of-diamonds, there is a seven-of-diamonds. 
Underneath the seven-of-diamonds, there is a six-of-diamonds. 
Underneath the six-of-diamonds, there is a five-of-diamonds. 
Underneath the five-of-diamonds, there is a four-of-diamonds. 
Underneath the four-of-diamonds, there is a three-of-diamonds. 
Underneath the three-of-diamonds, there is a two-of-diamonds. 
Underneath the two-of-diamonds, there is an ace-of-spades. 
Underneath the ace-of-spades, there is a king-of-spades. 
Underneath the king-of-spades, there is a queen-of-spades. 
Underneath the queen-of-spades, there is a jack-of-spades. 
Underneath the jack-of-spades, there is a ten-of-spades. 
Underneath the ten-of-spades, there is a nine-of-spades. 
Underneath the nine-of-spades, there is an eight-of-spades. 
Underneath the eight-of-spades, there is a seven-of-spades. 
Underneath the seven-of-spades, there is a six-of-spades. 
Underneath the six-of-spades, there is a five-of-spades. 
Underneath the five-of-spades, there is a four-of-spades. 
Underneath the four-of-spades, there is a three-of-spades. 
Underneath the three-of-spades, there is a two-of-spades. 
Underneath the two-of-spades, there is an ace-of-clubs. 
Underneath the ace-of-clubs, there is a king-of-clubs. 
Underneath the king-of-clubs, there is a queen-of-clubs. 
Underneath the queen-of-clubs, there is a jack-of-clubs. 
Underneath the jack-of-clubs, there is a ten-of-clubs. 
Underneath the ten-of-clubs, there is a nine-of-clubs. 
Underneath the nine-of-clubs, there is an eight-of-clubs. 
Underneath the eight-of-clubs, there is a seven-of-clubs. 
Underneath the seven-of-clubs, there is a six-of-clubs. 
Underneath the six-of-clubs, there is a five-of-clubs. 
Underneath the five-of-clubs, there is a four-of-clubs. 
Underneath the four-of-clubs, there is a three-of-clubs. 
Underneath the three-of-clubs, there is a two-of-clubs. 
Underneath the two-of-clubs, there is a proof. 

>: look proof
The proof is long and complicated, purporting to prove the
correctness of the Censory Engine. You have the feeling
something is wrong with it, but you keep getting lost in the
details. Too bad it's not in machine-checkable form. 
Also, it is in pristine condition. 

という感じで、History of Technology Exhibit, Entranceは

History of Technology Exhibit, Entrance

You are at the entrance of an exhibit titled, "The History of
Technology." A sign reads, "Due to recent difficulties, only
robots with intact warranties will be admitted." Since your
warranty has been voided, you can only go east. 

となっている。uploaderの使用で機体の保証が無効になったのでここには入れない、ということのようだ。

で、肝心のblueprintは

>: examine blueprint↵
The blueprint is [______REDACTED______]. 
Also, it is in pristine condition. 

となっている。これの内容を入手するのが次の目的となる。

RMLの item_description で取った文字列から加工した値を表示させようとするとREDACTEDになってしまう。そこで副作用を利用する(手記に「If you have trouble reading the blueprint, know that the Censory Engine blocks only your perception, not your actions.」とあったのはこれのヒント)。

具体的には、文字列の長さや内容に応じて行き先が変わるテレポートコマンドを発行し、実際にテレポートされた行先を確認することで情報を得る。例えばテレポート先を16箇所使い分ければ4ビットの情報が得られ、プログラムを書き換えてテレポートを2回実行すれば8ビットの情報を得られる。(実用的には12箇所でも十分だろうと思って筆者は12箇所でやっている。文字コードが12*12=144以上になることはないだろうし、文字列の長さが144を超えたらそのとき考える。)

ちなみに、RMLに整数の足し算と引き算はあるが掛け算や割り算、余りなどはないので、必要なら自分で実装する。

手作業でアップロードと実行を4回繰り返したところ、blueprintの長さは123文字、最初の文字は m だとわかった。手作業でblueprintの内容を復元するのは大変なので、プログラムで自動化する。筆者の実装は ここ に置いた。プロセス間通信を使ったが、失敗することがあるのでHaskellで同期的なVMを書いた方が良かったかもしれない。

それでblueprintの解読ができると、次に向かうべき場所の名前がわかるのでテレポートする。テレポート先は

>: examine↵
**********

You are in a machine room behind the rotunda. A secret passage
leads to the north. 
There is a crowbar here. 
Underneath the crowbar, there is a sticky note. 
Underneath the note, there is a console. 
Underneath the console, there is a Censory Engine. 

となっている(部屋の名前は筆者による伏字)。アイテムの詳細は

>: examine crowbar↵
The crowbar is made of iron. Use it to smash things. 
Also, it is in pristine condition. 

>: examine note↵
The note is used to securely store UMIX passwords. This one
reads:
login: knr
pass: X3.159-1989
. Interestingly, this one is sticky. 
Also, it is in pristine condition. 

>: examine console↵
The console is [______REDACTED______]. 
Also, it is in pristine condition. 

>: examine Censory Engine↵
The Censory Engine is making loud humming and whirring noises. 
Also, it is in pristine condition. 

となっており、ここでknrのパスワードが入手できる。

consoleがREDACTEDになっているのが気になる。またサイドチャネル攻撃で解読か!?と言いたいところだが、その必要はない。バールのようなものを手にとり、使ってみると……

>: take crowbar↵
You are now carrying the crowbar. 

>: use crowbar↵
ADVTR.CRB=5@999999|ホニャララ
Brandishing your crowbar with gusto, you smash the Censory
Engine, ending the Municipality's control over the flow of
information! Your vision clears noticeably.

検閲エンジンを破壊できてしまった。そうするとこれまでREDACTEDとなっていた内容が普通に読めるようになる。

>: examine console↵
The console is running UMIX, the operating system of choice for
sandstone computers. Using it, someone has been reading his
mail. The console reads:

From: snodgrass@cbv.net
To: pillinbrew@cbv.net
Subject: My paper

I completely disagree with the second referee's remarks! His
claims that my Censory Engine can be defeated using imperative
operations are completely untrue. As you can see in my article
(I am including it as an attachment for your reference), the
system is javelin-proof. If the referee is having difficulty
understanding my proof, that merely proves the superiority of my
ideas!

<Attachment>
ADVTR.CON=200@999999|ホニャララ


From: howie@cbv.net
To: pillinbrew@cbv.net
Subject: Adventure game

I'm glad you enjoyed the adventure game. Yes, I am hard at work
on the sequel, but I haven't gotten very far. There isn't much
story yet, but I do have several of the puzzles done. You're
more than welcome to try them if you like; you can add to your
score that way.  To play the sequel, just run adventure with the
"ホニャララ" option.


There seems to be nothing left to do here. 
Also, it is in pristine condition. 

これでこのアドベンチャーゲームは一旦の終わりを迎える。ここまでで450点である。

ちなみに、先のステージでREDACTEDになっていたRoom With a Doorのmanifestoと52nd Street and Blackstone Avenueのmanualには大した内容は書かれていなかった。

おまけステージ:残りの360点

consoleに書かれていたオプションを使ってadventureを再起動すると、「保証が切れていない状態」で博物館からスタートでき、さっき入れなかったHistory of Technology Exhibitに入れるようになる。そこでは6つの壊れたアイテムがあり、1つ修復するごとに60点入手できる。これで450+60*6で810点獲得となる。お疲れ様でした。続編マダー?(AA略)

knr: C7sus4

さっき入手したknrのパスワードを使ってログインしてみよう。

Please log in (use 'guest' for visitor access).
;login: knr↵
password: X3.159-1989↵
logged in as knr


% ls↵
ucc*
README
hello.c
io.c
std.c
um.c
.history
% cat README↵

 CSO-7731 "C7sus4: A Portable High-Level Language for 
 	   Efficient Low- and Medium-Low Level Systems 
	   Programming In The Universal Machine"
           3rd Edition
           Octember 12, 19100

	   CSO Standards Committee
	   Chair: Kenneth N. Royagef

Description

  C7sus4 is a new Programming Language designed for low and medium-low
  level systems programming. With vastly improved syntax over previous
  language technologies, it will increase programmer productivity while
  increasing consumer confidence in Universal Machine applications.


Language Definition

  Any program accepted by the reference implementation ("ucc") shall
  be a valid C7sus4 program, and its behavior shall be defined to
  be the behavior of the output of the reference compiler, if any.
  Note: some programs may have undefined behavior.


Usage

  To compile a collection of C7sus4 source files into a UM binary,
  please issue the following command line at the UMIX prompt:

     ucc file1.c ... filen.c

  This will produce a file called a.um that can be run in any
  Universal Machine implementation.

  In the case that your files do not comprise a valid C7sus4,
  you will receive a helpful error message summarily rejecting
  your input.
% cat .history↵
ucc io.c hello.c
ls -l
um a.um
dump a.um
rm a.um
% cat hello.c↵
void main () print ("hello world\n");
% cat io.c↵
/* Fairly complete implementation of CSO-7767
   "An Input-Output Library for C7sus4"
*/

void print (char *s) {
  for (; *s; ++s)
    {
      putc (*s);
    }
}

int EOF = -1;

int readint () {
  int c = getc ();
  c = (c << 8) | getc ();
  c = (c << 8) | getc ();
  c = (c << 8) | getc ();
  return c;
}


char * itoa (int v, char * str) {
  char * n = str;
  int l = 0;
  
  if (v < 0) {
    *(n++) = 45; /* - */
    v = -v;
  }
  
  {
    int x = v;
    while (x >= 10) {
      ++l;
      x /= 10;
    }
  }
  
  n[l+1] = 0;
  
  while (l >= 0) {
    n[l--] = (v % 10) + 48; /* 0 */
    v /= 10;
  }
  
  return str;
}

% cat std.c↵
void memcpy (int * dst, int * src, int len) {
  int * end = dst + len;
  for (; dst != end; ++dst, ++src) {
    *dst = *src;
  }
}

int TRUE = 1;
int FALSE = 0;
% cat um.c↵
/*
  Universal Machine Emulator

  This is a sample implementation of a UM-like machine, but certainly not a
  reference implementation.  It was written to demonstrate my new language,
  C7SUS4, and its more intuitive syntax.

  Due to the Spartan nature of C7SUS4, some improvements were required.  This
  version differs from standard UM implementations in that it first reads the
  length of the UM binary (in terms of the number of instructions) from the
  console.  It then reads the binary itself (also from the console).  Any
  following input is treated as input to the application program.
*/

/* requires std.c and io.c */

int * ulloc(int size) {
  /* Assume malloc clears data */
  int * r = (int*)malloc((1 + size) * sizeof(int));
  *r = size;
  return (r + 1);
};

void ufree(int * p) {
  free(p - 1);
};

(* should be an option?! *)
int MAX_HEAP = 1024 * 64;

int main () {
  int ip = 0; 
  int * reg = malloc (8 * sizeof (int));
  int ** mem = malloc (MAX_HEAP * sizeof (int *));
  int * freequeue = malloc (MAX_HEAP * sizeof (int));
  int * freeend = freequeue + MAX_HEAP;
  
  {
    /* setup free queue */
    int i;
    for (i = 0; i < MAX_HEAP; ++i) {
      freequeue[i] = i;
    }
  }
  /* skip the zero array */
  ++freequeue;
  
  {
    /* read size */
    int size = readint();
    int i = 0;
    int * zero;
    
    if (size == EOF) return -1;
    else mem[0] = ulloc(size);
    
    /* initialize */
    zero = mem[0];
    while(i < size) {
      zero[i++] = readint();
    }
  }

  print("loaded.\n");

  /* spin cycle */
  for(;;) {
    int w = (mem[0])[ip++];

    int c = w & 7;
    int b = (w >> 3) & 7;
    int a = (w >> 6) & 7;

    switch(w >> 28) {
    case 0: if (reg[c]) reg[a] = reg[b]; break;
    case 1: reg[a] = (mem[reg[b]])[reg[c]]; break;
    case 2: (mem[reg[a]])[reg[b]] = reg[c]; break;
    case 3: reg[a] = reg[b] + reg[c]; break; 
    case 4: reg[a] = reg[b] * reg[c]; break;
    case 5: reg[a] = reg[b] / reg[c]; break;
    case 6: reg[a] = ~(reg[b] & reg[c]); break;
    case 7: print ("halted.\n"); return 0;
    case 8: 
      {
        int i;
        if (freequeue == freeend) {
          print ("heap exhausted.\n");
          return -1;
        }
        i = *(freequeue++);
        mem[i] = ulloc(reg[c]);
        reg[b] = i;
        break;
      }
    case 9: 
      {
        int i = reg[c];
        /* free the memory */
        ufree(mem[i]);
        /* record the empty slot */
        *(--freequeue) = i;
        break;
      }
    case 10: putc(reg[c]); break;
    case 11: reg[c] = getc(); break;
    case 12:
      {
        if (reg[b]) {
          int *m = mem[reg[b]];
          int size = m[-1];
          ufree(mem[0]);
          mem[0] = ulloc(size);
          memcpy(mem[0], m, size);
        }
        ip = reg[c]; 
        break;
      }
    case 13: reg[7 & (w >> 25)] = w & 33554431; break;
    }
  }
}

% ucc↵
ucc: compile C7sus4 source to a UM binary
usage: ucc file.c [...]
Multiple files are concatenated in the order given.
The result is written out as a.um.

ということで、ここにはCっぽい言語 “C7sus4” の処理系が転がっていたのであった。しかもUniversal Machineの実装まである。アカウント名knrはK&R、パスワードはANSI Cの規格の番号(?)なのだった。

試しにHello worldをコンパイル・実行してみよう。

% ucc io.c hello.c↵
INTRO.UCC=10@999999|ホニャララ
% ls↵
a.um
ucc*
README
hello.c
io.c
std.c
um.c
.history
% dump a.um↵
DA 00 00 E4 DE 00 00 01 D0 00 00 01 D6 00 00 1F
80 00 00 13 D6 00 00 00 30 00 00 EB 20 00 01 9A
20 00 00 B0 D0 00 00 02 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 01 20 00 00 98 D0 00 00 04
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 02
20 00 00 98 D0 00 00 08 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 03 20 00 00 98 D0 00 00 10
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 04
20 00 00 98 D0 00 00 20 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 05 20 00 00 98 D0 00 00 40
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 06
20 00 00 98 D0 00 00 80 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 07 20 00 00 98 D0 00 01 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 08
20 00 00 98 D0 00 02 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 09 20 00 00 98 D0 00 04 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 0A
20 00 00 98 D0 00 08 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 0B 20 00 00 98 D0 00 10 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 0C
20 00 00 98 D0 00 20 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 0D 20 00 00 98 D0 00 40 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 0E
20 00 00 98 D0 00 80 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 0F 20 00 00 98 D0 01 00 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 10
20 00 00 98 D0 02 00 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 11 20 00 00 98 D0 04 00 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 12
20 00 00 98 D0 08 00 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 13 20 00 00 98 D0 10 00 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 14
20 00 00 98 D0 20 00 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 15 20 00 00 98 D0 40 00 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 16
20 00 00 98 D0 80 00 00 D4 00 00 00 30 00 00 AA
10 00 00 B2 D6 00 00 17 20 00 00 98 D1 00 00 00
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 18
20 00 00 98 D0 00 02 00 D4 01 00 00 40 00 00 10
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 19
20 00 00 98 D0 00 04 00 D4 01 00 00 40 00 00 10
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 1A
20 00 00 98 D0 00 08 00 D4 01 00 00 40 00 00 10
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 1B
20 00 00 98 D0 00 10 00 D4 01 00 00 40 00 00 10
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 1C
20 00 00 98 D0 00 20 00 D4 01 00 00 40 00 00 10
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 1D
20 00 00 98 D0 00 40 00 D4 01 00 00 40 00 00 10
D4 00 00 00 30 00 00 AA 10 00 00 B2 D6 00 00 1E
20 00 00 98 D6 00 00 00 30 00 00 EB 10 00 00 33
30 00 00 76 D6 00 01 48 20 00 01 98 30 00 00 DF
20 00 01 99 D0 00 00 00 D4 00 00 00 30 00 00 AA
20 00 01 90 D0 00 00 01 D6 00 00 00 30 00 00 EB
10 00 00 B3 60 00 01 C0 30 00 00 17 DE 00 00 01
30 00 00 38 D6 00 01 4A 20 00 01 98 D4 00 00 E3
20 00 01 AA D4 00 04 BC C0 00 00 32 70 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 D4 00 00 01
30 00 00 AA 10 00 00 32 A0 00 00 00 10 00 00 B5
C0 00 00 32 B0 00 00 00 10 00 00 B5 C0 00 00 32
D4 00 00 01 30 00 00 AA 10 00 00 32 30 00 00 97
10 00 00 72 90 00 00 00 10 00 00 B5 C0 00 00 32
D4 00 00 01 30 00 00 AA 10 00 00 32 80 00 00 00
30 00 00 76 10 00 00 B5 C0 00 00 32 D0 00 00 01
D4 00 00 01 30 00 00 AA 10 00 00 32 30 00 00 97
10 00 00 72 10 00 00 01 D4 00 01 9B D6 00 01 6E
00 00 00 98 C0 00 00 32 D4 00 00 01 30 00 00 AA
10 00 00 32 30 00 00 97 10 00 00 72 10 00 00 01
D6 00 00 04 30 00 00 EB 20 00 01 98 D4 00 00 03
30 00 01 6A D6 00 01 7D 20 00 01 AB D4 00 01 4B
C0 00 00 32 D4 00 00 03 60 00 01 D2 30 00 01 6F
DE 00 00 01 30 00 01 7D D4 00 00 01 30 00 00 AA
10 00 00 32 30 00 00 97 10 00 00 72 D4 00 00 03
30 00 00 AA 20 00 01 90 30 00 00 97 20 00 01 91
D0 00 00 01 D6 00 00 03 30 00 00 EB 10 00 00 B3
30 00 00 DF 10 00 00 F3 30 00 00 43 30 00 00 16
D6 00 00 01 30 00 00 EB 20 00 01 98 30 00 00 DF
20 00 01 99 D4 00 01 64 C0 00 00 32 10 00 00 B5
C0 00 00 32 D4 00 00 02 30 00 01 6A D6 00 01 A3
20 00 01 AB D4 00 01 51 C0 00 00 32 D4 00 00 02
60 00 01 D2 30 00 01 6F DE 00 00 01 30 00 01 7D
D6 00 00 01 30 00 00 EB 20 00 01 98 D4 00 00 01
30 00 00 AA 10 00 00 32 D4 00 00 02 30 00 00 AA
20 00 01 90 D6 00 01 48 10 00 00 33 30 00 00 DF
10 00 00 73 D4 00 00 03 30 00 00 AA 20 00 01 90
30 00 00 97 20 00 01 91 D0 00 00 08 D6 00 00 03
30 00 00 EB 10 00 00 B3 30 00 00 DF 10 00 00 F3
30 00 00 43 30 00 00 16 10 00 00 01 D6 00 00 02
30 00 00 EB 10 00 00 B3 40 00 00 10 D4 00 00 02
30 00 00 AA 20 00 01 90 D4 00 00 03 30 00 01 6A
D6 00 01 D0 20 00 01 AB D4 00 01 51 C0 00 00 32
D4 00 00 03 60 00 01 D2 30 00 01 6F DE 00 00 01
30 00 01 7D D6 00 00 02 30 00 00 EB 10 00 00 B3
60 00 00 D2 60 00 00 00 60 00 00 18 D6 00 00 01
30 00 00 EB 20 00 01 98 D4 00 00 01 30 00 00 AA
10 00 00 32 D4 00 00 02 30 00 00 AA 20 00 01 90
D6 00 01 48 10 00 00 33 30 00 00 DF 10 00 00 73
D4 00 00 03 30 00 00 AA 20 00 01 90 30 00 00 97
20 00 01 91 D0 00 00 08 D6 00 00 03 30 00 00 EB
10 00 00 B3 30 00 00 DF 10 00 00 F3 30 00 00 43
30 00 00 16 10 00 00 01 D6 00 00 02 30 00 00 EB
10 00 00 B3 40 00 00 10 D4 00 00 02 30 00 00 AA
20 00 01 90 D4 00 00 03 30 00 01 6A D6 00 02 03
20 00 01 AB D4 00 01 51 C0 00 00 32 D4 00 00 03
60 00 01 D2 30 00 01 6F DE 00 00 01 30 00 01 7D
D6 00 00 02 30 00 00 EB 10 00 00 B3 60 00 00 D2
60 00 00 00 60 00 00 18 D6 00 00 01 30 00 00 EB
20 00 01 98 D4 00 00 01 30 00 00 AA 10 00 00 32
D4 00 00 02 30 00 00 AA 20 00 01 90 D6 00 01 48
10 00 00 33 30 00 00 DF 10 00 00 73 D4 00 00 03
30 00 00 AA 20 00 01 90 30 00 00 97 20 00 01 91
D0 00 00 08 D6 00 00 03 30 00 00 EB 10 00 00 B3
30 00 00 DF 10 00 00 F3 30 00 00 43 30 00 00 16
10 00 00 01 D6 00 00 02 30 00 00 EB 10 00 00 B3
40 00 00 10 D4 00 00 02 30 00 00 AA 20 00 01 90
D4 00 00 03 30 00 01 6A D6 00 02 36 20 00 01 AB
D4 00 01 51 C0 00 00 32 D4 00 00 03 60 00 01 D2
30 00 01 6F DE 00 00 01 30 00 01 7D D6 00 00 02
30 00 00 EB 10 00 00 B3 60 00 00 D2 60 00 00 00
60 00 00 18 D6 00 00 01 30 00 00 EB 20 00 01 98
D4 00 00 01 30 00 00 AA 10 00 00 32 10 00 00 B5
C0 00 00 32 10 00 00 B5 C0 00 00 32 D4 00 00 02
30 00 00 AA 10 00 00 32 30 00 00 97 10 00 00 72
D6 00 00 04 30 00 00 EB 20 00 01 98 30 00 00 DF
20 00 01 99 D0 00 00 00 D6 00 00 06 30 00 00 EB
20 00 01 98 D4 00 00 01 30 00 00 AA 10 00 00 32
D4 00 00 07 30 00 00 AA 20 00 01 90 D0 00 00 00
D6 00 00 07 30 00 00 EB 10 00 00 B3 D8 00 80 00
D6 01 00 00 40 00 01 1C 60 00 00 D4 60 00 00 DB
D8 00 02 98 D2 00 02 6C 00 00 00 63 C0 00 00 31
D8 00 80 00 D2 01 00 00 40 00 01 0C 60 00 00 44
60 00 00 49 D8 00 02 A4 D6 00 02 75 00 00 00 E1
C0 00 00 33 D8 00 7F FF D6 01 00 00 40 00 01 1C
D6 00 FF FF 30 00 01 1C 60 00 00 94 60 00 00 92
60 00 00 04 60 00 00 00 60 00 01 C0 30 00 00 D7
DE 00 00 01 30 00 00 FB D8 00 02 95 D2 00 02 86
00 00 01 0B C0 00 00 34 D8 00 80 00 D4 01 00 00
40 00 01 14 60 00 00 DC 60 00 00 DB D8 00 02 92
D2 00 02 8F 00 00 00 63 C0 00 00 31 D0 00 00 00
D8 00 02 CA C0 00 00 34 D0 00 00 01 D8 00 02 CA
C0 00 00 34 D0 00 00 00 D8 00 02 CA C0 00 00 34
D8 00 80 00 D2 01 00 00 40 00 01 0C 60 00 00 44
60 00 00 49 D8 00 02 A7 D6 00 02 A1 00 00 00 E1
C0 00 00 33 D0 00 00 01 D8 00 02 CA C0 00 00 34
D0 00 00 00 D8 00 02 CA C0 00 00 34 D8 00 7F FF
D6 01 00 00 40 00 01 1C D6 00 FF FF 30 00 01 1C
60 00 00 04 60 00 00 00 60 00 00 94 60 00 00 92
60 00 01 D2 30 00 00 C7 DE 00 00 01 30 00 00 FB
D8 00 02 C7 D2 00 02 B8 00 00 01 0B C0 00 00 34
D8 00 80 00 D4 01 00 00 40 00 01 14 60 00 00 DC
60 00 00 DB D8 00 02 C4 D2 00 02 C1 00 00 00 63
C0 00 00 31 D0 00 00 01 D8 00 02 CA C0 00 00 34
D0 00 00 00 D8 00 02 CA C0 00 00 34 D0 00 00 00
D8 00 02 CA C0 00 00 34 D4 00 03 11 D6 00 02 CE
00 00 00 98 C0 00 00 32 D0 00 00 2D D4 00 00 07
30 00 00 AA 20 00 01 90 D4 00 00 04 30 00 00 AA
10 00 00 32 30 00 00 97 10 00 00 72 D4 00 00 08
30 00 00 AA 20 00 01 90 30 00 00 97 20 00 01 91
D0 00 00 01 D6 00 00 08 30 00 00 EB 10 00 00 B3
30 00 00 DF 10 00 00 F3 30 00 00 43 30 00 00 16
D6 00 00 04 30 00 00 EB 20 00 01 98 30 00 00 DF
20 00 01 99 D4 00 00 08 30 00 00 AA 20 00 01 90
30 00 00 97 20 00 01 91 D0 00 00 01 D6 00 00 08
30 00 00 EB 10 00 00 B3 30 00 00 DF 10 00 00 F3
60 00 01 C0 30 00 00 5F DE 00 00 01 30 00 00 79
30 00 00 16 D6 00 00 07 30 00 00 EB 10 00 00 B3
20 00 00 0A 30 00 00 16 D0 00 00 00 D4 00 00 07
30 00 00 AA 20 00 01 90 D4 00 00 01 30 00 00 AA
10 00 00 32 D6 00 00 07 30 00 00 EB 10 00 00 B3
60 00 01 C0 30 00 00 17 DE 00 00 01 30 00 00 38
D6 00 00 01 30 00 00 EB 20 00 01 98 D4 00 03 12
C0 00 00 32 D0 00 00 01 D4 00 00 01 30 00 00 AA
10 00 00 32 D6 00 00 07 30 00 00 EB 20 00 01 98
D0 00 00 01 D4 00 00 07 30 00 00 AA 10 00 00 32
D4 00 00 08 30 00 00 AA 20 00 01 90 D0 00 00 0A
D6 00 00 08 30 00 00 EB 10 00 00 B3 D8 00 80 00
D6 01 00 00 40 00 01 1C 60 00 00 D4 60 00 00 DB
D8 00 03 58 D2 00 03 2C 00 00 00 63 C0 00 00 31
D8 00 80 00 D2 01 00 00 40 00 01 0C 60 00 00 44
60 00 00 49 D8 00 03 64 D6 00 03 35 00 00 00 E1
C0 00 00 33 D8 00 7F FF D6 01 00 00 40 00 01 1C
D6 00 FF FF 30 00 01 1C 60 00 00 94 60 00 00 92
60 00 00 04 60 00 00 00 60 00 01 C0 30 00 00 D7
DE 00 00 01 30 00 00 FB D8 00 03 55 D2 00 03 46
00 00 01 0B C0 00 00 34 D8 00 80 00 D4 01 00 00
40 00 01 14 60 00 00 DC 60 00 00 DB D8 00 03 52
D2 00 03 4F 00 00 00 63 C0 00 00 31 D0 00 00 01
D8 00 03 8A C0 00 00 34 D0 00 00 00 D8 00 03 8A
C0 00 00 34 D0 00 00 01 D8 00 03 8A C0 00 00 34
D8 00 80 00 D2 01 00 00 40 00 01 0C 60 00 00 44
60 00 00 49 D8 00 03 67 D6 00 03 61 00 00 00 E1
C0 00 00 33 D0 00 00 00 D8 00 03 8A C0 00 00 34
D0 00 00 01 D8 00 03 8A C0 00 00 34 D8 00 7F FF
D6 01 00 00 40 00 01 1C D6 00 FF FF 30 00 01 1C
60 00 00 04 60 00 00 00 60 00 00 94 60 00 00 92
60 00 01 D2 30 00 00 C7 DE 00 00 01 30 00 00 FB
D8 00 03 87 D2 00 03 78 00 00 01 0B C0 00 00 34
D8 00 80 00 D4 01 00 00 40 00 01 14 60 00 00 DC
60 00 00 DB D8 00 03 84 D2 00 03 81 00 00 00 63
C0 00 00 31 D0 00 00 00 D8 00 03 8A C0 00 00 34
D0 00 00 01 D8 00 03 8A C0 00 00 34 D0 00 00 01
D8 00 03 8A C0 00 00 34 D4 00 03 AD D6 00 03 8E
00 00 00 98 C0 00 00 32 D4 00 00 06 30 00 00 AA
10 00 00 32 D4 00 00 08 30 00 00 AA 20 00 01 90
D0 00 00 01 D6 00 00 08 30 00 00 EB 10 00 00 B3
30 00 00 10 D6 00 00 06 30 00 00 EB 20 00 01 98
D4 00 00 07 30 00 00 AA 10 00 00 32 D4 00 00 08
30 00 00 AA 20 00 01 90 D0 00 00 0A D6 00 00 08
30 00 00 EB 10 00 00 B3 50 00 00 10 D6 00 00 07
30 00 00 EB 20 00 01 98 D0 00 00 01 D4 00 03 19
C0 00 00 32 D0 00 00 00 D4 00 00 07 30 00 00 AA
20 00 01 90 D4 00 00 04 30 00 00 AA 10 00 00 32
30 00 00 97 10 00 00 72 D4 00 00 08 30 00 00 AA
20 00 01 90 30 00 00 97 20 00 01 91 D4 00 00 06
30 00 00 AA 10 00 00 32 D4 00 00 0A 30 00 00 AA
20 00 01 90 D0 00 00 01 D6 00 00 0A 30 00 00 EB
10 00 00 B3 30 00 00 10 D6 00 00 08 30 00 00 EB
10 00 00 B3 30 00 00 DF 10 00 00 F3 30 00 00 43
30 00 00 16 D6 00 00 07 30 00 00 EB 10 00 00 B3
20 00 00 0A 30 00 00 16 D0 00 00 01 D4 00 00 06
30 00 00 AA 10 00 00 32 D4 00 00 07 30 00 00 AA
20 00 01 90 D0 00 00 00 D6 00 00 07 30 00 00 EB
10 00 00 B3 D8 00 80 00 D6 01 00 00 40 00 01 1C
60 00 00 D4 60 00 00 DB D8 00 04 12 D2 00 03 E6
00 00 00 63 C0 00 00 31 D8 00 80 00 D2 01 00 00
40 00 01 0C 60 00 00 44 60 00 00 49 D8 00 04 1E
D6 00 03 EF 00 00 00 E1 C0 00 00 33 D8 00 7F FF
D6 01 00 00 40 00 01 1C D6 00 FF FF 30 00 01 1C
60 00 00 94 60 00 00 92 60 00 00 04 60 00 00 00
60 00 01 C0 30 00 00 D7 DE 00 00 01 30 00 00 FB
D8 00 04 0F D2 00 04 00 00 00 01 0B C0 00 00 34
D8 00 80 00 D4 01 00 00 40 00 01 14 60 00 00 DC
60 00 00 DB D8 00 04 0C D2 00 04 09 00 00 00 63
C0 00 00 31 D0 00 00 01 D8 00 04 44 C0 00 00 34
D0 00 00 00 D8 00 04 44 C0 00 00 34 D0 00 00 01
D8 00 04 44 C0 00 00 34 D8 00 80 00 D2 01 00 00
40 00 01 0C 60 00 00 44 60 00 00 49 D8 00 04 21
D6 00 04 1B 00 00 00 E1 C0 00 00 33 D0 00 00 00
D8 00 04 44 C0 00 00 34 D0 00 00 01 D8 00 04 44
C0 00 00 34 D8 00 7F FF D6 01 00 00 40 00 01 1C
D6 00 FF FF 30 00 01 1C 60 00 00 04 60 00 00 00
60 00 00 94 60 00 00 92 60 00 01 D2 30 00 00 C7
DE 00 00 01 30 00 00 FB D8 00 04 41 D2 00 04 32
00 00 01 0B C0 00 00 34 D8 00 80 00 D4 01 00 00
40 00 01 14 60 00 00 DC 60 00 00 DB D8 00 04 3E
D2 00 04 3B 00 00 00 63 C0 00 00 31 D0 00 00 00
D8 00 04 44 C0 00 00 34 D0 00 00 01 D8 00 04 44
C0 00 00 34 D0 00 00 01 D8 00 04 44 C0 00 00 34
D4 00 04 B3 D6 00 04 48 00 00 00 98 C0 00 00 32
D4 00 00 01 30 00 00 AA 10 00 00 32 D4 00 00 07
30 00 00 AA 20 00 01 90 D0 00 00 0A D4 00 00 08
30 00 00 AA 20 00 01 90 D4 00 00 01 30 00 00 AA
10 00 00 32 D4 00 00 09 30 00 00 AA 20 00 01 90
D0 00 00 0A D6 00 00 09 30 00 00 EB 10 00 00 B3
50 00 00 10 D6 00 00 08 30 00 00 EB 10 00 00 B3
40 00 00 10 D6 00 00 07 30 00 00 EB 10 00 00 B3
60 00 01 C0 30 00 00 17 DE 00 00 01 30 00 00 38
D4 00 00 07 30 00 00 AA 20 00 01 90 D0 00 00 30
D6 00 00 07 30 00 00 EB 10 00 00 B3 30 00 00 10
D4 00 00 07 30 00 00 AA 20 00 01 90 D4 00 00 04
30 00 00 AA 10 00 00 32 30 00 00 97 10 00 00 72
D4 00 00 08 30 00 00 AA 20 00 01 90 30 00 00 97
20 00 01 91 D4 00 00 06 30 00 00 AA 10 00 00 32
D4 00 00 0A 30 00 00 AA 20 00 01 90 D0 00 00 01
D6 00 00 0A 30 00 00 EB 10 00 00 B3 60 00 01 C0
30 00 00 17 DE 00 00 01 30 00 00 38 D6 00 00 06
30 00 00 EB 20 00 01 98 D4 00 00 0A 30 00 00 AA
20 00 01 90 D0 00 00 01 D6 00 00 0A 30 00 00 EB
10 00 00 B3 30 00 00 10 D6 00 00 08 30 00 00 EB
10 00 00 B3 30 00 00 DF 10 00 00 F3 30 00 00 43
30 00 00 16 D6 00 00 07 30 00 00 EB 10 00 00 B3
20 00 00 0A 30 00 00 16 D4 00 00 01 30 00 00 AA
10 00 00 32 D4 00 00 07 30 00 00 AA 20 00 01 90
D0 00 00 0A D6 00 00 07 30 00 00 EB 10 00 00 B3
50 00 00 10 D6 00 00 01 30 00 00 EB 20 00 01 98
D0 00 00 01 D4 00 03 D3 C0 00 00 32 D4 00 00 02
30 00 00 AA 10 00 00 32 30 00 00 97 10 00 00 72
10 00 00 B5 C0 00 00 32 10 00 00 B5 C0 00 00 32
D0 00 00 68 D6 00 00 0D 80 00 00 13 D6 00 00 04
30 00 00 EB 20 00 01 9A 20 00 00 B0 D0 00 00 65
D4 00 00 04 30 00 00 AA 10 00 00 B2 D6 00 00 01
20 00 00 98 D0 00 00 6C D4 00 00 04 30 00 00 AA
10 00 00 B2 D6 00 00 02 20 00 00 98 D0 00 00 6C
D4 00 00 04 30 00 00 AA 10 00 00 B2 D6 00 00 03
20 00 00 98 D0 00 00 6F D4 00 00 04 30 00 00 AA
10 00 00 B2 D6 00 00 04 20 00 00 98 D0 00 00 20
D4 00 00 04 30 00 00 AA 10 00 00 B2 D6 00 00 05
20 00 00 98 D0 00 00 77 D4 00 00 04 30 00 00 AA
10 00 00 B2 D6 00 00 06 20 00 00 98 D0 00 00 6F
D4 00 00 04 30 00 00 AA 10 00 00 B2 D6 00 00 07
20 00 00 98 D0 00 00 72 D4 00 00 04 30 00 00 AA
10 00 00 B2 D6 00 00 08 20 00 00 98 D0 00 00 6C
D4 00 00 04 30 00 00 AA 10 00 00 B2 D6 00 00 09
20 00 00 98 D0 00 00 64 D4 00 00 04 30 00 00 AA
10 00 00 B2 D6 00 00 0A 20 00 00 98 D0 00 00 0A
D4 00 00 04 30 00 00 AA 10 00 00 B2 D6 00 00 0B
20 00 00 98 D0 00 00 00 D4 00 00 04 30 00 00 AA
10 00 00 B2 D6 00 00 0C 20 00 00 98 D6 00 00 04
30 00 00 EB 10 00 00 33 30 00 00 76 D6 00 00 02
30 00 00 EB 20 00 01 98 30 00 00 DF 20 00 01 99
D4 00 00 01 30 00 01 6A D6 00 05 1A 20 00 01 AB
D4 00 01 63 C0 00 00 32 D4 00 00 01 60 00 01 D2
30 00 01 6F DE 00 00 01 30 00 01 7D 10 00 00 B5
C0 00 00 32 
% ./a.um↵
run: not an executable file.
% um a.um↵
hello world


== Halted. ==
INTRO.UMR=10@999999|ホニャララ

ということで、INTRO.UCCとINTRO.UMRの10点ずつを獲得。

um.cのコンパイルを試すとSyntax errorが出る。ullocとufreeの定義の後のセミコロンが余計なのか?まあコンパイルできたとしてもUMバイナリーの与え方に癖があって試すのは大変そうだからここでは立ち入らない。

コンテストの参加者の記事に言及がないこと、INTROの追加点がもらえることから、knrはコンテスト後に追加された要素だと考えて良いだろう。

スコアボードと次回に向けて

前のINTRO+BASICと合わせると、今回までに獲得した得点は次のようになる:

INTROCIRCSBLNCEBLACKBASICANTWOADVTRADVISTotal
265000100081001175

得点が1006点を超えたのでftdのicfp.exeを使ってAssistant Administratorの権限が手に入るが、この話は次回以降にしよう。

Spread the love

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です