123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- --------------
- ---hivemind Copyright 2020 Francisco "FreeLikeGNU" Athens, MIT license
- --------------
- -- hivemind enables player-entity and entity-entity relations to be transfered between entities
- -- so that we have a more natural flow of relationships and meaningful interactions throughout a worldspace.
- local function strip_escapes(input)
- hivemind.strip_escapes(input)
- end
- local function print_s(input)
- print(hivemind.strip_escapes(input))
- end
- local S = minetest.get_translator("hivemind")
- ---hivemind.encounter can be used to initialize, query and write data in the form of key/(int)value pairs
- -- to an entity as self.hivemind
- --@ the optional "relation" is a {key = (int)value} pair to which we will write, queries should not include this
- function hivemind.encounter (self, target_name, relation)
- local hm_t = target_name
- local hm_r = relation
- local ent = ""
- --are we a player?
- if hm_t and hm_t:is_player() then
- ent = hm_t:get_player_name()
- else
- ---figure something else out
- end
- --haz hivemind?
- if not self.hivemind then --give us a brain
- self.hivemind = {id = "hm_"..string.format("%x", math.random()*10^14)} --create our ID
- --create our own dataset
- self.hivemind[self.hivemind.id] = {}
- end
- local shm = self.hivemind -- either existing or freshly created brains!
- if not hm_t then return shm end --we may be done if we are just querying everthing we know
- --we must have a target if we got this far
- if not shm[shm.id][ent] then --if no local entry exists we need to identify and create an entry for the target
- shm[shm.id][ent] = {fe = os.time()} --"fe" stands for "first encounter"
- end
- if hm_t and not hm_r then -- we just have a query about the player (or mob)
- --we may have just met a player, create a table for it
- if not shm[shm.id][ent] then shm[shm.id][ent] = {} end
- return shm[shm.id][ent] -- return what we know about the target
- end
- if hm_t and hm_r then
- for k,v in pairs(hm_r) do -- write the tables
- if not shm[shm.id][ent][k] then shm[shm.id][ent][k] = 0 end --initialize
- shm[shm.id][ent][k] = shm[shm.id][ent][k] + v
- shm[shm.id][ent]["le"] = os.time() --"le" stands for "last encounter"
- end
- return shm[shm.id][ent][hm_r]
- end
- end
- ---hivemind.propogate transfers knowledge between entities
- -- we scan for others in the collective in range every 4-6 sec unless defined otherwise
- function hivemind.pull(self,t_min,t_max,range)
- local t_min = t_min or 4
- local t_max = t_max or t_min + 2
- if self.last_time and self.last_time + math.random(t_min, t_max) > os.time() then return end
- self.last_time = os.time()
- --local ent = target:get_luaentity()
- local pos = vector.round(self.object:getpos())
- local s = self.object:get_pos()
- local objs = minetest.get_objects_inside_radius(s, range or self.view_range or 10)
- --print_s(S(dump(aggro_wielded)))
- -- remove entities we aren't interested in
- for n = 1, #objs do
- local ent = objs[n]:get_luaentity()
- -- are we a player?
- if objs[n]:is_player() then --we don't care now
- -- local pname = objs[n]:get_player_name()
- --if not ent.hivemind then ent.hivemind["id"] = math.random() end
- elseif ent == self then
- --we dont care about our own brain!
- elseif not ent.hivemind then
- ---they have nothing to say!
- else
- print("I found a brain: "..dump(ent.hivemind.id))
- local mst = minetest.serialize
- local mdt = minetest.deserialize
- local ehm = ent.hivemind
- local ehm_s = mst(ehm)
- --round up our own relations (as we may not even have any!)
- local shm = hivemind.encounter(self)
- --get the knowledge
- print("Hi, I am: "..dump(shm.id))
- for k,v in pairs(ehm) do
- if k == "id" then -- record our meeting
- if not shm[shm.id][ehm.id] then
- shm[shm.id][ehm.id] = {fe = os.time()}
- print(" we are meeting for the first time!")--make an introduction
- shm[shm.id][ehm.id].le = os.time()
- end
- shm[shm.id][ehm.id].le = os.time()
- --print("( "..shm.id.." meeting "..ehm.id.. " recorded at "..shm[shm.id][ehm.id].le.." )")
- elseif k ~= shm.id then
- print(" We are talking about ".. k.."'s encounters")
- for x,y in pairs(ehm[k]) do
- if x ~= shm.id then
- print(" ehm: "..x.." "..mst(y))
- if not shm[k]then
- print(" I didn't know anything about " ..k)
- shm[k] = {}
- end
- if not shm[k][x] then--we need to fill the gap
- print(" ehm le = "..ehm[k][x].le.. " vs " ..mst(shm[k]))
- shm[k][x] = table.copy(ehm[k][x])
- print(" I just learned about"..mst(shm[k]))
- end
- if shm[k][x] and shm[k][x].le then
- print( " shm knows about : "..k.." "..mst(shm[k]))
- if shm[k][x].le < ehm[k][x].le then
- print(" ...but I did not know that about " ..x.." and "..k)
- shm[k][x] = table.copy(ehm[k][x])
- print(" and now I know what " ..x.." did since " ..shm[k][x].le)
- end
- end
- end
- end
- end
- end
- end
- end
- end
|