This commit is contained in:
Lincoln-LM 2022-01-04 07:31:25 -07:00
commit e652126cd5
9 changed files with 382 additions and 3 deletions

BIN
images/mtcoronet/eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
images/spearpillar/eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

BIN
images/trophygarden/eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -7,3 +7,6 @@ home/eye_normal : 905, 480, 55, 200
ruin/eye : 920, 490, 35, 50
secretbase/eye : 870, 680, 85, 90
underground/eye : 925, 520, 35, 35
trophygarden/eye : 930, 505, 30, 30
mtcoronet/eye : 930, 510, 30, 40
spearpillar/eye : 935,505,25,30

188
src/debug/calc.py Normal file
View File

@ -0,0 +1,188 @@
import numpy as np
from functools import reduce
from bisect import bisect
def getZero(size=32):
return np.zeros((size,size),dtype="uint8")
def getI(size=32):
return np.identity(size,dtype="uint8")
def getShift(n,size=32):
return np.eye(size,k=n,dtype="uint8")
def getTrans():
t11,t12,t13,t14 = getZero(),getI(),getZero(),getZero()
t21,t22,t23,t24 = getZero(),getZero(),getI(),getZero()
t31,t32,t33,t34 = getZero(),getZero(),getZero(),getI()
t41,t42,t43,t44 = (getI()^getShift(-8))@(getI()^getShift(11))%2,getZero(),getZero(),getI()^getShift(-19)
trans = np.block([
[t11,t12,t13,t14],
[t21,t22,t23,t24],
[t31,t32,t33,t34],
[t41,t42,t43,t44],
])
return trans
def getS(intervals,rows = 39):
intervals = intervals[:rows]
t = getTrans()
t_ = getTrans()
s = np.zeros((4*rows,128),"uint8")
for i in range(rows):
s[4*i:4*(i+1)] = t[-4:]
for j in range(intervals[i]):
t = t@t_%2
return s
def getS_munchlax(intervals):
intervals = intervals[::-1]
section = [0, 3.4333333333333336, 3.795832327504833, 3.995832327504833, 4.358332394560066, 4.558332394560066, 4.9208324616153, 5.120832461615299, 5.483332528670533, 5.683332528670532, 6.045832595725767, 6.2458325957257665, 6.608332662781, 6.808332662780999, 7.170832729836233, 7.370832729836232, 7.733332796891467, 7.933332796891467, 8.2958328639467, 8.4958328639467, 8.858332931001934, 9.058332931001933, 9.420832998057167, 9.620832998057166, 9.9833330651124, 10.1833330651124, 10.545833132167635, 10.745833132167634, 11.108333199222866, 11.308333199222865, 11.6708332662781, 11.8708332662781, 12.233333333333334,]
t = getTrans()
t_ = getTrans()
s = np.zeros((128,128),"uint8")
safe_intervals = []
for i in range(32):
#intervals[-1]を挿入した際のインデックスが奇数だと危険な値の可能性がある
is_carriable = bisect(section,intervals[-1])%2==1
while is_carriable:
#スキップする
t = t@t_%2
#危険な値を除外
intervals.pop()
is_carriable = bisect(section,intervals[-1])%2==1
s[4*i:4*(i+1)] = t[105:109]
t = t@t_%2
safe_intervals.append(intervals.pop())
return s, safe_intervals
def gauss_jordan(mat,observed:list):
r,c = mat.shape
bitmat = [list2bitvec(mat[i]) for i in range(r)]
res = [d for d in observed]
#forward elimination
pivot = 0
for i in range(c):
isfound = False
for j in range(i,r):
if isfound:
check = 1<<(c-i-1)
if bitmat[j]&check==check:
bitmat[j] ^= bitmat[pivot]
res[j] ^= res[pivot]
else:
check = 1<<(c-i-1)
if bitmat[j]&check==check:
isfound = True
bitmat[j],bitmat[pivot] = bitmat[pivot],bitmat[j]
res[j],res[pivot] = res[pivot],res[j]
if isfound:
pivot += 1
for i in range(c):
check = 1<<(c-i-1)
assert bitmat[i]&check>0
#backward assignment
for i in range(1,c)[::-1]:
check = 1<<(c-i-1)
for j in range(i)[::-1]:
if bitmat[j]&check==check:
bitmat[j] ^= bitmat[i]
res[j] ^= res[i]
return res[:c]
def getInverse(mat):
r,c = mat.shape
assert r==c
n = r
res = [(1<<i) for i in range(n)]
res = res[::-1]#identity matrix
bitmat = [list2bitvec(mat[i]) for i in range(n)]
pivot = 0
for i in range(n):
isfound = False
for j in range(i,n):
if isfound:
check = 1<<(n-i-1)
if bitmat[j]&check==check:
bitmat[j] ^= bitmat[pivot]
res[j] ^= res[pivot]
else:
check = 1<<(n-i-1)
if bitmat[j]&check==check:
isfound = True
bitmat[j],bitmat[pivot] = bitmat[pivot],bitmat[j]
res[j],res[pivot] = res[pivot],res[j]
if isfound:
pivot += 1
#backward assignment
for i in range(1,n)[::-1]:
check = 1<<(n-i-1)
for j in range(i)[::-1]:
if bitmat[j]&check==check:
bitmat[j] ^= bitmat[i]
res[j] ^= res[i]
return res
def bitvec2list(bitvec,size=128):
lst = [(bitvec>>i)%2 for i in range(size)]
return np.array(lst[::-1])
def list2bitvec(lst):
bitvec = reduce(lambda p,q: (int(p)<<1)|int(q),lst)
return bitvec
def reverseStates(rawblinks:list, intervals:list)->int:
blinks = []
for b in rawblinks:
blinks.extend([0,0,0])
blinks.append(b)
#print(blinks)
s = getS(intervals)
lst_result = gauss_jordan(s, blinks)
bitvec_result = list2bitvec(lst_result)
result = []
for i in range(4):
result.append(bitvec_result&0xFFFFFFFF)
bitvec_result>>=32
result = result[::-1]#reverse order
return result
def reverseFloatRange(f:float,mi:float,ma:float):
norm_f = (ma-f)/(ma-mi)
norm_i = int(norm_f*8388607.0)
return int(norm_f*8388607.0)&0x7fffff
def reverseStatesByMunchlax(intervals:list)->int:
s, safe_intervals = getS_munchlax(intervals)
bitvectorized_intervals = [reverseFloatRange(30.0*f,100,370)>>19 for f in safe_intervals]
bitlst_intervals = []
for b in bitvectorized_intervals[::-1]:
for i in range(4):
bitlst_intervals.append(b&1)
b >>= 1
bitlst_intervals = bitlst_intervals[::-1]
bitvec_result = list2bitvec(gauss_jordan(s, bitlst_intervals))
result = []
for i in range(4):
result.append(bitvec_result&0xFFFFFFFF)
bitvec_result>>=32
result = result[::-1]#reverse order
return result

View File

@ -13,9 +13,14 @@ def splitstate(state:int):
def main():
prng = Xorshift(0x12,0x34,0x56,0x00)
prng.advances(1000)
for i in range(10):
print(*list(map(hex,prng.getState())))
prng.prev()
for i in range(10):
print(prng.range(100.0, 370.0))
print(*list(map(hex,prng.getState())))
if __name__ == "__main__":
main()

147
src/stationary.py Normal file
View File

@ -0,0 +1,147 @@
import rngtool
import calc
import cv2
import time
from xorshift import Xorshift
import heapq
imgpath = "./trainer/mtcoronet/eye.png"
def firstspecify():
player_eye = cv2.imread(imgpath, cv2.IMREAD_GRAYSCALE)
if player_eye is None:
print("path is wrong")
return
blinks, intervals, offset_time = rngtool.tracking_blink(player_eye, 930, 510, 30, 35)
prng = rngtool.recov(blinks, intervals)
waituntil = time.perf_counter()
diff = round(waituntil-offset_time)
prng.getNextRandSequence(diff)
state = prng.getState()
print("state(64bit 64bit)")
print(hex(state[0]<<32|state[1]), hex(state[2]<<32|state[3]))
print("state(32bit 32bit 32bit 32bit)")
print(*[hex(s) for s in state])
def reidentify():
print("input xorshift state(state[0] state[1] state[2] state[3])")
state = [int(x,0) for x in input().split()]
player_eye = cv2.imread(imgpath, cv2.IMREAD_GRAYSCALE)
if player_eye is None:
print("path is wrong")
return
observed_blinks, _, offset_time = rngtool.tracking_blink(player_eye, 930,510,30,35,size=20)
reidentified_rng = rngtool.reidentifyByBlinks(Xorshift(*state), observed_blinks)
if reidentified_rng is None:
print("couldn't reidentify state.")
return
waituntil = time.perf_counter()
diff = int(-(-(waituntil-offset_time)//1))
print(diff, waituntil-offset_time)
reidentified_rng.advances(max(diff,0))
state = reidentified_rng.getState()
print("state(64bit 64bit)")
print(hex(state[0]<<32|state[1]), hex(state[2]<<32|state[3]))
print("state(32bit 32bit 32bit 32bit)")
print(*[hex(s) for s in state])
#timecounter reset
advances = 0
stat_prng = Xorshift(*reidentified_rng.getState())
stat_prng.getNextRandSequence(2)
advances = 0
waituntil = time.perf_counter()
time.sleep(diff - (waituntil - offset_time))
while True:
advances += 1
r = reidentified_rng.next()
wild_r = stat_prng.next()
waituntil += 1.017
next_time = waituntil - time.perf_counter() or 0
time.sleep(next_time)
print(f"advances:{advances}, blink:{hex(r&0xF)}")
def stationary_timeline():
print("input xorshift state(state[0] state[1] state[2] state[3])")
state = [int(x,0) for x in input().split()]
player_eye = cv2.imread(imgpath, cv2.IMREAD_GRAYSCALE)
if player_eye is None:
print("path is wrong")
return
observed_blinks, _, offset_time = rngtool.tracking_blink(player_eye, 930,510,30,35,size=20)
reidentified_rng = rngtool.reidentifyByBlinks(Xorshift(*state), observed_blinks)
if reidentified_rng is None:
print("couldn't reidentify state.")
return
waituntil = time.perf_counter()
diff = int(-(-(waituntil-offset_time)//1))
reidentified_rng.advances(max(diff,0))
state = reidentified_rng.getState()
print("state(64bit 64bit)")
print(hex(state[0]<<32|state[1]), hex(state[2]<<32|state[3]))
print("state(32bit 32bit 32bit 32bit)")
print(*[hex(s) for s in state])
#timecounter reset
advances = 0
waituntil = time.perf_counter()
time.sleep(diff - (waituntil - offset_time))
for _ in [0]*60:
advances += 1
r = reidentified_rng.next()
waituntil += 1.017
next_time = waituntil - time.perf_counter() or 0
time.sleep(next_time)
print(f"advances:{advances}, blink:{hex(r&0xF)}")
#rng blankread
reidentified_rng.next()
#whiteout
time.sleep(2)
waituntil = time.perf_counter()
print("entered the stationary symbol room")
queue = []
heapq.heappush(queue, (waituntil+1.017,0))
#blink_int = reidentified_rng.range(100.0, 370.0)/30 - 0.048
blink_int = reidentified_rng.rangefloat(100.0, 370.0)/30 - 0.048
heapq.heappush(queue, (waituntil+blink_int,1))
while queue:
advances += 1
w, q = heapq.heappop(queue)
next_time = w - time.perf_counter() or 0
if next_time>0:
time.sleep(next_time)
if q==0:
r = reidentified_rng.next()
print(f"advances:{advances}, blink:{hex(r&0xF)}")
heapq.heappush(queue, (w+1.017, 0))
else:
#blink_int = reidentified_rng.range(100.0, 370.0)/30 - 0.048
blink_int = reidentified_rng.rangefloat(100.0, 370.0)/30 - 0.048
heapq.heappush(queue, (w+blink_int, 1))
print(f"advances:{advances}, interval:{blink_int}")
if __name__ == "__main__":
#firstspecify()
#reidentify()
stationary_timeline()

View File

@ -47,8 +47,8 @@ def reidentify():
reidentified_rng = rngtool.reidentifyByBlinks(Xorshift(*state), observed_blinks)
waituntil = time.perf_counter()
diff = round(waituntil-offset_time)+1
reidentified_rng.getNextRandSequence(diff)
diff = int(-(-(waituntil-offset_time)//1))
reidentified_rng.advances(max(diff,0))
state = reidentified_rng.getState()
print("state(64bit 64bit)")

View File

@ -40,6 +40,42 @@ class Xorshift(object):
def range(self,mi,ma):
return self.next() % (ma-mi) + min
def advance(self,length:int):
self.getNextRandSequence(length)
def range(self,mi:int,ma:int)->int:
"""generate random integer value in [mi,ma)
Args:
mi ([int]): minimum
ma ([int]): maximam
Returns:
[int]: random integer value
"""
return self.next() % (ma-mi) + min
def float(self)->float:
"""generate random value in [0,1]
Returns:
float: random value
"""
return (self.next() & 0x7fffff) / 8388607.0
def rangefloat(self,mi:float,ma:float)->float:
"""generate random value in [mi,ma]
Args:
mi (float): minimum
ma (float): maximam
Returns:
[type]: [description]
"""
t = self.float()
return t * mi + (1-t) * ma
def getNextRandSequence(self,length):
return [self.next() for _ in range(length)]