Page 1 of 3 123 LastLast
Results 1 to 10 of 23

Thread: selectBestPlaces (do-it-yourself documentation)

  1. #1

    Post selectBestPlaces (do-it-yourself documentation)

    So, there's this promising command selectBestPlaces, but once more the documentation is barely useable. The search here didn't yield a single hit either...

    But fortunately I've scanned config.cpp some time ago, which enabled me to get some idea what expression in this context could mean, so excuse the little digression:

    cost/probability expressions in config.cpp

    There is the subclass Ambient in config.cpp containing definitions of all the small animals, and an - tada - expression (named "cost" here) that defines, where and when these animals may apear (all guesswork of course, so don't take this for granted).

    The cost for these is a simple function (or expression) returning scalar based on simple arithmetic and some interesting keywords serving as variables of the sampled positions. The higher the output of this function, the more likely is it, that such an animal gets spawned at the sampling position. (plus there are again subclasses of these, where the cost is usually set to 1, while we have another expression for "probability" where `more exclusive?` keywords are beeing used...)

    The keywords used in config.cpp are:
    • forest
    • trees
    • meadow
    • hills
    • houses
    • sea
    • night
    • rain
    • windy
    • deadBody


    Each of theses variable in an expression will be replaced by the actual sampling value at the sample position of this factor, ranging from 0 to 1, where 0 means not at all and 1 means totally! (which allows for easy arithmetic combination of multiple factors)

    Thus we can mix factors from three major different dimensions: the geographic dimension, time and the weather. (plus the deadBody thing, which looks like a "bonus" dimension implemented especially for the flies)

    Some short examples:
    • deep forest: "(1 + forest + trees) * (1 - sea) * (1 - houses)"
    • tree, but not in forest: "(1 - forest) * (1 + trees)"
    • hill, no forest: "(1 - forest) * (1 + hills) * (1 - sea)"
    • house on hill: "(1 + houses) * (1 + hills)"
    • ...


    This is how leaves get spawned where trees are near, while the game spawns rocks where hills are located (clutter particles). And this is how the HouseFly finds deadBody, DragonFlys the forest and ButterFly the meadow, while the birds disapear in the night or in the rain.

    Some examples, taken from config.cpp:
    Code:
             class BigBirds {
                radius = 300;
                cost = "((1 + forest + trees) - ((2 * rain)) - houses) * (1 - night) * (1 - sea)";
    
                class Species {
    
                   class Hawk {
                      probability = 0.200000;
                      cost = 1;
                   };
                };
             };
    
             class BigInsects {
                radius = 20;
                cost = "(5 - (2 * houses)) * (1 - night) * (1 - rain) * (1 - sea) * (1 - windy)";
    
                class Species {
    
                   class DragonFly {
                      probability = "0.6 - (meadow * 0.5) + (forest * 0.4)";
                      cost = 1;
                   };
    
                   class ButterFly {
                      probability = "0.4 + (meadow * 0.5) - (forest * 0.4)";
                      cost = 1;
                   };
                };
             };
    
             class SmallInsects {
                radius = 3;
                cost = "(12 - 8 * hills) * (1 - night) * (1 - rain) * (1 - sea) * (1 - windy)";
    
                class Species {
    
                   class HouseFly {
                      probability = "deadBody + (1 - deadBody) * (0.5 - forest * 0.1 - meadow * 0.2)";
                      cost = 1;
                   };
    
                   class HoneyBee {
                      probability = "(1 - deadBody) * (0.5 - forest * 0.1 + meadow * 0.2)";
                      cost = 1;
                   };
    
                   class Mosquito {
                      probability = "(1 - deadBody) * (0.2 * forest)";
                      cost = 1;
                   };
                };
             };
    
             class WindClutter {
                radius = 10;
                cost = "((20 - 5 * rain) * (3 * (windy factor [0.2, 0.5]))) * (1 - sea)";
    
                class Species {
    
                   class FxWindGrass1 {
                      probability = "0.4 - 0.2 * hills - 0.2 * trees";
                      cost = 1;
                   };
    
                   class FxWindGrass2 {
                      probability = "0.4 - 0.2 * hills - 0.2 * trees";
                      cost = 1;
                   };
    
                   class FxWindRock1 {
                      probability = "0.4 * hills";
                      cost = 1;
                   };
    
                   class FxCrWindLeaf1 {
                      probability = "0.2 * trees";
                      cost = 1;
                   };
    
                   class FxCrWindLeaf2 {
                      probability = "0.1 * trees + 0.2";
                      cost = 1;
                   };
    
                   class FxCrWindLeaf3 {
                      probability = "0.1 * trees";
                      cost = 1;
                   };
                };
             };
    ...you get the idea. And as it turns out, these config entries (cost/probability) will be feed to exactly this selectBestPlaces command.


    selectBestPlaces

    Thus, I may (with some surety, based on my experiments) complete the documentation for this command:
    Code:
    selectBestPlaces [_position,_radius,_expression,_precision,_sourcesCount]
    Parameters:
    • _position: sample position (2d position seems to be sufficient, so no ASL position needed)
    • _radius: defines the area to find the positions in (scalar in meter)
    • _expression: cost function (string, not code!), calculated for every sampling position returning a positive number. The higher (positive) the value, the better. Zero means that the expression does not apply. The expression can rely on any of the variables in: [forest, trees, meadow, hills, houses, sea, night, rain, windy, deadBody], maybe more.
    • _precision: sample precision/ radius of the sample position (scalar, maybe in meter, but for sure this is no 0 to 1 range). Given a precision of zero, your game will probably halt for some time, most likely for ever for you basically try to divide by zero. I guess we divide the area by this sampling area the precision/radius defines. With a very low value, you may get a lot of "bestPlaces" very near to each other - the precision as min. probably. With a greater value the returned positions are much further apart from each other, though it looks like the min. distance isn't exactly the given precision interpreted as radius... But you get the idea.
    • _sourcesCount: number of best places returned (integer)


    Returns:
    No, you won't get an array of positions. You will get an empty array in case no best places were found (I guess this is true, when all "costs" where exactly zero) OR an array of "bestPlaces", where "bestPlaces" is an array of:
    • _this select 0: position
    • _this select 1: cost (expression result at this position)


    Now be carefull with the sampling radius and precision because selectBestPlaces gets computed in one go and doesn't suffer from any maximum runtime-cap each frame. Thus if you're precision is too small for a too large sampling area, you may freeze the game for several seconds! (too many samples taken, plus all these samples need to be sorted too, to return the "best" ones, of course..)

    Oh, after a first unsuccessfull regex search for an official example, I actually do have found just some, all from the animal module (of course, DO!), in Animals_main.fsm:
    Code:
       _root = configFile >> "CfgVehicles" >> "Goat";
       _favouritezones = getText ( _root >> "favouritezones");
     
       _randrefpoint =  [(getpos player select 0) +Random(2*_SpawnRadius) -_SpawnRadius,(getpos player select 1) +Random(2*_SpawnRadius) -_SpawnRadius];
       _PosList = selectbestplaces [_randrefpoint,_FindPlaceRadius,_favouritezones,10,5];
       _PosSelect = _PosList select (floor random (count _PosList));
       _Pos =  _PosSelect select 0;
    So there you go. Happy selecting best places. I imagine this is an elegant way to solve similar problems of finding appropriate places randomly.

    And in case some developer pops in, I'd like to know if I've mention all of the available sampling-variables? What's really the meaning of precision? Or anything else, that I got wrong... so once we have the facts straight, we may complete the wiki about it..

  2. #2
    If i understand this right we can use this command to up the count of insects in forest and birds and the like? And spawn flies around dead enemies?

    Sorry for being so noobish, but as far as i read(the whole thing!) it, im not quite sure i understood it. But by all means, it was well presented! =)

  3. #3
    Master Sergeant ruebe's Avatar
    Join Date
    May 15 2006
    Location
    Switzerland
    Posts
    701
    Author of the Thread
    Quote Originally Posted by Jelliz View Post
    But by all means, it was well presented! =)
    Well, obviously not, hehe. (I'm sorry, I usually fail at keeping things short and spot on..)

    To answer your question: well, sure you could (and this is how the animal module decides where each kind gets spawned exactly), but all this command does is returning positions with the highest value of the given expression. What you do with those positions (e.g. spawn appropriate animals there) is completely up to you, and therefore this command may be valuable for completely other task than spawning animals.

    Just remeber this command, next time you need to find one or multiple positions that are guaranteed to be characterised by your expression.

  4. #4
    Aaaah man i got it Thanks

  5. #5
    this is nice! I've been looking for something to help me spawn tanks in a random area without having them spawn in dumb places like dense forest or on a building. NICE!

  6. #6

    Another sample

    So I've been playing around with this because I wanted to be able to spawn tanks/armor in random areas, but they would sometimes spawn in dumb places like in the middle of forests. I wanted them only to spawn in meadow/planes so this is how I got it to work. I just made a quick sample mission with a single marker in the editor named "marker" and then put this into init.sqf and it spawns a new USMC guy in a meadow every time:

    Code:
    _pos = getmarkerpos "marker";
    _radius = 500;
    _exp = "(1 + meadow) * (1 - forest) * (1 - trees)";
    _prec = 10;
    
    _bestplace = selectBestPlaces [_pos,_radius,_exp,_prec,1];
    _spot = _bestplace select 0;
    _spot2 = _spot select 0;
    
    
    "USMC_Soldier_MG" createUnit [_spot2, group player, "newguy = this", 0.5, "corporal"];
    sleep 2;
    selectPlayer newguy;
    I figured out the hard way that selectBestPlaces was returning a multi-dimensional array, which is why I needed this bit:

    _spot = _bestplace select 0;
    _spot2 = _spot select 0;

    in order to end up with the coordinate value that I needed.
    Last edited by node_runner; Apr 18 2010 at 03:14.

  7. #7
    First Lieutenant Kremator's Avatar
    Join Date
    Jun 8 2007
    Location
    Cambridge, UK
    Posts
    5,076
    Hmmmm could this then be combined with helo landings so that they ONLY landing in proper clearings and NOT on top of trees ?

  8. #8
    Nice find Ruebe, and well doco'd will be handy for when I am trying to randomly hide ammo caches in forests rather than in the middle of an open field!

    As a side note to some of the previous posts, I use isflatEmpty a lot to find suitable placement locations. It checks for things like not on water or visa versa, slope angle isn't to great and that the object will fit between existing objects at the location. Great for placing HQ's(tanks LZ's) that aren't impailed in trees and hanging off cliffs!

    http://community.bistudio.com/wiki/isFlatEmpty
    Last edited by blakeace; Apr 18 2010 at 07:59.

  9. #9
    I'm looking for interesting ways to pick random spots, so this is very much appreciated!
    Last edited by Wokstation; Apr 18 2010 at 11:05.

  10. #10
    Excellent work ruebe. Thank you for taking the time to document and show this. I can think of interesting ways to make the AI find cover with this command.

    -AI could search for a treeline for cover.

    -Snipers could search for hills with no trees for overwatch.

    -Medics set up MASH behind building areas for better cover while they heal.

    Again, great work and contribution to this board.

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •