予測可能なランダムジェネレーターの必要性


151

私はウェブゲームの開発者で、乱数に問題がありました。プレーヤーが剣でクリティカルヒットを得る確率が20%であるとしましょう。つまり、5ヒットのうち1ヒットが重要です。問題は、実際の結果が非常に悪いことです。5ヒットで3クリティカル、15ヒットでまったくクリティカルにならない場合があります。戦いはかなり短い(3-10ヒット)ので、良いランダム分布を得ることが重要です。

現在はPHPを使用していますがmt_rand()、コードをC ++に移動しているだけなので、ゲームの新しいエンジンでこの問題を解決したいと考えています。

解が均一な乱数発生器であるかどうか、または適切な分布を強制するために以前のランダムな状態を覚えているかもしれません。


58
真の乱数を仮定すると、厳密に3つのクリティカルヒットと2つの非クリティカルヒットの確率は約0.5%であり、連続して15の非クリティカルヒットの3.5%の確率があります。
Nixuz、2009年

10
上記に+1。乱数の特徴の1つは、外れ値を取得することです。
ConcernedOfTunbridgeWells

45
@Nixus:いいえ、3つのクリティカルヒットと2つの非クリティカルヒットの確率は約5%であり、(5!/(3!* 2!))= 10を掛けるのを忘れています。95%の信頼レベルでは、 5つのストライキで3つのクリティカルヒットが発生する可能性は統計的にありません。
erikkallen 2009年

7
最初はこれはばかげた質問だと思いました...もう一度、私はSOに謙虚になりました。
SergioL 2009年

回答:


39

一部のゲームの小規模な実行における真のランダム性は望ましくないという以前の回答に同意します-一部のユースケースでは不公平に思えます。

Rubyでの実装のような単純なシャッフルバッグを作成し、いくつかのテストを行いました。実装はこれを行いました:

  • それでもフェアであると思われる場合、または最小ロールのしきい値に達していない場合は、通常の確率に基づいてフェアヒットを返します。
  • 過去のロールから観測された確率が不公平に見える場合、「公正な」ヒットを返します。

境界確率に基づいて不公平と見なされます。たとえば、20%の確率で、10%を下限、40%を上限として設定できます。

これらの範囲を使用して、10ヒットの実行で、実際の疑似ランダム実装が14.2%の時間でこれらの範囲外の結果を生成したことがわかりました。時間の約11%で、10回の試行で0のクリティカルヒットが記録されました。3.3%の確率で、5回以上のクリティカルヒットが10から発生しました。当然、このアルゴリズムを使用して(最小ロールカウントは5)、「フェアリー」ランのはるかに少ない量(0.03%)が範囲外でした。 。以下の実装が不適切な場合でも(確かにもっと賢いことが可能です)、実際の疑似ランダムソリューションでは不公平であるとユーザーが感じることは注目に値します。

FairishBagRubyで書かれた私の肉は次のとおりです。実装全体とクイックモンテカルロシミュレーションは、こちらから入手できます(要旨)

def fire!
  hit = if @rolls >= @min_rolls && observed_probability > @unfair_high
    false
  elsif @rolls >= @min_rolls && observed_probability < @unfair_low
    true
  else
    rand <= @probability
  end
  @hits += 1 if hit
  @rolls += 1
  return hit
end

def observed_probability
  @hits.to_f / @rolls
end

更新:この方法を使用すると、クリティカルヒットが発生する可能性が全体的に増加し、上記の範囲を使用すると約22%になります。「実際の」確率を少し低く設定することで、これを相殺できます。フェアリッシュな修正を加えた17.5%の確率は、約20%の観測された長期確率をもたらし、短期の実行を公平に保ちます。


これは私のニーズに合った最良のソリューションだと思います。ベストポインテッドアンサーで言及されているシャッフルバッグは悪くありませんが、多くの計算が必要であり、ターゲットにつながる最も簡単なソリューションが好きです。
思想家

スティーブ・ラビンはゲームのランダム性について興味深い記事を書きました。要するに、真の「ランダム」な振る舞いは、ほとんどの人にとって実際にランダムな「感じ」ではなく、研究がこれを裏付けています。彼の記事はAI決定とゲームロジックのためのフィルターされたランダム性と呼ばれ、「AIゲームプログラミングの知恵2」(2003)に掲載されています。あなたはそれをチェックするべきです、おそらくあなたに役立つでしょう。
ジェフタッカー

@IanTerrellテストのサンプルサイズがどれだけ大きいか、つまり、それらの確率を決定するためにどれだけのバトルが行われるかを述べるとよいでしょう。

@ user677656:要点はありますが、100kです
Ian Terrell

223

つまり、5ヒットのうち1ヒットが重要です。問題は、実際の結果が非常に悪いことです。5ヒットで3クリティカル、15ヒットでまったくクリティカルにならない場合があります。

必要なのはシャッフルバッグです。真のランダムがゲームにとってランダムすぎるという問題を解決します。

アルゴリズムは次のようなものです。1つのクリティカルヒットと4つの非クリティカルヒットをバッグに入れます。次に、バッグの順序をランダムにして、一度に1つずつ取り出します。バッグが空の場合は、同じ値を再度入力してランダム化します。このようにして、5ヒットあたり平均1クリティカルヒット、最大で2クリティカルヒットと8ノンクリティカルヒットを続けて取得できます。バッグ内のアイテムの数を増やしてランダム性を高めます。

これは、(Javaでの)実装の例と前に書いたテストケースです。


21
+ 1は批判のない良いアイデアです。より高度なランダム性のためにバッグをスケーリングし、プレイヤー間のクリティカルチャンスの変動に対処します(変数ofcの場合)
TheMissingLINQ 2009年

16
バッグのサイズは10です。1ヒットを入れると、30%の確率で1秒になります。クリティカルチャンスが変わった場合は、バッグを捨てて新しいバッグを開始することができます。このようなスキームは、あなた(またはあなたの対戦相手)がクリティカルヒットの確率とバッグのサイズを知っている場合に、特定の数のロールで別のクリティカルが発生しないことが確実にわかる場合があることに注意してください。これは戦術に影響を与える可能性があります。
スティーブジェソップ

3
ええと...このようなもので、あなたはカードを数えるのと同様のリックを実行します。ピョンを危険にさらすのか、それとも大量殺戮に参加するのか...固定された潜在的な結果の小さなセットは、損失のリスクを減らし、「賭け」の可能性を高めることができる
マシューホワイト

8
シャッフルバッグのアイデアは好きですが、クリティカルヒットの確率が20%(つまり、10ヒットで何もできない)はもう確率ではないので、これはゲームの「精神」とは一致しません。5ヒットごとに1ヒットになります。さらに、クリティカルヒットの確率が変化した場合にバッグを再ロールすると、ゲームに不具合が発生します。私のクリティカルヒットが行われた場合、次の評論家を早く獲得するために自分に呪文をかけます:p
ミハエルカーペンティア

2
@ジョナサン:バッグのサイズを大きくすると、実際にはバッグ全体のアイデアが元に戻ります。許容できるスロー数の範囲内で何かが発生する(達成されるクリティカル)ことを確認します。バッグを50000に大きくすることは、乱数ジェネレータを使用することとほぼ同じです。
dstibbe 2009

113

ランダムの意味が誤解されています。

これらのうちどれがよりランダムですか?

ここに画像の説明を入力してください ここに画像の説明を入力してください

2番目のプロットはより均等に分布しているように見えますが、実際にはよりランダムなものが最初のプロットです。人間の心はパターンをランダムに見ることが多いので、最初のプロットの塊はパターンとして見えますが、そうではなく、ランダムに選択されたサンプルの一部にすぎません。


25
良いNumb3rsの説明!
RMAAlmeida、2009年

9
技術的には、ランダム性を測定することはできません。どちらの分布も私にはかなり恣意的に見えますが、私の推測はどちらもアルゴリズムで生成されたものです。最初のプロットでいくつかのテストを実行し、均一分布に従ってポイントを配置するプロセスからのものである可能性が高いと判断できますが、よりランダムであると結論付けることはできません。反例として、線形合同発生器を使用して最初のようなプロットを作成し、ツェナーダイオードからの増幅ノイズを使用して2番目のようなプロットを作成できます。ランダムではなく無相関の単語を試してください。
ディートリッヒエップ

8
上記の分布がランダムである確率を測定できます。
ceejayoz、2009年


2
公平を期すために、OPは正しい用語を使用していない可能性がありますが、ユーザーにとってより「公平」であると感じるため、乱数ジェネレーターが最初のグラフのようなものを提供していることを理解しています。
Kip

88

あなたが求めている振る舞いを考えると、あなたは間違った変数をランダム化していると思います。

このヒットがクリティカルになるかどうかをランダム化するのではなく、次のクリティカルヒットが発生するまでターン数をランダム化してみてください。たとえば、プレーヤーがクリティカルを取得するたびに2から9までの数を選択し、そのラウンド数が経過した後に次のクリティカルを与えるだけです。サイコロの方法を使用して正規分布に近づけることもできます。たとえば、2D4ターンで次のクリティカルを取得します。

このテクニックは、地上でもランダムに遭遇するRPGで使用されると思います。ステップカウンターをランダム化し、その数のステップの後で、再びヒットします。2回続けて遭遇することはほとんどないので、より公平に感じられます。それが一度でも発生すると、プレイヤーはイライラします。


これは素晴らしい解決策だと思いますが、80%の確率はどうでしょうか。
思想家

時々、多次元のランダムジェネレーターを使用することも好きです。ヒットするチャンス+パワーにチャンス+クリティカルにチャンス ただ、D&Dでいくつかの異なるサイコロを転がすように
マシュー白く塗った

私はこのアイデアが好きです、そしてあなたはステップカウンターの事について完全に正しいです、それは例えば非常に長い間ファイナルファンタジーで使われていました
エド・ジェームズ

これに関する1つの問題は、クリティカルの確率がヒット間でほぼ一定である場合にのみ機能することです。戦闘中、プレーヤーがクリティカルヒットの可能性を2倍にする呪文を唱えたとします。それでは、ターン数をどのように調整しますか?
Alex319

+1非常に優れており、20%よりも少ないラウンドのヒット確率を非常に簡単に処理します。
アリスパーセル

53

まず、「適切な」分布を定義します。乱数はまあ、ランダムです-あなたが見ている結果は(疑似)ランダム性と完全に一致しています。

これをさらに拡大すると、「フェアネス」の感覚が欲しいと思うので、ユーザーは100ターン成功することができません。もしそうなら、私は最後の成功以降の失敗の数を追跡し、生成された結果に重みを付けます。5分の1のロールで「成功」したいとしましょう。したがって、1から5までの数をランダムに生成し、5の場合は素晴らしいです。

そうでない場合は、失敗を記録し、次に1から5までの数を生成しますが、たとえば、floor(numFailures / 2)を追加します。したがって、今回も、5分の1のチャンスがあります。それらが失敗した場合、次回の勝ちの間隔は4 5です。成功の5分の2の確率。これらの選択により、8つの失敗の後、それらは確実に成功します。


そのノートでは...乱数の範囲が分布に影響を与えます...たとえばRandom r = new Random();を選択します。r.Next(1,5)対r.Next(1、1000000)%200000
Eoin Campbell

23
ランダムに誤解しているOPに伝える代わりに、リクエストの背後にある問題を確認するための+1。
Boris Callens、

4
これを行うと、成功の全体的な比率は5分の1を超えることに注意してください。これを回避する方法は、たとえば、1..100の範囲からランダムに20の異なる数を選択し、それらが事前に決定することです。彼らの重要なことです。ただし、これはかなりの簿記です。
スティーブジェソップ

「5分の1を超える」-長期的には予想されます。
スティーブジェソップ

開始確率を少し下げて、全体の比率を1/5に減らすことができます。どれだけ削減する必要があるかはわかりませんが、すべてが継続的であるため、正しい答えが必要です。
スティーブジェソップ

35

mt_rand()をこのようなものに置き換えてみませんか?

XKCDコミック(RFC 1149.5では、標準のIEEE検査済みの乱数として4が指定されています。)

(RFC 1149.5は、標準のIEEE検査済み乱数として4を指定しています。)

XKCDから。


良い問題ですが、これはOPの乱数分布の問題を解決しますか?;-)
Arjan Einbu、2009年

あんまり; 彼はこの関数を使用できるランダムでないRNGを求めています。しかし、彼が本当に望んでいることは、より良い現在のトップの答えによって説明される(stackoverflow.com/questions/910215/910224#910224
コリン・ピカード

28
これはOPの欲求よりもランダムである
ÇağdaşTekinの

-1 RFC1149にはセクション5がないため(代わりに1149.5がないため)。+1はランダム性を高めます。
greyfade 2011

34

この記事がお役に立てば幸いです:http : //web.archive.org/web/20090103063439/http : //www.gamedev.net :80/reference/design/features/randomness /

「乱数」を生成するこの方法は、rpg / mmorpgゲームでは一般的です。

それが解決する問題はこれです(抜粋):

ブレードスパイダーが喉に近づいています。ヒットしてミス。それは再びヒットし、あなたは再びミスします。そして、何度も何度も、あなたに当たるものがなくなるまで。あなたは死んでいて、死体の上に2トンのクモが浮かんでいます。不可能な?いいえ、ありそうですか?はい。しかし、十分なプレーヤーと十分な時間が与えられれば、ありえないことはほぼ確実になります。ブレードスパイダーが硬かったのではなく、不運だった。いらいらする。プレイヤーをやめたければ十分です。


1
私はこれに関する変形を聞いた-「100万分の1のイベントが世界の人口で6,000回発生する」。
ceejayoz

19

必要なのは乱数ではなく、人間にはランダムに見える数字です。他の人は、Shuffle Badのように、あなたを助けることができる個々のアルゴリズムをすでに提案しています。

このドメインの詳細で広範な分析については、AI Game Programming Wisdom 2を参照してください。本全体はどのゲーム開発者にとっても読む価値があります。「一見すると乱数」という考えは章で処理されます。

AIの決定とゲームロジックのフィルタリングされたランダム性

要約:従来の知識では、乱数発生器が優れているほど、ゲームの予測が難しくなることが示唆されています。ただし、心理学の研究によると、短期間の真のランダム性は、多くの場合、人間には明らかにランダムであるように見えます。この記事では、強力な統計的ランダム性を維持しながら、ランダムなAIの決定とゲームロジックをプレイヤーにとってよりランダムに見えるようにする方法を示します。

別の章も興味深いかもしれません:

乱数の統計

要約:乱数は、人工知能およびゲーム一般で最も頻繁に使用されます。彼らの可能性を無視することは、ゲームを予測可能で退屈なものにすることです。それらを誤って使用することは、完全にそれらを無視するのと同じくらい悪いことです。乱数がどのように生成されるか、それらの制限と機能を理解することで、乱数をゲームで使用する際の多くの困難を取り除くことができます。この記事では、乱数、その生成、および良いものと悪いものを区別する方法についての洞察を提供します。


8

確かに任意の乱数生成がそのような実行を生成する可能性がありますか?適切なパーセンテージを表示するのに十分な大きさのサンプルセットを3〜10個のロールで取得することはありません。

たぶん、あなたが望むのは慈悲のしきい値でしょう...最後の10のロールを思い出してください。クリティカルヒットがなかった場合は、景品をあげてください。ランダムのスリングと矢印を滑らかにします。


8

最善の解決策は、複数の異なるランダムスキームを使用してプレイテストを行い、プレイヤーを最も幸せにするものを選択することです。

たとえば、プレーヤーが1最初のターンにを出してそれを受け入れた場合など、特定のエンカウンターで同じ番号に対してバックオフポリシーを試すこともできます。別のものを手に入れるために、1彼らは2 1秒続けて振る必要があります。3分の1を取得するに1は、連続して3 が必要です。


7

残念ながら、あなたが求めているのは事実上、非乱数ジェネレータです-次の数を決定するときに以前の結果を考慮に入れたいからです。これは、乱数発生器がどのように機能するかではありません。

5ヒットごとに1クリティカルにする場合は、1から5までの数値を選択して、そのヒットがクリティカルになると言います。


1
彼はゲームに優しいランダムを望んでいます。厳密なランダムに生成された数値を使用すると、「韓国のランダム」な結果になる場合があります。これらはランダムな結果であり、プレーヤーを怒らせてイライラさせる頻度が高くなります(系統2のプレーヤーに質問してください);)
Juan Techera

したがって、最初のヒットがクリティカルである場合、次の4つはクリティカルではありません。これはOPが望んでいるように聞こえますが、このように言うと、遅れて聞こえます。あなたは私のUVを手に入れます。
belgariontheking 2009年

-1「ランダム」と「メモリレス」を混同しているように見える-en.wikipedia.org/wiki/Memorylessness
Alice Purcell

7

mt_rand()はMersenne Twisterの実装に基づいています。これは、取得できる最良のランダム分布の1つを生成することを意味します。

どうやら必要なのはランダム性ではないので、必要なものを正確に指定することから始める必要があります。期待が矛盾していることに気づくでしょう-結果は真にランダムで予測不可能であると同時に、指定された確率からの局所的な変動を示さないはずですが、その後予測可能になります。連続して最大10の非クリティカルを設定した場合は、「連続して9の非クリティカルがあった場合、次のクリティカルは100%の確率でクリティカルになる」とプレイヤーに伝えたことになります。まあ、ランダム性はまったく気になりません。


6

このような少数のテストでは、次のような結果が期待できます。

真のランダム性は巨大なセットサイズでのみ予測可能です。つまり、コインを裏返して最初に3回続けて表を出すことは十分に可能ですが、数百万回以上の裏返しでは、結果として約50〜50になります。


7
数百万枚のコイン投げの後も、コインの片面しか見られない可能性はまだあります。これが起こったとしても、おそらく無限の可能性のないドライブの近くに座っているでしょう:P
Grant Peters

はは、ええ、でもチャンスは信じられないほど低いので、数学の法則は、あなたが偶数分布を見る必要があると言っています。
エドジェームス

6

以前に生成された数値を追跡すること、またはすべての可能な値をシャッフルすることを提案する多くの回答が表示されます。

個人的に、私は同意しません、連続して3つのクリティカルが悪いことです。また、連続して15の非クリティカルが悪いことにも同意しません。

私は、各数値の後に、クリティカルチャンスを修正することで、問題を解決します。例(アイデアを示すため):

int base_chance = 20;
int current_chance = base_chance;

int hit = generate_random_number(0, 100) + 1; // anything from 1 to 100
if(hit < current_chance)//Or whatever method you use to check
{
    //crit!
    if(current_chance > base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 0.8; // decrease the crit chance for the NEXT hit.
}
else
{
    //no crit.
    if(current_chance < base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 1.1; // increase the crit chance for the NEXT hit.
    //raise the current_chance
}

クリティカルが長くならないほど、次のアクションがクリティカルになる可能性が高くなります。私が含めたリセットは完全にオプションであり、それが必要かどうかを判断するにはテストが必要です。クリティカルではない長いアクションチェーンの後で、連続する複数のアクションに対してクリティカルの確率が高くなることが望ましい場合と望ましくない場合があります。

私の2セントを投入するだけ...


私はこのようなアプローチが好きです。私はおそらくそれを別の方法で行うでしょう。低い確率で開始し、ヒットするまで最大20%+いくつかの追加されたパーセンテージまで構築し、再度低い量にリセットします。
マシュー

5

上位のいくつかの回答は優れた説明であるため、「不良ストリーク」の確率を制御しながら、決定論的になることのないアルゴリズムに焦点を当てます。これはあなたがすべきだと私が思うことです:

代わりに、指定のP、クリティカルヒットのあなたの確率であるベルヌーイ分布のパラメータを指定し、Bをベルヌーイ分布の「共役前」、ベータ分布のパラメータを設定します。これまでのクリティカルヒットと非クリティカルヒットの数であるABを追跡する必要があります。

ここで、aおよびbを指定するために、クリティカルヒットの可能性であるa /(a + b)= pであることを確認します。(a + b)は、A /(A + B)を一般にpにどの程度近づけたいかを数値化したものです。

次のようにサンプリングを行います。

p(x)ベータ分布の確率密度関数とします。多くの場所で入手できますが、GSLでgsl_ran_beta_pdfとして見つけることができます。

S = A+B+1
p_1 = p((A+1)/S)
p_2 = p(A/S)

確率p_1 /(p_1 + p_2)でベルヌーイ分布からサンプリングしてクリティカルヒットを選択します

あなたは、ランダムな数字があまりにも多くの「悪いすじ」を持っていることが判明した場合、スケールアップおよびbは、しかし限界で、ようやbは無限大に行く、あなたはシャッフルバッグアプローチは、先に説明しています。

これを実装する場合は、どうなるか教えてください!


5

繰り返し値を落とす分布が必要な場合は、単純な繰り返し拒否アルゴリズムを使用できます。

例えば

int GetRand(int nSize)
{
    return 1 + (::rand() % nSize);
}
int GetDice()
{
    static int nPrevious=-1;
    while (1) {
        int nValue = GetRand(6);
        // only allow repeat 5% of the time
        if (nValue==nPrevious && GetRand(100)<95)
            continue;
        nPrevious = nValue;
        return nValue;
    }
}

このコードは、95%の確率で繰り返し値を拒否するため、繰り返しはほとんどありませんが不可能ではありません。統計的には少し見苦しいですが、おそらくあなたが望む結果を生み出すでしょう。もちろん、「5 4 5 4 5」のような配布を妨げることはありません。あなたはより巧妙になって、最後の(たとえば)60%の時間を拒否し、3番目の(たとえば)30%を拒否することができます。

これは良いゲームデザインとしてはお勧めしません。単にあなたが望むものを達成する方法を提案しています。


クリティカルヒットのような私のゲームの一部の値は50%を超える可能性がないため、繰り返しをまったくブロックしますが、これによりイベントの可能性が数パーセント低下します。
思想家

4

あなたが何を望んでいるかは本当にはっきりしていません。最初に5回呼び出すと、ランダムな順序で1〜5の数値が返されるように関数を作成できます。

しかし、それは本当にランダムではありません。プレーヤーは、次の5つの攻撃でちょうど1つの5を獲得することを知っています。それはあなたが望むものかもしれません、そしてその場合、あなたは単にあなた自身でそれをコーディングしなければなりません。(数値を含む配列を作成し、それらをシャッフルします)

あるいは、現在のアプローチを使い続け、現在の結果がランダムジェネレーターの不良によるものであると想定することもできます。現在の数字に問題はないことに注意してください。ランダムな値はランダムです。時には、同じ値の2、3、または8が連続して表示されることがあります。ランダムだからです。優れたランダムジェネレーターは、平均してすべての数値が均等に返されることを保証します。

もちろん、悪い乱数発生器を使用している場合は、結果が歪んでいる可能性があります。その場合は、より良い乱数発生器に切り替えるだけで問題が解決するはずです。(より良いジェネレーターについては、Boost.Randomライブラリーをチェックしてください)

あるいは、ランダム関数によって返された最後のN個の値を覚えて、それらの結果を比較することもできます。(簡単な例は、「新しい結果が発生するたびに、値を破棄して新しい値を取得する必要がある確率は50%です。」

推測しなければならないのであれば、「実際の」ランダム性を守ることが最善の策だと思います。優れたランダムジェネレーターを使用していることを確認してから、今のやり方を続けてください。


実際、彼が使用している関数は、boostライブラリの最高のRNGと同じです。
Michael Borgwardt、

MTは「ベスト」ではありません。それは素晴らしく、シンプルで高速ですが、最良のディストリビューションを生成しません。とにかく、100万の乱数を取得し、分布を確認します。ランダム関数が実際に均一分布を与えるかどうかを調べます。そうでない場合は、より良いジェネレータを見つけてください。そうである場合は、それを吸い上げて、時々発生するクリティカルの列を受け入れるか、チートして結果をランダムでなく、より予測可能にします。
2009年

4

1から5までの数値を含むリストを作成し、ランダムに並べ替えることができます。次に、作成したリストを確認します。少なくとも1回はすべての数字に出会うことが保証されています...最初の5個が終わったら、さらに5個の数字を作成してください...


4

私はブリザードが使用するような漸進的な割合システムをお勧めします: http //www.shacknews.com/onearticle.x/57886

通常、RNGをロールしてから、それを値と比較して、成功したかどうかを判断します。次のようになります。

if ( randNumber <= .2 ) {
   //Critical
} else {
   //Normal
}

あなたがする必要があるのは、ベースチャンスの漸進的な増加を追加することです...

if (randNumber <= .2 + progressiveChance ) {
   progressiveChance = 0;
   //Critical
} else {
   progressiveChance += CHANCE_MODIFIER;
   //Normal hit
}

もっと豪華にしたい場合は、追加するのは簡単です。あなたは、progressiveChanceが100%のクリティカルチャンスを回避したり、特定のイベントでリセットしたりできる量に上限を設けることができます。また、プログレッシブチャンス+ =(1-プログレッシブチャンス)* SCALE(SCALE <1)のように、ブーストごとに少しずつプログレッシブチャンスを増やすこともできます。


4

まあ、あなたが数学に少し興味があるなら、おそらく指数分布を試すことができます

たとえば、ラムダ= 0.5の場合、期待値は2です(その記事を読んでください!)。これは、2ターンごとにヒット/クリティカル/何でも(50%など)ヒットすることを意味します。ただし、このような確率分布では、0ターン(イベントが既に発生しており、turn_counterがリセットされているターン)で、かなりミスする(または何と反対になる)と、次のターンにヒットする確率は40%、約65%になります。 2回目(次の次のターン)にそれを行うチャンス、約80%で3回目をヒット、など。

その分布の全体的な目的は、50%のヒットチャンスがあり、連続して3回ミスした場合、彼は確実に(まあ、80%を超える確率でヒットし、次のターンごとに増加します)ヒットです。これにより、より公平な結果が得られ、50%を超える確率が変更されません。

クリティカルの20%の確率で、

  • 17%で第1ターンをクリティカル
  • 以前のすべてでクリティカルが発生しなかった場合、2ターン目にクリティカルする32%。
  • 以前のすべてでクリティカルが発生しなかった場合、45%で3ターン目をクリティカルします。
  • 以前のすべてでクリティカルが発生しなかった場合、4ターンをクリティカルする54%。
  • ...
  • 以前のすべてでクリティカルが発生しなかった場合、8ターン目のクリティカルの80%。

それでも、約0.2%(対5%)の確率で、3クリティカル+ 2ノンクリティカルの確率が5ターン発生します。そして、4つの結果としての非クリティカルの可能性は14%、5のうちの5%、6では1.5%、7では0.3%、8つの結果としての非クリティカルでは0.07%です。41%、32%、26%、21%、16%よりも「公平」だと思います。

あなたがまだ死ぬほど退屈していないことを願っています。


これは、最後のクリティカルヒットからの時間のみを「記憶」することを除いて、私のソリューションとかなり似ています。このソリューションでは、4つのクリティカルヒットのストリングは、将来の確率に関する限り、1つのクリティカルヒットのストリングと同じです。したがって、クリティカルヒットが良好である場合、このソリューションはダウンサイドリスクを制限しますが、アップサイドは制限しません。私の解決策は両方に影響します。
ニールG

さまざまなソリューションに独自の利点があることは明らかです。これは、科学の観点からランダム性をクリーンに保つことに焦点を当てています。シャッフルバッグや他の何よりも、それが何とか優れているという意味ではありません。これは、試してみる価値があると思われるソリューションにすぎません。
ダーク

3

クリティカルの可能性を作ることについては、最後のN攻撃に依存します。単純なスキームの1つは、マルコフチェーンの一種です。http://en.wikipedia.org/wiki/Markov_chainですが、コードは非常に単純です。


IF turns_since_last_critical < M THEN 
   critial = false
   turns_since_last_critical++;
ELSE
   critial = IsCritical(chance);
   IF Critial THEN
       turns_since_last_critica = 0;
   ELSE
       turns_since_last_critica++;
   END IF;
END IF;

もちろん、最後のターンから十分なターンであることがわかったら、クリティカルの可能性はクリティカルの可能性よりも低いため、計算を行う必要があります。


最後の攻撃を考慮するだけで、ほとんどの効果を得ることができます。観測されたヒット率をP、ミス後のヒット率をR、ヒット後のヒット率をR / 2とします。定義により、任意の時点で、P = P * R +(1-P)*(R / 2)をヒットするチャンスがあります。これは、P = R /(2-R)
MSalters 2009年

2

OP、

ほとんどの場合、それを公平にしたい場合は、ランダムではありません。

あなたのゲームの問題は、実際の試合の長さです。一致が長ければ長いほど、ランダムさが少なくなり(クリティカルは20%になる傾向があります)、意図した値に近づきます。

前のロールに基づいて攻撃を事前に計算する2つのオプションがあります。5回の攻撃(20%に基づく)ごとに1つのクリティカルを取得しますが、ランダムに発生する順序を作成できます。

listOfFollowingAttacks = {ヒット、ヒット、ヒット、ミス、クリティカル};

それがあなたが望むパターンです。そのリストからランダムに選択させ、空になるまで再作成します。

それは私が自分のゲーム用に作成したパターンであり、私がやりたいことに対して、それはかなりうまくいきます。

2番目のオプションは、批判の可能性を高めることです。おそらく、すべての攻撃の最後に偶数がより多く表示されます(一致がかなり早く終了すると想定)。確率が低いほど、RNGが多くなります。


2

正規分布が必要な場合に、線形分布を調べています。

若者がD&Dをプレイしていたことを思い出すと、複数のn面サイコロを振って結果を合計するように求められました。

たとえば、4 x 6面のサイコロを振るのは、1 x 24面のサイコロを振るのとは異なります。


2

City of Heroesには、この問題を正確に解決する「ストリークブレーカー」と呼ばれるメカニズムがあります。それが機能する方法は、文字列内の最も低いヒット確率に関連する長さの一連のミスの後で、次の攻撃がヒットであることが保証されることです。たとえば、ヒット率が90%を超える攻撃を逃した場合、次の攻撃は自動的にヒットしますが、ヒット率が60%のように低い場合、「ストリークブレーカー」をトリガーするために連続して数回ミスする必要があります(正確な数がわからない)


2

代替テキスト

これは本当に予測可能です...しかし、あなたは確信が持てません。


これは私のデスクトップの壁紙でなければなりません!!

0

値の重み付けはどうですか?

たとえば、クリティカルヒットの可能性が20%の場合、1から5までの数値を生成し、1つの数値がクリティカルヒットを表すか、1から100までの数値を生成し、20の数値がクリティカルヒットであることを示します。

ただし、乱数または疑似乱数を使用している限り、現在表示されている結果を潜在的に回避する方法はありません。それはランダム性の性質です。


そして、なぜそれが違いを生むのでしょうか?両方の数値セットでクリティカルになる可能性はまったく同じです。
samjudson 2009年

丁度。彼の20%の例として、彼に2つのオプションを提示します。整数のパーセンテージを処理している場合は100の方が効果的ですが、そのように考える場合は1つの「ダイ」のみをシミュレートする必要があるためです。
Thomas Owens、

あなたが提示しているオプションは、まさに彼がすでにやっていることです。
ceejayoz 09年

2
彼が望むものではありません。彼はそれが乱数ジェネレータと呼ばれていると思っていても、彼は非乱数ジェネレータを望んでいます。
ceejayoz 2009年

0

反応:「問題は、実際の結果が非常に悪いことです。5ヒットで3クリティカル、15ヒットでまったくクリティカルにならない場合があります。」

15ヒットで何も得られない確率は3〜4%です...


3500人のプレイヤーがオンラインで1分間に10000のバトルを戦っている場合、3%のバトルで発生する問題は非常に一般的な問題です。
思想家

繰り返しになりますが、3%の戦闘で発生する不運は、まだ不運です。
MSalters 2009年

0

次の「ランダムに遅延されたプットバックダイ」を提案します。

  • 2つの配列を維持します。1つは(in-array)最初は0からn-1までの値で埋められ、もう1つは(out-array)空です
  • 結果が要求された場合:
    • すべてからランダムな値を返す定義された値でin-array
    • この値をからin-arrayに移動しますout-array
    • 1つのランダムな要素(未定義を含むすべての要素上)をout-array後ろからin-array

これには、nが大きいほど「反応」が遅くなるという性質があります。たとえば、20%の確率が必要な場合、nを5 に設定して0を打つことは、nを10に設定して0または1を打つよりも「ランダム性が低く」、1000のうち0から199にすることはほぼ小さなサンプルの真のランダム性と区別がつかない。nをサンプルサイズに調整する必要があります。


0

プレイヤーのランダムクリティカルヒット事前に計算します。

// OBJECT
//...
// OnAttack()
//...
c_h = c_h -1;
if ( c_h == 0 ) {
 // Yes, critical hit!
 c_h = random(5) + 1 // for the next time
 // ...
}

0

おそらく、あなたは間違ったランダム分布関数を使用していると思います。おそらく、数値を均等に分散したくないでしょう。代わりに正規分布を試して、クリティカルヒットが「通常の」ヒットよりも一般的でないようにします。

私はJavaを使用しているので、正規分布で乱数を提供するC ++のどこを見つけることができるかわかりませんが、そこに何かがあるはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.