silent-frontier / main.py
mkhi238's picture
Apply gitignore, add app.py, stop tracking db and env
345e21b
Raw
History Blame Contribute Delete
3.91 kB
from retriever import FAISSRetriever
from constraints import ConstraintChecker
from agent import NPCAgent, check_duplicates, candidate_generator
from character import NPCNode
from config import lore_data, INDEX_PATH, MAX_ATTEMPTS, CLUE_THRESHOLD, MAX_MESSAGES_BEFORE_CLUE, configure_lm
configure_lm()
agent = NPCAgent()
retriever = FAISSRetriever(index_dir=INDEX_PATH)
checker = ConstraintChecker(lore_data)
# instantiate NPC
orion = NPCNode.from_lore(lore_data, "Commander Orion")
sorel = NPCNode.from_lore(lore_data, "Admiral Sorel")
lira = NPCNode.from_lore(lore_data, "Lira Dawn")
shade7 = NPCNode.from_lore(lore_data, "Shade-7")
ren = NPCNode.from_lore(lore_data, "Ren Ashford")
elandra = NPCNode.from_lore(lore_data, "Sage Elandra")
warden = NPCNode.from_lore(lore_data, "The Warden")
orion.clear_memory()
sorel.clear_memory()
lira.clear_memory()
shade7.clear_memory()
ren.clear_memory()
elandra.clear_memory()
warden.clear_memory()
orion.next_npc = sorel
sorel.next_npc = lira
lira.next_npc = shade7
shade7.next_npc = ren
ren.next_npc = elandra
elandra.next_npc = warden
warden.next_npc = None
orion.clue_topic = "Silent Frontier Expedition"
sorel.clue_topic = "why the expedition was authorized"
lira.clue_topic = "navigational data route"
shade7.clue_topic = "what the expedition found"
ren.clue_topic = "Vorne's Log"
elandra.clue_topic = "Echo Prism memory fragment"
warden.clue_topic = "Resonance Point structure"
npc_map = {
"Commander Orion": orion,
"Admiral Sorel": sorel,
"Lira Dawn": lira,
"Shade-7": shade7,
"Ren Ashford": ren,
"Sage Elandra": elandra,
"The Warden": warden
}
print("NPCs available:", ", ".join(npc_map.keys()))
npc_choice = input("Who do you want to speak to? > ")
npc = npc_map.get(npc_choice, orion)
clue_unlocked = False
while True:
player_input = input("What do you say to the NPC? > ")
if player_input.lower() in ["quit", "exit", "q"]:
break
game_state = npc.build_game_state(player_input)
state_results = retriever.retrieve(game_state, k=3)
npc_results = retriever.retrieve(npc.name, k=2)
retrieved = state_results + npc_results
unique_ret = check_duplicates(retrieved)
lore_context = " ".join([retriever.flatten_entry(r) for r in unique_ret])
if npc.clue and not clue_unlocked:
similarity = retriever.measure_clue_similarity(player_input, npc.clue_topic)
clue_unlocked = True if (similarity > CLUE_THRESHOLD or npc.message_count >= MAX_MESSAGES_BEFORE_CLUE) else False
npc_secret = f"Topic: {npc.clue_topic}. Secret: {npc.clue}" if clue_unlocked else f"Steer conversation toward: {npc.clue_topic} without revealing details yet."
for attempt in range(MAX_ATTEMPTS):
results = agent(
game_state=game_state,
lore_context=lore_context,
npc_name=npc.name,
npc_personality=f"Speaking style: {npc.speaking_style}; Personality: {npc.personality}",
npc_secret= npc_secret,
next_npc = npc.next_npc.name if (clue_unlocked and npc.next_npc) else ""
)
generator = candidate_generator(results, checker, npc.name)
found_pass = False
best, best_ruling, best_justification, best_flags = None, None, None, None
#lazy evaluation on candidate strings
for candidate, ruling, justification, flags in generator:
if ruling.strip().upper() == "PASS":
best, best_ruling, best_justification, best_flags = candidate, ruling, justification, flags
found_pass = True
break
if best is None or len(flags) < len(best_flags):
best = candidate
best_ruling = ruling
best_justification = justification
best_flags = flags
if found_pass: break
npc.store_exchange(player_input, best.dialogue)
print("DIALOGUE:", best.dialogue)
#print("REASONING:", best.reasoning)
#print("RULING:", best_ruling)
#print("JUSTIFICATION:", best_justification)
#print("FLAGS:", best_flags)