ID:265314
 
Just a small idea...
Every time you walk on grass a certain amount of times, it turns into a dirtpath... thus lowering the monster spawns for that area... and walking in weeds too much would turn it into grass, and so on...

:o
I think I may use this for my game...
Dynamic grass generation! I like it.

Don't forget to make grass slowly grow back if hardly anyone steps on it, though, otherwise you'll eventually end up with a dirt wasteland. Autojoining turfs would be a nice visual effect for this, too.

Might be a bit CPU intensive for such a minor feature, but it's still cool. =)
In response to Crispy
I was actually thinking of something like this a while ago, but I decided it would be too much memory and CPU. It COULD be done in other media, but I don't think BYOND would handle this too well. Maybe you'd have to create something of an event system for it...

I could be wrong, but I can't see any way to do this logically without a lot of memory or CPU just being wasted on the environment.
In response to Crispy
Crispy wrote:
Dynamic grass generation! I like it.

Don't forget to make grass slowly grow back if hardly anyone steps on it, though, otherwise you'll eventually end up with a dirt wasteland. Autojoining turfs would be a nice visual effect for this, too.

Might be a bit CPU intensive for such a minor feature, but it's still cool. =)

_>
Thanks for the idea...
And I don't think it'd be THAT CPU-usage-ish...
Just when a mob steps on a tile raise a variable by ten, and if it passes by a certain ammount... ½ minute more the the path the deterate each time you step on it... AFTER, it's made. Otherwise, if it's just made, it'll b e deterated within ½ a minute unless you keep walking on it.
In response to Ter13
Well, let's see how much the CPU usage can be reduced. *puts on thinking cap*

Okay, the most straightforward way to make grass turfs get worn out is to give them a variable that indicates how worn they are, and add a certain amount to it whenever someone steps on it. Depending on whether the value has reached certain thresholds, change the turf's icon and do any necessary autojoining on it and adjacent turfs.

The cost for that is pretty minimal; in the best case, adding to a variable and doing a few if()s. In the worst case, you need to change some icons around and do a bit of calculations, but an efficient autojoining system would still handle this quite speedily. You'd get quite a bit more of a performance hit if you tried to dynamically generate the grass icon, so doing so is quite a bad idea.

So wearing out is pretty easy. Growing back is slightly trickier. The obvious solution is to run a global loop that periodically sweeps through turfs and subtracts from the variable. But that's pretty inefficient.

A faster way would be to only update it when you needed to. To facilitate this, to store the value of world.realtime when the turf is updated. When the turf is updated again, use the difference between the time then and the time now to work out how much to make the grass grow back.

Now we need to decide when to update the turf. An easy and mostly foolproof but still slightly wasteful solution is to update all the turfs in a large enough range of a mob whenever the mob moves (but only if it's a player mob). For efficiency, looping through block() is better than view() or range(): block(locate(x-5,y-5,z),locate(x+5,y+5,z)) (that assumes an 11x11 view). The only problem with that is that if a player doesn't move for a long time, they won't see the grass grow gradually; it'll all happen at once when they next move. There are various ways to make sure they can't be idle for a long time, or you can opt to do something like periodically check for idle clients (using client.inactivity) and make all turfs in range of their mobs update. Say, every few minutes or something. Because you're only looping through clients in the best case, and you're doing it very infrequently, the costs are drastically reduced.

I don't know exactly how fast that will run, but I think it's about as optimised as I can make it this late at night. =) Shouldn't be too slow, anyway.
In response to Crispy
Depending on the size of the world, how much things move around, whether or not they walk on the same tiles all the time or move about erratically to affect many tiles, and some other things, it might be better to just keep a list of turfs affected by this system. Then you could just loop through that list periodically.

If the map is not overly large and there are many people, most of the overrun grass is going to be checked all the time anyway. In this case, you could save a lot of time by looping through a list of the grass once every X amount of time since you would be looping through most of them, along with everything else around them, possibly multiple times per second.

If I were doing it, I would probably use both methods. Keep a global variable of true or false. When the loop is running, at each iteration check the number of clients logged in, toggling the global variable and aborting the function if there are a certain amount (determine this amount ahead of time by your own judgement based on map size an use). Whenever anyone moves, check the variable; if it is false, check the number of clients again, toggling the variable and calling the loop if over the specified number or looping through and changing the turfs in a view-ranged block if not.
In response to Loduwijk
o.o
turf
var/path
grass
icon = 'grass.dmi'
Entered(mob/M)
if(M.client)
path++
if(path>=50)
var/turf/path/P = new(M.loc,M)
grassrestore(src)
proc/grassrestore()
sleep(300)
path--
if(path<=50)
var/turf/grass/G = new(src)
else
grassrestore(src)

Something like that? >_>
In response to Hell Ramen
Not exactly. I don't think that would do quite what was wanted. Also, it would be a better idea to just change the turf's icon state instead of dropping a new turf onto the spot so you don't lose the data from the old one.

Doing it the way you just showed there, and making it work properly, it would be a bit more like the following.
turf/grass
var/health = 50 //I would tend to look at it as grass HP
Entered(atom/movable/A)
if(ismob(A))
spawn()if(health==50)regenerate()
if(health>0)health-=10
if(health<=0&&icon_state!="path")icon_state=path
proc/regenerate()
while(health<50)
sleep(300)
health++
if(health>=30&&icon_state!="grass")icon_state="grass"

Giving the turf its own function to handle itself is a nice way to go since it is more precise than a global function that loops through them all at the same time and it has more control over every other way to accomplish the task. But depending on how many turfs will be affected at any given moment, it might be harsh on the CPU. You will probably want to set background to 1 in the function no matter which way you do it so it doesn't freeze the computer up when things pile up.
In response to Loduwijk
Loduwijk wrote:
Not exactly. I don't think that would do quite what was wanted. Also, it would be a better idea to just change the turf's icon state instead of dropping a new turf onto the spot so you don't lose the data from the old one.

Doing it the way you just showed there, and making it work properly, it would be a bit more like the following.
> turf/grass
> var/health = 50 //I would tend to look at it as grass HP
> Entered(atom/movable/A)
> if(ismob(A))
> spawn()if(health==50)regenerate()
> if(health>0)health-=10
> if(health<=0&&icon_state!="path")icon_state=path
> proc/regenerate()
> while(health<50)
> sleep(300)
> health++
> if(health>=30&&icon_state!="grass")icon_state="grass"
>

Giving the turf its own function to handle itself is a nice way to go since it is more precise than a global function that loops through them all at the same time and it has more control over every other way to accomplish the task. But depending on how many turfs will be affected at any given moment, it might be harsh on the CPU. You will probably want to set background to 1 in the function no matter which way you do it so it doesn't freeze the computer up when things pile up.

But, grass isn't auto-joinable, paths are. ;o
I tryed it, it did not work too well. Basicly, when you weigh the positives and the negetives, it isnt worth it, at least on byond. If byond could hand graphics a little more gracfuly, it might be ok, but as is, it doesnt work out that great.
In response to Loduwijk
Loduwijk wrote:
Depending on the size of the world, how much things move around, whether or not they walk on the same tiles all the time or move about erratically to affect many tiles, and some other things, it might be better to just keep a list of turfs affected by this system. Then you could just loop through that list periodically.

If the map is not overly large and there are many people, most of the overrun grass is going to be checked all the time anyway. In this case, you could save a lot of time by looping through a list of the grass once every X amount of time since you would be looping through most of them, along with everything else around them, possibly multiple times per second.

If I were doing it, I would probably use both methods. Keep a global variable of true or false. When the loop is running, at each iteration check the number of clients logged in, toggling the global variable and aborting the function if there are a certain amount (determine this amount ahead of time by your own judgement based on map size an use). Whenever anyone moves, check the variable; if it is false, check the number of clients again, toggling the variable and calling the loop if over the specified number or looping through and changing the turfs in a view-ranged block if not.


Haven't played much with time, but why not have a ticker running (to keep game time, or use the actual clock I guess). I'm not too sure how intensive this is but make a loop that loops through all the grass tiles (block, or a list of the locations, or all turfs check but only run the process if it is grass...) and does 1 tile every 10 secs so as not to hog CPU. Each grass tile has 2 vars: it's life, and a last checked var to know when it was last refrenced. this will slowly updated the tiles not visited. Also you can have it skip the grass if it's life is full. The other time it's updated is when it's walked on.

Dynamic grass sounds cool, and would haved a good visual effect.
In response to Loduwijk
Loduwijk wrote:
Giving the turf its own function to handle itself is a nice way to go

Except that, as you mentioned, it's apparently less efficient than doing a global loop. I have no idea how much less efficient it actually is, but there are usually quite a lot of turfs in a world, so the impact would be more than usual.
In response to Crispy
Which is why I used it in the context that I did.

Loduwijk wrote:
Giving the turf its own function to handle itself is a nice way to go since it is more precise than a global function that loops through them all at the same time and it has more control over every other way to accomplish the task.

Letting every object run its own function lets the process be more precise, obviously, as its first benefit. If you are looping through all trampled turfs every X amount of time, they will all be changed at once regardless of the small time differences in which they were trampled. Something as slow as regrowing grass isn't important enough to warrent it as I said, but it is good to know of it regardless in case the system is used for any other similar things that do need to be more precise.

Besides that, you have more control over each individual object. For instance, what if you want the /grass type to just grow back normally but a subtype of /grass/corn to grow back with a couple /food/corn objects attached? It would be nicer to do it in a function belonging to the object than to check its type in a global function.

As I said though, it all depends on the program in question, since there are as many different ways to accomplish something as there are seperate programmers and many of those ways work better for different situations. This is the root of the whole "There is no THE code, dang it!!!" thing, as you know.

Interesting thread we have going here. Perhaps we should link people asking for "the code" over here so they can understand the problems of that style of reasoning. That is, assuming they understand what is posted here.
In response to Loduwijk
Hey, I practically INVENTED grass growth simulation in BYOND.

I have two simulations:


1. Simulates growth of grass, and how fast it can populate an area.

2. Simulates mutation in grass.


I am the grass master.
In response to Crispy
Good idea, Crispy.
In response to Loduwijk
Loduwijk wrote:
Which is why I used it in the context that I did.
[snip]
Letting every object run its own function lets the process be more precise, obviously, as its first benefit. If you are looping through all trampled turfs every X amount of time, they will all be changed at once regardless of the small time differences in which they were trampled. Something as slow as regrowing grass isn't important enough to warrent it as I said, but it is good to know of it regardless in case the system is used for any other similar things that do need to be more precise.

Oh, certainly. I much prefer being able to have that fine control, but I keep getting yelled at for doing that by certain people who shall remain unnamed (you know who you are, Theodis =P).

As I said though, it all depends on the program in question, since there are as many different ways to accomplish something as there are seperate programmers and many of those ways work better for different situations. This is the root of the whole "There is no THE code, dang it!!!" thing, as you know.

Yeah. If there was only "one code" for everything, this forum would have little reason for existing in the first place. =)

Interesting thread we have going here. Perhaps we should link people asking for "the code" over here so they can understand the problems of that style of reasoning. That is, assuming they understand what is posted here.

Good idea!