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