This video shows how to create a dungeon and dragon game with help of local models with Ollama easily.
Code:
conda create -n ai python=3.10 -y && conda activate ai
mkdir mygame && cd mygame 
pip install pydantic==2.8.2 gradio==4.44.1 ollama 
system_prompt = f"""
Your job is to help create interesting futuristic worlds that \
players would love to explore.
Instructions:
- Only generate in plain text without formatting.
- Use simple clear language without being overly technical.
- You must stay below 3-5 sentences for each description.
"""
world_prompt = f"""
Generate a creative description for a unique futuristic world with an
interesting concept around humans colonizing new planets in a distant galaxy.
Output content in the form:
World Name: <WORLD NAME>
World Description: <WORLD DESCRIPTION>
World Name:"""
import os
import json
from ollama import chat
from ollama import ChatResponse
response: ChatResponse = chat(model='llama3.2',
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": world_prompt}
    ]
)
world_output = response['message']['content']
print(world_output)
world_output = world_output.strip()
world = {
    "name": world_output.split('\n')[0].strip()
    .replace('World Name: ', ''),
    "description": '\n'.join(world_output.split('\n')[1:])
    .replace('World Description:', '').strip()
}
kingdom_prompt = f"""
Create 3 different colonies for a futuristic world.
For each colony describe the leaders, societal structures, and notable achievements.
Output content in the form:
Colony 1 Name: <COLONY NAME>
Colony 1 Description: <COLONY DESCRIPTION>
Colony 2 Name: <COLONY NAME>
Colony 2 Description: <COLONY DESCRIPTION>
Colony 3 Name: <COLONY NAME>
Colony 3 Description: <COLONY DESCRIPTION>
World Name: {world['name']}
World Description: {world['description']}
Colony 1"""
response: ChatResponse = chat(model='llama3.2',
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": kingdom_prompt}
    ]
)
kingdoms = {}
kingdoms_output = response['message']['content']
for output in kingdoms_output.split('\n\n'):
  kingdom_name = output.strip().split('\n')[0] \
    .split('Name: ')[1].strip()
  print(f'Created colony "{kingdom_name}" in {world["name"]}')
  kingdom_description = output.strip().split('\n')[1] \
    .split('Description: ')[1].strip()
  kingdom = {
      "name": kingdom_name,
      "description": kingdom_description,
      "world": world['name']
  }
  kingdoms[kingdom_name] = kingdom
world['kingdoms'] = kingdoms
print(f'\nColony 1 Description: \
{kingdom["description"]}')
def get_town_prompt(world, kingdom):
    return f"""
    Create 3 different starports for a futuristic colony and world. \
    Describe the region they're in, important facilities, \
    and notable history.
    Output content in the form:
    Starport 1 Name: <STARPORT NAME>
    Starport 1 Description: <STARPORT DESCRIPTION>
    Starport 2 Name: <STARPORT NAME>
    Starport 2 Description: <STARPORT DESCRIPTION>
    Starport 3 Name: <STARPORT NAME>
    Starport 3 Description: <STARPORT DESCRIPTION>
    World Name: {world['name']}
    World Description: {world['description']}
    Colony Name: {kingdom['name']}
    Colony Description {kingdom['description']}
    Starport 1 Name:"""
def create_towns(world, kingdom):
    print(f'\nCreating starports for colony: {kingdom["name"]}...')
    response: ChatResponse = chat(model='llama3.2',
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": get_town_prompt(world, kingdom)}
        ]
    )   
    towns_output = response['message']['content']
    towns = {}
    for output in towns_output.split('\n\n'):
        town_name = output.strip().split('\n')[0]\
        .split('Name: ')[1].strip()
        print(f'- {town_name} created')
        town_description = output.strip().split('\n')[1]\
        .split('Description: ')[1].strip()
        town = {
          "name": town_name,
          "description": town_description,
          "world": world['name'],
          "kingdom": kingdom['name']
        }
        towns[town_name] = town
    kingdom["towns"] = towns
for kingdom in kingdoms.values():
    create_towns(world, kingdom)  
town = list(kingdom['towns'].values())[0]
print(f'\nStarport 1 Description: \
{town["description"]}')
def get_npc_prompt(world, kingdom, town): 
    return f"""
    Create 3 different characters based on the world, colony, \
    and starport they're in. Describe the character's appearance and \
    role, as well as their motivations and challenges.
    Output content in the form:
    Character 1 Name: <CHARACTER NAME>
    Character 1 Description: <CHARACTER DESCRIPTION>
    Character 2 Name: <CHARACTER NAME>
    Character 2 Description: <CHARACTER DESCRIPTION>
    Character 3 Name: <CHARACTER NAME>
    Character 3 Description: <CHARACTER DESCRIPTION>
    World Name: {world['name']}
    World Description: {world['description']}
    Colony Name: {kingdom['name']}
    Colony Description: {kingdom['description']}
    Starport Name: {town['name']}
    Starport Description: {town['description']}
    Character 1 Name:"""
def create_npcs(world, kingdom, town):
    print(f'\nCreating characters for the starport of: {town["name"]}...')
    response: ChatResponse = chat(model='llama3.2',
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": get_npc_prompt(world, kingdom, town)}
        ]
    )
    npcs_output = response['message']['content']
    npcs = {}
    for output in npcs_output.split('\n\n'):
        lines = output.strip().split('\n')
        if len(lines) < 2:
            print(f"Warning: skipping invalid NPC output - {output}")
            continue
        npc_name_line = lines[0]
        if "Name: " not in npc_name_line:
            print(f"Warning: skipping invalid NPC output - {output}")
            continue
        npc_name = npc_name_line.split('Name: ')[1].strip()
        npc_description = ""
        for line in lines[1:]:
            if "Description: " in line:
                npc_description = line.split('Description: ')[1].strip()
            elif "Motivations and Challenges: " in line:
                npc_description += "\n" + line.split('Motivations and Challenges: ')[1].strip()
        print(f'- "{npc_name}" created')
        npc = {
        "name": npc_name,
        "description": npc_description,
        "world": world['name'],
        "kingdom": kingdom['name'],
        "town": town['name']
        }
        npcs[npc_name] = npc
    town["npcs"] = npcs
for kingdom in kingdoms.values():
    for town in kingdom['towns'].values():
        create_npcs(world, kingdom, town)
  # For now we'll only generate npcs for one kingdom
    break
npc = list(town['npcs'].values())[0]
print(f'\nNPC 1 in {town["name"]}, \
{kingdom["name"]}:\n{npc["description"]}')
def save_world(world, filename):
    with open(filename, 'w') as f:
        json.dump(world, f)
def load_world(filename):
    with open(filename, 'r') as f:
        return json.load(f)
save_world(world, 'MyWorld.json')
import gradio as gr
import os
demo = None #added to allow restart
def start_game(main_loop, share=False):
    # added code to support restart
    global demo
    # If demo is already running, close it first
    if demo is not None:
        demo.close()
    demo = gr.ChatInterface(
        main_loop,
        chatbot=gr.Chatbot(height=250, placeholder="Type 'start game' to begin"),
        textbox=gr.Textbox(placeholder="What do you do next?", container=False, scale=7),
        title="AI RPG",
        # description="Ask Yes Man any question",
        theme="soft",
        examples=["Look around", "Continue the story"],
        cache_examples=False,
        retry_btn="Retry",
        undo_btn="Undo",
        clear_btn="Clear",
                           )
    demo.launch(share=share, server_name="0.0.0.0")
def test_main_loop(message, history):
    return 'Entered Action: ' + message
start_game(test_main_loop)
world = load_world('MyWorld.json')
kingdom = world['kingdoms']['Aurora Isles']
town = kingdom['towns']["Helios Landing"]
character = town['npcs']['Dr. Lyra Flynn']
system_prompt = """You are an AI Game master. Your job is to create a 
start to an adventure based on the world, colony, starport, and character 
a player is playing as. 
Instructions:
You must only use 2-4 sentences \
Write in second person. For example: "You are Alex" \
Write in present tense. For example "You are standing..." \
First describe the character and their background. \
Then describe where they start and what they see around them."""
world_info = f"""
World: {world}
Kingdom: {kingdom}
Town: {town}
Your Character: {character}
"""
response: ChatResponse = chat(model='llama3.2',
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": world_info + '\nYour Start:'}
    ]
)
start = response['message']['content']
print(start)
world['start'] = start
save_world(world, 'MyWorld.json')
def run_action(message, history, game_state):
    if(message == 'start game'):
        return game_state['start']
    system_prompt = """You are an AI Game master. Your job is to write what \
happens next in a player's adventure game.\
Instructions: \
You must only write 1-3 sentences in response. \
Always write in second person present tense. \
Ex. (You approach the control panel...)"""
    world_info = f"""
World: {game_state['world']}
Kingdom: {game_state['kingdom']}
Town: {game_state['town']}
Your Character:  {game_state['character']}"""
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": world_info}
    ]
    for action in history:
        messages.append({"role": "assistant", "content": action[0]})
        messages.append({"role": "user", "content": action[1]})
    messages.append({"role": "user", "content": message})
    response: ChatResponse = chat(model='llama3.2',
        messages=messages
    )
    result = response['message']['content']
    return result
game_state = {
    "world": world['description'],
    "kingdom": kingdom['description'],
    "town": town['description'],
    "character": character['description'],
    "start": start,
}
def main_loop(message, history):
    return run_action(message, history, game_state)
No comments:
Post a Comment