📝 Game Development

Python Achievements System — Gamification! 🏆

0
Author
04e5cc8b-58ac-4bdc-bdee-661bbb
📅
Published
03.04.2026
⏱️
Reading time
8 min
👁️
Views
90
🌱
Level
Beginner

What is an achievements system?

Achievements — rewards for completing tasks.

Why does it matter?

Achievements = Motivation + Engagement

Gamification boosts retention by 30–40%! 🎮


Basic achievements system

Achievement Class:

class Achievement:
    """An achievement."""

    def __init__(self, id, name, description, points, condition):
        """
        Args:
            id: Unique ID
            name: Achievement name
            description: Description
            points: How many points it awards
            condition: Check function (returns True/False)
        """
        self.id = id
        self.name = name
        self.description = description
        self.points = points
        self.condition = condition
        self.unlocked = False
        self.unlocked_at = None

    def check(self, user_data):
        """Check whether the achievement is unlocked."""
        if self.unlocked:
            return False  # Already unlocked

        if self.condition(user_data):
            self.unlocked = True
            from datetime import datetime
            self.unlocked_at = datetime.now()
            return True

        return False

    def __str__(self):
        status = "🔓" if self.unlocked else "🔒"
        return f"{status} {self.name} ({self.points} pts)"

# Example conditions
def first_login(data):
    """First login."""
    return data.get("logins", 0) >= 1

def power_user(data):
    """100+ logins."""
    return data.get("logins", 0) >= 100

# Creating achievements
achievements = [
    Achievement(
        id="first_login",
        name="First Step",
        description="Log in for the first time",
        points=10,
        condition=first_login
    ),
    Achievement(
        id="power_user",
        name="Power User",
        description="100 logins",
        points=100,
        condition=power_user
    )
]

# Check
user = {"logins": 1}

for ach in achievements:
    if ach.check(user):
        print(f"🎉 Unlocked: {ach.name} (+{ach.points} pts)")

Progress Tracking

ProgressTracker Class:

class ProgressTracker:
    """Track a user's progress."""

    def __init__(self, user_id):
        self.user_id = user_id
        self.stats = {
            "logins": 0,
            "tasks_completed": 0,
            "points_earned": 0,
            "days_active": 0,
            "streak": 0,  # Consecutive days
            "lessons_finished": 0,
            "code_lines": 0
        }
        self.achievements_unlocked = []
        self.last_active = None

    def record_action(self, action_type, value=1):
        """Record an action."""
        if action_type in self.stats:
            self.stats[action_type] += value

        # Streak check
        from datetime import datetime, timedelta
        today = datetime.now().date()

        if self.last_active:
            last_date = self.last_active.date()
            if today == last_date + timedelta(days=1):
                self.stats["streak"] += 1
            elif today != last_date:
                self.stats["streak"] = 1
        else:
            self.stats["streak"] = 1

        self.last_active = datetime.now()

    def get_progress_percent(self, achievement):
        """Percentage progress toward an achievement."""
        # Already unlocked
        if achievement.unlocked:
            return 100

        # Approximate check (simplified)
        # In production you'd parse the condition
        return min(100, (self.stats.get("tasks_completed", 0) / 10) * 100)

    def get_summary(self):
        """Progress summary."""
        return {
            "total_points": self.stats["points_earned"],
            "achievements": len(self.achievements_unlocked),
            "streak": self.stats["streak"],
            "tasks": self.stats["tasks_completed"]
        }

# Usage
tracker = ProgressTracker(user_id=1)

# User performs actions
tracker.record_action("logins")
tracker.record_action("tasks_completed")
tracker.record_action("points_earned", 50)

print(tracker.get_summary())
# {'total_points': 50, 'achievements': 0, 'streak': 1, 'tasks': 1}

Achievement Manager

Central management system:

class AchievementManager:
    """Manage all achievements."""

    def __init__(self):
        self.achievements = []
        self.user_progresses = {}

    def register_achievement(self, achievement):
        """Register an achievement."""
        self.achievements.append(achievement)

    def get_user_progress(self, user_id):
        """Get a user's progress tracker."""
        if user_id not in self.user_progresses:
            self.user_progresses[user_id] = ProgressTracker(user_id)
        return self.user_progresses[user_id]

    def check_achievements(self, user_id):
        """Check all achievements for a user."""
        tracker = self.get_user_progress(user_id)
        newly_unlocked = []

        for achievement in self.achievements:
            if achievement.check(tracker.stats):
                tracker.achievements_unlocked.append(achievement.id)
                tracker.stats["points_earned"] += achievement.points
                newly_unlocked.append(achievement)

        return newly_unlocked

    def get_user_achievements(self, user_id):
        """All achievements for a user."""
        tracker = self.get_user_progress(user_id)

        result = {
            "unlocked": [],
            "locked": [],
            "total_points": tracker.stats["points_earned"]
        }

        for ach in self.achievements:
            if ach.id in tracker.achievements_unlocked:
                result["unlocked"].append({
                    "name": ach.name,
                    "points": ach.points,
                    "unlocked_at": ach.unlocked_at
                })
            else:
                result["locked"].append({
                    "name": ach.name,
                    "description": ach.description,
                    "points": ach.points
                })

        return result

# Example usage
manager = AchievementManager()

# Register achievements
manager.register_achievement(Achievement(
    "first_task", "First Steps", "Complete your first task",
    points=10,
    condition=lambda data: data.get("tasks_completed", 0) >= 1
))

manager.register_achievement(Achievement(
    "task_master", "Task Master", "Complete 50 tasks",
    points=200,
    condition=lambda data: data.get("tasks_completed", 0) >= 50
))

# User completes a task
tracker = manager.get_user_progress(user_id=1)
tracker.record_action("tasks_completed")

# Check
new_achievements = manager.check_achievements(user_id=1)

for ach in new_achievements:
    print(f"🎉 {ach.name} (+{ach.points} pts)")

Achievement types

1. Milestone Achievements (count-based):

def create_milestone_achievement(name, stat_key, threshold, points):
    """Achievement for reaching a numeric threshold."""
    return Achievement(
        id=f"{stat_key}_{threshold}",
        name=name,
        description=f"Reach {threshold} {stat_key}",
        points=points,
        condition=lambda data: data.get(stat_key, 0) >= threshold
    )

# Examples
milestones = [
    create_milestone_achievement("Beginner", "lessons_finished", 1, 10),
    create_milestone_achievement("Student", "lessons_finished", 5, 50),
    create_milestone_achievement("Expert", "lessons_finished", 20, 200),
    create_milestone_achievement("Master", "lessons_finished", 50, 500)
]

2. Streak Achievements (consistency-based):

def create_streak_achievement(days, points):
    """Achievement for consecutive days."""
    return Achievement(
        id=f"streak_{days}",
        name=f"{days}-day streak",
        description=f"Log in {days} days in a row",
        points=points,
        condition=lambda data: data.get("streak", 0) >= days
    )

streaks = [
    create_streak_achievement(3, 30),
    create_streak_achievement(7, 100),
    create_streak_achievement(30, 500),
    create_streak_achievement(100, 2000)
]

3. Challenge Achievements (special conditions):

# Combined conditions
def early_bird_condition(data):
    """Early bird — log in before 6 AM."""
    if not data.get("last_login_hour"):
        return False
    return data["last_login_hour"] < 6

def night_owl_condition(data):
    """Night owl — log in after 11 PM."""
    if not data.get("last_login_hour"):
        return False
    return data["last_login_hour"] >= 23

challenges = [
    Achievement(
        "early_bird", "Early Bird", "Log in before 6:00 AM", 50, early_bird_condition
    ),
    Achievement(
        "night_owl", "Night Owl", "Log in after 11:00 PM", 50, night_owl_condition
    )
]

Badges & Tiers

Tier system:

class BadgeSystem:
    """Badge and tier system."""

    TIERS = [
        {"name": "Beginner", "min_points": 0, "badge": "🥉"},
        {"name": "Student", "min_points": 100, "badge": "🥈"},
        {"name": "Expert", "min_points": 500, "badge": "🥇"},
        {"name": "Master", "min_points": 1000, "badge": "💎"},
        {"name": "Legend", "min_points": 5000, "badge": "👑"}
    ]

    @classmethod
    def get_tier(cls, points):
        """Get tier by points."""
        current_tier = cls.TIERS[0]

        for tier in cls.TIERS:
            if points >= tier["min_points"]:
                current_tier = tier
            else:
                break

        return current_tier

    @classmethod
    def get_next_tier(cls, points):
        """Get the next tier."""
        for tier in cls.TIERS:
            if points < tier["min_points"]:
                return tier
        return None

    @classmethod
    def progress_to_next(cls, points):
        """Progress percentage toward the next tier."""
        next_tier = cls.get_next_tier(points)

        if not next_tier:
            return 100  # Max tier

        current = cls.get_tier(points)
        needed = next_tier["min_points"] - current["min_points"]
        earned = points - current["min_points"]

        return (earned / needed) * 100 if needed > 0 else 100

# Usage
user_points = 350

tier = BadgeSystem.get_tier(user_points)
print(f"Current tier: {tier['badge']} {tier['name']}")

next_tier = BadgeSystem.get_next_tier(user_points)
if next_tier:
    progress = BadgeSystem.progress_to_next(user_points)
    print(f"Progress to {next_tier['name']}: {progress:.1f}%")

Leaderboard

Ranking system:

class Leaderboard:
    """Leaderboard."""

    def __init__(self):
        self.users = []

    def add_user(self, user_id, username, points):
        """Add a user."""
        self.users.append({
            "user_id": user_id,
            "username": username,
            "points": points
        })

    def get_rankings(self, limit=10):
        """Top users."""
        sorted_users = sorted(
            self.users,
            key=lambda x: x["points"],
            reverse=True
        )

        # Add position
        for i, user in enumerate(sorted_users[:limit], 1):
            user["rank"] = i

            # Medals for top 3
            if i == 1:
                user["medal"] = "🥇"
            elif i == 2:
                user["medal"] = "🥈"
            elif i == 3:
                user["medal"] = "🥉"
            else:
                user["medal"] = ""

        return sorted_users[:limit]

    def get_user_rank(self, user_id):
        """A user's position on the leaderboard."""
        sorted_users = sorted(
            self.users,
            key=lambda x: x["points"],
            reverse=True
        )

        for i, user in enumerate(sorted_users, 1):
            if user["user_id"] == user_id:
                return {
                    "rank": i,
                    "total_users": len(self.users),
                    "percentile": ((len(self.users) - i) / len(self.users)) * 100
                }

        return None

# Example
leaderboard = Leaderboard()

leaderboard.add_user(1, "Alice", 5000)
leaderboard.add_user(2, "Bob", 3500)
leaderboard.add_user(3, "Charlie", 4200)
leaderboard.add_user(4, "Diana", 2800)

print("🏆 Top users:")
for user in leaderboard.get_rankings():
    medal = user.get("medal", "")
    print(f"{medal} #{user['rank']} {user['username']}: {user['points']} pts")

# Rank for a specific user
rank_info = leaderboard.get_user_rank(4)
print(f"\nYour rank: #{rank_info['rank']}/{rank_info['total_users']}")
print(f"Top {rank_info['percentile']:.0f}%")

Notifications & Rewards

Notification system:

class AchievementNotification:
    """Achievement notifications."""

    @staticmethod
    def show_unlock(achievement):
        """Show an unlock notification."""
        print("=" * 50)
        print("🎉 ACHIEVEMENT UNLOCKED! 🎉")
        print("=" * 50)
        print(f"✨ {achievement.name}")
        print(f"📝 {achievement.description}")
        print(f"⭐ +{achievement.points} points")
        print("=" * 50)

    @staticmethod
    def show_progress(achievement, percent):
        """Show progress toward an achievement."""
        bar_length = 20
        filled = int(bar_length * percent / 100)
        bar = "█" * filled + "░" * (bar_length - filled)
        print(f"{achievement.name}: [{bar}] {percent:.0f}%")

    @staticmethod
    def show_tier_up(old_tier, new_tier):
        """Show a tier-up notification."""
        print("=" * 50)
        print("🎊 TIER UP! 🎊")
        print("=" * 50)
        print(f"{old_tier['badge']} {old_tier['name']} → {new_tier['badge']} {new_tier['name']}")
        print("=" * 50)

# Example
achievement = Achievement(
    "master", "Python Master", "Complete 100 tasks",
    points=500,
    condition=lambda x: x.get("tasks", 0) >= 100
)

# On unlock
AchievementNotification.show_unlock(achievement)

# Progress
AchievementNotification.show_progress(achievement, 75)

Full system

Putting it all together:

class GamificationSystem:
    """Full gamification system."""

    def __init__(self):
        self.achievement_manager = AchievementManager()
        self.badge_system = BadgeSystem()
        self.leaderboard = Leaderboard()

        # Register default achievements
        self._register_default_achievements()

    def _register_default_achievements(self):
        """Default achievements."""
        # Milestones
        for tasks in [1, 10, 50, 100]:
            self.achievement_manager.register_achievement(
                create_milestone_achievement(
                    f"{tasks} tasks",
                    "tasks_completed",
                    tasks,
                    tasks * 10
                )
            )

        # Streaks
        for days in [3, 7, 30]:
            self.achievement_manager.register_achievement(
                create_streak_achievement(days, days * 10)
            )

    def record_user_action(self, user_id, action_type, value=1):
        """Record a user action."""
        # Update tracker
        tracker = self.achievement_manager.get_user_progress(user_id)
        old_points = tracker.stats["points_earned"]
        old_tier = self.badge_system.get_tier(old_points)

        tracker.record_action(action_type, value)

        # Check achievements
        new_achievements = self.achievement_manager.check_achievements(user_id)

        # Show notifications
        for ach in new_achievements:
            AchievementNotification.show_unlock(ach)

        # Check for tier up
        new_points = tracker.stats["points_earned"]
        new_tier = self.badge_system.get_tier(new_points)

        if new_tier["name"] != old_tier["name"]:
            AchievementNotification.show_tier_up(old_tier, new_tier)

        # Update leaderboard
        self._update_leaderboard(user_id, new_points)

    def _update_leaderboard(self, user_id, points):
        """Update the leaderboard."""
        # Remove old entry
        self.leaderboard.users = [
            u for u in self.leaderboard.users if u["user_id"] != user_id
        ]

        # Add new entry
        self.leaderboard.add_user(user_id, f"User{user_id}", points)

    def get_user_dashboard(self, user_id):
        """User dashboard."""
        tracker = self.achievement_manager.get_user_progress(user_id)
        points = tracker.stats["points_earned"]
        tier = self.badge_system.get_tier(points)
        rank_info = self.leaderboard.get_user_rank(user_id)

        return {
            "tier": tier,
            "points": points,
            "rank": rank_info,
            "achievements": self.achievement_manager.get_user_achievements(user_id),
            "stats": tracker.stats
        }

# Usage
system = GamificationSystem()

# User completes tasks
system.record_user_action(user_id=1, action_type="tasks_completed")
system.record_user_action(user_id=1, action_type="tasks_completed")
system.record_user_action(user_id=1, action_type="tasks_completed")

# Dashboard
dashboard = system.get_user_dashboard(user_id=1)
print(f"\n{dashboard['tier']['badge']} {dashboard['tier']['name']}")
print(f"Points: {dashboard['points']}")
print(f"Achievements unlocked: {len(dashboard['achievements']['unlocked'])}")

Common mistakes

❌ Mistake 1: Achievements that are too easy

# BAD: unlocked immediately
Achievement("easy", "Hello", "Just show up", 1000,
            lambda x: True)  # Way too easy!

# ✅ GOOD: real goals
Achievement("hard", "Master", "100 tasks", 500,
            lambda x: x.get("tasks", 0) >= 100)

❌ Mistake 2: Achievements that are too hard

# BAD: impossible
Achievement("impossible", "God", "1 million tasks", 1,
            lambda x: x.get("tasks", 0) >= 1000000)  # Unrealistic!

# ✅ GOOD: challenging but achievable
Achievement("challenge", "Hero", "500 tasks", 1000,
            lambda x: x.get("tasks", 0) >= 500)

❌ Mistake 3: No progress feedback

# BAD: don't show progress
show_only_unlocked()  # Users don't know what to aim for

# ✅ GOOD: show progress
for ach in all_achievements:
    progress = tracker.get_progress_percent(ach)
    AchievementNotification.show_progress(ach, progress)

Best Practices

1. Balance rewards:

reward_tiers = {
    "easy": (1, 50),      # First achievements
    "medium": (50, 200),  # Mid-tier
    "hard": (200, 500),   # Hard
    "epic": (500, 2000)   # Epic
}

2. Variety:

achievement_types = [
    "milestones",    # Count-based
    "streaks",       # Consistency-based
    "challenges",    # Special conditions
    "hidden",        # Secret (condition hidden)
    "time_limited"   # Time-limited
]

3. Engagement Loops:

def create_engagement_loop():
    """Engagement loop."""
    steps = [
        "1. User sees their progress",
        "2. Almost unlocked an achievement (80%)",
        "3. Motivation to finish",
        "4. Unlock → satisfaction",
        "5. User sees the next achievement",
        "6. Loop repeats"
    ]
    return steps

Summary

System components:

components = {
    "Achievement": "The achievement itself",
    "ProgressTracker": "Tracks progress",
    "AchievementManager": "Manages everything",
    "BadgeSystem": "Tiers and badges",
    "Leaderboard": "Rankings",
    "Notifications": "Notifications"
}

Achievement types:

types = {
    "Milestone": "Count-based (10, 50, 100 tasks)",
    "Streak": "Consecutive days (3, 7, 30 days)",
    "Challenge": "Special conditions (early bird, night owl)",
    "Hidden": "Secret (condition hidden)",
    "Tier": "Tiers (beginner → master)"
}

System balance:

  • Early achievements — quick wins for onboarding
  • 📈 Mid-tier — regular rewards for retention
  • 🏆 Hard — rare rewards for prestige
  • 👑 Epic — extremely rare, legendary status

Build an achievement system and keep your users engaged! 🎮🚀

Your reaction to the article

💬 Comments (0)

🔐 Sign in to leave a comment
🚪 Login
💭

No comments yet

Be the first to share your opinion about this article!

🔗 Similar

Similar articles

Continue learning with these materials

📝

Building a Game in Python: A Step-by-Step Guide 🎮

Games are the best way to learn programming! Let's walk through how to build your...

📅 03.04.2026 👁️ 105
📝

10 Ideas for Your First Python Projects 💡

Already know the Python basics? Time to put them into practice! Here are 10 projects,...

📅 03.04.2026 👁️ 88
📝

10 Game Ideas in Python 🎮

Want to build your own game? Here are 10 ideas from simple to complex, complete...

📅 03.04.2026 👁️ 92

Did you like the article?

Subscribe to our updates and receive new articles first. Grow with PyLand!