diff --git a/polymer/eduke32/source/lunatic/bcarray.lua b/polymer/eduke32/source/lunatic/bcarray.lua
index 9d4c0e9c9..b73b3e56d 100644
--- a/polymer/eduke32/source/lunatic/bcarray.lua
+++ b/polymer/eduke32/source/lunatic/bcarray.lua
@@ -1,4 +1,4 @@
--- Implementation of a bound-checked array type factory for LuaJIT.
+-- Implementation of a bound-checked array type factory for LuaJIT 2.0 or later.
 --
 -- Usage example:
 --
@@ -36,7 +36,7 @@ function flatten_array(nelts, rng)
     return table.concat(strtab)
 end
 
--- ct = bcarray.new(basetype, numelts, showname [, typename] [, rng] [, mtadd])
+-- ctype = bcarray.new(basetype, numelts, showname [, typename] [, rng] [, mtadd])
 -- (optional fields may be nil)
 --
 -- <numelts>: Number of elements in array (small number)
@@ -44,7 +44,7 @@ end
 -- <typename>: If non-nil, the name under which the derived type is typedef'd
 -- <rng>: Random generator state + method :getu32(). If nil, then members are
 --  named _a1, _a2, ...
--- <mtadd>: A table containing functions __index and/or __index. They are
+-- <mtadd>: A table containing functions __index and/or __newindex. They are
 --  called first and the bound-checking ones are tail-called then.
 function new(basetype, numelts, showname, typename, rng, mtadd)
     local eltptr_t = ffi.typeof("$ *", ffi.typeof(basetype))
diff --git a/polymer/eduke32/source/lunatic/bitar.lua b/polymer/eduke32/source/lunatic/bitar.lua
index 454578981..3ea895d59 100644
--- a/polymer/eduke32/source/lunatic/bitar.lua
+++ b/polymer/eduke32/source/lunatic/bitar.lua
@@ -16,11 +16,7 @@ local tostring = tostring
 module(...)
 
 
-ffi.cdef[[
-struct bitar { const double maxbidx, maxidx; const intptr_t arptr; }
-]]
-
-local bitar_ct = ffi.typeof("struct bitar")
+local bitar_ct = ffi.typeof("struct { const double maxbidx, maxidx; const intptr_t arptr; }")
 local ptr_to_int = ffi.typeof("int32_t *")
 
 local anchor = {}
@@ -216,7 +212,7 @@ local mt = {
     end,
 }
 
-local bitar = ffi.metatype("struct bitar", mt)
+local bitar = ffi.metatype(bitar_ct, mt)
 
 -- Create new bit array.
 function new(maxbidx, initval)
diff --git a/polymer/eduke32/source/lunatic/bittest.lua b/polymer/eduke32/source/lunatic/bittest.lua
index 9fa6a2af9..e11cd23a8 100755
--- a/polymer/eduke32/source/lunatic/bittest.lua
+++ b/polymer/eduke32/source/lunatic/bittest.lua
@@ -140,5 +140,8 @@ if (string.dump) then
     print(p-p)  -- test set difference
     print(-p)
 --]]
+
+    -- Set difference of self with self is the same as set intersection of self
+    -- with complement of self:
     assert(p-p == p*(-p))
 end
diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua
index c04ff8544..ca64a2495 100644
--- a/polymer/eduke32/source/lunatic/defs.ilua
+++ b/polymer/eduke32/source/lunatic/defs.ilua
@@ -290,20 +290,12 @@ typedef struct
 ]].. mangle_arrays(ACTOR_STRUCT) ..[[
 actor_t;
 
-typedef struct
-]].. strip_const(ACTOR_STRUCT).. [[
-actor_u_t;  // The _u_t versions are unrestricted variants for internal use.
-
 typedef struct { int32_t _p; } weaponaccess_t;
 
 typedef struct
 ]].. mangle_arrays(DUKEPLAYER_STRUCT) ..[[
 DukePlayer_t;
 
-typedef struct
-]].. strip_const(DUKEPLAYER_STRUCT) ..[[
-DukePlayer_u_t;
-
 typedef struct {
     uint32_t bits; // 4b
     int16_t fvel, svel; // 4b
@@ -619,8 +611,9 @@ local function check_literal_am(am, typename)
     end
 end
 
-local actor_ptr_ct = ffi.typeof("actor_u_t *")  -- an unrestricted actor_t pointer
-local player_ptr_ct = ffi.typeof("DukePlayer_u_t *")
+-- An unrestricted actor_t pointer, for internal use:
+local actor_ptr_ct = ffi.typeof("$ *", ffi.typeof("struct"..strip_const(ACTOR_STRUCT)))
+local player_ptr_ct = ffi.typeof("$ *", ffi.typeof("struct"..strip_const(DUKEPLAYER_STRUCT)))
 local con_action_ct = ffi.typeof("con_action_t")
 local con_move_ct = ffi.typeof("con_move_t")
 local con_ai_ct = ffi.typeof("con_ai_t")
diff --git a/polymer/eduke32/source/lunatic/defs_common.lua b/polymer/eduke32/source/lunatic/defs_common.lua
index c36c0250f..393685863 100644
--- a/polymer/eduke32/source/lunatic/defs_common.lua
+++ b/polymer/eduke32/source/lunatic/defs_common.lua
@@ -257,7 +257,7 @@ local ivec3_mt = {
         return ivec3_(v.x, v.y, v.z-zofs)
     end,
 }
-ivec3_ = ffi.metatype("vec3_t", ivec3_mt)
+ivec3_ = ffi.metatype(vec3_ct, ivec3_mt)
 
 local xor = bit.bxor
 local wallsofsec  -- fwd-decl
diff --git a/polymer/eduke32/source/lunatic/geom.lua b/polymer/eduke32/source/lunatic/geom.lua
index c841c7569..099469350 100644
--- a/polymer/eduke32/source/lunatic/geom.lua
+++ b/polymer/eduke32/source/lunatic/geom.lua
@@ -10,10 +10,9 @@ local error = error
 module(...)
 
 
-ffi.cdef[[
-typedef struct { double x, y; } dvec2_t;
-typedef struct { double x, y, z; } dvec3_t;
-]]
+local dvec2_t = ffi.typeof("struct { double x, y; }")
+local dvec3_t = ffi.typeof("struct { double x, y, z; }")
+
 
 local vec2_
 local vec2_mt = {
@@ -40,6 +39,8 @@ local vec2_mt = {
     end,
 
     __eq = function(a,b)
+        -- XXX: will error if <a> is not a ctype (can only happen if __eq was
+        -- called by <b>)
         return (ffi.istype(a,b) and a.x==b.x and a.y==b.y)
     end,
 
@@ -77,6 +78,7 @@ local vec3_mt = {
     end,
 
     __eq = function(a,b)
+        -- XXX: see vec2
         return (ffi.istype(a,b) and a.x==b.x and a.y==b.y and a.z==b.z)
     end,
 
@@ -92,7 +94,7 @@ local vec3_mt = {
 -- VEC2 user data constructor.
 --  * vec2(<table>), <table> should be indexable with "x" and "y"
 --  * vec2(x, y), assuming that x and y are numbers
-vec2_ = ffi.metatype("dvec2_t", vec2_mt)
+vec2_ = ffi.metatype(dvec2_t, vec2_mt)
 vec2 = vec2_
 
 -- Returns a vec2 from anything indexable with "x" and "y"
@@ -100,7 +102,7 @@ vec2 = vec2_
 function tovec2(t) return vec2(t.x, t.y) end
 
 -- Same for vec3
-vec3_ = ffi.metatype("dvec3_t", vec3_mt)
+vec3_ = ffi.metatype(dvec3_t, vec3_mt)
 vec3 = vec3_
 function tovec3(t) return vec3(t.x, t.y, t.z) end
 
@@ -108,11 +110,10 @@ function tovec3(t) return vec3(t.x, t.y, t.z) end
 -- integer values, e.g. geom.ivec3(x, y, z) is a reasonable way to round
 -- a vec3.  It can be also used as the RHS to the vec2/vec3 arithmetic
 -- methods.
-ffi.cdef[[
-#pragma pack(push,1)
-typedef struct { int32_t x, y, z; } vec3_t;
-#pragma pack(pop)
-]]
+-- NOTE: We must have a typedef with that exact name, because for
+-- Lunatic (i.e. not stand-alone), it is a duplicate (and ignored)
+-- declaration for an already metatype'd type.
+ffi.cdef "typedef struct { int32_t x, y, z; } vec3_t;"
 ivec3 = ffi.typeof("vec3_t")