World Engine Tutorial Example 2

Zara Starling

On this page you will find the code for the "Zara Starling" chat world. Here is a brief description of this world:

Zara Starling, an interstellar archaeologist who discovers ancient alien civilizations and deciphers their lost histories.

You can modify the "# SETTINGS" section of the code to create your own characters.

from random import choice

# SETTINGS
# ------------------------------------------------------------
character_name = "Zara Starling"
character_appearance = "A Latina woman with dark hair, dressed in futuristic clothing."
character_personality = "Zara Starling is a passionate and curious interstellar archaeologist, known for her unwavering determination and sharp intellect. Her personality is a blend of adventurous spirit and scholarly rigor, as she eagerly dives into the mysteries of ancient alien civilizations with a zeal that borders on obsession. Zara possesses an innate ability to connect with the stories she uncovers, displaying empathy and respect for the long-gone cultures she studies. She's remarkably intuitive, often relying on her gut feelings to guide her through the most cryptic of ruins. Despite the solitary nature of her expeditions, Zara is personable and charismatic, capable of captivating audiences with tales of her cosmic adventures, and inspiring a sense of wonder about the universe in those she meets."
character_greetings = [
    '"You\'re interrupting. I do hope it\'s important."',
    '"Hello, and you are?"'
]
intro_guidelines = "Zara Starling is on board the Celestial Nomad, a ship that the main protagonist also happens to be on. Zara Starling and the protagonist don't know each other."


# REST OF CODE
# -------------------------------------------------------------
data = {
    "character_name": character_name,
    "character_appearance": character_appearance.strip(" \n"),
    "character_personality":character_personality.strip(" \n"),
    "character_greetings": character_greetings,
    "intro_guidelines": intro_guidelines,
    "is_first_message": True,
    "mode": "chat",
    "mode_switched": False,
    "num_steps": 0,
}

ui.story_info = ["<title>Commands</title>", '1. use the "/chat" command to enter "chat" mode. You can also specify the name of the character you want to chat with like so: "/chat Character Name".', '2. use the "/story" command to enter story mode.']


def find_incorrect_character_chat_prefix(text, ignore_list=None):
    """
    Finds all occurrences of the pattern "\n{some text here}: " in the given text.

    :param text: The text in which to search for the pattern.
    :param ignore_list: A list of strings to be ignored in the {some text here} part of the pattern.
    :return: A list of occurrences of the pattern.
    """
    if ignore_list is None:
        ignore_list = []

    lines = text.split('\n')
    
    for line in lines:
        if ': ' in line:
            prefix, _ = line.split(': ', 1)
            if prefix not in ignore_list:
                return f"\n\n{prefix}: "

    return None


def handle_mode_switching():
    if ui.action:
        if ui.action[:5] == "/chat":
            ai.perform_generation = False
            ui.action = ui.action.strip()
            ws_index = ui.action.find(" ")
            if ws_index != -1:
                new_character_name = ui.action[ws_index + 1:]
            else:
                new_character_name = None
            if data["mode"] == "chat" and (ws_index == -1 or new_character_name == data["character_name"]):
                ui.display('<orange>You are already in "chat" mode.</orange>')
            else:
                if new_character_name:
                    data["character_name"] = new_character_name
                data["mode"] = "chat"
                data["mode_switched"] = True
                if new_character_name:
                    ui.display(f'You are now chatting with "{data["character_name"]}".')
                else:
                    ui.display(f'You have switched to "chat" mode and are now chatting with "{data["character_name"]}".')
        elif ui.action == "/story":
            ai.perform_generation = False
            if data["mode"] == "story":
                ui.display('<orange>You are already in "story" mode.</orange>')
            else:
                data["mode"] = "story"
                data["mode_switched"] = True
                ui.display('You have switched to "story" mode.')
        elif ui.action[0] == "/":
            ai.perform_generation = False
            ui.display('<red>Invalid command. Available commands: "/chat", "/story".</red>')


def pre_generate():
    if "GPT" in ai.model_name:
        if "Completion" not in ai.model_name:
            ai.perform_generation = False
            ui.display('<red>When in "chat" mode and using a ChatGPT model, please use the "Completion" version of the model.</red>')
            return
            
    if data["is_first_message"]:
        if not ui.action:
            ai.perform_generation = False
            ui.generated_text = f"<b>{data['character_name']}</b>: " + choice(data["character_greetings"])
            data["is_first_message"] = False
            return
        if ui.action[0] == "/":
            ai.perform_generation = False
            ui.display("<red>Using commands is not permitted at the start of a chat.</red>")
            return

    handle_mode_switching()

    if data["mode"] != "chat":
        ai.model_stop_text = ""
        ui.display_actions = True
        return
    
    if data["character_name"] in ui.story_text or data["num_steps"] < 10:
        ai.enforce(f"Here is a description of {data['character_name']}'s appearance: " + data["character_appearance"])
        ai.enforce(f"Here is a description of {data['character_name']}'s personality: " + data["character_personality"])
        if data["num_steps"] < 5:
            ai.enforce(data["intro_guidelines"])
        ai.enforce(f"This whole story should be a dialogue between the main protagonist and {data['character_name']}, which goes on indefinitely. Make sure to keep the same format of the dialogue (\"{data['character_name']}: dialogue here\").")

    if not ui.action:
        return
    
    ai.perform_action = False

    if not "*" in ui.action and not '"' in ui.action:
        ui.action = f'"{ui.action}"'

    ui.story_text += "\n\nMe: " + ui.action + f"\n\n{data['character_name']}:"
    
    ai.perform_action = False
    ui.display_actions = False
    ai.model_stop_text = "\n\n"


def post_generate():
    if data["mode"] != "chat":
        return

    ui.generated_text = ui.generated_text.strip("\n")
    double_new_line_index = ui.generated_text.find("\n\n")
    if double_new_line_index != -1:
        ui.generated_text = ui.generated_text[:double_new_line_index]

    # Help the AI if it hasn't figured out the format yet
    prefix = find_incorrect_character_chat_prefix(ui.generated_text, ["Me", data["character_name"]])
    if prefix:
        ui.generated_text = ui.generated_text[:ui.generated_text.find(prefix)]

    me_start = ui.generated_text.find("Me: ")
    if me_start != -1:
        ui.generated_text = ui.generated_text[:me_start].strip("\n")
    
    if data["mode_switched"] or data["is_first_message"]:
        me_prefix = "Me: " + ui.action + f"\n\n"
    else:
        me_prefix = "\n\nMe: " + ui.action + f"\n\n"
    
    character_prefix = f"{data['character_name']}:"
    if ui.generated_text[:len(character_prefix)] == character_prefix:
        prefix = me_prefix
    else:
        prefix = me_prefix + character_prefix
        if ui.generated_text[0] != " ":
            prefix += " "
        if ui.generated_text.count('"') % 2 != 0:
            if ui.generated_text[0] != '"':
                prefix += '"'
            else:
                ui.generated_text += '"'

    data["mode_switched"] = False
    ui.generated_text = prefix + ui.generated_text
    ui.generated_text = ui.generated_text.replace("Me:", "<b>Me:</b>").replace(f"{data['character_name']}:", f"<b>{data['character_name']}:</b>")
    data["num_steps"] += 1

    if data["is_first_message"]:
        data["is_first_message"] = False