Not logged inOpenClonk Forum
Up Topic Development / Developer's Corner / Request For Comments: FindLocation
- - By Zapper [de] Date 2013-01-12 22:39
I have created a helper-function FindLocation to find a random location with some parameters.
The function randomly selects a spot in the landscape and then checks the conditions. Repeat until found or max. times exceeded.

The function parameters are provided similarly to the FindObject parameters.

FindLocation is relatively slow and should ideally only be used to create environmental objects etc. at scenario start.

example from the large cave mushroom:
var spot = FindLocation([Loc_Tunnel(), Loc_Wall(CNAT_Bottom), Loc_Space(20, true), Loc_Condition(LargeCaveMushroom.GoodSpot)]);
// can't place more
if (!spot) return plants;


Comments? Since I hope that the function will be used a lot to place stuff, it should be as usable as possible. And that can still be changed easily right now.
(Especially about the syntax / usage of the function)
Parent - - By Newton [de] Date 2013-01-13 01:31
Does the function always return the same spot with the same parameters? Do you intend to have something like FindLocations(num, conditions,...)?
Why do you encased all the parameters in an array? In my opinion, the syntax should be similar to FindObject except there is a good reason not to.
Parent - - By Zapper [de] Date 2013-01-13 09:05
It does not always return the same spot with the same parameter due to its random nature (what is "num" supposed to do?).

The array was because there is no Par() equivalent(?) I admit I didn't check, though
Parent - By Newton [de] Date 2013-01-13 13:48
But Par() is still there, isn't it? At least FindObject still works...

num would be the number of spots to return. But if FindLocation always returns another location its fine as well.
Parent - - By Newton [de] Date 2013-01-13 13:53
+ LocInMaterial("Tunnel") / Gold,Lava etc.
+ LocInFluid/LocInSolid?
Parent - By Zapper [de] Date 2013-01-13 14:20
Loc_Solid exists. I'll put in InFluid and InMaterial.
Parent - By Dragonclonk [de] Date 2013-01-14 07:44

> LocInMaterial("Tunnel")


LocInMaterial("Earth", "earth_dry") respectively texture would also be useful to place objects in special earth layers or different lakes (but with exceptions where no fishes can exist).
Reply
Parent - - By Dragonclonk [de] Date 2013-01-13 15:02 Edited 2013-01-13 15:07
Very useful, but got sometimes returned nil instead of coordinates (same map with small tunnel areas).

->FindLocation([Loc_Tunnel(), Loc_Wall(CNAT_Bottom), Loc_Space(20, true)])
= nil


[edit]
Of course after nil the engine still returns valid coordinates.
Reply
Parent - - By Zapper [de] Date 2013-01-13 17:10
Yes, especially when what you are looking for is not common on your map, FindLocation might return nil. It only does about 5000 tries with random points. I could add a flag to increase that limit
Parent - - By Maikel Date 2013-01-13 17:34
Very nice initiative :)

Did you also already look at occurrences of old code which can be replaced by this method?
Regarding the search algorithm, maybe one can design something smarter than just generating a random point? Not that anything comes to my mind immediately!
Parent - - By Zapper [de] Date 2013-01-13 18:07
No, I did not look through old code yet. But I guess some of the vegetation stuff can be replaced

Regarding the algorithm: I thought about remembering the points, but discarded that. It might help to take points from a randomized raster instead of pure random points, not sure
Parent - By Gurkenglas [de] Date 2013-01-14 22:37 Edited 2013-01-14 22:56
Could one tell the engine in advance that the Script will need one/100 points of these criteria at some point, and that it should note it down when it creates some?
For example, walls should be quite easy to find if you tell the engine that while generating the landscape, it should make a note when switching from "Here be Firefluid" to drawing Tunnel.
Reply
Parent - By Newton [de] Date 2013-01-13 19:31

> Did you also already look at occurrences of old code which can be replaced by this method?


I stumbled on some today but in the engine (spawning the player's crew on start of the scenario). Would perhaps speak to move the implementation to the engine so that the occurances in the engine could also be replaced. Just an idea though.
Parent - - By Dragonclonk [de] Date 2013-01-13 17:36
I don't know how this function works but does it help if a more specific rectangle is defined if the approximate coordinates are known?
Reply
Parent - By Zapper [de] Date 2013-01-13 18:03
Yes, the 5000 random points are all taken from within the rectangle. Your chance to find the right spot should increase that way
Parent - - By Caesar [de] Date 2013-01-13 18:50
Neat, could you add something like Loc_Effort(n) to control how many random points are tried?
Parent - By Zapper [de] Date 2013-01-13 19:29
Yes
- - By Zapper [de] Date 2013-01-14 10:43
38bdfd296dd67b51892a469075a99164b964d0a9
added:
- Loc_Sky
- Loc_Liquid
- Loc_And
- Loc_Or
- Loc_Material(string material, string texture) // texture optional
- Loc_MaxTries(int maximum_number_of_random_points_to_try)

renamed Loc_Condition to Loc_Func (to be more similar to Find_Func)

FindLocation now uses unnamed parameters (Par(i)) instead of an array. Limits parameters to 10 (or 9?), use Loc_And when you have more.
Parent - - By PeterW [gb] Date 2013-01-14 13:59

> // this part just moves the random point to left/right/up/down until a wall is hit


Hm, this gives you a bias towards walls that have a lot of material next to it... Not an easy problem to solve, just pointing it out.

The whole thing would be a pretty good example for what function pointers could be good for. Another optimization idea could be to put each type of condition into a different object definition, then pass those around as quasi function pointers. Not sure this would actually do more than pushing the loop into the engine though.
Parent - - By Zapper [de] Date 2013-01-14 14:16

>Hm, this gives you a bias towards walls that have a lot of material next to it... Not an easy problem to solve, just pointing it out.


Sure? I think it gives me a bias towards walls that have a lot of free space next to them (the search always starts in free space)

Function pointers would help if I could set parameters beforehand (see Haskell etc) and create a new function that only needs the remaining parameters
Parent - - By PeterW [gb] Date 2013-01-14 16:13

> Function pointers would help if I could set parameters beforehand


That would help even more - but even just passing the parameter array to the right portion of code right away would save you some repeated ifs. A small optimization admittedly :)
Parent - By Zapper [de] Date 2013-01-14 16:48
Oh, because I don't have to check for the false ones. Ok, I get what you mean now
Parent - - By Sven2 [de] Date 2013-01-14 16:54

> The whole thing would be a pretty good example for what function pointers could be good for.


What do you mean by "could"? We have function pointers, don't we?
Parent - - By PeterW [gb] Date 2013-01-14 17:29
Ah, foiled again. Why aren't you using function pointers, Zapper? :)
Parent - - By Zapper [de] Date 2013-01-14 17:35
I am using them in Loc_Func ;P

The only thing I could save would be the if-checks for flags that are not fitting, right?

PS: I would have to put all those functions into global scope, I guess :/
Parent - - By PeterW [gb] Date 2013-01-14 17:56
Well, the idea would be to replace LOC_FUNC & co with function pointers, so your loop just has to call the function in the first array element passing it the array itself for the parameters. On the other hand - can we check function pointers for equality?
Parent - - By Zapper [de] Date 2013-01-14 18:08
I wouldn't need to check them for equality.

I guess that would save some failing ifs, yes. But I don't want to put my helper functions into global scope, Guenther?
Parent - - By Sven2 [de] Date 2013-01-14 19:11
You don't have to. You can have a definition like e.g. LocationFinder and have your Loc_And and friends be regular functions of that definition. All functions of a definition can be accessed as properties (var myptr = LocationFinder.Loc_And;).
Parent - By Zapper [de] Date 2013-01-14 19:25
Yes, that would need a definition, though.
Up Topic Development / Developer's Corner / Request For Comments: FindLocation

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill