面白いゲームだ
というわけで、先日からプレイを始めている「セブン・ビリオン・ヒューマンズ」ですけど、やっぱりこれ私好みだなぁ。
何がいいのかというと、考えて作ったプログラムが出来上がったら動かして、後はそのプログラムがガチャガチャ動作するのを見守るわけですけど、それが最後までうまく動いてくれた時の気持ちよさがいいんですねぇ。
この達成感。
パズルゲーム(ピクロスとか)特有のやったぜ!っていう感覚がいい。
49年目ができねぇ
で、今回は1ステージずつ完璧に攻略してから次のステージに進むというポリシーでプレイしているんですけど、49年目(=ステージ49)がむずい。

「ステージ数は60以上」というゲームなので、終盤に差し掛かっていることもあって難易度高いのだろうか。
……けど、この49年目の近くのステージであっても、ステージによっては一発でクリアできたりもするので、このゲームにおいてはプレイヤーによってステージの得手不得手が大きく分かれやすい気がする。
その人その人で思考パターンが違って、プログラムへのアプローチも違うというのがあると思われる。
そんなわけで、私の場合は49年目が苦手パターンなのです。
で、実はもう3日も悩んでいてくじけそうになってきたので、何がわからないのかを初めから整理しつつ、さらにこの面白いゲームを改めてお勧めしたいと思ったので、またもやブログに書くことにした次第です。
この面白さが届いたらいいなと思います。
こういうステージでハマっています
問題となっているのは「端っこの人から」という名前のステージ。

こういうステージになっています。

この画面について説明するとこういう感じです。

操作するのはほとんどは画面の右半分だけで、こっちにプログラムを作ります。
で、できたプログラムを再生すると、画面左側の社員たちがこのプログラム通りに動くのであります。
1人目の社員にはこのプログラム、2人目の社員にはこのプログラム……というのではなくて、全員が同じたった1つのプログラムの指示通りに動きます。
なお、パネルには数字がついていますが、動かすたびにランダムで変わります。今回の課題ではパネルの数字は関係ないので無視してOK。
あと、上司もプログラムには関係ないので無視してOK。
で、このステージもとりあえずクリア自体はしているんですけど……、

「行数目標」というところについて、7行以内のプログラムでうまいことやりましょうという目標があるんですけど、今のところベストな時でも15行のプログラムになってしまっている。(この画面はいろいろいじって19行になったときのもの)
そんなわけでこのステージでは、8枚並んだパネルについて、左端のパネル→右端のパネル→新たに左端になったパネル→という順番で拾ってシュレッダーに放り込む、7行以下のプログラムを作りたいんです。
けどそれがわからんのですなぁ……。
たぶんググると答え見つかるんですけど、見たらそれまでなので見ない。この悩んでいる時間が楽しいんだ。
少しずつ整理して考えよう
さて、まず、このステージで使える命令(コマンド)を改めて整理してみたい。
- step:いずれかの方向に移動する。
- pickUp:指定した方向の物を持ち上げる(拾う)。
- drop:持っているものを置く。
- giveTo:持っているものを何かに渡す。
- nearest:最も近いところにあるパネルやシュレッダーの位置を記憶する。
- set:パネルに書かれた番号などを記憶する。
- tell:何か言う。
- listen:tellにより、指定された声が聞こえるまで一時停止する。
- if:指定した条件に合っているときのみ次の動きをする。
- jump:指定した行に飛んでプログラムを続行する。
- end:行動を終了する。(プログラムの一番下に到達したときと同じ)
- 「~」:コメント(メモ)を書いておけるやつ。
こういったコマンドが使えるわけですけど、パネルをシュレッダーにかけるにあたっては少なくとも「パネルを拾って」、「シュレッダーの位置を把握して」、「シュレッダーにパネルを渡す」という3つの行動が必要になるでしょう。

とりあえずコマンドを3行置いてみました。
(mem1というのはメモリ(記憶)の1番のことで、各社員はmem1~mem4まで4つのことを覚えておけます。giveToで直接シュレッダーを指定できれば楽なんですけど、いったんmem1などに覚えないとgiveToで指定できない仕様。)
これで動かすと、

全員一気に動くのでわちゃわちゃしますけど、とりあえずシュレッダーにパネルを放り込む動きはできている。
あとは、順番さえちゃんと課題通りにできれば……!
じゃあ次は……、一番最初に左端のパネルを入れる必要があるので、if文を使ってみよう…。
左端の社員だけ動いてほしいので、03行目に「if 左 ≠ 社員」と書いてgiveToをifの中に入れると、「自分の左が社員ではない」つまり8人のうち左端の社員だけ04行目のgiveToをやることができる。

ここまでもいい感じにできているとは思うんだけど、果たして…。
しかしもう4行も使ってしまっているので目標達成までにはあと3行しか書くことができない。
なんとなくだけど2番目にシュレッダーにかけたい右端の社員も一緒に動かしてみるか……。
というわけで、if文の後ろにor(または)として条件を追加してみる。
(ifはor(または)とand(かつ)を使って条件をつなげることができますが、あくまでも1つのifの行なので行数が増えないのはうれしいところ。)

これで動かしたら、両端の2名が同時にシュレッダーに向かいましたが、シュレッダーがちょっと左寄りに置かれているために、うまいこと左端→右端の順番になりました。
いいぞ。
3人目からがよくわからん
じゃあ3人目はどうすればいいのかという話になるんですけど、とりあえず両端以外のひとは「Go!」って聞こえるまで一時待機(listen)してもらいつつ、シュレッダーにパネルを放り込んだ人はtellで「Go!」って言うことにして、これをjumpで繰り返させたらどうか。

結果、1人目(左端)がシュレッダーにかけてGo!というと3・4人目がすでに動き出すし、そうしているうちに2人目(右端)がシュレッダーにかけてGo!っていうと次の5・6人目が動き出すとかになるのでシュレッダー前が混雑して順番がめちゃくちゃになりました。

うーん、7行の目標達成にはlistenとtellを使うのは厳しいか?
もう一度整理する
改めて、さっき最初に挙げた3行の他に、絶対必要なコマンドを考えてみよう……。
全員一気に動いてはいけないから、たぶん、一部の決まった人だけ動くようにするためにifは必要だろう。
あと、8人を順次動かす必要があるから、jumpを使ってプログラムを上に戻して何度か回すようにする必要もあるだろう。

とりあえず、これらを使って「自分の左に社員がいて、右にも社員がいたら(つまり両隣に社員がいるときは)」ifの前までジャンプ(ループ)させておいて、それ以外の端っこの社員だけを動かすようにしたら良いのでは?
端っこの社員がシュレッダーに動いていけば、新たに端っこになった社員がこのループから抜けることができるので、なんとなく方針としてはよさそう。

やっぱりシュレッダー前が混雑する(シュレッダーに放り込む時間がちょっとかかる)のできれいに左右左右…とはいかないけど、惜しい感じはするんだよなぁ……。
その後いろいろ(以下、ネタバレ注意)
最初の何人かはうまくいくので、後半の社員はすぐに動かないようにif文を調整してみる。

どうも最後の2人が早く動き出しちゃって割り込むみたいになるので、真下にシュレッダー待ちの社員がいるときはまだシュレッダーに向かわないように(giveToしないように)ループしてもらうようにしよう。
と思ったら最後の2人のうち、右(41番のパネル)が先に動いてしまった。

おしいなぁ、最後だけ右左になる。
その後もさらにif文をいじったり…、

コメント機能をメモ代わりにして社員とパネルの位置関係を書いて考えてみたり……、

……してたら、

クリアできた件!
(一般的なプログラミング言語だと、if文の中のandとorではandが優先順位高かったりしますけど、セブン・ビリオン・ヒューマンズではとにかく前から順番に評価する模様。)

ウォー!
マジでブログに書くためにスクリーンショットを保存しながら一つ一つ考えながらやってた最中だったんですけど、なんか解決したぞ!
まとめ
考え方を変えて、少しずつ改めて考えるということをしていったら答えにたどり着くこともある。
そういったことを今日は学んだ気がする。
あと、今日のブログは動画もなしに画面だけでチンプンカンプンな内容だったかもしれません。すみません。
しかしもしセブン・ビリオン・ヒューマンズに興味が出たらGo!してみてはいかがでしょうか。
おわり。
コメント