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