After discovering Dialog, I have become enamored with the idea of writing text games in logic languages. Unfortunately, Dialog has some key limitations that makes me think twice about starting a large project in it: mutable facts can only be unary or binary, there is no/little support for FFI, and objects cannot be instantiated at runtime. While these problems can be worked around, it starts to defeat the purpose of using a DSL - not to mention the runtime costs of everything but hacking in an FFI.
Being passingly familiar with logic languages in general, I looked towards Prolog to see if it would be suitable and found that there is little support for mutability in most logic languages. One either passes around the world state (potentially slow) as a parameter, or uses the incredibly dangerous assert*/retract family. With a bit of imagination, I can envision perhaps some system that assembles prolog/datalog databases dynamically, or translates queries to SQL, but this is well beyond what I am familiar with.
Being out of my depth, I'm hoping I can ask around for some advice; Gamedev SE seems like an appropriate place to ask in lieu of the strangely hostile StackOverflow. If this isn't the right place, would anyone know of somewhere more suitable?
To clarify why I think Dialog is inappropriate, I will examine the workarounds that I know/can think of. For the limited arity of facts, you have the macro facility which allows you to bundle facts like so:
@($Obj is $Rel $Parent) *($Obj has relation $Rel) *($Obj has parent $Parent)
You may notice that this macro only works if
$Obj has only one relation (mutable facts are deterministic). This can be worked around by interpreting some datastructure composed of lists, but will miss out on optimization by the compiler. Similarly, you could enumerate these composite facts with IDs, but I also anticipate performance issues there.
@($Obj is $Rel $Parent ! $ID) *($ID has object $Obj) *($ID has relation $Rel) *($ID has parent $Parent)
For dynamic object creation, you can apply a similar tactic of assigning unique IDs to objects and tracking them with lists, but this again frustrates the compiler's optimization which is built around the object datatype (IIUC).
(new $Class is $ID) (there are $N instances) (world objects $Objs) (now) (world objects [$Class | $Objs]) ($N + 1 is $ID) (now) (there are $ID instances)