2

環境がランダムに生成されるゲームをPythonで書いています。現在、ゲームの「保存」機能は、プレイヤーが探索した環境のすべての部分を書き出すことによって機能します。その結果、セーブ ファイルは必要以上に大きくなります。再生成できるのに、ランダム データをディスクに書き込む必要はありません。

私が使用できるのは、ランダム ノイズ関数です。乱数を返すnoiseような関数で、同じ値で呼び出されたときはいつでも常に同じ番号です。これで、ゲーム環境の各ポイントに対して、を使用して乱数を生成し、結果を に保存する代わりに、 を使用して乱数を生成し、それを破棄して、後で同じ数を生成することができます。noise(x)x(x,y)random()env[(x,y)]noise((x,y))

4

3 に答える 3

4

明らかなことを述べているかどうかは定かではありませんが、パーリン ノイズ ジェネレーターのいくつかのバリエーションを使用することは、これを行う一般的な方法です。この投稿は、これを正確に行うための優れた説明です(コメントで述べたように、正確にはパーリンノイズではありません

指定された位置に対して、Perlin 関数はランダムな値を返します (位置は 2D、3D、または任意の次元にすることができます)。

ノイズモジュールがあり、このページにはその実装があります

gamedev.SEにも同様のスレッドがあります

于 2012-10-18T02:14:40.323 に答える
2

まず、noise(x) が同じ x に対して常に同じ値を返すことを真にする必要がある場合は、たとえそれが呼び出されていなくても、実際にはランダム性をまったく使用できません。適切なハッシュ関数が唯一の可能性です。

ただし、以前に探索したすべてのポイントの値で構成される以前の状態を復元できるようにする必要がある場合(未探索のポイントは、終了していない場合とは保存および読み込み後に異なる場合があります... しかし、どうすれば複数のユニバースへのアクセスなしに誰が言うのですか?)、そしてそれらのポイントのすべてを保存したくない場合は、それらを再生成することが合理的かもしれません.

しかし、一歩後退しましょう。ハッシュ関数のように機能するものが必要です。使用できるハッシュ関数はありますか?

hashlibのアルゴリズムが遅すぎると思います (おそらくmd5最速ですが、すべてをテストします) が、実際にテストせずにそれらを拒否することはありません。

zlib.adler32(または)の「ランダムな期間」がzlib.crc32短すぎる可能性がありますが、それでhash十分かどうかを考えずに (おそらく を除いて) 拒否することはありません。さらに言えば、まともな固定側ブレンダー機能を加えてもhash十分かもしれません (少なくとも 64 ビット システムでは)。

md5Python には、すぐに使用できる「adler32」と「中間」のものは何もありません。しかし、他の何百ものハッシュ アルゴリズムの PyPI モジュールやソース レシピを見つけることができます。さらに言えば、良さそうな特定のハッシュ アルゴリズムに精通している場合、それらのほとんどは自明なものです。代替案。

また、「新しいゲーム」時に大量のランダムなバイトを生成し、それを保存ファイルに保存して、ハッシュ関数へのソルトとして使用できることに注意してください。

可能性を使い果たした場合、任意のソルトを使用した十分に高速なハッシュ関数が単独で提供できるよりも多くのランダム性が本当に必要な場合は、次のようになります。

ユーザーが探索したポイントのリストを保存する必要があるようです (復元する必要があるポイントを他にどのように知ることができるでしょうか?)。そして、順序は重要ではありません。そのため、探索順に格納できます。つまり、(リストを反復するだけで) 決定論的に値を再生成できます。つまり、@delnan による提案を自分の回答に使用できます。

ただし、seedそれを行う方法ではありません。実行、Python バージョン、マシンなどで毎回 RNG を同じ状態にすることは保証されていません。そのためには、次のものが必要ですsetstate

  • 保存するには、 を呼び出しrandom.getstate()、ピクルして結果を隠します。
  • ロードするには、状態を読み取り、unpickle して、 を呼び出しますrandom.setstate(state)

詳細については、ドキュメントを参照してください。

インスタンスを使用している場合は、それを呼び出す前にrandom.Randoma を作成する必要があることを除いて、まったく同じです。random.Randomsetstate

これは、プログラムの実行間、マシン間などで動作することが保証されています。Python の新しいバージョンでも動作します。ただし、古いバージョンの Python での動作は保証されていません。(つまり、ユーザーがゲームを Python 2.6 で保存し、それを 2.5 で読み込もうとすると、状態は互換性がなくなります。問題は 2.6-> 古いものと 2.3-> 古いものだけだと思いますが、もちろん、将来追加のものがないという保証はありません。) 私は Python のバージョンを隠しておくことをお勧めします。それらがダウングレードされている場合は、「この保存ファイルには Python 2.6 以降が必要です。Python 2.5 を使用しています。読み込みに失敗する可能性があります。続行しますか?"

random.Randomこれは、モジュール自体に対してのみ保証されrandomます (トップレベルのモジュール関数は hidden を使用するだけなのでrandom.Random)。特に、random.SystemRandom動作しないことが明示的に文書化されています。

実際には、a を直接ピクルすることもできますrandom.Random。これは、状態がピクルされるためです。それは機能するはずですが、Randomオブジェクトをピクルする意味は何ですか? そして、それは間違いなく機能します。しかし、実際に動作するように文書化されていないのでgetstate、安全のために , を酸洗いすることに固執します.

于 2012-10-18T01:06:40.820 に答える
1

の 1 つの可能な実装noiseは次のとおりです。

import random

def noise(point):
    gen = random.Random()
    gen.seed(point)
    return gen.random()

どれくらい速いかはわからないけどRandom.seed()。さらに、RandomPython のあるバージョンから次のバージョンに変更される可能性があり、私のゲームのプレイヤーは、アップグレードすると環境が変わることに気付くことになります。

于 2012-10-18T00:19:15.347 に答える