hivemind.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. --------------
  2. ---hivemind Copyright 2020 Francisco "FreeLikeGNU" Athens, MIT license
  3. --------------
  4. -- hivemind enables player-entity and entity-entity relations to be transfered between entities
  5. -- so that we have a more natural flow of relationships and meaningful interactions throughout a worldspace.
  6. local function strip_escapes(input)
  7. hivemind.strip_escapes(input)
  8. end
  9. local function print_s(input)
  10. print(hivemind.strip_escapes(input))
  11. end
  12. local S = minetest.get_translator("hivemind")
  13. ---hivemind.encounter can be used to initialize, query and write data in the form of key/(int)value pairs
  14. -- to an entity as self.hivemind
  15. --@ the optional "relation" is a {key = (int)value} pair to which we will write, queries should not include this
  16. function hivemind.encounter (self, target_name, relation)
  17. local hm_t = target_name
  18. local hm_r = relation
  19. local ent = ""
  20. --are we a player?
  21. if hm_t and hm_t:is_player() then
  22. ent = hm_t:get_player_name()
  23. else
  24. ---figure something else out
  25. end
  26. --haz hivemind?
  27. if not self.hivemind then --give us a brain
  28. self.hivemind = {id = "hm_"..string.format("%x", math.random()*10^14)} --create our ID
  29. --create our own dataset
  30. self.hivemind[self.hivemind.id] = {}
  31. end
  32. local shm = self.hivemind -- either existing or freshly created brains!
  33. if not hm_t then return shm end --we may be done if we are just querying everthing we know
  34. --we must have a target if we got this far
  35. if not shm[shm.id][ent] then --if no local entry exists we need to identify and create an entry for the target
  36. shm[shm.id][ent] = {fe = os.time()} --"fe" stands for "first encounter"
  37. end
  38. if hm_t and not hm_r then -- we just have a query about the player (or mob)
  39. --we may have just met a player, create a table for it
  40. if not shm[shm.id][ent] then shm[shm.id][ent] = {} end
  41. return shm[shm.id][ent] -- return what we know about the target
  42. end
  43. if hm_t and hm_r then
  44. for k,v in pairs(hm_r) do -- write the tables
  45. if not shm[shm.id][ent][k] then shm[shm.id][ent][k] = 0 end --initialize
  46. shm[shm.id][ent][k] = shm[shm.id][ent][k] + v
  47. shm[shm.id][ent]["le"] = os.time() --"le" stands for "last encounter"
  48. end
  49. return shm[shm.id][ent][hm_r]
  50. end
  51. end
  52. ---hivemind.propogate transfers knowledge between entities
  53. -- we scan for others in the collective in range every 4-6 sec unless defined otherwise
  54. function hivemind.pull(self,t_min,t_max,range)
  55. local t_min = t_min or 4
  56. local t_max = t_max or t_min + 2
  57. if self.last_time and self.last_time + math.random(t_min, t_max) > os.time() then return end
  58. self.last_time = os.time()
  59. --local ent = target:get_luaentity()
  60. local pos = vector.round(self.object:getpos())
  61. local s = self.object:get_pos()
  62. local objs = minetest.get_objects_inside_radius(s, range or self.view_range or 10)
  63. --print_s(S(dump(aggro_wielded)))
  64. -- remove entities we aren't interested in
  65. for n = 1, #objs do
  66. local ent = objs[n]:get_luaentity()
  67. -- are we a player?
  68. if objs[n]:is_player() then --we don't care now
  69. -- local pname = objs[n]:get_player_name()
  70. --if not ent.hivemind then ent.hivemind["id"] = math.random() end
  71. elseif ent == self then
  72. --we dont care about our own brain!
  73. elseif not ent.hivemind then
  74. ---they have nothing to say!
  75. else
  76. print("I found a brain: "..dump(ent.hivemind.id))
  77. local mst = minetest.serialize
  78. local mdt = minetest.deserialize
  79. local ehm = ent.hivemind
  80. local ehm_s = mst(ehm)
  81. --round up our own relations (as we may not even have any!)
  82. local shm = hivemind.encounter(self)
  83. --get the knowledge
  84. print("Hi, I am: "..dump(shm.id))
  85. for k,v in pairs(ehm) do
  86. if k == "id" then -- record our meeting
  87. if not shm[shm.id][ehm.id] then
  88. shm[shm.id][ehm.id] = {fe = os.time()}
  89. print(" we are meeting for the first time!")--make an introduction
  90. shm[shm.id][ehm.id].le = os.time()
  91. end
  92. shm[shm.id][ehm.id].le = os.time()
  93. --print("( "..shm.id.." meeting "..ehm.id.. " recorded at "..shm[shm.id][ehm.id].le.." )")
  94. elseif k ~= shm.id then
  95. print(" We are talking about ".. k.."'s encounters")
  96. for x,y in pairs(ehm[k]) do
  97. if x ~= shm.id then
  98. print(" ehm: "..x.." "..mst(y))
  99. if not shm[k]then
  100. print(" I didn't know anything about " ..k)
  101. shm[k] = {}
  102. end
  103. if not shm[k][x] then--we need to fill the gap
  104. print(" ehm le = "..ehm[k][x].le.. " vs " ..mst(shm[k]))
  105. shm[k][x] = table.copy(ehm[k][x])
  106. print(" I just learned about"..mst(shm[k]))
  107. end
  108. if shm[k][x] and shm[k][x].le then
  109. print( " shm knows about : "..k.." "..mst(shm[k]))
  110. if shm[k][x].le < ehm[k][x].le then
  111. print(" ...but I did not know that about " ..x.." and "..k)
  112. shm[k][x] = table.copy(ehm[k][x])
  113. print(" and now I know what " ..x.." did since " ..shm[k][x].le)
  114. end
  115. end
  116. end
  117. end
  118. end
  119. end
  120. end
  121. end
  122. end