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.
6 from server.config.world_data import world_db
10 if not (action_exists("drink") and world_db["WORLD_ACTIVE"]
11 and world_db["Things"][0]["T_LIFEPOINTS"] > 0):
13 pos = world_db["Things"][0]["pos"]
14 if not (chr(world_db["MAP"][pos]) == "0"
15 and world_db["wetmap"][pos] > ord("0")):
16 log("NOTHING to drink here.")
18 elif world_db["Things"][0]["T_KIDNEY"] >= 32:
19 log("You're too FULL to drink more.")
21 world_db["set_command"]("drink")
26 if chr(world_db["MAP"][pos]) == "0" and \
27 world_db["wetmap"][pos] > ord("0") and t["T_KIDNEY"] < 32:
28 if world_db["Things"][0] == t:
31 world_db["wetmap"][pos] -= 1
32 if world_db["wetmap"][pos] == ord("0"):
33 world_db["MAP"][pos] = ord("0")
34 elif t == world_db["Things"][0]:
35 log("YOU FAIL TO DRINK " + str(world_db["MAP"][pos] - ord("0")))
39 if not (action_exists("pee") and world_db["WORLD_ACTIVE"]
40 and world_db["Things"][0]["T_LIFEPOINTS"] > 0):
42 if world_db["Things"][0]["T_BLADDER"] < 1:
43 log("Nothing to drop from empty bladder.")
45 world_db["set_command"]("pee")
49 if t["T_BLADDER"] < 1:
51 if t == world_db["Things"][0]:
52 log("You LOSE fluid.")
53 if not world_db["test_air"](t):
56 world_db["wetmap"][t["pos"]] += 1
60 if not (action_exists("drop") and world_db["WORLD_ACTIVE"]
61 and world_db["Things"][0]["T_LIFEPOINTS"] > 0):
63 if world_db["Things"][0]["T_BOWEL"] < 1:
64 log("Nothing to drop from empty bowel.")
66 world_db["set_command"]("drop")
72 if t == world_db["Things"][0]:
73 log("You DROP waste.")
74 if not world_db["test_air"](t):
76 world_db["MAP"][t["pos"]] += 1
80 def play_move(str_arg):
81 if not (action_exists("move") and world_db["WORLD_ACTIVE"]
82 and world_db["Things"][0]["T_LIFEPOINTS"] > 0):
84 from server.config.world_data import directions_db, symbols_passable
85 t = world_db["Things"][0]
86 if not str_arg in directions_db:
87 print("Illegal move direction string.")
89 d = ord(directions_db[str_arg])
90 from server.utils import mv_yx_in_dir_legal
91 move_result = mv_yx_in_dir_legal(chr(d), t["T_POSY"], t["T_POSX"])
92 if 1 == move_result[0]:
93 pos = (move_result[1] * world_db["MAP_LENGTH"]) + move_result[2]
94 hitted = [tid for tid in world_db["Things"]
95 if world_db["Things"][tid]["T_POSY"] == move_result[1]
96 if world_db["Things"][tid]["T_POSX"] == move_result[2]]
98 if t["T_STOMACH"] >= 32 and t["T_KIDNEY"] >= 32:
99 if t == world_db["Things"][0]:
100 log("You're too FULL to suck from another creature.")
102 world_db["Things"][0]["T_ARGUMENT"] = d
103 world_db["set_command"]("eat")
105 if chr(world_db["MAP"][pos]) in "34":
106 if t["T_STOMACH"] >= 32:
107 if t == world_db["Things"][0]:
108 log("You're too FULL to eat.")
110 world_db["Things"][0]["T_ARGUMENT"] = d
111 world_db["set_command"]("eat")
113 if chr(world_db["MAP"][pos]) in symbols_passable:
114 world_db["Things"][0]["T_ARGUMENT"] = d
115 world_db["set_command"]("move")
117 log("You CAN'T eat your way through there.")
121 from server.utils import mv_yx_in_dir_legal, rand
122 from server.config.world_data import symbols_passable
124 move_result = mv_yx_in_dir_legal(chr(t["T_ARGUMENT"]),
125 t["T_POSY"], t["T_POSX"])
126 if 1 == move_result[0]:
127 pos = (move_result[1] * world_db["MAP_LENGTH"]) + move_result[2]
128 hitted = [tid for tid in world_db["Things"]
129 if world_db["Things"][tid]["T_POSY"] == move_result[1]
130 if world_db["Things"][tid]["T_POSX"] == move_result[2]]
133 hitted_tid = world_db["Things"][hit_id]["T_TYPE"]
134 if t == world_db["Things"][0]:
135 hitted_name = world_db["ThingTypes"][hitted_tid]["TT_NAME"]
136 log("You SUCK from " + hitted_name + ".")
138 hitter_name = world_db["ThingTypes"][t["T_TYPE"]]["TT_NAME"]
139 log(hitter_name +" SUCKS from you.")
140 hitted = world_db["Things"][hit_id]
141 if t["T_STOMACH"] < 32:
142 t["T_STOMACH"] = t["T_STOMACH"] + 1
143 hitted["T_STOMACH"] -= 1
144 if t["T_KIDNEY"] < 32:
145 t["T_KIDNEY"] = t["T_KIDNEY"] + 1
146 hitted["T_KIDNEY"] -= 1
148 passable = chr(world_db["MAP"][pos]) in symbols_passable
149 if passable and t == world_db["Things"][0]:
150 log("You try to EAT, but fail.")
152 height = world_db["MAP"][pos] - ord("0")
153 if t["T_STOMACH"] >= 32 or height == 5:
156 if t == world_db["Things"][0]:
158 eaten = (height == 3 and 0 == int(rand.next() % 2)) or \
159 (height == 4 and 0 == int(rand.next() % 5))
161 world_db["MAP"][pos] = ord("0")
162 if t["T_STOMACH"] > 32:
167 from server.build_fov_map import build_fov_map
168 from server.utils import mv_yx_in_dir_legal, rand
169 from server.config.world_data import symbols_passable
171 move_result = mv_yx_in_dir_legal(chr(t["T_ARGUMENT"]),
172 t["T_POSY"], t["T_POSX"])
173 if 1 == move_result[0]:
174 pos = (move_result[1] * world_db["MAP_LENGTH"]) + move_result[2]
175 hitted = [tid for tid in world_db["Things"]
176 if world_db["Things"][tid]["T_POSY"] == move_result[1]
177 if world_db["Things"][tid]["T_POSX"] == move_result[2]]
180 hitted_tid = world_db["Things"][hit_id]["T_TYPE"]
181 if t == world_db["Things"][0]:
182 hitted_name = world_db["ThingTypes"][hitted_tid]["TT_NAME"]
183 log("You BUMP into " + hitted_name + ".")
185 hitter_name = world_db["ThingTypes"][t["T_TYPE"]]["TT_NAME"]
186 log(hitter_name +" BUMPS into you.")
188 passable = chr(world_db["MAP"][pos]) in symbols_passable
190 t["T_POSY"] = move_result[1]
191 t["T_POSX"] = move_result[2]
192 t["pos"] = move_result[1] * world_db["MAP_LENGTH"] + move_result[2]
193 world_db["soundmap"][t["pos"]] = ord("9")
194 elif t == world_db["Things"][0]:
195 log("You try to MOVE there, but fail.")
199 if world_db["MAP"][t["pos"]] == ord("-"):
200 world_db["die"](t, "You FALL in a hole, and die.")
203 world_db["test_hole"] = test_hole
207 if world_db["terrain_fullness"](t["pos"]) > 5:
208 world_db["die"](t, "You SUFFOCATE")
211 world_db["test_air"] = test_air
215 t["T_LIFEPOINTS"] = 0
216 if t == world_db["Things"][0]:
217 t["fovmap"] = bytearray(b' ' * (world_db["MAP_LENGTH"] ** 2))
218 t["T_MEMMAP"][t["pos"]] = ord("@")
221 world_db["MAP"][t["pos"]] = ord("5")
222 world_db["HUMILITY"] = t["T_KIDNEY"] + t["T_BLADDER"] + \
223 (world_db["wetmap"][t["pos"]] - ord("0"))
224 world_db["wetmap"][t["pos"]] = 0
225 tid = next(tid for tid in world_db["Things"]
226 if world_db["Things"][tid] == t)
227 del world_db["Things"][tid]
228 world_db["die"] = die
232 from server.make_map import new_pos, is_neighbor
233 from server.utils import rand
234 world_db["MAP"] = bytearray(b'5' * (world_db["MAP_LENGTH"] ** 2))
235 length = world_db["MAP_LENGTH"]
236 add_half_width = (not (length % 2)) * int(length / 2)
237 world_db["MAP"][int((length ** 2) / 2) + add_half_width] = ord("4")
239 y, x, pos = new_pos()
240 if "5" == chr(world_db["MAP"][pos]) and is_neighbor((y, x), "4"):
241 if y == 0 or y == (length - 1) or x == 0 or x == (length - 1):
243 world_db["MAP"][pos] = ord("4")
244 n_ground = int((length ** 2) / 16)
246 while (i_ground <= n_ground):
247 single_allowed = rand.next() % 32
248 y, x, pos = new_pos()
249 if "4" == chr(world_db["MAP"][pos]) \
250 and ((not single_allowed) or is_neighbor((y, x), "0")):
251 world_db["MAP"][pos] = ord("0")
253 n_water = int((length ** 2) / 32)
255 while (i_water <= n_water):
256 y, x, pos = new_pos()
257 if ord("0") == world_db["MAP"][pos] and \
258 ord("0") == world_db["wetmap"][pos]:
259 world_db["wetmap"][pos] = ord("3")
263 def calc_effort(ta, t):
264 from server.utils import mv_yx_in_dir_legal
265 if ta["TA_NAME"] == "move":
266 move_result = mv_yx_in_dir_legal(chr(t["T_ARGUMENT"]),
267 t["T_POSY"], t["T_POSX"])
268 if 1 == move_result[0]:
269 pos = (move_result[1] * world_db["MAP_LENGTH"]) + move_result[2]
270 narrowness = world_db["MAP"][pos] - ord("0")
271 return 2 ** narrowness
273 world_db["calc_effort"] = calc_effort
277 from server.ai import ai
278 from server.config.actions import action_db
279 from server.update_map_memory import update_map_memory
280 from server.io import try_worldstate_update
281 from server.config.io import io_db
282 from server.utils import rand
283 from server.build_fov_map import build_fov_map
284 while world_db["Things"][0]["T_LIFEPOINTS"]:
285 for tid in [tid for tid in world_db["Things"]]:
286 if not tid in world_db["Things"]:
288 t = world_db["Things"][tid]
289 if t["T_LIFEPOINTS"]:
290 if not (world_db["test_air"](t) and world_db["test_hole"](t)):
292 if not t["T_COMMAND"]:
298 if t["T_LIFEPOINTS"]:
300 taid = [a for a in world_db["ThingActions"]
301 if a == t["T_COMMAND"]][0]
302 ThingAction = world_db["ThingActions"][taid]
303 effort = world_db["calc_effort"](ThingAction, t)
304 if t["T_PROGRESS"] >= effort:
305 action = action_db["actor_" + ThingAction["TA_NAME"]]
309 if t["T_BOWEL"] > 16:
310 if 0 == (rand.next() % (33 - t["T_BOWEL"])):
311 action_db["actor_drop"](t)
312 if t["T_BLADDER"] > 16:
313 if 0 == (rand.next() % (33 - t["T_BLADDER"])):
314 action_db["actor_pee"](t)
315 if 0 == world_db["TURN"] % 5:
320 if t["T_STOMACH"] <= 0:
321 world_db["die"](t, "You DIE of hunger.")
322 elif t["T_KIDNEY"] <= 0:
323 world_db["die"](t, "You DIE of dehydration.")
324 for pos in range(world_db["MAP_LENGTH"] ** 2):
325 wetness = world_db["wetmap"][pos] - ord("0")
326 height = world_db["MAP"][pos] - ord("0")
327 if height == 0 and wetness > 0 \
328 and 0 == rand.next() % ((2 ** 13) / (2 ** wetness)):
329 world_db["MAP"][pos] = ord("-")
330 if ((wetness > 0 and height != 0) or wetness > 1) \
331 and 0 == rand.next() % 5:
332 world_db["wetmap"][pos] -= 1
333 world_db["HUMIDITY"] += 1
334 if world_db["HUMIDITY"] > 0:
335 if world_db["HUMIDITY"] > 2 and 0 == rand.next() % 2:
336 world_db["NEW_SPAWN"] += 1
337 world_db["HUMIDITY"] -= 1
338 if world_db["NEW_SPAWN"] >= 16:
339 world_db["NEW_SPAWN"] -= 16
340 from server.new_thing import new_Thing
342 y = rand.next() % world_db["MAP_LENGTH"]
343 x = rand.next() % world_db["MAP_LENGTH"]
344 if chr(world_db["MAP"][y * world_db["MAP_LENGTH"] + x]) !=\
346 from server.utils import id_setter
347 tid = id_setter(-1, "Things")
348 world_db["Things"][tid] = new_Thing(
349 world_db["PLAYER_TYPE"], (y, x))
350 pos = y * world_db["MAP_LENGTH"] + x
352 positions_to_wet = []
353 for pos in range(world_db["MAP_LENGTH"] ** 2):
354 if world_db["MAP"][pos] == ord("0") \
355 and world_db["wetmap"][pos] < ord("5"):
356 positions_to_wet += [pos]
357 while world_db["HUMIDITY"] > 0 and len(positions_to_wet) > 0:
358 select = rand.next() % len(positions_to_wet)
359 pos = positions_to_wet[select]
360 world_db["wetmap"][pos] += 1
361 positions_to_wet.remove(pos)
362 world_db["HUMIDITY"] -= 1
363 for pos in range(world_db["MAP_LENGTH"] ** 2):
364 if world_db["soundmap"][pos] > ord("0"):
365 world_db["soundmap"][pos] -= 1
366 world_db["TURN"] += 1
367 io_db["worldstate_updateable"] = True
368 try_worldstate_update()
369 world_db["turn_over"] = turn_over
373 """Call ai() on player Thing, then turn_over()."""
374 if not (world_db["WORLD_ACTIVE"]
375 and world_db["Things"][0]["T_LIFEPOINTS"] > 0):
377 from server.ai import ai
378 ai(world_db["Things"][0])
379 world_db["turn_over"]()
382 def set_command(action):
383 """Set player's T_COMMAND, then call turn_over()."""
384 tid = [x for x in world_db["ThingActions"]
385 if world_db["ThingActions"][x]["TA_NAME"] == action][0]
386 world_db["Things"][0]["T_COMMAND"] = tid
387 world_db["turn_over"]()
388 world_db["set_command"] = set_command
392 """Try "wait" as player's T_COMMAND."""
393 if world_db["WORLD_ACTIVE"]:
394 world_db["set_command"]("wait")
398 length = world_db["MAP_LENGTH"]
400 for i in range(length):
401 line = world_db["wetmap"][i * length:(i * length) + length].decode()
402 string = string + "WETMAP" + " " + str(i) + " " + line + "\n"
403 for i in range(length):
404 line = world_db["soundmap"][i * length:(i * length) + length].decode()
405 string = string + "SOUNDMAP" + " " + str(i) + " " + line + "\n"
409 def soundmapset(str_int, mapline):
410 def valid_map_line(str_int, mapline):
411 from server.utils import integer_test
412 val = integer_test(str_int, 0, 255)
414 if val >= world_db["MAP_LENGTH"]:
415 print("Illegal value for map line number.")
416 elif len(mapline) != world_db["MAP_LENGTH"]:
417 print("Map line length is unequal map width.")
421 val = valid_map_line(str_int, mapline)
423 length = world_db["MAP_LENGTH"]
424 if not world_db["soundmap"]:
425 m = bytearray(b' ' * (length ** 2))
427 m = world_db["soundmap"]
428 m[val * length:(val * length) + length] = mapline.encode()
429 if not world_db["soundmap"]:
430 world_db["soundmap"] = m
433 def wetmapset(str_int, mapline):
434 def valid_map_line(str_int, mapline):
435 from server.utils import integer_test
436 val = integer_test(str_int, 0, 255)
438 if val >= world_db["MAP_LENGTH"]:
439 print("Illegal value for map line number.")
440 elif len(mapline) != world_db["MAP_LENGTH"]:
441 print("Map line length is unequal map width.")
445 val = valid_map_line(str_int, mapline)
447 length = world_db["MAP_LENGTH"]
448 if not world_db["wetmap"]:
449 m = bytearray(b' ' * (length ** 2))
451 m = world_db["wetmap"]
452 m[val * length:(val * length) + length] = mapline.encode()
453 if not world_db["wetmap"]:
454 world_db["wetmap"] = m
457 def write_soundmap():
458 from server.worldstate_write_helpers import write_map
459 length = world_db["MAP_LENGTH"]
460 return write_map(world_db["soundmap"], world_db["MAP_LENGTH"])
464 from server.worldstate_write_helpers import write_map
465 length = world_db["MAP_LENGTH"]
466 visible_wetmap = bytearray(b' ' * (length ** 2))
467 for i in range(length ** 2):
468 if world_db["Things"][0]["fovmap"][i] == ord('v'):
469 visible_wetmap[i] = world_db["wetmap"][i]
470 return write_map(visible_wetmap, world_db["MAP_LENGTH"])
474 if world_db["WORLD_ACTIVE"]:
475 world_db["ai"](world_db["Things"][0])
476 world_db["turn_over"]()
479 def get_dir_to_target(t, target):
481 from server.utils import rand, libpr, c_pointer_to_bytearray
482 from server.config.world_data import symbols_passable
484 def get_map_score(pos):
485 result = libpr.get_map_score(pos)
487 raise RuntimeError("No score map allocated for get_map_score().")
490 def zero_score_map_where_char_on_memdepthmap(c):
491 map = c_pointer_to_bytearray(t["T_MEMDEPTHMAP"])
492 if libpr.zero_score_map_where_char_on_memdepthmap(c, map):
493 raise RuntimeError("No score map allocated for "
494 "zero_score_map_where_char_on_memdepthmap().")
496 def set_map_score(pos, score):
497 test = libpr.set_map_score(pos, score)
499 raise RuntimeError("No score map allocated for set_map_score().")
501 def set_movement_cost_map():
502 copy_memmap = t["T_MEMMAP"][:]
503 copy_memmap.replace(b' ', b'4')
504 memmap = c_pointer_to_bytearray(copy_memmap)
505 if libpr.TCE_set_movement_cost_map(memmap):
506 raise RuntimeError("No movement cost map allocated for "
507 "set_movement_cost_map().")
509 def animates_in_fov(maplength):
510 return [Thing for Thing in world_db["Things"].values()
511 if Thing["T_LIFEPOINTS"] and 118 == t["fovmap"][Thing["pos"]]
512 and (not Thing == t)]
518 except StopIteration:
521 mapsize = world_db["MAP_LENGTH"] ** 2
522 if target == "food" and t["T_MEMMAP"]:
523 return exists(pos for pos in range(mapsize)
524 if ord("2") < t["T_MEMMAP"][pos] < ord("5"))
525 elif target == "fluid_certain" and t["fovmap"]:
526 return exists(pos for pos in range(mapsize)
527 if t["fovmap"] == ord("v")
528 if world_db["MAP"][pos] == ord("0")
529 if world_db["wetmap"][pos] > ord("0"))
530 elif target == "fluid_potential" and t["T_MEMMAP"] and t["fovmap"]:
531 return exists(pos for pos in range(mapsize)
532 if t["T_MEMMAP"][pos] == ord("0")
533 if t["fovmap"] != ord("v"))
534 elif target == "space_big" and t["T_MEMMAP"] and t["fovmap"]:
535 return exists(pos for pos in range(mapsize)
536 if ord("0") <= t["T_MEMMAP"][pos] <= ord("2")
537 if (t["fovmap"] != ord("v")
538 or world_db["terrain_fullness"](pos) < 5))
539 elif target in {"hunt", "flee"} and t["fovmap"]:
540 return exists(Thing for
541 Thing in animates_in_fov(world_db["MAP_LENGTH"])) \
542 or exists(pos for pos in range(mapsize)
543 if world_db["soundmap"][pos] > ord("0")
544 if t["fovmap"][pos] != ord("v"))
547 def init_score_map():
548 mapsize = world_db["MAP_LENGTH"] ** 2
549 test = libpr.TCE_init_score_map()
550 [set_map_score(pos, 65535) for pos in range(mapsize)
551 if chr(t["T_MEMMAP"][pos]) in "5-"]
552 set_movement_cost_map()
554 raise RuntimeError("Malloc error in init_score_map().")
555 if target == "food" and t["T_MEMMAP"]:
556 [set_map_score(pos, 0) for pos in range(mapsize)
557 if ord("2") < t["T_MEMMAP"][pos] < ord("5")]
558 elif target == "fluid_certain" and t["fovmap"]:
559 [set_map_score(pos, 0) for pos in range(mapsize)
560 if t["fovmap"] == ord("v")
561 if world_db["MAP"][pos] == ord("0")
562 if world_db["wetmap"][pos] > ord("0")]
563 elif target == "fluid_potential" and t["T_MEMMAP"] and t["fovmap"]:
564 [set_map_score(pos, 0) for pos in range(mapsize)
565 if t["T_MEMMAP"][pos] == ord("0")
566 if t["fovmap"] != ord("v")]
567 elif target == "space" and t["T_MEMMAP"] and t["fovmap"]:
568 [set_map_score(pos, 0) for pos in range(mapsize)
569 if ord("0") <= t["T_MEMMAP"][pos] <= ord("2")
570 if (t["fovmap"] != ord("v")
571 or world_db["terrain_fullness"](pos) < 5)]
572 elif target == "search":
573 zero_score_map_where_char_on_memdepthmap(mem_depth_c[0])
574 elif target in {"hunt", "flee"}:
575 [set_map_score(Thing["pos"], 0) for
576 Thing in animates_in_fov(world_db["MAP_LENGTH"])]
577 [set_map_score(pos, 0) for pos in range(mapsize)
578 if world_db["soundmap"][pos] > ord("0")
579 if t["fovmap"][pos] != ord("v")]
581 def rand_target_dir(neighbors, cmp, dirs):
584 for i in range(len(dirs)):
585 if cmp == neighbors[i]:
586 candidates.append(dirs[i])
588 return candidates[rand.next() % n_candidates] if n_candidates else 0
590 def get_neighbor_scores(dirs, eye_pos):
592 if libpr.ready_neighbor_scores(eye_pos):
593 raise RuntimeError("No score map allocated for " +
594 "ready_neighbor_scores.()")
595 for i in range(len(dirs)):
596 scores.append(libpr.get_neighbor_score(i))
599 def get_dir_from_neighbors():
601 dir_to_target = False
604 neighbors = get_neighbor_scores(dirs, eye_pos)
605 minmax_start = 0 if "flee" == target else 65535 - 1
606 minmax_neighbor = minmax_start
607 for i in range(len(dirs)):
608 if ("flee" == target and get_map_score(t["pos"]) < neighbors[i] and
609 minmax_neighbor < neighbors[i] and 65535 != neighbors[i]) \
610 or ("flee" != target and minmax_neighbor > neighbors[i]):
611 minmax_neighbor = neighbors[i]
612 if minmax_neighbor != minmax_start:
613 dir_to_target = rand_target_dir(neighbors, minmax_neighbor, dirs)
615 distance = get_map_score(t["pos"])
618 if not dir_to_target:
619 if attack_distance >= distance:
620 dir_to_target = rand_target_dir(neighbors,
622 elif dir_to_target and fear_distance < distance:
624 return dir_to_target, minmax_neighbor
626 dir_to_target = False
628 run_i = 9 + 1 if "search" == target else 1
630 while run_i and not dir_to_target and \
631 ("search" == target or seeing_thing()):
634 mem_depth_c = b'9' if b' ' == mem_depth_c \
635 else bytes([mem_depth_c[0] - 1])
636 if libpr.TCE_dijkstra_map_with_movement_cost():
637 raise RuntimeError("No score map allocated for dijkstra_map().")
638 dir_to_target, minmax_neighbor = get_dir_from_neighbors()
639 libpr.free_score_map()
640 if dir_to_target and str == type(dir_to_target):
642 from server.utils import mv_yx_in_dir_legal
643 move_result = mv_yx_in_dir_legal(dir_to_target, t["T_POSY"],
645 if 1 != move_result[0]:
647 pos = (move_result[1] * world_db["MAP_LENGTH"]) + move_result[2]
648 hitted = [tid for tid in world_db["Things"]
649 if world_db["Things"][tid]["pos"] == pos]
650 if world_db["MAP"][pos] > ord("2") or len(hitted) > 0:
652 t["T_COMMAND"] = [taid for taid in world_db["ThingActions"]
653 if world_db["ThingActions"][taid]["TA_NAME"]
655 t["T_ARGUMENT"] = ord(dir_to_target)
656 return dir_to_target, minmax_neighbor
657 world_db["get_dir_to_target"] = get_dir_to_target
660 def terrain_fullness(pos):
661 return (world_db["MAP"][pos] - ord("0")) + \
662 (world_db["wetmap"][pos] - ord("0"))
663 world_db["terrain_fullness"] = terrain_fullness
668 if t["T_LIFEPOINTS"] == 0:
671 def standing_on_fluid(t):
672 if world_db["MAP"][t["pos"]] == ord("0") and \
673 world_db["wetmap"][t["pos"]] > ord("0"):
678 def thing_action_id(name):
679 return [taid for taid in world_db["ThingActions"]
680 if world_db["ThingActions"][taid]
681 ["TA_NAME"] == name][0]
683 t["T_COMMAND"] = thing_action_id("wait")
686 "safe_pee": (world_db["terrain_fullness"](t["pos"]) * t["T_BLADDER"]) / 4,
687 "safe_drop": (world_db["terrain_fullness"](t["pos"]) * t["T_BOWEL"]) / 4,
688 "food": 33 - t["T_STOMACH"],
689 "fluid_certain": 33 - t["T_KIDNEY"],
690 "fluid_potential": 32 - t["T_KIDNEY"],
693 from operator import itemgetter
694 needs = sorted(needs.items(), key=itemgetter(1,0))
698 if need[0] in {"fluid_certain", "fluid_potential"}:
699 if standing_on_fluid(t):
700 t["T_COMMAND"] = thing_action_id("drink")
702 elif t["T_BLADDER"] > 0 and \
703 world_db["MAP"][t["pos"]] == ord("0"):
704 t["T_COMMAND"] = thing_action_id("pee")
706 elif need[0] in {"safe_pee", "safe_drop"}:
707 action_name = need[0][len("safe_"):]
708 if world_db["terrain_fullness"](t["pos"]) <= 3:
709 t["T_COMMAND"] = thing_action_id(action_name)
711 test = world_db["get_dir_to_target"](t, "space")
715 elif world["terrain_fullness"](t["pos"]) < 5:
716 t["T_COMMAND"] = thing_action_id(action_name)
718 if t["T_STOMACH"] < 32 and \
719 world_db["get_dir_to_target"](t, "food")[0]:
722 if need[0] in {"fluid_certain", "fluid_potential", "food"}:
723 if world_db["get_dir_to_target"](t, need[0])[0]:
725 elif world_db["get_dir_to_target"](t, "hunt")[0]:
727 elif need[0] != "food" and t["T_STOMACH"] < 32 and \
728 world_db["get_dir_to_target"](t, "food")[0]:
730 elif world_db["get_dir_to_target"](t, need[0])[0]:
735 from server.config.io import io_db
736 io_db["worldstate_write_order"] += [["T_STOMACH", "player_int"]]
737 io_db["worldstate_write_order"] += [["T_KIDNEY", "player_int"]]
738 io_db["worldstate_write_order"] += [["T_BOWEL", "player_int"]]
739 io_db["worldstate_write_order"] += [["T_BLADDER", "player_int"]]
740 io_db["worldstate_write_order"] += [[write_wetmap, "func"]]
741 io_db["worldstate_write_order"] += [[write_soundmap, "func"]]
742 import server.config.world_data
743 server.config.world_data.symbols_hide = "345"
744 server.config.world_data.symbols_passable = "012-"
745 server.config.world_data.thing_defaults["T_STOMACH"] = 16
746 server.config.world_data.thing_defaults["T_BOWEL"] = 0
747 server.config.world_data.thing_defaults["T_KIDNEY"] = 16
748 server.config.world_data.thing_defaults["T_BLADDER"] = 0
749 world_db["soundmap"] = bytearray(b"0" * world_db["MAP_LENGTH"] ** 2)
750 world_db["wetmap"] = bytearray(b"0" * world_db["MAP_LENGTH"] ** 2)
751 if not "NEW_SPAWN" in world_db:
752 world_db["NEW_SPAWN"] = 0
753 if not "HUMIDITY" in world_db:
754 world_db["HUMIDITY"] = 0
755 io_db["hook_save"] = save_maps
756 import server.config.make_world_helpers
757 server.config.make_world_helpers.make_map = make_map
758 from server.config.commands import commands_db
759 commands_db["THINGS_HERE"] = (2, True, lambda x, y: None)
760 commands_db["ai"] = (0, False, command_ai)
761 commands_db["move"] = (1, False, play_move)
762 commands_db["eat"] = (1, False, play_move)
763 commands_db["wait"] = (0, False, play_wait)
764 commands_db["drop"] = (0, False, play_drop)
765 commands_db["drink"] = (0, False, play_drink)
766 commands_db["pee"] = (0, False, play_pee)
767 commands_db["use"] = (1, False, lambda x: None)
768 commands_db["pickup"] = (0, False, lambda: None)
769 commands_db["NEW_SPAWN"] = (1, False, setter(None, "NEW_SPAWN", 0, 255))
770 commands_db["HUMIDITY"] = (1, False, setter(None, "HUMIDITY", 0, 65535))
771 commands_db["T_STOMACH"] = (1, False, setter("Thing", "T_STOMACH", 0, 255))
772 commands_db["T_KIDNEY"] = (1, False, setter("Thing", "T_KIDNEY", 0, 255))
773 commands_db["T_BOWEL"] = (1, False, setter("Thing", "T_BOWEL", 0, 255))
774 commands_db["T_BLADDER"] = (1, False, setter("Thing", "T_BLADDER", 0, 255))
775 commands_db["WETMAP"] = (2, False, wetmapset)
776 commands_db["SOUNDMAP"] = (2, False, soundmapset)
777 from server.actions import actor_wait
778 import server.config.actions
779 server.config.actions.action_db = {
780 "actor_wait": actor_wait,
781 "actor_move": actor_move,
782 "actor_drop": actor_drop,
783 "actor_drink": actor_drink,
784 "actor_pee": actor_pee,
785 "actor_eat": actor_eat,
788 strong_write(io_db["file_out"], "PLUGIN TheCrawlingEater\n")