kmeow's blog

my first website in like 20 years

Scripting engine

January 15, 2020 — ~kmeow

I spent a couple weeks this month abroad and wasn't able to work on the MUD very much, but now that I'm back home and settled in I've been able to make some progress, chiefly on the game's scripting engine.

The more I thought about what I wanted done in the script language, the less Lua seemed like a good fit. Simulations and games are described very naturally in an object-oriented style, by which I mean you're able to build abstractions which closely match the problems at hand without having to deal in a lot of extra, conceptually irrelevant boilerplate. Lua is capable of mimicking OOP, but only through a very ugly, fragile approach involving metatables. It is also generally too simplistic to build very large systems out of - you end up having to write a lot tedious code that you may as well have just written in C.

After experimenting with a number of other languages, I decided on a relatively little-known one named Angelscript, which bills itself as a sort of scripted C++ lite. Superficially, it resembles Java much more than C++ (Java was the original interpreted C++ lite), but has operator overloading, non-member functions, and no Super-Object from which everything else is descendant.

As I've planned, the mud engine will manage the network I/O and data persistence, and everything else will be free for the MUD designer to implement in Angelscript. How MUD objects, players, rooms, commands, and virtually everything else are designed and structured will be entirely up to the scripts. Angelscript has JIT through a 3rd party library, so these scripts should run nearly as fast as if they'd been compiled.

The lack of a strong separation between the easy and hard parts of MUD development (outside of LPMud) is a big reason why there have traditionally been distinct, primary flavors of MU*s - people are understandably very timid about stripping out lower level parts of the game and generally don't need to, and so tend to just add atop of the core of what's already there. DIKUMUDs look unmistakably like DIKUMUDs, and every MUSH has about 3-4 layers of redundant commands from apparently every generation of its engine's lineage. There being kind of a living history of MUD engines is pretty cool and makes games easier for players to learn, but you should only have to look like a particular MUD if you want to.

tags: space western, MUDs, RPIs, space, programming

Modeling star distributions

December 23, 2019 — ~kmeow

It'd be nice to have a catalogue of every actual star in the Milky Way, but, as I noted in the last post, there are more than 200 billion of them. Storing the bare minimum (a name and coordinate) for each would take around 17 TiB of space, so what I'm going to do instead is procedurally generate them, perhaps adding well-known real stars and cosmic features manually afterward.

I found a parametric equation, developed by Canadian astronomer Jacques P. Vallée, which approximates the arms of the Milky Way using logarithmic spirals. I'm in the process of adapting the equation to model the distribution of stars in the game galaxy.

The equation:

My adaptation, rendered in GNUPlot

I've injected noise into the equation by multiplying the (tan p)-1 term by pseudo-random numbers, and I can decrease or increase the coherence of the arms (how tightly the stars stick to the spirals) by adjusting parameter R0.

I can run that equation with a set of coordinates as input to produce what I can interpret as the probability stars will be present in the volume around it.

There are an average of 0.004035059 stars per cubic light year in our galaxy, which means an average of 4 stars per 1000 ly3. This makes 1000 ly3 a very natural unit of volume to subdivide space into for purposes of star generation. (Imagine evaluating the equation 1000 times, only to have it produce a negative result 996 times on average - scanning even nearby space would be prohibitively expensive.)

Regarding the white space in the center of the model: the center of the galaxy around Sagittarius A* actually has a tremendous density of stars, but for now I've decided that players will unable to enter the region safely. The radiation would be overwhelming, jump drives would sputter out, etc. It's also about 26,000 light years away, which would take more than 17 years to cross even at the ludicrous speed of Star Trek warp 9 (1516 times the speed of light!)

tags: space western, MUDs, RPIs, space, math

Estimations for the game galaxy

December 22, 2019 — ~kmeow

Scale and coordinates

(This is more a scratch pad and a working design document/brain dump than a blog entry.)

1 light year = 63241.1 astronomical units (au)

1 au = 149597870700 meters

For reference, the maximum 64-bit signed integer is 9,223,372,036,854,775,807; the minimum 64-bit signed integer is -9,223,372,036,854,775,808. Modern computers can operate on numbers within this range very quickly, and much less quickly on numbers outside of it. Floating point numbers can represent larger ranges, but lose precision as the magnitude of their represented values increase.

The playable volume of the galaxy will be 110000 ly * 110000 ly * 1000 ly.

In au, this volume is expressed as 6956521000 au * 6956521000 au * 63241100 au.

In meters, 1040680729079834700000 m * 1040680729079834700000 m * 9460733900725770000 m.

Since there are more meters in the playable space than can be represented by 64 bit values (signed or unsigned), we'll have to use two coordinate systems simultaneously to represent object positions. An object's position will have a galactic coordinate, and a local "sector" coordinate.

The sectors the galaxy will be subdivided into will each have a volume of 1 cubic au.

The very center of the galaxy, the origin sector, will be at <0 au, 0 au, 0 au>. The top-right corner of the galaxy's volume will have the coordinates <3478260500 au, 3478260500 au, 31620550 au>, and the bottom-left corner will be at <-3478260500 au, -3478260500 au, -31620550 au>.

The top-right corner of each sector will have the local coordinates <74798935350 m, 74798935350 m, 74798935350 m>, and the bottom-left corner of each sector will be at < -74798935350 m, -74798935350 m, -74798935350 m>.

For notational convenience, sectors themselves can be divided into 8 equal cubic volumes called octants.

An octant will have a volume of 74,798,935,350 m3. The origin of a sector's local coordinate system, <0,0,0>, will be the corner shared by all 8 octants in the sector's center of volume.

An object's complete coordinates would take 384 bits to store and would look like <30000,7600204,4565211>.<9874122,-3661752,5644326>, which happens to be a unique position in the galaxy 1.326328E18 meters from the galactic origin. It would take ~140 years to cross this distance while traveling at the speed of light.

Celestial objects

Realistically, there would be approximately 250,000,000,000 stars in the galaxy, and around 100,000,000,000 planets. That is a total of at least 350,000,000,000 celestial bodies, not even considering the possibility of other objects such as comets. A name uniquely identifying each object in 350,000,000,000 would require at least 39 bits (log base 2 of 350,000,000,000 is 38.35).

With a unique name and a unique position, each celestial body would take 423 bits, or 53 bytes. Storing this for every celestial body would take 18550000000000 bytes, which is approximately 17 terabytes. By today's standards, storing all that would not be impossible, and not even really that infeasible (a 1 TiB drive in 2019 costs around 100 USD). It would, however, be pretty dumb.

350,000,000,000 major celestial bodies is a large number, but compare that to the 3,060,438,215,441,274,625,100,000,000 total sectors in the galaxy's volume. Ignoring the possibility of objects spanning multiple au (almost none do), the probability any given sector has anything in it is around 0.00000000000001144%. Put another way, ~99.99999999999998856% of all galactic sectors have absolutely nothing in them.

Populating the Galaxy

Consider that, even if you could visit one of these major celestial bodies every second, it would still take you 11,098.43 years to see all of them.

In other games, instead of precreating all these celestial bodies which would never, ever be seen, people have used pseudo-random number generation (PRNG) to determine - as the player explores - which sectors have a star in them, a solar system, etc, and which don't. PRNG algorithms are deterministic, which means given the same seed they will always produce the same sequence of output. That way, a game could create an object consistently every time a player could interact with it, and would never have to store anything about it unless the player somehow modified it.

I'll clearly have to do something like this, but there's a complication: I've wanted to simulate the motion of major celestial bodies. If everything was static and did not move, I'd only have to determine where to generate what; with motion, I need to determine both when and where to generate what.

After some thinking about it, my basic ideas at this point are:

1) Find equations that model, roughly, the distribution of stars around the galactic origin. Combine with a hashing function that maps every coordinate set to Y/N according to the probability that particular coordinate will have a star.

2) Ignore the motion of stars relative to the galactic origin - they move very quickly, but less so with respect to each other

3) Develop an equation that pseudo-randomly determines whether or not a star has a planetary system around it by using its static galactic coordinates as a seed/hash input

4) Model planetary orbits as ellipses and generate the parameters for each orbit by using the star's coordinate as seed

5) Repeat 3 and 4, but for planets and their moons instead of stars and their planets; use the planet's order # ORed with star coords as seed; assume planetary orbits never cross over each other

6) Ignore real time gravity interactions between celestial objects, even within a star system. Ships and characters may be affected - gravity assist might be fun.

Simulation and game mechanics

The simulation will only run for systems in which players are present. Different systems should be far enough apart that their planets should not be visible from each other at a level of detail that requires simulation. Star systems should start simulating once players travel within a certain distance of their outermost planet's orbit. Ships departing orbit will begin with the velocity of their orbit, and ships departing from a station or other ship will have the velocity of the place they left from.

Piloting commands will usually be relative to another object and ships will fly more or less automatically, but the motion of objects relative to one another will affect the time and distance of travel as well as the intercept point. Players should be provided tools that give them the optimal times for departure to a given destination.

I haven't yet decided how to model ship volume, if at all. OOC auto-piloting where your character or her ship computer does the actual work makes collision detection irrelevant (it'd be stupid in the first place). Stations could be represented by a radius, as could celestial objects.

How quickly I want to tick the simulation for a star system is probably something I'm going to have to experiment with. This isn't going to have to be rendered at 60 - 144 FPS.

Space magic and thoughts about game scope

After looking at the scale required for the game as I'd conceived it, there's no question we'll need FTL tech. I wonder how much and how fast. I like the idea that there could be corners of the galaxy no player could live long enough in real life to reach, even with FTL. The awful reality of space and our place in it works better for immersion than bouncing characters off arbitrary walls.

Putting in all this effort to permit an essentially unlimited range, though, as opposed to just having a few star systems ... is it too much? In other games I've seen people complain that the playerbase needed consolidation in a world with one city. With an ansible/space-internet and a primary hub with strong incentives to visit, perhaps it could work.

To really benefit from a larger arena, there'll have to be a fairly developed human spacefaring civilization (I haven't considered a game with contemporaneous sentient/complex alien life). Trade routes to raid/protect, pirate bases, derelict stations, and different political factions ... I can't see this all spanning between Earth and Neptune, exactly.

tags: space western, MUDs, RPIs, space, math

Some ideas about mechanics

December 20, 2019 — ~kmeow

Focus

While thinking about how I should design the skill system and how that would work with chargen, I came up with the idea of a mental focus attribute. It'd really be just like a stamina stat which would be drained upon any application of skill, then regenerate over time.

Some skills would not require mental focus points to perform, but would drain it anyway - if you're mentally exhausted, you're not just going to stop piloting a ship while trying to escape from a pirate, but you're probably not going to do it as well as you would were you fully rested, nor would you likely have the inclination or energy to craft 40 masterwork objects afterward.

The mechanic of a focus attribute would also let me give new characters skills commensurate with their age. If you've been doing something for twenty years, you're going to be better at it than you were ten years ago; on the flip side, you're also going to be older and have less mental energy to do it.

The amount of focus your character would have and how fast it would regenerate would be dependent on character traits, skills, and what he or she was doing. It could also be affected temporarily by things like alcohol and performance-enhancing drugs.

Stress

A related attribute I've been thinking about is stress, which could apply skill debuffs proportional (or not) to the amount built up. Combat would be the first obvious application of a stress mechanic - characters with particular traits/skills/experiences would have increased resistance to it, whereas someone without training or experience might rapidly crack.

I'll think about that while I finish up adding MCCP2 support.

MUD project

December 15, 2019 — ~kmeow

TECH

My current pet project is a MUD server. It started as a way for me to experiment with system building in Common Lisp, but I realized along the way that I'd end up using the FFI so much that I may as well just do it in C. So far it's multithreaded, uses a pool allocator, a heap-based PQ, epoll (judiciously, I hope ...). Compared to single threaded DIKU, certainly, my thread pool impl has so far shown very promising throughput.

After I get the heavy lifting done (which I just about have at this point - the next major subsystem I need to do is data persistence), I'll embed a scripting language like Lua or LISP and make the rest of the entire game in it, performance allowing. I want to be able to change any part of the game while it's live and have the changes take immediate effect, and also create an interface which makes it easy to make tools.

GAME

As for the actual game, I want to give the players most of the freedom of a MUSH (objects and rooms can be created and customized), but underpin that freedom by hard game rules and mechanics. For example, if your character had a certain amount of skill in say, weaponsmithing, they'd only be able to create a weapon up to a particular coded quality and the item should be described accordingly, though you'd be free to make it whatever you could otherwise imagine.

It'll be a roleplaying-intensive science fiction setting taking place primarily on ships and stations, and - this is the part that excites me most about designing the engine from the ground up - rooms will not be what holds the world together: rooms will be in the spacecraft and stations, but the ships and stations themselves won't move through those, they'll travel through simulated 3D space and have simulated properties like mass and top acceleration. Think vectors and waypoints in Cartesian space and craft control commands like approach station, enter orbit planet, follow cruiser 10km, ram interceptor.

With the horsepower of multiple threads, I'll hopefully be able to simulate (accurately enough for a text game) the movement of celestial bodies, station/ship orbits, etc. without worrying about adding a tremendous amount of latency.

Lorewise, think space western and generation ships instead of Starfleet. There'll be ancient, giant ships that essentially function like cities; gangs, corrupt megacorps, human cultures long and far removed from their roots on Earth. I haven't decided whether or how to incorporate FTL yet, and have yet to work out how combat will play - death will generally be permanent, though consciousness might persist through some sort of copying mechanism in rare instances. A key lore design point for me is to not shy away from popular sci-fi tropes. I don't want to reinvent the space western; I want the setting to be instantly familiar to devotees of the genre so they can pick up and roleplay without necessarily having to read a dissertation first.

tags: space western, MUDs, RPIs