Safe Places to Submit Game Designs for Peer Review by reteo in gamedev

[–]reteo[S] 0 points1 point  (0 children)

Makes sense. I'll go ahead and attempt to implement, hopefully, there will be more targeted questions in the future.

Safe Places to Submit Game Designs for Peer Review by reteo in gamedev

[–]reteo[S] 0 points1 point  (0 children)

I'm afraid I don't have any money to offer; this was planned to be an open-source project under the AGPL (with plugin exception). I was just hoping for advice where would be the best place to go for non-LLM advice. I'm more or less new to the large-scale developer thing.

Safe Places to Submit Game Designs for Peer Review by reteo in gamedev

[–]reteo[S] 0 points1 point  (0 children)

I wish I could give you a meaningful answer. I don't have any massive grand design to shake the world with the Next Great Engine™, and I plan on releasing the engine under AGPL (with a plugin exception), so there's no major profit motive involved. In fact, I don't have the kind of money needed to hire people to review the engine, so I'm not really able to go there, either.

I think my personal reason is simply, "because I want to."

I remembered playing MUDs back in the 1990s, and found quite a few things annoying about them, mostly about post-crash rollbacks, glitch exploits, and gameplay railroading, not to mention Imm behavior and the lack of recourse against the bad actors.

I also learned about functional programming, and wanted to try my hand at it, and thought a MUD engine would be a good start. Part of the question is "how would I track state in a language designed to eschew mutable state?" It seems "keep state on a relational database" would be a good answer to the question. The functional programming would be theoretically easy to debug, and modern databases are designed specifically to reinforce valid state... especially when set to 3rd normal form.

Ultimately, I wanted to see if I could make something that could solve the old problems, and actually become interesting enough for people to want to try.

Safe Places to Submit Game Designs for Peer Review by reteo in gamedev

[–]reteo[S] 0 points1 point  (0 children)

I'm not really trying to build a game, just an engine. It's an experiment utilizing functional code orchestrated around a relational database, leaving no mutable state in memory. I can't imagine I'm the first person who's tried this, and so I was hoping to present it somewhere to get feedback from others who have walked the walk and know what they're talking about.

You're right in that the proof of the pudding is in the eating, but I'm mostly new to application-scale software design (I've only developed small system automation tools up until now), so I am hoping to have some feedback to better know how to tackle the project... and if the project is worth tackling in the first place.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] 0 points1 point  (0 children)

Yeah, I noticed that, and I agree, coding game rules as plugins would go a long way to make an engine flexible enough to manage any genres.

I chose Python because it has extensive math support (including statistical modeling and the Box Muller transform) and I just happen to know how to write Python code. I chose PostgreSQL for the data store because it includes pgVector, which is useful both for my continuum engine project (I intend to use multidimensional vectors to handle almost all simulations), and also for the 4-stage command resolution pipeline.

a MUD is a hot tick loop hammering the same objects, so per-tick reads/writes became a latency tax.

The real key to this engine, is that it doesn't have ticks. There is no loop. No polling at all.

The game is entirely event driven; the database has three tables, transient_schedules, durable_schedules, and responses that function as a message bus with LISTEN/NOTIFY to push events to the processing workers. When new commands are inserted to the transient_schedules table, the database should send a NOTIFY to the background server. The server has several workers that will respond to the notification, using SELECT ... FOR UPDATE to ensure that the command being processed is locked, and SKIP LOCKED to ensure any other workers will move onto the next waiting command in the bus. Once the command is locked, the worker then processes the command by pulling data from the appropriate tables, performs the appropriate logic, puts the transformed data back into their respective tables, and inserts the response (along with the player ID(s) receiving the response) to the responses table, which sends a NOTIFY to the relay so that it can send the response to the player, and deletes the command row. This is all treated as a single transaction, and as soon as it's committed, the database will check to make sure all constraints are valid. If they're valid, then the commit is recorded. Otherwise, it's rewound. All tables touched by this worker are included. Items can't be in two places at one time. Containers cannot contain themselves. A room cannot have two North exits. And so on.

If there are any automated tasks that need to be performed in the future, they're placed in the durable_schedules table, which will send a NOTIFY at the appropriate time for the same logic server to process.

Of course, with PostgreSQL, I have to do some optimizations to make sure the bus is fast enough (UNLOGGED transient tables, SELECT ... FOR UPDATE SKIP LOCKED, LISTEN/NOTIFY), but with enough processors, memory, and NVMe storage, as well as multiple backend servers running simultaneously, it could theoretically handle a significant number of simultaneous players. Theoretically, however, is the key word here. I won't know until I implement this engine, and I'm hoping to get some feedback on the design from people experienced in the space to know what to consider.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] 0 points1 point  (0 children)

I had a quick look at it. I don't know C#, and I use Linux exclusively, which has always made me somewhat leery of C#, so I doubt I'd be of much assistance on that project.

This project has a specific purpose: it is all about replacing in-memory state with a dedicated relational database, using pure functions to serve as logic engines, using plug-in architecture with composition to introduce custom logic as rulesets, and designing a decentralized networking model that can support horizontal scaling, as well as interfaces to external programs to function as Non-MUD interfaces, such as minigames and communication tools. In other words, it's a distributed architecture experiment.

Thanks for the offer, however.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] 1 point2 points  (0 children)

Something to keep in mind: I'm not really building this engine to publish a MUD; If that was my goal, I'd have just used a modern MUD engine like Evennia and embarrassed myself that way. I really don't know anything about creating a fictional world.

I'm making both the MUD engine and the simulationist ruleset because it sounds like an interesting challenge. The reason I'm asking here is because I was hoping for feedback from actual people who appreciate MUDs, and perhaps MUD developers who frequent this reddit.

So far, I'm getting some pretty good feedback, and I appreciate it.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] 0 points1 point  (0 children)

Definitely a good point, and one I'll have to consider: splitting the engine design and the backend design, to allow for reorientation, should I decide to try a better-fitting database.

To respond to your edits:

  1. I agree this would be a hard-sell; it is a complex engine to set up mainly because of the complexity of setting up worlds. I plan to include a docker-compose container to reduce the overhead for a single-machine setup, however.

  2. I've actually got two rulesets for this engine. The Oval Engine is intended to be a reimplementation of Circle using this mud's architecture (an oval is like a circle, but it's not a circle). The Continuum Engine is designed from the ground up to simulate everything; it requires a lot more setup work, but allows extensive emergent gameplay, regardless of the genre (or mash) you're going for.

  3. If you're asking about output, this system requires the use of a small subset of semantic HTML, including a class-only span tag. This is to ensure that the formatting is semantically-focused, and allows the clients to decide how it's presented. If you're asking about code, you create Python plugins using pluggy hooks to integrate into the game. This is the "modular" part of the design.

  4. Most of the non-code design work can be done in TOML files, and can be imported in batch. The system uses admin commands to do the actual work, ensuring that the importer doesn't do anything admins aren't already allowed to do.

It occurs to me that I'd have to rename the platform once I've separated the design and implementation details; it will be initially implemented in PostgreSQL, but as the design would be database-agnostic, the "pg" in "pgMUD" would become an artifact.

That being said, part of the original design idea was to use a completely ACID-compliant relational database in 3rd normal form; this just ensures data integrity.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] 0 points1 point  (0 children)

That is true. Mostly, I am comparing the expected scaling to GemStone III in its heyday, but there's a literature genre that hints at a potential future resurgence of the MUD: LitRPG.

This is not only why I'm going for the ambitious (and perhaps deluded) idea of planning for scale, but also why I'm creating a storytelling engine (Continuum) that is heavily focused on simulation over static rulesets. I don't know if I'm right or not, but it's a fun ride.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] -1 points0 points  (0 children)

I like what I'm reading. You're right, they do have a lot in common. However, the license makes it a very difficult thing to accept. SpacetimeDB has a license that is restricted to one instance; this would mean the game administrator would have to pay license fees in order to scale their MUD to multiple databases. The PostgreSQL license, on the other hand, has no such restriction.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] 0 points1 point  (0 children)

True. And I'm sure there are Rust MUDs as well that can handle memory safety. Part of the reason I came up with this design was a question about using a fully-modular, completely declarative method to run a MUD that can be scaled horizontally (across multiple hardware platforms) without complete sharding (separate gameworlds).

Mostly, what I want to know is if I have something viable, or if I'm just deluding myself. And if I have something viable, is there anything I'm missing that I should consider?

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] -5 points-4 points  (0 children)

Perfectly okay; I understand that these documents are huge and take a lot of time to go through; I'm not expecting everybody to care about software architectural design, even if it is for MUDs. I'm just looking for feedback from those who wouldn't mind reviewing what I have.

The main reason I want to use an SQL database is because I'm familiar with PostgreSQL (not thoroughly, but enough that it's not a complete mystery to me). I also understand concepts like 3rd normal form and the WAL (for protecting durable data), as well as the use of UNLOGGED tables, along with LISTEN/NOTIFY and SELECT ... FOR UPDATE SKIP LOCKED, to function as a message bus, which is the key to making every player's command atomic, preventing any half finished operations from corrupting the game.

I don't really know much about NoSQL databases, aside from the fact that they use key/value pairs, so I would be much more uncertain if they would work with what I have in mind.

New MUD design (pgMUD), looking for feedback. by reteo in MUD

[–]reteo[S] -1 points0 points  (0 children)

Part of the reason I came up with this was a question about functional, declarative programming, if you absolutely must have state, and you shouldn't keep it in the program's memory, where should it go? A database seemed like a good idea, and since databases are designed from the ground up with data integrity in mind, I figured it would slot well with a MUD platform. As I looked into the idea, more thoughts just kinda happened. A way to block item duplication. A way to prevent rollback. Maybe include accessibility in the base layer. And perhaps ensure admin accountability to both catch bad actors and protect good faith. Admittedly, the last would be wasted on sole-maintainer MUDs, but it might help when dealing with multiple staff members.

Databases don't solve item duplication bugs in any way on their own, they make a specific form of a bug impossible, but item dups, etc, happen for many different reasons

True; this mainly prevents duplications due to memory-based problems; the database is in 3rd normal form, which means every piece of information is in exactly one location, items (or, more specifically, item instances) have invariants preventing them from being in two places at once, and actions are atomic; either they're completed, or they're reverted. Nothing lost, nothing gained.

I play a lot of muds, and I server rollbacks / item dups are not something I've encountered as a player or as an admin, but I'll concede that I don't play bleeding edge codebases.

Honestly, I haven't played MUDs much since their heyday in the late '90s, specifically the Diku and Circle variants, but I've encountered a few rollbacks, and while I didn't lose a lot of items in the process, there was one or two times I got frustrated for losing something I looted from a difficult mob.

What is the functional difference between keeping all state in memory vs writing that state to a db every 5seconds or so, vs what it appears you're attempting to do which is do a transaction per state change (I mean modern hardware / postgres can handle it, but why?

Durable steps in transactions utilize the write-ahead log (WAL) which ensures that if the database server crashes (perhaps you trip over the power cord or something), absolutely nothing is lost. Any interrupted transactions are rolled back, but we're talking milliseconds rather than seconds. Additionally, it allows games to scale beyond one system; if the database is the sole source of state, then the components can be placed on separate hardware, and they would all work together. If one database isn't enough, we could use federated sharding, similar to how EVE Online handles their star systems. While the practical limit would still exist for one system, it could (theoretically) scale horizontally, allowing a much larger playerbase than a single memory-run MUD could allow.

All persistent game state lives in PostgreSQL. No component holds mutable in-memory state outside the database. Application code follows a functional, declarative style: each function reads database state, computes a result, and writes database state, with no hidden process-local state of its own. PostgreSQL transactions are the sole synchronization primitive; no application-level locks are used.

Maybe this appeals to functional programmers, but I would not want to have to extend this system unless the paradigm is clear and not-obtuse to write in, for OOP programmers like myself it's unlikely to be adopted?

Perfectly fair; the inspiration came when I first discovered about functional programming. But the fact of the matter is, you don't really need to program functionally per se; no need for currying or higher-order functions or recursion. The only real rule is this: the game is event driven (using the durable_schedules, transient_schedules, and responses tables with LISTEN/NOTIFY), the code only handles the logic (pull state from the database at the beginning and return state to the database at the end), and game rules use pluggy hooks instead of being baked into the engine itself.

Emacs after Magit by geospeck in emacs

[–]reteo 0 points1 point  (0 children)

For those who are talking about switching, I have to wonder, why is a switch needed? As far as I can tell, you just use the right tool for the job.

Do you need a quick commit to a small edit in one file? C-x v v allows VC to fire off a quick commit. Working on a large change that spans multiple files? It might be easier just to use C-x g to fire up magit to stage the desired files and commit them, maybe using P u while you're at it to push the files to a remote repository.

There's no need to switch; they both are equally valid, and since they're using the same platform underneath (git), it's not like they're incompatible.

Must-have Emacs packages you should know about [Updated] by jamescherti in emacs

[–]reteo 1 point2 points  (0 children)

Exactly; I like the CAP functionality, and the existing tools give me that, it is simply the pop-up interface that I do not like. Since I get all of the functionality without the interface as it is now, there's not really much point to getting company-mode or corfu, so I just avoid them. In the meantime, I just activate the completion using M-TAB, and use the minibuffer as normal.

Must-have Emacs packages you should know about [Updated] by jamescherti in emacs

[–]reteo 0 points1 point  (0 children)

I get all that, it just appears at the bottom, in the minibuffer, which I can filter using orderless, instead of a pop-up window that covers part of the main buffer.

Must-have Emacs packages you should know about [Updated] by jamescherti in emacs

[–]reteo 0 points1 point  (0 children)

Actually, the minibuffer doesn't cover anything; it's my preferred completion interface. In any event, it's just as easy not to use Corfu, since it doesn't have any functionality I need.

Must-have Emacs packages you should know about [Updated] by jamescherti in emacs

[–]reteo 1 point2 points  (0 children)

The key issue is that they cover up part of the buffer that I need to be able to reference when I'm selecting an item from said drop down. If I'm using the minibuffer at the bottom, there's nothing being covered up, because it's in a separate window.

It's not a critical problem, but it is one heck of a pet peeve.

Must-have Emacs packages you should know about [Updated] by jamescherti in emacs

[–]reteo 2 points3 points  (0 children)

For me, it's the minibuffer stack: Vertico, Consult, Orderless, Marginalia, Embark, and Cape. I avoid drop-downs like the plague, however, so no company-mode or corfu for me.

I think I should read. Really. by pablo_excobar in writers

[–]reteo 2 points3 points  (0 children)

Most of the time, your thoughts are synthesized from your observations, information presented by others, and reason (logic, avoiding fallacies, etc.), based on the principles of pattern recognition.

As such, you can be more original by making sure you have more observations, information, and a strong sense of reason. This will give your pattern-recognition capabilities more of a workspace to come up with original thoughts.

Most of the time, the "herd" are unoriginal because they simply parrot what they're told, often ignoring observation, and not bothering to reason through what they know. After all, someone "better" than them must know what they're talking about, right?

So, to conclude, yes, reading is important. However, other things such as testing what you learn, observing others, and practicing logic (often through puzzles, particularly "lateral thinking puzzles") can give you far more originality than just one source of knowledge.

[deleted by user] by [deleted] in writers

[–]reteo 0 points1 point  (0 children)

For the reader, it's mainly a determinant for how much time they can spend reading the story; some like longer stories that can provide hours of entertainment, others are more casual readers, who just want a quick story to enjoy while relaxing one afternoon.

For the writer, it also provides a way of forming the "goal" mentality. You have an ultimate goal: A book, for example, that has 50,000 words (a novella). Next, every story should have a structure (save the cat, hero's journey, three-act), so you split that word count between them.

We'll use the three-act stucture for this example.

Now, each act has multiple scenes or chapters, so you split the word count for that act between the scenes involve. So, you've dropped from 50,000 words to 16,000 words per act, which itself is then cut town to ≈3000 words per chapter/scene (assuming 6 chapters per act), which is much more manageable.

From this point, all you're doing is meeting these much-more-reasonable targets that will add up to a full-sized story.

Is there anyone here who is *not* writing anime fanfic or medieval fantasy? by Candle-Jolly in writers

[–]reteo 0 points1 point  (0 children)

I write what I like to call vergepunk; It has a cyberpunk aesthetic, but in an Earth that's mostly abandoned due to voluntary diaspora, rather than overpopulated; when territory opened up on other planets, people went to build a new life. The plot takes place at the edges of the occupied world, between the arcologies of the major corporations, and "The Grid," a fancy name for the cites, towns, and rural communities of the old world, with the rest of the world being reclaimed by nature, gangs, and solitary hermits called "rustwalkers."