I have a system where I'm sifting through a large number and variety of objects in my game, looking for objects that match an arbitrary search criteria that can be simple or complex.
For example, suppose a Foo has three integer properties, A, B, and C. I might search the list of Foo objects three times. First, I want to find a Foo where A>5. Second, I might want to find a Foo where A<B or B=8. Third, I might want to find a Foo where A=2, B=6, C>A, and C<B. The point is that I could arbitrarily pass any of a very wide set of conditions into the search.
Now here's my problem. In all cases, if I can't find an item that matches these criteria, I want to create a new Foo that does match, and add it to the list of Foo objects.
The thing I'm wrestling with is figuring out an underlying system of representing conditions that allows me to then create an item that directly matches those conditions. So far I've got two ideas, neither of which I'm a fan of:
- Repeatedly generate random Foo objects across the span of possible properties, until applying the criteria to one of them results in true. Given the possible permutations involved, this feels like an absolute performance nightmare, and would probably require a ton of caching logic to track what possibility spaces have already been tried.
- Establish a list of individual conditions with isolated variables (such as a GreaterThan condition with the referenced property that indicates whether the property is A, B, or C; and the target value) and create a corresponding declaration (Make [property] a random value between [targetValue] and [propertyMax]). Not only is this incredibly tedious, but I'm also not really confident I understand how it would work, particularly in C# but more generally also. This feels like self-reading code and that's something I have no experience with.
My question is, basically, what designs and techniques can I use to address this sort of issue - the need to create objects that match criteria, when those criteria could be arbitrary? Surely this has come up in other projects. What kinds of constraints or frameworks are applied to make this doable?