import shutil
import time
import ctypes
+import math # #
class RandomnessIO:
if time.time() > io_db["save_wait"] + 15:
atomic_write(io_db["path_record"], io_db["record_chunk"],
do_append=True)
- save_world()
+ if world_db["WORLD_ACTIVE"]:
+ save_world()
io_db["record_chunk"] = ""
io_db["save_wait"] = time.time()
io_db["worldstate_updateable"] = world_db["WORLD_ACTIVE"]
type_id = world_db["Things"][id]["T_TYPE"]
name = world_db["ThingTypes"][type_id]["TT_NAME"]
inventory = inventory + name + "\n"
- ## 7DRL additions: GOD_MOOD, GOD_FAVOR
+ # # 7DRL additions: GOD_MOOD, GOD_FAVOR
string = str(world_db["TURN"]) + "\n" + \
str(world_db["GOD_MOOD"]) + "\n" + \
str(world_db["GOD_FAVOR"]) + "\n" + \
def update_map_memory(t, age_map=True):
"""Update t's T_MEMMAP with what's in its FOV now,age its T_MEMMEPTHMAP."""
def age_some_memdepthmap_on_nonfov_cells():
- # OUTSOURCED TO libplomrogue.so:
+ # OUTSOURCED FOR PERFORMANCE REASONS TO libplomrogue.so:
+ # ord_v = ord("v")
+ # ord_0 = ord("0")
+ # ord_9 = ord("9")
# for pos in [pos for pos in range(world_db["MAP_LENGTH"] ** 2)
# if not ord_v == t["fovmap"][pos]
# if ord_0 <= t["T_MEMDEPTHMAP"][pos]
t["T_MEMMAP"][pos] = world_db["MAP"][pos]
if age_map:
age_some_memdepthmap_on_nonfov_cells()
- for mt in [mt for mt in t["T_MEMTHING"]
- if "v" == chr(t["fovmap"][(mt[1] * world_db["MAP_LENGTH"])
- + mt[2]])]:
- t["T_MEMTHING"].remove(mt)
+ t["T_MEMTHING"] = [mt for mt in t["T_MEMTHING"]
+ if ord_v != t["fovmap"][(mt[1] * world_db["MAP_LENGTH"])
+ + mt[2]]]
for id in [id for id in world_db["Things"]
if not world_db["Things"][id]["carried"]]:
type = world_db["Things"][id]["T_TYPE"]
if not world_db["ThingTypes"][type]["TT_LIFEPOINTS"]:
y = world_db["Things"][id]["T_POSY"]
x = world_db["Things"][id]["T_POSX"]
- if "v" == chr(t["fovmap"][(y * world_db["MAP_LENGTH"]) + x]):
+ if ord_v == t["fovmap"][(y * world_db["MAP_LENGTH"]) + x]:
t["T_MEMTHING"].append((type, y, x))
If t is the player avatar, only blank its fovmap, so that the client may
still display memory data. On non-player things, erase fovmap and memory.
+ Dying actors drop all their things.
"""
+ # # 7DRL: also decrements God's mood; deaths heavily so
+ # # 7DRL: return 1 if death, else 0
t["T_LIFEPOINTS"] -= 1
+ world_db["GOD_MOOD"] -= 1 # #
if 0 == t["T_LIFEPOINTS"]:
+ sadness = world_db["ThingTypes"][t["T_TYPE"]]["TT_LIFEPOINTS"] # #
+ world_db["GOD_MOOD"] -= sadness # #
+ for id in t["T_CARRIES"]:
+ t["T_CARRIES"].remove(id)
+ world_db["Things"][id]["T_POSY"] = t["T_POSY"]
+ world_db["Things"][id]["T_POSX"] = t["T_POSX"]
+ world_db["Things"][id]["carried"] = False
t["T_TYPE"] = world_db["ThingTypes"][t["T_TYPE"]]["TT_CORPSE_ID"]
if world_db["Things"][0] == t:
t["fovmap"] = bytearray(b' ' * (world_db["MAP_LENGTH"] ** 2))
t["T_MEMMAP"] = False
t["T_MEMDEPTHMAP"] = False
t["T_MEMTHING"] = []
- strong_write(io_db["file_out"], "LOG It dies.\n")
+ return sadness # #
+ return 0 # #
+
+
+def add_gods_favor(i): # #
+ """"Add to GOD_FAVOR, multiplied with factor growing log. with GOD_MOOD."""
+ def favor_multiplier(i):
+ x = 100
+ threshold = math.e * x
+ mood = world_db["GOD_MOOD"]
+ if i > 0:
+ if mood > threshold:
+ i = i * math.log(mood / x)
+ elif -mood > threshold:
+ i = i / math.log(-mood / x)
+ elif i < 0:
+ if -mood > threshold:
+ i = i * math.log(-mood / x)
+ if mood > threshold:
+ i = i / math.log(mood / x)
+ return int(i)
+ world_db["GOD_FAVOR"] += favor_multiplier(i)
def mv_yx_in_dir_legal(dir, y, x):
def actor_move(t):
"""If passable, move/collide(=attack) thing into T_ARGUMENT's direction."""
+ # # 7DRL: Player wounding (worse: killing) others will lower God's favor.
passable = False
move_result = mv_yx_in_dir_legal(chr(t["T_ARGUMENT"]),
t["T_POSY"], t["T_POSX"])
if world_db["Things"][id]["T_POSX"] == move_result[2]]
if len(hitted):
hit_id = hitted[0]
- hitter_name = world_db["ThingTypes"][t["T_TYPE"]]["TT_NAME"]
- hitter = "You" if t == world_db["Things"][0] else hitter_name
- hitted_type = world_db["Things"][hit_id]["T_TYPE"]
- hitted_name = world_db["ThingTypes"][hitted_type]["TT_NAME"]
- hitted = "you" if hit_id == 0 else hitted_name
- verb = " wound " if hitter == "You" else " wounds "
- strong_write(io_db["file_out"], "LOG " + hitter + verb + hitted +
- ".\n")
- decrement_lifepoints(world_db["Things"][hit_id])
+ if t == world_db["Things"][0]:
+ hitted_type = world_db["Things"][hit_id]["T_TYPE"]
+ hitted_name = world_db["ThingTypes"][hitted_type]["TT_NAME"]
+ strong_write(io_db["file_out"], "LOG You wound " + hitted_name
+ + ".\n")
+ add_gods_favor(-1) # #
+ elif 0 == hit_id:
+ hitter_name = world_db["ThingTypes"][t["T_TYPE"]]["TT_NAME"]
+ strong_write(io_db["file_out"], "LOG " + hitter_name +
+ " wounds you.\n")
+ test = decrement_lifepoints(world_db["Things"][hit_id]) # #(test=)
+ if test and t == world_db["Things"][0]: # #
+ add_gods_favor(-test) # #
return
dir = [dir for dir in directions_db
if directions_db[dir] == chr(t["T_ARGUMENT"])][0]
def actor_pick_up(t):
"""Make t pick up (topmost?) Thing from ground into inventory."""
- # Topmostness is actually not defined so far. Picks Thing with highest ID.
- ids = [id for id in world_db["Things"] if world_db["Things"][id] != t
- if not world_db["Things"][id]["carried"]
- if world_db["Things"][id]["T_POSY"] == t["T_POSY"]
- if world_db["Things"][id]["T_POSX"] == t["T_POSX"]]
- if len(ids):
- highest_id = 0
- for id in ids:
- if id > highest_id:
- highest_id = id
- world_db["Things"][highest_id]["carried"] = True
- t["T_CARRIES"].append(highest_id)
- if t == world_db["Things"][0]:
- strong_write(io_db["file_out"], "LOG You pick up an object.\n")
- elif t == world_db["Things"][0]:
- err = "You try to pick up an object, but there is none."
- strong_write(io_db["file_out"], "LOG " + err + "\n")
+ # Topmostness is actually not defined so far. Picks most nutritious Thing.
+ # 7DRL: Non-player picking up player-dropped consumable -> GOD_FAVOR gain.
+ used_slots = len(t["T_CARRIES"]) # #
+ if used_slots < world_db["ThingTypes"][t["T_TYPE"]]["TT_STORAGE"]: # #
+ ids = [id for id in world_db["Things"] if world_db["Things"][id] != t
+ if not world_db["Things"][id]["carried"]
+ if world_db["Things"][id]["T_POSY"] == t["T_POSY"]
+ if world_db["Things"][id]["T_POSX"] == t["T_POSX"]]
+ if len(ids):
+ highest_id = ids[0]
+ nutritious = 0
+ for id in ids:
+ type = world_db["Things"][id]["T_TYPE"]
+ if world_db["ThingTypes"][type]["TT_CONSUMABLE"] > nutritious:
+ nutritious = world_db["ThingTypes"][type]["TT_CONSUMABLE"]
+ highest_id = id
+ world_db["Things"][highest_id]["carried"] = True
+ if (t != world_db["Things"][0] and # #
+ world_db["Things"][highest_id]["T_PLAYERDROP"]): # #
+ x = world_db["Things"][highest_id]["T_TYPE"]
+ score = world_db["ThingTypes"][x]["TT_CONSUMABLE"] / 32 # #
+ add_gods_favor(score) # #
+ world_db["Things"][highest_id]["T_PLAYERDROP"] = 0 # #
+ t["T_CARRIES"].append(highest_id)
+ if t == world_db["Things"][0]:
+ strong_write(io_db["file_out"], "LOG You pick up an object.\n")
+ elif t == world_db["Things"][0]:
+ err = "You try to pick up an object, but there is none."
+ strong_write(io_db["file_out"], "LOG " + err + "\n")
+ elif t == world_db["Things"][0]: # #
+ strong_write(io_db["file_out"], "LOG Can't pick up object: " + # #
+ "No storage room to carry more.\n") # #
def actor_drop(t):
world_db["Things"][id]["carried"] = False
if t == world_db["Things"][0]:
strong_write(io_db["file_out"], "LOG You drop an object.\n")
+ world_db["Things"][id]["T_PLAYERDROP"] = 1 # #
elif t == world_db["Things"][0]:
err = "You try to drop an object, but you own none."
strong_write(io_db["file_out"], "LOG " + err + "\n")
"LOG You try to use an object, but you own none.\n")
-def thingproliferation(t):
- """To chance of 1/TT_PROLIFERATE, create t offspring in neighbor cell.
+def thingproliferation(t, prol_map):
+ """To chance of 1/TT_PROLIFERATE,create t offspring in open neighbor cell.
- Naturally only works with TT_PROLIFERATE > 0. The neighbor cell must be
- passable and not be inhabited by a Thing of the same type, or, if Thing is
- animate, any other animate Thing. If there are several map cell candidates,
- one is selected randomly.
+ Naturally only works with TT_PROLIFERATE > 0. The neighbor cell must be be
+ marked '.' in prol_map. If there are several map cell candidates, one is
+ selected randomly.
"""
- def test_cell(t, y, x):
- if "." == chr(world_db["MAP"][(y * world_db["MAP_LENGTH"]) + x]):
- for id in [id for id in world_db["Things"]
- if y == world_db["Things"][id]["T_POSY"]
- if x == world_db["Things"][id]["T_POSX"]
- if (t["T_TYPE"] == world_db["Things"][id]["T_TYPE"])
- or (t["T_LIFEPOINTS"] and
- world_db["Things"][id]["T_LIFEPOINTS"])]:
- return False
- return True
- return False
+ # # 7DRL: success increments God's mood
prolscore = world_db["ThingTypes"][t["T_TYPE"]]["TT_PROLIFERATE"]
if prolscore and (1 == prolscore or 1 == (rand.next() % prolscore)):
candidates = []
for dir in [directions_db[key] for key in directions_db]:
mv_result = mv_yx_in_dir_legal(dir, t["T_POSY"], t["T_POSX"])
- if mv_result[0] and test_cell(t, mv_result[1], mv_result[2]):
+ if mv_result[0] and ord('.') == prol_map[mv_result[1]
+ * world_db["MAP_LENGTH"]
+ + mv_result[2]]:
candidates.append((mv_result[1], mv_result[2]))
if len(candidates):
i = rand.next() % len(candidates)
id = id_setter(-1, "Things")
newT = new_Thing(t["T_TYPE"], (candidates[i][0], candidates[i][1]))
world_db["Things"][id] = newT
+ world_db["GOD_MOOD"] += 1 # #
def try_healing(t):
On success, decrease satiation score by 32.
"""
+ # # 7DRL: Successful heals increment God's mood.
if t["T_SATIATION"] > 0 \
and t["T_LIFEPOINTS"] < \
world_db["ThingTypes"][t["T_TYPE"]]["TT_LIFEPOINTS"] \
if world_db["ThingActions"][id]["TA_NAME"] ==
"wait"][0]:
t["T_LIFEPOINTS"] += 1
+ world_db["GOD_MOOD"] += 1 # #
t["T_SATIATION"] -= 32
if t == world_db["Things"][0]:
strong_write(io_db["file_out"], "LOG You heal.\n")
- else:
- name = world_db["ThingTypes"][t["T_TYPE"]]["TT_NAME"]
- strong_write(io_db["file_out"], "LOG " + name + "heals.\n")
def hunger(t):
if int(int(testbase / stomach) / ((rand.next() % stomach) + 1)):
if t == world_db["Things"][0]:
strong_write(io_db["file_out"], "LOG You suffer from hunger.\n")
- else:
- name = world_db["ThingTypes"][t["T_TYPE"]]["TT_NAME"]
- strong_write(io_db["file_out"], "LOG " + name +
- " suffers from hunger.\n")
decrement_lifepoints(t)
"""
def zero_score_map_where_char_on_memdepthmap(c):
- # OUTSOURCED TO libplomrogue.so:
+ # OUTSOURCED FOR PERFORMANCE REASONS TO libplomrogue.so:
# for i in [i for i in range(world_db["MAP_LENGTH"] ** 2)
# if t["T_MEMDEPTHMAP"][i] == mem_depth_c[0]]:
# set_map_score(i, 0)
return False
def set_cells_passable_on_memmap_to_65534_on_scoremap():
- # OUTSOURCED TO libplomrogue.so:
+ # OUTSOURCED FOR PERFORMANCE REASONS TO libplomrogue.so:
# ord_dot = ord(".")
# memmap = t["T_MEMMAP"]
# for i in [i for i in range(world_db["MAP_LENGTH"] ** 2)
none, they will explore parts of the map unseen since ever or for at least
one turn; if there is nothing to explore, they will simply wait.
"""
+ # # 7DRL add: Don't pick up or search things when inventory is full.
t["T_COMMAND"] = [id for id in world_db["ThingActions"]
if world_db["ThingActions"][id]["TA_NAME"] == "wait"][0]
if not get_dir_to_target(t, "f"):
if world_db["ThingActions"][id]["TA_NAME"]
== "use"][0]
t["T_ARGUMENT"] = sel
- elif standing_on_consumable(t):
+ elif standing_on_consumable(t) \
+ and (len(t["T_CARRIES"]) < # #
+ world_db["ThingTypes"][t["T_TYPE"]]["TT_STORAGE"]): # #
t["T_COMMAND"] = [id for id in world_db["ThingActions"]
if world_db["ThingActions"][id]["TA_NAME"]
== "pick_up"][0]
- elif (not get_dir_to_target(t, "c")) and \
+ elif (not
+ (len(t["T_CARRIES"]) < # #
+ world_db["ThingTypes"][t["T_TYPE"]]["TT_STORAGE"] # #
+ and get_dir_to_target(t, "c"))) and \
(not get_dir_to_target(t, "a")):
get_dir_to_target(t, "s")
id = 0
whilebreaker = False
while world_db["Things"][0]["T_LIFEPOINTS"]:
+ proliferable_map = world_db["MAP"][:]
+ for id in [id for id in world_db["Things"]
+ if not world_db["Things"][id]["carried"]]:
+ y = world_db["Things"][id]["T_POSY"]
+ x = world_db["Things"][id]["T_POSX"]
+ proliferable_map[y * world_db["MAP_LENGTH"] + x] = ord('X')
for id in [id for id in world_db["Things"]]: # Only what's from start!
if not id in world_db["Things"] or \
world_db["Things"][id]["carried"]: # May have been consumed or
Thing["T_COMMAND"] = 0
Thing["T_PROGRESS"] = 0
hunger(Thing)
- thingproliferation(Thing)
+ thingproliferation(Thing, proliferable_map)
if whilebreaker:
break
world_db["TURN"] += 1
"T_PROGRESS": 0,
"T_SATIATION": 0,
"T_COMMAND": 0,
+ "T_PLAYERDROP": 0, # #
"T_TYPE": type,
"T_POSY": pos[0],
"T_POSX": pos[1],
def command_quit():
"""Abort server process."""
- save_world()
- atomic_write(io_db["path_record"], io_db["record_chunk"], do_append=True)
+ if None == opts.replay:
+ if world_db["WORLD_ACTIVE"]:
+ save_world()
+ atomic_write(io_db["path_record"], io_db["record_chunk"], do_append=True)
raise SystemExit("received QUIT command")
"""Toggle world_db["WORLD_ACTIVE"] if possible.
An active world can always be set inactive. An inactive world can only be
- set active with a "wait" ThingAction, and a player Thing (of ID 0). On
- activation, rebuild all Things' FOVs, and the player's map memory.
+ set active with a "wait" ThingAction, and a player Thing (of ID 0), and a
+ map. On activation, rebuild all Things' FOVs, and the player's map memory.
"""
- # In original version, map existence was also tested (unnecessarily?).
val = integer_test(worldactive_string, 0, 1)
if val:
if 0 != world_db["WORLD_ACTIVE"]:
if 0 == Thing:
player_exists = True
break
- if wait_exists and player_exists:
+ if wait_exists and player_exists and world_db["MAP"]:
for id in world_db["Things"]:
if world_db["Things"][id]["T_LIFEPOINTS"]:
build_fov_map(world_db["Things"][id])
"TT_LIFEPOINTS": 0,
"TT_PROLIFERATE": 0,
"TT_START_NUMBER": 0,
+ "TT_STORAGE": 0, # #
"TT_SYMBOL": "?",
"TT_CORPSE_ID": id
}
"TT_PROLIFERATE": (1, False, setter("ThingType", "TT_PROLIFERATE",
0, 255)),
"TT_LIFEPOINTS": (1, False, setter("ThingType", "TT_LIFEPOINTS", 0, 255)),
+ "TT_STORAGE": (1, False, setter("ThingType", "TT_STORAGE", 0, 255)), # #
"T_ID": (1, False, command_tid),
"T_ARGUMENT": (1, False, setter("Thing", "T_ARGUMENT", 0, 255)),
"T_PROGRESS": (1, False, setter("Thing", "T_PROGRESS", 0, 255)),
"T_MEMTHING": (3, False, command_tmemthing),
"T_POSY": (1, False, setter_tpos("Y")),
"T_POSX": (1, False, setter_tpos("X")),
+ "T_PLAYERDROP": (1, False, setter("Thing", "T_PLAYERDROP", 0, 1)), # #
"wait": (0, False, play_commander("wait")),
"move": (1, False, play_commander("move")),
"pick_up": (0, False, play_commander("pick_up")),