public static void IGT(int delay, string path) { MakeSave(); IGTResults res = Gsc.IGTCheckParallel(MultiThread.MakeThreads <Gold>(8), 120, new GscIntroSequence(delay, GscStrat.GfSkip, GscStrat.TitleSkip, GscStrat.Continue), 60, gb => gb.Execute(path) == gb.OverworldLoopAddress); Console.WriteLine(res.TotalSuccesses + " (RNG: " + res.RNGSuccesses(10) + ")"); }
public static void Start() { Yellow[] gbs = MultiThread.MakeThreads <Yellow>(8, "baseSaves/yellow_moon_backup.sav"); Yellow gb = gbs[0]; gb.Show(); new RbyIntroSequence().Execute(gb); RbyMap map1 = gb.Maps[60]; RbyMap map2 = gb.Maps[61]; Pathfinding.GenerateEdges <RbyMap, RbyTile>(gb, 0, map2[12, 9], Action.Up | Action.Down | Action.Left | Action.Right | Action.A); map1[21, 16].GetEdge(0, Action.Down).NextTile = map2[21, 17]; map1[20, 17].GetEdge(0, Action.Right).NextTile = map2[21, 17]; for (int x = 0xd; x <= 0x12; x++) { for (int y = 0x10; y <= 0x11; y++) { map1[x, y].RemoveEdge(0, Action.A); map1[x, y].RemoveEdge(0, Action.Down); } } for (int x = 0xd; x <= 0x12; x++) { for (int y = 0x10; y <= 0x11; y++) { map1[x, y].RemoveEdge(0, Action.A); map1[x, y].RemoveEdge(0, Action.Down); } } for (int x = 0x11; x <= 0x17; x++) { map2[x, 0x1f].RemoveEdge(0, Action.A); } IGTResults initialState = Yellow.IGTCheckParallel(gbs, new RbyIntroSequence(), 60); StreamWriter writer = new StreamWriter("moon.txt"); writer.AutoFlush = true; DFParameters <Yellow, RbyMap, RbyTile> parameters = new DFParameters <Yellow, RbyMap, RbyTile>() { PruneAlreadySeenStates = true, MaxCost = 20, NoEncounterSS = 60, RNGSS = 56, EndTiles = new RbyTile[] { map2[12, 9], }, FoundCallback = state => writer.WriteLine(state.Log), EndEdgeSet = 0, }; DepthFirstSearch.StartSearch(gbs, parameters, gb.Tile, 0, initialState); }
public static IGTResults IGTCheckParallel <Gb>(Gb[] gbs, int timesec, GscIntroSequence intro, int numIgts, Func <Gb, bool> fn = null, int ss = 0, int igtOffset = 0) where Gb : Gsc { gbs[0].SetTimeSec(timesec); intro.ExecuteUntilIGT(gbs[0]); byte[] igtState = gbs[0].SaveState(); IGTResults introStates = new IGTResults(numIgts); MultiThread.For(numIgts, gbs, (gb, i) => { introStates[i] = gb.MakeIGTState(intro, igtState, i + igtOffset); }); return(IGTCheckParallel(gbs, introStates, x => fn == null || fn((Gb)x), ss)); }
public IGTResults IGTCheck(int timesec, GscIntroSequence intro, int numIgts, Func <bool> fn = null, int ss = 0, int igtOffset = 0) { SetTimeSec(timesec); intro.ExecuteUntilIGT(this); byte[] igtState = SaveState(); IGTResults introStates = new IGTResults(numIgts); for (int i = 0; i < numIgts; i++) { introStates[i] = MakeIGTState(intro, igtState, i + igtOffset); } return(IGTCheck(introStates, fn, ss)); }
static void Cherrygrove(Gold[] gbs, Action[] path, byte[][] states, GscTile startTile) { long cherryPathsFound = 0; long numSeenPaths = 0; HashSet <(int, int, int)> rngs = new HashSet <(int, int, int)>(); while (numSeenPaths < 30) { GC.Collect(); Console.WriteLine("Searching for cherrygrove path (" + cherryPathsFound + ")..."); var ret = RandomPathSearch.StartSearch(gbs, new RandomSearchParameters <GscTile>() { StateList = new List <byte[][]>() { states }, ClusterSize = 1, SS = 60, NumPathsToFind = 1, StartEdgeSet = 0, StartTile = startTile, EndTiles = new GscTile[] { r30[12, 46], r30[13, 46] }, ExecutionCallback = (gb, actions) => gb.Execute(actions) == gb.OverworldLoopAddress, }).First(); cherryPathsFound++; Action[] actions = ret.Actions; IGTResults results = ret.Results[0]; (int, int, int)rng = (results.MostCommonHRA, results.MostCommonHRS, results.MostCommonDivider); Action[] concatPath = path.Concat(actions).ToArray(); cherrygroveWriter.WriteLine(ActionFunctions.ActionsToPath(concatPath)); cherrygroveWriter.Flush(); if (!rngs.Add(rng)) { numSeenPaths++; continue; } else { numSeenPaths = 0; } gbs[0].LoadState(results.FirstState); End(gbs, concatPath, results.States, gbs[0].Tile); } }
private static void ParallelSearch <Gb, T>(ConcurrentBag <RandomPathResult> list, Gb gb, RandomSearchParameters <T> parameters, ref int pathsFound) where Gb : GameBoy where T : Tile <T> { Random random = new Random(); int igtFrames = parameters.StateList[0].Length; IGTResults[] results = new IGTResults[parameters.ClusterSize]; int statesIndex; int successes; while (pathsFound < parameters.NumPathsToFind) { Action[] actions = GenerateRandomPath(random, parameters.StartEdgeSet, parameters.StartTile, parameters.EndTiles).ToArray(); statesIndex = random.Next(parameters.StateList.Count - parameters.ClusterSize + 1); successes = igtFrames * parameters.ClusterSize; for (int i = 0; i < parameters.ClusterSize && successes >= parameters.SS; i++) { results[i] = gb.IGTCheck(parameters.StateList[statesIndex + i], gb => parameters.ExecutionCallback(gb, actions), parameters.SS, successes); successes -= results[i].TotalFailures; } if (successes >= parameters.SS) { if (parameters.FoundCallback != null) { parameters.FoundCallback(statesIndex, actions, successes); } if (parameters.NumPathsToFind > 0) { Interlocked.Increment(ref pathsFound); list.Add(new RandomPathResult { StatesIndex = statesIndex, Actions = actions, Results = results, }); } } } }
public static void StartSearch <Gb, T>(Gb[] gbs, DFParameters <Gb, T> parameters, T startTile, int startEdgeSet, byte[][] states) where Gb : GameBoy where T : Tile <T> { IGTResults initialState = new IGTResults(states.Length); for (int i = 0; i < states.Length; i++) { initialState[i] = new IGTState(); initialState[i].State = states[i]; initialState[i].HRA = -1; initialState[i].HRS = -1; initialState[i].Divider = -1; } RecursiveSearch(gbs, parameters, new DFState <T> { Tile = startTile, EdgeSet = startEdgeSet, WastedFrames = 0, Log = parameters.LogStart, BlockedActions = Action.A, IGT = initialState, }, new HashSet <int>()); }
static void R29(Gold[] gbs, byte[][] states, GscTile startTile) { HashSet <(int, int, int)> rngs = new HashSet <(int, int, int)>(); while (true) { Console.WriteLine("Searching for r29 path..."); var ret = RandomPathSearch.StartSearch(gbs, new RandomSearchParameters <GscTile>() { StateList = new List <byte[][]>() { states }, ClusterSize = 1, SS = 60, NumPathsToFind = 1, StartEdgeSet = 0, StartTile = startTile, EndTiles = new GscTile[] { cherrygrove[33, 7] }, ExecutionCallback = (gb, action) => gb.Execute(action) == gb.OverworldLoopAddress, }).First(); Action[] actions = ret.Actions; IGTResults results = ret.Results[0]; (int, int, int)rng = (results.MostCommonHRA, results.MostCommonHRS, results.MostCommonDivider); r29Writer.WriteLine(ActionFunctions.ActionsToPath(ret.Actions)); r29Writer.Flush(); if (!rngs.Add(rng)) { continue; } gbs[0].LoadState(results.FirstState); Cherrygrove(gbs, ret.Actions, results.States, gbs[0].Tile); } }
public static string CleanUpPathParallel <Gb>(Gb[] gbs, IGTResults initialStates, int ss, params Action[] path) where Gb : Gsc { List <int> aPressIndices = new List <int>(); for (int i = 0; i < path.Length; i++) { if ((path[i] & Action.A) > 0) { aPressIndices.Add(i); } } foreach (int index in aPressIndices) { path[index] &= ~Action.A; int successes = Gsc.IGTCheckParallel(gbs, initialStates, gb => gb.Execute(path) == gb.SYM["OWPlayerInput"]).TotalSuccesses; if (successes < ss) { path[index] |= Action.A; } } return(ActionFunctions.ActionsToPath(path)); }
public static void StartSearch(int numThreads) { bool[] threadsRunning = new bool[numThreads]; Thread[] threads = new Thread[numThreads]; Gold dummyGb = new Gold(); GscMap map = dummyGb.Maps[6149]; map.Sprites.Remove(5, 3); // Remove police officer (https://gunnermaniac.com/pokeworld2?map=6149#5/3) Pathfinding.GenerateEdges <GscMap, GscTile>(dummyGb, 0, map[7, 5], Action.Right | Action.Down | Action.StartB); Pathfinding.GenerateEdges <GscMap, GscTile>(dummyGb, 1, map[7, 4], Action.StartB); map[4, 5].RemoveEdge(0, Action.Down); map[4, 5].RemoveEdge(0, Action.Down | Action.A); // Don't walk into cutscene map[5, 5].RemoveEdge(0, Action.Down); map[5, 5].RemoveEdge(0, Action.Down | Action.A); // ^ map[7, 4].RemoveEdge(0, Action.Right); map[7, 4].RemoveEdge(0, Action.Right | Action.A); map[7, 5].RemoveEdge(0, Action.Right); map[7, 5].RemoveEdge(0, Action.Right | Action.A); map[4, 2].RemoveEdge(0, Action.Down | Action.A); map[5, 3].RemoveEdge(0, Action.Down | Action.A); map[7, 5].AddEdge(0, new Edge <GscMap, GscTile>() { Action = Action.Up, NextTile = map[7, 4], NextEdgeset = 1, Cost = 0, }); GscTile[] startTiles = { map[4, 2], map[4, 3], map[4, 4], map[5, 3], map[5, 4] }; byte[] startHours = { 10, 8, 2, 18 }; byte[] startMinutes = { 51, 59 }; byte[] audios = { 0xc1, 0xe1 }; int numSavesCompleted = 0; Writer = new StreamWriter("gold_toto_" + DateTime.Now.Ticks + ".txt"); int numSaves = startTiles.Length * startHours.Length * startMinutes.Length * 2 * 2 * 8 * 2 * 10; Console.WriteLine(numThreads + " threads, " + (numSaves) + " saves (" + (float)numSaves / (float)numThreads + " iterations)"); foreach (GscTile tile in startTiles) { foreach (byte hour in startHours) { foreach (byte minute in startMinutes) { for (byte momStep = 0; momStep <= 1; momStep++) { foreach (byte audio in audios) { for (byte frameType = 0; frameType <= 7; frameType++) { for (byte menuAccount = 0; menuAccount <= 1; menuAccount++) { for (byte igt = 0; igt < 60; igt += 6) { int threadIndex; while ((threadIndex = Array.IndexOf(threadsRunning, false)) == -1) { Thread.Sleep(50); } threadsRunning[threadIndex] = true; new Thread(parameter => { (int, (GscTile, byte, byte, byte, byte, byte, byte, byte))data = ((int, (GscTile, byte, byte, byte, byte, byte, byte, byte)))parameter; (GscTile tile, byte hour, byte minute, byte momStep, byte audio, byte frameType, byte menuAccount, byte igt)state = data.Item2; Gold gb; lock (startTiles) { MakeSave(state.tile.X, state.tile.Y, state.hour, state.minute, state.momStep, state.audio, state.frameType, state.menuAccount, state.igt); gb = new Gold("roms/gold_toto_temp.sav"); gb.SetTimeSec(120); gb.Hold(Joypad.Left, 0x100); } GscStrat.GfSkip.Execute(gb); GscStrat.TitleSkip.Execute(gb); byte[] mmbackState = gb.SaveState(); for (int mmBack = 0; mmBack <= 3; mmBack++) { GscStrat.Continue.Execute(gb); byte[] fsbackState = gb.SaveState(); for (int fsBack = 0; fsBack <= 3; fsBack++) { gb.Hold(Joypad.Left, "GetJoypad"); gb.AdvanceFrame(Joypad.Left); byte[] delayState = gb.SaveState(); for (int delay = 0; delay <= MaxCost; delay++) { int introCost = mmBack * 83 + fsBack * 101 + delay; if (introCost > MaxCost) { break; } gb.Hold(Joypad.A, "OWPlayerInput"); DFParameters <Gold, GscMap, GscTile> parameters = new DFParameters <Gold, GscMap, GscTile>() { NoEncounterSS = 1, PruneAlreadySeenStates = false, MaxCost = MaxCost - introCost, LogStart = string.Format("(x={0}, y={1}, h={2}, m={3}, momStep={4}, audio={5:x02}, frameType={6}, menuAccount={7}, igt={8}, mmback={9}, fsback={10}, delay={11}) ", state.tile.X, state.tile.Y, state.hour, state.minute, state.momStep, state.audio, state.frameType, state.menuAccount, state.igt, mmBack, fsBack, delay), EndTiles = new GscTile[] { map[7, 4] }, EndEdgeSet = 1, FoundCallback = state => EvaluateTototdile(gb, state), }; IGTResults results = new IGTResults(1); results[0] = new IGTState(gb, true, 0); DepthFirstSearch.StartSearch(new Gold[] { gb }, parameters, tile, 0, results); gb.LoadState(delayState); gb.AdvanceFrame(Joypad.Left); delayState = gb.SaveState(); } gb.LoadState(fsbackState); GscStrat.FsBack.Execute(gb); GscStrat.Continue.Execute(gb); fsbackState = gb.SaveState(); } gb.LoadState(mmbackState); GscStrat.MmBack.Execute(gb); GscStrat.TitleSkip.Execute(gb); mmbackState = gb.SaveState(); } Interlocked.Increment(ref numSavesCompleted); Console.WriteLine("Completed save " + numSavesCompleted + "/" + numSaves); threadsRunning[threadIndex] = false; }).Start((threadIndex, (tile, hour, minute, momStep, audio, frameType, menuAccount, igt))); } } } } } } } } while (true) { Thread.Sleep(10000); } }
private static void RecursiveSearch <Gb, M, T>(Gb[] gbs, DFParameters <Gb, M, T> parameters, DFState <M, T> state, HashSet <int> seenStates) where Gb : PokemonGame where M : Map <M, T> where T : Tile <M, T> { if (parameters.EndTiles != null && state.EdgeSet == parameters.EndEdgeSet && parameters.EndTiles.Any(t => t.X == state.Tile.X && t.Y == state.Tile.Y)) { if (parameters.FoundCallback != null) { parameters.FoundCallback(state); } } if (parameters.PruneAlreadySeenStates && !seenStates.Add(state.GetHashCode())) { return; } foreach (Edge <M, T> edge in state.Tile.Edges[state.EdgeSet]) { if (state.WastedFrames + edge.Cost > parameters.MaxCost) { continue; } if ((state.BlockedActions & edge.Action) > 0) { continue; } if (edge.Action == Action.A && state.APressCounter > 0) { continue; } IGTResults results = PokemonGame.IGTCheckParallel <Gb>(gbs, state.IGT, gb => gb.Execute(edge.Action) == gb.OverworldLoopAddress, parameters.NoEncounterSS); DFState <M, T> newState = new DFState <M, T>() { Tile = edge.NextTile, EdgeSet = edge.NextEdgeset, Log = state.Log + edge.Action.LogString() + " ", IGT = results, WastedFrames = state.WastedFrames + edge.Cost, }; int noEncounterSuccesses = results.TotalSuccesses; if (noEncounterSuccesses >= parameters.NoEncounterSS) { int rngSuccesses = results.RNGSuccesses(0x9); if (rngSuccesses >= parameters.RNGSS) { newState.APressCounter = edge.Action == Action.A ? 2 : Math.Max(state.APressCounter - 1, 0); Action blockedActions = state.BlockedActions; if ((edge.Action & Action.A) > 0) { blockedActions |= Action.A; } else { blockedActions &= ~(Action.A | Action.StartB); } newState.BlockedActions = blockedActions; RecursiveSearch(gbs, parameters, newState, seenStates); } } } }
public static void StartSearch <Gb, M, T>(Gb[] gbs, DFParameters <Gb, M, T> parameters, T startTile, int startEdgeSet, IGTResults initialState) where Gb : PokemonGame where M : Map <M, T> where T : Tile <M, T> { RecursiveSearch(gbs, parameters, new DFState <M, T> { Tile = startTile, EdgeSet = startEdgeSet, WastedFrames = 0, Log = parameters.LogStart, APressCounter = 1, IGT = initialState, }, new HashSet <int>()); }
private static void RecursiveSearch <Gb, T>(Gb[] gbs, DFParameters <Gb, T> parameters, DFState <T> state, HashSet <int> seenStates) where Gb : GameBoy where T : Tile <T> { if (parameters.EndTiles != null && state.EdgeSet == parameters.EndEdgeSet && parameters.EndTiles.Any(t => t.X == state.Tile.X && t.Y == state.Tile.Y)) { if (parameters.FoundCallback != null) { parameters.FoundCallback(state); } else { Console.WriteLine(state.Log); } } if (parameters.PruneAlreadySeenStates && !seenStates.Add(state.GetHashCode())) { return; } byte[][] states = state.IGT.States; foreach (Edge <T> edge in state.Tile.Edges[state.EdgeSet]) { if (state.WastedFrames + edge.Cost > parameters.MaxCost) { continue; } if ((state.BlockedActions & edge.Action) > 0) { continue; } IGTResults results = GameBoy.IGTCheckParallel <Gb>(gbs, states, gb => gb.Execute(edge.Action) == gb.OverworldLoopAddress, parameters.EncounterCallback == null ? parameters.NoEncounterSS : 0); DFState <T> newState = new DFState <T>() { Tile = edge.NextTile, EdgeSet = edge.NextEdgeset, Log = state.Log + edge.Action.LogString() + " ", IGT = results, WastedFrames = state.WastedFrames + edge.Cost, }; int noEncounterSuccesses = results.TotalSuccesses; if (parameters.EncounterCallback != null) { int encounterSuccesses = results.TotalFailures; for (int i = 0; i < results.NumIGTFrames && encounterSuccesses >= parameters.EncounterSS; i++) { gbs[0].LoadState(results.States[i]); if (parameters.EncounterCallback(gbs[0])) { encounterSuccesses++; } } if (encounterSuccesses >= parameters.EncounterSS) { if (parameters.FoundCallback != null) { parameters.FoundCallback(newState); } else { Console.WriteLine(state.Log); } } } if (noEncounterSuccesses >= parameters.NoEncounterSS) { Action blockedActions = state.BlockedActions; if (edge.Action == Action.A) { blockedActions |= Action.StartB; } if ((edge.Action & Action.A) > 0) { blockedActions |= Action.A; } else { blockedActions &= ~(Action.A | Action.StartB); } newState.BlockedActions = blockedActions; RecursiveSearch(gbs, parameters, newState, seenStates); } } }