Home > Software design >  Convert type string object to type class object in python
Convert type string object to type class object in python

Time:11-19

I have some code for a discord bot I am building that I want to make cleaner. Instead of writing a new if statement when a new enemy is made, I would like to check if a user input is already an enemy(class object) and then preform an action on that class object of the same name.

Below is the code for building an enemy.

class EnemyCreator:

type = 'enemy'

def __init__(self, name, enemy_type, health, ap):
    self.name = name
    self.enemy_type = enemy_type
    self.health = health
    self.ap = ap
    info = (name   ', '   str(health)   ', '   str(ap))
    npc_info.append(info)

And here is an example enemy:

skeleton = EnemyCreator('Randy Bones', 'skeleton', 100, 2)

I have an attack function:

def attack(enemy):
    enemy.health = enemy.health - playerChar.ap
    if enemy.health > 0:
        playerChar.health = playerChar.health - enemy.ap
        return ('You attacked '   enemy.name   '. '   str(enemy.health)   ' life remaining. \n'
                  enemy.name   ' attacks back! You take '   str(enemy.ap)   ' damage. You have '   str(playerChar.health)
                  ' remaining!')
    if enemy.health <= 0:
        return enemy.name   ' has been defeated!'
    if playerChar.health <= 0:
        return 'You died idiot.'

Then I have the input checked with this code:

async def on_message(message):
    print(message.content)
    if message.author != client.user:
        if 'test' in message.content.lower():
            print(npc_info)
        if '!attack' in message.content.lower():
            await message.channel.send(
                attack(message.content[8::))

However, this causes an issue because the object passed into the attack(enemy) function is a string, and I need it to be a class object. Any ideas on how to add this functionaliy?

CodePudding user response:

You should have a way of getting the existing enemies. I will propose something using an in-memory solution, but for a more robust/scalable solution, you should use a database (sqlite, Postgresql, Mysql), and for easy development, an ORM (SQLalchemy or Django).

An EnemyList would be:

class EnemyList:
    def __init__(self):
        self._enemies = []
    def new_enemy(name, enemy_type, health, ap):
        enemy = EnemyCreator(name, enemy_type, health, ap)
        self.enemies.append(enemy)
        return enemy
    def find_enemy(name):
        return next(filter(lambda enemy, enemy.name == name, self.enemies))

Then you would need to change your on_message function to use it

async def on_message(message):
    print(message.content)
    if message.author != client.user:
        if 'test' in message.content.lower():
            print(npc_info)
        if '!attack' in message.content.lower():
            await message.channel.send(
                attack(EnemyList.find_enemy(message.content[8::)))

This is the short answer, I won't add here other advice because they are not related to the question but you can also check:

  • String Formating
  • OO -> The attack function maybe should be a method of a playerChar object?
  • The DB thing I already spoke of.

CodePudding user response:

I found a solution. I have made a list of all enemy's along side their name. Then I return the index of the corresponding value to the enemies name. Below is what I came up with.

Enemy creation:

boss = EnemyCreator('Charles Hammerdick', 'boss', 10000, 200)
npc_list.append(boss)
npc_list.append(boss.name)

attack function:

def attack(enemy):
for thing in npc_list:
    if str(enemy) in str(thing):
        enemy = (npc_list[npc_list.index(thing) - 1])
        enemy.health = enemy.health - playerChar.ap
        if enemy.health > 0:
            playerChar.health = playerChar.health - enemy.ap
            return ('You attacked '   enemy.name   '. '   str(enemy.health)   ' life remaining. \n'
                      enemy.name   ' attacks back! You take '   str(enemy.ap)   ' damage. You have '   str(playerChar.health)
                      ' remaining!')
        if enemy.health <= 0:
            return enemy.name   ' has been defeated!'
        if playerChar.health <= 0:
            return 'You died idiot.'
  • Related