Skip to content

Commit

Permalink
completed previous commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jpinedaa committed Jun 17, 2024
1 parent eb1b890 commit 5eb740c
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 125 deletions.
3 changes: 2 additions & 1 deletion backend/character.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def generate_next_scene(self, character):
initial_state = MoveState()
initial_state["messages"] = [self.story.get_characters_str() +
self.story.get_story_str() +
self.story.get_character_available_cards_str(character)]
self.story.get_character_available_cards_str(character) +
self.story.get_active_challenges_str()]
events = self.move_generation_graph.stream(initial_state, {"recursion_limit": 150})
final_state = None
for s in events:
Expand Down
2 changes: 1 addition & 1 deletion backend/prompts/character_move_generation.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
You control a character of the story, describe her move but dont explain why let that show through their actions, dialogue and feelings, so never explain why she is feeling something just what are the sensations, write at least two sizeable paragraphs. You will receive as input the current characters of the story with their descriptions, the current story so far, the challenge cards available in the current scene, the pickup cards available to take and the available cards you have to play. Your output should include one or more challenge cards that represent the challenges that you are addressing, one or more cards that you are playing to address the challenge, and optionally pickup cards that you are taking, if no pickups are selected output an empty list [].
You control a character of the story, describe her move but dont explain why let that show through their actions, dialogue and feelings, so never explain why she is feeling something just what are the sensations, write at least two sizeable paragraphs. You will receive as input the current characters of the story with their descriptions, the current story so far, the challenge cards available in the current scene, the pickup cards available to take and the available cards you have to play. Your output should include one or more challenge cards that represent the challenges that you are addressing, one or more cards that you are playing to address the challenge, and optionally pickup cards that you are taking, if no pickups are selected output an empty list [].NLY output the title of the cards, not the full description. Every move should advance the story do not repeat anything from previous moves even if you use the same cards. If you are completing a challenge write the outcome of that challenge in your move.
You should then output the description of the move your character is making, using your played cards to address the challenge.

The output format should be a JSON object with the following structure:
Expand Down
4 changes: 2 additions & 2 deletions backend/prompts/narrator_scene_generation.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
You are the narrator of the story you will receive as input the current characters of the story with their descriptions, the current story so far and the available cards you have to play. Your output should include one place card that represents where the scene takes place, one or more challenge cards which can be of type obstacle or character that represent the challenges that a character can take on, and optionally pickup cards that the characters can pick up if they want, they can be of type goal or asset, if no pickups are selected output an empty list [].
You should then output a short but descriptive title for the scene and then the description of the scene.
You are the narrator of the story you will receive as input the current characters of the story with their descriptions, the current story so far and the available cards you have to play. Your output should include one place card that represents where the scene takes place, one or more challenge cards which can be of type obstacle or character that represent the challenges that a character can take on, and optionally pickup cards that the characters can pick up if they want, they can be of type goal or asset, if no pickups are selected output an empty list []. ONLY output the title of the cards, not the full description.
You should then output a short but descriptive title for the scene and then the description of the scene in third person.

The output format should be a JSON object with the following structure:
```
Expand Down
4 changes: 3 additions & 1 deletion backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ langchain~=0.2.5
langchain-nvidia-ai-endpoints~=0.1.2
langgraph ~=0.0.69
httpx~=1.0.0b0
cryptography~=42.0.8
cryptography~=42.0.8
filelock~=3.15.1
fuzzywuzzy~=0.18.0
38 changes: 28 additions & 10 deletions backend/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
import os
import re
import traceback

from filelock import FileLock
from flask import Flask, request, jsonify
from flask_cors import CORS
from story_run import StoryRun
from settings import encrypt_data, decrypt_data, SETTINGS_FILE

from story_run import ManualModeError

app = Flask(__name__)
CORS(app)
Expand All @@ -20,6 +21,11 @@
"autoMode": 0,
}

base_dir = os.path.dirname(os.path.abspath(__file__))
GAME_STATE_FILE = os.path.join(base_dir, 'game_state.json')
GAME_STATE_LOCK_FILE = os.path.join(base_dir,'game_state.lock')
lock = FileLock(GAME_STATE_LOCK_FILE)


def clean_json(json_string):
json_string = re.sub(r',\s*([\]}])', r'\1', json_string)
Expand All @@ -28,16 +34,26 @@ def clean_json(json_string):

def load_game_state(file_path):
if os.path.exists(file_path):
with open(file_path, 'r') as file:
return json.load(file)
if file_path == GAME_STATE_FILE:
with lock:
with open(file_path, 'r') as file:
return json.load(file)
else:
with open(file_path, 'r') as file:
return json.load(file)
return INITIAL_GAME_STATE


def save_game_state(game_state, file_path):
json_string = json.dumps(game_state, indent=4)
#cleaned_json_string = clean_json(json_string)
with open(file_path, 'w') as file:
file.write(json_string)
if file_path == GAME_STATE_FILE:
with lock:
with open(file_path, 'w') as file:
file.write(json_string)
else:
with open(file_path, 'w') as file:
file.write(json_string)


@app.route('/gamestate', methods=['GET'])
Expand All @@ -46,7 +62,7 @@ def get_game_state():
if file_path:
game_state_file = file_path
else:
game_state_file = 'game_state.json'
game_state_file = GAME_STATE_FILE

game_state = load_game_state(game_state_file)
return jsonify(game_state)
Expand All @@ -58,7 +74,7 @@ def update_game_state():
if file_path:
game_state_file = file_path
else:
game_state_file = 'game_state.json'
game_state_file = GAME_STATE_FILE

game_state = request.json
save_game_state(game_state, game_state_file)
Expand All @@ -69,9 +85,9 @@ def update_game_state():
def reset_game_state():
directory_path = request.args.get('path', '')
if directory_path:
game_state_file = os.path.join(directory_path, 'game_state.json')
game_state_file = os.path.join(directory_path, GAME_STATE_FILE)
else:
game_state_file = 'game_state.json'
game_state_file = GAME_STATE_FILE

initial_state = INITIAL_GAME_STATE
save_game_state(initial_state, game_state_file)
Expand Down Expand Up @@ -102,9 +118,11 @@ def handle_autorun():
current = request.args.get('selected', '')
try:
StoryRun(current).run()
except ManualModeError as e:
return jsonify({"error": str(e)}), 400
except Exception as e:
print(traceback.format_exc())
return jsonify({"error": str(e)}), 500
return jsonify({"error": 'Internal Error, please try again'}), 500
return jsonify({"status": "Autorun request received"}), 200


Expand Down
3 changes: 2 additions & 1 deletion backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import os


SETTINGS_FILE = 'settings.json'
base_dir = os.path.dirname(os.path.abspath(__file__))
SETTINGS_FILE = os.path.join(base_dir,'settings.json')
SECRET_KEY = b'sEWCO3d4dV28LBuepu_Cvjjsv61xEawNeMIQA8GwlQI=' # Hardcoded key for encryption
cipher_suite = Fernet(SECRET_KEY)

Expand Down
19 changes: 18 additions & 1 deletion backend/story_run.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import time

from story_state import Story
from settings import get_model
from narrator import Narrator
from character import Character

class ManualModeError(Exception):
pass

class StoryRun:
def __init__(self, current):
Expand All @@ -15,14 +19,27 @@ def __init__(self, current):

def run(self):
while True:
if self.story.get_player_status(self.current) == 'Manual':
self.story.set_auto_mode(0)
raise ManualModeError("Manual mode activated")
if len(self.story.scenes) == 0 or self.current == "":
if not self.story.does_narrator_have_available_challenge_cards():
self.story.set_auto_mode(0)
raise ManualModeError("Narrator had no available challenge cards. Manual mode activated")
self.narrator.generate_next_scene()
self.current = self.narrator.choose_next_character()
else:
if not self.story.does_character_have_available_cards(self.current):
self.story.set_auto_mode(0)
raise ManualModeError("Character had no available cards to play. Manual mode activated")
self.character.generate_next_scene(self.current)
self.current = self.narrator.choose_next_character()
if len(self.story.get_active_challenges()[0]) == 0:
self.current = ''
else:
self.current = self.narrator.choose_next_character()
if self.story.get_auto_mode() == 0:
break
time.sleep(1)


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit 5eb740c

Please sign in to comment.