SSブログ

フナ、クジラ、ヒトデ、ホッケ 仲間外れは? [HEX]

Excel は内部で Unicode を使うように構成されているらしい。ところが、Excel が吐く CSV のファイルは Shift-JIS なので、ここで文字コードの変換が行われる。Unicode と Shift-JIS で扱える文字集合が同じなら問題はないだろうけど、残念ながらそんなことはない。Unicode にあって Shift-JIS に無い文字はどう頑張っても表すことができない。

JIS 第三水準、第四水準に含まれるの多く(全てではないようです)は Shift-JIS に含まれないし、JIS に含まれないハングル文字のようなものも Shift-JIS では表せない。

Excel のセルに上記のような文字が含まれている場合でも、標準のワークブックの形式(.xlsx や .xls)で保存すれば問題なく使えるはず。問題になるのは CSV 形式で保存しようとした場合に限るということ。

今回は、Excel のワークブックにアクセスして CSV ファイルを自前で作ってしまうことを考える。その場合いくつかの方法があるのだけれど、

  1. Excel のマクロを使用する
  2. ADO を使用して、Excel のテーブルデータを読み出す
  3. オートメーションを使用して外部のプログラムから Excel のセルの情報を読み出す

どれも一長一短があり、常にどれかが優位になるというものではないのだけれど、今回はオートメーションを使ってみることにしよう。マクロを使用するには Excel を起動しないとならないし、ADO では綺麗に整列されたテーブルでないと使えないという点を考慮した結果の選択です。ただ、オートメーションは遅いという難点があるのですが...。

さて、タイトルのなぞなぞの答えですが、全ての選択肢で仲間外れになる要素を 1 つ以上持っているはず。ただ、今回のネタに合わせたものでは、ホッケだけが SHIFT-JIS 外の漢字という事です。


CSV [HEX]

経路探索を試してみたいのだけど、そのためにはチョット準備が必要。ユニットの可動範囲を条件に加えてやらないといけないのと、地形による移動コストを加味しておきたい。なので、この時点で最低限のマップ情報を構築してしまおうと思う。

マップ情報は Excel で作るということだけは決めたのだけど、データをどうやって取ってくるかを考えておきたい。最終的に出来上がったマップは Excel 以外の形式に変換するつもりではあるけど、現時点では簡単に読み書きできる形式であつかうことにする。

どんな形式が簡単かって言うと、先ず筆頭に挙げられるのが CSV。単純なテキスト形式だし、.NET Framework のサポートもあるのだけど、ちょっとした問題がある。実は、Excel が吐く CSV のファイルは Shift-JIS しか選べない。開発者リファレンスを見ると VBA を使うとコードページの指定が可能なようなんだけど、「無視される」と書いてあるので使いものにはならない。マップ情報だけなので、Shift-JIS 外の文字を使うことはないと思うのだけど、多少の日本語は入ると踏んでいる。

CSV で作られたマップ情報をプログラムから操作するのは当然なんだけど、別の応用もしたいと思っている。PowerShell から CSV を操作することで、ちょっとした解析をしたいと思うのだけど、PowerShell のコマンドレットは Shift-JIS の CSV を正しく扱えない。web を探してみるといくつかの解決策は公開されているものの CSV の仕様を満たさないものが多いようだ。

ここで言っている仕様というのは、RFC で公開されている仕様というわけではなく、Excel が読み書きできる CSV の仕様という意味。

望むものがないなら自分で作るしかないか、、、とは言ってもそんな面倒なものではない。Excel と PowerShell の連携で、希望のものを意外に簡単に手に入れる方法がある。次回は、PowerShell を使った CSV の作り方 前篇です。

 


距離 [HEX]

さて、比較する 2 点の座標が決まれば距離を求めるのは難しくない。ピタゴラスの定理をそのまま当てはめればいいわけで、2点の座標をを (x0, y0)と(x1, y1) とするなら、

d = √(x1-x0)2+(y1-y0)2 

 で求めることができる。ただし、ここでは実際に距離が知りたいわけではなく、特定の射程に収まるかどうかが知りたいだけなので、式を下記のように変形してしまうのが得策。

 d2 = (x1-x0)2+(y1-y0)2 

 大抵のプロセッサは除算が大の苦手、それに対して乗算は(加減算ほどではないけど)結構速い。繰り返し実行されるような処理ならば、除算はない方がいい。

除算を減らす鉄則のようなものも色々あるので、機会があったら紹介します。

射程を求めることができたので、これをそのまま ZOC に適用しよう。そうすることで経路探索における移動コストに応用することが可能になるから。

こう言っちゃなんだけど、経路探索の方がいろいろと条件を組み合わせられるので面白いところが多い。射程に関しては経路探索のためのネタ作りの一環のようなもの。

ということで、次回は経路探索の条件について考察します。

 


正六角形 [HEX]

ヘックスマップは本来正六角形を並べて作るものなのだろう。少なくとも見かけはその方がきれいに見える。Hexmap05.png

ココでは Excel で(適当に)作ったヘックスマップを扱っているために若干の誤差が出ている。そのからくりを考察してみる。

同じ額面の硬貨を 7 枚、互いに接するように並べた状態(左図)がヘックスの構成になる。

WikiPedia では円に内接する六角形ということで作図の説明がされている(2014-10-09 時点)けれど、ヘックスマップの場合、外接する六角形の方がわかりやすいかもしれない。

円(六角形)の中心の位置関係を考えてみる。今、円の半径を r とした場合、任意の円と、それに接する円の中心点を結ぶ線分の長さは 2r となる。六角形が図のような向き(2 辺が X 軸に平行になるような)に配置した場合、任意の六角形の上あるいは下に接する六角形は X 座標の値は変わらず、Y 座標の値が ±2r の位置に配置される。

では、それ以外はどうなる?簡単なのは Y 座標、必ず ±r の値になるはず。直角三角形の斜辺の長さがが 2r、他の 1 辺の長さが r とわかっているなら、残る 1 辺は r√3 になるのはピタゴラスの定理より求められる。

Excel で作った似非ヘックスマップでは、円とそれに接する円の X 方向距離が 1.5r となっていることから、どうしても歪みが出てしまう。Excel でヘックスマップを作った理由は、ヘックスマップの属性値を Excel で作るということだったので、図の精度に関しては取り敢えず目を瞑ることにする。

Excel で作ったヘックスマップは、 r/2 を Excel のセルの幅および高さに合わせているため、こんな数値になっている。

歪みの原因が解ったところで、次回から本題である射程についての考察を続けることにしよう。


射程 [HEX]

今回は予告通り射程の話。地形に関わらず 2 点間の距離を求めることで攻撃が可能か否かを判断する時に使う計算。ZOC(Zone Of Control) の判定も同様のはず。Hexmap03.png

今、ヘックスマップ上の 3,7 のセルから、射程が 3 となるセルを探すことを考える。当該セルと射程 3 の位置がわかるようにシェイプをはりつけておいた。若干縦長に見えるのは錯覚ではない。

「ヘックスの中心が射程内にあれば攻撃可能」という考え方をするのであれば、中心のセルの座標とターゲットのセルの座標から距離を求めて、それを判定するのが手っ取り早い方法だろう。

若干面倒なのが、「射程 3 の位置にだけ攻撃できる」ような間接攻撃専門のユニットの場合。図を見ると 3,1 の位置にあるセルは、その中心が円周上にあるのに対して、4,2 の位置のセルは円周の内側にいる。

実は、3,1、6,4、6,10、3,13、0,10、0,4 の 6 点は円周上にいる。そして残りの点は、この 6 点を結んでできる 六角形の辺の上に配置されているはず。

このヘックスマップを作るのに必要は計算はすべて整数演算で済ませている。まともに描画するならπや平方根のお世話になるはずなんだけど、ここでは背景にうっすらと見えているマス目の数だけで描画してしまっている。なにしろ、ヘックスマップを Excel の罫線で書いているのでこれ以外の単位を使うことができないからね...。

3,7 のセルから 3,1 のセルまでの距離は 12 マス分であり、これが射程 3 の円の半径ということになる。各セルまでの距離を求めて、この値以下になるようなら「射程 3 以内」と判断する方法がひとつ目。

射程 3 のセルだけを探すには、3,7 のセルから 3,3 のセルまでの距離を求め、これを射程 2 の半径とする。目的のセルは射程 3 の範囲に含まれ、且つ、射程 2 の範囲に含まれないものが該当する。

次回は、実際の計算方法について考察する予定。多分、土日は多分更新しないので、公開するのは月曜日になります。


座標系 [HEX]

昨日の段階で、ヘックスマップを Excel に表示するところまではできているんで、マップ上のセルに座標(番号)をつけておきたいと思う。最終的な成果物で座標が必要になることはないと思うのだけど、ヘックスマップを見ながら検討するような場合に、何か目印になるようなものがあった方が便利だよね。Hexmap02.png

座標の振り方は単純にしよう。左上を原点にして、右あるいは下に行くにしたがって数値が増えていくような感じ。表記は X 座標, Y座標の並びとする。

ゼロから始まるのがなんとなく一般的ではなく変な感じもするけど、今のところはこれで良しとしよう。

さて、この座標値を眺めてみるといくつかの特徴が見えてくる。

  • 座標値は常に、偶数,偶数か奇数,奇数となる。偶数,奇数や奇数,偶数という組み合わせは存在しない。このサンプルは 8 × 16 のサイズなので、普通に数えると 128 セルあるはずなのだけど、実際に使用するセルは丁度半分の 64 しかない。
  • 任意のセルを考えた場合、隣接するセルとの位置関係は常に等しくなる。たとえば、上に隣接するセルは、X,Y-2 の座標値を持つことがわかる。

ひとつめの特徴から、このヘックスマップのメモリ使用量がある程度削れることがわかる。ふたつめの特徴からは、これから先に現れることになる各種のアルゴリズム(経路探索やら射程の判定やら)に、多少係数をかけることはあるかもしれないけど座標値をそのまま利用できるかもしれないと予想できる。

 各種アルゴリズムの話は次回以降にするとして、ヘックスマップの管理方法を簡単にかたずけてしまおう。

特に難しい話じゃない。図にある座標値の X 成分はそのまま、Y 成分を 2 で割った値(小数点以下は切り捨てる)を考える。出来上がった値を配列のインデックスとして扱えば、面倒くさそうに見えるヘックスマップを単純な二次元配列で表すことができてしまうことがわかる。

ヘックスマップ上の 2 点を考える場合、ウォー・シミュレーションでは 2 つの計測の方法が考えられる。自分のユニットから相手のユニットを攻撃する際の射程と、自分のユニットを特定のセルまで移動させる道程の考え方。ただ、現時点で後者の道程に関する考察をするには少しばかり情報が足りない。ユニットの属性(移動量)や地形の属性の検討ののちということになる。

ということで、次回は射程の考え方です。


六角形 [HEX]

何年か前に、ウォー・シミュレーションゲームに興味をもったことがある。当時は、作ったものを動かす環境に適当なものが見つからず挫折してしまったのだけど、最近になっていろいろと面白そうなものが見つかったおかげで興味が再燃してしまった。

ゲームといっても、シナリオやデザイン、アニメーションについては門外漢なので、純粋に実装に関わるアルゴリズム限定で考察していきたいと思う。

まず手始めに、フィールドの形状から。ここでは、タイトルの通りヘックス(六角形)のセルを並べたヘックスマップで進めて行くことにする。スクエアのセルよりもヘックスのセルの方がウォー・シミュレーションっぽいかなぁという、とんでもなくいい加減な理由からだったりする。

ヘックスマップを採用すると決めるところまでは簡単なのだけど、いきなりハードルが表れてしまう。市販のゲームで遊ぶだけならいいのだけれど、自作するとなるとマップも自作しなければならない。ただ、汎用のヘックスマップエディタのようなものの存在をあてにはできないので、なんとか手持ちのもので代用してしまいたい。エディタ作っても、あまり面白そうじゃないので、そこは考えないことにする。

私の場合、「GUIを使って編集」とか「汎用の...」といったキーワードが出てくると、思考が殆ど Excel 一択になってしまう。一応、要件としては...

  • ヘックスマップを表示できること
    六角形のセルをイメージだけで検討するのはつらい。中身は大したことがなくても、見た目がなんとかなれば、かなりの成果が出るものと考える。
  • 作成したデータを取り出せること
    作ったデータを見てるだけじゃ意味がない。オンラインでもオフラインでも構わないので、出来上がったデータの幾何情報以外の情報を取り出したい。
  • 印刷できること
    紙にすることにはこだわらないのだけど、手書きでメモをつけられるようにしたい。OneNote あたりと連携してもいいかもしれない。

ただ、すべてを盛り込もうとすると、どうしても無理が出てくるような気がする。大勢に影響のないところは譲歩してしまってもいいだろう。

  • 正確な描画は期待しない
    Excel はあくまでもスプレッドシートなので、ここにきれいなイメージを貼るようなことは考えないでおく。また、六角形にもこだわらないことにする。

本当は地形の違いを色分けできたらいいとも思うのだけれど、シェイプを使うようなアプローチをとるとセルに情報を埋めにくくなってしまいそうなので、とりあえず我慢。

どんな感じになるか、試しに作ってみたのがコレ。Hexmap01.png

Excel 方眼紙(正式名称ではないよね)を作った上で、罫線だけで作図してみた。セルのサイズを変えてしまうと形状が崩れてしまうという難点はあるものの、意外なほど簡単にできる。既にマクロにしてしまってるし。

また、上述の通り正六角形にはなっていない(計算では斜めの線が横線より 1 割程度長くなる)けど、気にしないことにした。実は、そのおかげで六角形のレンダリングに必要になる頂点座標を求める工程がすべて簡単な整数演算で済むようになるというメリットが生まれるから。

 このヘックスマップを構築するマクロ、ブログを更新しながら作ってたわけじゃない...って、そりゃそうだよね。数日前に完成していたものなんだけど、ちょっとした落とし穴がある。そして、その落とし穴にはまったのが自分自身だという情けないオチまでついている。

オチについては追々紹介することになると思う。ウォー・シミュレーションには欠かせない機能に関わるものなのでね。

ということで、今日の更新はココまで。次回は、このヘックスマップをプログラムからどう扱うかを考察してみたい。


この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。