Bug Fix: Fully working entitiesAt and allEntities functions.

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
JohnWordsworth
Posts: 1387
Joined: Fri Sep 14, 2012 4:19 pm
Location: Devon, United Kingdom
Contact:

Bug Fix: Fully working entitiesAt and allEntities functions.

Post by JohnWordsworth » Mon Aug 26, 2013 12:57 am

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!
Last edited by JohnWordsworth on Thu Feb 13, 2014 12:49 pm, edited 1 time in total.
My Grimrock Projects Page with links to the Grimrock Model Toolkit, GrimFBX, Atlas Toolkit, QuickBar, NoteBook and the Oriental Weapons Pack.

User avatar
Komag
Posts: 3629
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by Komag » Mon Aug 26, 2013 1:12 am

very nice, this should be used by everyone!
Finished Dungeons - complete mods to play

User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by Diarmuid » Mon Aug 26, 2013 5:25 pm

That's golden. Thank you so much, John! :D :!:

User avatar
petri
Posts: 1898
Joined: Thu Mar 01, 2012 4:58 pm
Location: Finland

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by petri » Mon Aug 26, 2013 7:38 pm

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.

User avatar
flatline
Posts: 189
Joined: Thu Oct 04, 2012 11:13 am

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by flatline » Mon Aug 26, 2013 9:19 pm

Sweet, I have an immediate use for that fix, I think. Nothing like the Grimrock forums to get the creativity flowing :)

User avatar
msyblade
Posts: 792
Joined: Fri Oct 12, 2012 4:40 am
Location: New Mexico, USA
Contact:

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by msyblade » Mon Aug 26, 2013 10:51 pm

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:
Currently conspiring with many modders on the "Legends of the Northern Realms"project.

"You have been captured by a psychopathic diety who needs a new plaything to torture."
Hotel Hades

User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by Diarmuid » Mon Aug 26, 2013 11:27 pm

We're going to have a marker-plague free ORRR2 experience thanks to that.

User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by Diarmuid » Sat Oct 05, 2013 5:08 am

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.
Last edited by Diarmuid on Sat Oct 05, 2013 2:44 pm, edited 1 time in total.

User avatar
Eleven Warrior
Posts: 726
Joined: Thu Apr 18, 2013 2:32 pm
Location: Australia

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by Eleven Warrior » Sat Oct 05, 2013 10:24 am

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?

User avatar
Komag
Posts: 3629
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Bug Fix: Fully working entitiesAt and allEntities functi

Post by Komag » Sun Oct 06, 2013 12:23 am

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. :)
Finished Dungeons - complete mods to play

Post Reply