Working on my version of Dynamicland. Today I got this small thing working where I can now live-edit the behaviour of the editor script, see https://www.youtube.com/shorts/ZjxPIv-XwoU
This might be your jam. I should revisit this, most of it is unimplemented. But the parsing part was interesting, since MTG has such a codified language for explaining the rules. My idea here was to take a card's rules text from the official API and parse it into smth that can be used in the game, so you could keep up with new sets with implementation. The weird rule-breaking edge cases will always fail, but a large set of design space can fit, I think.
Somewhat related, check out https://github.com/wordbots/wordbots-parser, a digital card game where you write the cards and the engine parses them to determine what they do. It's fun to mess around with.
>> The weird rule-breaking edge cases will always fail, but a large set of design space can fit, I think.
Well, in that case you just update the parser or the rules engine. That's precisely how M:tG Arena works and they 've managed to keep up with new sets at a pace never before seen in official M:tG engines. There was a time when writing an M:tG parser was considered impossible [1] and M:tG engines, both official and community ones, each had their own little DSL that they had to manually translate ability text into which could take months especially if the engine also had to be updated to use the new rules in a set. Eventually someone in Wizards realised this is just dumb and they did it the way you go about it above.
______________
[1] Source: my conversations with the folks behind Forge and other community-made M:tG engines.
A while ago I was playing the romhack Run&Bun, which drastically ups the difficulty of Pokemon Emerald. Watching others play, most of the game was doing 'calcs': calculating how to approach a battle. This was done using a javascript frontend to a simulator, and a lot of excel sheets.
My runs died pretty early, but there are some notes here as I was implementing that are fun to read. I implemented each battle as a test case and let my solver find a solution, then amended the plan and commented on what actually happened. For example: https://github.com/deosjr/runbuncalc/blob/master/run10.pl#L2...
I've made a lot of progress recently working on my own homebrew version, running it in the browser in order to share it with people. Planning to take some time soon to take another stab at the real (physical) thing.
Exploring the implementation of Dynamicland (dynamicland.org) using Guile Scheme, Hoot (scheme->wasm) and miniKanren. Main write-up can be found here: https://deosjr.github.io/dynamicland/
I cycle between learning about scheme macro hygiene and implementing more and more realtalk/dynamicland demos and trying to grok the programming model. Doing this in the browser is a weird but fun constraint that makes things shareable.
I recently shared a project I did using Hoot, by Spritely institute.
It's Guile Scheme compiling to WASM, and it works really well!
See https://spritely.institute/hoot/
Thank you for the feedback! I agree with all of the above.
Should've probably been a bit more clear on the dl-find syntax; I find it just as unacceptable as you do. It is the result of laziness: my intended use of this minimal Datalog does not include any querying whatsoever but abuses fixpoint analysis for side-effects (see https://github.com/deosjr/deosjr.github.io/blob/master/dynam... which I intend to go over in a future post).
I initially had it working like you described but butchered it for the above and haven't repaired it yet (see https://github.com/deosjr/whistle?tab=readme-ov-file#datalog). This version relied on some monstrous eval-hacking using a homebrew Lisp, which I've mostly cleaned up now in this version (https://github.com/deosjr/whistle/blob/main/datalog/datalog.... is a crime, for example).
The semantics are indeed limited to binary relations atm, which I agree is the main thing that disqualifies this as a proper Datalog. iirc the tutorial on Datalog that I based this implementation on only handled triples as well so I stopped there, but extending to N-ary relations is on my list to look into for sure.
This sounds very interesting! I'll have to take a look.
I am always worried about posting comments like mine because often people get defensive when I try to engage, as I see it, on substance. Responses like yours make it all worthwhile!
I appreciate it; this kind of exchange is exactly why I read HackerNews.
If you have any good sources on extending Datalog to N-ary relations, I'd love to know. Just had a look at the implementation I based mine on and it exclusively talks about triples: https://www.instantdb.com/essays/datalogjs
Coming from Prolog I'd like to get closer to the original if possible :)
They use triples as triplets can represent any n-tuple facts.
E.g., if you have a fact id=(a,b,c,d), you can record triples (id, 1, a), (id, 2, b), (id, 3, c) and (id, 4, d) and reconstruct original fact.
Look at it as columnar storage in databases.
Then, if your query only needs a third value from a 4-tuple facts, you can get only those, ignoring first, second and fourth values. This is what columnar storage engines do.
In fact, I read that one of most efficient datalog engines use relational query execution under the hood.
The paper you'll most probably find interesting is "Better Together: Unifying Datalog and Equality Saturation," but there are many others interesting things there.
It also turned up "Portability of Syntax and Semantics in Datalog" which turned out to be an unrelated NLP AI system called Datalog.
Bancilhon, Maier, Sagiv, & Ullman give as their reference for Datalog "Maier and Warren [1985]", which turns out to be "D. Maier and D. S. Warren [1985]. Introduction to Logic Programming, unpublished memorandum, Oregon Graduate Center," which I can't find a copy of easily. But given that Maier is a shared author we can probably trust their summary of what Datalog is.
Ceri, Gottlob, and Tanca reference "[120], [15], [16]," which are respectively:
J. D. Ullman, “Implementation of logic query languages for databases,” ACM Trans. Database Syst., vol. 10, no. 3, 1985
F. Bancilhon and R. Ramakrishnan, “An amateur’s introduction to recursive query processing,” in Proc. ACM-SIGMOD Conf., May 1986.
-, “Performance evaluation of data intensive logic programs,” in Foundations of Deductive Databases and Logic Programming, J. Minker, Ed. Washington, DC, 1986.
The Ullman paper is https://dl.acm.org/doi/pdf/10.1145/3979.3980, "Implementation of Logical Query Languages for Databases", ACM Transactions on Database Systems, Vol. 10, No. 3, September 1985, Pages 289-321 (33 pp.). Ceri, Gottlob, and Tanca screwed up the title. https://dl.acm.org/doi/10.1145/971699.320000 probably isn't it; the journal name, volume number, and issue number don't match, although it's the right author and year. That seems to be the oldest published Datalog paper, although the word "Datalog" hadn't been invented yet and doesn't appear in the paper.
I think I'm going to read the Bancilhon, Maier, Sagiv, & Ullman paper first, because it's shorter and has a more readable-sounding title, and then maybe Ceri, Gottlob, and Tanca, and then maybe Ullman, and then maybe a relevant chapter or two of Gallaire and Minker.
Thanks Dave, high praise! I was inspired after seeing you all take over the declarative & minimalist programming room at FOSDEM this year.
If you thought this was cool, wait until you see what I ended up using it for: https://deosjr.github.io/dynamicland/
I personally think this is much cooler :) But it needs some more explaining before I can broadly share, I think.
Now that I have you here, a question: am I correct in thinking that in Hoot, eval in the browser does not currently work with macros?
I'm glad you felt inspired! This Dynamicland implementation looks awesome. I look forward to this being shared to a wider audience. :)
Regarding your question, as of Hoot 0.6.1 we now have a psyntax-based macro expander integrated with eval so you can use syntax-rules and syntax-case. There are still rough edges, though. I'm currently focused on some non-Hoot tasks but the next Hoot priority is to implement a Guile-like REPL and really kick the tires on the interpreter before the 0.7.0 release.
I recently implemented a version of Bret Victor's Dynamicland in the browser using miniKanren, Datalog, and WebAssembly: https://deosjr.github.io/dynamicland/
Knowing how to implement a small logic programming language from scratch really feels like a superpower sometimes.
Repo is here if anyone wants to have a look: https://github.com/deosjr/unreal-talk
And a browser-based version can be found here: https://deosjr.github.io/dynamicland/live