diff --git a/barry/eye.png b/barry/eye.png new file mode 100644 index 0000000..5950cf7 Binary files /dev/null and b/barry/eye.png differ diff --git a/cresselia/eye.png b/cresselia/eye.png new file mode 100644 index 0000000..453d494 Binary files /dev/null and b/cresselia/eye.png differ diff --git a/images/fullmoon/eye.png b/images/fullmoon/eye.png new file mode 100644 index 0000000..87bfa3a Binary files /dev/null and b/images/fullmoon/eye.png differ diff --git a/images/lake/eye.png b/images/lake/eye.png new file mode 100644 index 0000000..a4ac541 Binary files /dev/null and b/images/lake/eye.png differ diff --git a/memo.md b/memo.md index ef83512..dca0715 100644 --- a/memo.md +++ b/memo.md @@ -2,6 +2,7 @@ memo.md type : roi_x, roi_y, roi_w, roi_h munchlax : 730, 670 ,50, 60 +cresselia/eye :805, 480, 20, 30 trainer/home/eye_blur : 905, 750, 55, 55 trainer/home/eye_normal : 905, 480, 55, 200 trainer/ruin/eye : 920, 490, 35, 50 @@ -10,4 +11,6 @@ trainer/underground/eye : 925, 520, 35, 35 trainer/trophygarden/eye : 930, 505, 30, 30 trainer/mtcoronet/eye : 930, 510, 30, 40 trainer/spearpillar/eye : 935,505,25,30 -barry/eye : 1065, 490, 30, 35 \ No newline at end of file +trainer/lake/eye : 930, 490, 30, 35 +trainer/fullmoon/eye : 925, 500, 35, 35 +barry/eye : 1065, 490, 30, 35 diff --git a/src/cresselia.py b/src/cresselia.py new file mode 100644 index 0000000..5cb5b36 --- /dev/null +++ b/src/cresselia.py @@ -0,0 +1,187 @@ +""" +this program is experimental. +""" + +import rngtool +import calc +import cv2 +import time +from xorshift import Xorshift +import heapq + +imgpath = "./trainer/fullmoon/eye.png" + +def firstspecify(): + imgpath = "./trainer/secretbase/eye.png" + 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, 870, 680, 85, 90) + 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()] + plimgpath = "./trainer/fullmoon/eye.png" + plimg = cv2.imread(plimgpath, cv2.IMREAD_GRAYSCALE) + plroi = (925, 500, 35, 35) + + pkimgpath = "./cresselia/eye.png" + pkimg = cv2.imread(pkimgpath, cv2.IMREAD_GRAYSCALE) + pkroi = (805, 475, 20, 30) + blinks, observed_intervals, offset_time = rngtool.simultaneous_tracking(plimg, plroi, pkimg, pkroi, pkth = 0.999185, size = 8) + + reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, th=2, search_max=10**5) + 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 + waituntil = time.perf_counter() + time.sleep(diff - (waituntil - offset_time)) + + while True: + 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)}") + +def reidentifyInSecretBase(): + """reidentify xorshift internal state in the cresselia's room + note: this function is a bit unreliable since it is difficult to track the blinks of cresselia. + + """ + print("input xorshift state(state[0] state[1] state[2] state[3])") + state = [int(x,0) for x in input().split()] + imgpath = "./trainer/secretbase/eye.png" + player_eye = cv2.imread(imgpath, cv2.IMREAD_GRAYSCALE) + if player_eye is None: + print("path is wrong") + return + blinks, observed_intervals, offset_time = rngtool.tracking_blink(player_eye, 870, 680, 85, 90, size=7) + reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, npc=0) + 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 + waituntil = time.perf_counter() + time.sleep(diff - (waituntil - offset_time)) + + while True: + 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)}") + +def cresselia_timeline(): + print("input xorshift state(state[0] state[1] state[2] state[3])") + state = [int(x,0) for x in input().split()] + plimgpath = "./trainer/fullmoon/eye.png" + plimg = cv2.imread(plimgpath, cv2.IMREAD_GRAYSCALE) + plroi = (925, 500, 35, 35) + + pkimgpath = "./cresselia/eye.png" + pkimg = cv2.imread(pkimgpath, cv2.IMREAD_GRAYSCALE) + pkroi = (805, 475, 20, 30) + blinks, observed_intervals, offset_time = rngtool.simultaneous_tracking(plimg, plroi, pkimg, pkroi, pkth = 0.999185, size = 4) + + reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, th=1, search_max=1*10**3, search_min=0) + 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]) + + advances = 1 + waituntil = time.perf_counter() + time.sleep(diff - (waituntil - offset_time)) + #timeline prepare + queue = [] + blink_int = reidentified_rng.range(3.0, 12.0) + 0.285 + #blink_int = reidentified_rng.rangefloat(3,12) + 0.285 + heapq.heappush(queue, (waituntil+blink_int,1)) + + #_ = reidentified_rng.next() + heapq.heappush(queue, (waituntil+1.017,0)) + + 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(3.0, 12.0) + 0.285 + #blink_int = reidentified_rng.rangefloat(3,12) + 0.285 + + heapq.heappush(queue, (w+blink_int, 1)) + print(f"advances:{advances}, interval:{blink_int}") + +if __name__ == "__main__": + #note: + #1. specify internal state with firstspecify() (secretbase is better place) + #2. search target on pokefinder + #3. advance rng (fullmoon island exterior is fast, about +250/s) + #4. enter the cresselia's room 2000 advances before the target, and reidentify state with cresselia_timeline() + #5. + + #firstspecify() + #reidentifyInSecretBase() + cresselia_timeline() diff --git a/src/rngtool.py b/src/rngtool.py index b60cb16..9621e6e 100644 --- a/src/rngtool.py +++ b/src/rngtool.py @@ -8,6 +8,7 @@ import sys import cv2 from xorshift import Xorshift import calc +from collections import Counter IDLE = 0xFF SINGLE = 0xF0 @@ -21,7 +22,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40, Monitor """measuring the type and interval of player's blinks Returns: - blinks:List[int],intervals:list[int],offset_time:float: [description] + blinks:List[int], intervals:list[int], offset_time:float """ eye = img @@ -55,7 +56,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40, Monitor offset_time = 0 - # 瞬きの観測 + # observe blinks while len(blinks)Tuple[List[int],List[int],float]: + """measuring type/intervals of player's blinks and the interval of pokemon's blinks + note: this methods is very unstable. it not recommended to use. + Returns: + intervals:list[int],offset_time:float: [description] + """ + video = cv2.VideoCapture(0,cv2.CAP_DSHOW) + video.set(cv2.CAP_PROP_FRAME_WIDTH,1920) + video.set(cv2.CAP_PROP_FRAME_HEIGHT,1080) + video.set(cv2.CAP_PROP_BUFFERSIZE,1) + + pl_state = IDLE + pk_state = IDLE + blinks = [] + intervals = [] + pl_prev = time.perf_counter() + pk_prev = time.perf_counter() + + prev_roi = None + debug_txt = "" + + offset_time = 0 + + blinkcounter = 0 + + # observe blinks + while len(blinks)0.3: + blinks[-1] = 1 + debug_txt = debug_txt+"d" + pl_state = DOUBLE + elif pl_state==DOUBLE: + pass + + if pl_state!=IDLE and time_counter - pl_prev>0.7: + pl_state = IDLE + print(debug_txt, len(blinks)) + + if pk_state==IDLE: + #poke eye + roi_x,roi_y,roi_w,roi_h = pkroi + roi = cv2.cvtColor(frame[roi_y:roi_y+roi_h,roi_x:roi_x+roi_w],cv2.COLOR_RGB2GRAY) + + res = cv2.matchTemplate(roi,pkimg,cv2.TM_CCORR_NORMED)#CCORR might be better? + _, match, _, _ = cv2.minMaxLoc(res) + cv2.imshow("pk",roi) + cv2.waitKey(1) + if 0.40.7: + pk_state = IDLE + + cv2.destroyAllWindows() + print(intervals) + return (blinks, intervals, offset_time) + def recov(blinks:List[int],rawintervals:List[int])->Xorshift: """ Recover the xorshift from the type and interval of blinks. @@ -443,8 +538,8 @@ def recovByMunchlax(rawintervals:List[float])->Xorshift: Xorshift: [description] """ advances = len(rawintervals) - intervals = [interval+0.048 for interval in rawintervals]#観測結果のずれを補正 - intervals = intervals[1:]#最初の観測結果はノイズなのでそれ以降を使う + intervals = [interval+0.048 for interval in rawintervals]#Corrects for delays in observation results + intervals = intervals[1:]#The first observation is noise, so we use the one after that. states = calc.reverseStatesByMunchlax(intervals) prng = Xorshift(*states) diff --git a/src/underground.py b/src/underground.py index 1a95d63..fcb0c3a 100644 --- a/src/underground.py +++ b/src/underground.py @@ -112,7 +112,7 @@ def reidentifyInSecretBase(): if player_eye is None: print("path is wrong") return - blinks, observed_intervals, offset_time = rngtool.tracking_blink(player_eye, 870, 680, 85, 90, size=6) + blinks, observed_intervals, offset_time = rngtool.tracking_blink(player_eye, 870, 680, 85, 90, size=7) reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, npc=0) if reidentified_rng is None: print("couldn't reidentify state.")