- MCP server with stdio transport for local use - Search episodes, transcripts, hosts, and series - 4,511 episodes with metadata and transcripts - Data loader with in-memory JSON storage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
333 lines
17 KiB
Plaintext
333 lines
17 KiB
Plaintext
Episode: 2703
|
|
Title: HPR2703: Fog of war in Yesod based game
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2703/hpr2703.mp3
|
|
Transcribed: 2025-10-19 07:45:16
|
|
|
|
---
|
|
|
|
This is HPR Episode 2,703 entitled, FOD on War in the SOD based game.
|
|
It is hosted by Tuku Toroto and is about 25 minutes long and Karima Clean Flag.
|
|
The summary is how to implement FOD on War System in turn based web game.
|
|
This episode of HPR is brought to you by archive.org.
|
|
Support universal access to all knowledge by heading over to archive.org
|
|
forward slash donate.
|
|
Support universal access to all knowledge of FOD on War in the SOD.
|
|
Support universal access to all knowledge of FOD on War in the SOD based game.
|
|
Support universal access to all knowledge of FOD on War in the SOD based game.
|
|
Support universal access to all knowledge of FOD on War in the SOD based game.
|
|
Support universal access to all knowledge of FOD on War in the SOD based game.
|
|
Support universal access to all knowledge of FOD on War in the SOD based game.
|
|
Hello my name is Tuku and you are listening to Hacker Public Radio.
|
|
Today I'm going to look how to make a one way,
|
|
today I'm going to look into a fun way of making a FOD on War in a desert based
|
|
web game.
|
|
Premise is that there is an unknown simple web test.
|
|
Space exploration game and big part of the Space exploration game is of course exploration.
|
|
So you need to have something to explore.
|
|
But it's not fun if you immediately in the beginning of the game
|
|
have a complete view of everything that is in the game.
|
|
So there's a sort of a dual of the universe, two sides of the universe.
|
|
There's this part that really is and there's this part that the players see.
|
|
And even more every player have a slightly different view of what they
|
|
because they start from the different planets and exploratory different directions
|
|
and do the different kind of things.
|
|
So the first part, what really is, is used for the running that reasonable simulation.
|
|
And the second part is what gives the players chance to explore.
|
|
So the solution I game up for this is a relatively simple, I like simple solutions.
|
|
So the real situation is stored in the database.
|
|
For example, there's a one table for the star systems.
|
|
One table for the stars that are located in the star systems are the table for the planets.
|
|
And another table that stores the population of the planets.
|
|
And one table that stores the buildings that are located in the planets.
|
|
So basically one table for the type of entity.
|
|
And then there's a separate tables that met almost one to one with these ones.
|
|
That has to use to store reports or observations.
|
|
So there's a small table, then there's a star, a star report table.
|
|
And planet report and population report and building report and so on.
|
|
And all of these report tables are connected to a faction.
|
|
If you remember every player is a part of a faction.
|
|
The essentially is just a group of players that work together and it's the faction
|
|
who owns the planet and has the shipments and so on.
|
|
But every report table is connected to a faction.
|
|
Basically this is a following key to the faction table.
|
|
And this causes the...
|
|
This is because then it's the faction that has the view of the universe.
|
|
If there's a two players that form a faction and one that is first one direction and another one to the other direction.
|
|
They automatically share all the things they find.
|
|
They let one.
|
|
Basically all the players in the faction have the same view of the universe.
|
|
Okay. And these reports are also tied in time.
|
|
There's another column that tells this observation or report was done.
|
|
And reports are almost always in partial and they may even be incorrect.
|
|
So for example, when a ship arrives to a new system, they might initially spot very crude details like this.
|
|
But okay, here's a star and then there's a sum amount of planet.
|
|
And if they start doing scientific observations in the system, they slowly start accumulating more information.
|
|
For example, they get the luminosity of the star or stellar class or they measure the gravity of the planet
|
|
and measure what kind of atmosphere it has.
|
|
All that information slowly starts accumulating.
|
|
Sometimes they might make mistakes and then a bit later they might correct those mistakes like what they are thought.
|
|
But this planet is...
|
|
gravity is one C but it's actually later on realized that it's 0.98 C's.
|
|
And at this point it might be a good idea to have a look at the show notes.
|
|
I have shown how they...
|
|
I'm going to use a planet as an example and I have copied the definition of the planet and planet report tables.
|
|
So basically the planet has a name, position in the system like we from 1 to n.
|
|
Link to the sciences to make this.
|
|
It might have an owner that is a fraction who has the owner's report planet.
|
|
Oh, it might not help if it's a completely answer to planet and gravity.
|
|
And the report has the same similar information, it has the...
|
|
But it has a link to the planet that is the report is about.
|
|
It has the owner that is the fraction.
|
|
It has the link to the space system that the planet is located.
|
|
And it's a name, position, gravity.
|
|
And the information when it was...
|
|
When the observation was made.
|
|
But if you look, you notice that these information are...
|
|
For example, gravity is double maybe.
|
|
And position is int maybe, meaning that it's a...
|
|
The information might or might not be present there.
|
|
In the code, wherever there's a gravity regarding to the planet, it's always double.
|
|
But in the planet...
|
|
In the code, the planet report is maybe double.
|
|
It may be nothing, meaning that the observation hasn't been done.
|
|
Or it may be just double, meaning that observation hasn't been done.
|
|
And the same number, and no, no.
|
|
So, there's a lot of maybe, maybe...
|
|
Feel Center reports.
|
|
Okay.
|
|
As I said, reports are cumulative.
|
|
So the...
|
|
The multiple, multiple observations are done.
|
|
About the same entities over the time.
|
|
And this...
|
|
And when the player is viewing the information,
|
|
all this information is actually created, compared to the one single report
|
|
that is shown to the player that this is the current information you know about.
|
|
So the basic tests are entities.
|
|
These are the planets.
|
|
They test the report, planet report, and then test the...
|
|
These are stored in the database.
|
|
And then test the final thing, collated report that is shown to the players.
|
|
So, I'm going to have a closer look in the gold next.
|
|
There's a...
|
|
This code uses some pipe classes.
|
|
They are really common in Haskell there.
|
|
Basically they define a set of operations that can be performed to instances of the pipe class.
|
|
For example,
|
|
For example, number type class in Haskell defines that you can add and subtract and multiply
|
|
instances and then there's a...
|
|
You can...
|
|
Then there's a defined hat there.
|
|
Then the Haskell defines instances in and flowed and such for the...
|
|
For the pipe class.
|
|
Meaning that you can multiply in the case.
|
|
You can multiply tables.
|
|
And I approached this by dividing the whole process into...
|
|
A whole process into several sets.
|
|
So first we need to get that data from the database and transform it into the form that can be processed.
|
|
And getting the data from the database is persistent.
|
|
A lot of people handle that for me.
|
|
But to transform that data into something that is more easily processable,
|
|
I have a report transform type class that defines one operation from the report.
|
|
And this is...
|
|
Usually match one to one between the report and the database and the collated report.
|
|
But in some cases, it's possible to add some extra data.
|
|
For example, for the population, the population table stores just a raise ID.
|
|
There can be different raises like their runs and such in the game.
|
|
But the population table stores only a raise ID.
|
|
And the raises are defined on a different table.
|
|
And in this report transform phrase that ID is used to place the name of the raise into the collated report.
|
|
That way when the player gets the report they know that it's about the name of the raise.
|
|
That is in happening a planet instead of just the ID.
|
|
But in case of the planet and planet reports, it's just a one to one mapping basically.
|
|
Okay, now that we have a stack of reports about several planets,
|
|
some of those reports might be about the same planet and some of the reports might be different planets.
|
|
This situation could be that the seed has arrived into a star system and they have been observing the system of the scientific officer
|
|
as a huge stack of or rather huge pile of reports on that table.
|
|
I need to make some order on it.
|
|
So I defined a class called, that class called cropped.
|
|
That is used to indicate if two reports are about the same entity.
|
|
So it again defines only one function, same group.
|
|
That takes two reports, sorry two collated reports.
|
|
And actually it takes two of anything that has been defined to have an instance of the group.
|
|
But it takes two of those collated reports and tells if they are about the same entity.
|
|
Usually it's the simple comparison of the primary piece.
|
|
And that's exactly what we are doing in the case of the planet reports,
|
|
because these are just comparing the planet ID of those or reports if they are the same,
|
|
then they are about the same planet if they are not the same entity or not about the same planet.
|
|
Okay, and now that we have sorted those planets on a sort of reports into need stacks,
|
|
we need to combine one stack into a single report.
|
|
So all the information that has been collected for example about Venus will be squeezed and aggregated into one report.
|
|
And that is the pattern, or the pattern maybe is the pattern.
|
|
These are easy way to combine these stack, one stack called monoid.
|
|
And these are, if you start programming in Haskell, monoids are going to run into them all the time.
|
|
They are very common.
|
|
It is a simple abstraction, mathematical abstraction.
|
|
And basically it defines that there's an object in how case a planet report,
|
|
sorry collated planet report, and an associative binary operation that is used to combine these.
|
|
And then there's an empty element.
|
|
And then there's a couple of rules, how these should work.
|
|
For example, in case of text, which is really a list of characters,
|
|
if you have A, B and C, and you combine them with this operation,
|
|
you get a string A, B, C altogether.
|
|
But if you add some parenthesis, you have A plus B inside of parenthesis plus C.
|
|
That is equal to A plus B plus C inside parenthesis.
|
|
So all the things are combined matters.
|
|
But like you cannot just move, switch A and B around and get the same result.
|
|
Of course, that's a different.
|
|
But adding parenthesis doesn't matter.
|
|
And then there's the empty element.
|
|
That A plus empty string is A, and empty string plus A is again A.
|
|
So this is what forms a monoid.
|
|
And also every monoid is also semi-group, which is just this binary operation,
|
|
without the empty element.
|
|
So how this mathematical notion relates to collated planet reports is
|
|
that if you have a stack of collated planet reports,
|
|
we can just take two of those and make a third one,
|
|
where all the information of the old one is superimposed with a new one.
|
|
So basically, we are just collecting the newest information that is available.
|
|
And then we need that empty report.
|
|
In case we don't have anything, or if you have,
|
|
then we have just a collated planet report where all the fields are nothing empty.
|
|
And then I had to take a, I didn't really know what's the best way.
|
|
So I ended up setting the, for entry, keys to zeroes,
|
|
and the dates to zero to indicate this information is incorrect.
|
|
This might not be the best way of doing that,
|
|
but I couldn't figure out a way to around this.
|
|
And if we define these type classes,
|
|
or are the instances of these type classes to have our entries,
|
|
the actual processing is just a couple of lines.
|
|
But I'll try to find a better explanation about the monoid and what it is about,
|
|
and link it into the show notes.
|
|
So the actual processing, now that we have defined all these auxiliary functions,
|
|
is that the collated report function,
|
|
that this is for the single entity.
|
|
This takes a, this takes a list of things,
|
|
and these things must have a report transform type class,
|
|
and it produces a single thing,
|
|
that has to be a result of that report transform,
|
|
and also form a monoidal instance.
|
|
And the actual implementation is just M concat map from report to reports.
|
|
For, for, for, for words.
|
|
And this just, first it maps the reports from the database,
|
|
the address and the tion into that collated representation,
|
|
and then it uses M concat to squeeze all those collated reports into a single one.
|
|
And M concat is defined by the hospital,
|
|
in the, by the terms of the, that diamond operation,
|
|
that single binary operation that we talk about a little bit later,
|
|
that we define, when we were defining the monoidal instance.
|
|
And for the multiple reports, the situation is slightly more complex,
|
|
because now we have a stack of these things,
|
|
and we are producing stack of these things.
|
|
So we have a stack of, but we have a stack of something
|
|
that can be used in the report, report transformation,
|
|
and we are producing a stack of things,
|
|
that are a result of that report transformation,
|
|
form a monoid, and also that first item has to be something
|
|
that can be grouped like we, we can tell that,
|
|
what is about the same entity.
|
|
But that basically is just in that,
|
|
I defined that in a two steps,
|
|
like the special case is when you have an empty list,
|
|
then you, the result is an empty list, that's easy.
|
|
But if you have something on your list,
|
|
then you are first going to split them,
|
|
you are the code collected, that is often,
|
|
it picks the first item,
|
|
collects from the list all the items that belong to the same group,
|
|
and then it collates them with the earlier function,
|
|
and then it takes the next item that hasn't been processed,
|
|
and that's the same thing.
|
|
Okay, but all this happens on the server side, of course,
|
|
and the data on the server is going to help the player match
|
|
at all, they need to see that,
|
|
so we need to send it to the client somehow.
|
|
There's two ways we can render it as an HTML page,
|
|
or we can send it as a JSON,
|
|
and in the example I'm going through the hit,
|
|
change on, and the first we need to define a way
|
|
how to transform our report into the JSON,
|
|
and template Haskell offers as a shortcut.
|
|
We can just use the derived JSON with default options,
|
|
or our collated planet report data,
|
|
and it will create as to from JSON and to JSON instances.
|
|
Now we can, now we can, with a single call,
|
|
transform JSON into a,
|
|
we can actually transform JSON message into collated planet report,
|
|
and the vice versa collated planet report into JSON,
|
|
and now the code to actually do all this
|
|
is again pretty short.
|
|
There's a handler that takes a key planet.
|
|
This is the primary of the planet we are interested in,
|
|
and returns a handler value.
|
|
This is JSON in our case.
|
|
First, that is to check that the player is actually
|
|
a mentor of a faction,
|
|
and before that the code checks
|
|
that they are actually locked in and outindicated.
|
|
And if this fails, they are going to get,
|
|
I don't remove what error code they are going to get,
|
|
maybe 500, maybe something else.
|
|
But if this check passes,
|
|
then we are loading the,
|
|
using the persistent select list
|
|
to load all the planet reports
|
|
that are of this given planet,
|
|
and are made by the section that the player is member of,
|
|
and we are sorting them by the report date.
|
|
And then we are just calling the collated report
|
|
to take this loaded data
|
|
from into the collated planet report.
|
|
That not entity law is there
|
|
because the loaded planet reports,
|
|
the planet reports that are loaded
|
|
from the database tables of two items.
|
|
First element is the ID,
|
|
and second element is the actual report.
|
|
So doing the not entity law gives us the actual reports.
|
|
And then we are going to just turn that into the JSON
|
|
with a two JSON code and return it.
|
|
So I really like how simple it looks
|
|
at this level.
|
|
Like, just authenticate the loaded data
|
|
to the report,
|
|
to turn the player down.
|
|
And the actual report thing
|
|
is not that complex.
|
|
It's just quite a bit of stuff to write there.
|
|
And of course you have to write that
|
|
for each and every entity type in your game.
|
|
That's quite a bit of type.
|
|
Okay, I'm going to call this off.
|
|
And I will be interested to hear
|
|
if you have written something similar,
|
|
or tackle the similar problem.
|
|
And what do you think about the approach in general?
|
|
Okay, until next time,
|
|
this is Doug, signing off.
|
|
You've been listening to HackerPublicRadio
|
|
at HackerPublicRadio.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 contribute link
|
|
to find out how easy it really is.
|
|
HackerPublicRadio was founded
|
|
by the digital dog pound
|
|
and the Infonomicon Computer Club.
|
|
And it's 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,
|
|
Attribution,
|
|
ShareLife,
|
|
3.0 license.
|