kr_ryo 徒然日誌 <2006年2月12日分>

三國志製作記128〜混乱したオブジェクト指向は戦場で退却するか?〜

妙にあったかくなったり寒いというより冷たくなったり、まさに三寒四温、しかもインフルエンザも流行りだし、体調があっと言う間に悪くなりがちな日々、皆さまいかがお過ごしでしょうか?今年度私はまだ風邪ひいてないんですよね〜(^^;;そうそう、あったかくなるにつれ恐怖の花粉症が襲ってくるころでもあります。風邪対策マスクの人にまじりちらほら超立体マスクをしている人もいます。私はまだ大丈夫のようです、が、もうじき生産性低下シーズンですね〜それまでにがんばって作りたいところ(^^;;

ところが戦闘シーンを、動作を確かめもせずにげしげし書いていったところ、ぱたっと生産が止まります。やっぱりちょびっとつくって反応を確かめ、エラーを直し、して作らないと、うまくいっているのかどうかまったくわからず極端に作りにくくなってしまったようですね。ううむ…

しかもいくらオブジェクト指向といえども、大量のオブジェクトを作ってしまって、いったいどこにどんな名前のオブジェクトを作ったのか、どこにどんなメソッドを書いたのかわけがわからなくなってきました(*_*)ちょいとばかり継ぎ足しがすぎまして、無秩序化してきたかもしれません。しばらく使ってないオブジェクトなんて、何がどうなっているのやら…(--;)

さらに戦闘シーンは、何をどういう順番でやってもいい、というわけではなく、敵との相対で何ができるかが決まるので手続的です。作っているオブジェクトも、メソッドを順繰りに呼び出す昔ながらの手続指向的なプログラムになってきました。これもオブジェクト指向プログラマーとしてはなんとなく危険を感じさせます(~_~;)さらに私もずーっと誤解していて、実はその誤解は他の人もしがちであって、さらに本質的にオブジェクト指向言語が完全にオブジェクト指向を表現できていない、ということから生じます。

なんのことかというと、あるオブジェクトから別のオブジェクトを呼び出したとすると、元のオブジェクトではそのまま次の命令に進み、呼び出されたオブジェクトは元のオブジェクトとは別に、しかし時間的に同時に、マルチタスクして動くもんだと思っていました。軍団オブジェクトが武将オブジェクトに移動を命じたら、武将オブジェクトは移動を開始するとともに、軍団オブジェクトはすぐに次の命令である攻撃を実行する、と、こういうイメージでした。オブジェクト指向とはこういうもんだ、というイメージを持っていたので、挙動不審なプログラムのエラーが理解不能になることが多かったのです。

ところが、違うのです。なんと、実際は、軍団オブジェクトが武将オブジェクトを呼べば、武将オブジェクトに命令は移り、その武将オブジェクトの実施すべき移動命令が完全に終わってから、軍団オブジェクトに戻り、軍団オブジェクトの次の命令である攻撃を実行していたのです。へぇっ!だったらシングルタスクじゃん!!

実際のところ、OSのマルチタスクといえど、本当の意味での同時並行はできておらず、それぞれのプログラムを順番に少しずつ実行してマルチタスクに見せかけているだけです。まあ、人間様にとってはそれで十分マルチタスクなわけですが、本当のマルチタスクを実行できるようにするためには、CPUを複数にするとかしないといけないようです。それだって本当は純粋にはマルチタスクにならないのは、現在のコンピュータが作られているモデルが命令を順番に実行する、というものである以上しょうがないようですね。もっともコンピュータによるマルチタスクを本当にしたければ、1台のパソコンのCPUを複数にするとかするより、2台以上用意して別々のプログラムを実行すればもっと効率よくできてしまいます(^^;;

さらに、オブジェクト指向が別々のオブジェクト同士の共同作業のように見えるあまり、手続指向型ちっくなプログラムを作っていると、もはや戻らないと思い込んでいる呼出元のオブジェクトに処理が戻ってしまって、わけのわからない結果になったりします。どういうことかというと、手続指向型だとサブルーチンにでもしない限り、処理を別の場所に飛ばしてしまったらそれっきり元の場所には戻ってこないんですけど、オブジェクト指向では他のオブジェクトを呼び出して、他のオブジェクトの処理が流れていったとはいえ、その処理が終わったら元のオブジェクトに処理が戻るのです。手続指向型プログラムではツリー図のように条件やなんかでどんどん先へ先へ分岐しますんで、先へ行ききったらどうなるか、ということが必要になってくるんですけど、オブジェクト指向では順繰りに戻ってくるんですね。巻き戻ししている感じになって、条件で分岐させて別のオブジェクトに飛ばしたのに、また戻ってきたら先の分岐では行かないはずの処理が実行されてしまう!(*_*)まあ、if〜elseできちんと条件指定していればいいんですけどね、やっぱり行ったきりの発想なんでなんとなく忘れてしまったりします。そういう意味では、手続指向型というのはやっぱりどういう流れが続いているか、という記憶を強いますね…

そういうわけであんまり覚えなくてすむ、というオブジェクト指向でオブジェクト指向的なプログラムを作る方が楽は楽です。完成する前ながらちょいと作り直さなくちゃいけませんかねぇ…次の処理に進むのに、ある処理を完全に終わらせる前に別の処理を呼び出すから手続指向型ちっくになるんであって、それぞれの処理を関数のように考え、処理を順に呼び出す管理のための処理を用意すれば話はわかりやすいんですけどね。ふむー!デザインパターンでいうところのStrategyパターンですかね。ふんふん、なんとなくできそうな(^O^)

ということで、今回は速攻で解決策が出てきたので早速プログラムに戻り…というのはちと早すぎる気がするんで(^^;;今考えているネタを2つほど。1つは先程のつづきで、これまた先程ご紹介したサイトにもあるように意外にオブジェクト指向は理解されないのは説明もたとえも悪い、というお話。もう1つは、戦闘における勝敗についてです。

前掲のサイトの管理者さんは本も出している方で、意見批判大歓迎だそうです、が、とりあえず大賛成なんで(^^;;まあ、問題はないんですけども、私が絶賛していた『憂鬱なプログラマのためのオブジェクト指向開発講座』での名詞を即オブジェクトとするモデリングを批判されています……って、私も実は仕様から名詞を取り出してオブジェクトにする、ということで混乱し、なんとかデザインパターンでその無理さ加減を認識して正道復帰したくちなんで、確かに問題ではありますね。もっとも、90年代発刊のこの本の当時では、オブジェクトは名詞を取り出すとされていたわけで、それがいかん、というのもなかなか厳しいわけです。逆にいうと、オブジェクト指向自体の発明?は古くに行われていたのになかなか流行らなかったのは、名詞即オブジェクトである、というやや問題のあるモデリングにもあったのかもしれません。

仕様に現れる名詞をオブジェクトとする、という考えで我が三国志をオブジェクトにしてみましょう…って、やりましたね(^^;;もっかい取り上げましょう。これです。

モデル

私は今やUMLに移っているので○●が懐かしいOMTモデルですね。って、去年の話なんで我ながら早いバージョンアップ(^^;これの問題は何かというと、まず、UI=ユーザーインターフェース絡みが全然出てきません。右クリックメニューなんてのは仕様をどう書いても、仕様それ自体からは普通は出てこないでしょう。「武将を操作するのはリスト中の武将名を右クリックして出てくるメニューから…」なんてやるのは、右クリックメニューを使うことにして、それを仕様に書いた場合だけです。普通に仕様を書いていても、どう右クリックメニューが現れるというのか…?そのため、仕様から即オブジェクトを起こせません。仕様やモデル図をどうひねくりまわしても、どう細かく書いても描いても、現実の操作を想定したそういうウィンドウを作ってみる方がはるかに早くできあがるでしょう。

それから、武将というオブジェクト。オブジェクト自体は独自データと共通操作を持つ固まりであります。先程のサイトにもありますが、オブジェクト指向のいいところは、オブジェクトを大量生産できることにあります。大量生産といってもまったく同じものを大量に作るわけではなく、それぞれ別の独自の内容は、独自データとして保持できます。武将オブジェクトなら行動などは共通操作で、名前や能力などは独自データとして持てば、それぞれ別々の武将を武将オブジェクトとして大量生産できます。

それの何が問題かというと、それだけだとその大量生産オブジェクトを管理することができないということにあるんです。プログラム中では、ユーザの指定した誰か、という、武将オブジェクトなら誰でもいいから誰か、という指示の必要があるんですけど、張飛オブジェクトとか関羽オブジェクトとかそれぞれ名前をつけた管理の仕方をすると、呼び出す方法がものすごく複雑になります。10人くらいなら分岐できるんでしょうけど、100人200人となるともうやってられません。分岐専用オブジェクトみたいなのが必要になってくるものの、それは仕様&名詞モデリングでは絶対出てこないような内容です。

これをデザインパターンで考え直すと、個別のオブジェクトに個別の名前なんてつけず、管理オブジェクトとデータ保持オブジェクトとを分離して作成することになります。管理オブジェクトは指示されたデータオブジェクトを呼び出すだけでなく、操作もデータオブジェクトでなく管理オブジェクトの側で持つことで、設計がすっきりします。当然のことながら、こういったデザインは仕様&名詞モデルでは出てきません。そうしよう、と思ってしなければ、自然と浮かび上がるものではないのです。

ということで、オブジェクト指向はむしろデザインパターンを学んでようやくさまになる、という感じです。なので、仕様とその名詞から自然とモデルが出来上がる、ということは残念ながら幻想で、その幻想のせいでまともなモデリングができず、モデリングの深みにはまるか、オブジェクト指向なんてつかえね〜!となるようですね。もっとも、管理オブジェクトをデータオブジェクトとセットで武将オブジェクトと見れば、先のモデル図と同じになるわけではあるんですが(^^;;あのモデル図から管理オブジェクトとデータオブジェクトの分離の発想が出てくることは、まあ、無理ですね(*_*)

さらに今回オブジェクト指向は実は関数呼出やサブルーチンにすぎないものの、やっぱり手続指向型とは発想が違うという認識を新たにしたので、また将来的にはオブジェクト指向について書いてみたいと思います…で、もうひとつ、戦闘の勝敗について。

生ける仲達が走ろうがなんだろうが、ある場所に最後までいた方が勝利者であるのは間違いありません。だからといって、最後の1兵が生き残った方が勝利者、とするのはあまりに史実を無視しすぎです。本来全滅するまで戦うのは、全滅しそうな方の士気がよっぽど高くないといけません。皆が死を恐れぬ勇者であるとか、最後の砦であるとか、降伏しても許してくれないのがわかっているとか、相手がエイリアンでどうしようもないとか(*_*)、退けないし降伏もできないシーンは、そうそう多くあるもんではありません。劉禅のように最後の砦だろうが呆気なく落ちることもあります。ところがよくあるシミュレーションゲームでは、SWGも含めて(^^;A、勝敗は全滅をもって決めることが多いです。よほど勇者揃いなのかもしれません。

昔似たようなお話をしましたけど、勝てるかどうかわからないから戦うのであって、勝てないとわかっていればはなから戦いません。それでも戦いを挑んで来られたら、戦わず崩れて逃げ出すでしょう。ということは、負ける、とわかる以前、勝てないと思ったら逃げ腰になってしまうわけです。たとえ相手が100万、味方は3千であっても、勝てると思えば突っ込めますし、勝てないと思えば戦わず逃げ出すか降伏するでしょう。その辺は将の器量にもよるんでしょうね。ただ、張飛といえど長坂坡で曹操軍に突っ込むようなことはしませんでしたねえ。最初は逃げなかった、というだけで、とりあえず後で逃げてることは変わりありません。曹操も、計略があると思ったからうかつに攻めなかっただけで、そうでなければもみ潰したでしょうから。

で、勝てないとわかれば逃げ出しますから、全滅するまで戦うなんてことはしません。逃げられなければ降伏するでしょうし、逃げられるなら逃げます。問題は勝てないと思うのはどういう時なのでしょうか。兵数の単純な差であれば、まったく互角でなければ一方は必ず戦わず逃げ出すことになってしまってそれこそ史実に反します。大軍さえ率いれば勝てることになれば、官渡の戦いで袁紹は負けなかったはずです。逆にこの時曹操はあえて少数精鋭で向かったようで、それは袁紹軍に匹敵するだけの兵を集められない以上、無駄に雑兵が多くても、萎縮して逃げ出してしまうくらいならいない方がましと考えたのでしょう。と、考えると、兵自身の自信や主将に対する信頼というものが重要な気がします。

ナポレオンがあれだけ強かったのは、兵士がナポレオンは絶対負けないという強烈な信頼をおいていたから、という考えもできます。実際に強かったうえ、兵士が主将に信仰に近い信頼を置いていたことが大きな影響を与えていたんでしょう。劉備にしても呂布にしても、なかなかしぶとく生き延びたのは、主将や配下がやたらめったら強かったというのがあるはずです。

もちろん兵力差というのは大きく、袁紹に攻められた曹操、曹操に攻められた孫権なんかは、主将の意向はどうあれ、配下はものすごく動揺しています。兵力差が大きいのに、多い方が戦わず逃げ出すなんてことはあんまりありえません。しかしながら、戦ってみて、簡単には勝てず、むしろ自軍の方が損害が大きく、押され気味である、というシーンにおいて、勝てないんじゃないか?と兵が疑いを持ち出すと大軍も脆くなります。また、大軍側はたいてい兵力差だけで勝負しようとし、他の面、武将の質や兵糧の準備、兵の訓練などがおろそかになっていることが多いので、勝てなさそうな場面で主将が一時転進なんか指示しようものなら、主将からして逃げるんだからこの勝負は負けだ、とばかり、一気にボロボロになり、そこを攻めこまれでもすれば、総崩れになる、というところでしょう。

そうすると、士気値とかよりむしろ、状況状況において主将などが正しい判断ができなかったことや、そもそもの準備不足などによって脆い部分がさらけ出された、といった場合に戦線が崩壊する、と考えてよさそうです。兵がどんだけ死のうがなんだろうが、守れ、と泰然としている、もしくは無関心で馬鹿な将軍の方がしぶといわけで、兵と同じように、このままでは負ける、死ぬ、とか恐怖にかられる将軍はあっさり退いてしまって、つけ込まれてやっぱり負けるんですね。諸葛亮はなかなか勝てないわけです…対して徐庶はやっぱり剣客だけあって強かったんでしょうね〜!兵もそうですが、将の心の弱気、これこそが退却の決め手になるのかもしれません(^O^)

index

〔TopPage〕

このページへのリンクはフリーです。
このページについてのご意見、ご質問などは、kr_ryo_green@yahoo.co.jpまでお願いします。
Copyright 2006© kr_ryo All rights reserved.
訪問件数