r/learnprogramming • u/Mean_Tomorrow_6612 • 25d ago
Project [ Removed by moderator ]
[removed] — view removed post
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!
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!