1

I found this fantasy name generator here.

I am trying to adapt the code to suit my purpose. I want to create an NPC name automatically, using the function name_gen within the class NPC. With the NPC characteristics being:

class NPC:
  def __init__(self, name, age, gender):
    self.name = name_gen
    self.age = 25
    self.gender = M

The code from the name generator I need is the following:

from random import randrange

def line_appender(file_path, target):
    file = open(file_path, "r")
    splitfile = file.read().splitlines()
    for line in splitfile:
        target.append(line)

def name_selector(target_list):
    selected = target_list[randrange(len(target_list))]
    return selected

def name_builder(first_name_list_path, last_name_list_path):
    first_name_list = []
    last_name_list = []

    line_appender(first_name_list_path, first_name_list)
    line_appender(last_name_list_path, last_name_list)

    first_name_selected = name_selector(first_name_list)
    last_name_selected = name_selector(last_name_list)

    name = first_name_selected+" "+last_name_selected
    return name

Now the only thing I think I still need to do, is to generate the name from within the class NPC. I thought doing something like:

def name_gen
    if gender == "M":
    name = name_builder("first_name_male.txt", "last_name.txt")
    elif gender == "F":
    name = name_builder("first_name_female.txt", "last_name.txt")

But I don't understand how to make the name_gen function check the class NPC properties, so that it generates the desired name.

Could someone perhaps help me out?

EDIT

Thank you for all the solutions! I am pretty new to Python; In order to test Samwises solution, I tried to run it as a separate script (in order to check whether I would get a name) with the code below. It does however not print anything. I'm putting this in an EDIT because I think it might be a trivial question. If it is worth posting a separate question, please let me know:

import random

running = True

npc_input_messsage = "npc = NPC(25, 'M')"

class NameChooser:
    def __init__(self, file_path):
        with open(file_path) as f:
            self._names = f.read().splitlines()
    
    def choice(self):
        return random.choice(self._names)

first_choosers = {
    "M": NameChooser("first_name_male.txt"),
    "F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")

def name_gen(gender):
    return f"{first_choosers[gender].choice()} {last_chooser.choice()}" 

class NPC:
    def __init__(self, age, gender):
        self.name = name_gen(gender)
        self.age = age
        self.gender = gender

while running:

    npc = input(npc_input_messsage)

# I'm entering npc = NPC(25, "M")

print(npc)
1
  • 1
    Re: your edit, you're not using input() in a way that's appropriate to what you're trying to do. Get rid of the while running and just put one line of code like npc = NPC(25, 'M') and then print(npc) immediately after it. Commented Mar 5, 2022 at 23:27

3 Answers 3

1

Your name generator is a little over-complicated IMO. I'd suggest wrapping all the file reading and name selection stuff in a simple class so you can define it once and then instantiate it for each of your name lists. Putting the file reading part in __init__ means you only do it once per list instead of re-reading the file each time you need to pick a name.

import random

class NameChooser:
    def __init__(self, file_path):
        with open(file_path) as f:
            self._names = f.read().splitlines()
    
    def choice(self):
        return random.choice(self._names)

Now you can define three NameChoosers and a name_gen function that picks among them:

first_choosers = {
    "M": NameChooser("first_name_male.txt"),
    "F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")

def name_gen(gender):
    return f"{first_choosers[gender].choice()} {last_chooser.choice()}"

And now you can define an NPC class that takes age and gender as arguments to the constructor, and picks a random name using name_gen():

class NPC:
    def __init__(self, age, gender):
        self.name = name_gen(gender)
        self.age = age
        self.gender = gender

    def __str__(self):
        return f"{self.name} ({self.age}/{self.gender})"


npc = NPC(25, "M")
print(npc)  # prints "Bob Small (25/M)"
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you very much for your answer. I am pretty new to Python. To check your code I thought trying to run your solution as a separate script and trying to print(npc) at the end to see what comes out. However, although it runs, for some reason that does not print anything. Do I need to do something special to print npc ?
It doesn't print anything? Or does it print something like <__main__.NPC object at 0x0000016C0DB5B820>? Try print(npc.name) -- or you can define a __str__ method inside your NPC class that returns a nicer-looking string!
I made an edit with the script I tried to run.
I tried print(npc.name), but it still just asks for input again. (So indeed, it does not print anything)
Try just running the exact code I posted. The way you set npc doesn’t work.
0

I think you're confused about OOP concepts.

First, let's edit your class:

class NPC:
  def __init__(self, name, age, gender):
    self.name = name
    self.age = age
    self.gender = gender

See, I have assigned parameter values to the attributes. Now let's make changes to your function:

def name_gen(gender):
    if gender == "M":
        name = name_builder("first_name_male.txt", "last_name.txt")
    elif gender == "F":
        name = name_builder("first_name_female.txt", "last_name.txt")
    return name

Here I have added a parameter to your function since you're using its value. Now let's create an instance for your class.

npc = NPC("Vishwas", 25, "M") # Instance of the class
print(name_gen(npc.gender)) # Print generated name

Comments

0

A straightforward way to make happen automatically would be to simply call the name generator from with the NPC.__init__() method. In the code below it's been made a private method of the class by starting its name with an underscore character. Note that the call to it has to wait until all the instance attributes it references have been assigned value.

from random import randrange


class NPC:
    def __init__(self, age, gender):
        self.age = age
        self.gender = gender
        self.name = self._name_gen()

    def _name_gen(self):
        if self.gender == "M":
            name = name_builder("first_name_male.txt", "last_name.txt")
        elif self.gender == "F":
            name = name_builder("first_name_female.txt", "last_name.txt")
        return name


def line_appender(file_path, target):
    file = open(file_path, "r")
    splitfile = file.read().splitlines()
    for line in splitfile:
        target.append(line)

def name_selector(target_list):
    selected = target_list[randrange(len(target_list))]
    return selected

def name_builder(first_name_list_path, last_name_list_path):
    first_name_list = []
    last_name_list = []

    line_appender(first_name_list_path, first_name_list)
    line_appender(last_name_list_path, last_name_list)

    first_name_selected = name_selector(first_name_list)
    last_name_selected = name_selector(last_name_list)

    name = first_name_selected+" "+last_name_selected
    return name

if __name__ == '__main__':
    npc1 = NPC(25, 'M')
    print(f'{npc1.name!r}')
    npc2 = NPC(21, 'F')
    print(f'{npc2.name!r}')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.