X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=roguelike-server;h=30f9337d0c2287b912ffc05b436e270cfdd1ef59;hb=fc0fedeaa7cee764f7f65d09a88bc2d7603e98cb;hp=bd3ab104da977ddadc359214b8e190def2d6cb23;hpb=bd7aea84a41b3ece88ffeff75b3e99023a3ca859;p=plomrogue diff --git a/roguelike-server b/roguelike-server index bd3ab10..30f9337 100755 --- a/roguelike-server +++ b/roguelike-server @@ -786,16 +786,15 @@ def get_dir_to_target(t, filter): The path-wise nearest target is chosen, via the shortest available path. Target must not be t. On succcess, return positive value, else False. Filters: - "a": Thing in FOV is below a certain distance, animate, but of ThingType - that is not t's, and starts out weaker than t is; build path as - avoiding things of t's ThingType - "f": neighbor cell (not inhabited by any animate Thing) further away from - animate Thing not further than x steps away and in FOV and of a - ThingType that is not t's, and starts out stronger or as strong as t - is currently; or (cornered), if no such flight cell, but Thing of - above criteria is too near,1 a cell closer to it, or, if less near, - just wait - "c": Thing in memorized map is consumable + "a": Thing in FOV is animate, but of ThingType, starts out weaker than t + is, and its corpse would be healthy food for t + "f": move away from an enemy – any visible actor whose thing type has more + TT_LIFEPOINTS than t LIFEPOINTS, and might find t's corpse healthy + food – if it is closer than n steps, where n will shrink as t's hunger + grows; if enemy is too close, move towards (attack) the enemy instead; + if no fleeing is possible, nor attacking useful, wait; don't tread on + non-enemies for fleeing + "c": Thing in memorized map is consumable of sufficient nutrition for t "s": memory map cell with greatest-reachable degree of unexploredness """ @@ -809,6 +808,11 @@ def get_dir_to_target(t, filter): raise RuntimeError("No score map allocated for " "zero_score_map_where_char_on_memdepthmap().") + def set_map_score_at_thingpos(id, score): + pos = world_db["Things"][id]["T_POSY"] * world_db["MAP_LENGTH"] \ + + world_db["Things"][id]["T_POSX"] + set_map_score(pos, score) + def set_map_score(pos, score): test = libpr.set_map_score(pos, score) if test: @@ -820,20 +824,44 @@ def get_dir_to_target(t, filter): raise RuntimeError("No score map allocated for get_map_score().") return result + def animate_in_fov(Thing): + if Thing["carried"] or Thing == t or not Thing["T_LIFEPOINTS"]: + return False + pos = Thing["T_POSY"] * world_db["MAP_LENGTH"] + Thing["T_POSX"] + if ord("v") == t["fovmap"][pos]: + return True + + def good_attack_target(v): + eat_cost = eat_vs_hunger_threshold(t["T_TYPE"]) + type = world_db["ThingTypes"][v["T_TYPE"]] + type_corpse = world_db["ThingTypes"][type["TT_CORPSE_ID"]] + if t["T_LIFEPOINTS"] > type["TT_LIFEPOINTS"] \ + and type_corpse["TT_TOOL"] == "food" \ + and type_corpse["TT_TOOLPOWER"] > eat_cost: + return True + return False + + def good_flee_target(m): + own_corpse_id = world_db["ThingTypes"][t["T_TYPE"]]["TT_CORPSE_ID"] + corpse_type = world_db["ThingTypes"][own_corpse_id] + targetness = 0 if corpse_type["TT_TOOL"] != "food" \ + else corpse_type["TT_TOOLPOWER"] + type = world_db["ThingTypes"][m["T_TYPE"]] + if t["T_LIFEPOINTS"] < type["TT_LIFEPOINTS"] \ + and targetness > eat_vs_hunger_threshold(m["T_TYPE"]): + return True + return False + def seeing_thing(): - if t["fovmap"] and ("a" == filter or "f" == filter): + if t["fovmap"] and "a" == filter: + for id in world_db["Things"]: + if animate_in_fov(world_db["Things"][id]): + if good_attack_target(world_db["Things"][id]): + return True + elif t["fovmap"] and "f" == filter: for id in world_db["Things"]: - Thing = world_db["Things"][id] - if Thing != t and Thing["T_LIFEPOINTS"] and \ - t["T_TYPE"] != Thing["T_TYPE"] and \ - 'v' == chr(t["fovmap"][(Thing["T_POSY"] - * world_db["MAP_LENGTH"]) - + Thing["T_POSX"]]): - ThingType = world_db["ThingTypes"][Thing["T_TYPE"]] - if ("f" == filter and ThingType["TT_LIFEPOINTS"] >= - t["T_LIFEPOINTS"]) \ - or ("a" == filter and ThingType["TT_LIFEPOINTS"] < - t["T_LIFEPOINTS"]): + if animate_in_fov(world_db["Things"][id]): + if good_flee_target(world_db["Things"][id]): return True elif t["T_MEMMAP"] and "c" == filter: eat_cost = eat_vs_hunger_threshold(t["T_TYPE"]) @@ -867,28 +895,14 @@ def get_dir_to_target(t, filter): set_cells_passable_on_memmap_to_65534_on_scoremap() if "a" == filter: for id in world_db["Things"]: - Thing = world_db["Things"][id] - pos = Thing["T_POSY"] * world_db["MAP_LENGTH"] \ - + Thing["T_POSX"] - if t != Thing and Thing["T_LIFEPOINTS"] and \ - t["T_TYPE"] != Thing["T_TYPE"] and \ - ord_v == t["fovmap"][pos] and \ - t["T_LIFEPOINTS"] > \ - world_db["ThingTypes"][Thing["T_TYPE"]]["TT_LIFEPOINTS"]: - set_map_score(pos, 0) - elif t["T_TYPE"] == Thing["T_TYPE"]: - set_map_score(pos, 65535) + if animate_in_fov(world_db["Things"][id]) \ + and good_attack_target(world_db["Things"][id]): + set_map_score_at_thingpos(id, 0) elif "f" == filter: - for id in [id for id in world_db["Things"] - if world_db["Things"][id]["T_LIFEPOINTS"]]: - Thing = world_db["Things"][id] - pos = Thing["T_POSY"] * world_db["MAP_LENGTH"] \ - + Thing["T_POSX"] - if t["T_TYPE"] != Thing["T_TYPE"] and \ - ord_v == t["fovmap"][pos] and \ - t["T_LIFEPOINTS"] <= \ - world_db["ThingTypes"][Thing["T_TYPE"]]["TT_LIFEPOINTS"]: - set_map_score(pos, 0) + for id in world_db["Things"]: + if animate_in_fov(world_db["Things"][id]) \ + and good_flee_target(world_db["Things"][id]): + set_map_score_at_thingpos(id, 0) elif "c" == filter: eat_cost = eat_vs_hunger_threshold(t["T_TYPE"]) for mt in [mt for mt in t["T_MEMTHING"] @@ -901,6 +915,16 @@ def get_dir_to_target(t, filter): set_map_score(mt[1] * world_db["MAP_LENGTH"] + mt[2], 0) elif "s" == filter: zero_score_map_where_char_on_memdepthmap(mem_depth_c[0]) + if "a" != filter: + for id in world_db["Things"]: + if animate_in_fov(world_db["Things"][id]): + if "f" == filter: + pos = world_db["Things"][id]["T_POSY"] \ + * world_db["MAP_LENGTH"] \ + + world_db["Things"][id]["T_POSX"] + if 0 == get_map_score(pos): + continue + set_map_score_at_thingpos(id, 65535) def rand_target_dir(neighbors, cmp, dirs): candidates = [] @@ -925,19 +949,6 @@ def get_dir_to_target(t, filter): dirs = "edcxsw" eye_pos = t["T_POSY"] * world_db["MAP_LENGTH"] + t["T_POSX"] neighbors = get_neighbor_scores(dirs, eye_pos) - if "f" == filter: - inhabited = [world_db["Things"][id]["T_POSY"] - * world_db["MAP_LENGTH"] - + world_db["Things"][id]["T_POSX"] - for id in world_db["Things"] - if world_db["Things"][id]["T_LIFEPOINTS"]] - for i in range(len(dirs)): - mv_yx_in_dir_legal(dirs[i], t["T_POSY"], t["T_POSX"]) - pos_cmp = libpr.result_y() * world_db["MAP_LENGTH"] \ - + libpr.result_x() - for pos in [pos for pos in inhabited if pos == pos_cmp]: - neighbors[i] = 65535 - break minmax_start = 0 if "f" == filter else 65535 - 1 minmax_neighbor = minmax_start for i in range(len(dirs)): @@ -948,19 +959,23 @@ def get_dir_to_target(t, filter): if minmax_neighbor != minmax_start: dir_to_target = rand_target_dir(neighbors, minmax_neighbor, dirs) if "f" == filter: + distance = get_map_score(eye_pos) + fear_distance = world_db["MAP_LENGTH"] + if t["T_SATIATION"] < 0 and math.sqrt(-t["T_SATIATION"]) > 0: + fear_distance = fear_distance / math.sqrt(-t["T_SATIATION"]) + attack_distance = 1 if not dir_to_target: - if 1 == get_map_score(eye_pos): - dir_to_target = rand_target_dir(neighbors, 0, dirs) - elif 3 >= get_map_score(eye_pos): + if attack_distance >= distance: + dir_to_target = rand_target_dir(neighbors, + distance - 1, dirs) + elif fear_distance >= distance: t["T_COMMAND"] = [id for id in world_db["ThingActions"] if world_db["ThingActions"][id]["TA_NAME"] == "wait"][0] return 1 - elif dir_to_target and 3 < get_map_score(eye_pos): + elif dir_to_target and fear_distance < distance: dir_to_target = 0 - elif "a" == filter and 10 <= get_map_score(eye_pos): - dir_to_target = 0 return dir_to_target dir_to_target = False @@ -1019,32 +1034,27 @@ def get_inventory_slot_to_consume(t): def ai(t): - """Determine next command/argment for actor t via AI algorithms. - - AI will look for, and move towards, enemies (animate Things not of their - own ThingType); if they see none, they will consume consumables in their - inventory; if there are none, they will pick up what they stand on if they - stand on consumables; if they stand on none, they will move towards the - next consumable they see or remember on the map; if they see or remember - 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. - """ + """Determine next command/argment for actor t via AI algorithms.""" 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"): - sel = get_inventory_slot_to_consume(t) - if -1 != sel: - t["T_COMMAND"] = [id for id in world_db["ThingActions"] - if world_db["ThingActions"][id]["TA_NAME"] - == "use"][0] - t["T_ARGUMENT"] = sel - elif standing_on_food(t): + if get_dir_to_target(t, "f"): + return + sel = get_inventory_slot_to_consume(t) + if -1 != sel: + t["T_COMMAND"] = [id for id in world_db["ThingActions"] + if world_db["ThingActions"][id]["TA_NAME"] + == "use"][0] + t["T_ARGUMENT"] = sel + elif standing_on_food(t): 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 \ - (not get_dir_to_target(t, "a")): - get_dir_to_target(t, "s") + else: + going_to_known_food_spot = get_dir_to_target(t, "c") + if not going_to_known_food_spot: + aiming_for_walking_food = get_dir_to_target(t, "a") + if not aiming_for_walking_food: + get_dir_to_target(t, "s") def turn_over():