[ create a new paste ] login | about

Link: http://codepad.org/tAKLuFqs    [ raw code | output | fork ]

Lua, pasted on Sep 29:
local function withmultiple (t)
	local mt = getmetatable(t) or { }
	function mt.__call (self, _, i)
		local env = getfenv(2)
		local f = debug.getinfo(2, "f").func
		return coroutine.wrap(function (t, obj)
			repeat
				obj = next(t, obj)
				if obj then
					local prevother = obj.other
					obj.other = env
					setfenv(f, obj)
					coroutine.yield(obj)
					obj.other = prevother
				end
			until not obj
			setfenv(f, env)
		end), self, i
	end
	return setmetatable(t, mt)
end
local function withsingle (t)
	local mt = getmetatable(t) or { }
	function mt.__call (self, _, i)
		local env = getfenv(2)
		local f = debug.getinfo(2, "f").func
		return coroutine.wrap(function ()
			local prevother = self.other
			self.other = env
			setfenv(f, self)
			coroutine.yield(self)
			self.other = prevother
			setfenv(f, env)
		end)
	end
	return setmetatable(t, mt)
end

local objecttypes = { }
local objects = withmultiple(setmetatable({ }, { __index = objecttypes}))

-- this might also work with __index'd methods but i don't want to find out
local function Object (data)
	data = withsingle(data or { })

	data.id = tostring(data)

	data.x = data.x or 0
	data.y = data.y or 0
	data.type = data.type or "friend"

	data.other = "test"

	function data.shout () return "HELLO I AM " .. tostring(data):upper() end
	function data.setcode (f) data.code = setfenv(f, data) end

	data.code = data.code or data.setcode(function () end)

	objects[data] = true
	if not objecttypes[data.type] then
		objecttypes[data.type] = withmultiple { }
	end
	objects[data.type][data] = true

	getmetatable(data).__index = _G
	return data
end

Object { x = 16, y = 384, type = "enemy" }
Object { x = 48, y = 48, type = "enemy" }
Object { x = 24, y = 128 }
Object { x = 256, y = 0 }
Object { x = 64, y = 64, type = "enemy" }

local PARENT = Object { x = 56, y = 56, type = "player" }

PARENT.setcode(function (self)
	print "----- all objects -----"
	for _ in objects() do
		print(shout(), x, y, type, other == PARENT and "ok" or "oops")
	end

	print "----- just enemies -----"
	for _ in objects.enemy() do
		print(shout(), x, y, type, other == PARENT and "ok" or "oops")
	end

	print "----- just this object -----"
	for _ in self() do
		print(shout(), x, y, type, other == PARENT and "ok" or "oops")
	end

	print "----- nested -----"
	for _ in objects.enemy() do
	local distance = math.sqrt((x - other.x)^2 + (y - other.y)^2)
		if distance < 20 then
			for _ in other() do
				print(id .. " got shot by " .. other.id)
			end
		end
	end

	print "----- check that 'other' is restored when 'with' finishes -----"
	for o in pairs(objects) do
		print(o, o.other == "test" and "ok" or "oops")
	end
end)

-- main loop goes here
PARENT:code()


-- i've never used gm and the manual doesn't really make clear whether the object calling the with is included in 'all' or whatever object type is provided. this code assumes it is... anyway i think i'll stick to explicit referencing
-- also lua users please pretend this code never existed. i don't know if it even works in all cases or is technically correct (i probably missed some things)


Output:
----- all objects -----
HELLO I AM TABLE: 0X806F7A8	56	56	player	ok
HELLO I AM TABLE: 0X806F270	16	384	enemy	ok
HELLO I AM TABLE: 0X806F600	24	128	friend	ok
HELLO I AM TABLE: 0X8070410	48	48	enemy	ok
HELLO I AM TABLE: 0X8070E28	64	64	enemy	ok
HELLO I AM TABLE: 0X806FD80	256	0	friend	ok
----- just enemies -----
HELLO I AM TABLE: 0X8070E28	64	64	enemy	ok
HELLO I AM TABLE: 0X8070410	48	48	enemy	ok
HELLO I AM TABLE: 0X806F270	16	384	enemy	ok
----- just this object -----
HELLO I AM TABLE: 0X806F7A8	56	56	player	ok
----- nested -----
table: 0x806f7a8 got shot by table: 0x8070e28
table: 0x806f7a8 got shot by table: 0x8070410
----- check that 'other' is restored when 'with' finishes -----
table: 0x806f7a8	ok
table: 0x806f270	ok
table: 0x806f600	ok
table: 0x8070410	ok
table: 0x8070e28	ok
table: 0x806fd80	ok


Create a new paste based on this one


Comments: