Building a Simple AI Game
Create a complete AI-powered game from concept to deployment. This comprehensive tutorial will guide you through building "The AI Tavern" - a text-based adventure game where players interact with AI-powered NPCs, complete quests, and explore a dynamic world.
What You'll Learn
By the end of this tutorial, you'll have:
- A complete AI-powered game ready to play
- Multiple AI NPCs with unique personalities
- Quest system with AI-generated content
- Player progression and relationship tracking
- Game polish and deployment strategies
Game Design: "The AI Tavern"
Game Concept
"The AI Tavern" is a text-based adventure where players:
- Explore a tavern filled with AI-powered NPCs
- Complete quests generated by AI
- Build relationships with NPCs over time
- Unlock new areas and storylines
- Experience emergent storytelling through AI interactions
Core Gameplay Loop
- Enter the tavern and meet NPCs
- Talk to NPCs to learn about quests and stories
- Complete quests to gain experience and items
- Build relationships with NPCs through conversation
- Unlock new content as relationships develop
Step 1: Game Architecture
Project Structure
ai-tavern-game/
├── src/
│ ├── game/
│ │ ├── __init__.py
│ │ ├── game.py
│ │ ├── player.py
│ │ ├── world.py
│ │ └── quests.py
│ ├── ai/
│ │ ├── __init__.py
│ │ ├── npcs.py
│ │ └── services.py
│ └── main.py
├── data/
│ ├── locations.json
│ ├── items.json
│ └── quests.json
├── .env
├── requirements.txt
└── README.md
Core Game Class
# src/game/game.py
import json
import time
from typing import Dict, List, Optional
from src.ai.npcs import AINPC
from src.game.player import Player
from src.game.world import GameWorld
class AITavernGame:
def __init__(self):
self.player = Player()
self.world = GameWorld()
self.npcs = {}
self.game_state = "playing"
self.current_location = "tavern"
self.setup_game()
def setup_game(self):
"""Initialize the game world and NPCs"""
print("Welcome to The AI Tavern!")
print("A text-based adventure powered by AI")
print("=" * 50)
# Create NPCs
self.create_npcs()
# Load game data
self.load_game_data()
print("Game initialized successfully!")
print("Type 'help' for commands, 'quit' to exit")
print()
def create_npcs(self):
"""Create AI-powered NPCs"""
from src.ai.services import AIService
ai_service = AIService()
# Elena - Tavern Keeper
elena_profile = {
"name": "Elena",
"background": "Former adventurer who runs the tavern",
"personality": {"friendliness": 0.9, "humor": 0.7, "wisdom": 0.8},
"goals": ["Help adventurers", "Keep tavern safe"],
"fears": ["Dangerous quests", "Losing tavern"]
}
self.npcs["elena"] = AINPC(elena_profile, ai_service)
# Marcus - Blacksmith
marcus_profile = {
"name": "Marcus",
"background": "Skilled blacksmith with a mysterious past",
"personality": {"friendliness": 0.6, "humor": 0.4, "wisdom": 0.9},
"goals": ["Create masterwork weapons", "Train apprentices"],
"fears": ["Inferior craftsmanship", "Losing his tools"]
}
self.npcs["marcus"] = AINPC(marcus_profile, ai_service)
# Luna - Mystic
luna_profile = {
"name": "Luna",
"background": "Mystic who reads the stars and future",
"personality": {"friendliness": 0.7, "humor": 0.5, "wisdom": 0.9},
"goals": ["Help others find their path", "Study the mysteries"],
"fears": ["Dark omens", "Misreading the stars"]
}
self.npcs["luna"] = AINPC(luna_profile, ai_service)
def load_game_data(self):
"""Load game data from JSON files"""
try:
with open('data/locations.json', 'r') as f:
self.world.locations = json.load(f)
with open('data/items.json', 'r') as f:
self.world.items = json.load(f)
with open('data/quests.json', 'r') as f:
self.world.quests = json.load(f)
except FileNotFoundError:
print("Game data files not found. Using default data.")
self.create_default_data()
def create_default_data(self):
"""Create default game data"""
self.world.locations = {
"tavern": {
"name": "The AI Tavern",
"description": "A cozy tavern filled with interesting characters",
"npcs": ["elena", "marcus", "luna"],
"exits": ["village", "dungeon"]
}
}
self.world.items = {
"health_potion": {"name": "Health Potion", "type": "consumable", "value": 10},
"sword": {"name": "Iron Sword", "type": "weapon", "value": 50}
}
self.world.quests = {
"find_herbs": {
"name": "Find Healing Herbs",
"description": "Collect 5 healing herbs for Elena",
"reward": "health_potion",
"completed": False
}
}
def run(self):
"""Main game loop"""
while self.game_state == "playing":
self.display_status()
command = input("\nWhat would you like to do? ").strip().lower()
self.process_command(command)
def display_status(self):
"""Display current game status"""
print(f"\n--- {self.world.locations[self.current_location]['name']} ---")
print(f"Health: {self.player.health}/100")
print(f"Level: {self.player.level}")
print(f"Experience: {self.player.experience}")
print(f"Gold: {self.player.gold}")
# Show available NPCs
location_npcs = self.world.locations[self.current_location].get('npcs', [])
if location_npcs:
print(f"\nYou see: {', '.join([self.npcs[npc].profile['name'] for npc in location_npcs])}")
def process_command(self, command):
"""Process player commands"""
if command == "quit":
self.game_state = "quit"
print("Thanks for playing The AI Tavern!")
elif command == "help":
self.show_help()
elif command.startswith("talk "):
npc_name = command[5:].lower()
self.talk_to_npc(npc_name)
elif command == "look":
self.look_around()
elif command == "inventory":
self.show_inventory()
elif command.startswith("quest "):
quest_name = command[6:]
self.handle_quest(quest_name)
else:
print("I don't understand that command. Type 'help' for available commands.")
def talk_to_npc(self, npc_name):
"""Talk to an NPC"""
# Find NPC by name
npc_key = None
for key, npc in self.npcs.items():
if npc.profile['name'].lower() == npc_name:
npc_key = key
break
if not npc_key:
print(f"I don't see {npc_name} here.")
return
npc = self.npcs[npc_key]
print(f"\nYou approach {npc.profile['name']}...")
print(f"{npc.profile['name']}: Hello there! How can I help you?")
# Conversation loop
while True:
player_input = input(f"\nYou: ").strip()
if player_input.lower() in ['bye', 'goodbye', 'leave']:
print(f"{npc.profile['name']}: Farewell! Come back anytime.")
break
response = npc.interact(player_input, self.player.id)
print(f"{npc.profile['name']}: {response}")
def look_around(self):
"""Look around the current location"""
location = self.world.locations[self.current_location]
print(f"\n{location['name']}")
print(f"{location['description']}")
# Show NPCs
npcs = location.get('npcs', [])
if npcs:
print(f"\nYou see: {', '.join([self.npcs[npc].profile['name'] for npc in npcs])}")
# Show exits
exits = location.get('exits', [])
if exits:
print(f"\nExits: {', '.join(exits)}")
def show_inventory(self):
"""Show player inventory"""
if not self.player.inventory:
print("Your inventory is empty.")
else:
print("Your inventory:")
for item, count in self.player.inventory.items():
print(f"- {item}: {count}")
def show_help(self):
"""Show available commands"""
print("\nAvailable commands:")
print("- talk [npc_name]: Talk to an NPC")
print("- look: Look around the current location")
print("- inventory: Show your inventory")
print("- quest [quest_name]: Handle quests")
print("- help: Show this help message")
print("- quit: Exit the game")
def handle_quest(self, quest_name):
"""Handle quest-related commands"""
if quest_name == "list":
self.list_quests()
elif quest_name in self.world.quests:
self.show_quest(quest_name)
else:
print("Quest not found. Type 'quest list' to see available quests.")
def list_quests(self):
"""List available quests"""
print("\nAvailable quests:")
for quest_id, quest in self.world.quests.items():
status = "✓" if quest.get('completed', False) else "○"
print(f"{status} {quest['name']}: {quest['description']}")
def show_quest(self, quest_id):
"""Show quest details"""
quest = self.world.quests[quest_id]
print(f"\nQuest: {quest['name']}")
print(f"Description: {quest['description']}")
if 'reward' in quest:
print(f"Reward: {quest['reward']}")
print(f"Status: {'Completed' if quest.get('completed', False) else 'In Progress'}")
Step 2: Player System
Player Class
# src/game/player.py
import uuid
from typing import Dict, List
class Player:
def __init__(self):
self.id = str(uuid.uuid4())
self.name = "Adventurer"
self.level = 1
self.experience = 0
self.health = 100
self.max_health = 100
self.gold = 50
self.inventory = {}
self.relationships = {} # NPC relationships
self.completed_quests = []
self.current_quests = []
def gain_experience(self, amount):
"""Gain experience and level up if needed"""
self.experience += amount
old_level = self.level
# Level up every 100 experience
self.level = (self.experience // 100) + 1
if self.level > old_level:
self.level_up()
def level_up(self):
"""Handle level up"""
self.max_health += 20
self.health = self.max_health
print(f"🎉 Level up! You are now level {self.level}!")
print(f"Health increased to {self.max_health}")
def add_item(self, item_name, quantity=1):
"""Add item to inventory"""
if item_name in self.inventory:
self.inventory[item_name] += quantity
else:
self.inventory[item_name] = quantity
print(f"Added {quantity} {item_name} to inventory")
def remove_item(self, item_name, quantity=1):
"""Remove item from inventory"""
if item_name in self.inventory:
if self.inventory[item_name] >= quantity:
self.inventory[item_name] -= quantity
if self.inventory[item_name] == 0:
del self.inventory[item_name]
return True
return False
def has_item(self, item_name, quantity=1):
"""Check if player has item"""
return self.inventory.get(item_name, 0) >= quantity
def update_relationship(self, npc_id, change):
"""Update relationship with NPC"""
if npc_id not in self.relationships:
self.relationships[npc_id] = 0.5
self.relationships[npc_id] = max(0, min(1, self.relationships[npc_id] + change))
def get_relationship_status(self, npc_id):
"""Get relationship status with NPC"""
if npc_id not in self.relationships:
return "stranger"
rel = self.relationships[npc_id]
if rel > 0.8:
return "close_friend"
elif rel > 0.6:
return "friend"
elif rel > 0.4:
return "acquaintance"
elif rel > 0.2:
return "neutral"
else:
return "unfriendly"
Step 3: World System
Game World Class
# src/game/world.py
from typing import Dict, List, Optional
class GameWorld:
def __init__(self):
self.locations = {}
self.items = {}
self.quests = {}
self.events = []
def add_location(self, location_id, name, description, npcs=None, exits=None):
"""Add a location to the world"""
self.locations[location_id] = {
"name": name,
"description": description,
"npcs": npcs or [],
"exits": exits or []
}
def add_item(self, item_id, name, item_type, value, description=""):
"""Add an item to the world"""
self.items[item_id] = {
"name": name,
"type": item_type,
"value": value,
"description": description
}
def add_quest(self, quest_id, name, description, reward=None, requirements=None):
"""Add a quest to the world"""
self.quests[quest_id] = {
"name": name,
"description": description,
"reward": reward,
"requirements": requirements or [],
"completed": False
}
def get_location(self, location_id):
"""Get location by ID"""
return self.locations.get(location_id)
def get_item(self, item_id):
"""Get item by ID"""
return self.items.get(item_id)
def get_quest(self, quest_id):
"""Get quest by ID"""
return self.quests.get(quest_id)
def complete_quest(self, quest_id):
"""Mark quest as completed"""
if quest_id in self.quests:
self.quests[quest_id]["completed"] = True
return True
return False
Step 4: Quest System
Quest System Implementation
# src/game/quests.py
from typing import Dict, List, Optional
from src.ai.services import AIService
class QuestSystem:
def __init__(self, ai_service):
self.ai_service = ai_service
self.active_quests = {}
self.completed_quests = {}
def generate_quest(self, player_level, npc_personality, quest_type="general"):
"""Generate a quest using AI"""
prompt = f"""
Generate a quest for a level {player_level} player.
The quest giver has a {npc_personality} personality.
Quest type: {quest_type}
Make it engaging and appropriate for the player's level.
Include: objective, rewards, and any special requirements.
"""
context = """
You are a game master creating quests for an RPG.
Make quests:
- Appropriate for the player's level
- Engaging and interesting
- Clear objectives
- Rewarding completion
- Themed to the quest giver's personality
"""
quest_description = self.ai_service.generate_response(prompt, context)
return {
"description": quest_description,
"level": player_level,
"type": quest_type,
"status": "available"
}
def offer_quest(self, npc, player_level):
"""Offer a quest to the player"""
quest = self.generate_quest(player_level, npc.profile['personality'])
offer_prompt = f"""
Offer this quest to the player: {quest['description']}
Make it sound engaging and explain why you need their help.
"""
offer_context = f"""
You are {npc.profile['name']}, offering a quest to an adventurer.
Your personality: {npc.profile['personality']}
Be persuasive but not pushy.
"""
return self.ai_service.generate_response(offer_prompt, offer_context)
def complete_quest(self, quest_id, player):
"""Complete a quest and give rewards"""
if quest_id in self.active_quests:
quest = self.active_quests[quest_id]
# Give rewards
if 'reward' in quest:
player.add_item(quest['reward'])
# Give experience
player.gain_experience(quest.get('experience', 50))
# Move to completed
self.completed_quests[quest_id] = quest
del self.active_quests[quest_id]
return True
return False
Step 5: Game Polish and Features
Save/Load System
# src/game/save_system.py
import json
import os
from datetime import datetime
class SaveSystem:
def __init__(self, save_dir="saves"):
self.save_dir = save_dir
if not os.path.exists(save_dir):
os.makedirs(save_dir)
def save_game(self, game, filename=None):
"""Save game state"""
if not filename:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"save_{timestamp}.json"
save_data = {
"player": {
"name": game.player.name,
"level": game.player.level,
"experience": game.player.experience,
"health": game.player.health,
"gold": game.player.gold,
"inventory": game.player.inventory,
"relationships": game.player.relationships,
"completed_quests": game.player.completed_quests
},
"world": {
"locations": game.world.locations,
"items": game.world.items,
"quests": game.world.quests
},
"game_state": {
"current_location": game.current_location,
"game_state": game.game_state
}
}
filepath = os.path.join(self.save_dir, filename)
with open(filepath, 'w') as f:
json.dump(save_data, f, indent=2)
print(f"Game saved to {filename}")
return filename
def load_game(self, filename):
"""Load game state"""
filepath = os.path.join(self.save_dir, filename)
if not os.path.exists(filepath):
print(f"Save file {filename} not found")
return None
with open(filepath, 'r') as f:
save_data = json.load(f)
return save_data
Game Statistics
# src/game/stats.py
import time
from typing import Dict, Any
class GameStats:
def __init__(self):
self.start_time = time.time()
self.actions_taken = 0
self.npcs_talked_to = set()
self.quests_completed = 0
self.items_collected = 0
self.relationships_formed = 0
def record_action(self, action_type, details=None):
"""Record a game action"""
self.actions_taken += 1
if action_type == "talk_to_npc":
self.npcs_talked_to.add(details)
elif action_type == "complete_quest":
self.quests_completed += 1
elif action_type == "collect_item":
self.items_collected += 1
elif action_type == "form_relationship":
self.relationships_formed += 1
def get_stats(self):
"""Get current game statistics"""
play_time = time.time() - self.start_time
return {
"play_time": f"{play_time:.1f} seconds",
"actions_taken": self.actions_taken,
"npcs_talked_to": len(self.npcs_talked_to),
"quests_completed": self.quests_completed,
"items_collected": self.items_collected,
"relationships_formed": self.relationships_formed
}
def display_stats(self):
"""Display game statistics"""
stats = self.get_stats()
print("\n--- Game Statistics ---")
for key, value in stats.items():
print(f"{key.replace('_', ' ').title()}: {value}")
Step 6: Testing and Debugging
Test Script
# test_game.py
def test_game():
"""Test the complete game"""
print("Testing AI Tavern Game")
print("=" * 30)
# Initialize game
game = AITavernGame()
# Test basic functionality
print("Testing game initialization...")
assert game.player.level == 1
assert game.current_location == "tavern"
assert len(game.npcs) == 3
print("✓ Game initialization successful")
# Test NPC interactions
print("\nTesting NPC interactions...")
elena = game.npcs["elena"]
response = elena.interact("Hello!", game.player.id)
assert response is not None
print("✓ NPC interactions working")
# Test quest system
print("\nTesting quest system...")
quest_system = QuestSystem(game.npcs["elena"].ai_service)
quest = quest_system.generate_quest(1, {"friendliness": 0.9})
assert quest is not None
print("✓ Quest system working")
# Test save/load
print("\nTesting save/load system...")
save_system = SaveSystem()
filename = save_system.save_game(game)
assert filename is not None
print("✓ Save/load system working")
print("\n🎉 All tests passed! Game is ready to play.")
if __name__ == "__main__":
test_game()
Step 7: Deployment and Distribution
Packaging the Game
# setup.py
from setuptools import setup, find_packages
setup(
name="ai-tavern-game",
version="1.0.0",
description="A text-based adventure game powered by AI",
author="GamineAI Team",
packages=find_packages(),
install_requires=[
"openai>=1.0.0",
"python-dotenv>=0.19.0",
"requests>=2.25.0"
],
entry_points={
"console_scripts": [
"ai-tavern=src.main:main"
]
}
)
Distribution
# Create distribution package
python setup.py sdist bdist_wheel
# Install the game
pip install dist/ai_tavern_game-1.0.0-py3-none-any.whl
# Run the game
ai-tavern
Best Practices for AI Games
1. Performance Optimization
- Cache AI responses for common interactions
- Use local models for simple responses
- Implement response timeouts and fallbacks
2. Content Quality
- Test AI responses with various inputs
- Implement content filters and safety checks
- Monitor and improve response quality
3. User Experience
- Provide clear instructions and help
- Implement save/load functionality
- Add progress tracking and statistics
4. Scalability
- Design for multiple NPCs and locations
- Implement modular quest and story systems
- Plan for content expansion
Next Steps
Congratulations! You've built a complete AI-powered game. Here's what to do next:
1. Enhance Your Game
- Add more NPCs and locations
- Implement combat and item systems
- Create branching storylines
2. Share Your Game
- Deploy to a web platform
- Share with the community
- Get feedback and improve
3. Continue Learning
- Move to intermediate tutorials
- Explore advanced AI techniques
- Learn about game deployment
4. Join the Community
- Share your game projects
- Learn from other developers
- Contribute to the community
Resources and Further Reading
Documentation
Community
Tools
- GitHub - For version control
- PyInstaller - For packaging
- Docker - For deployment
Conclusion
You've successfully built a complete AI-powered game! You now understand:
- How to design and implement AI-powered games
- How to create engaging NPCs with AI dialogue
- How to build quest systems with AI-generated content
- How to implement player progression and relationships
- How to polish and deploy your game
Your game demonstrates the power of AI in game development, creating dynamic, engaging experiences that adapt to player interactions. This foundation will serve you well as you continue to explore AI game development.
Ready for the next step? Continue with Testing and Debugging AI Systems to learn how to ensure your AI systems work reliably.
This tutorial is part of the GamineAI Beginner Tutorial Series. Learn at your own pace, practice with hands-on exercises, and build the skills you need to create amazing AI-powered games.