Iāve looked into this a little bit, but some of the math is a little funky, so Iām not sure itās really working as intended.
Probably the simplest thing to do is set some threshold before the loop based on how good the monster is at smelling, and do:
smell = g->scent(blabla);
if( smell < threshold ) continue;
Scent is currently a cloud that disperses very rapidly unless itās refreshed constantly.
game::update_scent() is responsible for updating the scent cloud, which is maintained in game::grscent[][], a 2D array of scent intensity, this should probably live in the map, not the game structure for one thing.
what it does is fairly simple, first it sets the square the player is on equal to the playerās scent, then for each tile within an 18-square radius* it calculates a pseudo-average** of each squareās adjacent*** scent values, then overwrites the old scent map with the new one.
Thereās a proposal to make the playerās scent āstickā to the area where the player has been more strongly, and make it spread less, so it acts more like a trail than a cloud.
*18 looks like a legacy value since the active area is 120 squares across. Additionally it looks like itās going to leave phantom scent values in some cases if there is any scent left once the player is more than 18 squares away because it stops updating the values then, but theyāre still used for monster navigation.
**This pseudo-average is kind of weird, it only counts squares that are stronger or as strong as the current square, but then adds one to the average, which means isolated pockets of scent die off VERY fast.
***Since it equally weights surrounding squares, the cloud would expand in a square as long as the player doesnāt move, but due to the weird averaging thing, the corners of the square will decay faster than the sides (since there arenāt as many adjacent equal-or-higher-strength squares)
BTW, hereās how the algorithm progresses if you cut the max value to 0xF and donāt move:
0000000 0000000 0000000 0000000
0000000 0000000 0000000 0000000
0000000 0011100 0032300 0064600
000F000 001F100 002F200 004F400
0000000 0011100 0032300 0064600
0000000 0000000 0000000 0000000
0000000 0000000 0000000 0000000
0000000 0000000 0000000 0000000
0011100 0023200 0044400 0045400
0175710 0276720 0476740 0476740
015F510 036F630 046F640 056F650
0175710 0266720 0466740 0476740
0011100 0023200 0044400 0045400
0000000 0000000 0000000 0000000
It progresses from left-to-right then top-down. As you can see, it spreads pretty fast (this would only take a minute in game, and would spread even faster if the max value was the default (600) instead of 0xF). I was really wasting my time with this, because with values this small the algorithm gets dominated by rounding errors. For example, it spreads to 0 tiles very slowly because every adjacent tile gets averaged in, which means the adjacent values have to add up to 10 before a 0 transitions to a 1. This isnāt an issue with large values, because that threshold of 10 is more easily met since the values start in the hundreds. You can see several features of the algorithm though, one is that each concentric circle is roughly half the next circle in, and at some point the whole thing reaches stasis because the averaging is so aggressive. As long as the player doesnāt move, that last scentmap will stay stable indefinitely. This points out another feature, which is that an area never develops āmemoryā of the playerās presence, the scentmap will roughly stabilize within 10 mins or so, after which itās just a static feature. Another feature this doesnāt highlight is that walls block scent, or more properly they can never have scent. [size=12pt]Something that surprised me is that windows and doors donāt block scent at all, just walls, which means weāve been giving people bad advice about avoiding being sniffed out by zombies :P[/size] I think Iāll want to do something about this in the short term while Iām still mulling over what to do about the system as a whole, because closed doors and windows should definitely attenuate scent more than that.