import shlex
import shutil
import time
+import ctypes
+
+
+class RandomnessIO:
+ """"Interface to libplomrogue's pseudo-randomness generator."""
+
+ def set_seed(self, seed):
+ libpr.seed_rrand(1, seed)
+
+ def get_seed(self):
+ return libpr.seed_rrand(0, 0)
+
+ def next(self):
+ return libpr.rrand()
+
+ seed = property(get_seed, set_seed)
+
+
+def prep_library():
+ """Prepare ctypes library at ./libplomrogue.so"""
+ libpath = ("./libplomrogue.so")
+ if not os.access(libpath, os.F_OK):
+ raise SystemExit("No library " + libpath + ", run ./compile.sh first?")
+ libpr = ctypes.cdll.LoadLibrary(libpath)
+ libpr.seed_rrand.argtypes = [ctypes.c_uint8, ctypes.c_uint32]
+ libpr.seed_rrand.restype = ctypes.c_uint32
+ libpr.rrand.argtypes = []
+ libpr.rrand.restype = ctypes.c_uint16
+ return libpr
def strong_write(file, string):
string = string + "T_ID " + str(id) + "\n"
for carried_id in world_db["Things"][id]["T_CARRIES"]:
string = string + "T_CARRIES " + str(carried_id) + "\n"
- string = string + "WORLD_ACTIVE " + str(world_db["WORLD_ACTIVE"])
+ string = string + "SEED_RANDOMNESS " + str(rand.seed) + "\n" + \
+ "WORLD_ACTIVE " + str(world_db["WORLD_ACTIVE"])
atomic_write(io_db["path_save"], string)
# DUMMY so far. Just builds an all-visible map.
+def actor_wait(t):
+ """Make t do nothing (but loudly, if player avatar)."""
+ if t == world_db["Things"][0]:
+ strong_write(io_db["file_out"], "LOG You wait.\n")
+
+
+def actor_move(t):
+ pass
+
+
+def actor_pick_up(t):
+ """Make t pick up (topmost?) Thing from ground into inventory."""
+ # Topmostness is actually not defined so far.
+ 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):
+ world_db["Things"][ids[0]]["carried"] = True
+ t["T_CARRIES"].append(ids[0])
+ 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")
+
+
+def actor_drop(t):
+ """Make t rop Thing from inventory to ground indexed by T_ARGUMENT."""
+ # TODO: Handle case where T_ARGUMENT matches nothing.
+ if len(t["T_CARRIES"]):
+ id = t["T_CARRIES"][t["T_ARGUMENT"]]
+ t["T_CARRIES"].remove(id)
+ world_db["Things"][id]["carried"] = False
+ if t == world_db["Things"][0]:
+ strong_write(io_db["file_out"], "LOG You drop an object.\n")
+ 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")
+
+
+def actor_use(t):
+ """Make t use (for now: consume) T_ARGUMENT-indexed Thing in inventory."""
+ # Original wrongly featured lifepoints increase through consumable!
+ # TODO: Handle case where T_ARGUMENT matches nothing.
+ if len(t["T_CARRIES"]):
+ id = t["T_CARRIES"][t["T_ARGUMENT"]]
+ type = world_db["Things"][id]["T_TYPE"]
+ if world_db["ThingTypes"][type]["TT_CONSUMABLE"]:
+ t["T_CARRIES"].remove(id)
+ del world_db["Things"][id]
+ t["T_SATIATION"] += world_db["ThingTypes"][type]["TT_CONSUMABLE"]
+ strong_write(io_db["file_out"], "LOG You consume this object.\n")
+ else:
+ strong_write(io_db["file_out"], "LOG You try to use this object," +
+ "but fail.\n")
+ else:
+ strong_write(io_db["file_out"], "LOG You try to use an object, but " +
+ "you own none.\n")
+
+
def turn_over():
"""Run game world and its inhabitants until new player input expected."""
id = 0
- print("turning over")
whilebreaker = False
while world_db["Things"][0]["T_LIFEPOINTS"]:
for id in [id for id in world_db["Things"]
- if not world_db["Things"][id]["carried"]
- if world_db["Things"][id]["T_LIFEPOINTS"]]:
- print(str(id))
+ if world_db["Things"][id]["T_LIFEPOINTS"]]:
Thing = world_db["Things"][id]
if Thing["T_LIFEPOINTS"]:
- print(" evaluating thing")
if not Thing["T_COMMAND"]:
- print(" thing needs new command")
update_map_memory(Thing)
if 0 == id:
whilebreaker = True
break
# DUMMY: ai(thing)
- print(" run AI")
Thing["T_COMMAND"] = 1
# DUMMY: try_healing
Thing["T_PROGRESS"] += 1
if a == Thing["T_COMMAND"]][0]
ThingAction = world_db["ThingActions"][taid]
if Thing["T_PROGRESS"] == ThingAction["TA_EFFORT"]:
- print(" running thing action")
- # run_thing_action(action["TA_NAME"])
+ eval("actor_" + ThingAction["TA_NAME"])(Thing)
Thing["T_COMMAND"] = 0
Thing["T_PROGRESS"] = 0
# DUMMY: hunger
# DUMMY: thingproliferation
if whilebreaker:
break
- print(" turn finished")
world_db["TURN"] += 1
- print(" new turn " + str(world_db["TURN"]))
def new_Thing(type):
"""Write to out file list of Things known to player at coordinate y, x."""
def write_thing_if_here():
if y == world_db["Things"][id]["T_POSY"] \
- and x == world_db["Things"][id]["T_POSX"]:
+ and x == world_db["Things"][id]["T_POSX"] \
+ and not world_db["Things"][id]["carried"]:
type = world_db["Things"][id]["T_TYPE"]
name = world_db["ThingTypes"][type]["TT_NAME"]
strong_write(io_db["file_out"], name + "\n")
return set_command
+def command_seedrandomness(seed_string):
+ """Set rand seed to int(seed_string)."""
+ val = integer_test(seed_string, 0, 4294967295)
+ if None != val:
+ rand.seed = val
+ else:
+ print("Ignoring: Value must be integer >= 0, <= 4294967295.")
+
+
def command_seedmap(seed_string):
"""Set world_db["SEED_MAP"] to int(seed_string), then (re-)make map."""
setter(None, "SEED_MAP", 0, 4294967295)(seed_string)
def command_makeworld(seed_string):
"""(Re-)build game world, i.e. map, things, to a new turn 1 from seed.
- Make seed world_db["SEED_RANDOMNESS"] and world_db["SEED_MAP"]. Do more
- only with a "wait" ThingAction and world["PLAYER_TYPE"] matching ThingType
- of TT_START_NUMBER > 0. Then, world_db["Things"] emptied, call remake_map()
+ Seed rand with seed, fill it into world_db["SEED_MAP"]. Do more only with a
+ "wait" ThingAction and world["PLAYER_TYPE"] matching ThingType of
+ TT_START_NUMBER > 0. Then, world_db["Things"] emptied, call remake_map()
and set world_db["WORLD_ACTIVE"], world_db["TURN"] to 1. Build new Things
according to ThingTypes' TT_START_NUMBERS, with Thing of ID 0 to ThingType
of ID = world["PLAYER_TYPE"]. Place Things randomly, and actors not on each
other. Init player's memory map. Write "NEW_WORLD" line to out file.
"""
- setter(None, "SEED_RANDOMNESS", 0, 4294967295)(seed_string)
- setter(None, "SEED_MAP", 0, 4294967295)(seed_string)
+ val = integer_test(seed_string, 0, 4294967295)
+ if None == val:
+ print("Ignoring: Value must be integer >= 0, <= 4294967295.")
+ return
+ rand.seed = val
+ world_db["SEED_MAP"] = val
player_will_be_generated = False
playertype = world_db["PLAYER_TYPE"]
for ThingType in world_db["ThingTypes"]:
"THINGS_HERE": (2, True, command_thingshere),
"MAKE_WORLD": (1, False, command_makeworld),
"SEED_MAP": (1, False, command_seedmap),
- "SEED_RANDOMNESS": (1, False, setter(None, "SEED_RANDOMNESS",
- 0, 4294967295)),
+ "SEED_RANDOMNESS": (1, False, command_seedrandomness),
"TURN": (1, False, setter(None, "TURN", 0, 65535)),
"PLAYER_TYPE": (1, False, setter(None, "PLAYER_TYPE", 0, 255)),
"MAP_LENGTH": (1, False, command_maplength),
}
-"""World state database. With sane default values."""
+"""World state database. With sane default values. (Randomness is in rand.)"""
world_db = {
"TURN": 0,
"SEED_MAP": 0,
- "SEED_RANDOMNESS": 0,
"PLAYER_TYPE": 0,
"MAP_LENGTH": 64,
"WORLD_ACTIVE": 0,
try:
+ libpr = prep_library()
+ rand = RandomnessIO()
opts = parse_command_line_arguments()
setup_server_io()
if None != opts.replay: