Пример #1
0
    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);
                }
            }
        }
    }
Пример #2
0
    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);
            }
        }
    }