「乱数」を含む日記 RSS

はてなキーワード: 乱数とは

2012-11-28

破綻しないバトルバランス

カードゲームコンピュータゲームをやっているとたまに思うことをまとめたいと思う。

さまざまなゲームヒットポイント通称HPライフとも体力とも)、マジックポイント(通称MPマナ、エナジー、リソースとも)という概念が使われているのだが、この関係をよくよく考え直してみるとバトルバランスは数式(のようなもの)で書き表すことができるのではないだろうか?

まず、ゲームのバトルとは基本的に「自分MPを使って行動を行い、相手のHPゼロにする」ことを目的としている。まずはここからスタートしよう。

議論の簡単化のため、まずは連続時間リアルタイムバトルではなく離散時間のターン制バトルとし、ターン内のMPを使用した行動は完全に同時に終了することにする。

さて、まずメラ(仮)という行動を導入してみよう。このメラという行動は自分MPを1消費して、相手のHPを1減らすという行動になる。

  • A(100, 100) vs. B(100, 100) [Aのメラ]→ A(100, 99) vs. B(99, 100)
  • A(100, 99) vs. B(99, 100) [Bのメラ]→ A(99, 99) vs. B(99, 99)

こんな感じだ。さて今ゲーム目的は相手のHPゼロにすることであるから、AもBも相手のHPゼロになるまでメラを打ち続けることが最適行動である。この行動を続けていくと必ず次のような状態で収束するだろう。

  • A(0,0) vs. B(0,0)

AもBも勝利条件を満たしているが、勝敗が付いていない。しかも何回やっても勝敗が付かない。これはバトルバランスとしては破綻してはいないだろうか?

破綻しないバトルバランスの第1条件「バトルは常に勝敗が決しなければならない」

さて、この条件を満たすためにメラという操作に工夫を加えることはできないだろうか?すぐに思いつく方法ダメージを固定値ではなく乱数である程度の幅を持たせることである。こうすれば期待値では互角であっても引き分けになる確率はかなり下がる。よってこのバトルバランス破綻していない!

・・・しかちょっと待ってほしい。このバトルバランス破綻していないと本当に言えるのだろうか?抽選の揺らぎの積み重ねだけで果たして本当にAとBは「相手に勝った・負けた」と納得できるだろうか?答えはノーだと自分は考えている。

破綻しないバトルバランスの第2条件「乱数抽選の揺らぎのみによって勝敗が決してはならない」

この第二条件を満たすためによく採用されるのが回復という行動だ(以下ホイミ(仮)とする)。この行動はメラとは逆に自分MPを消費して自分HPを増加させる行動である。A、Bはこの行動を適宜行うことで相手の行動を阻害することが可能になる。

しかしこのホイミはメラの完全に逆の操作であるために、Aがメラをし続けBがホイミをし続けてしまうと:

  • A(100, 100) vs. B(100, 100) [Aのメラ]→ A(100, 99) vs. B(99, 100)
  • A(100, 99) vs. B(99, 100) [Bのホイミ]→ A(100, 99) vs. B(100, 99)

以下の状況に収束する。

  • A(100, 0) vs. B(100, 0)

両者も勝利条件を満たせず、MPが尽きるという事態が発生する。これは第一条件にも反するし、別の条件としても書き下せるだろう。

破綻しないバトルバランスの第3条件「誰も何もできない状況を作ってはならない」

(以下自分の手元と頭の中で続く。たぶん不変条件としてバトルバランスが綺麗に書けるはず……)

2012-07-30

Island Life - 模範解答と過剰適応

極端な話、「±5点くらい完全にランダムオフセットを加算してから 合否を決めます」くらい最初に宣言しておいた方が、点数にこだわる人が減って良いかもしれない。


Twitter / alohakun: 大学入試とかの点数に、乱数でプラマイ 10 点ぐらい ...

大学入試とかの点数に、乱数プラマイ 10 点ぐらい足した後に合否判定するって良いアイデアだと思う。バツグンとゼンゼンダメな人には影響無いし、ボーダー付近合格した人も不合格だった人も、必要以上に点数にシリアスにならないで済む。全ては時の運なのだ

2012-05-20

http://anond.hatelabo.jp/20120520172658

単語じゃねーよwwwwバカだな、お前はwwww

ただの乱数として1文字ずつ組み合わせて送ってんだからかんけーねーっつってんだろwwwwww

これだから低能はwwww

2011-12-12

コンピュータプログラミング概念技法モデル」の目次

第1章 プログラミング概念入門
	1.1 計算器
	1.2 変数
	1.3 関数
	1.4 リスト
	1.5 リストについての関数
	1.6 プログラムの正しさ
	1.7 計算量
	1.8 遅延計算
	1.9 高階プログラミング
	1.10 並列性
	1.11 データフロー
	1.12 明示的状態
	1.13 オブジェクト
	1.14 クラス
	1.15 非決定性と時間
	1.16 原子性
	1.17 ここからどこへ行くのか?
	1.18 練習問題

第1部 一般的計算モデル

第2章 宣言的計算モデル
	2.1 実用プログラミング言語定義
		2.1.1 言語の構文
		2.1.2 言語意味
	2.2 単一代入格納域
		2.2.1 宣言的変数
		2.2.2 値格納域
		2.2.3 値生成
		2.2.4 変数識別子
		2.2.5 識別子を使う値生成
		2.2.6 部分値
		2.2.7 変数の,変数への束縛
		2.2.8 データフロー変数
	2.3 核言語
		2.3.1 構文
		2.3.2 値と型
		2.3.3 基本型
		2.3.4 レコード手続き
		2.3.5 基本操作
	2.4 核言語意味
		2.4.1 基本概念
		2.4.2 抽象マシン
		2.4.3 待機不能な文
		2.4.4 待機可能な文
		2.4.5 基本概念再訪
	2.5 メモリ管理
		2.5.1 末尾呼び出し最適化
		2.5.2 メモリライフサイクル
		2.5.3 ガーベッジコレクション
		2.5.4 ガーベッジコレクションは魔術ではない
		2.5.5 Mozartのガーベッジコレクタ
	2.6 核言語から実用言語へ
		2.6.1 構文上の便宜
		2.6.2 関数(fun文)
		2.6.3 対話的インターフェース(declare文)
	2.7 例外
		2.7.1 動機と基本概念
		2.7.2 例外を持つ宣言的モデル
		2.7.3 親言語の構文
		2.7.4 システム例外
	2.8 進んだ話題
		2.8.1 関数型プログラミング言語
		2.8.2 単一化と内含(entailment)
		2.8.3 動的型付けと静的型付け
	2.9 練習問題

第3章 宣言的プログラミング技法
	3.1 宣言的とはどういうことか?
		3.1.1 宣言的プログラムの分類
		3.1.2 仕様記述言語
		3.1.3 宣言的モデルにおいてコンポーネントを実装すること
	3.2 反復計算
		3.2.1 一般的図式
		3.2.2 数についての反復
		3.2.3 局所的手続きを使うこと
		3.2.4 一般的図式から制御抽象へ
	3.3 再帰計算
		3.3.1 スタックの大きさの増加
		3.3.2 代入ベース抽象マシン
		3.3.3 再帰計算を反復計算に変換すること
	3.4 再帰を用いるプログラミング
		3.4.1 型の記法
		3.4.2 リストについてのプログラミング
		3.4.3 アキュムレータ
		3.4.4 差分リスト
		3.4.5 キュー
		3.4.6 木
		3.4.7 木を描画すること
		3.4.8 構文解析
	3.5 時間効率空間効率
		3.5.1 実行時間
		3.5.2 メモリ使用量
		3.5.3 償却的計算量
		3.5.4 性能についての考察
	3.6 高階プログラミング
		3.6.1 基本操作
		3.6.2 ループ抽象
		3.6.3 ループ言語的支援
		3.6.4 データ駆動技法
		3.6.5 明示的遅延計算
		3.6.6 カリー化
	3.7 抽象データ型
		3.7.1 宣言的スタック
		3.7.2 宣言的辞書
		3.7.3 単語出現頻度アプリケーション
		3.7.4 安全抽象データ型
		3.7.5 安全な型を備えた宣言的モデル
		3.7.6 安全な宣言的辞書
		3.7.7 資格セキュリティ
	3.8 宣言的でない必要物
		3.8.1 ファイルを伴うテキスト入出力
		3.8.2 グラフィカルユーザインタフェースを伴うテキスト入出力
		3.8.3 ファイルとの状態なしデータI/O
	3.9 小規模プログラム設計
		3.9.1 設計方法
		3.9.2 プログラム設計の例
		3.9.3 ソフトウェアコンポーネント
		3.9.4 スタンドアロンプログラムの例
	3.10 練習問題

第4章 宣言的並列性
	4.1 データ駆動並列モデル
		4.1.1 基本概念
		4.1.2 スレッド意味
		4.1.3 実行列
		4.1.4 宣言的並列性とは何か?
	4.2 スレッドプログラミングの基本的技法
		4.2.1 スレッドを生成すること
		4.2.2 スレッドブラウザ
		4.2.3 スレッドを使うデータフロー計算
		4.2.4 スレッドスケジューリング
		4.2.5 協調的並列性と競合的並列性
		4.2.6 スレッド操作
	4.3 ストリーム
		4.3.1 基本的生産者消費者
		4.3.2 変換器とパイプライン
		4.3.3 資源管理し,処理能力改善すること
		4.3.4 ストリームオブジェクト
		4.3.5 ディジタル論理シミュレーション
	4.4 宣言的並列モデルを直接使うこと
		4.4.1 順序決定並列性
		4.4.2 コルーチン
		4.4.3 並列的合成
	4.5 遅延実行
		4.5.1 要求駆動並列モデル
		4.5.2 宣言的計算モデル
		4.5.3 遅延ストリーム
		4.5.4 有界バッファ
		4.5.5 ファイルを遅延的に読み込むこと
		4.5.6 ハミング問題
		4.5.7 遅延リスト操作
		4.5.8 永続的キューアルゴリズム設計
		4.5.9 リスト内包表記
	4.6 甘いリアルタイムプログラミング
		4.6.1 基本操作
		4.6.2 ティッキング(ticking)
	4.7 Haskell言語
		4.7.1 計算モデル
		4.7.2 遅延計算
		4.7.3 カリー化
		4.7.4 多態型
		4.7.5 型クラス
	4.8 宣言的プログラム限界拡張
		4.8.1 効率性
		4.8.2 モジュラ性
		4.8.3 非決定性
		4.8.4 現実世界
		4.8.5 正しいモデルを選ぶこと
		4.8.6 拡張されたモデル
		4.8.7 異なるモデルを一緒に使うこと
	4.9 進んだ話題
		4.9.1 例外を持つ宣言的並列モデル
		4.9.2 さらに遅延実行について
		4.9.3 通信チャンネルとしてのデータフロー変数
		4.9.4 さらに同期について
		4.9.5 データフロー変数有用性
	4.10 歴史に関する注記
	4.11 練習問題

第5章 メッセージ伝達並列性
	5.1 メッセージ伝達並列モデル
		5.1.1 ポート
		5.1.2 ポート意味
	5.2 ポートオブジェクト
		5.2.1 NewPortObject抽象
		5.2.2 例
		5.2.3 ポートオブジェクトに関する議論
	5.3 簡単なメッセージプロトコル
		5.3.1 RMI(遠隔メソッド起動)
		5.3.2 非同期RMI
		5.3.3 コールバックのあるRMI(スレッド使用)
		5.3.4 コールバックのあるRMI(継続のためのレコード使用)
		5.3.5 コールバックのあるRMI(継続のための手続き使用)
		5.3.6 エラー報告
		5.3.7 コールバックのある非同期RMI
		5.3.8 二重コールバック
	5.4 並列性のためのプログラム設計
		5.4.1 並列コンポーネントを使うプログラミング
		5.4.2 設計方法
		5.4.3 並列性パターンとしての機能的構成要素
	5.5 リフト制御システム
		5.5.1 状態遷移図
		5.5.2 実装
		5.5.3 リフト制御システムの改良
	5.6 メソッド伝達モデルを直接使用すること
		5.6.1 1つのスレッドを共有する複数のポートオブジェクト
		5.6.2 ポートを使う並列キュー
		5.6.3 終点検出を行うスレッド抽象
		5.6.4 直列依存関係の除去
	5.7 Erlang言語
		5.7.1 計算モデル
		5.7.2 Erlangプログラミング入門
		5.7.3 receive操作
	5.8 進んだ話題
		5.8.1 非決定性並列モデル
	5.9 練習問題

第6章 明示的状態
	6.1 状態とは何か?
		6.1.1 暗黙的(宣言的)状態
		6.1.2 明示的状態
	6.2 状態とシステム構築
		6.2.1 システムの性質
		6.2.2 コンポーネントベースプログラミング
		6.2.3 オブジェクト指向プログラミング
	6.3 明示的状態を持つ宣言的モデル
		6.3.1 セル
		6.3.2 セル意味
		6.3.3 宣言的プログラミングとの関係
		6.3.4 共有と同等
	6.4 データ抽象
		6.4.1 データ抽象組織する8つの方法
		6.4.2 スタックの変種
		6.4.3 多態性
		6.4.4 引数受け渡し
		6.4.5 取り消し可能資格
	6.5 状態ありコレクション
		6.5.1 インデックス付きコレクション
		6.5.2 インデックス付きコレクションを選ぶこと
		6.5.3 その他のコレクション
	6.6 状態に関する推論
		6.6.1 不変表明
		6.6.2 例
		6.6.3 表明
		6.6.4 証明規則
		6.6.5 正常終了
	6.7 大規模プログラム設計
		6.7.1 設計方法
		6.7.2 階層システム構造
		6.7.3 保守性
		6.7.4 将来の発展
		6.7.5 さらに深く知るために
	6.8 ケーススタディ
		6.8.1 遷移的閉包
		6.8.2 単語出現頻度(状態あり辞書を使用する)
		6.8.3 乱数を生成すること
		6.8.4 口コミシミュレーション
	6.9 進んだ話題
		6.9.1 状態ありプログラミング限界
		6.9.2 メモリ管理と外部参照
	6.10 練習問題

第7章 オブジェクト指向プログラミング
	7.1 継承
	7.2 完全なデータ抽象としてのクラス
		7.2.1 例
		7.2.2 この例の意味
		7.2.3 クラスオブジェクト定義すること
		7.2.4 クラスメンバ
		7.2.5 属性初期化すること
		7.2.6 第1級メッセージ
		7.2.7 第1級の属性
		7.2.8 プログラミング技法
	7.3 漸増的データ抽象としてのクラス
		7.3.1 継承グラフ
		7.3.2 メソッドアクセス制御(静的束縛と動的束縛)
		7.3.3 カプセル化制御
		7.3.4 転嫁委任
		7.3.5 内省
	7.4 継承を使うプログラミング
		7.4.1 継承の正しい使い方
		7.4.2 型に従って階層を構成すること
		7.4.3 汎用クラス
		7.4.4 多重継承
		7.4.5 多重継承に関するおおざっぱな指針
		7.4.6 クラス図の目的
		7.4.7 デザインパターン
	7.5 他の計算モデルとの関係
		7.5.1 オブジェクトベースプログラミングコンポーネントベースプログラミング
		7.5.2 高階プログラミング
		7.5.3 関数分解と型分解
		7.5.4 すべてをオブジェクトにすべきか?
	7.6 オブジェクトシステムを実装すること
		7.6.1 抽象図
		7.6.2 クラスを実装すること
		7.6.3 オブジェクトの実装
		7.6.4 継承の実装
	7.7 Java言語(直列部分)
		7.7.1 計算モデル
		7.7.2 Javaプログラミング入門
	7.8 能動オブジェクト
		7.8.1 例
		7.8.2 NewActive抽象
		7.8.3 フラウィウス・ヨセフスの問題
		7.8.4 その他の能動オブジェクト抽象
		7.8.5 能動オブジェクトを使うイベントマネージャ
	7.9 練習問題

第8章 状態共有並列性
	8.1 状態共有並列モデル
	8.2 並列性を持つプログラミング
		8.2.1 さまざまな手法概観
		8.2.2 状態共有並列モデルを直接使うこと
		8.2.3 原子アクションを使うプログラミング
		8.2.4 さらに読むべき本
	8.3 ロック
		8.3.1 状態あり並列データ抽象を構築すること
		8.3.2 タプル空間(Linda)
		8.3.3 ロックを実装すること
	8.4 モニタ
		8.4.1 定義
		8.4.2 有界バッファ
		8.4.3 モニタを使うプログラミング
		8.4.4 モニタを実装すること
		8.4.5 モニタの別の意味
	8.5 トランザクション
		8.5.1 並列性制御
		8.5.2 簡易トランザクションマネージャ
		8.5.3 セルについてのトランザクション
		8.5.4 セルについてのトランザクションを実装すること
		8.5.5 トランザクションについてさらに
	8.6 Java言語(並列部分)
		8.6.1 ロック
		8.6.2 モニタ
	8.7 練習問題

第9章 関係プログラミング
	9.1 関係計算モデル
		9.1.1 choice文とfail文
		9.1.2 探索木
		9.1.3 カプセル化された
		9.1.4 Solve関数
	9.2 別の例
		9.2.1 数値例
		9.2.2 パズルとnクイーン問題
	9.3 論理プログラミングとの関係
		9.3.1 論理論理プログラミング
		9.3.2 操作意味論理意味
		9.3.3 非決定性論理プログラミング
		9.3.4 純粋Prologとの関係
		9.3.5 他のモデルにおける論理プログラミング
	9.4 自然言語構文解析
		9.4.1 簡単な文法
		9.4.2 この文法に従う構文解析
		9.4.3 構文木を生成すること
		9.4.4 限定記号を生成すること
		9.4.5 パーサを走らせること
		9.4.6 パーサを「逆向きに(backward)」走らせること
		9.4.7 単一化文法
	9.5 文法インタプリタ
		9.5.1 簡単な文法
		9.5.2 文法のコード化
		9.5.3 文法インタプリタを走らせること
		9.5.4 文法インタプリタを実装すること
	9.6 データベース
		9.6.1 関係を定義すること
		9.6.2 関係を使って計算すること
		9.6.3 関係を実装すること
	9.7 Prolog言語
		9.7.1 計算モデル
		9.7.2 Prologプログラミング入門
		9.7.3 Prologプログラムを関係プログラム翻訳すること
	9.8 練習問題

第2部 特殊化された計算モデル10グラフィカルユーザインタフェースプログラミング
	10.1 宣言的/手続き的方法
	10.2 宣言的/手続き的方法を使うこと
		10.2.1 基本的ユーザインタフェースの要素
		10.2.2 GUIを構築すること
		10.2.3 宣言的座標
		10.2.4 リサイズ時の宣言的振る舞い
		10.2.5 ウィジェットの動的振る舞い
	10.3 対話的学習ツールPrototyper
	10.4 ケーススタディ
		10.4.1 簡単なプログレモニタ
		10.4.2 簡単なカレンダウィジェット
		10.4.3 ユーザインタフェースの動的生成
		10.4.4 状況順応時計
	10.5 GUIツールを実装すること
	10.6 練習問題

第11章 分散プログラミング
	11.1 分散システムの分類
	11.2 分散モデル
	11.3 宣言的データの分散
		11.3.1 オープン分散と大域的ネーミング
		11.3.2 宣言的データを共有すること
		11.3.3 チケット配布
		11.3.4 ストリーム通信
	11.4 状態の分散
		11.4.1 単純状態共有
		11.4.2 分散字句的スコープ
	11.5 ネットワークアウェアネス
	11.6 共通分散プログラミングパターン
		11.6.1 静的オブジェクトモバイルオブジェクト
		11.6.2 非同期的オブジェクトデータフロー
		11.6.3 サーバ
		11.6.4 クローズド分散
	11.7 分散プロトコル
		11.7.1 言語実体
		11.7.2 モバイル状態プロトコル
		11.7.3 分散束縛プロトコル
		11.7.4 メモリ管理
	11.8 部分的失敗
		11.8.1 失敗モデル
		11.8.2 失敗処理の簡単な場合
		11.8.3 回復可能サーバ
		11.8.4 アクティブフォールトトレランス
	11.9 セキュリティ
	11.10 アプリケーションを構築すること
		11.10.1 まずは集中,後に分散
		11.10.2 部分的失敗に対処すること
		11.10.3 分散コンポーネント
	11.11 練習問題

第12章 制約プログラミング
	12.1 伝播・探索法
		12.1.1 基本的考え方
		12.1.2 部分情報を使って計算すること
		12.1.3 例
		12.1.4 この例を実行すること
		12.1.5 まとめ
	12.2 プログラミング技法
		12.2.1 覆面算
		12.2.2 回文積再訪
	12.3 制約ベース計算モデル
		12.3.1 基本的制約と伝播子
		12.3.2 計算空間の探索をプログラムすること
	12.4 計算空間定義し,使うこと
		12.4.1 深さ優先探索エンジン
		12.4.2 検索エンジンの実行例
		12.4.3 計算空間の生成
		12.4.4 空間の実行
		12.4.5 制約の登録
		12.4.6 並列的伝播
		12.4.7 分配(探索準備)
		12.4.8 空間の状態
		12.4.9 空間クローン
		12.4.10 選択肢を先に任せること
		12.4.11 空間マージすること
		12.4.12 空間失敗
		12.4.13 空間計算を注入すること
	12.5 関係計算モデルを実装すること
		12.5.1 choice文
		12.5.2 Solve関数
	12.6 練習問題

第3部 意味

第13章 言語意味
	13.1 一般的計算モデル
		13.1.1 格納域
		13.1.2 単一代入(制約)格納域
		13.1.3 抽象構文
		13.1.4 構造的規則
		13.1.5 直列実行と並列実行
		13.1.6 抽象マシン意味との比較
		13.1.7 変数導入
		13.1.8 同等性の強制(tell)
		13.1.9 条件文(ask)
		13.1.10 名前
		13.1.11 手続抽象
		13.1.12 明示的状態
		13.1.13 by-need同期
		13.1.14 読み出し専用変数
		13.1.15 例外処理
		13.1.16 失敗値
		13.1.17 変数置き換え
	13.2 宣言的並列性
		13.2.1 部分停止と全体停止
		13.2.2 論理同値
		13.2.3 宣言的並列性の形式的定義
		13.2.4 合流性
	13.3 8つの計算モデル
	13.4 よくある抽象意味
	13.5 歴史に関する注記
	13.6 練習問題

2011-11-04

モバイルゲームの何が問題なのか~ゲーム性課金システム

長文は面倒なので端的に書くと

1、ゲーム性を高める為にファミコンからソフトメーカーは高画質・高品質ゲームを作り続けているが、

モバイルゲームで利用されている内容は、ほぼファミコン時代システムその物で、単純な物にしか客がお金を落とさなくなると、

ハードゲームで高度なレベルソフトを作る会社に資金が回らなくなり、ゲーム業界の力が無くなる。

現在、家庭用又はPCのみのハードゲームだけ作っている会社はほぼ皆無)

2、課金システム企業にとってはドル箱システムであるが、ゲーム性という観点から見れば最低な手段

少し前にゲーム業界で問題になったのは、乱数により釣れるつりゲームにおいて、魚が釣れる可能性が高くなる釣竿(回数制限あり)に数百円の値段を付けたという物

壊れるので際購入が必要なのである確立が高いだけで確実に釣れる訳ではないのである

そもそも乱数により釣れるつりゲームの何処にゲーム性を見出せばいいのかという疑問もあるが、その上でこの鬼畜システムである

消費者は安い(基本無料)便利(携帯ダウンロード一発)早い(何処でも暇な時間に出来る)に流されたわけだが、

その結果現実になったのは、ゲーム性皆無の作業プログラムを嬉々として延々やるパンピーと、ゲーム性を追及する層に完全に分断されるという事である

ゲームの終着点の一つとして、完全なる仮想現実を構築して、そこにおける様々なプレイを実現させるという壮大な考えがあるが、

2011年現在流行っているものは残念ながらそんな理想とは程遠い物なのである、結果ソフトメーカーは資金難で潰れる。

これはゲーム業界に限った話ではないが、闇雲に安易な理由で消費行動に走らず、自分が消費する影響も考えて欲しい物である

資本主義において消費者は愚かでないといけない前提があるという事実がそこに存在している。

2011-09-22

reCAPTCHAはちゃんとした英単語に「なってない」方だけを正確に入力すれば通る

理由は分かるよね?reCAPTCHAの謳っている文句的にこれはまずくない?

要はreCAPTCHAでは二つの単語プログラムで生成された単語OCRで読み取れなかった単語、が提示されて、ユーザはそれを読み取ることを求められる。しかし、この際正確に入力するのはプログラムで生成された単語のみで良い。なぜなら、OCRで読み取れなかった単語には答えが無いか適当入力してもプログラムからは分からないので。reCAPTCHAの問題はその二つの単語が容易に区別できてしまうこと。なぜ区別が付くかというと、プログラムで生成した単語乱数で生成した無意味文字列なのに対して、OCRで読み取れなかった単語はきちんとした英単語から。その二つを区別するコストが二つの単語を読み取る手間より低ければ、reCAPTCHAのもう一つの目的である人力OCRは成立しなくなってしまう。

この問題に対処するには、プログラムで生成する単語無意味文字列ではなく、辞書から引っ張ってきたものにすれば良い。ただ、ノイズ処理のかけ方からその二つの単語の区別は容易につくような気もする。こういうの論文ネタにならないかしら。

公式実働サンプル

2011-09-04

パスワードEvernoteに保存する

ちょっと釣りっぽいタイトルで書いたけど…

Twitterハッカーとのコンタクト成功―攻撃手口の詳細が判明した

http://jp.techcrunch.com/archives/20090719the-anatomy-of-the-twitter-attack/

とかを読んで、パスワードの保存方法をいろいろ考えなおして悩んだ。条件は、

ってこと。現在、この方法実験的に移行しつつあるけど、はてな民のみなさんの意見が聞きたい。

で、いろいろ考えた挙句、以下の方法を取ることにした

以上の準備の上で、真のパスワードは (A) + (B) + (C) という文字列

以下に具体例を書く。

まず、(A)だが、これは座右の銘とかことわざとか住所とかを、うまい具合に省略して決める。例えば、座右の銘が「寿限無寿限無 五劫の擦り切れ」だったとすると、(A)を "jgmjgm"とかにする。これはどこにも書かない、あまり変えない。逆に言うと、忘れにくいものにする。

次に、記号(B)を決める。これは無難に "@" にする。実は、この(B)は、厳密には存在意義があまりないんだけど、(A)(C)に記号を含ませるのはちょっと面倒なので強引に記号を導入するということで組み入れた。

最後適当乱数ジェネレータとかで(C)を決める。例えば "8sbI" だとする。

で、Evernoteメモる。

はてな:8sbI

実際のパスワードは、"jgmjgm@8sbI" となるので、これでパスワードを変更する。

現実には、パスワードブラウザに覚えさせるので、マスターパスワードは絶対に設定する。ブラウザマスターパスワードEvernoteパスワードくらいは別にして「気合いで」覚えても良いかもしれない。

あと当たり前なんだけど、Evernoteが乗っ取られたときに備えて、該当のメモノートには「パスワード」とは書かない。タイトルは「もつ鍋レシピ」とかにして、もつ鍋の写真を先頭に貼っておくと、Evernoteプレビューでは写真けがでかでかと強調されて表示されるので若干リスクが下がる。どうでもいいけど。

蛇足:面倒臭いのは、パスワードの文字数上限が8文字とか、記号禁止とか、そういう例外的なクソサイトへの対応なんだよな。使わないってのが最適解なんだけどね。俺の経験上、もっともクソだったのが就活サイト全般。

2011-01-25

ここ最近パチスロで異常割で撤去や改修なんて無かったけどなぁ

サミーが「サクラ大戦3」で、想定外の出球割をやらかして撤去

http://www.j-cast.com/2011/01/25086431.html



なんか、10年以上昔にもどったような、そんなニュースだったw

はいえ、覚えている限りでも、パチスロの異常割は結構な件数が在ったり。



メーカー純正台での異常割事件/バグ

(いわゆるゴトと呼ばれる、特殊機器や台扉開けなどの操作を除く)


1.5号機時代

FireBird(現ユニバーサル系列): ボーナス中に特殊な打ち方で、予定枚数を越えてコインを出す事が出来た。


2号機時代

リバティベルその他(現ユニバーサル系列) : 特定の操作ボーナス強制スタート

サファリラリー(現大都?) : 小ボーナスを揃えられる状態なのに、大ボーナスを揃えられた

ムサシ2 (パイオニア): 大ボーナス揃えられる状態で延々とコインを増やせた/何と盤面をグッと押すとリールを止められたwそのままボーナスをそろえる事も可能


3号機時代

コンチネンタル(現ユニバーサル系列): 大ボーナス揃えられる状態で延々とコインを増やせた/メーカーが仕組んだボーナス強制成立装置に、アホな罠があったため、ボーナスかけ放題

スペーススペクターその他 : クレジット枚数操作その他

ドリームセブンJr/マジカルベンハー(現アリビット系列?) : 大ボーナス中に再度大ボーナススタート


4号機時代

ビーナス(現オリンピア系): 子役を取得する方法を工夫する(変則押し等で察知)事で、通常時に子役を想定より多く取得する事が出来た

※あともう1台、別メーカーで同じ失敗の台があったはず。名前失念。



メーカー純正台での異常割事件/それメーカー(というか開発者)がコッソリ仕組んだんちゃうの?編

(以下すべて4号機)

サミー系の多数の台 : レバーゆっくり下げて、リールが回ったら即放すという手順で、取得した乱数を前回の値のままに出来た。

 ※当時、特定の台では特殊な子役をきっかけに大量の出コインを獲得できる抽選を行っていた為、破壊力が大きかった。

獣王(現サミー系) : ランプの点滅で、特殊なゾーンに居る事を察知する事が可能(これは判別できてはいけなかった)

インディジョーズ(現サミー系) : ランプの点滅で、多数ある15枚子役の絵柄を推測しそろえることが可能

ゴールドX(現ユニバーサル系) : 液晶に出る数字で、15枚子役の揃え方を推測可能



雑誌などにも載った、有名かつ知名度の高いものに絞っても、こんなところ。

1号~3号機までは、パチスロそのものの作りが甘く、これらの話も多く聞く事があった。

しかし4号機の初期は、メーカー側も決まりきった性能の台しか作らなかったので、この手の話は殆ど聞かなかった。

4号機後半になって、特殊なゲーム性お目こぼしで許可されたとたんに、色々と変な事件が出たりしたけど、それも結局5号機で完全に息の根を止められたわけで。

5号機になってからは、割の計算技術介入余地などは、完全にシミュレートしているので、そう簡単にこの手の話は出てこないと思い込んでたんだけども。


って、ここまで書いて、ヤケにサミー系の黒さが目についたりw

今回の事件は、はて、バグなのか計算ミスなのか、それとも…?


※なお、「x号機」という表記は、その時点でのパチスロに関する規約とご理解下さい。

http://anond.hatelabo.jp/20110125200523

俺はTASの良さが理解できないんだけどあれは何に感動すればいいんだ?

事前に乱数を調べておいてその通り進めるんならその通り進んで当然だし

めんどくさい下調べの労力を賞賛すればいいのか?

2010-10-09

ポケモンプレイして感じたやっぱ任天堂の本気はすげぇ

かれこれ、初代ポケモングリーンをやったのが最初最後だったから、今回ポケモンブラックプレイしたのはもう12年ぶりくらいなんだろうか。

いろいろ感じたことは、ポケモンとは今までのRPG集大成だということだ。

(1)自由なパートウエイトが大きい

とりあえずエンディングまでは辿りついた。

まだまだ冒険は終わりではないらしい。。

これからは順不同で自由度の高い旅が用意されているみたい。

出会いを求め、伝承を辿り、新たな発見を求めて冒険がずっと続いていく。

近作のポケモンコンピュータRPG史上初めて導入された画期的な要素ではないけれど、このエンディング後のパートが大きいのは特徴的だ。

一本道の必須パート+エンディング後(あるいはエンディングの前から)に自由なパート

の2パート構成は最近RPGにはよくある。

例をあげれば、クリアした後も、エンディング後にいけるようになる隠しダンジョンや、クエストとよばれる小冒険を続けることでストーリーテリングの楽しさが去った後もゲーム面白さを維持できる。

もともと、自由なパートが置かれる以前でもPG(ここではドラクエに代表されるRPG)の魅力の1つは探索だった。

近作のポケモンは後半のパートがかなり多い。

今回、ポケモンブラックホワイトエンディングまでに巡ることが出来る町はマップにある町のたった3/4ほどだ。

ダンジョンに至っては半分くらいストーリーと無縁だ。

もちろん、通信機能を使ったクエストも用意されている。

(2)キャラ育成要素と感情移入しやすさのバランス

ドラクエでいえば3、FFでいえば5、自由度の高い育成要素を加えたゲーム面白い

反面、キャラ自由度を持たせることは、人格定義しにくくなる。

ドラマパートでは勇ましいセリフを言うけれど、戦闘シーンでのジョブ遊び人だとか、移動シーンでは鎧を着てるのに戦闘シーンでは魔法使いローブを着ているとか。

か弱い女性という設定なのにパーティ最高火力だとか。

その点で、ポケモン完璧だ。

どんなにポケモンを鍛えようと、どんなポケモンを育てようと、主人公の人格違和感はない。

パーティメンバー過去の設定をつけないという意味では、DQ3のルイーダの酒場システムWizのが古いしギルガメッシュ酒場というべきか)と同じのはずだが、ポケモンのほうが自然キャラ感情移入が出来る。

流石にそこは人間と獣の差、獣はペットを飼う感覚で従えることができるが、共に冒険する仲間にはそれぞれ世界にたった一つの冒険する理由が欲しい。

戦闘員と主人公を全く切り離し、戦闘員を非人間にすることで完璧な解決を図ってる。

とはいえ、これだってポケモンが初の試みになるかは微妙だ。

たとえば昔から女神転生では似たシステム採用されてた。

(3)狭い世界

RPGにおける世界の広さは、スーパーファミコン時代が一番広かったと思われる。

主人公が住む世界地球規模(船や空を飛んで一周できる)で、さらにもう1つ、あるいは二つ同じように地球規模の異世界次元をまたいだり時空をまたいで存在し、同じように人の営みが用意されていた。

ところが、それ以降は世界の広がりはない。

むしろ、ある外界から隔たった特定地方舞台にすることが増えてきた。

おそらく、僕らの住む現実世界のようにいろんな人がいて、いろんな思想、派閥存在する世界の諸問題は、魔王を倒せば解決するような単純なものではないからだ。

ポケモンもこの流れを踏襲してる。

狭い、人の繋がりの密な世界の温かさ、かといって冒険が不自由なわけではない。

世界が狭いからといって、すぐに退屈してしまうことはない。

僕が子供の頃に近所の廃屋や林を探索していたときには退屈さを感じなかったように。

(4)古きよきターン制

ポケモン廃人パラメータからダメージ計算できるように、極めて厳格なルールで動いている。

パラメータと行動の結果がほとんど予想可能なまでにすることで、カードゲームのような戦略性が生まれている。

そこに、僅かに1つ2つ、(僅かであるのがミソだ)乱数で決まる要素を加えることで、興奮が高まる。

テーブルトークRPGから伝統的な古きよきターン制だ。

しばらく気付けなかったが、風来のシレンのようなダンジョンRPGに通じるものがある。

なにを、何回、どういう順番で、行うか、それをプレーヤーに考えさせる。

MP制でなくPP制にしたのもそのせいだと思う。

もちろん、これが対戦という状況においてさらに頭脳戦の楽しさとなるだろうことは想像に難くない、

(5)通信要素

思えば、初代ポケモングリーンレッドの2バージョンを用意することで、通信なくしてコンプリートできない仕様にしたのは画期的だった。

最近だと、インターネットにより携帯機でなくとも通信は可能になったけれど、ネットワーク利用で面白さを倍増させることに関しては、これ以上のゲームはなさそうだ。

面白さを倍増と書いたが、累乗といっていいかもしれない。

DSのためのソフト、いや、ポケモンのためのハードこそDS

ラブプラスDSの特性を最大限生かしたゲームとか言う意見を聞いたけど、そんなレベルを遥かに上回る。

(6)ゲームバランス

やりこみ要素が強いのに、廃人初心者も、小学生大きなお友達も、みんな楽しめる。

極めて凶悪なコンボがありながら、完璧なハメ手がない。

以上、近作のポケモンゲーム史上画期的というようなシステムはない。

ただ、集大成だ。

そのクォリティが高すぎて、RPGというよりもポケモンという新しいジャンルだと言っていい。

しかし、おそらくこんないろんな要素を絶妙なバランスで詰め込むのは他社には出来ない芸当だったと思う。

どうせ子供向けだろとか、グラフィックドットが粗いとか、そう思って見向きもしてないだろうけど、みんなポケモンやってみてくれ。

2010-03-04

サマーウォーズ思ったこと

2048Bitの暗号?っていうけど、文字数になおすと256文字。打ち込むの大変だろう・・・・

大半が自動生成のソルトで残り8文字ぐらいがパスワードだとしても、ソルトの部分には非表示可能文字を入れることもできるから、複合後が完全に乱数で手がかりなし。どうやって解読するんだと。

バイトしてたから、ソルト知ってる?バイトソルト教えるなよw。

そもそも、パスワード作るときは、n文字目とm文字目を混ぜて暗号化とかやっていくので、1文字だけ間違えるなどは無理。間違えるとしたら複数文字セットで間違えることになる。んーあれは解読ミスじゃなくて、タイプミスか。

とりあえず、2048Bitの暗号?なら256文字セットで一気にわかるはず=でないと当たり外れが判定できない。なので、1文字入力して考えとかない。もしそれができたら高々8Bitしか鍵長がない。

そもそも、パスワードは 不可逆関数であって暗号化ではないので、元には戻せない。戻せるとしたらそれ、セキュリティーホールじゃね?しかも、それを画面に表示とかすげー、セキュリティーホールじゃね?

 

誰でも思うことだろうけど、いや、うん。OZシステムは、そんなに危険なのにどんだけ初歩的なセキュリティホールを抱えてるんだ?

 

そして、そもそも論として、鍵のハッシュ後の値を知ってるなら、自分プルートフォースかけた方がはやくねーか?ラブマシーン。いや、それがダメなりゆうは小説読んでるから知ってるけどwww。それにしても、どう考えても、そこは、プルートフォース

 

そして、そもそも、コンソールからrootログインすればいんじゃね?

世界の端っこの方で愛を探すプログラマ0.999はそう思いました。こんにちは増田の皆さん。サマーウォーズどうでした・・・って冬だし。

2010-02-21

http://anond.hatelabo.jp/20100214192014

ブックマークコメントトラックバック嫌儲とかなんとか話がすっ飛んでてびっくりした

みんな一足飛びに書いてないことまで読み取っててすごすぎる、自分にはできない

それとも俺が見たときには既に書き換わってた問題箇所があったんだろか

件のサービスに関しては、適当乱数当てるプログラムよりよっぽど真面目だよね

2010-02-13

R基礎文法最速マスター

基礎

外部スクリプトの読み込み

Rコンソールに一行ずつコマンド入力してもいいけど、実際に使うにはテキストファイルコマンドを書いて(ソースコード)一気に実行させる方が楽。

source('hogehoge.R')

hogehoge.Rというのがソースコードを書いたファイルソースファイル)の名前

ライブラリの追加

CRANという、CPANパクリがある。膨大な数のライブラリがあるので、好きなものをインストールするには、

install.packages('hoge',dependencies=TRUE)

とするのが楽。

変数宣言

不要。変数に使える文字も結構多い。日本語でもOK。

> あ<-1
> あ
[1] 1
代入
a<-1
b=2
1->a

どれでもいい。但し推奨されてるのは一番上。Rの人は「束縛」という言葉を使いたがる傾向があるけど、どっちでもいいと思う。

余談だけど、関数引数の中で代入できる、しかもその値をそのあとの引数で使える。これ実は便利。

> sum(a<-1,a)
[1] 2
変数の内容を確認

基本は変数名を入力すれば表示される。

> a
[1] 1
> str(a)
 num 1
> summary(a)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      1       1       1       1       1       1 

最後のsummaryはRっぽい。strっていうのはstringではなくstructの略(だと思ってる)。Rの変数はいくらでも複雑な構造になり得るけど、そのときにぱっと見がわかるように構造を出力してくれる。

ベクトル

Rの基本はベクトル

ベクトルを作る

ベクトルの作り方はいくらでもあるけど、例示するのが早いでしょう。

> x<-1:3
> y<-c(TRUE, FALSE, TRUE)
> z<-c("a","b","c")
> x
[1] 1 2 3
> y
[1]  TRUE FALSE  TRUE
> z
[1] "a" "b" "c"

他にもいっぱいあるし、関数返値ベクトルってこともよくある。

> runif(3)
[1] 0.2200965 0.6391403 0.1089252

一様乱数を三個作った。

ベクトルの要素にアクセス
> x<-letters[1:5]
> x
[1] "a" "b" "c" "d" "e"
> x[2]
[1] "b"
> x[4:5]
[1] "d" "e"
> x[c(1,3,5)]
[1] "a" "c" "e"

こんな感じで、[]の中に添え字でアクセス。1-indexなので注意。2,3番目の例では添え字にもベクトルを使って、複数の要素に一気にアクセスしてる。

ベクトルの要素に代入
> x[3]<-"z"
> x
[1] "a" "b" "z" "d" "e"

でOK。

終わりに

要望があれば続くかも。

2010-01-03

http://anond.hatelabo.jp/20100102235955

乱数適当な長さの文字列を作って、それに初期化するようなシステムにすれば良いんじゃない?

パスワードを忘れた人には

「○○様 日頃は弊社サービスをご利用頂き誠にありがとうございます。

 新しいパスワードはxyeaksdfed12です。次回ログイン時にパスワードの変更を求められますので、ご対応をお願いいたします。

 これからも末永いお引き立てをお願いいたします」みたいなメールなり手紙なりを送る。

というか、そういう実装って枚挙に暇がないような。。。

2009-09-13

サマーウォーズ真犯人

サマーウォーズの鑑賞中、セキュリティ描写が気になって映画を半分(主にカズマパート)しか楽しめなかった。

その後、はたしてどのような描写であれば納得感を得られたのかと妄想していたら、妙な答えに行き着いた。

まぁ、妄想ネタであることを承知置きください。

http://d.hatena.ne.jp/LM-7/20090831/1251727185

ここにあるように、もしあの2056桁の数列がRSA暗号における鍵であるとして、健二が素因数分解により平文(おそらくアバターの操作や仮想建物への入室のためのパスワード)の復号をマトモに暗算で行っているということは考えにくい。そこには何らかのショートカットが存在するはず。おそらく、OZ暗号鍵生成アルゴリズムに実装上のバグがあり、何らかの推察(法nに規則性、乱数が甘いとか)を許してしまうような物だろう。これは、おそらくOZ技術者の中では既知のもので、対応中のものだったのではないだろうか。そう、だいたい55人くらいにはそのショートカット法を知られていたくらいには。

ここで思い出してほしいのは、健二はOZメンテナンスアルバイトをしていたということ。

メンテナンスのため管理棟(だっけ?)と言われる領域へログインし、何か作業を行っている様子が見られる。どんな作業かは分からないが、物理部の彼らのこと、そうした暗号への興味もあるだろうし、知ってしまっていたとしてもおかしくはない。(こんな危険バグの対応をバイト学生に任せるなんてありえないが、あるいはバイトとはこの問題への対応のためのテストであり、その過程で知ってしまったのかもしれない。)

健二が上田へ向かい、ラブマシーンが暴れだす。

だが、ラブマシーンの描写を見ると、できることはアバターを乗っ取ることだけで、OZの基幹系システムそのものを乗っ取ったわけではない。あくまでアバターの可能な範囲での権限の行使に限られていて、たとえば花札ルールに介入したり、配られる札を操作したりするようなことはできない。

ラブマシーンが米軍によりOZに放たれたとき、彼にできることは相当限られていたはず。

彼が暴れるためには、多くのユーザ秘密鍵管理を行う管理棟へ入れるアバターを乗っ取ることが必要だった。

ラブマシーンは何かのきっかけで上記の脆弱性を知り、OZ管理者に近いアバターの鍵をなぜか知り、その解を解けそうな人物へ送付する。メールでその鍵の復号を知る。

それを手がかりに秘密鍵へのアクセスを可能にし、あとは選択平文攻撃によってアバターを次々に乗っ取っていく。でも、最初の一歩、管理棟への出入りのための鍵はどこから?

その、最初の鍵は、どうやって手に入れたんだろう?

ここで、一人の傷心の人物が浮かび上がる。

OZバイトしていた、物理に興味のある、あまり目立たなかった人物。

彼は暗号を自力で解くほど数学の才に恵まれていたわけではなかったが、秘密鍵のありかと、脆弱性があることは知っていた。

じゃん拳に負け、東京に一人残った彼。

傷心の彼はその日、管理塔のまわりをうろつくラブマシーンに気がついた。何でも知ろうとし何でも吸収しようとするbot

本当は、知識を吸収して報告するだけの何も権限のないbot

そう、佐久間敬君、きみ、あれに何か渡さなかったかい?その見返りとして健二のアバターを使うように申し出たり?

暴走したラブマシーンとは、あれは君?

2009-07-21

団結をしない

http://chinachips.fc2web.com/argue/090706.html

さて、わたしは様々な事を「考える」ようにしていますが、このように「考えない」方もおられるようですので、代わりに考えなければいけないのかなぁ‥という気もします。

問題は2パラ目にあります。

ドイツナチスのケースも、ソヴィエト共産党のケースも、出発点では多数決だったのです。ーーーその多数決で「多数決をやめて、総てあなた方の判断で進めてください」と決めたのが「一党独裁」という結果になったわけです。

古い例を見れば、古代ギリシャで、直接民主制最盛期に、保守派の「キモン」を失脚させて登場した「ペリクレス」の、事実上独裁を許したのも「民主政体」です。つまり、

この意見がいうところの「多数決原理そのものが否定されかねません」は、無責任な「他人事評論家風」発言であり、その政局当事者達の想いとは乖離しているのです。

これは「多数決原理」が正しい、という誤解が土台にあります。

しかし、歴史を見ると、世情が混乱し多数決では纏まらず、「民主政体」では結果的に国が滅ぶケースもあり得るのです。

先日の都議選でもつくづく思ったのだが、どうしてみんなこう、右へならえが大好きというか

勝ち馬に乗りたがるというか、一党をバカ勝ちさせるような投票行動に出てしまうんだろうねえ。というか、よくこんなことが可能だなと、むしろ結束の強さに感心する。

それも60年近く似たような事を続けていて、一向に良くなってないのだから学習能力がというものがない。

上の方も言うように、議会があればいいというもんではない。

こう考えているのは少数派なのかもしれませんが、議会というのは意思決定の場であると同時に(実は)討論のための場でもあって、まともに討論するには各勢力が均衡していることが望ましいのだから(ゲームと同じで、1000対3とかでサッカーとかそんなのゲームと言わん)政権云々ではなく、等しく力を持っている、あるいは等しく無力であるべきであり

一党バカ勝ち戦略はどう考えても頭悪いし、現にあっちこっちにツケが回りまくっているよ。つまり皆さん意思決定の面しか見ていないんでしょうな。

その結果が拙速に次ぐ拙速で、出てきた法律は互いに殺しあってたりでわけがわからんです。

背脂で米炊いてるようなもんですよ。それを60年続けている。老舗の味ですかそうですか。いい加減にしてくれよ。

 

ねじれ国会とか言われましたが、この時期に少なからぬ膿を搾り出せたことには大いに意義があったし

しょっちゅうバカやらかしているとはいえ、そこそこ良いものを見せてもらったと思うのだがどうだろう。

このままねじれっぱなしでも構わないのだが、別にねじれてあるのにどの政党でなければならないという必要もありませんわな。

というわけで、今必要な調節機能とはむしろ団結しないこと(笑)、乱数的であることだろう、と

従って積極的に負け馬に賭け続ける戦略にも大いに意味があるのである。

(あまりに知性が感ぜられない候補者は勘弁だがのー)

 

http://blogs.itmedia.co.jp/mm21/2008/04/post-003c.html

民主主義的に意思決定する際、最後は「では、多数決で」と決議することが多いと思います。

しかし、多数決そのものは、民主主義ではありません。

私自身は、民主主義とは、異なる立場の意見をお互いに話し合い、理解しあい、相手のよい部分は取り込み、自分のよい部分は相手に認めてもらい、より高いレベルの解決策を見出していくプロセスである、と理解しています。このためには論理的な議論が必要です。

多数決に持ち込まざるを得ない、ということは、このようなプロセスが十分に働かず、より高いレベルの解決策が見出せなかった場合に起こります。

我々はそのレベルに達していないということですねわかります。

2009-05-22

ゲーム馬鹿には遊べない

ゲームでのスーパープレイっていうと、最近だと弾幕シューティングゲームとかパズルゲームとか、緻密な操作を要求されるゲームが注目されがちだけど

RPGで「縛りプレイ」の戦術考えるとか乱数を操作してレアアイテムを確実に入手する方法とかも同じぐらいのスーパープレイだと思う

仕組みさえわかれば真似するのがわりと容易な上に地味だからあまり目立たない、直接の評価には繋がりにくいけど

思えば自分洋ゲープレイすると大抵操作の難しさと管理する要素の多さで頭がパンクして投げ出してしまう悪癖がある

みんなどこからどうやって先陣を切ってパターンとか方法とか考えてるんだろう、自分はなんで普通プレイして何も思いつかないんだろう、

そしてゲーム開発者はこんな度量の広さ、遊びしろの広さをどうやって実現するんだろうと、ゲームを楽しむことの難しさに何重の憂鬱を抱えてしまい

もはや最近ゲーム普通に遊ぶこと自体があまり楽しくないように感じてきてしまっている

こういうゲームの下手さは現実での頭の悪さに直結して生活での齟齬を生み出してしまっている気もする

どうすればゲームがもっと楽しく遊べるようになるんだろう

2009-04-01

世論調査ってどこまで世論カバーしているんだろう

世論調査 - Wikipedia -

http://ja.wikipedia.org/wiki/%E4%B8%96%E8%AB%96%E8%AA%BF%E6%9F%BB

近年は電話によるRDD方式(Random Digit Dialing、コンピュータ乱数計算を基に電話番号を発生させて架電、応答した相手に質問を行なう)が多く採用されている。

ぶっちゃけ固定電話契約していて、且つ日の明るい時間帯に長々と電話に出られる人間の考えしか「世論」と認められていない状態なんだよな。

そんな事を考えてみると、ネットアンケートを「信憑性が無い」と安易に切り捨ててしまうのも考え直さなきゃならないような気がしてくる。

2009-02-05

http://anond.hatelabo.jp/20090203225439

http://anond.hatelabo.jp/20090204155747 をもう少し詳しく書こう。

ゲームプレイヤーは神だ。破壊神だ。

破壊神ネタバレや周回プレイによる未来視を持っている。

破壊神コンティニュー乱数操作によって運命を操る事ができる。

破壊神ゲーム世界主人公を、作為的に操作する事ができる。

ゲーム製作者もまた神だ。守護神だ。

守護神世界を作り、生命を生み出すことができる。

守護神生命知恵を与えることができる。

ただし、守護神の力は見えている範囲にしか届かない。

神による作為に対抗できるのは、神だけだ。

電源系ゲームでは、守護神はいつも留守にしている。

破壊神は、守護神のいない世界主人公を操作する。

神の守護を持たないキャラクターにできる事は何も無い。

守護神が事前に与えてくれた知恵にすがりつくより他に無い。

破壊神に対抗するためには、他の破壊神と争わせるか、守護神が常に見ているしかない。

前者FPSであり、MMORPGであり、ボードゲームであったりする。

後者は今のところ、TRPGしかない。

2008-11-21

http://anond.hatelabo.jp/20081121220542

横だけど。

モデル化さえしちまえばシミュレーションそのものは大したことないだろう。

基本的には乱数振ってモンテカルロでモニョモニョする感じになると思う。

ランダム交配を仮定すれば僅かにゆらぎながら線形で減衰していく感じになるのかな?

俺が元増田の書き込み見たときにパっと浮かんだのは、振動しながら減衰していくイメージだったけど、

これは何か適当バイアスモデルに入れないと見えないかもなあ。『一重はモテないから子供残しにくい』とかw

2008-11-12

衰退していくIT業界に向けて、30半ばシステムエンジニアが昔の思い出を語るよ 0010

 たくさんのブックマークと期待コメントありがとうございました。続きを書いていきます。

※これは連載です。初めての方は下記から見てください。

衰退していくIT業界に向けて、30半ばシステムエンジニアが昔の思い出を語るよ 0001

 兄貴FM-7で、初めはゲームばかりやっていたのだが、しばらくすると「信長の野望」には裏技存在する事を知ってしまった。裏技を使い、稼いだ金に物を言わせて増兵をしまくり、簡単にクリアできるようになってしまった僕。(ど忘れしたのでどんなのか調べたら、『いったん年貢率を0にしてから収穫前に上げることで米収入が上がり、その米を元手に富国強兵を行うといったテクニック』らしい。)

 その頃やっていた他のゲームは、ハイドライドウィザードリィ、ザ・ブラックオニキス、デゼニランドポートピア連続殺人事件など。自分で買ったゲームがほとんど無いので記憶は薄いのだが、みんなテープ媒体だったように思う。

 一方、兄貴はというと、なにやら熱心に毎月雑誌を買って、どこかへ投稿しようと試みているようだ。当然、それとなくそ雑誌も読んでみる事となる。それが僕と「マイコンBASICマガジン」、そしてプログラム言語との出会いだった。目の前にある機械ゲーム専用機ではなく、自分の思い通りに動かせるのか、と気付いた時の驚きと快感。今も忘れられない。

 前述の通り、その当時のマイコンは、電源を入れるとROMから「BASICモード」がいきなり立ち上がるのだけど、この状態から自力で何かを動かしたい場合、BASICと言われるプログラム言語を実行することにより、色々出来るようになる。

 マイコンBASICマガジン(長いので以降「ベーマガ」)は、主にBASICソースコードが掲載されている専門雑誌だ。基本的に、雑誌の構成は読者からの投稿で成り立っており、自ら投稿したBASICソースコードベーマガに掲載されるかどうかが、その当時マイコン小僧たち最大の憧れであり、ステータスだった。

 ご他聞に漏れず、ベーマガを読み始めてから僕はBASICの虜となってしまい、今までやっていたゲームの頻度は自然と減り、BASIC時間を割くようになった。

 今思えば、兄貴は本気でBASICプログラムを投稿し、掲載される気満々だったので、かなりの難しいコードを書いていたんだと思う。結局、彼の思いが果たせたのかは分からない。掲載されたコードを見せてもらった事が無いし、それなりに競争率が高かったので多分ダメだったんだろうと思う。

 一方、僕といえば、ベーマガで面白そうなゲームソースを見つけては、一生懸命コード入力し、誰かが作ったゲームをやることに専念していた。しばらくの間、記憶する媒体テープレコーダーしか無かった為、目の前にある「ベーマガ」のゲームがやりたければ、一字一句間違えずにソースコードを打ち込まなければならず、何回も何回も間違えながら入力していた記憶がある。テキストエディタなんてものがそもそもなかったので、ただ入力するだけでもかなりの難作業だった。

 そのうち入力しているだけでは我慢できなくなり、なんとなくBASICというものが理解出来て来たので、自力でゲームと言うものを作ってみる。しかし、「作る」と言っても一切の独創性はなく、ベーマガに載っていたゲームアイデアをほとんど流用していた。

 一番初めに作ったのは、縦スクロール型のスキー風障害物除けゲームだった気がする。僕みたいな初心者がこれを選ぶのには理由があって、RND(乱数発生関数)とPRINT(画面表示)だけ知っていれば縦スクロール自体はターミナル勝手にやってくれる為、後は壁の判定処理を入れるだけでよい。特に難しい事を考えなくてもある程度作れるからだ。

 当時、知っている命令語のレパートリーは極めて少なかったし、現在webのように、簡単な方法で調べる手立ても無かった。綴りや文法が分からない命令はいちいち調べるのが面倒くさいので、とにかく使わない方針で押し通していた。

 ロジックも見よう見まねで無理やりひねり出してたものだから、乱数が過激に発生して、スキーゲレンデが右側から大きくはみ出して表示がぐちゃぐちゃになったり、両側の壁に隙間が出来てプレイヤーがそこをすり抜けてしまったり。しかし、こういう試行錯誤の中で、ロジックの作り方や、エラー処理と言うものを知った。

 立体迷路とか、横スクロールゲームとか、ベーマガで輝いていたあのゲームを自力で作りたかったけど、その当時はそこまでのレベルに達することは出来なかった。

 ブクマを燃料として書き続けます。

次:衰退していくIT業界に向けて、30半ばシステムエンジニアが昔の思い出を語るよ 0011

2008-08-02

ミク厨が非ミク厨の彼女にボカロ曲を軽く紹介するための10本

アニオタが非オタの彼女にアニメ世界を軽く紹介するための10本

に触発されて作ってみた。少しも反省していない。

(2008/8/4 追記)

d:id:Ryuzu が素晴らしいネタを作ってくれました。

こちらのネタよりもさらに廃な世界が楽しめます。

ボカ廃が非ボカ廃の彼女にボカロアングラ曲を軽く(?)紹介するための10本 - アングラっておいしいの?

(2008/8/6 追記)

d:id:he-noki が10本選んでくれました。

ネギネタ等の二次設定を知らなくても楽しめるような曲を

真面目に10本紹介しています。

ボカロ廃が素人にボカロオリジナル曲を軽く紹介するための10本 - 耳小屋

-----------------

まあ、どのくらいの数のミク厨がそういう彼女をゲットできるかは別にして、

「ミク厨ではまったくないんだが、しかし自分のオタ趣味を肯定的に黙認してくれて、

 その上で全く知らない初音ミク世界とはなんなのか、ちょっとだけ好奇心持ってる」

ような、ヲタの都合のいい妄想の中に出てきそうな彼女に、ボカロ曲のことを紹介するために

聴かせるべき10本を選んでみたいのだけれど。

(要は「脱オタクファッションガイド」の正反対版だな。彼女にボカロ曲を布教するのではなく

 相互のコミュニケーションの入口として)

あくまで「入口」なので、時間的に過大な負担を伴うぼからん未掲載の大量のミク曲は避けたい。

(名誉の除外は例外)

できれば音楽ランキング入り、少なくとも合計再生数100位以内の作品にとどめたい。

あと、いくらミク厨的に基礎といってもオリジナル曲でないものは極力避けたい。

新参のミク厨が『星間飛行』は外せないと言っても、それはちょっとさすがになあ、と思う。

そういう感じ。

彼女の設定は

ボカロ曲の知識はいわゆる「組曲」系動画で聴いたり、ねんどろいどのミク動画を見たことがある程度

ニコ厨度も低いが、頭はけっこう良い

という条件で。

まずは俺的に。出した順番は実質的には意味がない。

初音ミク が オリジナル曲を歌ってくれたよ「メルト」

まあ、いきなりここかよとも思うけれど、「メルト以前」を濃縮しきっていて、「メルト以後」を決定づけたという点では

外せないんだよなあ。再生数も200万越えだし。

ただ、ここでオタトーク全開にしてしまうと、彼女との関係が崩れるかも。

このべたべたなラブソングについて、どれだけさらりと、嫌味にならず濃すぎず、それでいて必要最小限の情報彼女

伝えられるかということは、オタ側の「真のコミュニケーション能力」試験としてはいいタスクだろうと思う。

初音ミクがオリジナル曲を歌ってくれました「Packaged」 Full Ver.初音ミクオリジナル曲 「ハジメテノオト(Fullバージョン)」


アレって典型的な「ミク厨が考える一般人に受け入れられそうな曲(そうミク厨が思い込んでいるだけ。実際は全然受け入れられない)」そのもの

という意見には半分賛成・半分反対なのだけれど、それを彼女にぶつけて確かめてみるには

一番よさそうな素材なんじゃないのかな。

「ミク厨としてはこの二つは音楽としていいと思うんだけど、率直に言ってどう?」って。

【鏡音リン】 ココロ 【オリジナル曲】

ある種のミク厨が持ってる曲の背景への妄想と、鏡音リンのミクとは少し違う独特の声を

彼女に紹介するという意味ではいいなと思うのと、それに加えていかにもトラボルタP的な

リンへの愛情をこれでもか、というぐらいに詰め込んでいるのが、紹介してみたい理由。

【初音ミク】 サイハテ 【アニメ風PV・オリジナル曲】

たぶんこれを見た彼女は「お母さんのこと思い出しちゃった」と言ってくれるかもしれないが、そこが狙いといえば狙い。

この系譜の作品がその後続いていないこと、これがミク厨の間では大人気になったこと、

メジャーレーベルならミリオンセラーになって、葬式の時の定番ソングになってもおかしくはなさそうなのに、

商業音楽でこういうのがつくられないこと、なんかを非オタ彼女と話してみたいかな、という妄想的願望。

「卑怯戦隊うろたんだー」をKAITO,MEIKO,初音ミクにry【オリジナル】修正版

「やっぱり音楽はノリの良さだよね」という話になったときに、そこで選ぶのは私の時間

でもいいのだけれど、そこでこっちを選んだのは、この作品にかけるシンPの思いが好きだから。

どんな卑怯な手を使ってでも勝つ正義の味方、っていう設定が、どうしても俺の心をつかんでしまうのは、

その勝てば官軍的な発想そのものが卑怯だなあと思えてしまうから。

コテコテのヒーローソングを俺自身は陳腐とは思わないし、もうこれ以上のべたな曲はないとは思うけれど、一方でこれが

デッドボールP乱数Pだったらきっちり名誉の除外にしてしまうだろうとも思う。

しかも、自身で歌ってみた動画を作るのみならず、デッドボールPゆうゆP、暴走Pなどが自重せずに歌ってみた動画うpしてしまう(デッドボールPゆうゆP暴走P。特にデPの歌ってみたは必聴。これ以上ないというぐらい卑怯だから)、というあたり、どうしても

「自分の猛る気持ちを自重できないオタク」としては、たとえシンPや他のPがそういうキャラでなかったとしても、

親近感を禁じ得ない。作品自体の高評価と合わせて、そんなことを彼女に話してみたい。

「celluloid」 song by 初音ミク

ミク厨以外でこの曲を聴いたことのある人はそんなにいないと思うのだけれど、だから紹介してみたい。

メルトよりも前の段階で、baker音楽センスとか作曲技法とかはこの作品で頂点に達していたとも言えて、

こういうクオリティの作品がインターネット上でこの時代に聴けたんだよ、というのは、

別に俺自身がなんらそこに貢献してなくとも、なんとなくミク厨としては不思議に誇らしいし、

いわゆる組曲系でしかミクを知らない彼女には見せてあげたいなと思う。

【初音ミク】恋スルVOC@LOID (修正版)【オリジナル曲】

ふたなりPの「センス」あるいは「曲づくり」をミク厨として教えたい、というお節介焼きから見せる、ということではなくて。

女の子からの一方的な愛情を表現した曲を聴きたい」的な感覚アクティブさに欠け、女の子への能動的なアプローチが苦手なオタクには共通してあるのかなということを感じていて、

だからこそryoの作るメルト恋は戦争ワールドイズマインが大ヒットしたんだとも思う。

「自分のことを盲目的に愛してくれる女の子がいてほしい」というミク厨の願望が今日さらに強まっているとするなら、その「ミク厨の欲望」の

源は恋スルVOC@LOIDにあったんじゃないか、という、そんな理屈はかけらも口にせずに、

単純に楽しんでもらえるかどうかを見てみたい。

初音ミクのちょっとアレな曲1 既成事実 -Full ver.- (修正版)

これは地雷だよなあ。地雷が火を噴くか否か、そこのスリルを味わってみたいなあ。

こういうエロゲOP的な男の劣情を刺激する歌詞をこういうかたちでボカロオリジナル曲にして、それが非ミク厨に受け入れられるか

気持ち悪さを誘発するか、というのを見てみたい。

【初音ミク】みくみくにしてあげる♪【してやんよ】

9本まではあっさり決まったんだけど10本目は空白でもいいかな、などと思いつつ、便宜的にみくみくを選んだ。

メルトから始まってみくみくで終わるのもそれなりに収まりはいいだろうし(理由は毎週ぼからんを見てればわかる)、ニコニコを代表する作品でもあるし、紹介する価値はあるのだろうけど、もっと他にいい作品がありそうな気もする。

というわけで、俺のこういう意図にそって、もっといい10本目はこんなのどうよ、というのがあったら

教えてください。

「駄目だこの増田は。俺がちゃんとしたリストを作ってやる」というのは大歓迎。

こういう試みそのものに関する意見も聞けたら嬉しい。

2007-12-23

財布を落とした(長くてオチのない)話。

フリーター(21)のチラシの裏

おとといの晩(金曜)に地元居酒屋で結構な量のビールを飲んだ。

流れで「ボーリングいこーぜ!」となってそのままボーリング場へ。

夜が明けてきて酒が抜けてきたところで帰宅、そして就寝。

そのまま半日爆睡してしまった僕は昼過ぎ(土曜)にコタツからおきだして

夕方からの仕事に備えて身支度を始めた。

シャワーを浴びて髪を乾かして着替えて持ち物を用意して。

そしていざ家を出ようとしたところで気づいた。

サ イ フ が な い

====

仕事先へは普段は二輪で行くところなんだけどその日はとんでもなく

雨が降っていたので電車でいくつもりだった。

踵を返し、部屋に戻りあたりを探し回るも財布はみつからず、

時間が差し迫っていたので家の中の小銭を回収して電車に乗って仕事場へ。

なんとか仕事を片付けて昨日(昨土曜)の夜中に帰宅。

とりあえず落ち着いて昨日の自分の行動を思い返してみよう。

Q.あなたが最後にサイフを使ったのはどこですか?

A.昨日ボーリング場で帰る直前、知人にアイスを買わされたのが最後

ということはそれ以後。

自分の財布を落としたとはあまり思いたくなかったので(現実逃避

家に帰ってからの自分の行動をトレースしてサイフを捜索することに。

1.玄関を開ける

2.靴を脱いで階段を上がる

3.自室に入りコタツON

4.寝る

なにもやってなくてコタツ周辺にサイフが無ければアウト!

コタツ周辺をくまなく探したんだけどやっぱりありません。

はぁ…落としたか。とサイフの中身を思い出す。

1.現金1諭吉(もうあきらめている)

2.キャシュカード(ヤバイ)

3.ネットバンキング乱数表(かなりヤバイ)

4.クレジットA社(ヤバイヤバイヤバイ)

5.クレジットB社(ヤバイヤバイヤバイ)

半日ほど現実逃避していたとはいえこれはヤバイ。

キャッシュカードの4桁の番号はランダムな数字を入れてるから

個人情報から類推されて使われたりしないからなんとかなるとしても

その口座のネットバンク乱数表があるのはヤバイ。

乱数表さえあればログインパスワードの変更もできたはずだ。

すかさず、暗記していた口座番号で口座の残金確認を果たす。

なんとか減ってないようで安心。

「もう現実逃避なんてしてらんねー。」てこと

落としているとすると

1.ボーリング場(確立低)

2.帰宅途中(確立高)

のどちらか。ボーリング場に電話するよりK察に聞いたほうが早いかな

ってことでK察へ電話

ルルーガチャ

K「もしもしー、増田警察ですー。」

僕「あーすいません。拾得物管理している課につないでいただけますか?」

K「は?・・・・・・・会計課ですか?」

僕「そですそです」

K「会計課は日曜なので出勤している人がいないんです」

僕「なんと!!!!!」

K「とりあえずお名前とサイフの特徴と何が入っていたかを」

僕「ごにょごにょ

K「じゃぁちょっとみてきてみます。」

(数行で書いたけどこの間ものすごいグダグダで、

 電話の向こうでしている会話とかガサゴソ音とか聞こえてくるし、

 あげくに別の人が電話にでてきたりするし。

 こんなところで管理しているのか…と思い冷や汗)

K「あーもしもし」

僕「ありましたか?(wktk

K「あーありますねー益田さんのサイフー」

僕「ほ、ほんとですか!」

K「はぁ、ただ名前の入ったキャッシュカードと現金が一万円の黒い皮の財布としか

  かかれてないんでねー、うーん。」

僕「あのー中身確認していただけないですか?最悪カードとか止めたいので」

K「あー祭日なんで担当がいないんですー」

僕「!!!!」

K「それでですねー今日は取りに来ていただけないので…」

僕「(さえぎって)とりあえず中身の確認だけでもしていただけないんですか?」

K「担当がいないと(ごにょごにょ

僕「・・・」

K「拾得物いれてる金庫が担当しか開けれないんで。」

僕「土曜に落としたんですが土曜は担当の方がいないんですよね。誰が金庫にいれたんですか?」

K「それは(ごにょごにょ

僕「確認もできないんでしょうか。」

K「はい!」(ここだけ歯切れがいい)

僕「担当の方に連絡していただくことはできないんでしょうか」

K「出勤してくるまでは無理です」

僕「それはいつになりますか」

K「火曜日の朝です。月曜は祝日なので」

僕「!!!!」

K「で火曜日にもう一度電話いただいて現状をもう一度説明していただいて」

僕「はぁ…(引継ぎもないんですか…)」

K「で取りに来てもらうしかないですね」

僕「確認すらできないんですね」

K「はい!」

僕「orz

で結局カードを止めました。落とした自分が悪い。それにつきる話。

でももうちょっとどうにかK察頑張ってほしいなぁと思った今日この頃

追記:

とりあえず拾ってくれた人に感謝せねば。

2007-09-14

伝えたければ、もう語るのをやめてください。

d:id:shi3z:20070913

言いたいことはわかりますよ。スタックを知っていれば、レジスタを知っていれば、メモリ管理の仕組みを知っていれば… そういう知識があればあるほど、問題に遭遇したときの解決が早くなる。

そういった事の体験学習の道具としてマシン語(というかアセンブリ)を薦めたい気持ちもわかりますよ。

でもね。煽りすぎなんです。あなたの文章は、「これは、こういう仕組みになっています。これの意味は、こういう事です」の後に必ず「こんな事も知らない奴は」「絶対に知っておくべきだ」という脅しをかける。だから攻撃的でイヤミになるんですよ。

あなたは、その文を読んだ人が「チクショウ!」と思って勉強することを期待しているんでしょうが、現実は「こんなイヤミな奴の言うこと聞きたくない」の方じゃないですか? そうして若い人たちがマシン語に背を向けてしまったら悲しくないですか。

思い出してください。マシン語プログラミングの主役だったあの時代、なぜ人々はわざわざマシン語を選んでいたのか。“オールBASIC”のプログラムでは逆立ちしても実現できないことが、マシン語ならできる。家のPC-8001ギャラクシアンが動く。それに感動して、あのスパイ乱数表みたいなリストを打ち込んだんでしょう。どこかのイヤミな野郎にケツを叩かれて始めたわけじゃないでしょう。今はそれがRubyだったりJavascriptだったりするわけです。

マシン語を知らない子供たちも、プログラミングの喜びは知っています。だから、もうやめてください。

かつてのマイコン少年より。

id:motomachi24

匿名相手じゃなくてもキツいことは言えるみたいですね。というか、キツいことを言えるのが嬉しいんですか?

2007-07-12

迷路成プログラムVC++2005でやってみた。

http://anond.hatelabo.jp/20070711013155 こちらの宿題を作ってみました。

http://anond.hatelabo.jp/20070711080519 で参加を宣言した者です。

#include "stdafx.h"
#include <time.h>
#include <conio.h>
#include <list>

using namespace std;

enum MMError {
	MME_None = 0,
	MME_SizeError,
	MME_MemoryAllocError,
	MME_NotInitialized,
};

enum MMKind {
	MMK_None = 0,
	MMK_Space,		// 通路
	MMK_Filled,		// 埋まってるところ。掘れる。
	MMK_Wall,		// 壁。掘れないところ。
};

//
// 迷路実体管理用クラス定義
//
class CMazeMatrix
{
public:
	CMazeMatrix();
	virtual ~CMazeMatrix();

public:
	virtual bool	Initialize(int nXSize, int nYSize);	// 初期化すると同時に、外壁まで作ってしまう。
	virtual MMKind	GetAt(int nXPos, int nYPos);
	virtual bool	SetAt(int nXPos, int nYPos, MMKind kind);

	MMError	GetLastError() {return m_lastError;}


protected:
	inline	int calcIndex(int nXPos, int nYPos) {return nYPos * m_nXSize + nXPos;}
	bool	finalize();

protected:
	MMKind	*m_pMaze;
	int		m_nXSize;
	int		m_nYSize;

	MMError	m_lastError;
};

//
// 実体管理用クラス実体
//
CMazeMatrix::CMazeMatrix()
{
	m_pMaze = NULL;
	m_nXSize = 0;
	m_nYSize = 0;
	m_lastError = MME_None;
}

CMazeMatrix::~CMazeMatrix()
{
	finalize();
}


bool CMazeMatrix::Initialize(int nXSize, int nYSize)
{
	finalize();

	int nSize = nXSize * nYSize;
	if ((__int64)nSize != (__int64)nXSize * (__int64)nYSize) {
		m_lastError = MME_SizeError;
		return false;
	}
	m_pMaze = new MMKind[nSize];
	if (m_pMaze == NULL) {
		m_lastError = MME_MemoryAllocError;
		return false;
	}

	m_nXSize = nXSize;
	m_nYSize = nYSize;

	int nCnt;
	for (nCnt = 0; nCnt < nSize; nCnt++) 
		m_pMaze[nCnt] = MMK_Filled;

	for (nCnt = 0; nCnt < m_nXSize; nCnt++) {
		m_pMaze[calcIndex(nCnt, 0)] = MMK_Wall;
		m_pMaze[calcIndex(nCnt, m_nYSize - 1)] = MMK_Wall;

	}

	for (nCnt = 0; nCnt < m_nYSize; nCnt++) {
		m_pMaze[calcIndex(0, nCnt)] = MMK_Wall;
		m_pMaze[calcIndex(m_nXSize - 1, nCnt)] = MMK_Wall;
	}
	return true;
}

MMKind	CMazeMatrix::GetAt(int nXPos, int nYPos)
{
#ifdef _DEBUG
	if (nXPos < 0 || nXPos >= m_nXSize ||
		nYPos < 0 || nYPos >= m_nYSize)
	{
		m_lastError = MME_SizeError;
		return MMK_None;
	}
#endif
	return m_pMaze[calcIndex(nXPos, nYPos)];
}

bool	CMazeMatrix::SetAt(int nXPos, int nYPos, MMKind kind)
{
#ifdef _DEBUG
	if (nXPos < 0 || nXPos >= m_nXSize ||
		nYPos < 0 || nYPos >= m_nYSize)
	{
		m_lastError = MME_SizeError;
		return false;
	}
#endif
	m_pMaze[calcIndex(nXPos, nYPos)] = kind;
	return true;
}

bool	CMazeMatrix::finalize()
{
	if (m_pMaze != NULL) {
		delete [] m_pMaze;
		m_pMaze = NULL;
	}
	return true;
}


//
// 迷路作成用クラス定義
//
class CMazeMaker
{
public:
	CMazeMaker();
	virtual ~CMazeMaker();

public:
	bool	Initialize(int nXSize, int nYSize);

	// 力業。ループで回す。メモリは食わない。
	// 美しくない。
	bool	Generate1();

	// 掘った箇所をスタックに積んで、掘れなくなったらスタックを戻す。
	// 綺麗だけれど、迷路のサイズを増やすとスタックオーバーフローが起こる。
	bool	Generate2();

	// Generate2をlistに置き換えたもの。
	// stdを使ってしまったのが心残り。
	bool	Generate3();

	MMError	GetLastError() {return m_lastError;}

protected:
	bool	finalize();
	bool	checkPos(int nXPos, int nYPos, int nXAdd, int nYAdd);
	int		process(int nXPos, int nYPos);
	void	dig(int nXPos, int nYPos);
	bool	makeStartGoal();
	virtual	CMazeMatrix* matrixAllocate();

protected:
	int		m_nXSize;
	int		m_nYSize;
	CMazeMatrix *m_pMatrix;
	MMError	m_lastError;
};


CMazeMaker::CMazeMaker()
{
	m_nXSize = 0;
	m_nYSize = 0;
	m_pMatrix = NULL;
	m_lastError = MME_None;
}

CMazeMaker::~CMazeMaker()
{
	finalize();
}

bool CMazeMaker::Initialize(int nXSize, int nYSize)
{
	finalize();

	m_pMatrix = matrixAllocate();

	if (m_pMatrix == NULL) {
		m_lastError = MME_MemoryAllocError;
		return false;
	}

	if (m_pMatrix->Initialize(nXSize, nYSize) == false) {
		m_lastError = m_pMatrix->GetLastError();
		return false;
	}

	m_nXSize = nXSize;
	m_nYSize = nYSize;

	return true;
}

CMazeMatrix* CMazeMaker::matrixAllocate()
{
	return new CMazeMatrix;
}

bool CMazeMaker::finalize()
{
	if (m_pMatrix != NULL) {
		delete m_pMatrix;
		m_pMatrix = NULL;
	}
	return true;
}


// スタート位置と、ゴールの位置を作成。外壁部分に穴を開ける。
// 今回のアルゴリズムでは、外壁のすぐ内側が通路になっていないことがあるので
// その場合には箇所を移動させる。
// どこをとっても通路が見あたらない場合には、エラーとする。
// (乱数の発生具合がとても意地悪な場合を考えると、可能性は少なくとも0ではない。)
//
bool CMazeMaker::makeStartGoal()
{
	// スタート地点を左の壁の上の方に
	int nCnt = 0;
	for (nCnt = 1; nCnt < m_nYSize - 1; nCnt++) {
		if (m_pMatrix->GetAt(1, nCnt) == MMK_Space) {
			m_pMatrix->SetAt(0, nCnt, MMK_Space);
			break;
		}
	}
	if (nCnt == m_nXSize - 1) {
		return false;
	}

	// ゴール地点を右の壁の下の方に
	for (nCnt = m_nYSize; nCnt > 0; nCnt--) {
		if (m_pMatrix->GetAt(m_nXSize - 2, nCnt) == MMK_Space) {
			m_pMatrix->SetAt(m_nXSize - 1, nCnt, MMK_Space);
			break;
		}
	}
	if (nCnt == 0) {
		return false;
	}
	return true;
}


// 現在位置nXPos, nYPosからみて、nXAdd、nYAddを足した位置に移動できるかをチェック
// 移動先が埋まっている状態で、さらに三方が通路以外に覆われているなら、OKとする

bool CMazeMaker::checkPos(int nXPos, int nYPos, int nXAdd, int nYAdd)
{
	if (m_pMatrix->GetAt(nXPos + nXAdd, nYPos + nYAdd) != MMK_Filled) 
		return false;

	if (nXAdd == 0) {
		if (m_pMatrix->GetAt(nXPos - 1, nYPos + nYAdd * 2) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos    , nYPos + nYAdd * 2) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + 1, nYPos + nYAdd * 2) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos - 1, nYPos + nYAdd ) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + 1, nYPos + nYAdd ) != MMK_Space)
		{
			return true;
		}
	} else {
		if (m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos - 1) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos    ) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos + 1) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd , nYPos - 1) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd , nYPos + 1) != MMK_Space)
		{
			return true;
		}
	}
	return false;
}


static const int moveInfo[4][2] = {
	{-1, 0},
	{0, -1},
	{1, 0},
	{0, 1},
};

int CMazeMaker::process(int nXPos, int nYPos)
{
	int digCount=0;
	int aryMove[4] = {0};	

	if (m_pMatrix->GetAt(nXPos, nYPos) != MMK_Space) {
		return 0;
	}
	while (1) {
		int nMoveCount = 0;

		for (int nCnt = 0; nCnt < 4; nCnt++) {
			if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) {
				aryMove[nMoveCount] = nCnt;
				nMoveCount++;
			}
		}
		if (nMoveCount == 0) {
			break;
		}
		
		int nMove = ((rand() >> 1) % nMoveCount);
		nXPos = nXPos + moveInfo[aryMove[nMove]][0];
		nYPos = nYPos + moveInfo[aryMove[nMove]][1];
		m_pMatrix->SetAt(nXPos, nYPos, MMK_Space);
		digCount++;
	}
	return digCount;
}


bool CMazeMaker::Generate1()
{
	// 開始点は1, 1から。(ループの先頭
	m_pMatrix->SetAt(1, 1, MMK_Space);

	::srand((unsigned int)time(NULL));
	
	int nXCnt;
	int nYCnt;

	for (nXCnt = 1; nXCnt < m_nXSize - 1; nXCnt++) {
		for (nYCnt = 1; nYCnt < m_nYSize - 1; nYCnt++) {
			while (process(nXCnt, nYCnt) != 0) {}
		}
	}
	return makeStartGoal();
}


void CMazeMaker::dig(int nXPos, int nYPos)
{
	m_pMatrix->SetAt(nXPos, nYPos, MMK_Space);

	int aryMove[4] = {0};	

	while (1) {
		int nMoveCount = 0;

		for (int nCnt = 0; nCnt < 4; nCnt++) {
			if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) {
				aryMove[nMoveCount] = nCnt;
				nMoveCount++;
			}
		}
		if (nMoveCount == 0) {
			break;
		}
		
		int nMove = ((rand() >> 1) % nMoveCount);

		dig(nXPos + moveInfo[aryMove[nMove]][0], nYPos + moveInfo[aryMove[nMove]][1]);
	}
}

bool CMazeMaker::Generate2()
{
	::srand((unsigned int)time(NULL));
	int nXStart = ((rand() >> 1) % (m_nXSize - 2)) + 1;
	int nYStart = ((rand() >> 1) % (m_nYSize - 2)) + 1;
	dig(nXStart, nYStart);
	return makeStartGoal();
}

struct PosInfo {
	int xPos;
	int yPos;
};

bool CMazeMaker::Generate3()
{
	::srand((unsigned int)time(NULL));
	int nXStart = ((rand() >> 1) % (m_nXSize - 2)) + 1;
	int nYStart = ((rand() >> 1) % (m_nYSize - 2)) + 1;

	m_pMatrix->SetAt(nXStart, nYStart, MMK_Space);

	list<PosInfo> posList;

	PosInfo info = {nXStart, nYStart};
	posList.push_back(info);

	while (posList.size() != 0) {
		int nXPos = (posList.rbegin())->xPos;
		int nYPos = (posList.rbegin())->yPos;

		int aryMove[4] = {0};	

		int nMoveCount = 0;

		for (int nCnt = 0; nCnt < 4; nCnt++) {
			if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) {
				aryMove[nMoveCount] = nCnt;
				nMoveCount++;
			}
		}
		if (nMoveCount == 0) {
			posList.pop_back();
			continue;
		}
		
		int nMove = ((rand() >> 1) % nMoveCount);

		info.xPos = nXPos + moveInfo[aryMove[nMove]][0];
		info.yPos = nYPos + moveInfo[aryMove[nMove]][1];

		m_pMatrix->SetAt(info.xPos, info.yPos, MMK_Space);

		posList.push_back(info);
	}

	return makeStartGoal();
}

//
// コンソール出力用
class CMazeMakerConsole : public CMazeMaker
{
public:
	CMazeMakerConsole(){};
	virtual ~CMazeMakerConsole(){};

public:
	void Output();
};

void CMazeMakerConsole::Output()
{
	for (int nYCnt = 0; nYCnt < m_nYSize; nYCnt++) {
		for (int nXCnt = 0; nXCnt < m_nXSize; nXCnt++) {
			if (m_pMatrix->GetAt(nXCnt, nYCnt) == MMK_Space) {
				printf(".");
			} else {
				printf("#");
			}
		}
		puts("");
	}
	_getch();
}

// 
//
int _tmain(int argc, _TCHAR* argv[])
{
	CMazeMakerConsole maker;

	do {
		if (false == maker.Initialize(75, 50)) {
			puts("Initialize Error");
			return 0;
		}
	} while (false == maker.Generate3()); //失敗するのは、スタート、ゴールが作れなかった場合。偶然そういうことになることもあるので、そうなったら作り直す。


	maker.Output();

	return 0;
}

最初に昔の記憶を頼りにCMazeMaker::Generate1()を作ったけれど、美しくなかったのでGenerate2()を作成。迷路のサイズを増やすとスタックオーバーフローになるので、Generate3()を作成。一応、満足。

###########################################################################
.....##...#.#.##.....##......#....#...#.#.#.........#.##.........##.#.....#
#.#.##..#.#......###..###.##.#.##.#.###...#.#####.#....##.######....##.##.#
#.#..##.#.#.##.###.##.....##...#....#...#.....##..#.##.#..##...####..#..#.#
#.##..###.#..#..##..###.#..###.#.####.###.#####..####..#.##..#....##.##.#.#
#..##.....##.##..##...#.##..#######...#.#.#...#.##....##.#..###.#..#.##.###
#.####.#####.###.###.##..####.......###.###.#.###..##.#..#.##...##.#..#...#
#....###......#..#.#....##....########..##..#..#..#####.######.##..##.##.##
#.##..##.######.##...####..#####....#..##..###.#.##.##..#......#..###..#..#
#..##.#...##....#..#.#..#.##.#...#.##.##..##.....#.....####.####.##.##.##.#
##..#...#..#.#######...##....#.#####..#..#########.##.##.#..##...##..#....#
###.########.##...##########.#...##..##.##.##...####..#....##..###..#####.#
#.#..##...##..#.#.....##.....##.##..##..#...###.#.#..###.####.##...##.....#
#.##.#..#..##.#.#####.#..#####..#..##..##.#.....#...##.#.#....####.#..#####
#..#.#.###.#..#.....#...##.....##.##..##..##.##.#.###....####.#.#..#.###..#
#.##.#.##....######.########.###..#..###.##..#....#.##.#...#..#...##...##.#
#..#.#..###.##.#....#..#.....##..###..#...#.#######....#.#.#.##.#.####.##.#
##.#.##.##...#.#.#####...#####..##.##.##.##......#####.###.#.#..#..#.#..#.#
##....#..###...#....#..#.....#.##...#.#...#.#.##.....#..##.#...###...##...#
#..#####...########.####.##.##....#...#######..#####.####..#####.########.#
#.##.#.###..#.....#....###...###########...###..##...#....##.........##...#
#..#....###...#.#.####..#..#.....#.#.....#..#..##..###.#.##..#######.#..###
##.####...#######...###.##.#.###.#...######.####..##...#.#..##...#...#.##.#
#....####...#...###...#..#.#..####.#....#.....#..##..#.###.##..#.#.###.#..#
####...#..#.#.#..####.##.####......####.#####.##..#.##...#..####.#.#...#.##
##.###.#.##.#.##.#.#...#....##.######.#.##..#.###.######.##...#..#...###..#
#..##..#.####.##.#...#.####..#........#..##....##...##....###...######...##
#.##..##..##..#..##.####..##.#.######.##..####..#.#..##.###.#.#..#.##..#..#
#.##.####.#..##.##..##...###.###...#...##.##.##.####.#..#...####.#..#.###.#
#.#...#...#.###..##..#.#...#..#..#...#..#..#.##..##..#.##.#..##..##.#...###
#...#...#.#...##..##...#.####.####.#######.#..##.#..##..#.##..##..#...#...#
#.###########.###..#####....#...##.#..#....##..#...####.#..##..##.#######.#
#....#....##..#.##....###.#####..#...##.######.#####.##.##.###....#.....#.#
###.##.#.##..##..####..#..#...##.###.##......#...##.....##..########.##.#.#
#.#.#..#..#.####.#..##...##.#.#..#....######.#.#....#.#..##.#...##...#....#
#...#.###...#......####.##..#...###.###...##.#.######.#.##..#.#..##.####.##
#.#.#.#.#####.###.##....#..######.#.##..#..#.#..#.....#..##...##.#...#....#
#.###.#...##...#..#..####.##.#.##.#.#..##.##.##.#.###.##..######.#.#.####.#
#..##.#.#..#.#.####.###.#..#......#...#####..#..#...####.##..#.#.###.##...#
##..#...##.#.#.#........##.#.#.#.####..#....#######..##...##...#..#...###.#
###.######.#.#...####.#..#.#.###.#..##.#.####....###..###..##.###.###...#.#
#...#...#..#####...##.####.#..#....##..#..#...##...##...##......#..####.#.#
#.###.#...##...#####..##...##.#.##.#..###.#.######..##.###########.#....#.#
#..#..##.##..#.#...#.##..######..###.##.#....###.##.##...#.......#.#.#.####
#.##.###..#.##...#.###..##....##........#.##..#...#..#.#.#.###.#.#.###....#
#..#...##.#..#####..##.####.#.##.############...#.##.#.#.#...#.###..##.##.#
##.###..###.##...##.#..#....#..###....##....#######..#.###.###...##..###..#
#...###..#...##.###.#.##.#####...#.##.#..##.#...#...##..#...###.####.#...##
#.#...##...#......#......#.....#...#....##....#...#..##...#...#........#...
###########################################################################

ちなみに http://anond.hatelabo.jp/20070711194709 これを聞いたのは自分。

かなりたくさん書けることがわかりました。

ログイン ユーザー登録
ようこそ ゲスト さん