[FUNCTION] Find entities with text and method filtering
Posted: Thu Nov 01, 2012 7:59 pm
Here is a utility function I wrote as part of my cryogenic chamber I hope to publish later today. It looks at one or more squares at or around a given square and return objects found there filtering on key words found in the object name or on objects that have specific methods. These filters can be satisfied if any or only if all key words are matched. It looks at a single square, the single square that is in front of the square specified by coordinates (uses self.facing), or all squares surrounding (and including) either of the first two options. If you're looking at all squares surrounding something, you can filter the objects to only return objects that are facing the given (or self.facing offset) square. Although self.facing is used instead of passing the facing value to the script, it can easily be added to the argument list if you need it. Just don't confuse it with the "facing" logical.
The function is called as follows: table = findAll(level, x, y, keys, all, surrounding, facing, facingUs)
Return all monsters in a given square: monsters = findAll(self.level, self.x, self.y, {":setAIState"}) Note that a group of monsters may be returned as a single monster group, or may be broken down into separate monsters, one for each group member.
Return all monsters in a given square that you can add objects to (you can't add objects to groups that I can tell): CanCarry = findAll(self.level, self.x, self.y, {":addItem", ":setAIState"}, "all")
Return all doors that open into the square where our script is located: doors = findAll(self.level, self.x, self.y, {"door"}, "any", true, false, true) Any object that has "door" in its name will be returned. The surrounding flag is true, so nine squares will be examined for doors. Remember the "northern" door out of your chamber might actually be placed as the "southern" door in the square immediately to your north.
Have Fun, -Lark
The function is called as follows: table = findAll(level, x, y, keys, all, surrounding, facing, facingUs)
- level - level to inspect
- x - the x coordinate of the base square
- y - the y coordinate of the base square
- keys - a table of key words to be used as a filter.
- If omitted or specified as {"*"}, all objects are returned unfiltered.
- if a key word starts with a colon (":" - i.e. ":getWeight") then it is interpreted as a method name which the object must have to be included.
- if it does not start with anything special (i.e. "door") then the text must appear somewhere in the name to be included.
- all - specified as string "all" means all key words must be true to be included in the results. Otherwise any match will include the object.
- surrounding - true to inspect the current square and all surrounding squares for objects.
- facing - true to "move" the base square that is inspected from the x, y location specified to the square the script itself is facing.
- facingUs - true to include only objects that are surrounding the square inspected (as altered above) that are facing the square inspected.
Return all monsters in a given square: monsters = findAll(self.level, self.x, self.y, {":setAIState"}) Note that a group of monsters may be returned as a single monster group, or may be broken down into separate monsters, one for each group member.
Return all monsters in a given square that you can add objects to (you can't add objects to groups that I can tell): CanCarry = findAll(self.level, self.x, self.y, {":addItem", ":setAIState"}, "all")
Return all doors that open into the square where our script is located: doors = findAll(self.level, self.x, self.y, {"door"}, "any", true, false, true) Any object that has "door" in its name will be returned. The surrounding flag is true, so nine squares will be examined for doors. Remember the "northern" door out of your chamber might actually be placed as the "southern" door in the square immediately to your north.
Code: Select all
---
--- Generic Find: return all objects at, or surrounding, a given location containing all/any string/method in keys
---
-- keys == {"keyword", ":method", ...} a match with any/all items will include the object
-- all == "all" all keywords must be matched; else any keyword must be matched
-- surrounding == true - looks in the current space and all surrounding spaces
-- facing == true - looks in the space adjacent the direction we're facing
-- surrounding and facing == true - current space adjusted to where we're facing, then look at all surrounding
-- facingUs == true - limit matches to things that are facing us or that are in our own space
function findAll(level, x, y, keys, all, surrounding, facing, facingUs)
local answers, r, dx, dy, entity, match, _ = {}, 0
all = all == "all"
local any = not all
if surrounding then r = 1 end
if facing then
dx, dy = getForward(self.facing)
x, y = x + dx, y + dy
end
if keys == nil then keys = {"*"} end
for i = x - r, x + r do
for j = y - r, y + r do
if 0 < i and i < 33 and 0 < j and j < 33 then
for entity in entitiesAt(level, i, j) do
match = true
for _, value in ipairs(keys) do
if value == "*" then pass = true
elseif string.sub(value, 1, 1) == ":" then pass = entity[(string.sub(value, 2))] ~= nil
else pass = string.find(entity.name, value) ~= nil end
if all then match = pass and match
else match = pass end
if (match and any) or ((not match) and all) then break end
end
if match then
dx, dy = getForward(entity.facing)
if (not facingUs) or (facingUs and entity.x + dx == self.x and entity.y + dy == self.y) or (self.x == entity.x and self.y == entity.y) then
answers[# answers + 1] = entity
end
end
end
end
end
end
return answers
end