Page 1 of 2

Bug Fix: Fully working entitiesAt and allEntities functions.

Posted: Mon Aug 26, 2013 12:57 am
by JohnWordsworth
As I'm sure most of you are aware, the entitiesAt() and allEntities() iterators in Grimrock 1.3.7 are broken if the user decides to use Map Markers. After a little bit of toying with these functions today, I had a bit of an idea and have come up with a fix! Huzzah. See the attached video of the new iterators I have written in working order.

The video shows the results of the new methods compared to the old ones with Map Markers: https://docs.google.com/file/d/0B2rfBgD ... NwRllvZFE/

To use the new methods, you simply need to pop the following code into your dungeon in a script_entity called 'fix' (or whatever you like really). Then you need to change all of your calls to entitiesAt or allEntities to; fix.newEntitiesAt(level, x, y) and fix.newAllEntities(level). Feel free to rename the methods if you prefer, but you cannot use the name allEntities and entitiesAt in a script_entity or you get a stack overflow (hence me giving it the longer name).

Code: Select all

-- Script: entitesAt and allEntities Fix
-- Version: 0.9.1
-- Date: 25th August 2013
-- Author: John Wordsworth
--
-- Thanks to Diarmuid for the optimised version of the newAllEntities method. I didn't
-- realise that it was so slow until you did a performance check on it!
--
-- Provides a fix for the bug in Legend of Grimrock 1.3.7 where the entitiesAt()
-- and allEntities() methods will simply stop returning objects in a for loop if 
-- they hit a 'Map Marker' entity in the level. This means that if the user has 
-- placed a Map Marker on the level, allEntities will almost definitely fail, where
-- as entitiesAt will fail if the marker is on the same space.
--
-- Usage: Drop this into a script_entity called 'fix' in your dungeon.
-- From then onwards, call 
--   fix.newEntitiesAt(level,x,y)
-- and 
--   fix.newAllEntities(level)
-- instead of the standard methods in your code.
--


--
-- This entitiesAt method fixes the bug. The built-in iterator returns nil when it hits a map
-- marker, but the iterator itself still exists and is able to continue. So we simply keep
-- the underlying iterator object around and try to iterate over it twice if we hit a nil object.
-- This works on the assumption that you can only ever have one map marker in a space (so we only
-- have to skip 1 nil entry).
--

function newEntitiesAt(level, x, y)
	local it = entitiesAt(level, x, y);
	
	return function()
		local e = it();
		
		if ( e == nil ) then
			e = it();
		end
		
		if ( e ) then
			return e;
		end
	end
end


--
-- This iterator simply uses the fixed newEntitiesAt iterator
-- over and over to return entities in spaces.
--

function newAllEntities(level)
	local it = allEntities(level);
	local c = 0;
   
	return function()
		local e = it();
    
		while ( e == nil and c < 100) do
			e = it();
			c = c + 1
		end
      
		if ( e ) then
			return e;
		end
	end
end
Enjoy!

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Mon Aug 26, 2013 1:12 am
by Komag
very nice, this should be used by everyone!

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Mon Aug 26, 2013 5:25 pm
by Diarmuid
That's golden. Thank you so much, John! :D :!:

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Mon Aug 26, 2013 7:38 pm
by petri
Well done, John! I don't think it's possible to place more than one marker in one square, unless they are spawned from a script, so this should be a valid workaround.

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Mon Aug 26, 2013 9:19 pm
by flatline
Sweet, I have an immediate use for that fix, I think. Nothing like the Grimrock forums to get the creativity flowing :)

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Mon Aug 26, 2013 10:51 pm
by msyblade
I needed this for my ORRR2 room, that i'm building right now. Timing couldn't have been better! (Okay, maybe 2 months ago so the other author's could be spoiled, like me :roll:

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Mon Aug 26, 2013 11:27 pm
by Diarmuid
We're going to have a marker-plague free ORRR2 experience thanks to that.

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Sat Oct 05, 2013 5:08 am
by Diarmuid
Hi guys,

While doing some benchmarking for EXSP using my new profiler, I realized the above implementation of newAllEntities(level) was really slow (around 0.8ms for about a 100 entities).

Here is an updated version, which runs at about 0.04ms for 1000 entities, so approx 150-200x faster:

Code: Select all

function newAllEntities(level)
   local it = allEntities(level);
   local c = 0;
   
   return function()
      local e = it();
    while ( e == nil and c < 100) do
         e = it();
   c = c + 1
      end
      
      if ( e ) then
         return e;
      end
   end
end
Just replace the function in JohnWordsworth's "fix" script.

Explanation: basically, instead of running a newEntitiesAt() iterator on each of the 1024 squares of the grid, this new version calls the normal allEntities(), but gives it 100 "chances" to hit a map_marker before failing, which seemed a good margin. If you really think that your player might put more than 100 markers per level, you can raise the number, it's the "c < 100" bit in the code, but it will slow it down slightly. On the opposite, you could proably lower it towards 50 safely too I guess.

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Sat Oct 05, 2013 10:24 am
by Eleven Warrior
Hi

At the risk of sounding Stupid (lol) does this mean that if a player puts a maker on the map the game wont crash??

EDIT: If I add this Code to my mod now would it affect it Eg: Crash it?

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Posted: Sun Oct 06, 2013 12:23 am
by Komag
Okay, I've implemented this fix (the overall fix by JohnWordsworth along with Diarmuid's version of newAllEntities), and ran a few tests and I think everything is good.

After I finish a couple more updates for Master Quest and then do a full playthrough I'll see if I run into any bugs or performance issues. :)