絶版本の発見

 最近私は、人工知能もどきのプログラムとして、いわゆる簡単なオセロプログラムを完成させて動かせるようにしました。そのきっかけとなったのは、1980年代の後半あたりに神田神保町の本屋さんで見つけて買った『思考ゲームプログラミング −オセロゲームのアルゴリズムと作成法−』という本で、『森田オセロVer.6.1』のC言語によるプログラムリストを見て驚いたことでした。当時の私は、ツクダオリジナルのオセロゲームやコンピュータ・オセロゲーム専用機などを買って、あるいは、パソコンのゲームソフトとしてこの種のゲームを買って、一人で遊んでいました。だから、その本のように、今で言う『人工知能』的な動きをするコンピュータソフトの中味を逐一説明しているものを見つけると、一気に関心や好奇心を掻き立てられてしまいました。そうしたものを自作する技術や知識や能力が全く無かったにもかかわらず、当時の私はそうした本を探して買いあさっていました。
 昨年、私なりに人工知能もどきのプログラムを作った時に、そのもとになったのは、その本に記載されていた森田オセロのプログラムリストの一部を真似たVBSスクリプトでした。ただし、それはかのプログラムリストのほんの先頭部分しか作っておらず、ただの見かけ倒しのものでした。以前の私は、20代の頃に会社の業務でC言語を使っていたとはいえ、技術者としては若僧の半人前でした。その本を手にとった頃の私は30代半ばでしたが、著者の一人であった故・森田和郎さんのC言語のコーディングの内容がほとんど解読できませんでした。よって、それを真似て作ったVBスクリプトも、ゲームの最初の盤面をパソコンの画面に出したたげで終わってしまうという、一切中味の無いお粗末なものでした。
 それで、50代半ばを過ぎた私は、そのプログラム作りに再挑戦をしたわけですが、その直前にかの森田オセロのプログラムリストを見てみたくて、身の回りをあれこれ探し回りました。しかし、この本は見つかりませんでした。このようなコンピュータ・プログラミングの趣味にうつつを抜かしていると、本業の方がおろそかになると思って、あえて長野県の地元にはその本を持って来ていないことに、やがて気がつきました。東京の私の自宅にあるに違いないから、年末年始に帰省した折に探してみようと思いました。
 それで、今回東京の自宅に帰って、本棚や押し入れの中などを探してみたのですが、簡単には見つかりませんでした。2年か3年前の帰省の折に、大掃除のつもりで蔵書の一部を処分してしまいました。その時に処分してしまったかもしれないと思いつつも、部屋の奧隅に積み上げておいた箱の中まで調べてみました。
 すると、その本が見つかりました。以前ネットで調べたところによると、その本は絶版になっていて、簡単には手に入らないそうです。そのように、売れなくなった本は、世の中から必要とされなくなって、絶版となるのは仕方のないことなのかもしれません。今の私のように、人工知能(AI)をコンピュータ・プログラムの一種とみなしている人間でないかぎり、そのニーズは無いのかもしれません。しかしながら、この30数年前に出版された本にこそ、現代世界的に注目を浴びている人工知能(AI)の基礎が積み込まれていると、私は信じているのです。
 私が自宅で発見したその絶版本には、神田神保町東京堂書店のブックカバーがされていました。また、巻末のページには、「1986年3月1日 初版発行」「1986年5月25日 第1版第2刷発行」「定価1,600円」「著者 森田和郎・国枝交子・津田伸秀」「発行所 株式会社アスキー」などと書かれていました。それで、私は思い出しました。あの頃は、月刊アスキーという分厚いパソコン雑誌があって、しばしば本屋さんで買って読んだものでした。また、当時の東京堂書店のパソコン書籍コーナーでは、人工知能を扱った面白い書籍がほかにもありました。
 その中でも、『マイコン人工知能』という英語からの翻訳本は、チェッカーなどの対戦型ゲームのAIプログラム、ドクターという対話型AIプログラム、ライターという自動作文AIプログラムなどが、当時普及していた8ビットパソコン上のBASICプログラムで簡単に実現してしまうことが述べられていた本でした。その本に記述されていたBASICのプログラムは、当時私が持っていたパソコン上でも、多少の変更で動作可能となりました。おそらく、この著書は、人工知能について書かれた最も解りやすく、最も実践的なものだったと言えましょう。
 また、同じ東京堂書店のブックカバーがされた本で、今回私の自宅から見つかったもう1冊は、『BASICでつくる脳の情報システム』という本です。人間の脳のシステムが部分的にどうコンピュータ化されるかを、BASICのプログラム付きで浅く広く説明している本です。著者は、知能システム研究会です。ランダムドット・ステレオグラムや迷路の作り方とか、パーセプトロンやアソシアトロンなどの神経系のモデルや簡単な機械学習チューリング・マシンのモデル化などがパソコン上のプログラムで動作確認できるようになっています。広く浅くとはいえ、個々の内容は専門的で、少々とっつきにくい感じがしますが、いずれ人工知能やコンピュータ自身の理解に必要な基礎知識の一つになるようなことが書かれている著書だと、私には思えました。
 話を最初の『思考ゲームプログラミング』という著書に戻しましょう。この本に付けられていた帯には、「人工知能への挑戦 人工知能の実践として最も成功した思考ゲームのアルゴリズムをわかりやすく解説した初の書籍」と銘打ってありました。思考ゲームプログラミングの代表格である『森田オセロ』のプログラムが、そのように私たちを納得させるのには、それなりの根拠があると思います。私の自宅の書棚には、様々な人がプログラミングした自動翻訳システムの著書が4,5冊あります。しかし、どの著書を見ても、完全な自動翻訳システムというものは、残念ながらありませんでした。その代わり、自動翻訳システムは翻訳支援システムとして使われると、その威力を発揮すると考えられています。その翻訳の不完全さを補うのは、やはり人間の脳であり、人間の力なのです。
 しかし一方、『森田オセロ』は同じコンピュータ・プログラムでも、ゲームに勝つことを追求した人工知能の一つだったと思います。その完全さへの追及が、自動翻訳システムよりも徹底してできていると思われます。その精神は後に、『森田将棋』の開発に引き継がれ、現在の国産の、コンピュータ将棋ソフトやコンピュータ囲碁ソフトの開発にもつながっていると思います。
 今後、私としては、その絶版本から『森田オセロ』のアルゴリズムの解読を何とか進めて、それをVBスクリプトを使って、人工知能もどきのプログラムに組み込んでみようと計画しています。あくまでも趣味なので、納期はありません。いつ実現するかはわかりませんが、試してみようとは考えています。

災い転じて幸運となせるか?新たな挑戦!

 今年もかれこれ大晦日となってしまいましたが、それほど反省の多い一年間となってしまいました。とにかく今年は、私にとっては、学ぶべきことや知るべきことの多い年でした。そのため、どうしても、このブログ記事を書く時間的余裕が十分にありませんでした。
 ところで、今年も年末になって、今年を漢字の1文字で表すとしたら何になるか、といった行事が先日あったのですが、その日は、地元のJAきゅうり部会で埼玉の農薬製造工場へ視察研修に行っていて、そっちのことにかかりっきりになっていました。後日テレビやネットで確認したところによると、今年の漢字1文字は『災』だということがわかりました。自然災害や人災などによる事故や不幸を多くの人が感じていた今年一年だったということがわかります。
 私自身にそのことを照らし合わせて考えてみても、この一年、大小いろんな災いがあって、そのたびに苦労したな、と思い返します。つい最近も、12月に入って、キュウリ栽培や稲作に使った田畑の片づけをしていたのですが、半年くらい動かさなかった耕うん機を動かすことができずに苦労してしまいました。1日目に、エンジンオイルを交換したり、保守点検を自前でやってみたのですが、そのディーゼルエンジンが回らない。重たい鉄の機械で手で押したり引いたりすることもできず、JAの農業機械センターへ持っていって、故障個所を診てもらうこともできませんでした。仕方なく、その農業機械センターに行って、エンジニアの方に不具合の状況を話して、アドバイスをいただきました。
 そして、2日目3日目と、自前で修理点検を繰り返していたのですが、それでやっとその機械はエンジンが始動しました。それから、30アールの田んぼを6時間かけて土おこしすることができました。また、今回の機械修理で、ディーゼルエンジンの燃料パイプの空気抜きの方法もわかって、実際に試すことができました。それでわかったのですが、その数日前かに、氷点下のものすごく寒い日が続いていて、エンジンの排気口に詰まっていたススがその寒さで凍結していたのが、そのエンジンのかからなかった原因のようでした。
 また、12月に入って、こんなこともありました。私は、ビジネス用(つまり、ビジネスユース)の中古パソコンをいわゆる『趣味のマルチメディア・パソコン』として利用しています。説明が遅れてしまいましたが、私が趣味の一環としてパソコンを使い出したのは、意外と古く、1980年代からです。その中でも、自前でプログラムを組んで、写真などの画像データをパソコンの画面に出して、見て楽しむなどの趣味は、今でも続いています。(最近は、高解像度コスプレ写真などの巨大ファイルを狭い画面で観賞できるようなプログラムを作ったりして楽しんでいます。)ところが、先日、ネットからダウンロードした動画編集ソフト(フリーソフトのもの)をそのパソコンに入れて操作していたら、突如としてパソコンが誤動作してしまいました。最初は、扱った動画ファイルがアクセスできなくなるだけでしたが、そのうちに、ファイル操作がおかしくなって、コンピュータの動作そのものがのろくなりました。ついには、パソコンの電源は入るものの、ウィンドウズOS自体が立ち上がらなくなりました。
 これは大変、ということで、秋葉原電気店で以前買ってあったウィンドウズ8のDVDを使って、様々な復旧方法でシステムを回復しようとしましたが、どれもうまくいきません。それどころか、その復旧方法のいくつかは、膨大な時間を必要として、四六時中、問題のパソコンの電源を入れたままにしておかなくてはならなくなりました。その中古パソコンは、ビジネス用に作られていたので、ハードウェアが多少頑丈な作りになっていました。けれども、過去に多くのパソコンをお釈迦にしてきた私にとって、そのことはあまり当てにはできませんでした。実は、これが今年の最後に直面した私の最大の災いとなりました。
 その中古パソコンの復旧問題と2週間以上も、格闘する破目となりました。今となって考えてみると、機械の動作がおかしくなった時点で買い替えたほうがよかったのかもしれません。しかし、そのパソコンを廃棄することに抵抗感があったことと、私自身に昔のコンピュータ技術者としてのプライドがあったことが、さらに、このトラブルに輪をかけて災いしてしまったようです。
 ただし、そうした災いの連鎖だけが全てでなかったことは、ハッキリと述べておかなければいけません。いかなる災いにも、悲しみや残念に思えることは付き物です。けれども、そこから教訓や方策や新しい物事とか技術を学び取ることも、大切なことだと思います。それも、折角のチャンスだと思って、その苦境から逃げずに、敢然と立ち向かっていくことも時には良いのかもしれません。
 事実、私は今回のパソコンのトラブルで、ウィンドウズOSの復旧方法が、その不具合の段階に合わせていくつもあることを学びました。コンピュータの長いディスクアクセス時間中に電源を切ると、ディスクのデータ構成が壊れます。物理的にディスク装置の一部が壊れて、セクター不良になっていることが、しばしば昔のパソコンのディスク装置にはありました。現在のパソコンのディスク装置では、そこまでなっていなくても、クラスターの構成が少々おかしくなっているだけで、ウィンドウズを始めとするシステム・ソフトウェアが正しく動かないということがあるようです。今回のトラブルで、そうしたことが私にはよくわかりました。
 復旧方法をいろいろと試した挙句、望ましい結果がどうしても得られないことに気がつきました。結局、パソコンの内蔵ディスク装置をまっさらにして、ウィンドウズ8を新たに入れ直しました。がしかし、故障前のコンピュータの速さが戻りませんでした。この中古パソコンは、購入時にウィンドウズ7で動いていましたが、後に私はウィンドウズ8にアップデート(更新)しました。その時以降も、コンピュータの速さは落ちることがなかったので、そのまま何も調べずに使っていました。しかし、今回のトラブル以降は、シャットダウンした機械の立ち上がりが30分以上もかかるようになってしまいました。一体何が原因なのか、どうしたら電源投入後の立ち上がりを速くできるのか、などということを、探求する日々が続きました。すると、ウィンドウズOSには、大容量ハードディスクの中で頻繁に使われるデータを高速で読み書きできる仕組みとか、特定のディスク装置の読み書きを速くするデバイスドライバーとか、ウィンドウズ自体のディスク管理ユーティリティ(ファイルのインディクス管理、ディスククリーンアップ、デフラグなど)とかがあることを改めて知りました。しかも、それらを全て活用したとしても、必ずしもそのトータルとして、ウィンドウズOS自体が速くなるとは限らないこともわかりました。おそらく機能や性能のだぶりがあって、一度データを読み込むところを何度も読んでいてタイムロスが発生してしまうのかもしれません。
 そんなわけで、あれこれ回り道をしているうちに、いくつかの仕組みのより良い組み合わせを発見して、ウィンドウズが10分以内に立ち上がって、操作して使えるようになりました。ところが、この新たなシステムに変わって間もなく、さらに違う災いと遭遇することとなりました。これまで普通に動いていたフォトというアプリを使おうとして立ち上げると、写真データの数の多さから頻繁にダウン(終了)してしまうようになってしまいました。任意に選んだ写真データを画面に出すプログラムは作ってあったのですが、写真データを順次閲覧するようなアプリはまだ作ってはいませんでした。これまでは、フォトというアプリにそれを頼っていたのですが、それが使えなくなってしまいました。そこで、私の作った従来のプログラムを、写真データを順次閲覧できるものに改造して、フォトというアプリの代用としました。
 こんなふうに、そうしたトラブルなどの災いが起こるたびに、これまでとは違うやり方を発見したり、そこから学んだり、ということがあるものなのです。そうした災いにあって悲観することは仕方ありません。けれども、そこから得た教訓とか、学習したことというのは、いずれ悲しみが楽しみに変わる前兆と言えましょう。
 勿論、あらゆることが「禍(=災い)転じて福となす」となるとは限りません。そこには当然の事ながら、いばらの道が続いているかもしれません。しかし、それができるかできないかは、やってみないとわからない、というのも真実だと私は思います。そうした何らかの兆しとか小さなチャンスとかを誰もが見い出せることを、願ってやみません。

人工知能もどき開発事情

 人工知能(AI、Artifical Intelligence)は、現在世界的に流行しているIT技術の一つです。しかし、それは、一般の人々には手の届かない高付加価値な技術の一つとして、その成果に私たちの日常生活は支配されっ放しで、歯がゆい思いをしている人も多いと思います。確かに、今や人工知能は、私たち一人一人の将来をも左右しかねない脅威となりつつあると言えましょう。私のような個人ではどんなに努力をしても手にすることのできない、金銭と労力がこのテクノロジーの実現のために世界的に費やされている。それが、この世の現実であることを誰も否定できないと思います。
 それでは、誰もがこの現実を見て見ぬふり、いじめられっ子のようにされるがままになって、生きてゆくしかないということなのでしょうか。あるいは、どんなハラスメントを受けるよりもつらい未来が待っているにもかかわらず、私たちは、何をする術(すべ)も無く、それを手をこまねいて見ているしかないのでしょうか。いずれにしても、それは、私にとっては、好ましいことではないと思われました。
 つまり、私は、このことに関して、ささやかな反抗を試みてみようと考えました。私の習得している、ささやかなコンピュータ・ソフトウェア開発技術を駆使して、人工知能を中核とした巨大システムに一矢を報いたいと考えたのです。
 ここでまず申し上げておきたいことは、私自身は、人工知能そのものを作ることができないということです。人工知能に対する、私の抱いているイメージは、ハードルが高くて、例えば「オッケー、グーグル。」に反応して受け答えするくらいでは満足いたしません。したがって、私自身が満足するような高い機能仕様の人工知能を自作することは不可能なのです。
 その代わりにどうするのかと申しますと、「人工知能って、何だ?」という問いから始まって、それと似ているもの、すなわち、『人工知能もどき』(あるいは、人工知能の疑似プログラム)を開発しようと思いました。人工知能それ自身は手に入れられないけれども、人工知能っぽいコンピュータ・プログラムは自作できそうな気がしました。
 かつて、1980年代から1990年代の私は、双方向自動翻訳プログラムとか、森田オセロのプログラムとかを、雑誌や単行本の書籍で見つけて興味をそそられていました。こうしたBASICやC言語によるプログラムは、当時は『思考プログラミング』と呼ばれていました。これは、プログラマ(プログラムを組む人)の側に立った呼び名(ネーミング)でした。しかし、現在の私の考えでは、これこそ、人工知能もどきの中核部分になりえるプログラムに思えました。こうした『思考プログラミング』の考え方でパソコン上で今どきの簡易言語を使って、プログラムの中心部分を作り、さらに周辺部分をふくらませていけば、『人工知能みたいな感じの疑似プログラム』が組めるのではないかと、おおざっぱなシステム設計をしてみました。
 かつて、2000年代に、VBスクリプトやHTLMなどの簡易言語をかじりたてだった私は、『思考ゲームプログラミング − オセロのアルゴリズムと作成法』(アスキーブック)という書籍を購入して、コンピュータオセロの仕組みを学ぼうとしていました。4隅4辺を優先して取るように評価関数の値を上げるとか、先読みのためにゲーム木検索をしてアルファベータ法やミニマックス法で検索木の枝刈りをするとか書いてありました。関数の再帰的呼び出しによって、効率的なプログラミングをするとか、中盤には必勝読み、終盤には完全読みをするとか、その本には書かれていました。
 それらの事柄は、当時の私にとっては専門的すぎる内容でした。そのため、森田和郎さんのC言語によるソースプログラムが巻末に載っていましたが、途中で解読不能になって何度も私は投げ出してしまいました。そのC言語のプログラムをVBスクリプトに組み直して、最新のウィンドウズのプログラムにすることを、当時の私は趣味の一つとして思いついたのでした。がしかし、その移植の思いつきは、ものの見事に挫折してしまいました。プログラムの冒頭部分(ヘッダー)の定数定義と、盤面の表示部分を作っただけで、それ以降の中核になるプログラムは全く作れませんでした。
 ここ最近になって、年末年始に東京の実家に戻ると、本棚に眠っているその本を手に取ってみることが何度かありました。森田和郎さんのC言語によるコーディングは、私にとってはやはり難解でしたし、今さらその解読に時間と労力を費やすと、本業にさしさわります。そこは一銭にもならない趣味として、時間が取れたらやってみよう、森田オセロよりも簡単な、その中味がへっぽこでもいいじゃないか、という考えに変わっていきました。私の作りたいプログラムは、人工知能もどきなのだから、『へっぽこ人工知能』でかまわない、と考えるようになりました。
 というわけで、ここ半年余りで、何かの合間に作り足して、ウィンドウズOSのパソコン上で動作チェックをして、付録に示したような簡易言語プログラムが出来上がりました。これを作るにあたって、プログラム上のいろんなテクニックや仕組みを開発したのですが、その説明はまたの機会に譲ることといたします。ネット上の記事をほとんど参照としなかったので、見たこともないVBスクリプトによるコーディングがあるかもしれませんが、そのようなプログラム開発の方針のよるものだということでご了承ください。(HTMLで作ったゲーム盤をランダムアクセスするために、VBスクリプトでアドレスのベクターテーブルを作ったり、人工知能っぽく見せるために、イベント処理の反応の仕方に細工をしたりタイマー処理を連発させたりしています。)
 あとになって再び書くかもしれませんが、コンピュータ側が盤面に手を指す以下の一行の命令
    Q(yy, xx).InnerText = ComMove
の書かれる位置をプログラム上で少しあとにずらしただけで、盤面をチェックしていた他の関数がタイミングが合わずに正しくチェックできなくなって、プログラム全体が誤動作してしまうこともありました。結局その不具合を直して、プログラムが正しく動くようにしましたが、プログラム全体を大幅に修正することとなってしまいました。そうした悪い手本もあるので、プログラミング上での真似はあまり利益にならないのかもしれません。それでも、人工知能に似せた簡易言語プログラムがどのように動くのかを知るために、パソコン上でそれを動かしてみるのはそれなりの意義があると思います。できる人は、ぜひ今回の付録をコピペして、コンピュータ上で動作させてみてください。
 さらに説明しますと、このプログラムには、先読みをするプログラムとか、機械学習をするプログラムとかが入っていません。なのに、そこそこ強いので、人間の側が油断すると、簡単に負かされてしまいます。当たり前のことですが、それぞれの局面で相手側の石をひっくり返せる盤上の一手を全て洗い出します。そして、それぞれの一手に関して、ひっくり返せる石の数と、のちのち有利になる石の位置から評価値を割り出して、それが最大値となる手を『次の一手』に選びます。手の先読みをしない代わりに、指してはいけない手の評価値を下げて、その手を『次の一手』に選びにくくしています。
 私の作ったこのプログラムは、森田オセロの最初に説明されている、序盤のミニ定石データベース(あるいはデータブック)さえ持っていません。このプログラムの中核となる思考プログラミングは評価関数(EvaluateMax関数)以内に(あるいは、以下に)まとめています。その思考ルーチンは、ゲームの最初から最後まで同じものを使っています。ただし、それは、私のヒューリスティック(heuristic、発見学習)的なものを簡易言語を使ってプログラミングされています。(そのようなやり方が、プログラミングとして普通なのかもしれませんが)4隅4辺の場所を相手の石をはさみながら優先的に取るとか、4隅4辺を相手に取られてしまうきっかけとなる手はなるべく指さないとかいう条件を、コンピュータのロジック(論理)で記述しています。
 ここで、私の我がままを一言だけ申しておきます。私は、現在世界的に流行している人工知能が、機械学習とか深層学習(ディープラーニング)にとどまっていることが不満です。私たち人間は、発見的学習(ヒューリスティックス)によって、それをプログラミング言語に表現し直して、コンピュータを自在に操ることができます。だから、私たち人間が知っている人工知能は、人間と同じくらい発見的学習(ヒューリスティクス)ができないと、本当に人間を超えたことにならないのではないか、とも思えるのです。


注 "Othello"や『オセロ』は、株式会社メガハウス(旧ツクダオリジナル)の登録商標なので、以下の記事では、『オセロ』等の別名としてリバーシ(Reversi)という言葉を使います。


付録

Reversi V1.55.hta

<STYLE TYPE="text/css">

    BODY         { font-size:16pt; background-color:rgb(30%,70%,30%); scroll:no; }
    .scaleW      { font-size:16pt; font-family:"MS ゴシック"; text-align:center; }
    .scaleH      { font-size:16pt; font-family:"MS ゴシック"; text-align:left; 
                   line-height:18pt; position:relative; top:-220pt; }
    .banmen      { font-size:16pt; font-family:"MS ゴシック"; text-align:center;
                   border:1pt solid black; padding:5pt; margin:10pt 20pt;
                   cursor:default; }
    .message     { font-size:12pt; font-family:"MS ゴシック"; text-align:center;
                   padding:5pt; margin:10pt 5pt; }

    #fakebtn    { font-size:12pt; font-family:"MS ゴシック"; background-color:white;
                   border-style:outset; padding:5pt; margin:10pt 5pt;
                   cursor:default; display:none; }

</STYLE>

<HTA:Application Id=oHTA Border=dialog Scroll=no MaximizeButton=no Contextmenu=no />


<SCRIPT language="VBScript">
Option Explicit

Randomize

Const BLACK = "●"
Const WHITE = "○"
Const BLANK = "+"
Const BAD   = 0
Const BONUS = 8
Const GOOD  = 16
Const BEST  = 32

Dim WSHShell
Set WSHShell = CreateObject("WScript.Shell")

Dim Q(7,7), R(63), vx(7), vy(7)
Dim PointJustNow, ThinkingTime, RecoveringTime, gptr, wb, cp
Dim ManMove, ComMove, Selflag
Dim SaveMes


Call ResizeTo(280, 390)

Document.Title = "Reversi V1.55" 'This is a minor revision of Reversi Game v1.54

Set wb = New WatchingBoardSpace
Set cp = New CornerProcessingList


Sub Window_Onload
    Dim yy, xx, idx

    ManMove = BLACK
    ComMove = WHITE
    LargeMode = False

    idx = 0

    For yy = 0 to 7

        For xx = 0 to 7

            Set R(idx) = Document.all.tags("SPAN")(idx)
            Set Q(yy, xx) = R(idx)

            idx = idx + 1
        Next
    Next

    vy(0) = -1 : vy(1) = -1 : vy(2) = -1 : vy(3) = 0 : vy(4) = 0
    vy(5) = 1  : vy(6) = 1  : vy(7) =  1

    vx(0) = -1 : vx(1) = 0 : vx(2) = 1 : vx(3) = -1 : vx(4) = 1
    vx(5) = -1 : vx(6) = 0 : vx(7) = 1

    Call InitBan()

End Sub


Sub InitBan()
    Dim idx

    For idx = 0 to 63

        R(idx).InnerText = BLANK

    Next

    P33.InnerText = WHITE
    P34.InnerText = BLACK
    P43.InnerText = BLACK
    P44.InnerText = WHITE

    PointJustNow = ""
    ThinkingTime = False
    RecoveringTime = False

    Call wb.Clear()

    fakebtn.style.display = "none"
    mouth.InnerText = "さあ、始めましょう!"
    Call SelectStones()

End Sub


Private Sub SelectStones()

   Selflag = True

   TurnB.InnerHTML = "黒番?" : BStones.InnerHTML = " それとも、"
   TurnW.InnerHTML = "白番?" : WStones.InnerHTML = ""
   TurnB.style.cursor = "help"
   TurnW.style.cursor = "help"


End Sub


Class WatchingBoardSpace
    Private List(59), Lptr

    Public Sub Clear()

        Lptr = 0

    End Sub

    Public Property Let Watch(tid)

        If Not Found(tid) Then

           List(Lptr) = tid
           Lptr = Lptr + 1

        End If

    End Property

    Private Function Found(id)
        Dim idx, rfg

        rfg = False

        For idx = 0 to Lptr - 1

            If List(idx) = id Then

               rfg = True
               Exit For

            End If

        Next

        Found = rfg

    End Function

    Public Function AnyMore()
        Dim Empties

        Empties = GetBlanks()

        If (Lptr = 0) Or (Lptr < Empties) Then

           AnyMore = True

        Else

           AnyMore = False

        End If

    End Function

    Private Function GetBlanks()
        Dim idx, cnt

        cnt = 0

        For idx = 0 to 63

            If R(idx).InnerText = BLANK Then

               cnt = cnt + 1

            End If
        Next

        GetBlanks = cnt

    End Function

End Class


'
' Event Driven Routines
'
' On mouse over, On mouse out  ---  for user interface
' On click -- for user interface and the trigger on computer thinking
' On key press -- for board size changed by L key
'
Sub Document_Onmouseover
    Dim target

    Set target = Window.event.srcElement

    If Selflag Then

       If target.tagname = "SPAN" Then

          If Left(target.id, 4) = "Turn" Then

             With target.style
                  .color = "white"
                  .backgroundcolor = "rgb(10%,10%,10%)"
             End With

          End If
       End If

       Exit Sub

    End If

    If target.tagname = "SPAN" Then

       If Left(target.id, 1) = "P" Then

          If target.InnerText = BLANK Then

             wb.Watch = target.id

             If CountEnemy(target.id, ManMove, ComMove) > 0 Then

                With target.style
                     .backgroundcolor = "rgb(50%,80%,50%)"
                     .cursor = "help"
                End With

                PointJustNow = target.id

                Call wb.Clear()

             Else

                If Not wb.AnyMore() Then

                   mouth.InnerText = "打てませんね ...思考中"
                   ThinkingTime = True

                   Call setTimeout("NowThinking()", 2000)

                End If

             End If

          End If
       End If
    End If

End Sub


Sub Document_Onmouseout
    Dim target

    Set target = Window.event.srcElement

    If Selflag Then

       If target.tagname = "SPAN" Then

          If Left(target.id, 4) = "Turn" Then

             With target.style
                  .color = "black"
                  .backgroundcolor = "rgb(30%,70%,30%)"
             End With

          End If
       End If

       Exit Sub

    End If

    If target.tagname = "SPAN" Then

       If Left(target.id, 1) = "P" Then

          If target.innerText = BLANK Then

             With target.style
                  .backgroundcolor = ""
                  .cursor = "default"
             End With

             PointJustNow = ""

          End If
       End If
    End If

End Sub


Sub Document_Onclick
    Dim target, yy, xx

    If ThinkingTime Then Exit Sub

    Set target = Window.event.srcElement

    If target.id = "" Then Exit Sub


    If Selflag Then

       If Left(target.id, 4) = "Turn" Then

          With target.style
               .color = "black"
               .backgroundcolor = "rgb(30%,70%,30%)"
          End With

          TurnB.style.cursor = "default"
          TurnW.style.cursor = "default"

          Call FixTurn(target.InnerText)

          Selflag = False

          If ComMove = BLACK Then

             mouth.InnerText = "思考中 ..."
             ThinkingTime = True

             Call setTimeout("NowThinking()", 2000)

          End If

       End If

       Exit Sub

    End If


    If Left(target.id, 1) <> "P" Then Exit Sub

    If PointJustNow <> "" Then

       yy = Mid(target.id, 2, 1)
       xx = Mid(target.id, 3, 1)

       Q(yy, xx).InnerText = ManMove

       With target.style
            .backgroundcolor = ""
            .cursor = "default"
       End With

       PointJustNow = ""

       Call ReverseEnemy(ManMove, yy, xx, ComMove)

       If Not EndChecking() Then

          mouth.InnerText = "思考中 ..."
          ThinkingTime = True

          Call setTimeout("NowThinking()", 2000)

       End If

    End If

End Sub


Private Sub FixTurn(sterm)
    Dim st, dstr

    If sterm = "黒番?" Then

       st = BLACK

    ElseIf sterm = "白番?" Then

       st = WHITE

    Else

        msgbox"Illegally  selected [" & sterm & "]"

    End If

    If ManMove <> st Then

       ComMove = ManMove : ManMove = st

    End If


    TurnB.InnerText = "黒"
    TurnW.InnerText = "白"
    dstr = "(あなた)"

    If ManMove = BLACK Then

       TurnB.InnerText = TurnB.InnerText & dstr

    Else

       TurnW.InnerText = TurnW.InnerText & dstr

    End If

    BStones.innerText = " 2 個 "
    WStones.innerText = " 2 個"

End Sub


Private Sub NowThinking()

    If TurnToComputer() Then

       Call wb.Clear()

       If Not EndChecking() Then

          mouth.InnerText = DisplayYourTurn()

       End If

    Else

       If Not EndChecking() Then

          mouth.InnerText = "打つ手がありません。"

       End If

    End If

    ThinkingTime = False

End Sub


Function DisplayYourTurn()

    DisplayYourTurn  = "あなたの手番です。"             

End Function



Dim LargeMode

Sub Document_OnKeyPress()
    Dim tk, kc

    If ThinkingTime Then Exit Sub
    If RecoveringTime Then Exit Sub

    If fakebtn.style.display = "inline" Then Exit Sub

    tk = Window.event.keyCode
    kc = Chr(tk)

    RecoveringTime = True

    If kc = "l" Or kc = "L" Then

       LargeMode = Not LargeMode
       Call ChangeScale(LargeMode)

    Else

       RecoveringTime = False
    End If

End Sub


Private Sub ChangeScale(Lmode)
    Dim mes

    If Lmode Then
       mes = "盤を拡大サイズにします。"
    Else
       mes = "盤を通常サイズにします。"
    End If

    SaveMes = mouth.InnerText
    mouth.InnerText = mes

    Call setTimeout("RecoverMessage2()", 2000)

End Sub


Private Sub RecoverMessage2()

    If LargeMode Then

       Call ChangeScale2(420, 600, 22, 28, 24, 4, 31, -358, 24)

    Else

       Call ChangeScale2(280, 390, 12, 16, 16, 1, 18, -220, 12)

    End If

    RecoveringTime = False

End Sub


Private Sub ChangeScale2(sx, sy, fontSiz1, fontSiz2, fontSiz3, bSiz, Lh, topos, btnSiz)
    Dim obj, idx, cnm, styp

    Call ResizeTo(sx, sy)

    For idx = 0 to document.all.length - 1

        Set obj = document.all(idx)

        If obj.tagName = "DIV" Then

           cnm = obj.className
           Set styp = obj.style

           If cnm = "message" Then

              styp.fontSize = fontSiz1 & "pt"

           ElseIf cnm = "banmen" Then

              styp.fontSize = fontSiz2 & "pt"
              styp.border = bSiz & "pt solid black"
           Else

              styp.fontSize = fontSiz3 & "pt"

              If cnm = "scaleH" Then

                 styp.lineHeight = Lh & "pt"
                 styp.position = "relative"
                 styp.top = topos & "pt"
              End If
              
           End If

        ElseIf obj.id = "fakebtn" Then

           obj.style.fontSize = btnSiz & "pt"
        Else

        End If
    Next

    mouth.InnerText = SaveMes

End Sub


'
'  Heuristic AI Thinking subroutines
'
'
Function TurnToComputer()
    Dim tId(), tCnt1(), tCnt2(), tLast, maxidx, yy, xx

    tLast = ListingHands(ComMove, ManMove, tId, tCnt1)

    If tLast = -1 Then

       TurnToComputer = False

       Exit Function

    End If

    Call CopyTable(tCnt1, tCnt2, tLast)

    maxidx = EvaluateMax(tId, tCnt2, tLast)

    yy = Mid(tId(maxidx), 2, 1)
    xx = Mid(tId(maxidx), 3, 1)

    Set gptr = Q(yy, xx)
    gptr.style.backgroundcolor = "rgb(80%,50%,50%)"
    gptr.InnerText = ComMove

    Call setTimeout("ClearMarking()", 600)

    Call ReverseEnemy(ComMove, yy, xx, ManMove)

    TurnToComputer = True

End Function


Private Function ListingHands(fside, eside, tI, tC)
    Dim idx, cnt, tL

    tL = -1

    For idx = 0 to 63

        If R(idx).InnerText = BLANK Then

           cnt = CountEnemy(R(idx).id, fside, eside)

           If cnt > 0 Then

              tL = tL + 1
              ReDim Preserve tI(tL), tC(tL)

              tI(tL) = R(idx).id
              tC(tL) = cnt

            End If
        End If
    Next

    ListingHands = tL

End Function


Private Sub CopyTable(tC1, tC2, tL)
    Dim idx

    ReDim tC2(tL)

    For idx = 0 to tL

        tC2(idx) = tC1(idx)
    Next

End Sub


Private Sub ClearMarking()

    gptr.style.backgroundcolor = ""

    If Right(mouth.InnerText, 9) = "あなたの手番です。" Then

    End If

End Sub


Function EvaluateMax(tI, tC, tL)
    Dim idx, py, px, any

    For idx = 0 to tL

        py = Mid(tI(idx), 2, 1)
        px = Mid(tI(idx), 3, 1)

        If cp.RealCorner(py, px) Then

           tC(idx) = tC(idx) + BEST

        Else

           If CornerPriority(py, px) Then

              any = OtherPriority(py, px, tC(idx))

              If tC(idx) <> any Then

                 tC(idx) = any

              End If

           Else

              tC(idx) = BAD

           End If
       End If

    Next

    EvaluateMax = GetMaxIndex(tC, tL)

End Function


Private Function GetMaxIndex(tC, tL)
    Dim idx, retidx, maxcnt, Lst(), Lsts

    maxcnt = BAD - 1

    For idx = 0 to tL

        If tC(idx) > maxcnt Then

           maxcnt = tC(idx)
           retidx = idx

        End If
    Next

    Lsts = -1

    For idx = 0 to tL

        If maxcnt = tC(idx) Then

           Lsts = Lsts + 1
           ReDim Preserve Lst(Lsts)
           Lst(Lsts) = idx

        End If
    Next

    If Lsts > 0 Then

       idx = Int(Rnd * (Lsts + 1))
       retidx = Lst(idx)

    End If

    GetMaxIndex =retidx

End Function


Private Function CornerPriority(ay, ax)
    Dim pos

    If cp.CornerTL(ay, ax) Then

       pos = 0

    ElseIf cp.CornerBL(ay, ax) Then

       pos = 1

    ElseIf cp.CornerTR(ay, ax) Then

       pos = 2

    ElseIf cp.CornerBR(ay, ax) Then

       pos = 3

    Else

       CornerPriority = True
       Exit Function

    End If

    CornerPriority = cp.AroundCorner(ay, ax, pos)

End Function


Private Function OtherPriority(ay, ax, NowCnt)
    Dim ret

    If (ay = 0) Or (ay = 7) Then

       ret = OtherEvaluation(0, ay, ax, NowCnt)

    ElseIf (ax = 0) Or (ax = 7) Then

       ret = OtherEvaluation(1, ay, ax, NowCnt)

    ElseIf ComSide(0, 0) Or ComSide(7, 7) Then

       If cp.DiagonalTLBR(ay, ax) Then

          ret = OtherEvaluation(2, ay, ax, NowCnt)

       Else

          ret = NowCnt

       End If

    ElseIf ComSide(7, 0) Or ComSide(0, 7) Then

       If cp.DiagonalBLTR(ay, ax) Then

          ret = OtherEvaluation(3, ay, ax, NowCnt)

       Else

          ret = NowCnt

       End If

    Else

       ret = NowCnt

    End If

    OtherPriority = ret

End Function


Private Function ComSide(ay, ax)

    If Q(ay, ax).InnerText = ComMove Then
       ComSide = True
    Else
       ComSide = False
    End If

End Function


Class SideStatus
    Public bfg, tfg, gfg
    Private py, px, swch, mSideCorner

    Private Sub Class_Initialize
       bfg = False
       tfg = False
       gfg = False
    End Sub

    Public Sub PositionSet(sw, ay, ax)
       swch = sw
       py = ay
       px = ax
    End Sub

    Public Sub Checking(sdt, edt, vect)
       Dim idx, it

       If swch = 2 Then py = sdt
       If swch = 3 Then py = 7 - sdt

       For idx = sdt to edt step vect

           If swch = 1 Then

              it = Q(idx, px).InnerText
           Else

              it = Q(py, idx).InnerText
           End If

           If it = BLANK Then

              bfg = True
              Exit For

           End If

           If it = ManMove Then

              tfg = True

           Else

              If idx = edt Then gfg = True

              If tfg Then tfg = False

           End If

           If swch = 2 Then py = py + vect
           If swch = 3 Then py = py - vect

       Next

    End Sub

    Public Property Get AddBonus()

       If gfg Then
          AddBonus = BONUS
       Else
          AddBonus = 0
       End If

    End Property

End Class


Private Function OtherEvaluation(sw, ay, ax, Ncnt)
    Dim o1, o2

    Set o1 = New SideStatus
    Set o2 = New SideStatus

    Call o1.PositionSet(sw, ay, ax)
    Call o2.PositionSet(sw, ay, ax)

    If sw = 1 Then

       Call o1.Checking(ay+1, 7, +1)
       Call o2.Checking(ay-1, 0, -1)

    Else

       Call o1.Checking(ax+1, 7, +1)
       Call o2.Checking(ax-1, 0, -1)

    End If

    If OtherJudgement(o1, o2) Then

       OtherEvaluation = GOOD + Ncnt + o1.AddBonus + o2.AddBonus
    Else

       OtherEvaluation = BAD
    End If

    Set o1 = Nothing
    Set o2 = Nothing

End Function


Private Function OtherJudgement(o1, o2)
    Dim rfg

    If o1.bfg And o2.bfg Then

       If Not o1.tfg And Not o2.tfg Then

          rfg = True
       Else

          rfg = False
       End If

    ElseIf o1.bfg Or o2.bfg Then

       If (Not o2.bfg And o2.tfg) Or (Not o1.bfg And o1.tfg) Then

          rfg = False
       Else

          rfg = True
       End If

    Else

       rfg = True

    End If

    OtherJudgement = rfg

End Function


Class CornerProcessingList
    Private cny, cnx
    Private scy, scx
    Private cny0, cnx0
    Private cny1, cnx1, cny2, cnx2, cny3, cnx3
    Private last
    Private dgy0, dgx0, dgy1, dgx1

    Private Sub Class_Initialize
        Dim idx

        cny = array(0, 7, 0, 7)
        cnx = array(0, 0, 7, 7)
        scy = array(1, 6, 1, 6)
        scx = array(1, 1, 6, 6)

        cny0 = array(0, 0, 1, 2)
        cnx0 = array(1, 2, 0, 0)

        last = UBound(cny0)
        ReDim cny1(last), cny2(last), cny3(last)
        ReDim cnx1(last), cnx2(last), cnx3(last)

        For idx = 0 to last

            cny1(idx) = 7 - cny0(idx)
            cnx1(idx) = cnx0(idx)
            cny2(idx) = cny0(idx)
            cnx2(idx) = 7 - cnx0(idx)
            cny3(idx) = 7 - cny0(idx)
            cnx3(idx) = 7 - cnx0(idx)
        Next    

        dgy0 = array(1, 2, 5, 6)
        dgx0 = array(1, 2, 5, 6)
        dgy1 = array(1, 2, 5, 6)
        dgx1 = array(6, 5, 2, 1)

    End Sub

    Public Function RealCorner(dy, dx)

        RealCorner = CornerCheck(dy, dx, cny, cnx)

    End Function

    Public Function CornerTL(dy, dx)

        CornerTL = CornerCheck(dy, dx, cny0, cnx0)

    End Function

    Public Function CornerBL(dy, dx)

        CornerBL = CornerCheck(dy, dx, cny1, cnx1)

    End Function

    Public Function CornerTR(dy, dx)

        CornerTR = CornerCheck(dy, dx, cny2, cnx2)

    End Function

    Public Function CornerBR(dy, dx)

        CornerBR = CornerCheck(dy, dx, cny3, cnx3)

    End Function

    Public Function DiagonalTLBR(dy, dx)

        DiagonalTLBR = CornerCheck(dy, dx, dgy0, dgx0)

    End Function

    Public Function DiagonalBLTR(dy, dx)

        DiagonalBLTR = CornerCheck(dy, dx, dgy1, dgx1)

    End Function

    Private Function CornerCheck(ay, ax, cnyy, cnxx)
        Dim rfg, idx, iy, ix

        rfg = False

        iy = CInt(ay)
        ix = CInt(ax)
        For idx = 0 to last

            If (cnyy(idx) = iy) And (cnxx(idx) = ix) Then 

               rfg = True
               Exit For
            End If
        Next

        CornerCheck = rfg

    End Function

    Public Function AroundCorner(ay, ax, Index)
        Dim rfg, what, posy, posx, alty, altx

        rfg = True
        posy = cny(Index)
        posx = cnx(Index)
        what = Q(posy, posx).InnerText

        If what = BLANK Then

           posy = scy(Index)
           posx = scx(Index)
           what = Q(posy, posx).InnerText

           If what = ManMove Then

              alty = posy + posy - ay
              altx = posx + posx - ax
              what = Q(alty, altx).InnerText

              If what = ComMove Then

                 rfg = False

              End If
           End If
        End If

        AroundCorner = rfg

    End Function

End Class


'
' Common Subroutines
'
'
Function EndChecking()
    Dim rflg, bcnt, wcnt, mes

    bcnt = CalcStones(BLACK)
    wcnt = CalcStones(WHITE)
    BStones.innerText = " " & bcnt & " 個 "
    WStones.innerText = " " & wcnt & " 個"

    If bcnt + wcnt = 64 Or (Not wb.AnyMore()) Then

       If (bcnt = wcnt) Then

          mes = "珍しく引き分けです。"

       ElseIf bcnt > wcnt Then

          mes = "黒の勝ちです。"

       Else
       
          mes = "白の勝ちです。"

       End If

       rflg = True

    Else

       If bcnt = 0 Then

          mes = "白の勝ちです。"
          rflg = True
       
       ElseIf wcnt = 0 Then

          mes = "黒の勝ちです。"
          rflg = True

       Else

          rflg = False

       End If

    End If

    If rflg Then

       fakebtn.style.display = "inline"
       mouth.InnerText = mes

    End If

    EndChecking = rflg

End Function


Function CalcStones(side)
    Dim idx, cnt

    cnt = 0

    For idx = 0 to 63

        If R(idx).InnerText = side Then

           cnt = cnt + 1

        End If
    Next

    CalcStones = cnt

End Function



Function CountEnemy(tgid, mside, yside)
    Dim cnt, yy, xx, idx, nyy, nxx, vc(7)

    yy = Mid(tgid, 2, 1)
    xx = Mid(tgid, 3, 1)

    For idx = 0 to 7

        vc(idx) = 0

        If Not OutOfRange(yy, xx, idx) Then

           nyy = yy + vy(idx)
           nxx = xx + vx(idx)

           If Q(nyy, nxx).InnerText = yside Then

              vc(idx) = FriendsExist(mside, nyy, nxx, idx)

           End If

        End If        

    Next

    cnt = 0

    For idx = 0 to 7

        cnt = cnt + vc(idx)

    Next

    CountEnemy = cnt

End Function


Function FriendsExist(mm, dy, dx, d)
    Dim y, x, ret, fr, it


    y = dy
    x = dx
    ret = 0
    fr = False

    Do 

      it = Q(y, x).InnerText

      If it = mm Then

         fr = True

      ElseIf it = BLANK then

         Exit Do

      Else

         ret = ret + 1

         If OutOfRange(y, x, d) Then

            Exit Do

         Else

            y = y + vy(d)
            x = x + vx(d)

         End If

      End If

    Loop Until it = mm


    If Not fr Then

       ret = 0

    End If

    FriendsExist = ret

End Function


Function OutOfRange(y, x, d)


    If (y = 0 And vy(d) = -1) Or (y = 7 And vy(d) = 1) Or _
       (x = 0 And vx(d) = -1) Or (x = 7 And vx(d) = 1) Then

       OutOfRange = True

    Else

       OutOfRange = False

    End If

End Function


Sub ReverseEnemy(mside, yy, xx, yside)
    Dim idx, nyy, nxx

    For idx = 0 to 7

        If Not OutOfRange(yy, xx, idx) Then

           nyy = yy + vy(idx)
           nxx = xx + vx(idx)

           If Q(nyy, nxx).InnerText = yside Then

              Call ChangeToFriends(mside, nyy, nxx, idx)

           End If

        End If        

    Next

End Sub


Sub ChangeToFriends(mm, dy, dx, d)
    Dim y, x, it, mside

    y = dy
    x = dx
    mside = False

    Do 

      it = Q(y, x).InnerText

      If it = mm Then

         mside = True

      ElseIf it = BLANK then

         Exit Do

      Else

         If OutOfRange(y, x, d) Then

            Exit Do

         Else

            y = y + vy(d)
            x = x + vx(d)

         End If

      End If

    Loop Until it = mm


    If mside Then

       Call ChangeToMySide(mm, dy, dx, d)

    End If

End Sub


Sub ChangeToMySide(mm, dy, dx, d)
    Dim y, x, it

    y = dy
    x = dx

    Do 

      it = Q(y, x).InnerText

      If it <> mm Then

         Q(y, x).InnerText = mm

         y = y + vy(d)
         x = x + vx(d)

      End If

    Loop Until it = mm

End Sub

</SCRIPT>


<BODY>

<DIV class=scaleW >a b c d e f g h</DIV>

<DIV class=banmen >

<SPAN id=P00 ></SPAN> <SPAN id=P01 ></SPAN>
<SPAN id=P02 ></SPAN> <SPAN id=P03 ></SPAN>
<SPAN id=P04 ></SPAN> <SPAN id=P05 ></SPAN>
<SPAN id=P06 ></SPAN> <SPAN id=P07 ></SPAN><BR>

<SPAN id=P10 ></SPAN> <SPAN id=P11 ></SPAN>
<SPAN id=P12 ></SPAN> <SPAN id=P13 ></SPAN>
<SPAN id=P14 ></SPAN> <SPAN id=P15 ></SPAN>
<SPAN id=P16 ></SPAN> <SPAN id=P17 ></SPAN><BR>

<SPAN id=P20 ></SPAN> <SPAN id=P21 ></SPAN>
<SPAN id=P22 ></SPAN> <SPAN id=P23 ></SPAN>
<SPAN id=P24 ></SPAN> <SPAN id=P25 ></SPAN>
<SPAN id=P26 ></SPAN> <SPAN id=P27 ></SPAN><BR>

<SPAN id=P30 ></SPAN> <SPAN id=P31 ></SPAN>
<SPAN id=P32 ></SPAN> <SPAN id=P33 ></SPAN>
<SPAN id=P34 ></SPAN> <SPAN id=P35 ></SPAN>
<SPAN id=P36 ></SPAN> <SPAN id=P37 ></SPAN><BR>

<SPAN id=P40 ></SPAN> <SPAN id=P41 ></SPAN>
<SPAN id=P42 ></SPAN> <SPAN id=P43 ></SPAN>
<SPAN id=P44 ></SPAN> <SPAN id=P45 ></SPAN>
<SPAN id=P46 ></SPAN> <SPAN id=P47 ></SPAN><BR>

<SPAN id=P50 ></SPAN> <SPAN id=P51 ></SPAN>
<SPAN id=P52 ></SPAN> <SPAN id=P53 ></SPAN>
<SPAN id=P54 ></SPAN> <SPAN id=P55 ></SPAN>
<SPAN id=P56 ></SPAN> <SPAN id=P57 ></SPAN><BR>

<SPAN id=P60 ></SPAN> <SPAN id=P61 ></SPAN>
<SPAN id=P62 ></SPAN> <SPAN id=P63 ></SPAN>
<SPAN id=P64 ></SPAN> <SPAN id=P65 ></SPAN>
<SPAN id=P66 ></SPAN> <SPAN id=P67 ></SPAN><BR>

<SPAN id=P70 ></SPAN> <SPAN id=P71 ></SPAN>
<SPAN id=P72 ></SPAN> <SPAN id=P73 ></SPAN>
<SPAN id=P74 ></SPAN> <SPAN id=P75 ></SPAN>
<SPAN id=P76 ></SPAN> <SPAN id=P77 ></SPAN>

</DIV>

<DIV Class=message >

<SPAN id=TurnB></SPAN><SPAN id=BStones></SPAN>
<SPAN id=TurnW></SPAN><SPAN id=WStones></SPAN><BR><BR>

<SPAN id=Mouth></SPAN>
<SPAN id=fakebtn OnClick="InitBan()" >最初から</SPAN>

</DIV>

<DIV class=scaleH >1<BR>2<BR>3<BR>4<BR>5<BR>6<BR>7<BR>8</DIV>


</BODY>

愛国心、そして、自主独立と、自由の精神

 私の本業は、ここ10年来、慢性的な人手不足で困難を極めていました。10年ほど前にアルバイトとして雇っていた、若い男性に「アルバイトで支給される代金が安すぎる。」という理由で辞められてから、私は一人でこの本業をやってきました。家族も親戚も助けてくれないし、誰一人手伝ってさえもくれません。
 ある日、時間が足りなくて、夕方以降にヘッドライトを頭につけて田んぼで作業をしていると、地元JA営農センターのセンター長さんに「夜に一人で作業するのは危ないからやめな。」と注意されました。それからしばらく、彼と会うたびに何度も注意されました。
 そこで、とうとう私は彼に困難な状況をわかってもらうために、このように弁明したのです。「朝は、キュウリの収穫と出荷で毎日のように忙しく、炎天下の日中は、キュウリのかん水と消毒などの管理作業で毎日のように忙しく、それらが終わった後の時間は夕方近くになってしまい、田んぼで3時間ほど作業すると、すっかりまわりは夜で真っ暗になってしまうのです。他人を雇えるほどのお金も持っていませんし、東京にいる家族も長野県にいる親戚も誰一人として手伝ってくれさえもくれないので、私は一人で全ての仕事を終わらせなくてはならないのです。」
 そもそも、脱サラして生産者の一人となった私は、JA支部という団体職員である彼とは立場が違います。JA団体職員は、生産者の仕事を請け負ったりすることを、組織の規則で禁じられています。私も彼も、そのことをお互い承知していました。結局、彼のアドバイスを私が受けつけたというレベルでここは収めておき、それ以上は干渉し合わないことになりました。
 最近世の中では、働き方改革がやけに騒がれてきて、うるさくなりました。私がセンター長に注意されたのも、それが原因だと気づき、反省をすることにしました。これまでのスケジュールを反省して、なるべく残業や徹夜をしないで一人で安全に作業ができるようにしました。すなわち、短期間で無理をするのではなくて、作業日数を十分にとって、夜遅くまで作業しないスケジュールに工夫して改めることにしました。
 幸い今年は、暴風雨による稲の倒伏がほとんどありませんでした。ひどい台風が2度も来たのですが、私が借りている所の田んぼの稲は、ほとんど倒れずによく耐えてくれました。また、稲刈り・はぜかけ・脱穀作業を行う期間が、毎日のように日照り続きで、雨によって作業が中断されることもなかったので、予定していた作業のほとんどが順調に進みました。
 それにまた、機械の修理やメンテナンスを自力で念入りにしておいて、田んぼで中古の農業機械がエンジン・ストップしたり、ヒートアップして緊急停止したりすることがないようにできました。さらに、機械が苦手としている場所や、機械が泥土にはまって動かなくなる場所には、田植え機や稲刈り機をあえて入れませんでした。その代わりに、手植えや手刈りを私自身の人力でこなしました。すると、機械がトラブルを起こしてかかってしまうムダな時間や日数(ロスタイム)を結果的に減らすことができました。かえって、例年より今年は短期間で一連の作業が終わってしまいました。もちろん、誰の助けも借りずに無事故で作業を終えることができました。
 こうした話を長々とするのは、私の自慢話にしかなりません。しかし、本当に重要なのは、そんな自慢話ではありません。私が慢性的な人手不足を誰の力も借りずに対処できた、その一人のささやかな実績が重要なのです。私がこうまでしてその本業を頑張ることには、それなりの根拠があります。そのことを、これから述べておきたいのです。
 以前、私の携帯電話には、地元の日本語カレッジ・スクールから「外国人の学生を農業のアルバイトに使ってくれないか。」という依頼がよくかかってきました。しかし、私はそのたびにお断りをしてきました。それは、なぜかと申しますと、いくつかの理由があったからです。地元で私に農業の技術を教えて面倒をみて下さったキュウリ栽培の大先生(私の師匠)の、その息子さんは長野県警の警察官です。そのため、雇った外国人の方が日本の法律に引っかかったりすると、地方公務員で警察官である、その師匠の息子さんに迷惑がかかります。
 でも、本当はそれだけではありません。私自身の信条に関わる、大事な理由がほかにもあるのです。食べること、そして、働くことや生きることに関して、日本人は、もっと自信や自覚を持って、自主的になるべきだと思うのです。近年の風潮により、私たち日本人はどうしても外国人頼みになりがちです。お隣のK国が独立国家とは思えないようなことをしでかして、それに私たち日本国民が巻き込まれてしまいそうになることがしばしば起こります。でも、私たち日本人が、本当に自主独立と自由の精神を持っていたら、そうしたトラブルに巻き込まれないのではないかと思います。そうした精神をかえってK国に規範として示せるのではないかとさえ思えます。つまり、私が外国人を雇わないのは、「愛国心、そして、自主独立と、自由の精神」のためなのです。
 少子高齢化がどうであろうと、人手不足がどうであろうと、私は、従来の愛国心が邪魔をして、外国人を労働者として雇うことができないのです。そもそも、お金の問題で日本人さえ雇えないのに、外国人が雇えるわけがありません。仮に雇えたとして、地場産・国産のものを目当てに買ってくれるお客さんが、外国人が汗を流して作っているものを買わされていると知ったら、どんなにがっかりすることでしょう。
 私は、骨を抜いた魚の切り身を買うことがいまだにできません。外国人に骨を抜いてもらった魚を食べるなんて、道義的に考えても大変失礼だと思ってしまうのです。外国人労働者の方々は、ビジネスだからと、お金が欲しいからという経済的な理由で割り切って働いているのかもしれません。よって、そのことを責めるわけにはいきません。けれども、いくらお金を払っているからとはいえ、その恩恵にあやかっている私たち日本人の側が情けなく思われます。病気だとかという理由があるのなら仕方がありませんが、そうでないのならば、例え支払うお金に謝礼金が含まれていたとしても、自他おのおのの自主独立をまずは考えるべきだと、私は思うのです。
 また、農産物直売所で、顔の見える農家さんの顔写真が貼ってあったとしましょう。実際に農産物を作っているのがもし、その農家のおじさんではなくて、その下働きの外国人だとします。この場合、本当は、その外国人の顔写真を貼るべきだと、私は思うのです。現場で働く労働者を『下働き』として低く見る風潮は、これまでも多くの日本人労働者の心を傷つけて、仕事をやめさせてきました。いずれ、そのことには終止符が打たれなければならないと思います。
 愛国心に基づいて厳しいことを言わせていただきますが、自国を愛するということは、他国やその国民を愛することでもあると思うのです。自国を愛する代わりに他国を卑しめる、古き、そして恥ずべき日本の軍国主義のそれとは全く違うと思うのです。これまでの私たち日本国民は、世界の人々も、同じ信条で同じ考え方で同じ教育を受けてきたものと考え続けてきました。私たちが彼らと共栄していくためには、そういった考え方が本当は思い上がりでしかないことに目をつぶって、その考えを押し通すしかなかったのです。しかし、世界の現実は全く違います。そのことに、私たち日本国民は早く気がついて、目を開かなくてはなりません。
 私たち日本人とは同じではない信条、考え方、教育などを支えているのは、おのおのの国民の自主独立の精神だと思います。さらに、その精神を実現するためには自由でなければなりません。よって、自由の精神を持ち合わせていなければ、本当の意味での愛国心というのは、実は育たない、中途半端なものとなってしまう恐れがあると思います。
 もちろん、ここまで私が述べたことに反論する意見も多々あるとは思います。愛国心にそこまで求めなくてもいいじゃないか、とか、国家や個人のエゴがあってもいいじゃないか、とか、ノスタルジックでもいいじゃないか、とか、昔の日本の軍国主義のほうが良かったとかいう考えも当然あるとは思います。私の考えが、そういった反論に対する批判とならないことを期待します。
 実は、私がしたいことは批判ではありません。これまでの私は、自国のオフィス内や工場内や畑の中などで、外国の人たちと直接一緒に仕事をすることが何度かありました。その経験と皮膚感覚として、これまでの日本人の働き方が彼らとは大きく違うことを痛感せずにはおれませんでした。お金のために最初は日本人に合わせているように見えていても、彼らには自主独立や自由の精神があって、結局日本人の思い通りには行かないというのが、これまでのセオリーだったと思います。果たしてそれが、日本の少子高齢化や、企業の人手不足を解決できる決め手になるのかどうかは、今はまだわかりません。それをじっと静観していくしかないと、私は思っています。

当たり前と見なすことの良し悪し

 だいぶ間が空いてしまいましたが、私の前回のブログ記事(『走れメロス』の私見)において、書き足りなかった点があったかもしれません。そこで、今回は、その補足を簡単に述べておこうと思います。
 この『走れメロス』という小説が載せられていた、当時の国語の教科書では、この作品のすぐ後に、太宰治さんの小さな顔写真と、3行くらいの簡単なプロフィールが追記されていました。そして、さらにそのすぐ後に《学習の手引き》というものが載っていて、そこにはこのようなことが記述されていました。
 「この小説の作者は、主人公を通じて人間の内面を描いている。そのことをどう考えるか。みんなで話し合ってみよう。」というふうなことが書かれていました。
 しかし、当時の中2国語の授業では、その教科書の《学習の手引き》に書かれていた通りにみんなで話し合うというようなことは一切行われませんでした。その授業を担当していた国語の先生が、「作者の太宰治は、主人公の心の内面を描くことによって、人間の弱さについて表現しています。」と述べると、私たち生徒は皆それを聞いて、この小説のテーマとする所を学びました。「そうか、この『走れメロス』という小説は、人間の心の弱さを表現した作品なのだな。」と納得し理解していました。
 ここで大切なことは、先生がそう言ったのだから、それは、どう変えようもない真実であると、中学2年の私たち生徒が皆、そのことを信じて疑わなかったことです。暗記や記憶の詰め込み主義教育が当時の主流であっただけに、そのようなことは至極当たり前のことでした。つまり、それは、小説家が、人間の内面を描くことは、それほど珍しいことではないという考えにつながっていきます。
 悪く言えば、無関心・無感動世代と批判され、良く言えば、冷徹な判断を下せる世代と見なされていました。けれども、この作者がどんな気持ちでこの作品を創作したのか、その目的とか意図したことには少しも考え至らなかった世代だったのです。仮に、そうしたことに考え至った人がいたとしても、その人は天邪鬼(あまのじゃく)と見なされてしまう、そんな憂き目を見るしかありませんでした。
 何もかもが当たり前すぎて、つまらないと感じてしまう、そういった雰囲気が、私たち同級生の間にはありました。その『走れメロス』にしても、人間の内面とか、人間の弱い心とかが描かれるのは、至極ありふれたことだと考えていたわけです。テレビでドラマを観れば、登場人物が当たり前のように自らの心の中(うち)を口にします。その視聴者である私たちは、何も推し量ることなく、そのことが当たり前であるかのように受け止めて、十分理解したつもりでいました。そのくせ、実は、何も考えておらず、ぼーっとして生きていたのです。
 でも、私個人としては、そのようなことをそれほど批判する気にはなりません。あらゆることに気を配ることは、心身共に疲れます。世の中のあらゆる物事をそれほど気にせずに毎日生活していけたら、これほど幸せなことはないのかもしれません。精神的に緊張しないそういった状態になりたいと、時々私はあこがれてしまうのです。

『走れメロス』の私見

 ”熱中症”についてもそうですが、どうも私たち現代人の多くは、解決しがたい問題を抱えて日々を生きているようです。そんなこともあって、私は、何らかの知恵を書いてみようと思い立ちました。
 先日のEテレで『100分de名著 For ティーンズ 第3回『走れメロス』』を私は視聴しました。この小説は、番組中で述べられていた通り、いろんな見方ができる小説です。だから、私が中学2年で国語の教科書で読んだ時から今日に至るまで、全く変わっていない私自身の見方は、その番組中で紹介されていた所見とはだいぶ違っていました。
 その違いがどういう理由で生じたのか、時代の流れなのか、それとも、世の中の意識の変化なのか、それ探るのは、それはそれで興味の尽きぬ題材だと思います。しかし、今回の私は、そのことに深掘りをいたしません。ただ、私が、太宰治さんの著作『走れメロス』を読んで感じ取ったことを、文字にしてみたいだけなのです。
 まず、この小説の主人公は、メロスという人物一人であることに相違ないと思います。何となれば、メロスという一人の男を主人公にして、全て彼の視点から描かれた私小説であるとさえ言えます。つまり、作者である太宰治さんの分身となって、このメロスという主人公が作者の考えていることを代弁している、とこの小説の内容は考えられました。
 いきなり結論を申しますが、この小説の一番のテーマは、勇者メロスの正義でもなく、その勇気が邪悪な王様を改心させたことでもなく、メロスとその友人との無二の友情でもない、と私は思っていました。この小説を初めて読んだ中学2年(14歳)から今日(57歳)まで、私にとっては絶対に忘れてはならない考えがありました。
 それは、こういうことです。メロスのようにどんなに勇者であっても、すなわち、どんなに清く正しい正義の人であっても、どうしようもないことがあるということです。人間が人間として生きていく限りは、どうしても、人間としての弱さやガッカリな部分を公にさらしてしまうということなのです。そのことを小説という形で世の中に発信した意味において、作者である太宰治さんの功績は計り知れないと思いました。
 現代人は誰でも、こんなことは黙っておきたいものです。他人には知られたくない、自己の心の恥部と思われるかもしれません。しかし、作者である太宰治さんは、人間は誰しも、輝かしい希望や夢を持ってのみ生きていくものではなく、時には悲しみ汚れて、イヤな思いをして、それでも我慢をして生きていくから、本当に人間らしいのだと、述べているのです。
 この『走れメロス』という作品は、「メロスは激怒した。」で始まり、「勇者は、ひどく赤面した。」で終わっています。太宰治さんのお道化を借りて申せば、「勇者メロスが赤面したのは、公衆の面前でほとんど素っ裸だっただけではなく、ここまで読み進めてきた読者のみんなに彼の心の中が丸裸にされてしまったからなのだよ。」ということに尽きると思います。
 このような、清くて汚い人間の本質をわかっていれば、いじめを苦にする必要もないし、不幸だと言って生きることを放棄することもないのかもしれません。(けれど、本当は、誰の人生もままならないのかもしれません。当の太宰治さんは、自殺未遂や自殺をしています。)

避暑地の行為

 しばらくブログ記事を書くのを怠っていましたが、それにはワケがあります。ギネスブックに『世界一カロリーの低い果実』として認定されているキュウリの栽培に、どうしても専念しなければならなかったためです。今の私が、その実力で生計を立てるためには致し方ありませんでした。
 ギネスブックに『世界一カロリーの低い果実』として認定されているかぎり、キュウリを栽培する仕事なんて、「経済的に見て将来がない。」と誰もが思うかもしれません。それとも、経済的に裕福なお金持ちをターゲットにして、その仕事をしているのだろうと、思われているのかもしれません。でも、それらのことは皆さんの憶測にすぎません。この件に関しては、また日を改めて別のブログ記事で、真実を述べたいと思っています。
 今回のテーマは、避暑地の『恋』ではなくて避暑地の『行為』です。連日の猛暑の中で、私はテレビでこんなニュースを目にしました。日本の避暑地の一つと呼ばれる軽井沢へ行った人の話で、「日向(ひなた)の街の通りを歩ていて、ものすごく暑い。軽井沢は避暑地だと他人(ひと)から聞いていたのに、何だこの暑さは。これからの日本の国土はどうなっちゃうんだろう。」という話でした。
 確かに温度計の数値は、これまでの夏の暑さを越えてしまっていることを示している、と言えましょう。しかしながら、失礼を承知で申し上げるならば、その人が避暑地でとった『ある行為や行動』に全く非がなかったとは言えません。
 子供の頃の私は、軽井沢と同じ長野県に在(あ)る長野市松代町へ、八月の旧盆になると、何度か行きました。そこが私の母の実家で、私の母の兄夫婦が住んでいました。ある日の天気の良い午前中、南向きの玄関のすぐ前で遊んでいると、親戚のおばさんの誰かに叱られました。「そんな太陽の下で遊んでいると、日射病になりますよ。家の中へ入りなさい。日陰で遊びなさい。」と言われました。
 つまり、こういうことです。一般に、長野県は、昼夜の温度差が大きい大陸性の気候なのです。朝晩は夏でも涼しいことが多い、その一方で、日中は東京などの都会よりも陽射しが強くて、危険な暑さなのです。私が叱られたこの話は、五十年近く昔の話です。つい最近の話ではありません。
 もちろん長野県の避暑地と呼ばれるところには、高原(こうげん)特有の地形で涼しい場所があるかもしれません。ただし、よく観察してみればわかると思いますが、本当に涼しい場所は、ギラギラと輝く太陽の下ではなく、建物の陰や木陰で風通しの良い場所であることがわかります。そして、そこは、電気エネルギーを必要としない、全くお金のかからない天然のクーラーがあたかもあるかのような場所です。(ただし、そうした場所は、ハエやクモや蚊などの人間以外の生物も暑さから避難してくるので、衛生状態は悪いかもしれませんが…。)
 特に、『避暑地』という言葉は、日本人にとって語弊を招くものなのかもしれません。(例えば軽井沢に遊びに行けるほど)ある程度、経済的に豊かになっていれば、その『避暑地』のメリットのみを享受できると考えるのは、私たちの思い上がりに過ぎないのかもしれません。