Files
hpr-knowledge-base/hpr_transcripts/hpr2938.txt

216 lines
15 KiB
Plaintext
Raw Normal View History

Episode: 2938
Title: HPR2938: Naming pets in space game
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2938/hpr2938.mp3
Transcribed: 2025-10-24 13:36:58
---
This is HPR episode 2938 entitled, naming bets in space game, and in part of the series,
Hackel, it is hosted by Tuku Toroto, and in about 21 minutes long, and Karimaklin flag,
the summer is, how to use Markov chains to generate names.
This episode of HPR is brought to you by Ananasthos.com.
Get 15% discount on all shared hosting with the offer code HPR15, that's HPR15.
Better web hosting that's honest and fair at Ananasthos.com.
Hello, you are listening to the Hackel Public Radio and this is Tuku Toroto.
Today I am going to talk about how I implemented it.
In two previous episodes, we have built a great list, and used a great list to make Markov change.
This time we are going to use them to implement some space bets in our game.
In two previous episodes, we have built a great list, and used a great list to make Markov change.
And this time we are going to use them to implement some space bets in our game or bet in general.
And using them specifically for the names, this is very much work into progress.
Lots of things that I need to add and fine tune later on when I have sort of realized what I actually want to do.
But the idea is that any character can have bets, and those bets can have a take and be helpful in grants.
If you have a character who likes hunting, then the hunting talk is probably a good choice.
But if you have some sort of wizard with a lateratory full of delicate equipment, then the hunting talk is probably a spell for this after.
They can also provide health benefits and such, like if your character is stressed, then a guess might be a good idea or just funny events.
And I am going to skip a lot of code that is about the special events, because I made an episode about those already.
But the idea is that what I implemented is that there are small chance for a person to hear scarring sounds inside the walls of their quarters, this special event.
And then they have an option to choose, they can get a cat, they can try and tame the rat, that is making those sounds or they can let someone else to deal with the problem.
And those two first options result, a player, I mean the person getting a new bet, eat that or a rat.
And as soon as you acquire a bet, you get an other event that is for naming that bet.
So, and this is what we are using on Mark of Change.
So when that naming event is created, we are going to generate three names that haven't been used before for pets of that specific person.
Player can choose or person can choose any of those three, and then the bet is named to ask the choice, the person made.
Or you can say that somebody else can name it, in that case it gets completely random name, or you can just decide not to do anything that leads into the random name again.
And in order to have names to choose from, we first need to have some sort of, we need to generate them and to generate them, we need to have a configuration for name generation.
I'm not going to take very deep into how this works, I'm going to give you a high level overview, so we want to generate names.
I did this in a way that there's a big list of examples, and we feed those examples into the configuration.
And from that configuration, we can create new names that look similar to those old ones.
Because name is a sort of like a result of a Mark of Change.
It has a starting element, then it has elements that follow it, and then it has the ending elements.
And those elements are, in this case, letter pairs, like two letters.
And for creating that config, I have three functions, start, starting element into the configuration, links for recording a link between two elements.
For example, I can say links AB, and that means that from A, there's a chance of B following.
And there's the end, that's an ending element.
All these keep track of the wage, so if you call at A twice, then you have an inside of the configuration you have an A element that has a weight of two.
Okay, so for adding a component of a single name, we just chop the name into pieces of length of N.
These are, these are at name function in the show notes, that you might want to have a look if you want to ask, if you want to see exactly how it's done.
But first we are going to chop the name into pieces, we are calling it chunks N, S, where the S is the name, N is the amount of the letters we want to jump into.
So, at that point we have a list of elements that have length of N, the element is the text.
Then we want to combine those elements, in a way that I want to combine the first element to the width, I mean I want to make a table of the first element, the second element, the second element, the third element, the fourth element.
And this is done with writing chip elements, save the elements.
Okay, what does this do is that we take a save the element that takes the tail of the list, everything but the first item.
So, if we have a list, 1, 2, 3, 4, save there gives you a list of 2, 3, 4.
Then we are going to chip elements with that tail of the list, so that chip combines two lists, one item for both lists, makes a table, takes the next table.
So, after this we get a list of table, 1, 2, table, 2, 3, table, 3, 4, which is exactly what we want.
So, now we have a list of all the other elements with the consecutive elements, now we are going to fill the configuration.
So, we just call start elements config, so that takes our configuration, that is, and then add the start element, start element, so first element from the elements list.
Then we call element, end elements for that result of that previous call, that add the last element of our name into the configuration.
And then we call links to the result of the previous call, and we get those links added to them into the configuration, and that's it.
And now that we have, now that we have way to add single name into the config, we can just process a list of names, and this is done by folding them, so we are just doing folder, add name end, empty config access.
And end is now again the size of the chunks, and the access is the list of examples.
So, what does this tool is that it takes the empty config as an initial starting point, it takes the first item of our examples, the name called applies add name to that.
And to that configuration, so we get a new configuration, where we call the add name, to where the add name has been folded into, and then we take the next element of the list, call add name to that using the new configuration and proceed through the list of examples,
just always using add name to add that name into the process that name and add that into the configuration.
Okay, now we have a configuration, what we do next is that we need to generate some names based on the configuration, and the mark of chain generated from that configuration that we just created, that's just a list of two letter strings, that's not quite a name.
So, we make a help of function called names, it's again in the show notes, but this one takes a function from text to B, B can be anything, and then it takes the config text, a G that random generator and returns a list of B.
And this generates an infinite list, how we are processing, how we are doing this is that it's quite a lot of fact in the small space.
I'm just reading quickly, so it's nab, dollar, parente, dot, dot, dot, dot, dot, dot, dot, parent, dollar, diamond, change config G.
So it doesn't work well, I just walk through that.
We start to decide to read this, is to start from the right.
So change config G, change is what we defined last time.
So we are using that configuration and that random generator
that are packed in as parameters and calling change to generate
infinite list of change.
Then we are creating a new function on the fly using function composition.
That's that the d dot dot dot dot conkat part.
And conkat, so this works in a way that it just blocks the functions one of the each other.
They have a matching in the faces so we can do that.
So what we do is create a function that takes a single parameter,
runs conkat to that, meaning it combines a, it combines our list.
It combines a list of items into single item.
So we have a list of texts.
So it combines them into single text.
Then it calls to title it to capitalize it properly.
First letter is uppercase, rest is lowercase.
And then it calls t to that, t is a function from text to b.
And this is used in the end to turn our text into something more specific.
And then it, now that we have this function, that takes a list of strings
and turns it into a capitalized string from into something.
And we are running that with that dollar diamond to each and every chain mark of chain we have.
And then the last thing is that we are calling nub to that infinite list of names.
And that nub is going to, it's a filtering function that makes,
ensures that each and every element coming through it is unique.
This nub is a, nub is nice that you can use it on an infinite,
struct data structures.
The drawback is that the longer list it has the process, the slower it gets.
The usual trick that I used to make a list of something into unique
and having only unique elements is that I turn it into a set,
because set only has one of it and then that set back to the list.
That's the drawback, it has two drawbacks.
It doesn't work infinite elements, we infinite lists,
and it doesn't preserve the order of the list.
But here order doesn't matter, but we have an infinite list,
so that's why we are using map.
So now we have a function that can generate us names.
So in this example, the function text to, text ROB,
we are going to use mkbetname, that's a malware constructor making a betnames.
But later on, I'm going to use first name and semi name and ship name
and whatnot to generate all kinds of different parts of names,
because I like to keep types so relatively specific
so that you don't accidentally mix, for example,
third name and family name with each other.
So with these names, health of function we can just define our betnames
to be names, mkbetname, creeknameconfig.
Creeknameconfig being a configuration for creek names.
And now we can generate infinite lists of sort of creek looking names.
I had a list of instant creek names at hand, so I decided to use that one.
Okay, it's a very much working progress.
They are stored in a separate database table, of course.
They have few values like name and type and date of third,
possible date of date and order ID.
And that types are currently just cat and rat,
probably going to add more interesting ones later on
when I actually have a better idea of what kind of things I want to do with them.
So the actual name in the betnames.
We have a function name and betname that is called
when a person occurs a bet.
This takes a parameters as a person, bet, current date.
And it creates a, it creates you a special event.
It doesn't store it into the database, it just creates that.
So what the actual code is, again in the show notes,
I'm going to read through it, I'm just going to walk through how it's done.
Because this is pretty, this is quite a bit of code.
So first step, we are using select list to run database query
and load all the pets that are alive and belong to that.
We are giving this a betname event.
Then we are extracting names from those pets.
It's just using the betname function to get names from the pets.
We create a new random generator.
Using lift IO gets SDDchan.
This just gets the standard random generator.
After that, we have the generate list of petnames with petnames C.
We filter that by selecting, by we filter that,
checking that that element isn't in the names list that we loaded from the database.
So we only get the unique list of names that are not already used by these characters.
And then we take three first ones.
And then it's just a matter of creating a naming pet event
where we fill in all the information,
better from pet type, current date, and list of available names.
And then we return this out of the function.
And then the whoever is calling this naming pet event function
needs to save that special event that was created into that event.
This one isn't doing it.
This one is only concerned on creating them.
And well, that's basically what is all about.
For that, for this, we created the Markov chain that we can create names of the pets
and later on, names of all kinds of different things.
So the names are probably one of the most common applications of the Markov chains in games.
You can use them for other things that you are generating things from the based on the examples.
For example, if you want to create some nonsense articles
that on a first glance look like real articles, you can use this method.
You probably would chop examples into the based on the words,
not into small, not into the groupings of letters,
or into either to hold words or even groupings of words.
So you have a bit more sort of reason in the generated text.
You could even generate whole books if you wanted by this,
but there would be nonsense.
If this all sounded confusing, it's probably just my explanation.
Haskell is pretty relatively simple language.
It's like writing a bike.
Once you learn it, it is basically everything.
Things that you know are easy, things that you don't know.
And until you learn it, reading about it or listening about,
listening to podcasts about it might be interesting,
but that doesn't really teach you how to do it.
So if you think of analogy of writing the bike,
you can read all about how to write a bike,
how to lean to the correct direction,
and the breadth, marriage of hook,
better letters, lock, better letters,
normal turtles, and what kind of frames you have.
But all that, while interesting,
doesn't really teach you how to write a bike.
You have to just get on the bike and write it until you
either stop trying or learn how to write.
And then after that initial hump,
the rest is just beating up the strings.
So if you have any questions, comments,
or feedback they always welcomed,
best way to reach my nowadays is on email,
or in peripherals where I'm to do to my current social,
or even better you can record your own episode
for the Hague Public Radio.
Ad Astra.
You've been listening to Hague Public Radio at Hague Public Radio.org.
We are a community podcast network that releases shows
every weekday Monday through Friday.
Today's show, like all our shows,
was contributed by an HPR listener like yourself.
If you ever thought of recording a podcast,
then click on our contributing to find out
how easy it really is.
Hague Public Radio was founded by the digital dog pound
and the Infonomicon Computer Club,
and is part of the binary revolution at binrev.com.
If you have comments on today's show,
please email the host directly,
leave a comment on the website,
or record a follow-up episode yourself.
Unless otherwise stated,
today's show is released under
Creative Commons,
App Tribution,
ShareLite,
3.0 license.