ID:2300445
 
I've been toying around with a space game and the life support systems for a ship. Specially, the act of pumping oxygen and sucking it out. At present, I'm looping through all connected tiles when a leak state change occurs. This is pretty CPU intensive and it doesn't lend itself well to accounting for volume.

I thought I could improve performance and overall impact of volume by creating room datums to store information like size, room connections and etc. Then it occurred to me that I might be able to leverage the area atom for this.

Any thoughts or suggestions around this?
Using an area sounds like the right way to do it to me.

What kind of resolution are you hoping to achieve? Do you want to be able to track oxygen levels in individual tiles, track oxygen levels on a room/compartment basis, or track them for an entire ship?

My approach would probably be to track oxygen on a per-compartment basis (with each compartment being an area). A compartment would only have to consist of:

1) a volume
2) a set of openings
2) an oxygen level

An opening would just a size, and another area.

All openings would update every frame; if compartment A has less oxygen than compartment B, oxygen moves from B->A at a rate dependent on the size of the opening and the difference. Depending on that rate, you could trigger an event that sucks neighboring tiles in.

Space would just be an area with infinite volume and 0 oxygen.
Amusingly, both of the things you've described are different SS13 Atmospherics 'engines'

The every-turf approach is /tg/'s Linda
And the "use room datums/areas and connections between" them approach is ZAS (Zone Area Atmos)

Both can perform decently if optimised well.
In response to CrimsonVision
CrimsonVision wrote:
Amusingly, both of the things you've described are different SS13 Atmospherics 'engines'

The every-turf approach is /tg/'s Linda
And the "use room datums/areas and connections between" them approach is ZAS (Zone Area Atmos)

Both can perform decently if optimised well.

That's my understanding as well. The benefit of having both systems is when there's a hull breach you're able to rapidly suck out all the air from a room with very little CPU.

For day to day airflow on the station you use tile by tile flow.

This is a topic that interests me a lot and I haven't seen a great deal of research being done into new ways of doing it. SS13 pretty much has the best atmospherics around even if they're slow when you run it on a platform like BYOND.
It's interesting that they are using two.

I have seen some promise with creating a Room datum with parent_type = /Area. It actually opens a lot of other doors for me (in theory) such as, being able to select rooms, triggering room alarms, and etc so it seems like a good direction regardless of life support.

I'm just starting to work on how to process all the rooms because you have to make a number of passes to properly handle the distribution with each event.

I'm also going to think about some other ways to show the level of oxygen in each room. When you apply an overlay or change the color of the turfs (to red as example), it can be pretty expensive to show smooth transistions. I'm hoping to find an alternative that gets the job done for a lot less. I don't know how ss13 does it.

In response to PopLava
Is the map static or can you move the walls around? That's a big deal. If all you need to do is manually draw out each room that's easy.
Use areas for each room if it's a single player game.
var/area/a=src.loc.loc//as per lummox, and it works to grab areas
//just an example


Otherwise datums with lower left upper right coordinates plugged in will allow for block turf checking (not sure how intensive that would be).

In response to Zecronious
Zecronious wrote:
That's my understanding as well. The benefit of having both systems is when there's a hull breach you're able to rapidly suck out all the air from a room with very little CPU.

For day to day airflow on the station you use tile by tile flow.

This is a topic that interests me a lot and I haven't seen a great deal of research being done into new ways of doing it. SS13 pretty much has the best atmospherics around even if they're slow when you run it on a platform like BYOND.

Just to correct a misconception, I don't know of any SS13 server that uses both. It's either ZAS or LINDA, never both.

ZAS has the benefit of being extremely violent, rooms depressurize into space within seconds; but it absoloutely doesn't scale to large open spaces. It also doesn't have the amazing fire simulation as LINDA does. (I mean, there is fire, but LINDA's fire is better.)

LINDA is generally slower, you can actually see gasses move from tile to tile. But because it's not reliant on the chunk based system, it scales infinitely better and is more stable in terms of its CPU usage. And, as said, has better fire mechanics at the moment.
I'm generating the maps at run time so the Rooms (Areas) are getting created at run time as well.

This is going to be a co-op multiplayer game although I plan to support single player games as well. Ideally, I want it to be a multi-server mmog which is why I'm keen on keeping CPU utilization down.

For now, I've moved away from updating each tile and plan to update state per room. All tiles in a given room will be treated the same.

I'm not going for scientifically accurate. I'm going for simple, performant and gets the idea across.

Now that someone mentioned gas, I've got to think about that some because I hadn't considered other gas types. Spreading gas can be done similar to how I spread fire although my simplistic approach wouldn't account or allow for gas to react to things like pressure, weight and air flow.

1. Make a list
2. Store the X,Y,Z
3. Store the directions the title will share with
4. Store the atmospheric data
5. Create a loop for each Z you plan to use atmospheric data
6. Run through the loop
7. Check X,Y,Z. See what directions it shares with.
8. Add all atmospheric data from compatible directions as well as current atmospheric data.
9. Check to see if the average of the atmospheric data is greater, or less.
10. Check to see if atmospheric data is great enough to run a PushLoop on the tile itself, or if the atmospheric data is low enough to run a PullLoop.
11. Repeat loop.

Now you've created a purely list based calculating system without doing anything with any item other than calling a PushLoop/PullLoop on a turf that has had significant pressure gain/drop.

If you want optimization, then don't create 10000 loops for a 100x100 map. Just create 1. ;)
In response to LemonYourAid
LemonYourAid wrote:
1. Make a list
2. Store the X,Y,Z
3. Store the directions the title will share with
4. Store the atmospheric data
5. Create a loop for each Z you plan to use atmospheric data
6. Run through the loop
7. Check X,Y,Z. See what directions it shares with.
8. Add all atmospheric data from compatible directions as well as current atmospheric data.
9. Check to see if the average of the atmospheric data is greater, or less.
10. Check to see if atmospheric data is great enough to run a PushLoop on the tile itself, or if the atmospheric data is low enough to run a PullLoop.
11. Repeat loop.

Now you've created a purely list based calculating system without doing anything with any item other than calling a PushLoop/PullLoop on a turf that has had significant pressure gain/drop.

If you want optimization, then don't create 10000 loops for a 100x100 map. Just create 1. ;)

Thanks for the suggestion. I'll review this when I get back into the project at some point.