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('nn'):
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('nn'):
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('nn'):
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)