ID:1256072
 

So basically I made a thread asking what I could do to fix the issue*- but I think the issue stems from me just not doing it right. SO basically how would you program this system? I want it to fill rooms evenly and be effected by vacuums.

*The issue is the gas keeps on cycling non-stop AND doesn't work correctly when it has to fill a room near by which is a vacuum.

turf
/*Oxygen
Nitrogen
Hydrogen
CarbonDioxide*/


var
O2 = 0//Only using O2 atm, upon getting proper dispersion I'll handle multiple gas types
H2 = 0
CO2 = 0


proc/Disperse(var/mother=null)

spawn(1)
//if(O2<=0) return

var/list/directions = list(NORTH,SOUTH,EAST,WEST)//,NORTHWEST,SOUTHWEST,NORTHEAST,SOUTHEAST)
var/turf/LeastPressure = null
var/turf/MostPressure = null
//Initially I had it disperse into all 8 directions evenly but this causes alot of CPU ussage
//Then I got the idea to limit that to just the 4 cardinal directions and then one tile at a time.



while(directions.len)
//this portion checks the 4 cardinal tiles and checks which has the lowest ammount of "pressure"/"O2"

var/DIR = directions[rand(1,directions.len)]
var/turf/Ta = get_step(src,DIR)
directions -= DIR
if(Ta)
var/dense=0
for(var/obj/A in locate(Ta.x,Ta.y,Ta.z)) if(A.density>0) dense++
if(Ta!=mother && dense<=0 && (Ta.O2>O2) && (abs(O2-Ta.O2)>=1) && !(MostPressure && MostPressure.O2 > Ta.O2)) MostPressure=Ta
if(Ta!=mother && dense<=0 && (Ta.O2<O2) && (abs(O2-Ta.O2)>=1) && !(LeastPressure && LeastPressure.O2 < Ta.O2)) LeastPressure=Ta

if(LeastPressure)//handles the transfer and sets up both tiles involved to re_transfer
var/O2transfer = round(((O2-LeastPressure.O2)/2)+0.5)
LeastPressure.O2 += O2transfer
O2 -= O2transfer
IconDisperse()

LeastPressure.IconDisperse()
LeastPressure.Disperse(src)

if(MostPressure)
var/O2transfer = round(((MostPressure.O2-O2)/2)+0.5)
MostPressure.O2 -= O2transfer
O2 += O2transfer
IconDisperse()

MostPressure.IconDisperse()
MostPressure.Disperse(src)



I spent probably about a year and a half on this problem.

There are significant problems with airflow. First of all, don't think about individual gas transfer. Think about pressure.

Total your pressure based on molar mass in a space, not based on the amount of gases in a space.

Don't worry about equalizing individual gases until you equalize the pressure. If you move 50% of the pressure out of a room, assume that 50% of the molar mass of a particular gas also moves with it.

Second, you want to stop thinking about your individual tiles. You want to gather the entire map into a series of rooms and breaches. This will cut down on the complexity of your simulation and give you the needed horsepower to perform a full simulation.

Next, you need to run through a list of breaches currently open in the region. Calculate pressure from high to low, not low to high.

Once you've figured out the relative pressure venting out of a room from each breach, you can figure out where it will meet equilibrium.

Once you figure out the relative strength of each breach in a room, you can figure out how to move objects in the room, and you can also figure out the maximum weight of objects it will move.


The only issue you need to prevent with this issue, is that you can wind up causing backflow in a complex system of depressurizations, which I honestly didn't have a problem with. I found that the backflow made for some interesting vortex-like effects.

This system isn't easy to design at all, though. I'd suggest taking your time to draw out a few diagrams. you'll see what I mean.
Hmm. Very insightful, I guess I was thinking about it all wrong.

When you say you spent half a year, do you mean programming a similar system?
In response to Jittai
Jittai wrote:
Hmm. Very insightful, I guess I was thinking about it all wrong.

When you say you spent half a year, do you mean programming a similar system?

Year and a half. And yes. The code is sealed, though, as it belongs to another team.
I'm just curious if this was for a byond project or not, as I don't know any project with a similar system.
Hey, I don't think I've ever posted on the forums but I do know of a "similar system" of sorts (or so I believe it to be)

It may be hard to sift through, but Space Station 13 and it's various modifications run some fairly complex Atmospheric systems as far as I can recall. Some revisions have even taken to programming newer, more efficient systems. I believe it handles O2, N2, N20,and C02. I haven't played in a long while but I also recall a version that had a fairly realistic pressurization/depressurization system where objects would fly out of hull breaches into space. Hopefully you can find what I'm talking about, good luck with your project.
This post has actually really intrigued me and I've even started programming a simple demo just to see how it should work. The system really does have a lot of complex mathematics, but looking at it now it doesn't just stop at gaseous objects.

I can foresee the algorithm being used even for more complex map or civilization generation. Mainly to see how objects would diffuse within certain bounds. Instead of gas, the objects could represent a population spreading out from it's center and expanding, as it hits other populations they could do a whole number of things, from merging into one another as a new, separate population or even battle and fight each other.

I'm going to continue my work and see what I can do with this by setting up different rules for diffusion and mixture.
The issue I'm having at the moment is trying to set chambers/rooms to be accounted for with out setting them down to be static.
What do you mean setting them down to be static? Predetermined? Any decent system will never hard-code anything that interacts with other objects.
I mean I want some-way to re-identify separate chambers as the map changes. If dealing with rooms and vacuums like a spaceship I would like the fact shooting through a wall will vent the room and repairing it will allow stabilization. Along with the ability to make new rooms in the vacuum and vent air into it, etc.

Start at a chamber wall and begin traversing across walls adjacent to that wall. You have a polygon when you've found a simple path from the start wall through adjacent walls back to the start wall. The area of the polygon can be used as the volume of the polygon. That's the basic idea anyways, but it would be a lot more complex in implementation.
Actually, I would use more of a spreading algorithm. You take the start point with full volume, then it spreads out in all directions, and each of those new spaces spread out, getting thinner as you go. They don't expand through walls, so they'll naturally stop. Pretty soon your entire room is full of an even volume of substance. It'll go through doors and actually spread around the environment much more naturally than Cody's example.
That's what SS13 does as far as I know, but I was going more in the room-based direction that Ter was talking about. The SS13 way requires you to check all adjacent tiles for their pressure and then adjust towards equilibrium that way. It's more natural, but also more processor intensive than finding polygons and then associating a datum with them to represent their pressure and leaks into adjacent polygons.
That's what I'm currently trying to get a handle of, setting up datums with large lists of turfs. What I'm hoping is for the code to identify each compartment and space separately- equalizing pressure after that is easy I would think.

If only league of legends didn't keep distracting me. :(
Well, yes, but we're assuming that we do in fact want a more realistic system, and in the great scheme of things, it doesn't take that much processing power, because after a long enough time, the gas will defuse enough to where (If you're clever you would do this) it would automatically disappear, seeing as it's too small of an amount to do anything. And on top of that, there should be a delay between calls of the loop that spreads the gas.

If we were doing everything very rapidly, then I could see your point, but even a modestly short delay of only a half-second, you should ever experience any real issues.
In response to Solomn Architect
Solomn Architect wrote:
Well, yes, but we're assuming that we do in fact want a more realistic system, and in the great scheme of things, it doesn't take that much processing power, because after a long enough time, the gas will defuse enough to where (If you're clever you would do this) it would automatically disappear, seeing as it's too small of an amount to do anything. And on top of that, there should be a delay between calls of the loop that spreads the gas.

If we were doing everything very rapidly, then I could see your point, but even a modestly short delay of only a half-second, you should ever experience any real issues.

I mostly handled room-level changes at the 1 tick per second interval.

Since decompression affecting objects was figured by a distance heuristic to a breach locality, I didn't have to update the breach effects on an object until I detected changes to the breach itself.

I also kept priority lists of objects within rooms based on weight, that way, I would only have to sort through a limited subset of objects within a room based on how much the breach pressure differential changed.

Moving objects to/from a location based on decompression is pretty simple in a 2D simulation. You can calculate a path once it enters the simulation using a pathfinding solution. You can then store that path, and interpolate based on time along the path. You don't have to repath unless a move fails, or a breach object closes. You can move hundreds of objects a second as long as you don't have to recalculate the pathfinding too often.


There's a lot to the system, but once you get the particulars down to the methodology required, it's not hard to work on.


As for gas spreading, you want to handle breaching and gas spread separately. breaching and pressure equalization is pretty fast. For tracking things like poison gas and flammable substances, you want to spread them by pathing flow until they hit the entire extent of the room. Once they've filled every tile, you can assume that added volume will spread equally. No more need to pathfind.

SS13's method is not only computationally wasteful, but also poorly executed.
Distance heuristic? Wouldn't it be more accurate to use total volume pressure as a factor? A force factor would also be useful to determine how much the objects are moved by the air.
The distance heuristic is used to modulate the force factor of the negative pressure on an object.

I use distance to cut down on pathing distance as an arbitrary optimization.
*Gasp!* Optimizing code before optimization is actually required?!

Lol, anyways, I guess that makes sense, but I would take each tile and treat it is a separate entity, rather than the gaseous mass as a whole. However, understanding BYOND's limitations, I would program that in C++.
I got a solid way to identify chambers, and what I thought would be easy turned out a tad harder, lol.

I'll keep working on it, the issue I'm having is trying to get the behaviour of the objects to be what I want.
Page: 1 2