(57)【要約】【課題】リバーシのよさを活かしながらコンピュータ相手でも飽きないようなゲームを提供すること。【解決手段】本発明は、リバーシ又はリバーシを変形したもののルールの全部又は一部を実施するコンピュータゲーム装置であって、盤の端や角以外のとこにも壁（それを縦または横にはさんでは取れないオブジェクト）および又は柱（それを斜めにはさんではとれないオブジェクト）が配置され、コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用することを特徴とするコンピュータゲーム装置を提供する。【選択図】図３
2007135613.tif 000002
【特許請求の範囲】
【請求項１】
リバーシ又はリバーシを変形したもののルールの全部又は一部を実施するコンピュータゲーム装置であって、盤の端や角以外のところにも壁（それを縦または横にはさんでは取れないオブジェクト）および又は柱（それを斜めにはさんではとれないオブジェクト）が配置され、コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用することを特徴とするコンピュータゲーム装置。
【請求項２】
コンピュータが相手をするモードにおいて、コンピュータが、座標のうち、一方にすぐ壁又は柱がありかつ対応する反対側には壁や柱がなく開いている方向数およびそれぞれの見通しよく開けている度合いが大きい座標（高度一方開放座標と呼ぶ）を優先してとることを特徴とする、請求項１に記載のコンピュータゲーム装置。
【請求項３】
コンピュータが、前記高度一方開放座標に隣接する座標をなるべくとらないようにすることを特徴とする、請求項１に記載のコンピュータゲーム装置。
【請求項４】
序盤でのみ、前記高度一方開放座標を優先的にとることを特徴とする、請求項１に記載のコンピュータゲーム装置。
【請求項５】
コンピュータが相手をするモードにおいて、コンピュータが、座標のうち、一方にすぐ壁又は柱がありかつ対応する反対側には壁や柱がなく開いている方向数およびそれぞれの見通しよく開けている度合いの大きい座標（高度一方開放座標と呼ぶ）に向けて同様に（一方にすぐ壁又は柱がありかつ対応する反対側には壁や柱がなく）開いている方向数およびそれぞれの高度一方開放座標を含む度合いの大きい座標（高度一方開放座標高度含有一方開放座標と呼ぶ）を優先してとることを特徴とする、請求項１に記載のコンピュータゲーム装置。
【請求項６】
コンピュータが、前記高度一方開放座標高度含有一方開放座標に隣接する座標をなるべくとらないようにすることを特徴とする、請求項１に記載のコンピュータゲーム装置。
【請求項７】
序盤でのみ、前記高度一方開放座標高度含有一方開放座標を優先的にとることを特徴とする、請求項１に記載のコンピュータゲーム装置。
【請求項８】
コンピュータが相手をするモードにおいて、現在のゲーム状態に対して過去にコンピュータの思考ルーチンが決定した手又は過去に有利に戦った対戦者が決定した手を採用するキャッシュ手段を有する、請求項１に記載のコンピュータゲーム装置。
【請求項９】
コンピュータが相手をするモードにおいて、コンピュータの思考時間の短さの要請および又は先読みの度合いに対応する可能な手順の個数が、ＣＰＵおよび又はメモリの能力に比して十分小さくなるように、初期の敵味方駒、前記壁および又は前記柱の量および又は配置が調節された、請求項１に記載のコンピュータゲーム装置。
【請求項１０】
コンピュータが相手をするモードにおいて、より上位のハイスコアにスコア自体より大きい重みを与えながら、種々の盤（盤ごとに初期の敵味方駒、前記壁および又は前記柱の量および又は配置が異なる）のハイスコアを合計して表示するハイスコア合計手段を有する、請求項１に記載のコンピュータゲーム装置。
【請求項１１】
リバーシ又はリバーシを変形したもののルールの全部又は一部を実施するコンピュータゲームプログラムであって、盤の端や角以外のところにも壁（それを縦または横にはさんでは取れないオブジェクト）および又は柱（それを斜めにはさんではとれないオブジェクト）が配置され、コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用することを特徴とするコンピュータゲームプログラム
【請求項１２】
人対人がコンピュータなしで遊べるボードゲーム又は該ボードゲームを変形したもののルールの全部又は一部を実施するコンピュータゲームプログラムであって、盤の端や角以外のところにも壁（縦または横方向に関するゲームルール既定の効果を排除するオブジェクト）および又は柱（斜め方向に関するゲームルール既定の効果を排除するオブジェクト）が配置され、コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用することを特徴とするコンピュータゲームプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、通常のリバーシ、およびその他の人対人がコンピュータなしで遊べる通常のボードゲーム、とは異なる戦略性を要求できるコンピュータゲーム装置およびプログラムに関する。
【背景技術】
【０００２】
通常のリバーシ等はいつも同じ戦略性を要求するため、特にコンピュータが相手の場合は飽きてしまうことが多かった。
【発明の開示】
【発明が解決しようとする課題】
【０００３】
解決しようとする問題点は、通常のリバーシ等のよさ（シンプルさ、駒配置のわずかの差によるどんでん返し等）を活かしながらコンピュータ相手でも飽きないようなゲームを提供することである。
【課題を解決するための手段】
【０００４】
本発明は、リバーシ又はリバーシを変形したもののルールの全部又は一部を実施するコンピュータゲーム装置であって、盤の端や角以外のところにも壁（それを縦または横にはさんでは取れないオブジェクト）および又は柱（それを斜めにはさんではとれないオブジェクト）が配置され、コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用することを特徴とするコンピュータゲーム装置を提供する。
【０００５】
本発明では、コンピュータが相手をするモードにおいて、コンピュータが、座標のうち、一方にすぐ壁又は柱がありかつ対応する反対側には壁や柱がなく開いている方向数およびそれぞれの見通しよく開けている度合いが大きい座標（高度一方開放座標と呼ぶ）を優先してとることが好ましい。
【０００６】
また、コンピュータが、前記高度一方開放座標に隣接する座標をなるべくとらないようにすることが好ましい。
【０００７】
また、序盤でのみ、前記高度一方開放座標を優先的にとることが好ましい。
【０００８】
本発明では、コンピュータが相手をするモードにおいて、コンピュータが、座標のうち、一方にすぐ壁又は柱がありかつ対応する反対側には壁や柱がなく開いている方向数およびそれぞれの見通しよく開けている度合いの大きい座標（高度一方開放座標）に向けて同様に（一方にすぐ壁又は柱がありかつ対応する反対側には壁や柱がなく）開いている方向数およびそれぞれの高度一方開放座標を含む度合いの大きい座標（高度一方開放座標高度含有一方開放座標）を優先してとることが好ましい。
【０００９】
また、コンピュータが、前記高度一方開放座標高度含有一方開放座標に隣接する座標をなるべくとらないようにすることが好ましい。
【００１０】
また、序盤でのみ、前記高度一方開放座標高度含有一方開放座標を優先的にとることが好ましい。
【００１１】
本発明は、コンピュータが相手をするモードにおいて、現在のゲーム状態に対して過去にコンピュータの思考ルーチンが決定した手又は過去に有利に戦った対戦者が決定した手を採用するキャッシュ手段を有することが有利である。
【００１２】
また、コンピュータが相手をするモードにおいて、コンピュータの思考時間の短さの要請および又は先読みの度合いに対応する可能な手順の個数が、ＣＰＵおよび又はメモリの能力に比して十分小さくなるように、初期の敵味方駒、前記壁および又は前記柱の量および又は配置が調節されていることが有利である。
【００１３】
また、コンピュータが相手をするモードにおいて、より上位のハイスコアにスコア自体より大きい重みを与えながら、種々の盤（盤ごとに初期の敵味方駒、前記壁および又は前記柱の量および又は配置が異なる）のハイスコアを合計して表示するハイスコア合計手段を有することが好ましい。
【００１４】
本発明はまた、リバーシ又はリバーシを変形したもののルールの全部又は一部を実施するコンピュータゲームプログラムであって、盤の端や角以外のところにも壁（それを縦または横にはさんでは取れないオブジェクト）および又は柱（それを斜めにはさんではとれないオブジェクト）が配置され、コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用することを特徴とするコンピュータゲームプログラムを提供する。
本発明はまた、人対人がコンピュータなしで遊べるボードゲーム又は該ボードゲームを変形したもののルールの全部又は一部を実施するコンピュータゲームプログラムであって、盤の端や角以外のところにも壁（縦または横方向に関するゲームルール既定の効果を排除するオブジェクト）および又は柱（斜め方向に関するゲームルール既定の効果を排除するオブジェクト）が配置され、コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用することを特徴とするコンピュータゲームプログラムを提供する。
【発明の効果】
【００１５】
請求項１、１１および１２の発明では、それぞれ（盤（＝ボード）ごとに）異なる戦略性を要求することができ課題を達成できる。
請求項２および５の発明では、（壁や柱がなく）ひらけているため重要でかつ（反対方向に隣接する壁や柱があり）とられにくい地点（請求項２）およびそういった地点をとりやすい地点（請求項５）をコンピュータが優先してとるのでコンピュータの手が対戦相手としてふさわしい十分強いものになる。
また、請求項３および６の発明では、利用者が簡単に高度一方開放座標や高度一方開放座標高度含有一方開放座標をとることを防ぎゲームを面白くする。
また、請求項４および７の発明により、終盤では請求項２、５、３および６のようなヒューリスティックスよりも（公知の）ＭＩＮ−ＭＡＸ法等による具体的で確実な計算（ゲームの詰め）を優先することができる。
請求項８の発明により、コンピュータの思考ルーチンの応答時間を高速化したり応答内容（コンピュータの手）を多様化したり学習により強化したりすることが可能になる。また、本発明によるゲームではリバーシの定石データベース等が利用できない局面が多いため探索の機会およびコストが多大となり、探索結果を再活用したりできるこのような仕組みが特に効果的となる。また、壁や柱により探索空間（ゲーム空間）そのものが小さくなる場合があり、この場合にはリバーシよりもパターン（駒の配置パターン）の再現率（過去のパターンに出会うヒット率）が高くなるため、少ないメモリおよびオーバーヘッドで効果的に高速化を図ることができる。
また、請求項９の発明により、たとえば携帯電話用ＪＡＶＡ（登録商標）処理系などあまり処理スピードが高くないプラットフォームに対しても、十分、高速でかつ戦いがいのある強さのコンピュータ思考ルーチンを提供することができるようになる。
さらに請求項１０の発明により、他のプレイヤーとの対立構造が生じる国盗り合戦形式のゲーム性を楽しむことが可能になる。すなわち、ある盤で他人のハイスコアを追い抜くことにより、順位に応じたハイスコアの重みも変わり、他人のハイスコア合計を減らすことが可能になり、国盗り合戦と同様の利害構造となる。
【発明を実施するための最良の形態】
【００１６】
本発明をＷｅｂシステム用ブラウザソフトウエアで遊ぶためのＣＧＩプログラムとしてサーバーコンピュータが対戦相手およびルールの適用をするようにして実現した。
【実施例１】
【００１７】
サーバープログラムの主要部分のアルゴリズムは、２つのＣ言語モジュールとして記載すると、参考資料Ａ１（（１）biwako.cおよび（２）ws.c）のとおりである。なお、これらの２つのソースコードの一部をよりわかりやすい形式（白をＷで符号化し、黒をＢで符号化した形式）に書き直す等したものを参考資料Ｂ２（JP-wakwayama1.c）および参考資料Ｂ３(wseuc_num8an.c)として添付した。また、参考資料Ｂ１は、コンピュータ相手のモードにつき国盗り合戦形式を楽しめるようにした「盤選択用＆ハイスコア合計ランキング表示用ＴＯＰページ」（図１の画面に対応）のＣＧＩ（Ｐｅｒｌ言語で記載）プログラムである。参考資料Ｂ１、Ｂ２、Ｂ３および公知のミニマックス法（探索アルゴリズム）や公知の暗号化の知識があれば、当業者は、ＵＮＩＸ（登録商標）互換ＯＳ上でｇｃｃ等によりコンパイルしたり、さらにｈｔｔｐ（Ｗｅｂ）サーバであるａｐａｃｈｅ（登録商標）のＣＧＩ用ディレクトリに配置して実行パーミッションを与えるたりすることにより、本発明を容易に実施することができる。
【００１８】
なお、Ｗｅｂシステムのハードウエアと本発明によるＣＧＩプログラム（参考資料Ａ１（１）（２）をコンパイルしたもの（または、参考資料Ｂ２およびＢ３を一緒にコンパイルしたもの）および参考資料Ｂ１に実行権限を与えたもの）の関係について簡単に述べると、Ｗｅｂシステム用ブラウザソフトウエア（ＩＮＴＥＲＮＥＴ  ＥＸＰＬＯＲＥＲ（登録商標）等）は、家庭用ＰＣのＯＳソフトウエア（ＭＩＣＲＯＳＯＦＴ  ＷＩＮＤＯＷＳ（登録商標）等）上で動作するように構成されており、ＯＳソフトウエアの提供するＴＣＰ／ＩＰ通信機能等により、インターネットを介して、サーバーハードウエア（ワークステーション等）に、より上位のプロトコル（ｈｔｔｐ）を用いて、本発明によるゲームの表示を要求する。サーバーハードウエアには上記ＵＮＩＸ（登録商標）等のサーバーＯＳ用ソフトウエアが動作しており、このサーバーＯＳ用ソフトウエアが、上記ｈｔｔｐサーバープログラム（ａｐａｃｈｅ等）と本発明によるＣＧＩプログラム（参考資料Ｂ１についてはさらにＰｅｒｌ実行環境も含む）との協働を制御して、ＣＧＩプログラムの標準出力の内容（ＨＴＴＰプロトコル部分、ＨＴＭＬ部分、その他の事前定義されたＰＣ側ＷＥＢシステム用ブラウザ実行スクリプト等）を、やはりｈｔｔｐプロトコルで、家庭用ＰＣに返すことになる。Ｗｅｂシステム用ブラウザソフトウエアは、返されたＨＴＭＬ部分やその他の上記実行スクリプト等を解釈して、指定された場所に指定された色、文字、グラフィックやコントロールを配置し、利用者にゲームの状態（壁や柱の配置、地形の状況および白黒等の配置）を表示しかつゲームを進行するためのインターフェース（次の一手選択用リンクやハイスコアプレイヤー名入力欄やハイスコア送信ボタン等）を提供する（例えば、図２では利用者（白）の次の一手選択用のリンクがいくつか表示されている）。
【００１９】
図１は、本実施形態による「盤選択用＆ハイスコア合計ランキング表示用ＴＯＰページ」の例を説明するものである。最上部の「tottori1鳥取県」で始まるリンク項目は、鳥取県の行政区画をモチーフにしたゲームを始めることができる。また対応する「隣人対戦」リンクでは、同じモチーフ（鳥取県）で人対人が対戦することができる。利用者は、同様に、さらに下の他の県等をモチーフにしたゲームを選択することができる。なお、別の実施形態では、県ではなく、物品や動物や幾何学模様や記号、さらにはより抽象的なマーケット構造などのモチーフを表現する盤のリストから選択できるようになっている。
図１の中央以下は、ハイスコア合計ランキングであり、１位はyoshiの７８２１３９０石である。これは本実施形態がモチーフとする各県等の行政区画を盤とした各ゲームでのハイスコアの合計であるが、１位は１００００倍、２位は１０００倍、３位は１００倍、４位は１０倍の重みで、ハイスコア「合計」に加算されるため、yoshiが１位である県（例えばchiba1）で他の人（例えばＫＮ）にハイスコアを抜かれると、１００００倍にして加算されていたchiba1のハイスコアが１０００倍にしてyoshiのハイスコア合計に加算されるようになるため、yoshiのハイスコア合計値としては小さくなり、その他の人（ＫＮ）が結果的にchiba1を盗りハイスコア合計を大きく伸ばすことになる。
【００２０】
図２は、本実施形態によりコンピュータが相手をするモードのゲーム状態の表示＆操作画面の例である。人対人のモードの場合には、下部のランキングは表示されない。ランキングでは、上述したように上位の者が本来のハイスコアより大きい重み（１００００倍等）を与えられている。
図２上部のＪＰは図１の「盤選択用＆ハイスコア合計ランキング表示用ＴＯＰページ」に戻るためのリンク、ＵＶは他のテーマのモチーフを集めた別の「盤選択用＆ハイスコア合計ランキング表示用ＴＯＰページ」へ移動するためのリンクである。その下に、システム応答時間、盤名、現在の白黒の駒数、次のターンの駒色等が表示され、さらにその下に、現在のゲーム状態が表示される。通常のリバーシと異なり、本実施形態では、初期ゲーム状態の駒の配置がより自由に決められている。また、本発明による壁や柱がいくつか配置されている。ここでは、その配置のため、通常のリバーシでは取れる座標（Ｘ：６、Ｙ：５）がとれない場所（青丸のない場所）になっている。これは、座標（Ｘ：６、Ｙ：５）と座標（Ｘ：５、Ｙ：５）の間に黄色の壁があるためである。この壁によって座標（Ｘ：５、Ｙ：５）の黒は守られていることになる。
また、座標（Ｘ：６、Ｙ：５）の右上の点は現実世界の湖ないし池を本発明による柱として作用させたものであり、右下の点は現実世界の行政区画においてその区切りをまたぐ大きな道がないため、壁の間に柱を加えて完全に遮断したものである。このように現実を反映させることでゲームを親しみやすくしている。
また、座標（Ｘ：１、Ｙ：２）の下の青線は現実の川を本発明による壁として作用させたものである。また、下部の大きな青いエリアは海を示しており、陸との境界線に青い壁を配置することで、現実世界を反映した表示およびゲーム性にして利用者の興味を高めている。
【００２１】
図３は、本実施形態による壁（盤内の縦、横の長方形）や柱（盤内の小さい正方形の点）の影響を説明した遊び方画面の例である。左側には、日英でのルール説明文が８か条があり、右側にはいくつかの壁と柱を有する盤の例および盤内の各オブジェクトの説明が示される。この盤の例では、壁は、行政区画の区切り線に沿って配置され、区切り線をまたぐ大きな道が現実世界にある場合には、区切り線（壁）の間に柱を配置せずに区切られたエリア間の相互の影響が少し（斜め方向のみ）残るようにし、大きな道がない場合には柱を配置して区切られたエリア間の相互の影響がないようにしている。
【００２２】
自然法則の利用は、上記送受信動作において、ノイマン型コンピュータとしてのＰＣやワークステーションが、ＯＳソフトウエアや、本発明によるＣＧＩプログラムや、その他のツールプログラム（上記ａｐａｃｈｅ、ｐｅｒｌ等）の実行に際し、物理メモリ、ＣＰＵ、バス、通信ポート等のハードウエアを利用する際に明らかに行われる。特に、上記本発明による壁や柱の配置を管理するための配列変数やコンピュータ思考ルーチンのコンテキストを管理するためのスタック変数を、記憶手段としての高速な物理メモリ（ＲＡＭ、ハードディスク）に展開して記憶および参照することにより、本発明に特有のルール（壁、柱による挟む効果の遮断）に正確に沿い、盤上配置の一貫性もあり、かつ十分高速であるゲーム進行（人間対戦モードおよびコンピュータ対戦モード）と、重複やもれのない高速な思考プロセス（コンピュータ対戦モード）と、を可能にする。
【００２３】
以降では、本発明の各機能と参考資料Ｂ中のソースコードとの対応あるいは機能の実現方法について述べる。
【００２４】
盤の端や角以外のところにも壁（それを縦または横にはさんでは取れないオブジェクト）および又は柱（それを斜めにはさんではとれないオブジェクト）を配置しているのは、参考資料Ｂ２の“char board[21*21]=”以降であり、例えば“＋”は柱を、“｜”は縦の壁を、“−”は横の壁を、“Ｃ”は海、湖や川としての壁や柱を、“Ｇ”は山や行政区画としての壁や柱を示している。
コンピュータがゲームの進行にあたり、壁および又は柱に関する前記ルールを適用する部分は、参考資料Ｂ３の０２１２行目のpos_check等であり、上記“＋”等の存在を意識して盤オブジェクトを走査している。
【００２５】
コンピュータが、座標のうち、一方にすぐ壁又は柱がありかつ対応する反対側には壁や柱がなく開いている方向数およびそれぞれの見通しよく開けている度合いが大きい座標（高度一方開放座標と呼ぶ）を優先してとるようにしているのは、参考資料Ｂ３の００８８行目のvalue_init関数等である。この関数は高度一方開放座標の重み(valxy)が他の座標の重み(valxy)より重くなるようにし、pos_checkや思考ルーチンrecursive_all_pos_check（０９７９行目〜）でその重みの合計が多くなる手をコンピュータが選ぶようにすることにより、この機能を実現する。
【００２６】
コンピュータが、前記高度一方開放座標に隣接する座標をなるべくとらないようにすることも、value_init関数の０１６４行目から０１８６行目で行っている。すなわち、高度一方開放座標に隣接する座標はマイナスの重みなどとなり、（上記recursive_all_pos_check関数等で）重みの合計が多くなる手をコンピュータが選ぶ際に選択肢からはずされる。
【００２７】
序盤でのみ、前記高度一方開放座標を優先的にとるためには、参考資料Ｂ３のソースコードに、残り手数が所定の閾値（例えば８）以下になったとき等に重みvalxyをすべて１に固定するルーチンを、たとえば、value_initに条件実行文として加えればよい。これにより、すべての座標が平等な重みをもつことになり、客観的な勝利条件（駒数が多いほうが勝ち）を正確に反映したミニマックス判断等が可能になる。
【００２８】
コンピュータが、高度一方開放座標高度含有一方開放座標の重みvalxyを重くしてそれらを優先してとるための前処理は、参考資料Ｂ３内のvalue_initの０１３６行目から０１５６行目までで行っている。実際に優先してとる後処理は、高度一方開放座標と同様にpos_checkおよびrecursive_all_pos_checkが行う。
【００２９】
また、コンピュータが、前記高度一方開放座標高度含有一方開放座標に隣接する座標をなるべくとらないようにすることは、高度一方開放座標（多くの場合は高度一方開放座標高度含有一方開放座標と重なる）の場合と同様にvalue_init関数の０１６４行目から０１８６行目で行っている。
【００３０】
また、序盤でのみ、前記高度一方開放座標高度含有一方開放座標を優先的にとる処理も、上記高度一方開放座標の場合と同様に行うことができる。
【００３１】
現在のゲーム状態に対して過去にコンピュータの思考ルーチンが決定した手又は過去に有利に戦った対戦者が決定した手を採用するキャッシュ手段は、すべてのサーバープログラムの動作を図示しないデータベース等に残すことにより実現する。参考資料Ｂ３の１５６４行目の後に、now_status、黒およびＭＡＰ＿ＬＯＯＰをキーとしてmaxi、maxjを連想できるデータベース内データ構造（テーブル）への登録処理を挿入する。また、同じ１５６４行目を、now_status、黒およびＭＡＰ＿ＬＯＯＰがそのデータベース内データ構造（テーブル）に登録されていないときだけrecursive_all_pos_checkを実行して新たなmaxiおよびmaxjを求めるように書き換える。有利に戦った手の場合ログ統計等も参照して決定する。
【００３２】
コンピュータが相手をするモードにおいて、コンピュータの思考時間の短さの要請および又は先読みの度合いに対応する可能な手順の個数が、ＣＰＵおよび又はメモリの能力に比して十分小さくなるように、初期の敵味方駒、前記壁および又は前記柱の量および又は配置を調節することは、経験等に基づいて人手でおこなうこともできるが、プラットフォームのＣＰＵパフォーマンス等を随時検出して、設計した盤および初期駒配置についてのゲーム空間の広さに関する所定の測定値（たとえば壁や柱の少なさ）と比較して、適合する盤および初期駒配置を自動的に選択して提供するようにすることも明らかに可能である。
【００３３】
コンピュータが相手をするモードにおいて、より上位のハイスコアにスコア自体より大きい重みを与えながら、種々の盤（盤ごとに初期の敵味方駒、前記壁および又は前記柱の量および又は配置が異なる）のハイスコアを合計して表示するハイスコア合計手段は、参考資料Ｂ１のＣＧＩプログラム（Ｐｅｒｌ言語）の後半と、参考資料Ｂ３のソースコードの０８３５行目から０８８５行目までとが協働して実現している。
【００３４】
本明細書では、Ｗｅｂシステム用ブラウザソフトウエアとＣＧＩプログラムとによるクライアントサーバー型通信で本発明のコンピュータゲーム装置を実現する例について、以上説明してきたが、本発明の範囲は、この例に限られず、特許請求の範囲によってのみ定められる。
【００３５】
例えば、本発明の開示により、ＣＧＩプログラムとして実施する代わりに、明らかに、サーブレットプログラムとしてＪＡＶＡ言語その他のプラットフォームに移植する等して、実施することもできる。また、本発明の範囲内で、スタンドアロン型でも実施することができ、ソースコードとして示したサーバー用ＣＧＩプログラムの機能を、家庭用ＰＣ、ゲーム専用機、あるいは携帯電話等のソフトウエア（家庭用ＰＣのネーティブコード、ＪＡＶＡアプレット、その他の中間言語やスクリプト）内に含めるように構成し、他のサーバーとの送受信無しで実施することもできる。
また、例えば、壁や柱を太く大きく表示したり、柱を見やすく十字に表示したりすること等もできる。
また、例えば、リバーシの変形として盤内の座標をレンガ状に隣接させたり、蜂の巣状に隣接させたゲームにも適用することができ、この場合は、斜めのはさみ効果を遮断するものとして定義される柱は、板状に表示することができる。
また、将棋およびそれに類するルールを有するボードゲーム、囲碁およびそれに類するルールを有するボードゲーム、はさみ将棋およびそれに類するルール（全部飛車の動きではなく各駒固有の動きをしたり、王がとられたら終わりとしたりするルール）を有するボードゲーム、Ｎ目並べ（Ｎ＞２）およびそれに類するルールを有するボードゲーム等においても、壁および柱を意識したコンピュータの動作をリバーシの場合と同様に実現することにより（リバーシのルールと全く関係がないゲームの場合も含めて）明らかに戦略性を変更することができる。
将棋などについては、桂馬しか飛び越えられない又はどの駒も跨げない又は接しない駒が跨げないオブジェクトとしての壁および又は柱を、やはり本発明と同様に地形のルールや表示も実施しながら、城、砦または城壁等として設置したりできる。ただし、コンピュータ相手の場合の請求項２以降のヒューリスティックスは将棋に併せて変更が必要となる。基本は、味方駒の種類や配置（持ち駒も含む）も加味した勢力の有利度（特に序盤で重視）や王駒の危険度（特に終盤で重視、なお、敵味方いずれかの王駒の危険度が所定閾値を超えた場合を終盤と定義したり、駒の勢力差が所定閾値を超えた場合を終盤と定義したり、それらを組み合わせたりできる）に応じたゲーム状態の総合評価（本発明のリバーシの場合では、序盤は味方valxyの合計（と敵valxyの合計の差）にあたる値、終盤は味方の駒数（と敵の駒数の差）にあたる値）が高まるような手をミニマックス法等により決定することになる。
囲碁などについては、盤の隅角（周囲）以外にも出現した壁等と併せた囲みにより囲んでとるというルールを、コンピュータを用いて当業者に自明なアルゴリズムで、本発明と同様のアイディア（現実の地形の反映等）と構成で実施できる。コンピュータ相手の場合の総合評価としては、将棋同様に囲碁に関する総合評価方式（盤上の陣地の量の差、いずれかを敵を囲んでとるまで（あるいは囲んでとることについてのダブルリーチまでの）工数およびとれる数の差等）を壁等を意識したものに変形して用いることができる。
はさみ将棋等の場合では、壁や柱をまたいでは移動できないようにしたり、壁や柱と敵駒により移動できなくなった駒はとられるというルールをコンピュータが（自然法則を利用して（これは、全部のゲームで同じ））適用することができる。コンピュータが相手をする場合の基本はやはりミニマックス法でよいが、その際のゲーム状態の総合評価方式としては、上記将棋と囲碁の評価方式を組み合わせたものとすることができる。ただし、王駒をとられても終了しない場合には、王駒の危険度は考慮しない。
Ｎ目並べ（５目ならべ等）については、壁や柱をはさんでＮ目に並べても勝ちではないというルールを、本発明と同様にコンピュータが適用することができる。コンピュータが相手をする場合の基本はやはりミニマックス法でよいが、その際のゲーム状態の総合評価方式としては敵のダブルリーチ構築工数−味方のダブルリーチ構築工数等とすることができる。
どのゲーム種類の場合も戦略性が盤ごとに変わるため飽きにくく、身近な地形などの表示により「○○地域重視戦略」などと戦略に名前をつけて利用者の間で共有して楽しんだり研究したりしやすいものとなっている。また、壁や柱によって生じるルールの適用のコスト、（壁や柱によって大きくなる場合もある）次に打てる手の選択肢の抽出の人的労力、盤によってかわる地形等の表示コストが、自然法則を利用した高速で安定したコンピュータの利用により大幅に削減され有利になる。また、壁や柱をつくるルール変更は他のルール変更（駒の配置や効力や属性が時間等によって勝手にかわる等）に比べて、各ゲームについての公知・公用のコンピュータ実施手法（例えば公知のゲーム状態評価方式、状態表示方式、手有効性判断方式）の多くを簡単に（場合によってはそのまま）とりいれることができ、本明細書によるリバーシの場合についての詳細な説明、上記のような各ゲームについての簡明なルール変更の説明および各ルール変更に対応したゲーム状態評価方式の新しい指針の説明があれば、当業者はリバーシ以外のそのようなゲームについても容易に壁や柱のあるものを実現できる。
【００３６】
以下に上記参考資料としてのソースコードを示す。
＜参考資料Ａ１（１）＞
//以下、盤（＝面、ラウンド、モチーフ）ごとのプログラム(biwako.c)
char board[]=
// JP-biwako1
"+---------------+"
"|CCCC           |"
"|CCCC           |"
"|               |"
"|       CCCCC   |"
"|       CCCCC   |"
"|       CCCCC   |"
"|       CCCCC   |"
"|     CCCCCCC   |"
"|     CCCCC     |"
"|     CCCCC     |"
"|     CCC       |"
"|     CCC       |"
"|               |"
"|               |"
"|               |"
"+---------------+"
;
char init[]=
// JP-biwako1
"NNNNNNNN"
"NNNNNNNN"
"NNWRNNNN"
"NNRWNNNN"
"NNNNNNNN"
"NNNNRWNN"
"NNNNWRNN"
"NNNNNNNN"
;
＜参考資料Ａ１（２）＞
//以下メインプログラム( ws.c)
char CGINAME[ 1024 ];
extern char init[];
extern char board[];
#define IS_STACK_EST (0)
#define COLOR_GREEN "#33ff33"
#define MUGENM       (-65535)
#define MUGENP       (+65535)
#define GAME_SIZE_X  (8)
#define GAME_SIZE_Y  (8)
#define BOARD_SIZE_X (GAME_SIZE_X+GAME_SIZE_X+1)
#define BOARD_SIZE_Y (GAME_SIZE_Y+GAME_SIZE_Y+1)
//#define IMG "http://wallstreets.ws/icons/PIC_0041.JPG";
#define PIMGM "http://wallstreets.ws/icons/PIC_0043M.JPG";
#define PIMG "http://wallstreets.ws/icons/PIC_0043.JPG";
//char board[ 21*21 ] = {
/*
int valpr[ 9 ][ 9 ] = { 0 }; 
int valxy[ 9 ][ 9 ] = { 0 };
int dirnm[ 9 ][ 9 ] = { 0 };
char blockget( int sizex, int sizey, int x, int y, char *b)
{
return *(b + y*sizex + x);
}
int valdir( int basex, int basey, int dirx, int diry, char *b)
{
int point = 0;
int sizex = 8;
int sizey = 8; 
while( blockget( sizex*2+1, sizey*2+1, (basex-1)*2+1-dirx,  (basey-1)*2+1-diry, b) == ' '){ 
point++;
basex -= dirx;
basey -= diry;
}
return point;
}
int valdirxy( int basex, int basey, int dirx, int diry, char *b)
{
int point = 0;
int sizex = 8;
int sizey = 8; 
while( blockget( sizex*2+1, sizey*2+1, (basex-1)*2+1-dirx,  (basey-1)*2+1-diry, b) == ' '){ 
point += valpr[ basex ][ basey ];
basex -= dirx;
basey -= diry;
}
return point;
}
int valdirnb( int basex, int basey, int dirx, int diry, char *b)
{
return -valpr[ basex+dirx ][ basey+diry ]/dirnm[ basex+dirx ][ basey+diry ];
}
void value_init( char *b)
{
int sizex = 8;
int sizey = 8; 
int cx, cy;
for( cx = 1; cx ＜= 8; cx++)
for( cy = 1; cy ＜= 8; cy++)
dirnm[ cx ][ cy ] =
((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) == ' ') ? 
1:0)
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) == ' ') ? 
1:0)
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) == ' ') ?
1:0)
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) == ' ') ?
1:0)
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) == ' ') ?
1:0)
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) == ' ') ?
1:0)
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) == ' ') ?
1:0)
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) == ' ') ?
1:0);
for( cx = 1; cx ＜= 8; cx++)
for( cy = 1; cy ＜= 8; cy++){
valpr[ cx ][ cy ] =
((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) == ' ') ? 
0:valdir(cx,cy,-1,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) == ' ') ? 
0:valdir(cx,cy,-1, 0, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) == ' ') ?
0:valdir(cx,cy,-1,+1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) == ' ') ?
0:valdir(cx,cy, 0,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) == ' ') ?
0:valdir(cx,cy, 0,+1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) == ' ') ?
0:valdir(cx,cy,+1,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) == ' ') ?
0:valdir(cx,cy,+1, 0, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) == ' ') ?
0:valdir(cx,cy,+1,+1, b))
;
}
for( cx = 1; cx ＜= 8; cx++)
for( cy = 1; cy ＜= 8; cy++){
valxy[ cx ][ cy ] = valpr[ cx ][ cy ]
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) == ' ') ? 
0:valdirxy(cx,cy,-1,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) == ' ') ? 
0:valdirxy(cx,cy,-1, 0, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) == ' ') ?
0:valdirxy(cx,cy,-1,+1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) == ' ') ?
0:valdirxy(cx,cy, 0,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) == ' ') ?
0:valdirxy(cx,cy, 0,+1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) == ' ') ?
0:valdirxy(cx,cy,+1,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) == ' ') ?
0:valdirxy(cx,cy,+1, 0, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) == ' ') ?
0:valdirxy(cx,cy,+1,+1, b))
;
}
for( cx = 1; cx ＜= 8; cx++)
for( cy = 1; cy ＜= 8; cy++)
valpr[ cx ][ cy ] = valxy[ cx ][ cy ];
{
int min = 65535;
for( cx = 1; cx ＜= 8; cx++)
for( cy = 1; cy ＜= 8; cy++){
valxy[ cx ][ cy ] = valpr[ cx ][ cy ]
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) != ' ') ? 
0:valdirnb(cx,cy,-1,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) != ' ') ? 
0:valdirnb(cx,cy,-1, 0, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) != ' ') ?
0:valdirnb(cx,cy,-1,+1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) != ' ') ?
0:valdirnb(cx,cy, 0,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) != ' ') ?
0:valdirnb(cx,cy, 0,+1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) != ' ') ?
0:valdirnb(cx,cy,+1,-1, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) != ' ') ?
0:valdirnb(cx,cy,+1, 0, b))
+((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) != ' ') ?
0:valdirnb(cx,cy,+1,+1, b))
;
if(min ＞ valxy[ cx ][ cy ])
min = valxy[ cx ][ cy ];
}
if(0 && min ＜ 1){
for( cx = 1; cx ＜= 8; cx++)
for( cy = 1; cy ＜= 8; cy++){
valxy[ cx ][ cy ] += (-min+1);
}
}
}
}
void set( char c, int sizex, int sizey, int x, int y, char *s)
{
*(s + (y-1)*sizex + (x-1)) = c;
}
char get( int sizex, int sizey, int x, int y, char *s)
{
return *(s + (y-1)*sizex + (x-1));
}
int pos_check( 
int  is_turn, 
char turn, 
int  sizex, 
int  sizey, 
int  x, 
int  y, 
char *s
)
{
int cx, cy;
int exist_count = 0;
char tonari = (turn == 'W') ? 'R':'W';
int tonari_count;
int tonari_count_val;
//左
for( tonari_count = 0, cx = x-1, cy = y; ; cx--){
if(cx == 0 || 
blockget( sizex*2+1, sizey*2+1, cx*2, (cy-1)*2+1, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x-1, cy = y; tonari_count-- ＞ 0; cx--){
set( turn, sizex, sizey, cx, cy, s);
}
}
//右  
for( tonari_count = 0, cx = x+1, cy = y; ; cx++){
if(cx ＞ sizex ||
blockget( sizex*2+1, sizey*2+1, (cx-1)*2, (cy-1)*2+1, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x+1, cy = y; tonari_count-- ＞ 0; cx++){
set( turn, sizex, sizey, cx, cy, s);
}
}
//上
for( tonari_count = 0, cx = x, cy = y-1; ; cy--){
if(cy == 0 ||
blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, cy*2, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x, cy = y-1; tonari_count--; cy--){
set( turn, sizex, sizey, cx, cy, s);
}
}
//下
for( tonari_count = 0, cx = x, cy = y+1; ; cy++){
if(cy ＞ sizey ||
blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x, cy = y+1; tonari_count--; cy++){
set( turn, sizex, sizey, cx, cy, s);
}
}
//左上
for( tonari_count = 0, cx = x-1, cy = y-1; ; cx--, cy--){
if(cx == 0 || cy == 0 ||
blockget( sizex*2+1, sizey*2+1, cx*2, cy*2, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x-1, cy = y-1; tonari_count--; cx--, cy--){
set( turn, sizex, sizey, cx, cy, s);
}
}
//左下
for( tonari_count = 0, cx = x-1, cy = y+1; ; cx--, cy++){
if(cx == 0 || cy ＞ sizey||
blockget( sizex*2+1, sizey*2+1, cx*2, (cy-1)*2, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x-1, cy = y+1; tonari_count--; cx--, cy++){
set( turn, sizex, sizey, cx, cy, s);
}
}
//右上
for( tonari_count = 0, cx = x+1, cy = y-1; ; cx++, cy--){
if(cx ＞ sizex || cy == 0 ||
blockget( sizex*2+1, sizey*2+1, (cx-1)*2, cy*2, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x+1, cy = y-1; tonari_count--; cx++, cy--){
set( turn, sizex, sizey, cx, cy, s);
}
}
//右下
for( tonari_count = 0, cx = x+1, cy = y+1; ; cx++, cy++){
if(cx ＞ sizex || cy ＞ sizey ||
blockget( sizex*2+1, sizey*2+1, (cx-1)*2, (cy-1)*2, board) != ' '){
tonari_count = 0;
tonari_count_val = 0;
break;
}else{
char nc = get( sizex, sizey, cx, cy, s);
if(nc == tonari){
tonari_count++;
tonari_count_val+=valxy[ cx ][ cy ];
}else if(nc == turn && tonari_count ＞ 0){
//exist_count += tonari_count_val;
exist_count += tonari_count;
break;
}else{
tonari_count = 0;
tonari_count_val = 0;
break;
}
}
}
if(is_turn && tonari_count){
for( cx = x+1, cy = y+1; tonari_count--; cx++, cy++){
set( turn, sizex, sizey, cx, cy, s);
}
}
if(is_turn && exist_count)
set( turn, sizex, sizey, x, y, s);
return exist_count;
}
int disp_now( char nextturn, int xsize, int ysize, char *status, int isblue, int bx, int by, char *orgstatus)
{
}
int i[ 64+1 ],j[ 64+1 ];
int max[ 64+1 ];
char status[ 64+1 ][ 64+1 ];
char turn[ 64+1 ];
int check[ 64+1 ];
char now_status[ 1024 ];
void disp_head(int i, char *s)
{
}
int whitenum( char *status)
{
int ret = 0;
while( *status){
if(*status == 'R')
ret++;
status++;
}
return ret;
}
char *mycrypt( char *msg)
{
static char ret[ 64+1 ];
return ret;
}
void disp_tail(char nextturn, char *msg)
{
}
int all_pos_check( char nextturn, int *maxi, int *maxj, char *now_status) 
{
int i,j;
int max = 0;
*maxi = 0;
*maxj = 0;
for( i = 1; i ＜= 8; i++){
for( j = 1; j ＜=8; j++){
if(get( 8, 8, i, j, now_status) == 'N'){
int now = pos_check( 0, nextturn, 8, 8, i, j, now_status);
if(now ＞ max){
*maxi = i;
*maxj = j;
max = now;
}
}
}
}
return max;
}
void p( char *str)
{
printf( "%s\n", str);
} 
//int all_1_all_nM1_max_min_max;    //最終決定値
//int now_1_all_nM1_max_min;        //一手目ごとに   65535に初期化される
//int now_1_now_nM1_max;            //N-1手目ごとに -65535に初期化される
int minmax[ 64+1 ];               
//minmax[ 0 ] max_sp = 3 にとっての all_1_all_nM1_max_min_max;    //最終決定値に対応
//minmax[ 1 ] max_sp = 3 にとっての now_1_all_nM1_max_min;        //一手目ごとに   65535に初期化される
//minmax[ 2 ] max_sp = 3 にとっての now_1_now_nM1_max;            //N-1手目ごとに -65535に初期化される
//minmax[ 3 ] max_sp = 3 にとっての sum                           //
int max_sp;
int now_max_loop;
#ifdef DEBUG
void disp_stack( int x, int y, char *msg)
{
int n;
printf( "＜TR＞\n");
for( n = 1; n ＜= max_sp /*&& max[ n ]*/; n++){
printf( "＜TD valign=up＞\n");
printf( "chk[ %d ] : %d / (%d,%d) = %d-%d＜BR＞\n", n, check[ n ], i[ n ], j[ n ], x, y);
//printf( "status[ %d ] = ＜BR＞\n", i);
{
int m;
for(m = 0; m ＜ 64; m++){
switch( status[ n ][ m ]){
case 'N': printf("×");break;
case 'W': printf("白丸");break;
case 'R':printf("黒丸");break;
}
if(m % 8 == 7)
printf("＜BR＞\n");
}
}
printf("turn            = %c＜BR＞\n", turn[ n ]);
/*
printf("all_1_all_nM1_max_min_max %d＜BR＞\n", all_1_all_nM1_max_min_max);    //最終決定値
printf("now_1_all_nM1_max_min     %d＜BR＞\n", now_1_all_nM1_max_min);        //一手目ごとに   65535に初期化される
printf("now_1_now_nM1_max         %d＜BR＞\n", now_1_now_nM1_max);            //N-1手目ごとに -65535に初期化される
*/
{
int m;
for(m = 0; m ＜= max_sp; m++)
printf( "%d ", minmax[ m ]);
printf( "＜BR＞\n");
}
if(msg){
printf( "%d : %s＜BR＞\n", now_max_loop, msg);
}
printf( "＜/TD＞\n");
}
printf( "＜/TR＞\n");
}
#else
void disp_stack( int x, int y, char *msg)
{
;
}
#endif
/*---------------------------------------------------------------------------------
関数名  recursive_all_pos_check
機能    最も有望な手を返す
引数    nextturn               有望な手を探索する側('W'/'R')
*maxi                  有望な手のX座標
*maxj                  有望な手のY座標
now_status             探索の対象となるゲーム状態 
max_loop               最大の探索ループ数
---------------------------------------------------------------------------------*/
int recursive_all_pos_check( 
char  nextturn, 
int   *maxi, 
int   *maxj, 
char  *now_status,
unsigned long  max_loop
) 
{
const int level = LEVEL;
int first_get = 0;
int m,n;
*maxi = *maxj = 0;
//all_1_all_nM1_max_min_max = -65535;             //最終決定値
minmax[ 0 ] = MUGENM;
// スタックの初期化
max_sp = 0;
turn[ 0 ] = 'N';
strcpy( status[ 0 ], now_status);
i[ 0 ] = j[ 0 ] = 0;
max[ 0 ] = 0;
#ifdef DEBUG
printf( "＜TABLE border bgcolor=white＞\n");
#endif
// 次の一手
++max_sp;
turn[ max_sp ] = nextturn;
i[ max_sp ] = j[ max_sp ] = 1;
max[ max_sp ] = 0;
do{
if(--max_loop == 0){
disp_stack( *maxi, *maxj, "LOOPOVER");
break;
}
now_max_loop = max_loop;
if( max_sp % 2 == 1 && max_sp ＜ level){
// 1 or 3 のとき
minmax[ max_sp ] = MUGENP;
}
if( max_sp % 2 == 0 && max_sp ＜ level){
// 2 or 4 のとき(0はありえないから)
minmax[ max_sp ] = MUGENM;
} 
strcpy( status[ max_sp ], status[ max_sp-1 ]);
if( get( 8, 8, i[ max_sp ], j[ max_sp ], status[ max_sp ]) == 'N'
&&  (check[ max_sp ] 
=  pos_check( 1, turn[ max_sp ], 8, 8, i[ max_sp ], j[ max_sp ], status[ max_sp ])) ＞ 0){
// 注目した座標(i[max_sp],j[max_sp])に石がなくかつとれるので置ける場合
// 現在のmax_sp-1のゲーム状態に対して先の手max_spが存在することをマークする
max[ max_sp ] = check[ max_sp ];
if(max_sp ＜ level){
// まだ先を読む必要がある場合,
//disp_stack( *maxi, *maxj, "THINKING");
// 置いてみた後のstatus[ max_sp ]をスタックにつむ
++max_sp;
turn[ max_sp ] = (turn[ max_sp-1 ] == 'W') ? 'R':'W';
i[ max_sp ] = j[ max_sp ] = 1;
max[ max_sp ] = 0;
}else{
// 最深読みレベルに達していた場合
// 最深読みレベルの評価を計算する
int sum = 0;
int k;
if(IS_STACK_EST)
{
for( k = 1; k ＜= max_sp; k++)
sum += 
(turn[ k ] == nextturn) ? 
+(check[ k ]+valxy[i[ k ]][j[ k ]]) :  -(check[ k ]+valxy[i[ k ]][j[ k ]]);
//+(check[ k ]) :  -(check[ k ]);
}else{
int x,y;
int sumw = 0;
int sumb = 0;
for( x = 1; x ＜= 8; x++){
for( y = 1; y ＜= 8; y++){
switch(get( 8, 8, x, y, status[ max_sp ])){
case 'N': break;
case 'W': sumw += valxy[ x ][ y ]; break;
case 'R': sumb += valxy[ x ][ y ]; break;
}
}
}
sum = (nextturn == 'W') ? (sumw-sumb):(sumb-sumw);
}
if(/* 最深レベルは奇数故 max_sp % 2 = 1 のチェックはいらない */
sum ＞ minmax[ max_sp-1 ]){
minmax[ max_sp-1 ] = sum; 
//disp_stack( *maxi, *maxj, "sum ＞ minmax[ max_sp-1 ]");
}
//disp_stack( *maxi, *maxj);
// 次の候補にポインタを移す
while( j[ max_sp ] == 8 && i[ max_sp ] == 8 && max_sp ＞ 0){
max_sp --;
if(max_sp % 2 == 0 && max_sp ＜ level){
if(minmax[ max_sp ] ＜ minmax[ max_sp-1 ]){
minmax[ max_sp-1 ] = minmax[ max_sp ];
disp_stack( *maxi, *maxj, "minmax[ max_sp ] ＜ minmax[ max_sp-1 ]");
}
}
if(max_sp % 2 == 1 && max_sp ＜ level){
if(minmax[ max_sp-1 ] ＜ minmax[ max_sp ]){
minmax[ max_sp-1 ] = minmax[ max_sp ];
disp_stack( *maxi, *maxj, "minmax[ max_sp-1 ] ＜ minmax[ max_sp ]");
if( max_sp == 1){
*maxi = i[ 1 ];
*maxj = j[ 1 ];
first_get = check[ 1 ];
}
}
}
if(max_sp == 1)
disp_stack( *maxi, *maxj, "CANDIDATE");
}
if(max_sp ＞ 0){
if(j[ max_sp ] ＜ 8){
j[ max_sp ]++;
}else if(i[ max_sp ] ＜ 8){
i[ max_sp ]++;
j[ max_sp ] = 1;
} 
}
}
}else{
// 注目した座標(i[max_sp],j[max_sp])に既に石があるか,なくても置けないときの処理
if(j[ max_sp ] ＜ 8){
j[ max_sp ]++;
}else if(i[ max_sp ] ＜ 8){
i[ max_sp ]++;
j[ max_sp ] = 1;
}else{
//その手をすべて探索したとき
disp_stack( *maxi, *maxj, "all searched");
if(max[ max_sp ] == 0){
//すべて探索した結果としておけなかったとき
char revturn = (turn[ max_sp ] == 'W') ? 'R':'W';
int m,n,rev_check = 0;
int nokori = 0, rev_nokori = 0;
disp_stack( *maxi, *maxj, "max[ max_sp ] == 0");
// 番を相手にわたせるかどうか計算
for(m = 1; m ＜= 8; m++)
for(n = 1; n ＜= 8; n++){
char c = get( 8, 8, m, n, status[ max_sp ]);
if(c == 'N')
rev_check += pos_check( 0, revturn, 8, 8, m, n, status[ max_sp ]);
else if(c == revturn)
rev_nokori ++;
else
nokori ++;
}
if(rev_check ＞ 0 && max_sp ＜ level){
// 相手の置く場所があり番をわたせるとき
// 自分のturnはスキップする
i[ max_sp ] = 8;
j[ max_sp ] = 8;
// turnを交替して探索しなおし
++max_sp;
turn[ max_sp ] = revturn;
i[ max_sp ] = 1;
j[ max_sp ] = 0;
max[ max_sp ] = 0;
disp_stack( *maxi, *maxj, "PASS");
}else{
// ゲームルール上,自分も相手もおける石がなかった場合
if( max_sp == 1){
// １手目で自分も相手もなにもできないとき
disp_stack( *maxi, *maxj, "1 te PASSPASS GAMEOVER");
;//ゲームオーバー
}else{
disp_stack(  *maxi, *maxj, "max_sp ＞ 1");
// ２手先読みでこの状態に遭遇したとき
if(max_sp == 2 && rev_nokori ＞ nokori){
// ２手先で両者とも何もできなくなりコールド勝ちになる場合
*maxi = i[ 1 ];
*maxj = j[ 1 ];
//all_1_all_nM1_max_min_max = MUGENP;//この手に決めてしまう
minmax[ 0 ] = MUGENP;
first_get = check[ 1 ];
disp_stack(  *maxi, *maxj, "COLD WIN");
}else{
// ２手先以上で両者とも何もできなくなり,負けか引き分けのとき
// 最深読みレベルの評価を計算する
int sum = 0;
int k;
if(IS_STACK_EST){
for( k = 1; k ＜= max_sp; k++)
sum += 
(turn[ k ] == nextturn) ? 
+(check[ k ]+valxy[i[ k ]][j[ k ]]) :  -(check[ k ]+valxy[i[ k ]][j[ k ]]);
//+(check[ k ]) :  -(check[ k ]);
}else{
int x,y;
int sumw = 0;
int numw = 0;
int sumb = 0;
int numb = 0;
for( x = 1; x ＜= 8; x++){
for( y = 1; y ＜= 8; y++){
switch(get( 8, 8, x, y, status[ max_sp ])){
case 'N': break;
case 'W': numw++;sumw += valxy[ x ][ y ]; break;
case 'R': numb++;sumb += valxy[ x ][ y ]; break;
}
}
}
if(numw == 0){
sumw = MUGENM;
}
if(numb == 0){
sumb = MUGENM;
}
sum = (nextturn == 'W') ? (sumw-sumb):(sumb-sumw);
}
disp_stack(  *maxi, *maxj, "LOSEorDRAW-BACKTRACK");
if(sum ＞ minmax[ max_sp-1 ]){
// max_sp == 3 or 5 , max_sp-1 == 2 or 4を想定している
minmax[ max_sp-1 ] = sum;
disp_stack(  *maxi, *maxj, "LOSEorDRAW-BACKTRACK sum ＞ minmax[ max_sp-1 ]");
}
//負けか引き分けになりそうなときの処理終了
}
disp_stack( *maxi, *maxj, "NO GAME at 2 or more");
//２手先読み以上で遭遇した場合終了
}
disp_stack( *maxi, *maxj, "NO GAME at a context");
// ゲームルール上,自分も相手もおける石がなかった場合終了
}
disp_stack( *maxi, *maxj, "NO GAME");
// すべて探索した結果としておけなかったとき終了
}
//disp_stack(  *maxi, *maxj, "NO TE");
// 次の候補にポインタを移す
while( j[ max_sp ] == 8 && i[ max_sp ] == 8 && max_sp ＞ 0){
max_sp --;
if(max_sp % 2 == 0 && max_sp ＜ level){
if(minmax[ max_sp ] ＜ minmax[ max_sp-1 ]){
minmax[ max_sp-1 ] = minmax[ max_sp ];
disp_stack( *maxi, *maxj, "minmax[ max_sp ] ＜ minmax[ max_sp-1 ]");
}
}
if(max_sp % 2 == 1 && max_sp ＜ level){
if(minmax[ max_sp-1 ] ＜ minmax[ max_sp ]){
minmax[ max_sp-1 ] = minmax[ max_sp ];
disp_stack( *maxi, *maxj, "minmax[ max_sp-1 ] ＜ minmax[ max_sp ]");
if( max_sp == 1){
*maxi = i[ 1 ];
*maxj = j[ 1 ];
first_get = check[ 1 ];
}
}
}
}
//disp_stack( *maxi, *maxj, "BACKTRACK AFTER NO-TE");
if(max_sp ＞ 0){
if(j[ max_sp ] ＜ 8){
j[ max_sp ]++;
}else if(i[ max_sp ] ＜ 8){
i[ max_sp ]++;
j[ max_sp ] = 1;
} 
}
}
}
}while( max_sp ＞ 0);
#ifdef DEBUG
printf( "＜/TABLE＞\n");
#endif
return first_get;
}
int disp_point( int is_start, int x, int y, char *now_status, char nextturn, double t)
{
}
void countup( void)
{
/*  
REMOTE_ADDR：スクリプトを提出してきたホストIPアドレス
QUERY_STRING：GETによう問い合わせにおける引数の方法URLで「？」の後ろにあるものすべて
REQUEST_METHOD：フォームの提出方法(POST or GET)
REFERER_URL：CGIを送るのに使われたページのURLクライアント変数の中身、
ユーザがサイトを訪れる直前にブラウザがいたロケーションURLを返す
CONTENT_TYPE：POSTによってフォームが提出されてくる場合  
application/x-www-form-unlecodedという値になる
CONTENT_LENGTH：POST、GETによってフォームが提出される場合、標準出力から読み込む必要のあるバイト数 
char buf[ 256 ];
char *user = getenv("REMOTE_ADDR");
int fd = open("/home/httpd/cgi-bin/ws/wscount.dat", "at");
int count = 10; 
while( flock( fd, LOCK_EX)){
if(--count = 0)
exit(1);
sleep( 100);
}
fprintf( fp, "%s\n", usr);
flock( fd, LOCK_UN);
close( fd);
//system( buf);
*/
FILE *fp;
int fd;
int count = 0;
char buf[256];
bzero(buf, 256);
// ファイルを開く
fd = open("/home/httpd/cgi-bin/ws/counter.dat", O_RDWR | O_CREAT );
// 排他ロック
flock(fd, LOCK_EX );
// 読み込み
lseek(fd, 0, SEEK_SET);
read(fd, buf, 256);
// カウンタを足す
count = atoi(buf);
count++;
sprintf(buf, "%d", count);
// 書き込み
lseek(fd, 0, SEEK_SET);
write(fd, buf, 256);
fp = fopen("/home/httpd/cgi-bin/ws/log.dat", "at");
fprintf( fp, "%s:%s\n", buf, getenv("REMOTE_ADDR"));
fclose( fp);
// ロック開放
flock(fd, LOCK_UN );
close(fd);
}
const char codetbl[] = "0123456789ABCDEF";
int urldecode(char *in, char *out)
{
int cnt = 0;
int len;
char *str = in;
if (!in || (len = strlen(in)) == 0)
return -1;
memset( out, 0, len );
while( *str ) {
if (*str != '%') {
*(out + cnt++) = *str;
} else {
if ( *(str + 1) == 0 || *(str + 2) == 0) {
break;
}
*(out + cnt++) = 16 * (strchr(codetbl, *(str + 1)) - codetbl) \
+ (strchr(codetbl, *(str + 2)) - codetbl);
str = str + 2;
}
str++;
}
return(strlen(out));
} 
int main( int argc, char *argv[])
{
int smode = 1;
int isloop = 1;
char org_status[ 1024 ];
clock_t start,end;
{
char *cp = strrchr( argv[ 0 ], '/');
strcpy(CGINAME, cp+1);
}
start = clock();
char autonext[ 1024 ] = {""};
char lastturn = 'N';
char nextturn = 'N';
int is_p2p = IS_P2P;
int  x,y;
char cfgfilepath[ 1024 ];
char given_status[ 1024 ];
char *cp = getenv("QUERY_STRING"); cp = (cp) ? strcpy( given_status, cp) : NULL; 
char *user = getenv("REMOTE_ADDR");
{
//char buf[ 256 ];
////sprintf( buf, "/home/httpd/cgi-bin/ws/wscount.pl %s", user);
//sprintf( buf, "/home/httpd/cgi-bin/ws/wscount.pl aaaaaaaaa");
//system( buf);
}
value_init( board);
//自分の色および場所を変数にいれる
if(cp == NULL || *cp == '\0' || *(cp+2)=='h'){
char buf[ 1024 ];
if(*(cp+2) =='h'){
char *sp;
char *ep;
int point = 0;
char sname[  64 ];
char scrypt[ 64+1 ];
char ncrypt[ 64+1 ];
char sstat[  64+1 ];
fgets( buf, 1024, stdin);
sp = buf+5;
ep = strchr( sp, '&');
*ep = '\0';
strcpy( sstat, sp);
strcpy( ncrypt, (const char *)mycrypt( sstat));
sp = ep+7;
ep = strchr( sp, '&');
*ep = '\0';
strcpy( scrypt, sp);
sp = ep+10;
urldecode( sp, sname);
//strcpy( sname, sp);
if(strlen(sname) ＞ 0 && strcmp( ncrypt, scrypt) == 0){
int num = whitenum( sstat);
char buf[ 256 ]; 
char filename[ 256 ];
char filenamebak[ 256 ];
sprintf( filename, "%s.rank", CGINAME); 
sprintf( filenamebak, "%s.rank.bak", CGINAME); 
unlink( filenamebak);
rename( filename, filenamebak);
FILE *fin = fopen( filenamebak, "rb");
FILE *fout = fopen( filename, "wb");
if(fin){
while( fgets( buf, 256, fin ) ){
char *cp = strchr( buf, ',');
if(cp){
*cp = '\0';
if(atoi( buf) ＜ num){
fprintf( fout, "%d,%s\n", num, sname);  
num = 0;
}
fprintf( fout, "%s,%s", buf, cp+1);
}
}
fclose( fin);
//rename( filenamebak, filename);
fclose( fout);
}
}
//strcpy( buf, "test");
}else{
buf[0] = '\0';
}
// 引数が得られなかった場合
nextturn = 'R';
x = 0;
y = 0;
disp_head(0, NULL);
strcpy( now_status, init );
disp_point( 1, 0, 0, now_status, nextturn, 0.0f);
strcpy( org_status, now_status);
disp_now( 
nextturn, 
8, 8, now_status, 1, 0, 0, org_status
);
disp_tail(nextturn, user);
exit( 0);
}
// 引数を取得する
{
static char buf[ 1024 ];
char *ep;
/*
while(*cp != '=') cp++;
strcpy( cfgfilepath, ++cp);
set_cfg( cfgfilepath);
*/
while(*cp != '=') cp++;
nextturn = *(++cp);
while(*cp != '=') cp++;
ep = strchr( cp, (int)'&');
*ep = '\0'; 
x = atoi( ++cp);
while(*cp != '=') cp++;
ep = strchr( cp, (int)'&'); 
*ep = '\0'; 
y = atoi( ++cp);
while(*cp != '=') cp++;
strcpy( now_status, ++cp);
ep = strchr( now_status, (int)'&');
if( ep){
*ep = '\0'; 
while(*ep != '=') ep++;
_ADURL = strcpy(buf, ++ep);
}else{
_ADURL = NULL;
}
}
strcpy( org_status, now_status);
while( isloop){
int maxi, maxj;
switch( nextturn){
case 'r':  // 'r'(置くのみ（波及せず）)  
if(smode == 1){
nextturn = toupper(nextturn);
}else{
char nextnextturn = toupper( nextturn);  //Rを要求
sprintf( autonext,                       
"?t=%c&x=%d&y=%d&s=%s",
nextnextturn, 
x, 
y,
now_status
);
countup();
disp_head(0, autonext);//１秒後にジャンプ
//pos_check( 1, nextnextturn, 8, 8, x, y, now_status);
now_status[ (y-1)*8+(x-1) ] = 'R';
disp_point( 0, x, y, now_status, nextturn, 0.0f);
disp_now( 
nextturn, 
8, 8, now_status, 0, x, y, org_status
);
nextturn = nextnextturn;
disp_tail(nextturn, NULL);
exit( 0);
}
break;
case 'w':  // 'w'(推論して置くのみ（波及せず）)  前フェーズで置けることをチェックして、このフェーズに入るようにする
if(smode == 1){
recursive_all_pos_check('W', &maxi, &maxj, now_status, MAX_LOOP);
x = maxi;
y = maxj;
nextturn = 'W';
}else{
char nextnextturn = toupper( nextturn);
recursive_all_pos_check('W', &maxi, &maxj, now_status, MAX_LOOP);
end = clock();
sprintf( autonext, 
"?t=%c&x=%d&y=%d&s=%s",
'W', 
maxi, 
maxj,
now_status
);
disp_head(1, autonext);//１秒後にジャンプ
//pos_check( 1, nextnextturn, 8, 8, x, y, now_status);
now_status[ (maxj-1)*8+(maxi-1) ] = 'W';
disp_point( 0, maxi, maxj, now_status, nextturn, ((double)(end-start)/CLOCKS_PER_SEC));
disp_now( 
nextturn, 
8, 8, now_status, 0, maxi, maxj, org_status
);
nextturn = nextnextturn;
disp_tail(nextturn, NULL);
exit( 0);
isloop = 0;
}
break;
case 'R':
{
int isblue = 0;
pos_check( 1, 'R', 8, 8, x, y, now_status);
if(all_pos_check('W', &maxi, &maxj, now_status) ＞ 0){
//白完(w要求）
sprintf( autonext, 
"?t=%c&x=%d&y=%d&s=%s",
'w',
0, 
0,
now_status
);
disp_head(1, autonext);
}else{
if(all_pos_check('R',  &maxi, &maxj, now_status) ＞ 0){
//青完
disp_head(0, "");
isblue = 1; 
}else{
//相手も自分もおけなかったとき
nextturn = 'N';
disp_head(0, "");
}
}
disp_point( 0, x, y, now_status, nextturn, 0.0f);
disp_now( 
nextturn, 
8, 8, now_status, isblue, x, y, org_status
);
disp_tail(nextturn, NULL);
}
isloop = 0;
break;
case 'W':
{
int isblue = 1;
//now_status[ (y-1)*8+(x-1) ] = 'N';
pos_check( 1, 'W', 8, 8, x, y, now_status);
if(all_pos_check('R', &maxi, &maxj, now_status) ＞ 0){
//青完   
disp_head(0, "");
nextturn = 'R';
}else{
if(all_pos_check('W', &maxi, &maxj, now_status) ＞ 0){
//黒完(w要求) 
sprintf( autonext, 
"?t=%c&x=%d&y=%d&s=%s",
'w', 
0, 
0,
now_status
);
isblue = 0;
disp_head(1, autonext);
}else{
//相手も自分もおけなかったとき
nextturn = 'N';
disp_head(0, "");
}
}
end = clock();
disp_point( 0, x, y, now_status, nextturn, ((double)(end-start)/CLOCKS_PER_SEC));
disp_now( 
nextturn, 
8, 8, now_status, isblue, x, y, org_status
);
disp_tail(nextturn, NULL);
}
isloop = 0;
break;
case 'N':
{
disp_head(0, "");
disp_point( 0, x, y, now_status, nextturn, 0.0f);
disp_now( 
nextturn, 
8, 8, now_status, 0, x, y, org_status
);
disp_tail(nextturn, NULL);
}
isloop = 0;
break;
}
}
}
＜参考資料Ｂ１＞
#
# index.cgi  for Wallstreets top url
# Copyright(c) KeisukeNAKAMURA
# All rights reserved.
#
0001 #!/usr/bin/perl -w
0002 
0003 print ＜＜EOT;
0004 Content-type: text/html;charset=euc-jp;
0005 
0006 ＜HTML＞
0007 ＜HEAD＞
0008 ＜TITLE＞WALLSTREETS＜/TITLE＞
0009 
0010 ＜/HEAD＞
省略
0052 ＜TABLE BGCOLOR=#550000 style="width:410px;"＞
0053 ＜TR＞＜TD＞＜FONT color=silver＞ここから選んでください↓（Please select board)＜/FONT＞＜/TD＞＜/TR＞
0054 ＜TR＞＜TD＞
0055 EOT
0056 
0057 my ％ib_disp_head;
0058 my ％ib_disp_tail;
0059 
0060 open(FIN,"＜ib_disp.txt");
0061 while($disp = ＜FIN＞){
0062     chomp( $disp);
0063     ($key,$head,$tail) = split(/;/,$disp);
0064     $ib_disp_head{$key} = $head;
0065     $ib_disp_tail{$key} = $tail;
0066 }
0067 close(FIN);
0068 
0069 
0070 use DirHandle;
0071 
0072 $count = 0;
0073 my ％amount;
0074 my ％entry;
0075 my ％topplayer;
0076 
0077 $dir = new DirHandle '.';
0078 while($data = $dir-＞read){
0079     if($data =~ /\.rank$/ and $data =~ /^ws5-JP/){
0080  open( FIN, "＜$data") || last; 
0081  undef ％entry;
0082  for($i = 0; $i ＜ 8; $i++){
0083      $e =  ＜FIN＞;
0084      #print "\t$e";
0085      chomp $e; 
0086      ($a,$b) = split( /,/, $e);
0087      if($i == 0){
0088   $ter{$b} .= "$data;";
0089   $topplayer{$data}="$b＜BR＞$a";
0090   $a = $a * 10000;
0091      }
0092      if($i == 1){
0093   $a = $a * 1000;
0094      }
0095      if($i == 2){
0096   $a = $a * 100;
0097      }
0098      if($i == 3){
0099   $a = $a * 10;
0100      }
0101      if($a ＞ 0 and $b ne "-" and !defined($entry{$b})){
0102   $entry{$b} = 1;
0103   $amount{"$b"} += $a;
0104      }
0105  } 
0106  close(FIN);
0107     }
0108 }
0109 $dir-＞close;
0110 
0111 $dir = new DirHandle '.';
0112 while($data = $dir-＞read){
0113     if($data =~ /\.cgi$/ and $data =~ /^ws5-JP/){
0114  ++$count;
0115  $wsp = $data;
0116  $wsp =~ s/ws5/wsp/;
0117  $pref = $data;
0118  $pref =~ s/ws5-JP-//;
0119  $pref =~ s/\.cgi$//;
0120  if(defined($ib_disp_head{$pref})){
0121      push @urllist,"$ib_disp_head{$pref}＜A HREF=\"$data\"＞＜FONT color=gold size=2＞$pref＜/FONT＞$ib_disp_tail{$pref}＜/A＞＜/TD＞＜TD＞ ＜FONT color=silver size=1＞$topplayer{$data.'.rank'}＜/FONT＞＜/TD＞＜TD＞＜A HREF=\"$wsp\"＞＜FONT color=cyan size=2＞隣人＜BR＞対戦＜/FONT＞＜/A＞";
0122  }else{
0123      push @urllist,"＜A HREF=\"$data\"＞＜FONT color=gold＞$pref ＜/FONT＞＜/A＞\n";
0124  }
0125     }
0126 }
0127 $dir-＞close;
0128 print "＜TABLE bgcolor=#550000＞";
0129 @s_urllist = sort @urllist;
0130 my $ci = 0;
0131 while( $ni = shift @s_urllist){
0132     $ci ++;
0133     if($ci ％ 2 == 0){
0134  print "＜TR bgcolor=#553333＞＜TD align=right＞$ni＜/TD＞＜/TR＞";
0135     }else{
0136  print "＜TR bgcolor=#550000＞＜TD align=right＞$ni＜/TD＞＜/TR＞";
0137     }
0138 }
0139 
0140 print "＜/TABLE＞";
0141 print "＜/TD＞＜/TR＞＜/TABLE＞＜BR＞";
0142 
0143 
0144 print "＜TABLE style=\"width:410px;\" ＞\n";
0145 print "＜TR＞＜TD colspan=2 align=center＞＜FONT color=silver size=3＞スコア合計ランキング（HIGHSCORE AMOUNT RANKING）＜/FONT＞＜/TD＞＜/TR＞\n";
0146 
0147 while(($k,$v) = each ％amount){
0148  $vf = sprintf("％8d 石", $v);
0149  if(defined($ter{$k})){
0150   
0151 
0152   $p =  "＜TR＞＜TD align=right bgcolor=gold width=130＞＜FONT size=5＞$vf＜/FONT＞＜/TD＞＜TD bgcolor=silver＞＜font size=5＞$k＜BR＞＜/font＞";
0153   @tops = sort split(/;/, $ter{$k}); 
0154   while( $aurl = shift @tops){
0155    $aurl =~ s/\.rank//;
0156    $burl = $aurl;
0157    $burl =~ s/\.cgi//;
0158    $burl =~ s/ws5-JP-//;
0159    $p .= "＜a href=\"$aurl\"＞＜FONT size=2＞$burl＜/FONT＞＜/a＞\n";
0160   } 
0161   $p .= "＜TD＞＜/TR＞\n";
0162   push @rank, $p;
0163  }else{
0164   push @rank, "＜TR＞＜TD align=right bgcolor=gold width=130＞$vf＜/TD＞＜TD bgcolor=cyan＞＜font size=3＞$k＜/font＞＜TD＞＜/TR＞\n";
0165  }
0166 }
0167 
0168 print sort {$b cmp $a} @rank;
0169 
0170 print "＜/TABLE＞\n";
0171 
0172 print ＜＜EOT;
0173 
0174 ＜TABLE＞
0175 ＜TR＞
0176  ＜TD colspan=3 align=left＞
0177   ＜FONT color=silver＞Please contact to＜/FONT＞
0178  ＜/TD＞
0179 ＜/TR＞
省略
0189 ＜/TABLE＞
0190 
0191 ＜HR＞＜FONT color=gold＞ Copyright(Ｃ） ＜/font＞＜A HREF="http://knowrel.com/"＞＜FONT color=gold＞KnowrelSystem,Inc.＜/FONT＞＜/A＞＜FONT color=silver＞ Produced&Programmed by ＜A HREF="mailto:keisuke\@knowrel.com"＞KeisukeNAKAMURA＜/A＞＜/FONT＞
0192 ＜/CENTER＞
0193 ＜/BODY＞
0194 ＜/HTML＞
0195 EOT
＜参考資料Ｂ２＞
#
# JP-wakayama1.c
#
# Copyright(c) KeisukeNAKAMURA
# All Rights Reserved.
#
char init[]=
"NNNNNNNN"
"NNNNNNNN"
"NNNNNNNN"
"NNNBWNNN"
"NNNWBNNN"
"NNNNNNNB"
"NNNNNNNN"
"NNNNNNNN";
char board[21*21]=
"CG---+-GGGGGGG--+"
"C +   +       + |"
"C  + G          |"
"C             + |"
"CC           +  |"
"C           +   |"
"C          +    |"
"C         +     |"
"C           C   |"
"C         +     |"
"CCC   C    +++++|"
"CCC           + |"
"CCCCC          +|"
"CCCCC           G"
"CCCCCCC   C   CCC"
"CCCCCCC       CCC"
"CCCCCCCCCCCCCCCCC";
＜参考資料Ｂ３＞
#
# wseuc_num8an.c 
#
# Copyright(c) KeisukeNAKAMURA
# All rights reserved.
#
0001 #include ＜stdio.h＞
0002 #include ＜stdlib.h＞
0003 #include ＜string.h＞
0004 #include ＜ctype.h＞
0005 #include ＜time.h＞
0006 #include ＜sys/types.h＞
0007 #include ＜sys/file.h＞
0008 #include ＜sys/stat.h＞
0009 #include ＜fcntl.h＞
0010 //#include ＜malloc.h＞
0011 
0012 #define ___B___ 'B'
0013 #define ___b___ 'b'
0014 #define ___W___ 'W'
0015 #define ___w___ 'w'
0016 #define ___N___ 'N'
0017 #define ___n___ 'n'
0018 
0019 
省略
0021 
0022 #define MAX_LOOP     (2000000000)
0023 
0024 //#define LEVEL 3
0025 #define LEVEL 5
0026 //#define LEVEL 7
0027 
0028 #define IS_P2P       (0)
0029 //#define IS_P2P       (1)
0030 
0031 //#define DEBUG
0032 
0033 char CGINAME[ 1024 ];
0034 
0035 #define IS_STACK_EST (0)
0036 #define COLOR_GREEN "#33ff33"
0037 #define MUGENM       (-65535)
0038 #define MUGENP       (+65535)
0039 
0040 #define GAME_SIZE_X  (8)
0041 #define GAME_SIZE_Y  (8)
0042 #define BOARD_SIZE_X (GAME_SIZE_X+GAME_SIZE_X+1)
0043 #define BOARD_SIZE_Y (GAME_SIZE_Y+GAME_SIZE_Y+1)
0044 
0045 
0046 extern char init[];
0047 
0048 extern char board[];
0049 int valpr[ 9 ][ 9 ] = { 0 }; 
0050 int valxy[ 9 ][ 9 ] = { 0 };
0051 int dirnm[ 9 ][ 9 ] = { 0 };
0052 char blockget( int sizex, int sizey, int x, int y, char *b)
0053 {
0054   return *(b + y*sizex + x);
0055 }
0056 
0057 int valdir( int basex, int basey, int dirx, int diry, char *b)
0058 {
0059   int point = 0;
0060   int sizex = 8;
0061   int sizey = 8; 
0062   while( blockget( sizex*2+1, sizey*2+1, (basex-1)*2+1-dirx,  (basey-1)*2+1-diry, b) == ' '){ 
0063     point++;
0064     basex -= dirx;
0065     basey -= diry;
0066   }
0067   return point;
0068 }
0069 
0070 int valdirxy( int basex, int basey, int dirx, int diry, char *b)
0071 {
0072   int point = 0;
0073   int sizex = 8;
0074   int sizey = 8; 
0075   while( blockget( sizex*2+1, sizey*2+1, (basex-1)*2+1-dirx,  (basey-1)*2+1-diry, b) == ' '){ 
0076     point += valpr[ basex ][ basey ];
0077     basex -= dirx;
0078     basey -= diry;
0079   }
0080   return point;
0081 }
0082 
0083 int valdirnb( int basex, int basey, int dirx, int diry, char *b)
0084 {
0085   return -valpr[ basex+dirx ][ basey+diry ]/dirnm[ basex+dirx ][ basey+diry ];
0086 }
0087 
0088 void value_init( char *b)
0089 {
0090   int sizex = 8;
0091   int sizey = 8; 
0092   int cx, cy;
0093 
盤の空いた座標の数（事前にグローバル変数化する）から序盤であるか
判断し、
序盤でないとき（またはより極端に中盤を除いて終盤のとき）に
すべてのvalxy[][]に１をいれて戻るコードをここに入れることが可能
0094   for( cx = 1; cx ＜= 8; cx++)
0095     for( cy = 1; cy ＜= 8; cy++)
0096       dirnm[ cx ][ cy ] =
0097          ((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) == ' ') ? 
0098           1:0)
0099         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) == ' ') ? 
0100           1:0)
0101         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) == ' ') ?
0102           1:0)
0103         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) == ' ') ?
0104           1:0)
0105         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) == ' ') ?
0106           1:0)
0107         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) == ' ') ?
0108           1:0)
0109         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) == ' ') ?
0110           1:0)
0111         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) == ' ') ?
0112           1:0);
0113 
0114   for( cx = 1; cx ＜= 8; cx++)
0115     for( cy = 1; cy ＜= 8; cy++){
0116       valpr[ cx ][ cy ] =
0117          ((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) == ' ') ? 
0118           0:valdir(cx,cy,-1,-1, b))
0119         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) == ' ') ? 
0120           0:valdir(cx,cy,-1, 0, b))
0121         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) == ' ') ?
0122           0:valdir(cx,cy,-1,+1, b))
0123         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) == ' ') ?
0124           0:valdir(cx,cy, 0,-1, b))
0125         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) == ' ') ?
0126           0:valdir(cx,cy, 0,+1, b))
0127         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) == ' ') ?
0128           0:valdir(cx,cy,+1,-1, b))
0129         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) == ' ') ?
0130           0:valdir(cx,cy,+1, 0, b))
0131         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) == ' ') ?
0132           0:valdir(cx,cy,+1,+1, b))
0133         ;
0134     }
0135 
0136   for( cx = 1; cx ＜= 8; cx++)
0137     for( cy = 1; cy ＜= 8; cy++){
0138       valxy[ cx ][ cy ] = valpr[ cx ][ cy ]
0139         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) == ' ') ? 
0140           0:valdirxy(cx,cy,-1,-1, b))
0141         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) == ' ') ? 
0142           0:valdirxy(cx,cy,-1, 0, b))
0143         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) == ' ') ?
0144           0:valdirxy(cx,cy,-1,+1, b))
0145         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) == ' ') ?
0146           0:valdirxy(cx,cy, 0,-1, b))
0147         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) == ' ') ?
0148           0:valdirxy(cx,cy, 0,+1, b))
0149         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) == ' ') ?
0150           0:valdirxy(cx,cy,+1,-1, b))
0151         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) == ' ') ?
0152           0:valdirxy(cx,cy,+1, 0, b))
0153         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) == ' ') ?
0154           0:valdirxy(cx,cy,+1,+1, b))
0155         ;
0156     }
0157 
0158   for( cx = 1; cx ＜= 8; cx++)
0159     for( cy = 1; cy ＜= 8; cy++)
0160       valpr[ cx ][ cy ] = valxy[ cx ][ cy ];
0161 
0162   {
0163     int min = 65535;
0164     for( cx = 1; cx ＜= 8; cx++)
0165       for( cy = 1; cy ＜= 8; cy++){
0166         valxy[ cx ][ cy ] = valpr[ cx ][ cy ]
0167         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2,   b) != ' ') ? 
0168           0:valdirnb(cx,cy,-1,-1, b))
0169         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+1, b) != ' ') ? 
0170           0:valdirnb(cx,cy,-1, 0, b))
0171         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2,   (cy-1)*2+2, b) != ' ') ?
0172           0:valdirnb(cx,cy,-1,+1, b))
0173         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2,   b) != ' ') ?
0174           0:valdirnb(cx,cy, 0,-1, b))
0175         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2+2, b) != ' ') ?
0176           0:valdirnb(cx,cy, 0,+1, b))
0177         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2,   b) != ' ') ?
0178           0:valdirnb(cx,cy,+1,-1, b))
0179         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+1, b) != ' ') ?
0180           0:valdirnb(cx,cy,+1, 0, b))
0181         +((blockget( sizex*2+1, sizey*2+1, (cx-1)*2+2, (cy-1)*2+2, b) != ' ') ?
0182           0:valdirnb(cx,cy,+1,+1, b))
0183         ;
0184         if(min ＞ valxy[ cx ][ cy ])
0185           min = valxy[ cx ][ cy ];
0186       }
0187     if(0 && min ＜ 1){
0188       for( cx = 1; cx ＜= 8; cx++)
0189         for( cy = 1; cy ＜= 8; cy++){
0190           valxy[ cx ][ cy ] += (-min+1);
0191         }
0192     }
0193   }
0194 
0195 }
0196 
0197 
0198 
0199 void set( char c, int sizex, int sizey, int x, int y, char *s)
0200 {
0201   *(s + (y-1)*sizex + (x-1)) = c;
0202 }
0203 
0204 char get( int sizex, int sizey, int x, int y, char *s)
0205 {
0206   return *(s + (y-1)*sizex + (x-1));
0207 }
0208 
0209 
0210 
0211 
0212 int pos_check( 
0213            int  is_turn, 
0214            char turn, 
0215            int  sizex, 
0216            int  sizey, 
0217            int  x, 
0218            int  y, 
0219            char *s
0220            )
0221 {
0222   int cx, cy;
0223   int exist_count = 0;
0224   char tonari = (turn == ___B___) ? ___W___:___B___;
0225   int tonari_count;
0226   int tonari_count_val;
0227 
0228   //左
0229   for( tonari_count = 0, cx = x-1, cy = y; ; cx--){
0230     if(cx == 0 || 
0231        blockget( sizex*2+1, sizey*2+1, cx*2, (cy-1)*2+1, board) != ' '){
0232       tonari_count = 0;
0233       tonari_count_val = 0;
0234       break;
0235     }else{
0236       char nc = get( sizex, sizey, cx, cy, s);
0237       if(nc == tonari){
0238         tonari_count++;
0239         tonari_count_val+=valxy[ cx ][ cy ];
0240       }else if(nc == turn && tonari_count ＞ 0){
0241         //exist_count += tonari_count_val;
0242         exist_count += tonari_count;
0243         break;
0244       }else{
0245         tonari_count = 0;
0246         tonari_count_val = 0;
0247         break;
0248       }
0249     }
0250   }
0251   if(is_turn && tonari_count){
0252     for( cx = x-1, cy = y; tonari_count-- ＞ 0; cx--){
0253       set( turn, sizex, sizey, cx, cy, s);
0254     }
0255   }
0256 
0257   //右  
0258   for( tonari_count = 0, cx = x+1, cy = y; ; cx++){
0259     if(cx ＞ sizex ||
0260        blockget( sizex*2+1, sizey*2+1, (cx-1)*2, (cy-1)*2+1, board) != ' '){
0261       tonari_count = 0;
0262       tonari_count_val = 0;
0263       break;
0264     }else{
0265       char nc = get( sizex, sizey, cx, cy, s);
0266       if(nc == tonari){
0267         tonari_count++;
0268         tonari_count_val+=valxy[ cx ][ cy ];
0269       }else if(nc == turn && tonari_count ＞ 0){
0270         //exist_count += tonari_count_val;
0271         exist_count += tonari_count;
0272         break;
0273       }else{
0274         tonari_count = 0;
0275         tonari_count_val = 0;
0276         break;
0277       }
0278     }
0279   }
0280   if(is_turn && tonari_count){
0281     for( cx = x+1, cy = y; tonari_count-- ＞ 0; cx++){
0282       set( turn, sizex, sizey, cx, cy, s);
0283     }
0284   }
0285 
0286   //上
0287   for( tonari_count = 0, cx = x, cy = y-1; ; cy--){
0288     if(cy == 0 ||
0289        blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, cy*2, board) != ' '){
0290       tonari_count = 0;
0291       tonari_count_val = 0;
0292       break;
0293     }else{
0294       char nc = get( sizex, sizey, cx, cy, s);
0295       if(nc == tonari){
0296         tonari_count++;
0297         tonari_count_val+=valxy[ cx ][ cy ];
0298       }else if(nc == turn && tonari_count ＞ 0){
0299         //exist_count += tonari_count_val;
0300         exist_count += tonari_count;
0301         break;
0302       }else{
0303         tonari_count = 0;
0304         tonari_count_val = 0;
0305         break;
0306       }
0307     }
0308   }
0309   if(is_turn && tonari_count){
0310     for( cx = x, cy = y-1; tonari_count--; cy--){
0311       set( turn, sizex, sizey, cx, cy, s);
0312     }
0313   }
0314 
0315   //下
0316   for( tonari_count = 0, cx = x, cy = y+1; ; cy++){
0317     if(cy ＞ sizey ||
0318        blockget( sizex*2+1, sizey*2+1, (cx-1)*2+1, (cy-1)*2, board) != ' '){
0319       tonari_count = 0;
0320       tonari_count_val = 0;
0321       break;
0322     }else{
0323       char nc = get( sizex, sizey, cx, cy, s);
0324       if(nc == tonari){
0325         tonari_count++;
0326         tonari_count_val+=valxy[ cx ][ cy ];
0327       }else if(nc == turn && tonari_count ＞ 0){
0328         //exist_count += tonari_count_val;
0329         exist_count += tonari_count;
0330         break;
0331       }else{
0332         tonari_count = 0;
0333         tonari_count_val = 0;
0334         break;
0335       }
0336     }
0337   }
0338   if(is_turn && tonari_count){
0339     for( cx = x, cy = y+1; tonari_count--; cy++){
0340       set( turn, sizex, sizey, cx, cy, s);
0341     }
0342   }
0343 
0344   //左上
0345   for( tonari_count = 0, cx = x-1, cy = y-1; ; cx--, cy--){
0346     if(cx == 0 || cy == 0 ||
0347       blockget( sizex*2+1, sizey*2+1, cx*2, cy*2, board) != ' '){
0348       tonari_count = 0;
0349       tonari_count_val = 0;
0350       break;
0351     }else{
0352       char nc = get( sizex, sizey, cx, cy, s);
0353       if(nc == tonari){
0354         tonari_count++;
0355         tonari_count_val+=valxy[ cx ][ cy ];
0356       }else if(nc == turn && tonari_count ＞ 0){
0357         //exist_count += tonari_count_val;
0358         exist_count += tonari_count;
0359         break;
0360       }else{
0361         tonari_count = 0;
0362         tonari_count_val = 0;
0363         break;
0364       }
0365     }
0366   }
0367   if(is_turn && tonari_count){
0368     for( cx = x-1, cy = y-1; tonari_count--; cx--, cy--){
0369       set( turn, sizex, sizey, cx, cy, s);
0370     }
0371   }
0372 
0373   //左下
0374   for( tonari_count = 0, cx = x-1, cy = y+1; ; cx--, cy++){
0375     if(cx == 0 || cy ＞ sizey||
0376        blockget( sizex*2+1, sizey*2+1, cx*2, (cy-1)*2, board) != ' '){
0377       tonari_count = 0;
0378       tonari_count_val = 0;
0379       break;
0380     }else{
0381       char nc = get( sizex, sizey, cx, cy, s);
0382       if(nc == tonari){
0383         tonari_count++;
0384         tonari_count_val+=valxy[ cx ][ cy ];
0385       }else if(nc == turn && tonari_count ＞ 0){
0386         //exist_count += tonari_count_val;
0387         exist_count += tonari_count;
0388         break;
0389       }else{
0390         tonari_count = 0;
0391         tonari_count_val = 0;
0392         break;
0393       }
0394     }
0395   }
0396   if(is_turn && tonari_count){
0397     for( cx = x-1, cy = y+1; tonari_count--; cx--, cy++){
0398       set( turn, sizex, sizey, cx, cy, s);
0399     }
0400   }
0401 
0402   //右上
0403   for( tonari_count = 0, cx = x+1, cy = y-1; ; cx++, cy--){
0404     if(cx ＞ sizex || cy == 0 ||
0405        blockget( sizex*2+1, sizey*2+1, (cx-1)*2, cy*2, board) != ' '){
0406       tonari_count = 0;
0407       tonari_count_val = 0;
0408       break;
0409     }else{
0410       char nc = get( sizex, sizey, cx, cy, s);
0411       if(nc == tonari){
0412         tonari_count++;
0413         tonari_count_val+=valxy[ cx ][ cy ];
0414       }else if(nc == turn && tonari_count ＞ 0){
0415         //exist_count += tonari_count_val;
0416         exist_count += tonari_count;
0417         break;
0418       }else{
0419         tonari_count = 0;
0420         tonari_count_val = 0;
0421         break;
0422       }
0423     }
0424   }
0425   if(is_turn && tonari_count){
0426     for( cx = x+1, cy = y-1; tonari_count--; cx++, cy--){
0427       set( turn, sizex, sizey, cx, cy, s);
0428     }
0429   }
0430 
0431   //右下
0432   for( tonari_count = 0, cx = x+1, cy = y+1; ; cx++, cy++){
0433     if(cx ＞ sizex || cy ＞ sizey ||
0434        blockget( sizex*2+1, sizey*2+1, (cx-1)*2, (cy-1)*2, board) != ' '){
0435       tonari_count = 0;
0436       tonari_count_val = 0;
0437       break;
0438     }else{
0439       char nc = get( sizex, sizey, cx, cy, s);
0440       if(nc == tonari){
0441         tonari_count++;
0442         tonari_count_val+=valxy[ cx ][ cy ];
0443       }else if(nc == turn && tonari_count ＞ 0){
0444         //exist_count += tonari_count_val;
0445         exist_count += tonari_count;
0446         break;
0447       }else{
0448         tonari_count = 0;
0449         tonari_count_val = 0;
0450         break;
0451       }
0452     }
0453   }
0454   if(is_turn && tonari_count){
0455     for( cx = x+1, cy = y+1; tonari_count--; cx++, cy++){
0456       set( turn, sizex, sizey, cx, cy, s);
0457     }
0458   }
0459 
0460   if(is_turn && exist_count)
0461     set( turn, sizex, sizey, x, y, s);
0462 
0463   return exist_count;
0464 }
0465 
0466 const char urlcurs[ 63 ] = "0123456789"
0467 "abcdefghijklmnopqrstuvwxyz"
0468 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
0469 char * cur2urlcur( char *urlcur, char *cur)
0470 {
0471   static char *ret;
0472   int num = 0;
0473   int i=0;
0474   ret = urlcur;
0475   while(i ＜ 64){
0476     switch( *cur){
0477     case ___N___: num = num * 3;     break;
0478     case ___B___: num = num * 3 + 1; break;
0479     case ___W___: num = num * 3 + 2; break; 
0480     }
0481     cur++;
0482     i++;
0483     if( i ％ 3 == 0){
0484       *urlcur = urlcurs[ num ];
0485       urlcur++;
0486       num = 0;
0487     }
0488   }
0489   *urlcur = urlcurs[ num*3*3 ];
0490   urlcur++;
0491 
0492   *urlcur = '\0';
0493 
0494   return ret;
0495 }
0496 
0497 char * urlcur2cur( char *cur, char *urlcur)
0498 {
0499   static char *ret;
0500   int i=0;
0501   ret = cur;
0502   *cur = '\0';
0503   while( i ＜ 22){
0504     switch( *urlcur){
0505     case '0': *cur++ = ___N___; *cur++ = ___N___; *cur++ = ___N___; break;
0506     case '1': *cur++ = ___N___; *cur++ = ___N___; *cur++ = ___B___; break;
0507     case '2': *cur++ = ___N___; *cur++ = ___N___; *cur++ = ___W___; break;
0508     case '3': *cur++ = ___N___; *cur++ = ___B___; *cur++ = ___N___; break;
0509     case '4': *cur++ = ___N___; *cur++ = ___B___; *cur++ = ___B___; break;
0510     case '5': *cur++ = ___N___; *cur++ = ___B___; *cur++ = ___W___; break;
0511     case '6': *cur++ = ___N___; *cur++ = ___W___; *cur++ = ___N___; break;
0512     case '7': *cur++ = ___N___; *cur++ = ___W___; *cur++ = ___B___; break;
0513     case '8': *cur++ = ___N___; *cur++ = ___W___; *cur++ = ___W___; break;
0514 
0515     case '9': *cur++ = ___B___; *cur++ = ___N___; *cur++ = ___N___; break;
0516     case 'a': *cur++ = ___B___; *cur++ = ___N___; *cur++ = ___B___; break;
0517     case 'b': *cur++ = ___B___; *cur++ = ___N___; *cur++ = ___W___; break;
0518     case 'c': *cur++ = ___B___; *cur++ = ___B___; *cur++ = ___N___; break;
0519     case 'd': *cur++ = ___B___; *cur++ = ___B___; *cur++ = ___B___; break;
0520     case 'e': *cur++ = ___B___; *cur++ = ___B___; *cur++ = ___W___; break;
0521     case 'f': *cur++ = ___B___; *cur++ = ___W___; *cur++ = ___N___; break;
0522     case 'g': *cur++ = ___B___; *cur++ = ___W___; *cur++ = ___B___; break;
0523     case 'h': *cur++ = ___B___; *cur++ = ___W___; *cur++ = ___W___; break;
0524 
0525     case 'i': *cur++ = ___W___; *cur++ = ___N___; *cur++ = ___N___; break;
0526     case 'j': *cur++ = ___W___; *cur++ = ___N___; *cur++ = ___B___; break;
0527     case 'k': *cur++ = ___W___; *cur++ = ___N___; *cur++ = ___W___; break;
0528     case 'l': *cur++ = ___W___; *cur++ = ___B___; *cur++ = ___N___; break;
0529     case 'm': *cur++ = ___W___; *cur++ = ___B___; *cur++ = ___B___; break;
0530     case 'n': *cur++ = ___W___; *cur++ = ___B___; *cur++ = ___W___; break;
0531     case 'o': *cur++ = ___W___; *cur++ = ___W___; *cur++ = ___N___; break;
0532     case 'p': *cur++ = ___W___; *cur++ = ___W___; *cur++ = ___B___; break;
0533     case 'q': *cur++ = ___W___; *cur++ = ___W___; *cur++ = ___W___; break;
0534 
0535     }
0536     i++;
0537     urlcur++;
0538   }
0539   cur-=2;//3*22-8*8
0540   *cur = '\0';
0541
0542  return ret;
0543 }
0544 
0545 
0546 #define WALLCOLOR "gold"
0547 char * colorstring( int c, char *def)
0548 {
0549   switch( c){
0550   case 'C':
0551   case 'c':
0552     return "#33AAFF";
0553   case 'H':
0554   case 'h':
0555     return "gray";
0556   case 'B':
0557   case 'b':
0558     return "black";
0559   case 'G':
0560   case 'g':
0561     return WALLCOLOR;
0562   case 'S':
0563   case 's':
0564     return "silver";
0565   case 'R':
0566   case 'r':
0567     return "red";
0568   case '+':
0569   case '-':
0570   case '|':
0571   default:
0572     return def;
0573   }
0574 }
0575 
0576 char * colorPstring( int c, char *def)
0577 {
0578   switch( c){
0579   case 'C':
0580   case 'c':
0581     return "cyan";
0582   case 'H':
0583   case 'h':
0584     return "gray";
0585   case 'B':
0586   case 'b':
0587     return "black";
0588   case 'G':
0589   case 'g':
0590     return WALLCOLOR;
0591   case 'S':
0592   case 's':
0593     return "silver";
0594   case 'R':
0595   case 'r':
0596     return "red";
0597   case '+':
0598   case '-':
0599   case '|':
0600   default:
0601     return def;
0602   }
0603 }
0604 char * colorDstring( int c, char *def)
0605 {
0606   switch( c){
0607   case 'C':
0608   case 'c':
0609     return "cyan";
0610   case 'H':
0611   case 'h':
0612     return "gray";
0613   case 'B':
0614   case 'b':
0615     return "black";
0616   case 'G':
0617   case 'g':
0618     return WALLCOLOR;
0619   case 'S':
0620   case 's':
0621     return "silver";
0622   case 'R':
0623   case 'r':
0624     return "red";
0625   case '+':
0626   case '-':
0627   case '|':
0628   default:
0629     return def;
0630   }
0631 }
0632 
0633 int disp_now( char nextturn, int xsize, int ysize, char *status, int isblue, int bx, int by, char *orgstatus)
0634 {
0635   char urlstatus[ 24 ];
0636   int i,j;
0637   printf("＜TABLE bgcolor=green＞\n");
0638   for( i = 0; i ＜ (ysize*2)+1; i++)
0639     {
0640       printf("＜TR hight=16＞\n");
0641       for( j = 0; j ＜ (xsize*2)+1; j++)
0642         {
0643           char c = board[ i*(xsize*2+1)+j ];
0644           char m = *(status+(i/2)*xsize+(j/2));
0645           if(i％2 && j％2){  
0646             char ms[ 256 ];
0647             switch( m)
0648               {
0649 #ifdef IS_NUM
0650               case ___B___: sprintf(  ms, "＜FONT COLOR=WHITE＞●＜BR＞％d＜/FONT＞", valxy[ j/2+1 ][ i/2+1 ]);break;
0651               case ___W___: sprintf(  ms, "＜FONT COLOR=RED＞●＜BR＞％d＜/FONT＞", valxy[ j/2+1 ][ i/2+1 ]);break;
0652 #else
0653               case ___B___: 
0654                 if(i/2+1 == by && j/2+1 == bx)
0655                   sprintf(  ms, "＜IMG SRC=\"/icons/black24f.gif\"＞");
0656                 else if(*(orgstatus+(i/2)*xsize+(j/2)) != ___B___)
0657                   sprintf(  ms, "＜IMG SRC=\"/icons/black24d.gif\"＞");
0658                 else 
0659                   sprintf(  ms, "＜IMG SRC=\"/icons/black24c.gif\"＞");
0660                 break;
0661               case ___W___: 
0662                 if(i/2+1 == by && j/2+1 == bx)
0663                   sprintf(  ms, "＜IMG SRC=\"/icons/white24f.gif\"＞");
0664                 else if(*(orgstatus+(i/2)*xsize+(j/2)) != ___W___)
0665                   sprintf(  ms, "＜IMG SRC=\"/icons/white24d.gif\"＞");
0666                 else 
0667                   sprintf(  ms, "＜IMG SRC=\"/icons/white24c.gif\"＞");
0668                 break;
0669 #endif
0670               case ___N___: if(isblue == 0
0671                         || nextturn == ___N___
0672                         || nextturn == ___b___
0673                         || nextturn == ___w___   
0674                         || pos_check( 0, nextturn, 8, 8, j/2+1, i/2+1, status) == 0){
0675 #ifdef IS_NUM
0676                           sprintf( ms, "×＜BR＞％d", valxy[ j/2+1 ][ i/2+1 ]);
0677 #else
0678                           if(c == ' ')
0679                             sprintf( ms, 
0680                                        "＜IMG SRC=\"/icons/green24c.gif\" border=\"0\"＞");
0681                           else
0682                             sprintf( ms, "＜FONT COLOR=\"％s\"＞■＜/FONT＞", 
0683                                      colorPstring( c, "green"));
0684 #endif
0685                         }else{
0686 #ifdef IS_NUM
0687                           sprintf( ms, 
0688                            "＜A HREF=\"/cgi-bin/％s?t=％c&x=％d&y=％d&s=％s\"＞"
0689                                  "○＜BR＞％d"
0690                                  "＜/A＞", 
0691                                    CGINAME,
0692                                    tolower(nextturn), j/2+1, i/2+1,
0693                                    //status,
0694                                    cur2urlcur( urlstatus, status),
0695                                    valxy[ j/2+1 ][ i/2+1 ]
0696                                  );
0697 #else
0698                           sprintf( ms, 
0699                            "＜A HREF=\"/cgi-bin/％s?t=％c&x=％d&y=％d&s=％s\"＞"
0700                                    "＜IMG SRC=\"/icons/blue24e.gif\" border=\"0\"＞"
0701                                    //"○"
0702                                  "＜/A＞", 
0703                                    CGINAME,
0704                                    tolower(nextturn), j/2+1, i/2+1,
0705                                    //status
0706                                    cur2urlcur( urlstatus, status)
0707                                  );
0708 #endif
0709                         }
0710                         break;
0711               }
0712 #ifdef IS_NUM
0713             printf( 
0714                    "＜TD align=center bgcolor=green width=36 height=36＞％s＜/TD＞",
0715                    ms
0716                    );
0717 #else
0718             printf( 
0719                    "＜TD align=center bgcolor=％s width=32 height=32＞％s＜/TD＞",
0720                    ((c == ' ') ? "green":colorPstring(c, "green")) , 
0721                    ms
0722                    );
0723 #endif
0724           }else{
0725             printf( "＜TD bgcolor=％s width=1 height=3＞＜/TD＞",
0726                     (c==' ') ? 
0727                       "#009900":
0728                       (((i+j)％2) ?
0729                         ((j == 0 || 
0730                           j == (xsize*2) || 
0731                           i == (ysize*2) || 
0732                           i == 0) ? 
0733                           colorDstring(c, "black"):colorDstring(c, WALLCOLOR)
0734                          )
0735                        :
0736                         ((j == 0 || 
0737                           j == (xsize*2) || 
0738                           i == (ysize*2) || 
0739                           i == 0) ? 
0740                           colorDstring(c, "black"):colorDstring(c, WALLCOLOR)
0741                          )
0742                        )
0743                   ); 
0744           }
0745         }
0746       printf("＜/TR＞\n");
0747     }
0748   printf("＜/TABLE＞\n");
0749 }
0750 
0751 char * _ADURL = NULL;
0752 
0753 int i[ 64+1 ],j[ 64+1 ];
0754 int max[ 64+1 ];
0755 char status[ 64+1 ][ 64+1 ];
0756 char turn[ 64+1 ];
0757 int check[ 64+1 ];
0758 char now_status[ 1024 ];
0759 
0760 void disp_head(int i, char *s)
0761 {
0762   printf("Content-type: text/html;charset=euc-jp;\n\n"); 
0763   printf("＜HTML＞\n");
0764   printf("＜HEAD＞\n");
0765   if((i ＞ 0 ||(s && *s)))
0766     printf("＜META HTTP-EQUIV=\"REFRESH\" CONTENT=\"％d;URL=/cgi-bin/％s％s\"＞\n",i, CGINAME, s);
0767   printf("＜TITLE＞WALLSTREETS＜/TITLE＞\n");
0768   printf("＜STYLE TYPE=\"text/css\"＞");
0769   printf("＜!--\n");
0770   printf("H1{font-size:16pt; color:gold}\n");
0771   printf("H2{font-size:8pt; color:blue}\n");
0772   printf("body {\n");
0773   printf("background-repeat: no-repeat;\n");
0774   printf("background-attachment: fixed;\n");
0775   printf("background-position: center middle;\n");
0776   printf("}\n");
0777   printf("A{\n");
0778   printf("    text-decoration: none;\n");
0779   printf("}\n");
0780   printf("A:HOVER{\n");
0781   printf("background:repat-x center bottom;\n");
0782   printf("}\n");
0783   printf("--＞\n");
0784   printf("＜/STYLE＞\n");
0785   printf("＜/HEAD＞\n");
0786   printf("＜BODY bgcolor=#000033＞\n");
0787   printf("＜CENTER＞\n");
0788   if( s && *s){
0789     printf("＜TABLE＞＜TR＞＜TD align=center valign=top＞\n");
0790   }else{
0791     printf("＜TABLE＞＜TR＞＜TD align=center valign=top＞\n");
0792   }
0793   printf("＜TABLE bgcolor=#550000 style=\"width:335px;\"＞＜TR＞＜TD align=center＞＜FONT SIZE=5 COLOR=GOLD＞WallStreets＜/FONT＞＜A HREF=\"#\" onclick=\"var w01;w01=window.open('http://wallstreets.ws/','win1','width=480,height=730,resizable=yes');w01.focus()\"＞＜FONT SIZE=3 COLOR=silver＞ JP＜/FONT＞＜/A＞＜A HREF=\"#\" onclick=\"var w01;w01=window.open('http://wallstreets.ws/eu/','win1','width=480,height=730,resizable=yes');w01.focus()\"＞＜FONT SIZE=3 COLOR=silver＞ UV＜/FONT＞＜/A＞＜/TD＞＜/TR＞＜/TABLE＞\n");
0794 }
0795 
0796 int whitenum( char *status)
0797 {
0798   int ret = 0;
0799   while( *status){
0800     if(*status == ___W___)
0801       ret++;
0802     status++;
0803   }
0804 
0805   return ret;
0806 }
0807 
0808 char *mycrypt( char *msg)
0809 {
暗号化コードのため省略
0823 }
0824 
0825 
0826 void disp_tail(char nextturn, char *msg)
0827 {
0828   char buf[ 256 ];
0829   char filename[ 256 ];
0830   char  userpoint[ 8 ][ 160 ];
0831   char  username[ 8 ][ 320 ];
0832   int   i = 0;
0833 
0834 
0835   if(IS_P2P == 0){
0836     sprintf( filename, "％s.rank", CGINAME); 
0837 
0838     FILE *fp;
0839     do{
0840       fp = fopen( filename, "rb");
0841       if(!fp){
0842         FILE *fout = fopen(filename, "wb");
0843         fprintf(fout, "0,-\n0,-\n0,-\n0,-\n0,-\n0,-\n0,-\n0,-\n0,-\n");
0844         fclose(fout);
0845       }
0846     }while(!fp);
0847 
0848     while( fgets( buf, 256, fp ) && i ＜ 8){
0849       char *cp = strchr( buf, ',');
0850       *cp = '\0';
0851       strcpy( userpoint[ i ], buf);
0852       strcpy( username[ i ], cp+1);
0853       i++;
0854     }
0855     fclose( fp);
0856 
0857 
0858     printf("＜TABLE bgcolor=#550000 style=\"width:335px;\"＞\n");
0859     if(nextturn==___N___ && whitenum( now_status) ＞ atoi(userpoint[ 7 ])){ 
0860       printf("＜TR＞＜TD colspan=3 align=center＞\n");
0861       printf("＜FORM method=post action=\"http://wallstreets.ws/cgi-bin/％s?t=h\"＞\n", CGINAME);
0862       printf("＜INPUT TYPE=hidden name=stat value=\"％s\"＞\n", now_status);
0863       printf("＜INPUT TYPE=hidden name=crypt value=\"％s\"＞\n", mycrypt(now_status));
0864       printf("＜FONT color=gold＞nickname:＜/font＞＜INPUT TYPE=text name=username value=\"\"＞\n");
0865       printf("＜INPUT type=submit value=\"High Score Set\"＞\n");
0866       printf("＜/FORM＞\n");
0867       printf("＜/TD＞＜/TR＞\n");
0868     }
0869     {
0870       int i;
0871       if(atol(userpoint[0]) ＞ 0) strcat( userpoint[ 0 ], "0000");
0872       if(atol(userpoint[1]) ＞ 0) strcat( userpoint[ 1 ], "000");
0873       if(atol(userpoint[2]) ＞ 0) strcat( userpoint[ 2 ], "00");
0874       if(atol(userpoint[3]) ＞ 0) strcat( userpoint[ 3 ], "0");
0875       for(i = 0; i ＜ 8; i++)
0876         {
0877           printf("＜TR bgcolor=％s＞＜TD align=right＞\n", (i％2) ? "0x000033":"0x000011");
0878           printf("＜FONT color=silver＞＜％d＞＜/FONT＞＜/TD＞＜TD align=right＞＜FONT color=silver＞％s＜/FONT＞＜/TD＞＜TD align=center＞＜FONT color=silver＞％s＜/FONT＞\n", i+1, userpoint[ i ] , username[ i ]);
0879           printf("＜/TD＞＜/TR＞\n");
0880         }
0881     }
0882     printf("＜TR＞＜TD colspan=3 align=center＞\n");
0883     printf("＜FONT size=5 color=gold＞★RANKING★＜/FONT＞\n");
0884     printf("＜/TD＞＜/TR＞\n");
0885     printf("＜/TABLE＞\n");
0886   }
0887   printf("＜TD＞＜/TR＞＜/TABLE＞\n");
0888   printf("＜/BODY＞\n");
0889   printf("＜/HTML＞\n");
0890 }
0891 
0892 int all_pos_check( char nextturn, int *maxi, int *maxj, char *now_status)        
0893 {
0894   int i,j;
0895   int max = 0;
0896   *maxi = 0;
0897   *maxj = 0;
0898   for( i = 1; i ＜= 8; i++){
0899     for( j = 1; j ＜=8; j++){
0900       if(get( 8, 8, i, j, now_status) == ___N___){
0901         int now = pos_check( 0, nextturn, 8, 8, i, j, now_status);
0902         if(now ＞ max){
0903           *maxi = i;
0904           *maxj = j;
0905           max = now;
0906         }
0907       }
0908     }
0909   }
0910   return max;
0911 }
0912 
0913 void p( char *str)
0914 {
0915   printf( "％s\n", str);
0916 } 
0917 
0918 
0919 int minmax[ 64+1 ];               
省略
0926 int max_sp;
0927 int now_max_loop;
省略
0964 void disp_stack( int x, int y, char *msg)
0965 {
0966   ;
0967 }
省略
0969 
0970 /*-----------------------------------------------------------------------------
0971   関数名  recursive_all_pos_check
0972   機能    最も有望な手を返す
0973   引数    nextturn               有望な手を探索する側(___B___/___W___)
0974           *maxi                  有望な手のX座標
0975           *maxj                  有望な手のY座標
0976           now_status             探索の対象となるゲーム状態 
0977           max_loop               最大の探索ループ数
0978   ---------------------------------------------------------------------------*/
0979 int recursive_all_pos_check( 
0980                             char  nextturn, 
0981                             int   *maxi, 
0982                             int   *maxj, 
0983                             char  *now_status,
0984                             unsigned long  max_loop
0985 )        
0986 {
以下では、多ゲームプロセス同時処理用のサーバーや携帯電話など少ないメモリしか利用しないプラットフォームで、しかも適度に負ける必要のある場合に対応する「ひとつのベストモード」として、スタックによる、深さレベル（＝先読みレベル）制限つきの深さ優先探索をおこなっているが、多くのメモリが利用できるスピード優先ないし強さ優先（勝利優先）のモードでは、探索対象となるゲーム状態の合流（違う手として先読みして同じゲーム状態に遭遇する場合）をハッシュテーブル等により検知してその先の重複探索を回避したり、パターン化された有望な手筋についてのみ先読みの深さレベルを制限しないようにする等、より一般的な公知の探索手法も「別のベストモード」として採用できることは自明であり、これについては詳述しない。
基本的には公知のミニマックス法で最良の手を決定するが、手の評価において、自分の駒の置いてある座標の重み（value_init()で生成済のvalxy[][]）の和がなるべく大きくなる手を最良の手として選ぶ。
また、適度の負ける必要がなく、より強さ優先にするには、終盤で、座標の重み（座標の価値を表すvalxy[][]）を別途均一化し、単純に駒数で相手に優るような手を探索するようにする。
0987   const int level = LEVEL;
0988   int first_get = 0;
0989   int m,n;
0990 
0991   *maxi = *maxj = 0;
0992 
省略
0994   minmax[ 0 ] = MUGENM;
0995 
0996   // スタックの初期化
0997   max_sp = 0;
0998   turn[ 0 ] = ___N___;
0999   strcpy( status[ 0 ], now_status);
1000   i[ 0 ] = j[ 0 ] = 0;
1001   max[ 0 ] = 0;
1002 #ifdef DEBUG
1003 printf( "＜TABLE border bgcolor=white＞\n");
1004 #endif
1005   // 次の一手
1006   ++max_sp;
1007   turn[ max_sp ] = nextturn;
1008   i[ max_sp ] = j[ max_sp ] = 1;
1009   max[ max_sp ] = 0;
1010   do{
1011 
1012     if(--max_loop == 0){
1013       disp_stack( *maxi, *maxj, "LOOPOVER");
1014       break;
1015     }
1016     now_max_loop = max_loop;
1017 
1018     if( max_sp ％ 2 == 1 && max_sp ＜ level){
1019       // 1 or 3 のとき
1020       minmax[ max_sp ] = MUGENP;
1021     }
1022 
1023     if( max_sp ％ 2 == 0 && max_sp ＜ level){
1024       // 2 or 4 のとき(0はありえないから)
1025       minmax[ max_sp ] = MUGENM;
1026     } 
1027 
1028     strcpy( status[ max_sp ], status[ max_sp-1 ]);
1029 
1030     if( get( 8, 8, i[ max_sp ], j[ max_sp ], status[ max_sp ]) == ___N___
1031     &&  (check[ max_sp ] 
1032          =  pos_check( 1, turn[ max_sp ], 8, 8, i[ max_sp ], j[ max_sp ], status[ max_sp ])) ＞ 0){
1033       // 注目した座標(i[max_sp],j[max_sp])に石がなくかつとれるので置ける場合
1034 
1035       // 現在のmax_sp-1のゲーム状態に対して先の手max_spが存在することをマークする
1036       max[ max_sp ] = check[ max_sp ];
1037 
1038       if(max_sp ＜ level){
1039         // まだ先を読む必要がある場合,
1040 
1041         //disp_stack( *maxi, *maxj, "THINKING");
1042         // 置いてみた後のstatus[ max_sp ]をスタックにつむ
1043         ++max_sp;
1044         turn[ max_sp ] = (turn[ max_sp-1 ] == ___B___) ? ___W___:___B___;
1045         i[ max_sp ] = j[ max_sp ] = 1;
1046         max[ max_sp ] = 0;
1047 
1048       }else{
1049         // 最深読みレベルに達していた場合
1050 
1051         // 最深読みレベルの評価を計算する
1052         int sum = 0;
1053         int k;
1054         if(IS_STACK_EST)
1055         {
1056           for( k = 1; k ＜= max_sp; k++)
1057             sum += 
1058               (turn[ k ] == nextturn) ? 
1059               +(check[ k ]+valxy[i[ k ]][j[ k ]]) :  -(check[ k ]+valxy[i[ k ]][j[ k ]]);
1060           //+(check[ k ]) :  -(check[ k ]);
1061         }else{
1062           int x,y;
1063           int sumw = 0;
1064           int sumb = 0;
1065           for( x = 1; x ＜= 8; x++){
1066             for( y = 1; y ＜= 8; y++){
1067               switch(get( 8, 8, x, y, status[ max_sp ])){
1068               case ___N___: break;
1069               case ___B___: sumw += valxy[ x ][ y ]; break;
1070               case ___W___: sumb += valxy[ x ][ y ]; break;
1071               }
1072             }
1073           }
1074           sum = (nextturn == ___B___) ? (sumw-sumb):(sumb-sumw);
1075         }
1076         if(/* 最深レベルは奇数故 max_sp ％ 2 = 1 のチェックはいらない */
1077            sum ＞ minmax[ max_sp-1 ]){
1078           minmax[ max_sp-1 ] = sum; 
1079           //disp_stack( *maxi, *maxj, "sum ＞ minmax[ max_sp-1 ]");
1080         }
1081         //disp_stack( *maxi, *maxj);
1082 
1083         // 次の候補にポインタを移す
1084         while( j[ max_sp ] == 8 && i[ max_sp ] == 8 && max_sp ＞ 0){
1085           max_sp --;
1086           if(max_sp ％ 2 == 0 && max_sp ＜ level){
1087             if(minmax[ max_sp ] ＜ minmax[ max_sp-1 ]){
1088               minmax[ max_sp-1 ] = minmax[ max_sp ];
1089               disp_stack( *maxi, *maxj, "minmax[ max_sp ] ＜ minmax[ max_sp-1 ]");
1090             }
1091           }
1092 
1093           if(max_sp ％ 2 == 1 && max_sp ＜ level){
1094             if(minmax[ max_sp-1 ] ＜ minmax[ max_sp ]){
1095               minmax[ max_sp-1 ] = minmax[ max_sp ];
1096               disp_stack( *maxi, *maxj, "minmax[ max_sp-1 ] ＜ minmax[ max_sp ]");
1097               if( max_sp == 1){
1098                 *maxi = i[ 1 ];
1099                 *maxj = j[ 1 ];
1100                 first_get = check[ 1 ];
1101               }
1102             }
1103           }
1104           if(max_sp == 1)
1105             disp_stack( *maxi, *maxj, "CANDIDATE");
1106         }
1107         
1108         if(max_sp ＞ 0){
1109           if(j[ max_sp ] ＜ 8){
1110             j[ max_sp ]++;
1111           }else if(i[ max_sp ] ＜ 8){
1112             i[ max_sp ]++;
1113             j[ max_sp ] = 1;
1114           }        
1115         }
1116       }
1117     }else{
1118       // 注目した座標(i[max_sp],j[max_sp])に既に石があるか,なくても置けないときの処理
1119       if(j[ max_sp ] ＜ 8){
1120         j[ max_sp ]++;
1121       }else if(i[ max_sp ] ＜ 8){
1122         i[ max_sp ]++;
1123         j[ max_sp ] = 1;
1124       }else{
1125         //その手をすべて探索したとき
1126         disp_stack( *maxi, *maxj, "all searched");
1127         if(max[ max_sp ] == 0){
1128           //すべて探索した結果としておけなかったとき
1129           char revturn = (turn[ max_sp ] == ___B___) ? ___W___:___B___;
1130           int m,n,rev_check = 0;
1131           int nokori = 0, rev_nokori = 0;
1132     
1133           disp_stack( *maxi, *maxj, "max[ max_sp ] == 0");
1134           // 番を相手にわたせるかどうか計算
1135           for(m = 1; m ＜= 8; m++)
1136             for(n = 1; n ＜= 8; n++){
1137               char c = get( 8, 8, m, n, status[ max_sp ]);
1138               if(c == ___N___)
1139                 rev_check += pos_check( 0, revturn, 8, 8, m, n, status[ max_sp ]);
1140               else if(c == revturn)
1141                 rev_nokori ++;
1142               else
1143                 nokori ++;
1144             }
1145 
1146           if(rev_check ＞ 0 && max_sp ＜ level){
1147             // 相手の置く場所があり番をわたせるとき
1148             
1149             // 自分のturnはスキップする
1150             i[ max_sp ] = 8;
1151             j[ max_sp ] = 8;
1152 
1153             // turnを交替して探索しなおし
1154             ++max_sp;
1155             turn[ max_sp ] = revturn;
1156             i[ max_sp ] = 1;
1157             j[ max_sp ] = 0;
1158             max[ max_sp ] = 0;
1159 
1160             disp_stack( *maxi, *maxj, "PASS");
1161 
1162           }else{
1163             // ゲームルール上,自分も相手もおける石がなかった場合
1164             if( max_sp == 1){
1165               // １手目で自分も相手もなにもできないとき
1166               disp_stack( *maxi, *maxj, "1 te PASSPASS GAMEOVER");
1167               ;//ゲームオーバー
1168             }else{
1169               disp_stack(  *maxi, *maxj, "max_sp ＞ 1");
1170               // ２手先読みでこの状態に遭遇したとき
1171               if(max_sp == 2 && rev_nokori ＞ nokori){
1172                 // ２手先で両者とも何もできなくなりコールド勝ちになる場合
1173                 *maxi = i[ 1 ];
1174                 *maxj = j[ 1 ];
1175                 //all_1_all_nM1_max_min_max = MUGENP;//この手に決めてしまう
1176                 minmax[ 0 ] = MUGENP;
1177                 first_get = check[ 1 ];
1178                 disp_stack(  *maxi, *maxj, "COLD WIN");
1179               }else{
1180                 // ２手先以上で両者とも何もできなくなり,負けか引き分けのとき
1181                 // 最深読みレベルの評価を計算する
1182                 int sum = 0;
1183                 int k;
1184                 if(IS_STACK_EST){
1185                   for( k = 1; k ＜= max_sp; k++)
1186                     sum += 
1187                       (turn[ k ] == nextturn) ? 
1188                       +(check[ k ]+valxy[i[ k ]][j[ k ]]) :  -(check[ k ]+valxy[i[ k ]][j[ k ]]);
1189                     //+(check[ k ]) :  -(check[ k ]);
1190                 }else{
1191                   int x,y;
1192                   int sumw = 0;
1193                   int numw = 0;
1194                   int sumb = 0;
1195                   int numb = 0;
1196                   for( x = 1; x ＜= 8; x++){
1197                     for( y = 1; y ＜= 8; y++){
1198                       switch(get( 8, 8, x, y, status[ max_sp ])){
1199                       case ___N___: break;
1200                       case ___B___: numw++;sumw += valxy[ x ][ y ]; break;
1201                       case ___W___: numb++;sumb += valxy[ x ][ y ]; break;
1202                       }
1203                     }
1204                   }
1205                   if(numw == 0){
1206                     sumw = MUGENM;
1207                   }
1208                   if(numb == 0){
1209                     sumb = MUGENM;
1210                   }
1211                   sum = (nextturn == ___B___) ? (sumw-sumb):(sumb-sumw);
1212                 }
1213                 disp_stack(  *maxi, *maxj, "LOSEorDRAW-BACKTRACK");
1214                 if(sum ＞ minmax[ max_sp-1 ]){
1215                   // max_sp == 3 or 5 , max_sp-1 == 2 or 4を想定している
1216                   minmax[ max_sp-1 ] = sum;
1217                   disp_stack(  *maxi, *maxj, "LOSEorDRAW-BACKTRACK sum ＞ minmax[ max_sp-1 ]");
1218                 }
1219                 //負けか引き分けになりそうなときの処理終了
1220               }
1221               disp_stack( *maxi, *maxj, "NO GAME at 2 or more");
1222               //２手先読み以上で遭遇した場合終了
1223             }
1224             disp_stack( *maxi, *maxj, "NO GAME at a context");
1225             // ゲームルール上,自分も相手もおける石がなかった場合終了
1226           }
1227           disp_stack( *maxi, *maxj, "NO GAME");
1228           // すべて探索した結果としておけなかったとき終了
1229         }
1230 
1231         //disp_stack(  *maxi, *maxj, "NO TE");
1232 
1233         // 次の候補にポインタを移す
1234         while( j[ max_sp ] == 8 && i[ max_sp ] == 8 && max_sp ＞ 0){
1235           max_sp --;
1236           if(max_sp ％ 2 == 0 && max_sp ＜ level){
1237             if(minmax[ max_sp ] ＜ minmax[ max_sp-1 ]){
1238               minmax[ max_sp-1 ] = minmax[ max_sp ];
1239               disp_stack( *maxi, *maxj, "minmax[ max_sp ] ＜ minmax[ max_sp-1 ]");
1240             }
1241           }
1242           if(max_sp ％ 2 == 1 && max_sp ＜ level){
1243             if(minmax[ max_sp-1 ] ＜ minmax[ max_sp ]){
1244               minmax[ max_sp-1 ] = minmax[ max_sp ];
1245               disp_stack( *maxi, *maxj, "minmax[ max_sp-1 ] ＜ minmax[ max_sp ]");
1246               if( max_sp == 1){
1247                 *maxi = i[ 1 ];
1248                 *maxj = j[ 1 ];
1249                 first_get = check[ 1 ];
1250               }
1251             }
1252           }
1253         }
1254         //disp_stack( *maxi, *maxj, "BACKTRACK AFTER NO-TE");
1255         if(max_sp ＞ 0){
1256           if(j[ max_sp ] ＜ 8){
1257             j[ max_sp ]++;
1258           }else if(i[ max_sp ] ＜ 8){
1259             i[ max_sp ]++;
1260             j[ max_sp ] = 1;
1261           }        
1262         }
1263       }
1264     }
1265   }while( max_sp ＞ 0);
1266 
1267 #ifdef DEBUG
1268 printf( "＜/TABLE＞\n");
1269 #endif
1270 
1271 return first_get
1272 }
1273 
1274 int disp_point( int is_start, int x, int y, char *now_status, char nextturn, double t)
1275 {
1276   int i;
1277   int W = 0;
1278   int R = 0;
1279   char ch;
1280   char name[  256 ];
1281   char *cp;
1282   strcpy( name, CGINAME);
1283   cp= strchr( name, '.');
1284   *cp = '\0';
1285 
1286   for( i = 0; i ＜ 8*8; i++)
1287     {
1288       switch( now_status[ i ]){
1289       case ___N___:       break;
1290 #ifdef IS_NUM
1291       case ___B___: W += valxy[ i ％ 8 + 1 ][ i / 8 + 1 ]; break;
1292       case ___W___: R += valxy[ i ％ 8 + 1 ][ i / 8 + 1 ]; break;
1293 #else
1294       case ___B___: W ++; break;
1295       case ___W___: R ++; break;
1296 #endif
1297       }
1298     }
1299   if(W == R)
1300     ch = '=';
1301   else if(W ＞ R)
1302     ch = '＞';
1303   else 
1304     ch = '＜';
1305   if(nextturn == ___N___)
1306     printf("＜TABLE style=\"width:335px;\" bgcolor=#550000＞＜TR＞＜TD align=center＞＜FONT COLOR=gold SIZE=1＞％.2fs ％s ＜/FONT＞＜FONT color=silver size=3＞＜IMG SRC=\"/icons/black24c.gif\" width=12＞ ％d ％c ＜IMG SRC=\"/icons/white24c.gif\" width=12＞ ％d  → ＜A HREF=\"/cgi-bin/％s\"＞＜IMG SRC=\"/icons/replay.gif\" width=256＞＜/A＞＜FONT＞＜/TD＞＜/TR＞＜/TABLE＞\n", t, name, W, ch, R, CGINAME);
1307   else
1308     printf("＜TABLE style=\"width:335px;\" bgcolor=#550000＞＜TR＞＜TD align=center＞＜FONT COLOR=gold SIZE=1＞％.2fs ％s ＜/FONT＞＜FONT color=silver size=3＞＜IMG SRC=\"/icons/black24c.gif\" width=12＞ ％d ％c ＜IMG SRC=\"/icons/white24c.gif\" width=12＞ ％d  → ＜IMG SRC=\"/icons/％s24e.gif\" width=12＞ ％s＜/FONT＞＜/TD＞＜/TR＞＜/TABLE＞\n", t, name, W, ch, R, (nextturn == ___W___||nextturn == ___w___) ? "white":"black", ((nextturn == ___W___||nextturn == ___w___) || IS_P2P == 1) ? "＜font color=gold size=1＞pls. select＜/font＞":"＜font color=gold size=1＞please wait＜/font＞");
1309 }
1310 
1311 void countup( void)
1312 {
省略
1347 }
1348 
1349 const char codetbl[] = "0123456789ABCDEF";
1350 
1351 int urldecode(char *in, char *out)
1352 {
省略
1380 } 
1381 
1382 int main( int argc, char *argv[])
1383 {
1384   int smode = 1;
1385   int isloop = 1;
1386   char org_status[ 1024 ];
1387   char url_status[ 64 ];
1388 
1389   clock_t start,end;
1390   {
1391     char *cp = strrchr( argv[ 0 ], '/');
1392     strcpy(CGINAME, cp+1);
1393   }
1394   start = clock();
1395 
1396 
1397 
1398   char autonext[ 1024 ] = {""};
1399   char lastturn = ___N___;
1400   char nextturn = ___N___;
1401   int  x,y;
1402   char cfgfilepath[ 1024 ];
1403   char given_status[ 1024 ];
1404   char *cp = getenv("QUERY_STRING"); cp = (cp) ? strcpy( given_status, cp) : NULL; 
1405   char *user = getenv("REMOTE_ADDR");
1406  
1407   value_init( board);
1408   
1409   //自分の色および場所を変数にいれる
1410   if(cp == NULL || *cp == '\0' || *(cp+2)=='h'){
1411 
1412     char buf[ 1024 ];
1413 
1414     if(*(cp+2) =='h'){
1415       char *sp;
1416       char *ep;
1417       int point = 0;
1418       char sname[  64 ];
1419       char scrypt[ 64+1 ];
1420       char ncrypt[ 64+1 ];
1421       char sstat[  64+1 ];
1422 
1423       fgets( buf, 1024, stdin);
1424 
1425 
1426       sp = buf+5;
1427       ep = strchr( sp, '&');
1428       *ep = '\0';
1429       strcpy( sstat, sp);
1430       strcpy( ncrypt, (const char *)mycrypt( sstat));
1431       
1432       sp = ep+7;
1433       ep = strchr( sp, '&');
1434       *ep = '\0';
1435       strcpy( scrypt, sp);
1436 
1437       sp = ep+10;
1438       urldecode( sp, sname);
1439 
1440       if(strlen(sname) ＞ 0 && strcmp( ncrypt, scrypt) == 0){
1441         int num = whitenum( sstat);
1442         char buf[ 256 ]; 
1443         char filename[ 256 ];
1444         char filenamebak[ 256 ];
1445         sprintf( filename, "％s.rank", CGINAME); 
1446         sprintf( filenamebak, "％s.rank.bak", CGINAME); 
1447         unlink( filenamebak);
1448         rename( filename, filenamebak);
1449         FILE *fin = fopen( filenamebak, "rb");
1450         FILE *fout = fopen( filename, "wb");
1451         if(fin){
1452           while( fgets( buf, 256, fin ) ){
1453             char *cp = strchr( buf, ',');
1454             if(cp){
1455               *cp = '\0';
1456               if(atoi( buf) ＜ num){
1457                 fprintf( fout, "％d,％s\n", num, sname);  
1458                 num = 0;
1459               }
1460               fprintf( fout, "％s,％s", buf, cp+1);
1461             }
1462           }
1463         
1464           fclose( fin);
1465           //rename( filenamebak, filename);
1466           fclose( fout);
1467         }
1468       }
1469 
1470     }else{
1471       buf[0] = '\0';
1472     }
1473 
1474     // 引数が得られなかった場合
1475     nextturn = (IS_P2P) ? ___B___:___W___;
1476     x = 0;
1477     y = 0;
1478     disp_head(0, NULL);
1479     strcpy( now_status, init );
1480     disp_point( 1, 0, 0, now_status, nextturn, 0.0f);
1481     strcpy( org_status, now_status);
1482     disp_now( 
1483              nextturn, 
1484              8, 8, now_status, 1, 0, 0, org_status
1485              );
1486     disp_tail(nextturn, user);
1487     exit( 0);
1488   }
1489   
1490 
1491   // 引数を取得する
1492   {
1493     static char buf[ 1024 ];
1494     char *ep;
1495     while(*cp != '=') cp++;
1496     nextturn = *(++cp);
1497     while(*cp != '=') cp++;
1498     ep = strchr( cp, (int)'&');
1499     *ep = '\0'; 
1500     x = atoi( ++cp);
1501 
1502     while(*cp != '=') cp++;
1503     ep = strchr( cp, (int)'&'); 
1504     *ep = '\0'; 
1505     y = atoi( ++cp);
1506 
1507     while(*cp != '=') cp++;
1508 
1509     ++cp;
1510     if(*cp == ___N___ || *cp == ___B___ || *cp == ___W___)
1511       strcpy( now_status, cp);
1512     else
1513       urlcur2cur( now_status, cp);
1514 
1515     ep = strchr( now_status, (int)'&');
1516     if( ep){
1517       *ep = '\0'; 
1518       while(*ep != '=') ep++;
1519       _ADURL = strcpy(buf, ++ep);
1520     }else{
1521       _ADURL = NULL;
1522     }
1523   }
1524 
1525   strcpy( org_status, now_status);
1526  
1527   while( isloop){
1528     int maxi, maxj;
1529 
1530     switch( nextturn){
1531     case ___w___:  // ___w___(置くのみ（波及せず）)  
1532       if(smode == 1){
1533         nextturn = toupper(nextturn);
1534       }else{
省略
1557       }
1558       break;
1559     case ___b___:  // ___b___(推論して置くのみ（波及せず）)  前フェーズで置けることをチェックして、このフェーズに入るようにする
1560       if(smode == 1){
1561         if(IS_P2P){
1562           nextturn = ___B___;
1563         }else{
1564           recursive_all_pos_check(___B___, &maxi, &maxj, now_status, MAX_LOOP);
1565           x = maxi;
1566           y = maxj;
1567           nextturn = ___B___;
1568         }
1569       }else{
省略
1594       }
1595       break;
1596     case ___W___:
1597       {
1598         int isblue = IS_P2P;
1599         pos_check( 1, ___W___, 8, 8, x, y, now_status);
1600         if(all_pos_check(___B___, &maxi, &maxj, now_status) ＞ 0){
1601           //白完(w要求）
1602           nextturn = ___B___;
1603           if(IS_P2P)
1604             disp_head(0, "");
1605           else{
1606             sprintf( autonext, 
1607                      "?t=％c&x=％d&y=％d&s=％s",
1608                      (IS_P2P) ? ___B___:___b___,
1609                      0, 
1610                      0,
1611                      //now_status
1612                      cur2urlcur( url_status, now_status)
1613                      );           
1614             disp_head(1, autonext);
1615           }
1616           disp_point( 0, x, y, now_status, ___B___, 0.0f);
1617         }else{
1618           if(all_pos_check(___W___,  &maxi, &maxj, now_status) ＞ 0){
1619             //青完
1620             disp_head(0, "");
1621             isblue = 1; 
1622             disp_point( 0, x, y, now_status, ___W___, 0.0f);
1623           }else{
1624             //相手も自分もおけなかったとき
1625             nextturn = ___N___;
1626             disp_head(0, "");
1627             disp_point( 0, x, y, now_status, ___N___, 0.0f);
1628           }
1629         }
1630         disp_now( 
1631                  nextturn, 
1632                  8, 8, now_status, isblue, x, y, org_status
1633                  );
1634         disp_tail(nextturn, NULL);
1635         isloop = 0;
1636       }
1637       break;
1638     case ___B___:
1639       if(IS_P2P){
1640         int isblue = 1;
1641         pos_check( 1, ___B___, 8, 8, x, y, now_status);
1642         if(all_pos_check(___W___, &maxi, &maxj, now_status) ＞ 0){
1643           //白完(w要求）
1644           nextturn = ___W___;
1645           disp_head(0, "");
1646           disp_point( 0, x, y, now_status, ___W___, 0.0f);
1647         }else{
1648           if(all_pos_check(___B___,  &maxi, &maxj, now_status) ＞ 0){
1649             //青完
1650             disp_head(0, "");
1651             isblue = 1; 
1652             disp_point( 0, x, y, now_status, ___B___, 0.0f);
1653           }else{
1654             //相手も自分もおけなかったとき
1655             nextturn = ___N___;
1656             disp_head(0, "");
1657             disp_point( 0, x, y, now_status, ___N___, 0.0f);
1658           }
1659         }
1660         disp_now( 
1661                  nextturn, 
1662                  8, 8, now_status, isblue, x, y, org_status
1663                  );
1664         disp_tail(nextturn, NULL);
1665         isloop = 0;
1666       }else{
1667         int isblue = 1;
1668        
1669         //now_status[ (y-1)*8+(x-1) ] = ___N___;
1670         pos_check( 1, ___B___, 8, 8, x, y, now_status);
1671         if(all_pos_check(___W___, &maxi, &maxj, now_status) ＞ 0){
1672           //青完   
1673           disp_head(0, "");
1674           nextturn = ___W___;
1675           end = clock();
1676           disp_point( 0, x, y, now_status, nextturn, ((double)(end-start)/CLOCKS_PER_SEC));
1677         }else{
1678           if(all_pos_check(___B___, &maxi, &maxj, now_status) ＞ 0){
1679             //黒完(w要求) 
1680             sprintf( autonext, 
1681                      "?t=％c&x=％d&y=％d&s=％s",
1682                      ___b___, 
1683                      0, 
1684                      0,
1685                      //now_status
1686                      cur2urlcur( url_status, now_status)
1687                      );
1688             isblue = 0;
1689             disp_head(1, autonext);
1690             end = clock();
1691             disp_point( 0, x, y, now_status, nextturn, ((double)(end-start)/CLOCKS_PER_SEC));
1692           }else{
1693             //相手も自分もおけなかったとき
1694             nextturn = ___N___;
1695             disp_head(0, "");
1696             end = clock();
1697             disp_point( 0, x, y, now_status, nextturn, ((double)(end-start)/CLOCKS_PER_SEC));
1698           }
1699         }
1700         disp_now( 
1701                  nextturn, 
1702                  8, 8, now_status, isblue, x, y, org_status
1703                  );
1704 
1705         disp_tail(nextturn, NULL);
1706         isloop = 0;
1707       }
1708       break;
1709     case ___N___:
1710       {
1711         disp_head(0, "");
1712         disp_point( 0, x, y, now_status, nextturn, 0.0f);
1713         disp_now( 
1714                  nextturn, 
1715                  8, 8, now_status, 0, x, y, org_status
1716                  );
1717         disp_tail(nextturn, NULL);
1718         isloop = 0;
1719       }
1720       break;
1721     }
1722   }
1723 }
【産業上の利用可能性】
【００３７】
本発明は、広くゲーム産業、知育産業、教育産業、ボケ防止等に利用可能である。
【図面の簡単な説明】
【００３８】
【図１】本発明の一実施形態により国盗りゲームの利害構造を備えたハイスコア合計ランキングを表示する画面の説明図である。
【図２】本発明の一実施形態により壁や柱を配置しかつ壁や柱に関連する座標の状況（海、湖、山等）を表示した画面の説明図である。
【図３】本発明の一実施形態において壁や柱を例示的に配置してゲームのルールを示した画面の説明図である。
【符号の説明】
【００３９】
ｔｏｔｔｏｒｉ１    鳥取県の行政区画（県の形）をモチーフにしたゲームへのリンク
ｗａｋａｙａｍａ１    和歌山県の行政区画（県の形）をモチーフにしたゲームへのリンク
ｙｏｓｈｉ    ゲームの利用者１（ハイスコア合計が最高の利用者）
ＫＮ    ゲームの利用者２（ハイスコア合計が４位の利用者）
○    コンピュータ相手のモードにおいて利用者が現在のゲーム状態で駒（白）をおける場所
小さい点    柱
横棒  横の壁（縦方向のはさむ力を遮断する）
縦棒  縦の壁（横方向のはさむ力を遮断する）
【図１】
2007135613.tif 000003
【図２】
2007135613.tif 000004
【図３】
2007135613.tif 000005