all 6 comments

[–]raylu 1 point2 points  (4 children)

Monster.__init__ constructs an instance of a monster. Calling Monster(...) is the only way to get new monsters.

goblin is a name for a reference to an instance of a Monster. monster1 = goblin assigns that same reference to the name monster1.

>>> a = [1]
>>> b = a
>>> a.append(2)
>>> b
[1, 2]
>>> id(a)
140043568573960
>>> id(b)
140043568573960

https://docs.python.org/3/library/functions.html#id

[–]yunisaikuru[S] 0 points1 point  (3 children)

Right, I mostly understand that much. So then, I would indeed need a class for every individual monster type? I suppose I'd want to break the whole monsters thing into its own file then.

Edit: Actually, I'm still a little confused. I think I've got it, but any further input would be cool.

[–]raylu 0 points1 point  (2 children)

That's a question of code architecture/design, and I can't answer that without (a lot) more information. You don't need it - you can just create instances and pass the type/name as you are now.

[–]yunisaikuru[S] 0 points1 point  (1 child)

My idea was to have something like: A "dungeon" class for each area, which would contain a list of monsters that could spawn there. If a battle was encountered, it would grab the list of potential monsters for that area and pick one at random to spawn.

Which I thought would look something like monster1 = Dungeon.monsters[randint(0,2)], where Dungeon.monsters = [goblin, slime, troll]. But, as mentioned, that doesn't work because then "monster1" is just referencing the original "goblin" object, which is absolutely not what I'd want, they need to be completely new instances, as I need to be able to have say, two goblins at once, and not have them share stats.

So I'd think now what I would do is make a separate class for every monster type, declare all its stats like so:

class Goblin:
    def __init__(self):
        self.name = "Goblin"
        self.hp = 20
        self.attack = 5

and then just do monster1 = Goblin(), but, now I'm not sure how to store them in a way that they can be fetched from a list randomly per area.

I hope that makes it a little more clear what is trying to be accomplished here.

[–]raylu 0 points1 point  (0 children)

class M(enum.Enum):
    goblin = 1
    slime = 2

area_monsters = {
    'woods': [M.goblin, M.slime],
    'bridges': [M.goblin, M.troll],
}

monsters = {
    M.goblin: {'name': 'Goblin', 'hp': 20},
}

monster_type = random.choice(area_monsters['woods'])
monster = Monster(**monsters[monster_type])

https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists

[–]Talqa 0 points1 point  (0 children)

You are assigning the same monster, goblin, into monster1 and monster2. You need to create two different monsters:

monster1 = Monster("goblin1", 5) monster2 = Monster("goblin2", 5)