home · contact · privacy
Server, plugin: Refactor actor_use plugin hooking.
[plomrogue] / plugins / server / PleaseTheIslandGod.py
1 # This file is part of PlomRogue. PlomRogue is licensed under the GPL version 3
2 # or any later version. For details on its copyright, license, and warranties,
3 # see the file NOTICE in the root directory of the PlomRogue source package.
4
5
6 from server.io import log, strong_write
7 from server.config.world_data import world_db, directions_db
8 from server.utils import mv_yx_in_dir_legal, rand, id_setter
9 from server.config.io import io_db
10
11 def pos_test(type, y, x):
12     pos = y * world_db["MAP_LENGTH"] + x;
13     plant = world_db["ThingTypes"][type]["TT_PROLIFERATE"]
14     return (not plant or ":" == chr(world_db["MAP"][pos]))
15
16 def world_makable():
17     from server.world_makable import world_makable
18     playertype = world_makable()
19     for name in world_db["specials"]:
20         if world_db[name] not in world_db["ThingTypes"]:
21             print("Ignoring: No valid " + name + " set.")
22             return -1
23     return playertype
24
25 def make_map():
26     from server.make_map import make_map, is_neighbor, new_pos
27     global rand
28     make_map()
29     length = world_db["MAP_LENGTH"]
30     n_colons = int((length ** 2) / 16)
31     i_colons = 0
32     while (i_colons <= n_colons):
33         single_allowed = rand.next() % 256
34         y, x, pos = new_pos()
35         if ("." == chr(world_db["MAP"][pos])
36           and ((not single_allowed) or is_neighbor((y, x), ":"))):
37             world_db["MAP"][pos] = ord(":")
38             i_colons += 1
39     altar_placed = False
40     while not altar_placed:
41         y, x, pos = new_pos()
42         if (("." == chr(world_db["MAP"][pos]
43              or ":" == chr(world_db["MAP"][pos]))
44             and not is_neighbor((y, x), "X"))):
45             world_db["MAP"][pos] = ord("_")
46             world_db["altar"] = (y, x)
47             altar_placed = True
48
49 def field_spreadable(c, t):
50     return ":" == c or (world_db["ThingTypes"][t["T_TYPE"]]["TT_LIFEPOINTS"]
51                         and "." == c)
52
53 def thingprol_plugin_conditions(t):
54     tt = world_db["ThingTypes"][t["T_TYPE"]]
55     return (tt["TT_LIFEPOINTS"] == 0 or \
56             t["T_LIFEPOINTS"] >= 0.9 * tt["TT_LIFEPOINTS"])
57
58 def thingprol_plugin_post_create_hook(t):
59     tt = world_db["ThingTypes"][t["T_TYPE"]]
60     if (world_db["FAVOR_STAGE"] > 0 and t["T_TYPE"] == world_db["PLANT_0"]):
61         world_db["GOD_FAVOR"] += 5
62     elif t["T_TYPE"] == world_db["PLANT_1"]:
63         world_db["GOD_FAVOR"] += 25
64     elif world_db["FAVOR_STAGE"] >= 4 and t["T_TYPE"] == world_db["ANIMAL_1"]:
65         log("The Island God SMILES upon a new-born bear baby.")
66         world_db["GOD_FAVOR"] += 750
67
68 def ai_hook_pickup_test(t):
69     return len(t["T_CARRIES"]) < \
70         world_db["ThingTypes"][t["T_TYPE"]]["TT_STORAGE"]
71
72 def actor_pickup(t):
73     used_slots = len(t["T_CARRIES"])
74     if used_slots < world_db["ThingTypes"][t["T_TYPE"]]["TT_STORAGE"]:
75         from server.actions import actor_pickup
76         t_picked = actor_pickup(t)
77         if t_picked != None:
78             ty = world_db["ThingTypes"][t_picked["T_TYPE"]]
79             if t != world_db["Things"][0] and t_picked["T_PLAYERDROP"] \
80                     and ty["TT_TOOL"] == "food":
81                 score = int(ty["TT_TOOLPOWER"] / 32)
82                 world_db["GOD_FAVOR"] += score
83                 t_picked["T_PLAYERDROP"] = 0
84     elif t == world_db["Things"][0]:
85         log("CAN'T pick up object: No storage room to carry more.")
86
87 def actor_pickup_test_hook(t, tid):
88     from server.ai import eat_vs_hunger_threshold
89     tt = world_db["ThingTypes"][tid]
90     return not (t != world_db["Things"][0] and (tt["TT_TOOL"] != "food" or
91             (tt["TT_TOOLPOWER"] <= eat_vs_hunger_threshold(t["T_TYPE"]))))
92
93 def actor_drop(t):
94     from server.actions import actor_drop
95     dropped = actor_drop(t)
96     if dropped != None:
97         dropped["T_PLAYERDROP"] = 1
98
99 def actor_use_attempts_hook(t, ty):
100     if ty == world_db["SLIPPERS"]:
101         if t == world_db["Things"][0]:
102             log("You use the " + world_db["ThingTypes"][ty]["TT_NAME"] + ". " \
103                 "It glows in wondrous colors, and emits a sound as if from a d"
104                 "ying cat. The Island God laughs.\n")
105         t["T_LIFEPOINTS"] = 1
106         from server.config.misc import decrement_lifepoints_func
107         decrement_lifepoints_func(t)
108     elif (world_db["ThingTypes"][ty]["TT_TOOL"] == "carpentry"):
109         pos = t["T_POSY"] * world_db["MAP_LENGTH"] + t["T_POSX"]
110         if (world_db["MAP"][pos] == ord("X")
111             or world_db["MAP"][pos] == ord("|")):
112             return
113         for t_id in [t_id for t_id in world_db["Things"]
114                    if not world_db["Things"][t_id] == t
115                    if not world_db["Things"][t_id]["carried"]
116                    if world_db["Things"][t_id]["T_POSY"] == t["T_POSY"]
117                    if world_db["Things"][t_id]["T_POSX"] == t["T_POSX"]]:
118             return
119         wood_id = None
120         for t_id in t["T_CARRIES"]:
121             type_material = world_db["Things"][t_id]["T_TYPE"]
122             if (world_db["ThingTypes"][type_material]["TT_TOOL"] == "wood"):
123                 wood_id = t_id
124                 break
125         if wood_id != None:
126             t["T_CARRIES"].remove(wood_id)
127             del world_db["Things"][wood_id]
128             world_db["MAP"][pos] = ord("|")
129             log("With your " + world_db["ThingTypes"][ty]["TT_NAME"] + " you" \
130                 " build a WOODEN BARRIER from your "
131                 + world_db["ThingTypes"][type_material]["TT_NAME"] + ".")
132     elif world_db["ThingTypes"][ty]["TT_TOOL"] == "fertilizer":
133         pos = t["T_POSY"] * world_db["MAP_LENGTH"] + t["T_POSX"]
134         if world_db["MAP"][pos] == ord("."):
135             log("You create SOIL.")
136             world_db["MAP"][pos] = ord(":")
137
138 def decrement_lifepoints(t):
139     t["T_LIFEPOINTS"] -= 1
140     live_type = t["T_TYPE"]
141     _id = [_id for _id in world_db["Things"] if world_db["Things"][_id] == t][0]
142     if 0 == t["T_LIFEPOINTS"]:
143         for id in t["T_CARRIES"]:
144             t["T_CARRIES"].remove(id)
145             world_db["Things"][id]["T_POSY"] = t["T_POSY"]
146             world_db["Things"][id]["T_POSX"] = t["T_POSX"]
147             world_db["Things"][id]["carried"] = False
148         t["T_TYPE"] = world_db["ThingTypes"][t["T_TYPE"]]["TT_CORPSE_ID"]
149         if world_db["Things"][0] == t:
150             t["fovmap"] = bytearray(b' ' * (world_db["MAP_LENGTH"] ** 2))
151             log("You die.")
152             log("See README on how to start over.")
153         else:
154             t["fovmap"] = False
155             t["T_MEMMAP"] = False
156             t["T_MEMDEPTHMAP"] = False
157             t["T_MEMTHING"] = []
158             n_species = len([id for id in world_db["Things"]
159                              if world_db["Things"][id]["T_TYPE"] == live_type])
160             if 0 == n_species:
161                 from server.new_thing import new_Thing
162                 if world_db["FAVOR_STAGE"] >= 3 and \
163                     live_type == world_db["ANIMAL_0"]:
164                     world_db["GOD_FAVOR"] += 3000
165                     log("CONGRATULATIONS! The "
166                         + world_db["ThingTypes"][live_type]["TT_NAME"]
167                         + " species has died out. The Island God is pleased.")
168                 else:
169                     id = id_setter(-1, "Things")
170                     world_db["Things"][id] = new_Thing(live_type,
171                                                        world_db["altar"])
172                     log("The "
173                         + world_db["ThingTypes"][live_type]["TT_NAME"]
174                         + " species has temporarily died out. "
175                         + "One new-born is spawned at the altar.")
176         return world_db["ThingTypes"][t["T_TYPE"]]["TT_LIFEPOINTS"]
177     return 0
178
179 def actor_move(t):
180
181     def altar_msg_wait(limit):
182             log("The Island God will talk again when it favors you to >=" +
183                 str(limit) + " points.")
184
185     altar_msg_0 = "The Island God speaks to you: \"I don't trust you. You in" \
186     "trude on the island's affairs. I think you're a nuisance at best, and a" \
187     " danger to my children at worst. I will give you a chance to lighten my" \
188     " mood, however: For a while now, I've been trying to spread the plant " \
189     + world_db["ThingTypes"][world_db["PLANT_0"]]["TT_NAME"] + " (\"" + \
190     world_db["ThingTypes"][world_db["PLANT_0"]]["TT_SYMBOL"] + "\"). I have " \
191     "not been very successful so far. Maybe you can make yourself useful the" \
192     "re. I will count each further " + \
193     world_db["ThingTypes"][world_db["PLANT_0"]]["TT_NAME"] + " that grows to" \
194     " your favor.\""
195
196     altar_msg_1 = "The Island God speaks to you: \"You could have done worse" \
197     " so far. Maybe you are not the worst to happen to this island since the" \
198     " metal birds threw the great lightning ball. Maybe you can help me spre" \
199     "ad another plant. It multiplies faster,and it is highly nutritious: " + \
200     world_db["ThingTypes"][world_db["PLANT_1"]]["TT_NAME"] + " (\"" + \
201     world_db["ThingTypes"][world_db["PLANT_1"]]["TT_SYMBOL"] + "\"). It is n" \
202     "ew. I give you the only example. Be very careful with it! I also give y" \
203     "ou another tool that may be helpful.\""
204
205     altar_msg_2 = "The Island God speaks to you: \"I am greatly disappointed" \
206     " that you lost all " + \
207     world_db["ThingTypes"][world_db["PLANT_1"]]["TT_NAME"] + " this island h" \
208     "ad. Here is another one. It cost me great work. Be more careful this ti" \
209     "me when planting it.\""
210
211     altar_msg_3 = "The Island God speaks to you: \"The " + \
212     world_db["ThingTypes"][world_db["ANIMAL_0"]]["TT_NAME"] + " has lately b" \
213     "ecome a pest. These creatures do not please me as much as they used to " \
214     "do. Exterminate them all. I will count each kill to your favor. To help" \
215     " you with the hunting, I grant you the empathy and knowledge to read an" \
216     "imals.\""
217
218     altar_msg_4 = "You will now see animals' health bars, and activities (\"" \
219     "m\": moving (maybe for an attack), \"u\": eating, \"p\": picking someth" \
220     "ing up; no letter: waiting)."
221
222     altar_msg_5 = "The Island God speaks to you: \"You know what animal I fi" \
223     "nd the cutest? The " + \
224     world_db["ThingTypes"][world_db["ANIMAL_1"]]["TT_NAME"] + "! I think wha" \
225     "t this islands clearly needs more of is " + \
226     world_db["ThingTypes"][world_db["ANIMAL_1"]]["TT_NAME"] + "s. Why don't " \
227     "you help? Support them. Make sure they are well, and they will multiply" \
228     " faster. From now on, I will count each new-born " + \
229     world_db["ThingTypes"][world_db["ANIMAL_1"]]["TT_NAME"] + \
230     " (not spawned by me due to undo an extinction event) greatly to your fa" \
231     "vor. To help you with the feeding, here is something to make the ground" \
232     " bear more consumables."
233
234     altar_msg_6 = "The Island God speaks to you: \"You have proven yourself " \
235     "worthy of my respect. You were a good citizen to the island, and someti" \
236     "mes a better steward to its inhabitants than me. The island shall miss " \
237     "you when you leave. But you have earned the right to do so. Take this" + \
238     world_db["ThingTypes"][world_db["SLIPPERS"]]["TT_NAME"] + " and USE it w" \
239     "hen you please. It will take you to where you came from. (But do feel f" \
240     "ree to stay here as long as you like.)\""
241
242     def enter_altar():
243         from server.new_thing import new_Thing
244         if world_db["FAVOR_STAGE"] > 9000:
245            log("You step on a soul-less slab of stone.")
246            return
247         log("YOU ENTER SACRED GROUND.")
248         if world_db["FAVOR_STAGE"] == 0:
249             world_db["FAVOR_STAGE"] = 1
250             log(altar_msg_0)
251         elif world_db["FAVOR_STAGE"] == 1 and world_db["GOD_FAVOR"] < 100:
252             altar_msg_wait(100)
253         elif world_db["FAVOR_STAGE"] == 1 and world_db["GOD_FAVOR"] >= 100:
254             world_db["FAVOR_STAGE"] = 2
255             log(altar_msg_2)
256             id = id_setter(-1, "Things")
257             world_db["Things"][id] = new_Thing(world_db["PLANT_1"],
258                                                world_db["altar"])
259             id = id_setter(-1, "Things")
260             world_db["Things"][id] = new_Thing(world_db["TOOL_0"],
261                                                world_db["altar"])
262         elif world_db["FAVOR_STAGE"] == 2 and \
263             0 == len([id for id in world_db["Things"]
264                       if world_db["Things"][id]["T_TYPE"]
265                          == world_db["PLANT_1"]]):
266             log(altar_msg_2)
267             id = id_setter(-1, "Things")
268             world_db["Things"][id] = new_Thing(world_db["PLANT_1"],
269                                                world_db["altar"])
270             world_db["GOD_FAVOR"] -= 250
271         elif world_db["FAVOR_STAGE"] == 2 and world_db["GOD_FAVOR"] < 500:
272             altar_msg_wait(500)
273         elif world_db["FAVOR_STAGE"] == 2 and world_db["GOD_FAVOR"] >= 500:
274             world_db["FAVOR_STAGE"] = 3
275             log(altar_msg_3)
276             log(altar_msg_4)
277             world_db["EMPATHY"] = 1
278         elif world_db["FAVOR_STAGE"] == 3 and world_db["GOD_FAVOR"] < 5000:
279             altar_msg_wait(5000)
280         elif world_db["FAVOR_STAGE"] == 3 and world_db["GOD_FAVOR"] >= 5000:
281             world_db["FAVOR_STAGE"] = 4
282             log(altar_msg_5)
283             id = id_setter(-1, "Things")
284             world_db["Things"][id] = new_Thing(world_db["TOOL_1"],
285                                                world_db["altar"])
286         elif world_db["GOD_FAVOR"] < 20000:
287             altar_msg_wait(20000)
288         elif world_db["GOD_FAVOR"] > 20000:
289             world_db["FAVOR_STAGE"] = 9001
290             log(altar_msg_6)
291             id = id_setter(-1, "Things")
292             world_db["Things"][id] = new_Thing(world_db["SLIPPERS"],
293                                                world_db["altar"])
294
295     from server.config.world_data import symbols_passable
296     from server.build_fov_map import build_fov_map
297     from server.config.misc import decrement_lifepoints_func
298     from server.new_thing import new_Thing
299     global mv_yx_in_dir_legal
300     passable = False
301     move_result = mv_yx_in_dir_legal(chr(t["T_ARGUMENT"]),
302                                      t["T_POSY"], t["T_POSX"])
303     if 1 == move_result[0]:
304         pos = (move_result[1] * world_db["MAP_LENGTH"]) + move_result[2]
305         hitted = [id for id in world_db["Things"]
306                   if world_db["Things"][id] != t
307                   if world_db["Things"][id]["T_LIFEPOINTS"]
308                   if world_db["Things"][id]["T_POSY"] == move_result[1]
309                   if world_db["Things"][id]["T_POSX"] == move_result[2]]
310         if len(hitted):
311             hit_id = hitted[0]
312             hitted_type = world_db["Things"][hit_id]["T_TYPE"]
313             if t == world_db["Things"][0]:
314                 hitted_name = world_db["ThingTypes"][hitted_type]["TT_NAME"]
315                 log("You WOUND " + hitted_name + ".")
316                 world_db["GOD_FAVOR"] -= 1
317             elif 0 == hit_id:
318                 hitter_name = world_db["ThingTypes"][t["T_TYPE"]]["TT_NAME"]
319                 log(hitter_name +" WOUNDS you.")
320             test = decrement_lifepoints_func(world_db["Things"][hit_id])
321             if test and world_db["FAVOR_STAGE"] >= 3 and \
322                hitted_type == world_db["ANIMAL_0"]:
323                 world_db["GOD_FAVOR"] += 125
324             elif test and t == world_db["Things"][0]:
325                 world_db["GOD_FAVOR"] -= 2 * test
326             return
327         if (ord("X") == world_db["MAP"][pos]
328             or ord("|") == world_db["MAP"][pos]):
329             for id in t["T_CARRIES"]:
330                 type = world_db["Things"][id]["T_TYPE"]
331                 if world_db["ThingTypes"][type]["TT_TOOL"] == "axe":
332                     axe_name = world_db["ThingTypes"][type]["TT_NAME"]
333                     if t == world_db["Things"][0]:
334                         log("With your " + axe_name + ", you chop!")
335                         if ord("X") == world_db["MAP"][pos]:
336                             world_db["GOD_FAVOR"] -= 1
337                     chop_power = world_db["ThingTypes"][type]["TT_TOOLPOWER"]
338
339                     case_X = world_db["MAP"][pos] == ord("X")
340                     if (chop_power > 0
341                         and ((case_X and
342                               0 == int(rand.next() / chop_power))
343                         or (not case_X and
344                                  0 == int(rand.next() / (3 * chop_power))))):
345                         if t == world_db["Things"][0]:
346                             log("You chop it DOWN.")
347                             if ord("X") == world_db["MAP"][pos]:
348                                 world_db["GOD_FAVOR"] -= 10
349                         world_db["MAP"][pos] = ord(".")
350                         i = 3 if case_X else 1
351                         for i in range(i):
352                             id = id_setter(-1, "Things")
353                             world_db["Things"][id] = \
354                               new_Thing(world_db["LUMBER"],
355                                         (move_result[1], move_result[2]))
356                         build_fov_map(t)
357                     return
358         passable = chr(world_db["MAP"][pos]) in symbols_passable
359     global directions_db
360     dir = [dir for dir in directions_db
361            if directions_db[dir] == chr(t["T_ARGUMENT"])][0]
362     if passable:
363         t["T_POSY"] = move_result[1]
364         t["T_POSX"] = move_result[2]
365         for id in t["T_CARRIES"]:
366             world_db["Things"][id]["T_POSY"] = move_result[1]
367             world_db["Things"][id]["T_POSX"] = move_result[2]
368         build_fov_map(t)
369         if t == world_db["Things"][0]:
370             log("You MOVE " + dir + ".")
371             if (move_result[1] == world_db["altar"][0] and
372                 move_result[2] == world_db["altar"][1]):
373                 enter_altar()
374
375 def command_ttid(id_string):
376     id = id_setter(id_string, "ThingTypes", command_ttid)
377     if None != id:
378         world_db["ThingTypes"][id] = {
379             "TT_NAME": "(none)",
380             "TT_TOOLPOWER": 0,
381             "TT_LIFEPOINTS": 0,
382             "TT_PROLIFERATE": 0,
383             "TT_START_NUMBER": 0,
384             "TT_STORAGE": 0,
385             "TT_SYMBOL": "?",
386             "TT_CORPSE_ID": id,
387             "TT_TOOL": ""
388         }
389
390 def command_worldactive(worldactive_string):
391     val = integer_test(worldactive_string, 0, 1)
392     if None != val:
393         if 0 != world_db["WORLD_ACTIVE"]:
394             if 0 == val:
395                 set_world_inactive()
396             else:
397                 print("World already active.")
398         elif 0 == world_db["WORLD_ACTIVE"]:
399             for ThingAction in world_db["ThingActions"]:
400                 if "wait" == world_db["ThingActions"][ThingAction]["TA_NAME"]:
401                     break
402             else:
403                 print("Ignored: No wait action defined for world to activate.")
404                 return
405             for Thing in world_db["Things"]:
406                 if 0 == Thing:
407                     break
408             else:
409                 print("Ignored: No player defined for world to activate.")
410                 return
411             if world_db["MAP"]:
412                 pos = world_db["MAP"].find(b'_')
413                 if pos > 0:
414                     y = int(pos / world_db["MAP_LENGTH"])
415                     x = pos % world_db["MAP_LENGTH"]
416                     world_db["altar"] = (y, x)
417                 else:
418                     print("Ignored: No altar defined for world to activate.")
419                     return
420             else:
421                 print("Ignored: No map defined for world to activate.")
422                 return
423             for name in world_db["specials"]:
424                 if world_db[name] not in world_db["ThingTypes"]:
425                     print("Ignored: Not all specials set for world to "
426                           "activate.")
427                     return
428             for id in world_db["Things"]:
429                 if world_db["Things"][id]["T_LIFEPOINTS"]:
430                     build_fov_map(world_db["Things"][id])
431                     if 0 == id:
432                         update_map_memory(world_db["Things"][id], False)
433             if not world_db["Things"][0]["T_LIFEPOINTS"]:
434                 empty_fovmap = bytearray(b" " * world_db["MAP_LENGTH"] ** 2)
435                 world_db["Things"][0]["fovmap"] = empty_fovmap
436             world_db["WORLD_ACTIVE"] = 1
437
438 def play_move(str_arg):
439     if action_exists("move"):
440         from server.config.world_data import directions_db, symbols_passable
441         t = world_db["Things"][0]
442         if not str_arg in directions_db:
443             print("Illegal move direction string.")
444             return
445         dir = ord(directions_db[str_arg])
446         global mv_yx_in_dir_legal
447         move_result = mv_yx_in_dir_legal(chr(dir), t["T_POSY"], t["T_POSX"])
448         if 1 == move_result[0]:
449             pos = (move_result[1] * world_db["MAP_LENGTH"]) + move_result[2]
450             if ord("~") == world_db["MAP"][pos]:
451                 log("You can't SWIM.")
452                 return
453             if (ord("X") == world_db["MAP"][pos]
454                 or ord("|") == world_db["MAP"][pos]):
455                 carries_axe = False
456                 for id in t["T_CARRIES"]:
457                     type = world_db["Things"][id]["T_TYPE"]
458                     if world_db["ThingTypes"][type]["TT_TOOL"] == "axe":
459                         world_db["Things"][0]["T_ARGUMENT"] = dir
460                         set_command("move")
461                         return
462             if chr(world_db["MAP"][pos]) in symbols_passable:
463                 world_db["Things"][0]["T_ARGUMENT"] = dir
464                 set_command("move")
465                 return
466         log("You CAN'T move there.")
467
468 def play_use(str_arg):
469     if action_exists("use"):
470         t = world_db["Things"][0]
471         if 0 == len(t["T_CARRIES"]):
472             log("You have NOTHING to use in your inventory.")
473         else:
474             val = integer_test(str_arg, 0, 255)
475             if None != val and val < len(t["T_CARRIES"]):
476                 id = t["T_CARRIES"][val]
477                 type = world_db["Things"][id]["T_TYPE"]
478                 if (world_db["ThingTypes"][type]["TT_TOOL"] == "axe"
479                       and t == world_db["Things"][0]):
480                     log("To use this item for chopping, move towards a tree "
481                         "while carrying it in your inventory.")
482                     return
483                 elif (world_db["ThingTypes"][type]["TT_TOOL"] == "carpentry"):
484                     pos = t["T_POSY"] * world_db["MAP_LENGTH"] + t["T_POSX"]
485                     if (world_db["MAP"][pos] == ord("X")
486                         or world_db["MAP"][pos] == ord("|")):
487                         log("CAN'T build when standing on barrier.")
488                         return
489                     for id in [id for id in world_db["Things"]
490                                if not world_db["Things"][id] == t
491                                if not world_db["Things"][id]["carried"]
492                                if world_db["Things"][id]["T_POSY"] == t["T_POSY"]
493                                if world_db["Things"][id]["T_POSX"] == t["T_POSX"]]:
494                          log("CAN'T build when standing objects.")
495                          return
496                     wood_id = None
497                     for id in t["T_CARRIES"]:
498                         type_material = world_db["Things"][id]["T_TYPE"]
499                         if (world_db["ThingTypes"][type_material]["TT_TOOL"]
500                             == "wood"):
501                             wood_id = id
502                             break
503                     if wood_id == None:
504                         log("You CAN'T use a "
505                             + world_db["ThingTypes"][type]["TT_NAME"]
506                             + " without some wood in your inventory.")
507                         return
508                 elif world_db["ThingTypes"][type]["TT_TOOL"] == "fertilizer":
509                     pos = t["T_POSY"] * world_db["MAP_LENGTH"] + t["T_POSX"]
510                     if not world_db["MAP"][pos] == ord("."):
511                         log("Can only make soil out of NON-SOIL earth.")
512                         return
513                 elif world_db["ThingTypes"][type]["TT_TOOL"] == "wood":
514                         log("To use wood, you NEED a carpentry tool.")
515                         return
516                 elif type != world_db["SLIPPERS"] and not \
517                         world_db["ThingTypes"][type]["TT_TOOL"] == "food":
518                     log("You CAN'T consume this thing.")
519                     return
520                 world_db["Things"][0]["T_ARGUMENT"] = val
521                 set_command("use")
522             else:
523                 print("Illegal inventory index.")
524
525 def specialtypesetter(name):
526     def helper(str_int):
527         val = integer_test(str_int, 0)
528         if None != val:
529             world_db[name] = val
530             if world_db["WORLD_ACTIVE"] \
531                and world_db[name] not in world_db["ThingTypes"]:
532                 world_db["WORLD_ACTIVE"] = 0
533                 print(name + " fits no known ThingType, deactivating world.")
534     return helper
535
536 def write_metamap_A():
537     from server.worldstate_write_helpers import write_map
538     ord_v = ord("v")
539     length = world_db["MAP_LENGTH"]
540     metamapA = bytearray(b'0' * (length ** 2))
541     for id in [id for id in world_db["Things"]
542                   if not world_db["Things"][id]["carried"]
543                   if world_db["Things"][id]["T_LIFEPOINTS"]
544                   if world_db["Things"][0]["fovmap"][
545                        world_db["Things"][id]["T_POSY"] * length
546                        + world_db["Things"][id]["T_POSX"]] == ord_v]:
547         pos = (world_db["Things"][id]["T_POSY"] * length
548               + world_db["Things"][id]["T_POSX"])
549         if id == 0 or world_db["EMPATHY"]:
550             type = world_db["Things"][id]["T_TYPE"]
551             max_hp = world_db["ThingTypes"][type]["TT_LIFEPOINTS"]
552             third_of_hp = max_hp / 3
553             hp = world_db["Things"][id]["T_LIFEPOINTS"]
554             add = 0
555             if hp > 2 * third_of_hp:
556                  add = 2
557             elif hp > third_of_hp:
558                 add = 1
559             metamapA[pos] = ord('a') + add
560         else:
561             metamapA[pos] = ord('X')
562     for mt in world_db["Things"][0]["T_MEMTHING"]:
563         pos = mt[1] * length + mt[2]
564         if metamapA[pos] < ord('2'):
565             metamapA[pos] += 1
566     return write_map(metamapA, length)
567
568 def write_metamap_B():
569     from server.worldstate_write_helpers import write_map
570     ord_v = ord("v")
571     length = world_db["MAP_LENGTH"]
572     metamapB = bytearray(b' ' * (length ** 2))
573     for id in [id for id in world_db["Things"]
574                   if not world_db["Things"][id]["carried"]
575                   if world_db["Things"][id]["T_LIFEPOINTS"]
576                   if world_db["Things"][0]["fovmap"][
577                        world_db["Things"][id]["T_POSY"] * length
578                        + world_db["Things"][id]["T_POSX"]] == ord_v]:
579         pos = (world_db["Things"][id]["T_POSY"] * length
580               + world_db["Things"][id]["T_POSX"])
581         if id == 0 or world_db["EMPATHY"]:
582             action = world_db["Things"][id]["T_COMMAND"]
583             if 0 != action:
584                 name = world_db["ThingActions"][action]["TA_NAME"]
585             else:
586                 name = " "
587             metamapB[pos] = ord(name[0])
588     return write_map(metamapB, length)
589
590 def calc_effort(thing_action, thing):
591     from math import sqrt
592     effort = thing_action["TA_EFFORT"]
593     if thing_action["TA_NAME"] == "move":
594         typ = thing["T_TYPE"]
595         max_hp = (world_db["ThingTypes"][typ]["TT_LIFEPOINTS"])
596         effort = int(effort / sqrt(max_hp))
597         effort = 1 if effort == 0 else effort
598     return effort
599
600 def play_pickup():
601     """Try "pickup" as player's T_COMMAND"."""
602     if action_exists("pickup"):
603         t = world_db["Things"][0]
604         ids = [id for id in world_db["Things"] if id
605                if not world_db["Things"][id]["carried"]
606                if world_db["Things"][id]["T_POSY"] == t["T_POSY"]
607                if world_db["Things"][id]["T_POSX"] == t["T_POSX"]]
608         if not len(ids):
609             log("NOTHING to pick up.")
610         elif len(t["T_CARRIES"]) >= world_db["ThingTypes"][t["T_TYPE"]] \
611                 ["TT_STORAGE"]:
612             log("CAN'T pick up: No storage room to carry anything more.")
613         else:
614             set_command("pickup")
615
616 strong_write(io_db["file_out"], "PLUGIN PleaseTheIslandGod\n")
617
618 def set_zero_if_undefined(key):
619     if not key in world_db:
620         world_db[key] = 0
621
622 set_zero_if_undefined("GOD_FAVOR")
623 set_zero_if_undefined("FAVOR_STAGE")
624 set_zero_if_undefined("EMPATHY")
625 world_db["specials"] = ["SLIPPERS", "PLANT_0", "PLANT_1", "TOOL_0", "TOOL_1",
626     "LUMBER", "ANIMAL_0", "ANIMAL_1"]
627 for key in world_db["specials"]:
628     set_zero_if_undefined(key)
629
630 world_db["terrain_names"][":"] = "SOIL"
631 world_db["terrain_names"]["|"] = "WALL"
632 world_db["terrain_names"]["_"] = "ALTAR"
633 io_db["worldstate_write_order"] += [["GOD_FAVOR", "world_int"]]
634 io_db["worldstate_write_order"] += [[write_metamap_A, "func"]]
635 io_db["worldstate_write_order"] += [[write_metamap_B, "func"]]
636
637 import server.config.world_data
638 server.config.world_data.symbols_passable += ":_"
639
640 from server.config.world_data import thing_defaults
641 thing_defaults["T_PLAYERDROP"] = 0
642
643 import server.config.actions
644 server.config.actions.action_db["actor_move"] = actor_move
645 server.config.actions.action_db["actor_pickup"] = actor_pickup
646 server.config.actions.action_db["actor_drop"] = actor_drop
647 server.config.actions.actor_pickup_test_hook = actor_pickup_test_hook
648 server.config.actions.actor_use_attempts_hook = actor_use_attempts_hook
649
650 from server.config.commands import commands_db
651 commands_db["TT_ID"] = (1, False, command_ttid)
652 commands_db["GOD_FAVOR"] = (1, False, setter(None, "GOD_FAVOR", -32768, 32767))
653 commands_db["TT_STORAGE"] = (1, False, setter("ThingType", "TT_STORAGE", 0, 255))
654 commands_db["T_PLAYERDROP"] = (1, False, setter("Thing", "T_PLAYERDROP", 0, 1))
655 commands_db["WORLD_ACTIVE"] = (1, False, command_worldactive)
656 commands_db["FAVOR_STAGE"] = (1, False, setter(None, "FAVOR_STAGE", 0, 1))
657 commands_db["SLIPPERS"] = (1, False, specialtypesetter("SLIPPERS"))
658 commands_db["TOOL_0"] = (1, False, specialtypesetter("TOOL_0"))
659 commands_db["TOOL_1"] = (1, False, specialtypesetter("TOOL_1"))
660 commands_db["ANIMAL_0"] = (1, False, specialtypesetter("ANIMAL_0"))
661 commands_db["ANIMAL_1"] = (1, False, specialtypesetter("ANIMAL_1"))
662 commands_db["PLANT_0"] = (1, False, specialtypesetter("PLANT_0"))
663 commands_db["PLANT_1"] = (1, False, specialtypesetter("PLANT_1"))
664 commands_db["LUMBER"] = (1, False, specialtypesetter("LUMBER"))
665 commands_db["EMPATHY"] = (1, False, setter(None, "EMPATHY", 0, 1))
666 commands_db["use"] = (1, False, play_use)
667 commands_db["move"] = (1, False, play_move)
668 commands_db["pickup"] = (0, False, play_pickup)
669
670 import server.config.misc
671 server.config.misc.make_map_func = make_map
672 server.config.misc.decrement_lifepoints_func = decrement_lifepoints
673 server.config.misc.calc_effort_func = calc_effort
674
675 import server.config.make_world_helpers
676 server.config.make_world_helpers.pos_test_func = pos_test
677 server.config.make_world_helpers.world_makable_func = world_makable
678 server.config.make_world_helpers.make_map_func = make_map
679
680 import server.config.thingproliferation
681 server.config.thingproliferation.field_spreadable = field_spreadable
682 server.config.thingproliferation.thingprol_plugin_conditions = \
683     thingprol_plugin_conditions
684 server.config.thingproliferation.thingprol_plugin_post_create_hook = \
685     thingprol_plugin_post_create_hook
686
687 import server.config.ai
688 server.config.ai.ai_hook_pickup = ai_hook_pickup_test