public override void CountUp(ref uint seed) { // lifetimeが0になっているなら加算は行わない. if (lifetime == 0) { seed.Advance(); } else { Value += seed.GetRand_f() * coefficient; if (Value >= 1.0f) { Value -= 1.0f; seed.Advance(); objectLifetime = 21; } lifetime--; } objectLifetime--; RemoveDeadChilds(); child?.CountUp(ref seed); }
/// <summary> /// タイトル画面入る前(ロゴが出てくるあたり?)で発生する消費. /// 消費後の現在seedを返します. /// </summary> /// <param name="seed"></param> /// <param name="finSeed"></param> /// <returns></returns> public static uint GameInitialization(this uint seed) { seed.Advance1000(); seed.Advance(2); // tsv生成されてるけど色回避判定は無いらしい? // なんかエフィブラっぽいよね dummySlot.Generate(ref seed); dummySlot.Generate(ref seed); seed.Advance(2); // 用途不明 return(seed); }
/// <summary> /// とにかくバトルの画面に入るときに発生する消費. /// 消費後の現在seedを返します. /// </summary> /// <param name="seed"></param> /// <param name="finSeed"></param> /// <returns></returns> public static uint GenerateDummyParty(this uint seed) { seed.Advance(118); foreach (var team in dummyTeam) { seed.Advance(2); // tsv生成されてるけど色回避判定は無いらしい? foreach (var poke in team) { poke.Generate(ref seed); } } seed.Advance(7); // 完全に条件無しのダミーの生成 return(seed); }
public void SimulateCountUp(ref uint seed) { if (IsLiving) { if (lifetime == 0) { seed.Advance(); } else if (Value + seed.GetRand_f() * coefficient >= 1.0f) { seed.Advance(); } } child?.SimulateCountUp(ref seed); }
public uint AdvanceSeed(uint seed) { var enemyTeamIndex = seed.GetRand() & 0x7; uint playerTeamIndex; do { playerTeamIndex = seed.GetRand() & 0x7; } while (enemyTeamIndex == playerTeamIndex); var enemyTSV = seed.GetRand() ^ seed.GetRand(); foreach (var poke in teams[(int)enemyTeamIndex]) { poke.Generate(ref seed, enemyTSV); } seed.Advance(); // PlayerName var playerTSV = seed.GetRand() ^ seed.GetRand(); foreach (var poke in teams[playerTeamIndex]) { poke.Generate(ref seed, playerTSV); } return(seed); }
public bool CountUp(ref uint seed) { if (lifetime == 0) { lazyAdvance1.Enqueue(0); lazyAdvance2.Enqueue(0); return(false); } value += seed.GetRand_f() * (counter++ < 100 ? 0.5f : 0f); if (value >= 1.0f) { value -= 1.0f; lifetime = 100; seed.Advance(6); lazyAdvance1.Enqueue(3); lazyAdvance2.Enqueue(1); return(true); } lifetime--; lazyAdvance1.Enqueue(0); lazyAdvance2.Enqueue(0); return(false); }
public void SimulateCountUp(ref uint seed) { var v = Value + seed.GetRand_f() * coefficient; if (v >= 1.0f) { seed.Advance(); // サブカウンタが生える. // 初期化 + 直後に加算処理が入り, 繰り上げが発生したらさらに1消費. if (seed.GetRand_f() + seed.GetRand_f() * 0.5f >= 1.0f) { seed.Advance(); } } child?.SimulateCountUp(ref seed); }
/// <summary> /// 瞬きから現在seedを検索し, 条件に一致するものを返します. /// 省メモリかつ高速ですが, 瞬きを数回捨てる必要があります. /// </summary> /// <param name="seed"></param> /// <param name="minIndex"></param> /// <param name="maxIndex"></param> /// <param name="blinkInput"></param> /// <param name="allowanceLimitOfError"></param> /// <param name="coolTime"></param> /// <returns></returns> public static IEnumerable <uint> FindCurrentSeedByBlinkFaster(uint seed, uint minIndex, uint maxIndex, int[] blinkInput, int allowanceLimitOfError = 20, int coolTime = 4) { seed.Advance(minIndex); var n = (ulong)maxIndex - minIndex + 1; var e = seed.EnumerateBlinkingSeed(coolTime).GetEnumerator(); var blinkCache = new (int, uint)[256]; // 瞬き間隔をキャッシュしておく配列.
public void CountUp(ref uint seed) { value += seed.GetRand_f() * 0.8f; if (value >= 1.0f) { value -= 1.0f; seed.Advance(); } }
/// <summary> /// 無限にseedを返し続けます. SkipやTakeと組み合わせてください. /// </summary> /// <param name="seed"></param> /// <returns></returns> public static IEnumerable <uint> EnumerateSeed(this uint seed) { yield return(seed); while (true) { yield return(seed.Advance()); } }
/// <summary> /// スナッチリストを開いたときに発生する消費をシミュレートし, 無限にseedを返し続けます. /// PID再計算の発生に対応しています. /// SkipやTakeと組み合わせてください. /// </summary> /// <param name="seed"></param> /// <returns></returns> public static IEnumerable <uint> EnumerateSnatchListAdvance(this uint seed) { while (true) { yield return(seed); seed.Advance(5); // ID = 0x00000000による色回避判定が入る // GCのLCGパラメータでは、最大で2回の再計算が発生する var psv = seed.GetRand() ^ seed.GetRand(); if (psv < 8) { psv = seed.GetRand() ^ seed.GetRand(); if (psv < 8) { seed.Advance(2); } } } }
/// <summary> /// 瞬きから現在seedを検索し, 条件に一致するものを返します. /// </summary> /// <param name="seed"></param> /// <param name="minIndex"></param> /// <param name="maxIndex"></param> /// <param name="blinkInput"></param> /// <param name="allowanceLimitOfError"></param> /// <param name="coolTime"></param> /// <returns></returns> public static IEnumerable <uint> FindCurrentSeedByBlink(uint seed, uint minIndex, uint maxIndex, int[] blinkInput, int allowanceLimitOfError = 20, int coolTime = 4) { var res = new List <uint>(); seed.Advance(minIndex); blinkInput = blinkInput.Select(_ => _ - (5 + coolTime)).ToArray(); // 瞬き後のクールタイム分を引く. var n = maxIndex - minIndex + 1; // i = maxまで計算できるように, 全て最大間隔で瞬きが行われた場合でも足りるだけ余分に計算しておく. var len = (int)n + 85 * (blinkInput.Length + 2); // 「到達したときに瞬きをするような内部カウンタの値」の最小値に変換する. // UpperBoundしていたところは入力が高々65536通りしかないのであらかじめ計算しておくことでO(1)に落とせる. // とはいえそこまで劇的に変わるわけではない(UpperBoundの計算量は十分定数に近いので). var countList = seed.EnumerateRand().Take(len + 1).Select(_ => minBlinkableBlank[_]).ToArray(); // 「その位置で瞬きをした場合の, 次の瞬きまでの間隔」. // ここが定数倍大きいのでちょっと辛い. var blankList = Enumerable.Repeat(86, len).ToArray(); // 86 = INF for (int i = len - 1; i >= 0; i--) // 後ろから埋めていく. 確率的にcountListは大きい値が多く, 特に85になる確率が高い. { for (int k = countList[i]; k <= Math.Min(i, 85); k++) // kは『到達したときに瞬きするような内部カウンタの最小値』から85まで(境界を超えないように). { blankList[i - k] = Math.Min(blankList[i - k], k); // kの定義より, i-kで瞬きをしたら, 次は少なくともiで瞬きが発生する. } } // 『iフレーム目に1回目の瞬きが行われた』と仮定してシミュレート. for (int i = 0; i < n; i++) { int idx = i; int k; for (k = 0; k < blinkInput.Length; k++) { // 許容誤差を超えているなら次のフレームへ. if ((blinkInput[k] + allowanceLimitOfError) < blankList[idx] || blankList[idx] < (blinkInput[k] - allowanceLimitOfError)) { break; } // 間隔ぶんをindexに加算する. idx += blankList[idx] + 1; } // 入力と全て一致すればresに入れる. if (k == blinkInput.Length) { res.Add((uint)idx); } } return(res.Distinct().Select(_ => seed.NextSeed(_))); }
public void CountUp(ref uint seed) { var adv = (uint)mainCounters.Sum(_ => _.HeaderAdvance()); seed.Advance(adv); foreach (var c in mainCounters) { c.CountUp(ref seed); } }
/// <summary> /// 無限にseedと消費数のTupleを返し続けます. SkipやTakeと組み合わせてください. /// </summary> /// <param name="seed"></param> /// <returns></returns> public static IEnumerable <(int index, uint seed)> EnumerateSeedWithIndex(this uint seed) { int i = 0; yield return(i++, seed); while (true) { yield return(i++, seed.Advance()); } }
/// <summary> /// 名前入力画面での消費をシミュレートし, 無限にseedを返し続けます. SkipやTakeと組み合わせてください. /// </summary> /// <param name="seed"></param> /// <returns></returns> public static IEnumerable <uint> EnumerateSeedAtNamingScreen(this uint seed) { while (true) { yield return(seed); if (seed.GetRand() < 0x199A) { seed.Advance(4); // 実際はfloatに変換して0.1fと比較している. } } }
/// <summary> /// カウンタの加算処理を呼びます. /// そのまま子カウンタの加算処理も呼び出します. /// </summary> /// <param name="seed"></param> public void CountUp(ref uint seed) { Value += seed.GetRand_f() * 0.3f; if (Value >= 1.0f) { Value -= 1.0f; seed.Advance(2); onCarried?.Invoke(); } child?.CountUp(ref seed); }
public void CountUp(ref uint seed) { value += seed.GetRand_f() * 0.003f; if (value >= 1.0f) { value -= 1.0f; seed.Advance(); subCounter.Initialize(); } nextHeader = subCounter.CountUp(ref seed) ? 1u : 0u; }
public void SimulateCountUp(ref uint seed, SubCounter[] subordinateCounters) { var v = Value + seed.GetRand_f() * coefficient; if (v >= 1.0f) { seed.Advance(); // サブカウンタが生える. // 初期化 + 直後に加算処理が入り, 繰り上げが発生したらさらに1消費. if (seed.GetRand_f() + seed.GetRand_f() * 0.5f >= 1.0f) { seed.Advance(); } } // 遅延で生えたカウンタの加算処理. foreach (var sub in subordinateCounters) { sub.SimulateCountUp(ref seed); } child?.SimulateCountUp(ref seed); }
/// <summary> /// 名前入力画面での不定消費をシミュレートし, 無限にseedを返し続けます. SkipやTakeと組み合わせてください. /// </summary> /// <param name="seed"></param> /// <returns></returns> public static IEnumerable <(int frameIndex, uint lcgIndex, uint seed)> EnumerateSeedAtNamingScreenWithIndex(this uint seed) { uint index = 0; for (int frame = 0; true;) { yield return(frame++, index++, seed); if (seed.GetRand() < 0x199A) { seed.Advance(4); index += 4; } } }
public override uint[] GenerateIVs(ref uint seed) { seed.Advance(); var HAB = seed.GetRand(); var SCD = seed.GetRand(); return(new uint[6] { HAB& 0x1f, (HAB >> 5) & 0x1f, (HAB >> 10) & 0x1f, (SCD >> 5) & 0x1f, (SCD >> 10) & 0x1f, SCD & 0x1f }); }
public override void CountUp(ref uint seed) { Value += seed.GetRand_f() * coefficient; // メインカウンタは死ぬことは無い. if (Value >= 1.0f) { Value -= 1.0f; seed.Advance(); InterruptChild(new SubCounter(ref seed)); onCarried?.Invoke(); } RemoveDeadChilds(); child?.CountUp(ref seed); }
public void CountUp(ref uint seed) { var c = lazyGenerators.Count; // for内でEnqueueするので、外側で代入しておく必要がある. for (int i = 0; i < c; i++) { var value = lazyGenerators.Dequeue().CountDown(); if (value.IsZero) { seed.Advance(); } else { lazyGenerators.Enqueue(value); } } root.CountUp(ref seed); // 従属するカウンタのCountUpも再帰的に(?)呼び出す. }
public CalcBackCore(uint seed, GCSlot slot) { this.slot = slot; representativeSeed = seed; seed.Advance(2); ivs = seed.GetIVs(); abilityIndex = seed.GetRand() & 1; var hid = seed.GetRand(); var lid = seed.GetRand(); var psv = lid ^ hid; pid1 = lid | (hid << 16); do { hid = seed.GetRand(); lid = seed.GetRand(); pid2 = lid | (hid << 16); } while ((hid ^ lid ^ psv) >= 8); }
public uint CalcSeedBeforeEntryingBattle(uint seed) { // 戦闘突入時のエフェクトで4消費. 諸悪の根源. seed.Advance(4); // 遅延で生える処理をシミュレート. var lazy = lazyGenerators.Count(_ => _.CountDown().IsZero); var newSubCounters = new SubCounter[lazy]; for (int i = 0; i < newSubCounters.Length; i++) { newSubCounters[i] = new SubCounter(ref seed); } mainCounters[0].SimulateCountUp(ref seed, newSubCounters); mainCounters[1].SimulateCountUp(ref seed); mainCounters[2].SimulateCountUp(ref seed); mainCounters[3].SimulateCountUp(ref seed); mainCounters[4].SimulateCountUp(ref seed); mainCounters[5].SimulateCountUp(ref seed); return(seed); }
public bool TryGenerate(ref uint seed, out GBASlot result) { result = null; seed.Advance(); return(false); }