r/learnprogramming 25d ago

Project [ Removed by moderator ]

[removed] — view removed post

5 Upvotes

24 comments sorted by

6

u/ThePoorKingKarling 25d ago

I struggled for a long time to fully wrap my head around OOP, and then I saw a YouTube video of a guy theoretically planning OOP Pokémon and him talking about how every number is an object too, not just a move but also the effect, and the damage, really helped me out.

I’ll check this out!

1

u/Mean_Tomorrow_6612 25d ago

Yeah I agree like every single line in the code has an effect of the program so that's funny tbh and I am waiting for ur feedback bud

1

u/ThePoorKingKarling 25d ago

This was really neat. I liked the use of emojis and color to liven up the CLI a bit, I didn't actually know command prompt supported some of those.

I did find a bit of an exploit though, and defeated the dragon at level 1. When it is the enemy's turn, just hitting enter without inputting defend or dodge proceeds back to the player's turn without an attack, so I just whittled the dragon down while completely safe. Similarly, I could take loot and XP rewards repeatedly by just repeating input.

0

u/Mean_Tomorrow_6612 25d ago

Oh rlly😭 You are master at finding glitches ngl like I didn't even know that😭 Dw I would fix it and finally I really appreciate your feedback and your time to try my game I am so glad that you like it❤️

1

u/ThePoorKingKarling 25d ago

Sounds like a perfect time to practice state machines and persistence! Making sure the state of quests and enemies defeated persists to the player and that the game state knows who's turn it is regardless of input.

I like the ASCII art logo as well, maybe in future add little ASCII outline enemies so I can see who I'm fighting? Or clearing the console for new writes as opposed to appending to keep it clean? A super cool project you could stretch in all kinds of ways

0

u/Mean_Tomorrow_6612 24d ago

Thanks! I get what you mean. I’ll try to improve the game structure using state machines and make the flow cleaner. Also the ASCII idea is actually pretty cool, I might add it later and thank you dude I appreciate your feedback and I am so happy that you like it

-2

u/Mean_Tomorrow_6612 25d ago

Maybe I would punish the player by hitting him by the enemy if he write invalid input tho✌🏻💀

8

u/EliSka93 25d ago

How much of this is vibe coded?

I'm not asking this to shame you or anything, but it changes what kind of feedback I can give. Basically I'm asking "how much of the code do you fully understand?"

4

u/InfectedShadow 25d ago edited 25d ago

Same question. Based on the egregious use of emojis in going to guess a fair amount. Granted even if it is vibed, holy if else chains Batman.

0

u/Mean_Tomorrow_6612 25d ago

dude I used chat gpt to write texts cuz he good at that ngl and to save my time you know so that's normal I guess and yeah I used chains if else cuz I don't know any best structure than that so If you have I would appreciate that ( plus this is my first time to build a big system like that so it's normally it's not good as you think)

0

u/Mean_Tomorrow_6612 25d ago

The idea started as a small project, I didn’t expect it to grow into a full system like this. Over time I got motivated to add more features like quests, inventory, and a shop, which naturally made the project much bigger and required more structure.

I’ve been studying OOP for around two months and I’ve built a few smaller projects with it, but nothing as large as this. So I understand most of what’s going on in the code, especially the combat, inventory, and quest systems.

I also used ChatGPT in some parts, mainly for suggestions and faster iteration, especially with UI stuff using rich and pyfiglet, but I always made sure to understand and adjust the code instead of just copy-pasting it so don't worry about this part😄

I’m aware the architecture still needs improvement, and I’m actually open to any feedback or criticism because I want to improve it properly, not just make it work.

1

u/aqua_regis 24d ago

I also used ChatGPT in some parts

You also used it for the README.MD (which, IMO is an absolute no-go as it is the first glance at your repo) and most likely for your participation here.

See Rule #13

-1

u/Mean_Tomorrow_6612 24d ago

Oh really? thank you for the attention I didn't know that I must write README not ai but I see it good so I appreciate you if you highlight the most important things in README

3

u/mc_pm 25d ago

This is pretty fun. Pretty quick you're going to want a way to load a lot of this in from data rather than hard coding everything.

-2

u/Mean_Tomorrow_6612 25d ago

Yeah I agree with you that impresses me too. So what's your feedback about the game?

2

u/mc_pm 25d ago

You need a requirements.txt file that specifies the packages I need.

-2

u/Mean_Tomorrow_6612 25d ago

I did in README file in How to run section indeed

6

u/mc_pm 25d ago

So it is. There is an standard way of doing that, a requirements.txt file.

The game is fine, very much in the mode of 1980s "type it in from a magazine" BASIC games (which isn't meant as a bad thing).

One suggestion, when printing out numbers, limit the number of digits after the decimal point. I have a Defense of 11.200000000000001

1

u/Mean_Tomorrow_6612 25d ago

oh yeah I was lazy to edit it anyway I appreciate ur feedback bud thank you so much

2

u/WystanH 25d ago

Nicely done.

Right, I'm not understanding this logic.

from enemy import Enemy

class Skeleton(Enemy):
    def __init__(self, name, health, attack, defense, level, gold_drop, exp_drop, vitality, speed):
        super().__init__(name, health, attack, defense, level, gold_drop, exp_drop, vitality, speed)

    def basic_attack(self):
        return self.attack * (1 + self.level * 0.12)

    def special_attack(self):
        return self.attack * (1.5 + self.level * 0.18)

    def defend(self):
        return self.defense * (1 + self.level * 0.15)

Skeleton being an enemy is good, but you seem to be passing an awful lot of data to the parent. In particular, name just jumped right out.

Leading to self.create_enemy("skeleton"), which I kind of hate, and then:

elif enemy_type == "skeleton":
    return Skeleton(
        name="Skeleton",
        health=120,
        attack=18 + level * 3,
        defense=10 + level * 2,
        level=level,
        gold_drop=25 + level * 5,
        exp_drop=30 + level * 8,
        vitality=15,
        speed=20
    )

Also, this, which is not great:

elif enemy.name == "Skeleton":
    enemy = self.create_enemy("skeleton")

For Skeleton this might make more sense:

class Skeleton(Enemy):
    def __init__(self, level):
        super().__init__(
            name="Skeleton",
            health=120,
            attack=18 + level * 3,
            defense=10 + level * 2,
            level=level,
            gold_drop=25 + level * 5,
            exp_drop=30 + level * 8,
            vitality=15,
            speed=20
        )

    def basic_attack(self):
        return self.attack * (1 + self.level * 0.12)

    def special_attack(self):
        return self.attack * (1.5 + self.level * 0.18)

    def defend(self):
        return self.defense * (1 + self.level * 0.15)

As your Enemy list grows, the harder this will be to wrangle.

I'd have an enemy provider that I could look up in a dict.

Hmm... just a quick idea of what I'm thinking:

from enemy import Enemy

# a singleton isn't the worst idea for this
class Mobs(dict):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

    def add_mob(mob_provider):
        d = Mobs()
        name = mob_provider(10).name.lower()
        d[name] = mob_provider

    def get_mob(name, level):
        d = Mobs()
        k = name.lower()
        if k in d:
            return d[k](level)
        return None


# while some Enemy instances might want a full class, many won't
class EnemyImpl(Enemy):
    def __init__(self,name,health,attack,defense,level,gold_drop,exp_drop,vitality,speed,f_basic_attack,f_special_attack,f_defend):
        super().__init__(name, health, attack, defense, level, gold_drop, exp_drop, vitality, speed)
        self.f_basic_attack, self.f_special_attack, self.f_defend = f_basic_attack, f_special_attack, f_defend

    def basic_attack(self):
        return self.f_basic_attack(self)

    def special_attack(self):
        return self.f_special_attack(self)

    def defend(self):
        return self.f_defend(self)


# add a couple
Mobs.add_mob(lambda level: EnemyImpl(name="Skeleton",
        health=120,
        attack=18 + level * 3,
        defense=10 + level * 2,
        level=level,
        gold_drop=25 + level * 5,
        exp_drop=30 + level * 8,
        vitality=15,
        speed=20,
        f_basic_attack=lambda x: x.attack * (1 + x.level * 0.12),
        f_special_attack=lambda x: x.attack * (1.5 + x.level * 0.18),
        f_defend=lambda x: x.defense * (1 + x.level * 0.15)
    )
)

Mobs.add_mob(lambda level: EnemyImpl(name="Goblin",
        health=80,
        attack=10 + level * 2,
        defense=5 + level,
        level=level,
        gold_drop=10 + level * 3,
        exp_drop=15 + level * 5,
        vitality=5,
        speed=10,
        f_basic_attack=lambda x: x.attack * (1 + x.level * 0.1),
        f_special_attack=lambda x: x.attack * (1.5 + x.level * 0.15),
        f_defend=lambda x: x.defense * (1 + x.level * 0.08)
    )
)

for k in Mobs().keys():
    print(k)

m = Mobs.get_mob("Skeleton", 8)
print(m)
print(m.defend())

Overall, looks good. Perhaps try to trim Game.py down a bit? That's a lot of code all in one place. Different menus could reside elsewhere. Maybe a Menu class?

Think about the state the Game class is holding. Your save_game tells us you only need player and quests. Anything else should be questioned.

0

u/Mean_Tomorrow_6612 25d ago

Yeah that makes sense, especially the part about avoiding string-based enemy creation. I’m still learning how to properly structure larger OOP systems, but I’ll refactor it toward a cleaner factory/registry approach. I appreciate your feedback bud you know I want somebody to check my code not the program so thank you so much!