Skip to content

Implement Rule Builder#203

Open
silasary wants to merge 4 commits intomainfrom
rule-builder-was-merged
Open

Implement Rule Builder#203
silasary wants to merge 4 commits intomainfrom
rule-builder-was-merged

Conversation

@silasary
Copy link
Contributor

This is an absolute monstrosity of a refactor, but it is absolutely worth it.

I've stress-tested it on the ffxiv manual, over the past few months, and it can shave upwards of a minute off generation time.

That said, it is effectively a full rewrite of a lot of our core logic, so please test it properly.

Needs to be run against latest AP source, or it won't do anything at all.

"name": "Beat the Game - Deadpool",
"category": ["Unlocked Teams", "Right Side"],
"requires": "|Deadpool| or {YamlEnabled(free_deadpool)}"
"requires": "|Deadpool| or {YamlEnabled(start_with_deadpool)}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was a logic error that I discovered when implementing YamlEnabledRule

# if isinstance(value, bool):
# return value
# name = self.access_rule.__name__
# raise ValueError(f'Unexpected return value {value} from {name}')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if we want this here, or if I should remove it. I consider it a failed experiment, but it might be needed when we drop support for pre-0.6.7 and make RB rules mandatory?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personaly I would prefer we try and keep back compat somewhat but you know a lot more than me on how rules works.
in my ideal world there would be a way for us to detect incompatible rules and somehow make them work with the rule builder even if its only to explain that the logic require "functionPotato" to be true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On one hand, yes, absolutely.
On the other hand, permanently maintaining two separate codepaths is maintenance hell and technical debt.

Making this thing work is a much better way of doing backwards compatibility long term, as opposed to all the if use_rulebuilder branches and the legacy stringsub code.

break

if func and inspect.signature(func).return_annotation is str:
# I'm assuming that functions that return strings don't need states.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not let them have state?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

State does not exist this early

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under the old system, these functions are evaluated during generation, as it's trying to resolve item placement.

But this code is happening during set_rules, while the locations are still being built.

If we want a universal handler that can handle rules with (state) -> bool, we'd need to get the commented fallback rule at the bottom working.

rule_class = func
break

if func and inspect.signature(func).return_annotation is str:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had this idea while reading the code:
could we support functions that return valid rules? I could see someone doing some logic to build a rule and have that sent to us?
I have no idea how possible that would be its just an idea

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by that I mean return something like Has(X) & Has(Y)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically yes? But it's easier to just make a custom rule the right way:
https://github.com/silasary/APxiv/blob/287af9a70ac1d73c128949b6be066e36656876fc/src/hooks/Rules.py#L53-L59

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I very much want existing functions to continue to work without Builder, and the moment they can return a rule, that breaks.

@Mysteryem
Copy link
Contributor

Mysteryem commented Feb 14, 2026

I've stress-tested it on the ffxiv manual, over the past few months, and it can shave upwards of a minute off generation time.

While Rule Builder should be much faster for manual logic because manual logic currently re-parses each rule from json on every single call and evaluates every single part of a rule without any boolean short-circuiting, the performance improvement for the ffxiv manual is likely to be much more than other manuals because the ffxiv manual uses a lot of hook functions, and manual's current function parsing is extra slow to perform on every single access rule call.

I rewrote manual logic to compile all rules to lambdas a while back (https://github.com/Mysteryem/ManualForArchipelago/pull/1/changes#diff-a25c303033861df67335b2a78c209196808d8d93e059588997e9f5422bad35e8), but decided not to progress further until Rule Builder, since I expected Rule Builder would be the way forward for Manual.

@silasary
Copy link
Contributor Author

Oh, I am well aware that the FFXIV manual is an outlier when it comes to complexity and room for improvement. That's why I tested with it :)

@silasary silasary requested a review from FuzzyGamesOn March 2, 2026 11:08
@FuzzyGamesOn
Copy link
Contributor

With this being "an absolute monstrosity of a refactor", this feels too high risk to merge without a more recent stable release first (even though it includes tangible performance benefits for generation time). This could have a long time in unstable working out the issues, and I don't believe it should block the previous unstable improvements from being released in the meantime.

@silasary
Copy link
Contributor Author

silasary commented Mar 7, 2026

100% agreed. I think we get a new stable out soon, and then release an unstable with this shortly afterwards?

@silasary
Copy link
Contributor Author

New stable is out. Shall we?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants