Object.GetNearbyObjects() returns objects in a radius

Discussion about Mods for Prison Architect

Moderator: NBJeff

murgh
level2
level2
Posts: 232
Joined: Sat Jan 30, 2016 11:52 am

Re: Object.GetNearbyObjects() returns objects in a radius

Postby murgh » Tue Aug 23, 2016 2:49 pm

[completely off-topic]Perhaps you have any idea how to get colours to work in the tooltips? Try some lua examples on the net, won't work. But maybe I've tried it for the wrong lua version, didn't think of that... Or it has to be enabled by the devs in the code before we can reach it via mods.[/completely off-topic]
User avatar
Medu_Salem
level1
level1
Posts: 46
Joined: Fri May 16, 2014 6:42 pm

Re: Object.GetNearbyObjects() returns objects in a radius

Postby Medu_Salem » Tue Aug 23, 2016 6:15 pm

No, I don't have any clue about it... I asked myself about formating code already... like Size, Bold/Italic etc, but I would say that Lua manuals won't help here since it probably depends on how the game actually treats the Tooltips internally for display.

We at least know that some escape codes like "\n" work but that's all I know.
murgh
level2
level2
Posts: 232
Joined: Sat Jan 30, 2016 11:52 am

Re: Object.GetNearbyObjects() returns objects in a radius

Postby murgh » Tue Aug 23, 2016 9:46 pm

Medu_Salem wrote:Looks neat ^^

Is the "If" branch empty?

Because if so then you could restructure/invert the Condition in a way that the if branch is taken only if the sprinkler is out of bound, and skip the else part.

Something like so:

Code: Select all

function GetObjectsInSquare(theObject,theRange)
   if this.Or.x==-1 then print('-- rotated once')
      Xmin=math.floor(this.Pos.x-theRange)
      Xmax=this.Pos.x
      Ymin=math.ceil(this.Pos.y-theRange/2)
      Ymax=math.floor(this.Pos.y+theRange/2)
   elseif this.Or.y==-1 then print('-- rotated twice')
      Xmin=math.floor(this.Pos.x-theRange/2)
      Xmax=math.ceil(this.Pos.x+theRange/2)
      Ymin=math.ceil(this.Pos.y-theRange)
      Ymax=this.Pos.y
   elseif this.Or.x==1 then print('-- rotated three times')
      Xmin=this.Pos.x
      Xmax=math.ceil(this.Pos.x+theRange)
      Ymin=math.ceil(this.Pos.y-theRange/2)
      Ymax=math.floor(this.Pos.y+theRange/2)
   else print('--placed down')
      Xmin=math.floor(this.Pos.x-theRange/2)
      Xmax=math.ceil(this.Pos.x+theRange/2)
      Ymin=this.Pos.y
      Ymax=math.floor(this.Pos.y+theRange)
   end
   local ListOfObjects = this.GetNearbyObjects(theObject,theRange*1.2)
   for thatObject, distance in pairs(ListOfObjects) do
      if thatObject.Pos.x<Xmin or thatObject.Pos.x>Xmax or thatObject.Pos.y<Ymin or thatObject.Pos.y>Ymax then
         ListOfObjects[thatObject]=nil
      end
   end
   return ListOfObjects
end   


If one of the partial conditions returns true then it is out of bounds and due to the Or's the entire thing becomes true and the branch is taken and the sprinkler is removed from the list.

Else the sprinkler is inside and hence left in the list... but that can be skipped since you are not doing anything special in that case.

It's not really a mandatory improvement... but I somehow try to avoid the notation of empty branches (except maybe for debugging reasons). :D


No, it's better with the empty if branch since there are more sprinklers inside the square than being abandoned. So the way the if structure works now would be faster in theory. But thinking of it I'm not sure any more hehehhe. I don't mind. For universal usage it's good, never know what can be inside when used a bit differently in another mod :D
murgh
level2
level2
Posts: 232
Joined: Sat Jan 30, 2016 11:52 am

Re: Object.GetNearbyObjects() returns objects in a radius

Postby murgh » Tue Aug 23, 2016 10:02 pm

BTW this new scanning method works perfectly man. I set it to increase the range in odd numbers, so you can always draw the proper square: scan range 17 tiles? Draw a line 8 tiles to the left from the alarm, then 8 tiles to the right, and draw the square. There's your foolproof scanned square area!
User avatar
Medu_Salem
level1
level1
Posts: 46
Joined: Fri May 16, 2014 6:42 pm

Re: Object.GetNearbyObjects() returns objects in a radius

Postby Medu_Salem » Wed Aug 24, 2016 12:32 pm

murgh wrote:No, it's better with the empty if branch since there are more sprinklers inside the square than being abandoned. So the way the if structure works now would be faster in theory. But thinking of it I'm not sure any more hehehhe. I don't mind. For universal usage it's good, never know what can be inside when used a bit differently in another mod :D


It really depends on how the Lua runtime interprets if statements and converts them to machine instructions, which honestly I have no clue about. As it is a script language I don't even know if the Lua runtime converts the code of the branch which is not taken. Though it should prepare even the skipped branch as machine code for speed reasons because it may be too late/slow to convert just-in-time... at the point the outcome is determined there should already be the machine code for the next instruction ready to be issued or otherwise you cause unnecessary stalls in the processor pipeline due to interpreter overhead.

But if I remember right from my studying years then in the machine code resulting from regular compilers the next instruction following a jump-on-condition instruction is actually the else-branch in case the condition is not met. It only jumps to the if-branch if the condition actually was met (otherwise you'd have to invert the conditional outcome in some weird way). So basically the branches in machine code appear in reverse order than they were written while programming in higher languages. I may be wrong about it because last time I had such a hypothetical discussion was about 15 years ago.

At least it would mean that if you use an empty if-branch you force the processor to unnecessarily jump twice... once after the condition is met and the jump-to instruction is actually happening, and the second time after realizing that the if-branch is empty for jumping back to the beginning of the for-loop to continue with the next item of the iteration.

And it would mean that in my code example after it is sure the if-branch doesn't happen the processor would basically continue with the next instruction following after the jump instruction (which didn't happen) which then is the else-branch. And then it would only jump once to return to the beginning of the for-loop because there's nothing happening in the else-branch.

So basically in my variant it would only jump twice if the if-condition was actually true (which happens more seldom in your case), otherwise only once (which happens more often in your case), which would then be faster than your approach because you are doing it basically the other way around... Jumping twice more often, jumping once more seldom.

Though it cannot said per se that a jump is slow... especially if the jump target has a fixed offset the branch predictors should already have the target in the cache long before the outcome is really determined and start caching instructions for both branches.



But that's highly hypothetic stuff which is more important in instruction-set development and compiler development, which highly depend on:

  • Does one expect a branch to be taken more often or more seldom?
  • ... and if they are taken more often then do we place the if-branch in the memory directly after the jump-instruction and actually jump to the else part if the condition was not met
  • ... or do we expect them not to be taken and place the else-branch in memory before the if-branch and jump to the if-branch if the condition was met (which is what I believe is the way x86 machines are doing it, judging from the jump instructions)

Some instruction-sets even have such features... where the programmer can help the processor's branchpredictor with flags one can set for each case like "most likely taken" or "most likely not taken".

Which is where I don't really think that it would matter much for our little modding excursion due to how fast modern processors are and they are all using very advanced branch predictors, op caches and other stuff.
murgh
level2
level2
Posts: 232
Joined: Sat Jan 30, 2016 11:52 am

Re: Object.GetNearbyObjects() returns objects in a radius

Postby murgh » Wed Aug 24, 2016 2:00 pm

Medu_Salem wrote:Which is where I don't really think that it would matter much for our little modding excursion due to how fast modern processors are and they are all using very advanced branch predictors, op caches and other stuff.


^^this.
Since the cpu has become so fast nowadays it really doesn't matter for such small things as our mods. Perhaps in a big data warehouse they would have sleepless nights about things like this, but we shouldn't :D

Although just for fun sake it would be nice to do a little test with a timer in DebugOut() to show how much game time various implementations would take. Probably all methods would have negligible results when compared to each other. We simply don't produce enough data to keep the cpu busy for minutes or hours in a row sorting things out with our little scripts.
User avatar
Medu_Salem
level1
level1
Posts: 46
Joined: Fri May 16, 2014 6:42 pm

Re: Object.GetNearbyObjects() returns objects in a radius

Postby Medu_Salem » Thu Aug 25, 2016 9:55 pm

murgh wrote:Since the cpu has become so fast nowadays it really doesn't matter for such small things as our mods. Perhaps in a big data warehouse they would have sleepless nights about things like this, but we shouldn't :D.


Well I'd say microcontroller programming is where it would be the most important to squeeze out every bit of performance since they are pretty limited performance-wise. Some of the applications microcontrollers are used in absolutely have no margin for wasting any time/resources. It literally would mean the difference between life and death. But yeah I'm glad I don't have to think about that. :)

murgh wrote:Although just for fun sake it would be nice to do a little test with a timer in DebugOut() to show how much game time various implementations would take. Probably all methods would have negligible results when compared to each other. We simply don't produce enough data to keep the cpu busy for minutes or hours in a row sorting things out with our little scripts.


I always do that. I implemented my own "DebugOutput()" function, that basically timestamps every output using Game.Time()... and I have some timestamp variables going that calculate the time passed/difference between the last time my DebugOutput() function was called and the current call... and also a global variable how much time passed since the "Update()" function was called to gain some insight on how long it took for the entire Update to finish.

Using that feature I basically have a DebugOutput at the beginning of each function and at the end of each function... so I have a very detailed insight on how long each of my functions took.

Let's just say that you wouldn't even be able to measure a difference between before starting the for-loop and after finishing the for-loop, meaning the entire loop would be unrolled without the timer going up at all, let alone measure the difference between the if/else branch stuff we discussed above within a single loop iteration.

That said... if you are performing a lot of complex actions on a lot of objects then you'll measure the impact of a loop. For example in one of my scripts I'm iterating through the entire prisoner list to count all prisoners per security level... in a 700+ prisoner test prison that thing is producing a small difference of about 0.015 seconds between before and after the for-loop, barely less than 1 frame if you are running at 60fps.

By the way... getting all the prisoners in the entire map using GetNearbyObjects takes for 700+ prisoners about 0.35-0.5 seconds (it always seems to vary some bit). So that's actually noticable by a human being because it causes a serious hitch
murgh
level2
level2
Posts: 232
Joined: Sat Jan 30, 2016 11:52 am

Re: Object.GetNearbyObjects() returns objects in a radius

Postby murgh » Fri Aug 26, 2016 8:29 am

Well now you can also play around with the dev tools :mrgreen:
User avatar
Medu_Salem
level1
level1
Posts: 46
Joined: Fri May 16, 2014 6:42 pm

Re: Object.GetNearbyObjects() returns objects in a radius

Postby Medu_Salem » Fri Aug 26, 2016 6:06 pm

murgh wrote:Well now you can also play around with the dev tools :mrgreen:


Yeah, but I probably won't because the new update basically f'd up all of my prisons somehow and that's what has been bumming me out for the last 2-3 hours already, which is why I will leave the game be for a while because if I'm mad nothing good comes out of it and I don't want to wreck my computer just because I'm mad about a game.

The issue is completely unrelated to modding though:

In almost every prison I load with the new update it doesn't take long for the prisoners to start a prison-wide riot and I can't exactly tell why since the game as always tells you jack sh*t about why certain things happen, but I suspect it's the damn Gang Leaders causing the gangs to freak out whenever they receive punishment, especially the Extremely Volatile Gang Leaders. Probably due to the Gang having chosen new Gang Leaders since that has been bugged out in U7 so I didn't receive any new ones. And for some reason they all chose to have the Legendary Extremely Volatile Gang Members as their new leaders.

It's that kind of things that are really impossible to deal with in this game... how is one to deal with an Extremely Volatile Gang Leader... they freak out whenever they feel like it, which you can nothing do about because that's happening on a timer even if all of their needs are satisfied, and when they receive punishment (which is beyond my control either) then at least 50 gang members will jump at the throats of everyone, Guards, Staff, other Gangs and Prisoners (which don't even need to be in the same block because the instigator trait seems to be like an AoE projecting through walls) and then the other instigators of other security levels will jump in as well and voila prison wide riot with 20+ deaths at least and you can't do anything about it.

The combination of Legendary Extremely Volatile and Gang Member leading to Gang Leaders with Extremely Volatile rep should be banished from the game because there's literally no game mechanic in the game that can counteract the effect, meaning if they go on a rampage then you can't avoid riots and multiple deaths at all. With that in mind you can never activate failure conditions because you'll get sacked for things that are way beyond your control.

It's either that or the gangs shouldn't go all haywire just because the gang leader is receiving temporary punishment. They should only get angry if you put the leader on permanent punishment.

Whatever... I'm just mad that there is no practical solution to this. The game is throwing a challenge at you that can't be mastered. That's like if Super Mario Bros would have a gap that is too wide to be jumped over by Mario but it would be the only meaningful way to proceed in the level, the alternative being stuck in a place with infinitely respawning hammer brothers for all eternity until you give up because you can't win anyways. It would be cruel to do that but that's what Prison Architect does with Extremely Volatile Gang Leaders.

I don't even feel like going to Mantis and report the issue because I already know what the response to that is going to be like... "That's the challenge, just get better at the game" ... as if I wouldn't have at least 1000 hours of knowledge about the game already to realize that there is currently no solution to the problem.

Return to “Modding”

Who is online

Users browsing this forum: No registered users and 2 guests