I have just written a bunch of code that pretty much does the following. each mob/creature type is given a text variable called scent that is at the moment either "meat" or "wolf". Then I set up an Entered proc on the turf that adds that scent to a list also named scent. Then I have my preds looking at turf in oview(1) and checking that turf's scent for "meat". It then deletes that scent(so that it doesn't loop back) and moves to that turf before looking in oview(3) for a creature to attack.
will this theory work? will my predators hunt all the "meat"? is there a flaw in my basic theory, or in my execution? I'm just starting the testing, but I wanted all of your input.
ID:161665
Apr 12 2008, 3:35 pm
|
|
Apr 12 2008, 3:45 pm
|
|
I'd just make every type of creature leave an invisible scent trail as an object that only certain people can see and then follow.
|
In response to Dragonn
|
|
after some testing with original idea, I think you're on the right path. you can't look at turf by using view() as far as I can see, so I should just make the scent an object with a blank icon! thanks a lot.
|
In response to Jehubuddaka
|
|
Or you could just give it a "stink trail" icon and set the objects invisibility var to 1, and give the people who are capable of tracking scents a see_invisibility var of 1, that way only they can see the stink trail. Maybe.
|
In response to Dragonn
|
|
no I'm actually using it so that my non-player werewolves can hunt and kill smaller creatures that count as food for them. I'm trying to get them to follow scent trails.
|
In response to Jehubuddaka
|
|
My suggestion is to have a scent object (invisible of course) which the "meat" leaves behind whenever it moves from a tile. This object should have an automatic decay, which you could then use to tell which direction the source of the scent is in (the less decayed it is, the closer you are). That way, you can use ohearers() to locate the nearby scents, and also you could have multiple scents overlapping a single tile, if for instance 2 or 3 creatures passed by that space before the predator smelled it.
You could distinguish between the creatures using a variable in the scent object like "source" which contains some form of ID, possibly a \ref text, so predators could pick which scent to track. EDIT: I forgot to mention that the decay could be used to automatically remove the scents after a certain amount of time, thus ensuring that they don't get cluttered up. |
In response to Perpetr8r the Perpetu8r
|
|
once I get the basics set up right, I will definitely be using your ideas. :)
|
In response to Jehubuddaka
|
|
Well, it took me an hour to figure out that I cant use view when the proc is being called by a non-player mob, but darn it, I got it working anyway. I used get_dist instead.
Also, I had a problem with setting the scent during the new command. I had: new /obj/odor(locate(src.x, src.y, src.z), scent=src.scent) It didn't work EVER no matter how I tried it. I ended up having to make the mob change every odor object within a distance of 1 to have its scent. here's the current code layscent(mob/M as mob) var/obj/odor/O new /obj/odor (locate(M.x, M.y, M.z)) for(O) if(get_dist(M.loc, O.loc)<1) O.scent = M.scent Now I had my werewolf track me across the entire map by giving myself the "food" scent, but once again I think I'm doing this the hard way. How should I be doing this? |
In response to Jehubuddaka
|
|
You can use the view proc when it's being called by a non-player mob. You probably didn't set the center parameter to anything. It defaults to usr, which probably isn't set in this case.
|
In response to Jehubuddaka
|
|
I know everybody suggested this to you, but it's pretty bad implementation. If you're going to have a couple of these mobs around, say 10 or so, they're going to be leaving /objs all over the place and it's just messy. Also I don't think your code is entirely correct either.
Just have the wolf (or w/e) detect animals in the vicinity by using the built-in range() proc to return a list of atoms in the wanted range. Then if there is a juicy rabbit in that list, make it the wolf's target and make it step towards it's general location (or just outright make the wolf automatically know exactly where it is, if you want. maybe you could make it different between monsters depending on their smelling ability). So you're going to end up with something like this for your AI: monster This is an example and isn't perfect, or necessarily even good. It is just here to generally show you how to do this stuff. Things you'll want to do is a more throughout PickTarget() and possibly Smell(), a complete AI() proc and more. It also contains things you didn't ask for because I thought them nice, and since this code isn't meant to be copied and used anyway (and it will not compile if you do). Also, you could try using the apple() proc instead of orange(). hahahaha, get it, get it? |
In response to Kaioken
|
|
The reason I really like the scent idea is that the wolf could get to its objective even if the path the other critter took is a path through a maze. Maybe I can make each mob have its own scent string like "meat" or "veggie", then whenever they step onto a turf, using entered, I can add that string to a list contained in the turf, and then the predator could search for things by looking for turfs withing 2 steps of it and pick a turf to move towards by the scent. My only problem with that is I think the scent should definitely fade. Is there a way to attach an age to a string in a list? and if so, is there a way to slowly decrement that age until it reaches zero, and then delete that string? It just seems more realistic to me for a hunter to look around, and if it sees nothing, to scent around and follow the food smell until it can see something.
|
In response to Nickr5
|
|
so you're saying that I should be doing something like
for(M in view(3,src)) yadda yadda yadda I really should have just read the DM reference. Once you said that, I looked it up and it explains it nicely. |
In response to Jehubuddaka
|
|
Jehubuddaka wrote:
The reason I really like the scent idea is that the wolf could get to its objective even if the path the other critter took is a path through a maze. You can just use a path-finding walk proc so the monster finds it's way to the 'victim'. My only problem with that is I think the scent should definitely fade. Is there a way to attach an age to a string in a list? Look up associative lists. You could use world.time and later check if it expired. I don't know if it's necessarily realistic though since animals generally seem to have a good enough smelling sense to smell stuff from away even if they haven't passed threw where the animal currently is. |
In response to Jehubuddaka
|
|
yup, always read the reference
|
In response to Kaioken
|
|
See, this is why I said to use an object with an auto decay. The object itself would be declared like this:
obj This creates a scent which decays every half second for 50 seconds. If you reduce the sleep() time, you create a faster decay, which means that the creatures can move faster and leave a more accurate scent trail, but you'd then need to increase the decaytimer else the scents will decay that much faster. Also, if you choose to make scent an object, then you can't use hearers. That's ok though, just make sure you make the scents have an invisibility, and the predators have a see_invisible of at least that value. That way, you won't run into any issues with scents not being, uh, smelled. Also, you can check the decay timer of a scent to know how old it is. Here's an example: mob The above example can be used in conjunction with your view(<insert range here>,src) call to check the age of each scent. You should also make a function to check the owner and the type of each scent (modularity) so that you can actually track individual mobs with them. |
In response to Perpetr8r the Perpetu8r
|
|
Perpetr8r the Perpetu8r wrote:
See, this is why I said to use an object with an auto decay. The object itself would be declared like this: There's no reason to use an /obj for this though, you don't need any atom for this. Also, you don't even want the scent to be visible or even quite tangible, so it shouldn't be on the map. You'd also get the scent object needlessly included in lists like range(), etc. If you really wanted this method you could just use a list of recent scents on the turf, that's all you need. This creates a scent which decays every half second for 50 seconds. Is there much point in this? No need for a loop, just wait X time until it needs to be gone then delete it. You can still measure the scent's age this way if you use a list but I don't see why you really need to. If a scent is still there, it can be smelled. If it can't be anymore, just get rid of it. |
In response to Kaioken
|
|
Kaioken wrote:
There's no reason to use an /obj for this though, you don't need any atom for this. Also, you don't even want the scent to be visible or even quite tangible, so it shouldn't be on the map. You'd also get the scent object needlessly included in lists like range(), etc. Eh well the reason I'd use an object is because we need to store more information about the scent than just its location. Unless he wants to code in a jillion annoying extra variables for each turf (or a list with a jillion annoying variables in it), he needs some kind of container for all his information; A bigger one, might I add, than a simple associative list. Objects quite simply make that job MUCH easier and also provide something for a coder to actually look at and debug with (just turn see_invisible to 1 or whatever), instead of a bunch of hidden variables where anything can go wrong and you'll be unable to tell what it is without outputting all of your saved variables. Kaioken wrote: Is there much point in this? No need for a loop, just wait X time until it needs to be gone then delete it. You can still measure the scent's age this way if you use a list but I don't see why you really need to. If a scent is still there, it can be smelled. If it can't be anymore, just get rid of it. The reason for the loop is because if, for example, we just called sleep(500), then we'd have no idea how long the scent would have been there originally, without storing extra data. Personally, I think that storing lists about every single variable associated with a scent is a lot more clunky than placing an object on the map. Besides, it makes it easier to override if say the prey crosses back over the same tile. You can have it reset the scent's decay timer without creating or destroying any scents in the process. Remember, a scent needs to have a specific source, a type, an age, and a location in order to be usable. I suppose if you did a 2D list with 4 elements per row you could store all of those pieces of info separately for each scent, but why do it the hard way when BYOND provides you with objs for free? Besides, if you use lists, you need to write your own code for reading them and storing info in them, as well as any calcuations that need to be done (for example checking how long the scent has been there, or making a decay timer for it). |
In response to Perpetr8r the Perpetu8r
|
|
Perpetr8r the Perpetu8r wrote:
Eh well the reason I'd use an object is because we need to store more information about the scent than just its location. Unless he wants to code in a jillion annoying extra variables for each turf (or a list with a jillion annoying variables in it), he needs some kind of container for all his information; A bigger one, might I add, than a simple associative list. What more would you need to store than the time the scent was created/left? Objects quite simply make that job MUCH easier Indeed, but you don't need to use atoms. And like I said in my opinion this doesn't require an object but everyone and whatever floats his boat. and also provide something for a coder to actually look at and debug with (just turn see_invisible to 1 or whatever), instead of a bunch of hidden variables where anything can go wrong and you'll be unable to tell what it is without outputting all of your saved variables. Well, thats not really a good reason. Normally you'd never need all that extra atom information and it's wasted. You can handle debug however you want afterwards you get the system working in whichever way you've chosen. The reason for the loop is because if, for example, we just called sleep(500), then we'd have no idea how long the scent would have been there originally, without storing extra data. I was thinking about storing the time the scent was "created" as the associated value, and that should be enough for this stuff you want, and is also more useful than just knowing the ticks since it was created. Personally, I think that storing lists about every single variable associated with a scent is a lot more clunky than placing an object on the map. Well, your way you're creating a new /obj object per any scent in a turf. If there were multiple creatures passing threw a single turf you could have multiple /objs inside there this way. My way you only create a single new /list per turf, and either way a /list is cleaner than an /obj, and /obj even contains lists itself. Besides, it makes it easier to override if say the prey crosses back over the same tile. You can have it reset the scent's decay timer without creating or destroying any scents in the process. I don't see any problem with doing this in a list either. I think it's actually possible that it's easier with a list, since all you'll need to do is src.scents[M] = world.time and not anything else. Remember, a scent needs to have a specific source, a type, an age, and a location in order to be usable. You're absolutely right and it should be added you're approaching designs well. Here's how I'll have all this data by using lists: sample list: // list(object_reference = time_scent_was_created) The source: the rabbit. The type: simply the rabbit's type (variable: R.type), and if you need any more specific type you could likely get it from this type(=type path). The age: The associated value holds the time the scent was created, so the age would be world.time - scents[R]. The location: well, this would be 'src' and not particularly difficult to get a hold of. I suppose if you did a 2D list with 4 elements per row So no, this is done with a simple associative list. why do it the hard way when BYOND provides you with objs for free? Well, the above way isn't too hard IMO. If one already knows how to use associative lists it'd be more or less the same as using an obj. Besides, if you use lists, you need to write your own code for reading them and storing info in them, ? I don't understand. You need to write code for everything. Getting the above information from a list is still easy like I explained above. Anyway, you can definitely use basic objects for implementations in DM without using atoms needlessly (sorry, but-duh!). They're called "datums", look them up, and also read this useful link. http://www.byond.com/members/ DreamMakers?command=view_post&post=35530 |
In response to Jehubuddaka
|
|
Another thing to consider is wind. If you implement wind, you could have the scent objects move to it.
But one thing about predators is they want to be downwind of their prey. Otherwise the wolf's prey would become alert when they sense wolf scent. Smart wolves want to move cross-wind until they pick up the freshest scent, then stalk upwind to the prey. And what erases scent besides time? How about rain? If you implement a weather system, you could have rain erase scent objects. An animal swimming across a stream shouldn't be easy to follow. Have them stop dropping scent when they are wet. Also when they are rained on, they would be wet and still wet for a while when the rain stops. Another thing to consider is animal sign. An animal marks territory with sign (musk/urine/pheromones/etc). A player might be able to collect sign and use it for various purposes. For example, in the movie "Sniper" the hero covered himself with manure so the bad guys couldn't find him with hounds. |