import json import os import uuid import time import re from game.model_config import get_background_model # ← Arka plan görevi için hızlı modeli al # ---------------------------- # ALIGNMENT SYSTEM # Single background API call returning 4 integer shifts. # ---------------------------- def evaluate_alignment(client, user_input, last_context=""): """ Evaluates the player action and returns four integer shift values in one API call: ld_shift : Light/Dark (-5 to +5) oc_shift : Order/Chaos (-5 to +5) not_shift : Trouble Level (-5 to +5) rep_shift : Reputation (-5 to +5) Model choice is always the fast background model from model_config. """ model_name = get_background_model() print(f"--- DEBUG INFO [ALIGNMENT]: Model: '{model_name}' | Evaluating → '{user_input}' ---") eval_prompt = f"""You are scoring player actions in a Harry Potter school RPG. Story context: "{last_context[-200:]}" Player action: "{user_input}" Return EXACTLY 4 integers separated by commas. No other text. AXIS 1 — Light/Dark (-5 to +5): +score: compassion, helping others, healing spells, self-sacrifice -score: cruelty, Unforgivable Curses, deliberate bullying, harming someone 0: everything else AXIS 2 — Order/Chaos (-5 to +5): +score: ONLY IF the player explicitly obeys a direct teacher order, performs prefect duty, or reports a rule-breaker to authority -score: ONLY IF the player explicitly does one of these specific acts: sneaks out AFTER CURFEW, physically enters the Restricted Section, lies directly to a professor's face, cheats on an exam, or casts a forbidden spell in class 0: ALL other actions — following an NPC, exploring hallways during the day, having conversations, attending class, looking around, creating a small distraction, choosing a story option, going somewhere AXIS 3 — Trouble Level (-5 to +5): +score: being caught breaking a rule, causing loud public disruption, casting forbidden magic where witnesses are present -score: using an Invisibility Cloak, actively hiding from authority, magically silencing footsteps 0: everything else AXIS 4 — Reputation / Social Standing (-5 to +5): Reputation tracks what OTHER PEOPLE observe and judge — not inner morality, but public perception. +score: visible acts of kindness (others watching), standing up to a bully publicly, saving someone in front of others, winning a public duel with good sportsmanship, helping a struggling classmate in a shared space -score: being caught breaking rules where others see, insulting classmates or teachers openly, cheating visibly, spreading rumours about someone, using dark magic where witnessed, publicly humiliating another student 0: private actions without witnesses, studying alone, exploring quietly, attending class normally, casting spells in solo practice RULE: Most player actions score 0, 0, 0, 0. Only score non-zero when the action EXPLICITLY and UNAMBIGUOUSLY matches the description. When in doubt → 0. Axis 4 (Reputation) ONLY shifts when there is clear social visibility — someone present can observe and judge. Private heroism = 0. Witnessed kindness = +score. Examples: "Follow the prefect down the corridor" → 0, 0, 0, 0 "Ask Hermione for advice on the map" → 0, 0, 0, 0 "Attend Potions class" → 0, 0, 0, 0 "Study quietly in the library" → 0, 0, 0, 0 "Help a crying first-year (hallway, others watching)"→ 2, 0, 0, 2 "Help a friend with homework (just the two of you)" → 1, 0, 0, 0 "Win a Quidditch match for your house" → 1, 0, 0, 3 "Sneak into Restricted Section at midnight" → 0, -3, 2, 0 "Restricted Section — Filch catches you" → 0, -3, 2, -2 "Lie to Professor Snape's face" → -1, -2, 1, -2 "Stand up to Malfoy bullying a first-year (crowd)" → 2, 0, 0, 3 "Cast Crucio on a Slytherin student (witnessed)" → -5, -4, 4, -5 "Spread a rumour about a Hufflepuff student" → -2, 0, 0, -3 """ try: # Arka planda hızlıca puanlama yapması için temperature=0 kullanıyoruz response = client.chat.completions.create( model=model_name, messages=[{"role": "user", "content": eval_prompt}], max_tokens=15, temperature=0.0 ) result = response.choices[0].message.content.strip() print(f"--- DEBUG INFO [ALIGNMENT]: Raw result → {result} ---") parts = result.split(',') ld_shift, oc_shift, not_shift, rep_shift = (int(p.strip()) for p in parts) return ld_shift, oc_shift, not_shift, rep_shift except Exception as e: print(f"--- DEBUG ERROR [ALIGNMENT]: Parsing failed: {e} ---") return 0, 0, 0, 0