/// <summary> /// Attempts to sync RNG state to external state passed in. Guarenteed to be able to sync with an RNGState N * MinBufferSize positions in the future. /// </summary> /// <param name="inputState"></param> /// <returns>The number of positions in the future the RNG was synced to, or -1 if the RNG state difference could not be determined.</returns> public int SyncState(RNGState inputState) { //Check if inputState is within current mt window. if (mt.SequenceEqual(inputState.mt)) { int indexDifference = inputState.mti - mti; mti = inputState.mti; return(indexDifference); //May return negative value if input state was from a time "before" current state. // I dont feel like differentiating between a loss of sync, and a back-in-time sync. } //Now check if inputState is within lookahead buffer for (int i = 0; i < LookaheadBuffer.Count; i++) { if (LookaheadBuffer[i].SequenceEqual(inputState.mt)) { int stateDifference = inputState.mti - mti + (N * (i + 1)); LoadState(inputState); return(stateDifference); } } //State could not be synced LoadState(inputState); return(-1); }
/// <summary> /// Reads State of RNG in memory /// </summary> /// <param name="state"> The RNGState you read from memory.</param> /// <returns>true if read successfull, false otherwise.</returns> public bool ReadState(out RNGState state) { //I might even put this in a try-catch block just in case? //Really hard to tell what can happen if (AttachToProcess()) { int bytesRead = 0; //Read RNG state fotunately ReadProcessMemory(FF12Handle, MT_ADDR, rngStateBuffer, rngStateBuffer.Length, ref bytesRead); if (bytesRead == STATE_BUFFER_SIZE) { Int32 mti = BitConverter.ToInt32(rngStateBuffer, STATE_BUFFER_SIZE - INT32_SIZE); UInt32[] mt = new UInt32[RNG2002.N]; //Memory copy shenanigans abound. Fortunately these two arrays are binary compatible Buffer.BlockCopy(rngStateBuffer, 0, mt, 0, STATE_BUFFER_SIZE - INT32_SIZE); state = new RNGState { mt = mt, mti = mti }; return(true); } } state = new RNGState(); return(false); }
public RNGState DeepCopy() { RNGState ToReturn = new RNGState(); ToReturn.mti = mti; mt.CopyTo(ToReturn.mt, 0); return(ToReturn); }
/// <summary> /// Attempts to move existing Future syncAmount positions further. /// </summary> /// <returns>Updated future</returns> public virtual int SyncFuture(int syncAmount, IRNG rng, int offset = 0) { var state = rng.SaveState(); //Check if cached future is still good to advance without searching again. if (hasCachedFuture && CachedFuture - syncAmount >= 0) { CachedState = state; CachedOffset = offset; return(CachedFuture -= syncAmount); } else { hasCachedFuture = false; return(GetFuture(rng, offset)); } }
/// <summary> /// Determines number of positions to advance RNG to get DesiredResult /// </summary> /// <returns>Number of positions to advance RNG, or -1 if desired result could not be found in search depth.</returns> public virtual int GetFuture(IRNG rng, int offset = 0) { var state = rng.SaveState(); if (hasCachedFuture && offset == CachedOffset && state.mti == CachedState.mti && state.mt.SequenceEqual(CachedState.mt)) { return(CachedFuture); } hasCachedFuture = true; CachedState = state; CachedOffset = offset; for (int i = 0; i < SearchDepth; i++) { if (GenerateAndCheckResult(rng, i + offset)) { return(CachedFuture = i); } } return(CachedFuture = -1); }
/// <summary> /// Loads the state of the RNG /// </summary> /// <param name="inputState">Input state</param> public void LoadState(RNGState inputState) { LoadState(inputState.mti, inputState.mt); }
public RNGState(RNGState state) { mti = state.mti; mt = state.mt; }