DCのソフト、新作が入らない。
本体の生産中止とまで行くと、新作ソフトがまったく入らないですね。Resが欲しいかなと思ったんだけど売ってない。トイザラスにはあったけど1円しか安くなってないんじゃなぁ。あとはツタヤの中古で4000円。それが一番安いのか。とりあえず4000円は結構痛いので今のとこ保留。機会があったらLaoxも見に行こう。ResのPS2版は売ってるんだけど、PS2なんて持ってないからDC版を買うしかないし、PS2があってもDC版を買うと思う。うーん、DCは性能的にはまだまだいけるレベルなんだろうけど残念だ。
Ridge。Rubyならすぐ書ける。C++ではなかなか書けない。どういうことだ。やはりそれだけRubyは書きやすいってことなんだろうな。しかし、ネイティブなAPIをわざわざラッパ作ってRubyからいじる気にはならない。ほかのRubyのGUIライブラリ/ラッパを使って組むのもいいんだけど、ちょっと手のこんだ事をしようとなると面倒になる。それにBe用のRubyラッパはまだないからね。
以前書いたコードで、newにブロックを渡して新しいインスタンスのコンテキストでブロックを実行、ってのがあった。LocanaでもRuby/Tkでもそうしてたからなんだけど、どう実装すべきか、実際それで良いのかっていう問題があった。実装の問題は、newで実装するのかinitializeで実装するのか、の問題。newで実装するのはいいんだけど、initializeを呼ぶタイミングが微妙になる。え、いや、initialize呼んだ後にブロックに決まってるじゃん。実際それで良いのかっていうのは、それが本当にわかりやすいのかってこと。newで作ったインスタンスのコンテキストでブロックを実行するなら、newブロックの外側のローカル変数はまったくつかえなくなる。ひどい場合にはグローバル変数を使う可能性も出るってわけ。その中で全部終わらせられるんだったらいいんだけど、ひとつのコントロールを、いろんなウィンドウに貼り付けることも想定してるからなぁ。さらに、このブロックの特殊な条件*1を使用するときにいちいち気にしなくちゃいけないかも…。
…どうしようとか考えていたら、Ruby1.7では「newにブロックつけて新しいインスタンスのコンテキストでブロック実行」てのがClass.newについたみたい。あれ、Rubyの方で実装されてたんだね。まあRidgeが出来上がるころには1.7も1.8か2.0になってるでしょう。
とはいうものの、公式に採用されたルールなんだからこれでいい、というわけにはいかない。Ridge(俺)の信条としては、人がやってるからそれが正しいとは限らない、みたいなところがあるわけだ。あと、このルールを適用するとまずいのがselfを頻発することになる問題だ。ブロック内でのselfは、一見何も問題ないように見えるが、そのブロックを手続きオブジェクトにしたときに、selfがどうなってるのかわからなくなる。しかもその手続きオブジェクトをインスタンス変数に代入したりしてるんだから大変だ。ま、わかってる人から言わせて見れば、ブロックはそれが出てきた時点でのコンテキストで動くから、手続きオブジェクトを作ろうが何しようが変わらない、ってわけなんでしょうが。しかし、そんな面倒なこといちいち考えてeach使ってる人はいないでしょう。つまり、そんなルールは知ってる人が少ないと思われる。すると、ブロックの中のselfはあまり当てにしないほうがいいと思われる。
そこで代替案。ブロックの引数にオブジェクトを渡してしまえばいいというもの。
button = Button::new button['on_click'] = proc {|win| win['text'].prop['text'] = "Hellow World" }
といった感じ。これはいいんだけど、winはどこから持ってくるんだって話ですね。そこでmodule関数を追加する。
button['on_click'] = proc_with(window) {|win| #ここにコード }
ブロックの仮引数winにはwindowが渡されるんですね。proc_withはRidgeのモジュール関数で、callを呼ばれると引数におまけをつけて渡せるオブジェクトを生成する。まあ見た目はそんなに悪くないかも。Procクラスに対応してProcWithクラスでも作れば良いかな。
これでも、問題は残るから、とりあえずRuby1.7のnewに付随するブロックに渡される引数を見てみないと話が進まない。newに渡された引数がブロックにもわたるなら問題無いしね。
昨日は疲れたー。
昨日は東京行き。遊びに行ったわけじゃないんだけど、帰る途中にあったイエサブによってくる。ブルーローズぅ…ってなんじゃこりゃあ。すごい分厚くて、思わず2冊取ったかと思いました。持ち上がんないんですけど。他にもボードゲームとか、MageKnightとか欲しかったけどあまり金もないし荷物がかさばると嫌なのでやめておく。ブルーローズだけで行きの数倍の重さになってしまった*2。秋葉原によって帰ろうかとも思ったけど、帰る時間を考えると遅くなるのも嫌なんですぐ帰る。まあ、遊びに行ったわけじゃないしね。
んで今日。明日から三連休ということもあってやる気なし。たまたま学校の図書館に行くと『プログラミングRuby』を発見。即借りる。読む本はたくさんあるんだけど、これは読まなくてはならんでしょう。デザインパターンカタログは少しずつ読めばいいし。問題はヒーローウォーズとブルーローズだね。
ブルーローズを見ると、(c)マーク*3がついてないページはコピーしちゃいけません、みたいなことが最後に書いてあった。多分最近のエンターブレインの本にはだいたいついてるとは思うけど。思ったんだけど、個人で使う分にはコピーはかまわないはず。著作権法では個人使用での範囲の複製は認められている。っつーことは、これはコンベンションや仲間内でプレイする際のキャラクターシートのコピーとかに言及してるんだよね。
こういうのがついてるのはあたりまえなんだけど、こう目立って書いてあるのはちょっと考えることが出てくる。個人使用の範囲の問題だよね。どこからどこまでを個人使用の範囲とするかが問題。著作権法ってのはそういう境界が曖昧なんでなかなか難しい。もちろん、ここからここまでと定めるのも弊害があるから曖昧になってるわけなんだけど。とりあえず、みんなに配るってのは普通は不可なはず。みんなに配るのはTRPGでいえばキャラクタシートやその他シート類。自作シートなら問題ないだろうけど*4、本についてきたシート類は問題あるかも、と思うわけ。そこまで言及したルールブックって今まで見てない、というか目立つところに書いてあったのが少ないからかもしれないんだけど、エンターブレインの本がはじめてみた気がする*5。それが書いてないってことは、ゲームをやる上でのシートのコピー&配布は個人使用の範囲と判断されてたわけだ。まさか、キャラクターシートはコピーしてはいけませんとは言えないだろうからね。
よく考えてみると、コンベンションでプレイしたプレイヤーにキャラクターシートを渡すのは、個人使用の範囲ってのはおかしい気がする。プレイヤーがみんなルールブック(もしくは原本)を持っていればいいんだけど、常にそうとは限らないしそうあるほうが珍しい。引用にもなってないし、図書館の蔵書でもないからこれらの例外には当てはまらない。ということは結局、1プレイにかかわる人数が数人規模であるから個人的使用の範囲で済むだろうという考えになる。いつも友人とだけやってるならまだしも、コンベンションでは通用しなさそうだなぁ。で、エンターブレインはその辺ちゃんと考えてコピーライト標記が出てるわけだね。エンターブレインだけじゃないのかもしれない。最近のルールブックなら何でもついてるのかな。まあいいか。
勘違いしてはいけないのは、著作権についての記述がない本はコピーして良いかというとそうではないという事。記述がなくても著作権はありますし、勝手にコピーしちゃいけません。ただ著作権法は訴えなけりゃ意味がない。つまり、特に配ってもいいよっていう記述のないキャラクターシートをコンベンションとかでプレイヤーにあげていても、著作者が問題ないと判断して、訴えでなければ問題はないってこと。しかし、これにも問題はありまして。訴えられなければ問題ない、の影にはばれなきゃなんでもやっていい、みたいな考えをする人がいっぱいいます。そういうためのものじゃないんですけどねぇ…。あとは各人のモラルの問題になってしまうわけです。もし、そうやって無法なコピーやってる人のせいで著作権法が厳しくなっちゃったりしたら、物を作ってる人たちが困るんですよね。
著作権は難しいんだけど、結構面白い。ちょっとでも勉強しておくと何か作ろう/かこうと思ったときにいいかも。自分もまじめに勉強したわけじゃないんで上で間違ったことかいてるかも。そんなのがあったら教えてください。
…あれ。なんで著作権について語ってるんだ。
うちの猫がなでろと言ってうるさいので今日はここまで。
サボり。
んー、頭痛い。
今日もRidge。procで手続きオブジェクト作ったときにブロックの中からselfを使うとどうなるか試す。…なるほど、作ったときの外側のオブジェクトがselfになるわけね。だからeachとかが上手く動くわけか。
これで、結構問題が解決。問題っていうのは、たとえばボタンを押したときに実行されるコードから同じウィンドウ内のほかのオブジェクトを参照できない問題のこと。これならselfを使うことで解決できそう。
win = SimpleWindow::new win.add ['text', TextBox::new] win.add ['button', Button::new] btn.properties['on_click'] = proc {|| #ここからtextを参照できない。 }
これが次のようになる。
win = SimpleWindow::new {|| add ['text', TextBox::new] add ['button', Button::new] btn.properties['on_click'] = proc {|| self['text'].properties['text'] = 'Button was pushed.' } }
SimpleWindow::newに渡すブロックは新しいウィンドウのコンテキストで実行される。つまり、新しいウィンドウオブジェクトに対してinstance_evalしてるだけなんだけどね。ここで作られたprocのselfは新しいウィンドウオブジェクトになるから上のようなコードが使えるようになる、というわけ。でも、前のコードには抜け道があって、textを参照できない振りしてるけどwin['text']で参照可能。すぐわかると思うけど。
Mozilla0.9.8のJLPがでてる。早い。昨日出たばっかりなのに。別に英語でも使うのに苦労はしないけど、システムのデフォルトブラウザがMozillaになってるから家族で使うにはちょっとね。だったらMozillaじゃなくてNetscape6.2でも使えよってね。でもMozillaの方が機能進んでるんだもの。
Java+Ruby+Palmはまだ試してない。今日はいろいろと忙しかったのだ。
明日は東京行き。日帰りで。ブルーローズ探してみるかな。
あー、レポート書かなきゃ。
SINからリプレイ早く作るようにとの催促。そうだった。他にやることあると忘れ気味ですな。
JavaでRubyを動かす。JRubyだ。実は先日、PalmでJavaは動く、JavaでRubyは動く、よってPalmでRubyは動く、という三段論法が飛んでくる。どこから飛んできたのかは知らないが。それで。JRubyをダウンロード。基本はソースだよねぇ、とかほざきながら展開するもJDKがないことに気づく。Javaは好きでないわけだしJDKなんて入ってるわけもない。JREは入ってるんでやっぱりバイナリを落とす。…わーい。ほんとにRuby動いてるよ。しかもSwingとか使ってるじゃん。いいねぇ。
JRubyがSwing使ってるならKVMとかPalmじゃ動かないじゃん、とか思う。そこだけはずしてコンパイルかな。とおもったら、GUI関係のクラスはなさそう。sampleみるとJava.importとかやってますね。…つまり動的ロード。すげぇ、すげーよJRuby。惚れた。しかし問題はまだあった。Palmなんかのリソースでこれが動くのか?そもそもKVMはダイナミックローディングできるのか。とりあえずKVMを探しに行く。あった。以前落としたもんね。とおもったら、Palm用のバイナリが入っていない。なぜ。面倒なので、WabaとかいうVMを落としてくる。こっちのほうがらくそうだしね。インストールは簡単。コンパイルはやっぱりJDKか。jarは使えないかなとか思うと、wrapとかいう独自コマンド使うんですね。面倒だなぁ。今日試すのはやめよう。
Mozillaだ。0.9.8がやっとでた。NetInstaller使うも、すごく遅い。途中で止まる。あきらめようとも思ったが、FullInstallerをIrvineで落としてみる。…速いじゃん。最初からこうしておけば良かった。とりあえず、Tabの閉じるボタンがわかりやすくなっててとてもいい感じ。一目でわかる変更点はないみたいだけど…。「クリックしてダウンロードしたファイルの名前が〜」ってどういう意味かな。
つぎはRidge。C++で、テンプレート引数に文字列を渡すやり方がわからない。一回やったのはconst char*にしておくこと。これなら大丈夫だと思ってたんだけど変なところでエラーがでる。VC++だけの問題なのかな。それとも自分が間違ってるか。テンプレート引数に文字列渡すことなんて普通しないしな。で、C++の方のコード設計に困って中断。Rubyのインターフェースはこんな感じに。
win = SimpleWindow::new win.add ['button', Button::new] win['button'].properties['on_click'] = proc {|sender| print "Hellow World" } win.run.join win.children.remove 'button'
win.children['button']ではなくwin['button']にしたのは、すでにwinがコンテナとしての性質を持っているから。他のウィンドウにもコントロールをそのまま追加したい場合は次のようにすればいい。
win1 = SimpleWindow::new win2 = SimplwWindow::new cnt = SimpleContainer::new cnt.add ['button', Button::new] win1.add ['container', cnt] win2.add ['container', cnt]
これで上手くいくようにする。これだと、次のようにできる可能性もでてきてしまう。
win1 = SimpleWindow::new win2 = SimplwWindow::new win1.add ['button', Button::new] win2.add ['container', win1]
これでほぼ上と同じ動作をしてもらいたいと考えることもあるかもしれない。このときはウィンドウにコンテナの責任を与えるのはやめるか。ウィンドウにはコンテナが必ず入るようにするとか。それが一番まともな動作だと思うけどね。
風邪気味かも。早く寝よ。
Be上でGCCとbinutilsのメイク。一応、一番新しいリリースを取ってくる。どちらもつつがなく、っていいたいところなんだけど途中で何かエラーが出る。なんだかわからんけど、そのまま続くからよしとしよう。よしとするも何も、画面がスクロールして消えるから読む間もなかっただけなんですけどね。でもインストールは完了。バージョンもあがってるのでいいことにする。
GCCはObjective Cもつかえるみたい。で。WindowsでもObjective Cが使えたらちょっと幸せかもと思って、GCCとbinutilsを取ってくる。コンパイルはどうしようか。やっぱりcygwinしかないわけです。でもcygwinはあまり好きじゃないのでmingwをcygwin上から使うことに。binutilsはどうでもいいんだけど、GCCが問題。やっぱり止められる。makeした瞬間に、あるファイルのルールがないとかいわれる。うーん仕方ないかな。binutilsはmingw環境にないとか言われている。あれ?mingwのmakeとかGCC使ってるはずなんだけど…。それだけじゃ駄目なのかな。やっぱりエラーで止められてるし。
mingwのGCCはやっぱりObjective Cは使えないみたい。Objective CをWindows上でまじめに使うことはおそらくないだろうけど、試しにね。やっぱiMac欲しいよう。OS XでObjective Cでいろいろと…。あうー。
そういや、WinXPはJavaVMが標準で乗ってないんだっけ。.NETに置き換えたいんだろうね、MSは。でもXPにはまだ.NETランタイム乗ってないしなぁ。.NETランタイム、英語版が21〜22MBぐらいだった気がする。確かにJavaVMと同じくらい。で、いままでXP買った人はJavaも使えなけりゃ.NETも使えないわけだよね。これで負担がかかるのは開発側の人間なんだよな。その旨をいちいちコンピュータ用語のわからないユーザーに説明するんだから。XPにはJavaVMも.NETランタイムも標準添付にすりゃよかったのに。.NET正式にでるまでXP待っててもよかったと思うんだけどな。
XPのテーマの仕様って非公開らしいね。だれでもテーマ作れるものだと思ってたのに。残念。WindowBlind XPを見つけたときに、何でこんなものいまさらいるんだろうとか思ったが。非公開か…。だからバッシング喰らうんだよ。どうしてそんなところすらオープンにできないんだろうね。あとで仕様変更できなくなるからかな。そんな急造の仕様で製品だしてるわけじゃなかろうに。本当にそうだったら大変だけど。あ、ありえるか…。
う、geocitiesにつながらん。Too many users?みんな、この時間に集中してつなぐのか*6。って、何人までつなげるようになってるわけよ、いったい。
更新した。やっとだぁ。
更新したのはいいけど、新しいバナーとかがまだだ。最近グラフィック作るの面倒になってきちゃったからなぁ。早く何とかしよう。
更新以外にもRidgeを少しづつ。進めるといっても、設計で迷ってる段階。今日は実装のほうをまとめた。C++で組んでるんである程度インタフェース作って、それを実装する形にする。当然といえばそうなんだけど、どこからどこまでを分けるのかっていう問題や、クラス数が多くなるっていう問題、何よりRubyのクラスにこだわらないっていうのを忘れちゃいそうで怖かったから今まで出来なかった。だけど、やっぱりマルチプラットフォームにするにはかなりのレベルで分けないとあとで面倒になるからな。
新しいRubyのGUIライブラリLocanaがでてた。Windowsとtkがいまのところつかえるみたい。ん、HTMLってなんだろう。とりあえず見たところ、特に目新しいところのない無難な感じ。いろいろなGUIにバインディングしやすいってわけね。確かにそれも道のひとつだ。とりあえず目指すところは似たような感じなので一応目をつけとく。ライバルか!?(笑)
で、Locanaのイベントはこんな感じでバインド。
button.bind('on_action', "print 'Hellow World'")
…わからん。何でこうなるんだ。第二引数にはRubyのコードを文字列で指定するらしいんだけど、こうしたらいちいちevalしなくちゃ駄目じゃん。それ以前に文字列にすると""で囲ったりとか面倒なんだけどな。Apolloみたいにdefでオーバーライドする形式だと動的に切り替えられないからか*7。ブロック渡すってのは考えなかったのか。それとも何か問題があったんだろうか。謎。
Locanaのアトリビュ−ト(プロパティ)設定は次のようにやるみたい。
button['style'] = 'bold, italic'
これはまともだね。あとから追加とかもできるだろうから。いたってわかりやすい。いい案だと思う。けど…まだ甘いかな。Ridgeならこうする。
textbox.property['text'] = "Hellow World"
同じに見えるんですけど…ってそうですね。でも、こうできたらどうだろう。
props = { 'text'=>'Hellow World', 'fontname'=>'MS UI Gothic' } textbox.property = props button.property = props
こうすれば簡単にたくさんのオブジェクトのプロパティを設定できる。property=メソッドでは、ハッシュから必要な物だけ取り出して設定すればいいわけだし。次のような怪しいこともできる。
textbox2.property = textbox1.property
プロパティは大体こんなものかねぇ。ほんとはオブジェクトのアトリビュートにして設定できれば一番いいんだけど、それだとメンバがどんどん増える。追加もしづらくなるしね。あとはアトリビュートにすると上のようなことが出来なくなる。GUIライブラリでは、設定のコードがひたすら多くなるはずだからこういうことができるってのは重要だと思う。
あとはイベントのバインドだけど、eventアトリビュートを作ってpropertyと同じにするのか、それともイベントもプロパティの一部にしてしまうのか。どちらかというと後者のほうが好きだな。次のようになる。
button.property['on_click'] = proc { |obj| print 'Hellow World' }
イベントに設定するのは、callメソッドを持つオブジェクトなら何でも。上の例ならProcオブジェクト。他にもMethodオブジェクト、Continuationとかなんでも。べつにcallを持ってりゃなんでもいいわけだし。というか、それは呼び出し側が決めるんだし、呼び出し側が対応してればStringでもかまわないんだよね。
で、今思ったのがeventアトリビュートなんて作っても、実際書き込まれるものはなんだって良いわけなんだから、propertyと分ける意味がない。っつーわけで、余計なメンバが増えなくてすんだ。
ああ、結構仕様がまとまってきたかな。実装は大変なんだけど。上手くバインドできるように設計してないから、実際のAPIとあわせるのが大変なんだよね。いうならば俺Virtual Machine上では動きます。しかも俺VMが俺の理想OSで動いてるような感じなんだからな。しかし俺の理想OS、BeOSに近いんだよな。Beのネイティブな言語がC++じゃなくてRubyだったら、Ridgeなんて作ってなかっただろう。そしたらWindowsなんか使ってねぇよ。
♪ The Eccentric Opera : HYMN
*1新しいインスタンスのコンテキストで実行ってやつ
*2言い過ぎです。
*3まるCのマークと著作権者と年。
*4著作者が自分ですから。
*5あと、英語の本はあっても読まないないだけか。
*6現在11:30PMごろ
*7出来ないことはないけど。