Episode: 2908
Title: HPR2908: Modeling opinions in space game
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2908/hpr2908.mp3
Transcribed: 2025-10-24 13:04:30

---

This in HPR episode 2988 titled, Modeling Opinion in Space Game, and in part of the series,
Haskell, it is hosted by Tuku Toroto, and in about 35 minutes long, and Karima Clean Flag,
the Summer Inn, Tuku Toroto talks about Modeling Opinion.
This episode of HPR is brought to you by AnanasThost.com.
Get 15% discount on all shared hosting with the offer code HPR15. That's HPR15.
Bitcher web hosting that's honest and fair at AnanasThost.com.
Hello, you are listening to the Hacker Public Radio and this is Tutur Tottenham of Making
at Space Game in Haskell. Today, we continue with people, this time with the Opinions.
There is some more code around this time, but it might be a good idea to follow it,
shown once I try to keep the amount of code that I'm reading aloud to the minimum though.
So, Opinions. Different kinds of people get along with each other at a varying degree.
And in the game, this is modeled with the Opinions code. It can range from minus 100 to 100.
The 0 is neutral, minus 100 is the worst, and 100 is the best possible.
And Opinions may affect to the things like trade deals or marriage proposals or declarations
and such. And current system is somewhat limited. There are two things that are taken into account.
Currently, there's a trade and relations. Trades are defining things about characters.
You can be, for example, brave or coward or diligent or whatever. These are well-straighted.
So, for example, two brave characters automatically like each other a bit better than
prey than coward. And relations are relations between characters like parent and child,
automatically we like each other better than just a random person. And two rivals will hate each
other so much that it takes a lot of work to work over that. So, parent and child have a positive
opinion of each other or that relation contributes positively to the opinion. And two rivals will
have a negative opinion of each other. And to make things even complicated, all this is based
on the interlevels which may lead into the incorrect results just like in the real life.
So, if you don't have inter of some character, you don't get as good as good information about them
than if you have the inter. And the report, there's always reports
that have a whole different levels of information. And this is modeled in the report
press would data. That is, that's for internal use only. Client never sees that one.
And it has two things that actually three things he's struck off.
Confidence level, like what level of confidence you have on this result. Then there's the
opinion score, attention to minus 100 to 100. And they might be a list of opinion reasons.
It tells you that why you don't like somebody or why somebody else doesn't like,
why two characters that are not you don't like each other or like each other. So, this is as a
reparture result. It's a numeration with three value constructors feeling level that takes
opinion score as a parameter. Reason level takes that takes an opinion score and a list of opinion
reasons. And details level that takes an opinion score and a list of opinion reasons.
So, if you only have a gut feeling of something you you too get a score, but you don't get a
list of reasons. If you have reasons level, then you have a, then you have a score and a list of
reasons. And if you have detailed level, you have a better or better detailed information about
this. There you have a score and it's the reasons. Two last cases look similar, but they turn into
a little bit different explanation and attention into the client. That's why I'm giving them separate.
Okay, and a reparture result has semi-group and monoid instances because I want it to be a monoid
so that two results can be combined. So, if I have two reparture results, I can just use the
diamond operator to smash them together. And the result is that the scores are added up and the
opinion reasons those lists are just concatenated. And then because there's three levels, the
feeling level reasons level, deep level, the A, when you combine two of those, reparture results,
the confidence level of the new result is the lowest one of the two. So, if you combine two
detailed level results, you're going to get a detailed level result. But if you combine
feeling level and detail level, you get a feeling level result. The scores are still added up
and the lists are opinion reasonable lists are concatenated. And the empty instance, sorry,
empty, you need for reparture result is a detailed level without opinion score of 0 and the empty
opinion reasonable list because you can combine anything with this value without that combined item
changing to anything. I wrote the, I wrote the instance declaration show note, they are not
particular interesting, I think, but if you if you want to have a look, they are basically
they are just combining the scores together and lists together and keeping the lowest of the level.
Okay, now that we have a reparture result that we can use to give track of the, what's what's
the, what's the result of opinion calculation we can get, get started. The, so, so like I said,
there's two cases or two sources, however you want to, however you want to think about it. And
first I'm going to tackle the opinion based on its rates. So, if you have two persons and
you know what rates they have, you can calculate or compute what's the, how they like each other.
And here's a thing, it could be between a player character and somebody, or it would be,
then the, then the results would be that how much the player character likes somebody and how much
that's a mother character likes the player. Or it could be between two, two, two different characters
that are not the player character. Then the, then the result will be how, how well they like each other
based on the information what the player has. This is, this isn't always true,
player might not have all the information available. So, in that case, it's just the,
the best, the best ability, the result is calculated to the best ability.
So, current system is based on comparing two lists of the rates. So, you need to, if you want to know
how, how the characters like each other, you have to have all their traits as a list.
So, if you have a present brave, that's a good, that gives you an opinion bonus. If you have two
ambitious characters, that's right, that gives you an opinion bonus. And this doesn't work on the
traits that alone cause an effect. So, if you have a character who, if I had a character in a game
who would have a hypothetical trait called dislikeable, which would, of course, everybody do,
dislike him regardless of their traits. This system cannot handle it. You have to have
two traits that can repeat the calculation. So, that, that is something that I need to add up,
at some, at some later point. So, I have a function, the basic, basic, very bottom function
is a trait, their opinion. That is, given two traits, trait vibes, for example,
trait and trait. And it returns, maybe, a couple of opinions go, opinion reason. So, maybe,
it's returned, because it doesn't necessarily, if you have some combination of traits that don't
cause bonus or malus, then it's, it doesn't necessarily does nothing. But if there's some
combination of traits, for example, trait and trait, then it returns just a couple, with opinions
go, let's say, five, or then, and the opinion reason of two trait characters automatically
like each other. So, given two traits, it will tell how that trait, how that combination affects to
the, affects to the opinions and the reason, reasoning behind of it. And in order to have a
nice format for, or audata, we have a little help of function, trait score, that takes two trait
types, and returns, a couple of opinions go, a list of opinion reasons. This is just a
small help function, that takes the result of that previous combination. And in case of nothing,
it returns empty, which is a couple way, the opinion score is zero, and the opinion reason,
list is just an empty list. But if there's a, if there's a value, if the calculation
produces a value, then it returns an opinion score, a list of one item. So this might look up
bit silly, why do I want to do it like this? But this is because, a couple of opinions score,
opinion reason isn't a monoid, you cannot combine them, but the, a couple of opinions score,
list of opinion reason is a monoid. Because, couple, the both elements are monoid,
is a monoid. Opinions score is a monoid, because zero is the empty element, and the addition
is defined as a, that combination function, opinion reason is in the monoid, because it's a,
I mean, you could, it's not that, it's not reasonable monoid, because if you combine two opinion
reasons, you would get an opinion reason as a one long string, two strings has been combined together,
that does not make any sense. So, but if you make, make it a list, then you can combine two lists,
you just add them up. So, two, two reasons cannot be added up in a sensible way,
but two lists of reasons can be added in a sensible, sensible way, you just combine the list.
And, all this means that, if I use, if I'm making tuples of opinion score, list of opinion
reasons, I can combine them with that, damal operator, and that will be handy, at some later point,
during this episode. Okay, so, in order to calculate the score, based on the trait, we, we do it
like a, there's a bit code, that there's a function trait score, that takes a list of trait type,
person intel, analyst of trait type, analyst of person intel, and producer report, report, report,
result. We need that, there's the first trait type is for the originator, and the
person intel, intel for that person, and the second trait type and person intel is for the target,
the names are kind of arbitrary in this case. So, I have two, two characters, I have
list of the trait, and list of the intel, that we have available of those characters,
and based on all this information, we are going to produce a report of result.
Inside of the function data, if it checks that the intel contains, both intel contains trait,
so we have a trait information of both of these characters, if so, we are going to return
detailed level, result with a score and reasons, if we don't have traits on those two characters,
then we are going to return feeling level, result with only score, and most likely in this case,
the trait list will be empty anyway, and how we are going to calculate the score and reasons,
this is our reading aloud, this is our open parent score,
common reasons, close parent, so we are making a tuffle, and this is distracting it,
automatically so we get two values, score and reasons, equals m-conquat,
to the trait base, score, time and to the originator phrase,
download after this target phrase, so that's a quite a bit of stuff,
packed in a small space there, I'll go and try to unpack and explain that a little bit,
so the trait base score is a function that expects two trait type values as parameters,
so but we call it with two lists of such values, and how we are doing this is that we are
putting that time or dollar between trait base score and first parameter, that means that it creates
a list of functions of the first parameter comes from the originator phrase list,
but second parameter hasn't been given yet, so they are waiting for that second parameter,
so trait base score, time and dollar originator phrase creates a list of functions that are waiting
for the second parameter, first parameter comes from that list,
after this diamond after this target phrase means that we are taking that list of functions,
and for each of those functions we are calling with all the parameters or with all the values
coming from the target phrase, so that diamond after this applies each function to each value
of the second list, and the result here is that if we have a two list, if those
elements, if those lists that we have both have two elements, we are going to get four function
cores, and how we are going to get a list of four results, so the trait base score will be
called first, first it will be called another hundred percent of the order order is, but it does not
really matter, the first element is the first element is the trait base score,
chord with the first element of the borrowed list, second is the first element of the first list
and second element of the later list, third one is the last second element of the first list and
the first element of the second list and the fourth one is the second element of the
first list and second element of the last list. So it just calls with every possible combination.
So this is a list applicator that we are using here. I might have talked about this at some
last point. But the end result is that we are going to trade Tesco with combination,
all combination with all combination of two lists of parameters. So now we have a peak list of
a report results but we are not interested on the peak list of report results. We want one list
of one report result and then we are using Mconqat to that list of results. Mconqat is a
general function that when given a list of monoids, you will just combine them together. So this
uses the time operator that we know that when we define the semi-group for the report result
and monoid for the report result. This is why we did it because now we can just call Mconqat
to that long list and it will combine all those values. It will take the empty value,
time and it will do the first value of the list, time and it will do the second value of the
third value list until the end of the list. So let's match them all together. The result is that we have
a double of opinion score list of opinion regions and then we, because we define this as an open
parent score, comma regions close parent on the left side of the equal sign. We are taking the
double apart and ending up with the value of score and value of regions and these we are returning
from our trade score function. This is probably kind of convoluted and bad explanation but if you
have a chance to look at the show notes, it might probably, I hope, make some more sense.
So based on the available Inter report result of correct level is created.
So if we know the threads of the port persons, we get details level and if we don't then we get the
feeling of result. And this is how we get the opinion or opinion result of the
based on the trade scores. Sorry to trade in the inter. So the second part of the
puzzle is the opinion based on the relations. This is even more convoluted. This I'm not
100 percent happy but I couldn't figure out better later on doing this.
So this is a, this is a basic somewhat similar but it's a bit more complex. So the
intel here is two dimensions, the relationship visibility and level of detail. So you can have
a base opinion in the choices for opinions and detail opinions. And that second dimension is
opinion of two people, other than your character. So I hope that we will be a bit more
clear when I explain that. So the relation score is just like, again, it's a person in the list
of person in the list of relations and we are going to get a report result out of that.
And we need to take account of what level of intel we have about opinions and on
what detail. This is the enough function or intel. Visibility is unique relation,
visibility is that existing in relation in that particular case and the score is computer
present relation. So in the code, in the account, in the relation score, intel,
relation equals to m-conquat. So the relative report or intel score,
so that I'm going to do the visibility. So we are calling a real report function with the intel
we have available about this particular case, score that we calculated depending on the relation,
we have outlined the visibility that we have. This is an entity so that this can't be followed
without show notes, sorry, sorry about that, but I couldn't get this clean no matter how I tried.
But so the bottom line is that the real report function is the one that is doing most of the work.
And for that, you are going to give a parameters of opinion in the list,
opinions, a couple of opinions called list of opinion reasons, relation, visibility,
result, result, result. But what it does here, it's first it tries to find
matching intel of what this particular case, like depending on the
what type of relation it is, is it a familiar, is it a public relation, which is known to everyone,
is it a familiar relation, not only a small group of people, or is it a secret relation,
known only to those two particular persons. So it tries to find a visibility that matches.
And if there's no matching visibility, then you just get a feeling level, the result, if there's a,
if there's a matching, matching a visibility, you can get a feeling level,
a reasonable level, or a detailed level, depending on what type of information you have
for that particular character. Because like I explained it earlier, if you have two characters
that need a one of them is you, and you are trying to figure out how much they, what's the opinion of each other.
You have to have intel of those characters, which traits is easy, because you either have that
information or you don't have that information. But when you're trying to figure out how they
like each other based on the three relationships they have, you have to have an intel on
relationships. Of course, and that intel has a, that level that you can have an intel on,
you always have an intel on public relationships, because they are public. But you might have a,
you might not have an intel on the upper, the secret relations, because you know,
the secret. You have to, you have to work on to get that level of information out of them.
And you can have, because you have two characters, you could have a full intel on one character,
and you could, you would have a thin minimum intel of the another character. And based on that
info information, you can try to guess or compute what, how would they like each other.
And this is based on the intel you have, this cannot take into account, but intel,
those characters have about each other. For example, you might have an intel, secret intel about
both characters. That will tell that they are, they dislike each other, utterly, because of some
relationship they have with some thought person. But because those two characters don't have that
intel about each other, they might have only a public intel about each other. They don't know about
that secret relation that another character has. So the opinion of each other is different than what
you, what you compute it to be. So this is, like, you cannot, you cannot know what those characters
know and calculate the relationship score, opinions score based on that. You just don't,
you just don't have that information. You have to go based on the information you have about
those characters and make that best effort estimate. Okay, so that's why this is the
convoluted and not giving correct results. So to put all of this together, we combine results
of these two functions. So we have, we have an opinion result based on the traits and we have an
opinion result based on the relationship, relationships. And we can combine these with the
animal operator because they are just two, two opinion results which is done more than to get
one result where the scores are summed up and the reason lists are connected together and
confidently level is lower off the two. So that, that one monoid and semi-group
instantly declared earlier that gets quite a bit of use and I found it really handy here. And
when we add more factors that might affect to the system or to the opinion, it's just
with the time of the results together. It should work just fine. Okay, so now that we have
a very important result, we need to transfer into some information that we can return to the client.
And here we have an opinion report. The opinion report is the thing that we are returning to the client.
We are not returning that opinion report side because it, it, it, it is a bit too much of
information. We could feel that that information with the client, but we don't want to do that.
We want to return to the client only the information that they actually have access to and actually need.
So we have a function report result to opinion result that they've done.
Reparture result and retention of opinion result. And because opinion, opinion report is a,
it, it's a number of three values. It's a base opinion report of beta, with the opinion feeling.
Oh, it's an opinion, the reason report with opinion feeling and list of opinion reactions. Oh,
it's detailed opinion report with opinion score list of opinion reactions. So it matches
to that, to that report result by that we defined earlier with, bit, bit of changes.
So if we have a, if we have a, we feeling level at report result, we are going to get a base opinion
report with opinion feeling and opinion feeling is a, a number is just negative, neutral positive.
So we are going to turn that score that we spend a lot of effort to calculate into just a value,
is it a negative feeling, neutral feeling, positive feeling. I think the, anything below minus
15 is negative and anything above plus 15 is positive and minus 15 to be positive 15 is
neutral feeling. So if you, if the character doesn't have enough intel that's going to get a,
okay, I have a negative feeling or I think that car person has a positive feeling about that
person. If they have a, however, if they get an opinion reason report from the
computer, then they are going to get an opinion reason report. Then, to the client, here we have a,
again, we have opinion feeling. So it's an, a kind of negative, neutral positive, but we have a list
of reasons. So character can, can quantify if, got feeling a little bit better, like I don't like
that character because they are ambitious, ambitious and I am ambitious, so they are dangerous for me.
Or I bet this character likes that auto character because they are both cardiners, for example.
So again, you just get that feeling, but you have a bit more information why you get that feeling.
And the last one is that if you have detailed level,
detailed level report, you are going to the detailed opinions report where you have
actual score and the list of reasons. Here you can, here you can quantify things like
this character has an opinion of 25 of that another character because of this list of reasons.
And that's about, that's about what the opinions are currently. So by guys head,
Robert Erburtza based on the intel, in case of place own avatar, they have full intel of their own avatar.
So that's why the opinion about some other person is based, based on holy, on what we know about them.
But in case we are talking to somebody else's opinion about us, or person A's opinion of person D,
then we don't have, we don't have all that information, or we might have more information
that those other characters have which leads to incorrect results, but that's how it goes.
You know better what your yourself are thinking than what some other person is thinking.
So there's a change of misjudging things.
Okay, food or plants, I want to add more things that affect to the opinions,
like that single thread thing, like you might have a generally dislikable character,
that should be easy enough to add. It would be neat to have a history of actions.
Like if you know that there's some character who has consistently been really great,
you might like them slightly better because of that.
Or if there's some character who is a history of destroying planets,
you might dislike them quite a bit because of those history of actions they have done.
Culture could be a one thing that we could affect here. You have, you are, you probably,
as a character, probably doesn't like characters coming from different culture as much as
members of the own culture. And age could be thrown into mix. So if you are in a,
you know, maybe folks in the space, maybe some old general might naturally dislike young officers
or might like them depending on what kind of traits they have that old general.
Or if you have some really old general who is of opinion that nobody under,
under age of 50 should be a officer of some level, some certain level,
then that might affect to the opinion of the people around them.
So I'm going to finish it here. Questions, comments, feedback is always welcome.
Even better is if you record your own Hacker Public Radio every so,
this day to reach me nowadays is either email or very much there,
I'm due to but most of them that show so, hardass.
You've been listening to Hacker Public Radio at Hacker Public Radio dot org.
We are a community podcast network that release 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 and click on our contributing to find out how easy it really is.
Hacker Public Radio was founded by the Digital Dorf Pound and the Infonomicon Computer Club
and is part of the binary revolution at binwreff.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,
Attribution, ShareLite, free dot org license.
