๐พ Archived View for bbs.geminispace.org โบ u โบ stack โบ 17125 captured on 2024-05-26 at 14:46:31. Gemini links have been rewritten to link to archived content
โก๏ธ Next capture (2024-06-16)
-=-=-=-=-=-=-
Surprize! 'Simple' things turn out to be much more complicated than they should be.
This is my second go around: first time was spellbinding, which I implemented it as a specialized CGI program with a bunch of adjacent programs and scripts. While that worked, it required keeping track of a lot of details, scripts and cron jobs, and is so specialized that it's entirely useless for anything else.
So this time around I was going to be smart. I separated the game logic, the CGI script, from the database that stores the game state. Ideally the database should know nothing about the game itself it just serves data for each session.
The database worked like a charm. It is a separate server that maintains per-user data keyed by client certificate hash. Problem solved -- this component will work for any game -- it doesn't care about what data is stored.
While technically I could've used any key-value db, I chose to write my own for other reasons (no maintenance, in-memory-only, performance, minimal footprint, and need for full control, if you want to know)
So now the game automagically gets the session data,draws whatever it needs to draw, gets whatever input it needs to get and everybody's happy, right?
Well, we may also want to know global things like the leaderboard. We may want to limit the user to a single game a day or an hour.
And here are things get ugly. Where do we figure out the top 10 games? Certainly not the database because the database knows nothing about the game. And the game can only pull up data for its current user because it doesn't know anything about it other clients!
So now we need something that we've been trying to avoid: something that can access the database and pull up multiple records for many users. And figure out the top 10 scoring users.
For spellbinding I created a separate program that accessed the persisted database, dumped the contents, sorted them, and wrote a leaderboard file (which is simply embedded into the game screens). A cron task does it every 10 minutes. It works, but is problematic:
SpellBinding employs yet another brutal solution for managing games over long term. Another transcript simply kills the game every 24 hours. It also deletes the various dump files, leaderboard files, databases, and sets up a new game using a separate program. As you can see managing a spellbinding installation is not the easiest thing in the world.
Needless to say I'm not proud of it. It works OK here, where the expectations are pretty low, and maybe 20 users hit the site every day, but it really sucks to be honest. I didn't even bother releasing the code because the installation and maintenance checklist would be too convoluted (even if I had them!).
Now that I've learned so much from that experience I can fix all the problems, right?
To summarize: I now have a database server that is data agnostic, and a CGI Library that can access the database.
I wrote a simple game, Dice Poker, to try out some ideas on how to handle the situation.
Oddly, it's even more complicated now. SpellBinding kept its data on disc but now I have an in-memory server so I can't even get an immediate dump unless I add another command to the server, which I'd like to avoid. Also, it seems stupid to sort the entire database every time. Clearly the only time the leaderboard can change is at the end of a game so the CGI must trigger this process.
So here's what I did: the CGI, at the end of the game, executes a subroutine that deals with updating the leaderboard. It loads a special file that contains the top 10 entries and checks if this game deserves to be included. if so the game is inserted into the top 10, and another file, a leaderboard text file is generated from the new data, for inclusion into every page.
This is almost perfect. There is very little waste, and the solution is self-contained . However there is a slight issue with game management that will address in a minute.
While I could brutally wipe the database every so often I would like more fine-tuned solution. For instance what if I wanted to allow hourly games on a per user basis?
A minimal and rather generic change to the database would allow us to time-out individual records in the database. The database still doesn't know anything about the data, it just needs to wipe aged records every hour or whatever is specified. This completely does the trick on a per-user basis, without disrupting the other players
But what happens to the leaderboard? some additional logic is required to make sure that leaderboard keeps unique users.
This is getting much longer than I intended and so I'll stop. Aa you can see many problems have been solved, and many others (which I haven't even mentioned) remain. There's much work to be done on the database which is only partially implemented, and a bunch of open issues. However the game is already playable, and I'm pretty happy with the puzzles presented and the directions which are spontaneously emerging.
I don't really write code: I just try to be quiet, and the code writes itself. It is a practice similar to meditation, and is a source of great joy to me. I hope that you experience it too with whatever you do.
May 20 ยท 6 days ago
๐ gritty ยท May 20 at 23:41:
I see different yet similar struggles when I made Farkle. It's my first game and it's a hack job with many moving parts, but it works. Getting all the logic down in the few hours I have every week to code made it challenging for sure. I also enjoyed it.
๐ corscada ยท May 24 at 23:37:
I will say that I would be happy even if the leaderboard updated every hour as long as I know thats the case. I have to agree about cron jobs though.
Trying to avoid using databases atm when building projects but do want to try out cgisesh soon, looks very cool!
๐ stack [OP] ยท May 25 at 01:33:
@corscada: Check out the current version - the leaderboard updates at the end of each game. I wound up creating a separate leaderboard server!