I'm working on a small game with a procedural map. As the whole game is set in a labyrinth-like building I've decided to use tile maps.
The map generation algorithm produces a 2D matrix with 0s and 1s.
A 1 indicates that the tile is walkable while a 0 represents an impassable field.
In a simple 2D setting this could be represented by using a floor sprite for each 1 and a wall sprite for each 0.
However, this isn't very appealing.
Instead the visual representation of a tile should be depended on its neighborhood.
Each tile can have one of 256 (2^8) configurations.
These configurations can be reduced to 41 by considering rotations as one configuration.
As multiple configurations need the same wall layout we will only need 15 tiles to render the tile map.
My first approach to implement the rendering was to use shit ton of if statements.
The approach tested for all configurations to find the needed piece and rotation.
A few shortcuts prevented that I had to test for all 256 configurations but it was still too much.
After implementing this approach for 4 tile pieces I gave up.
My next idea was to represent the knowledge of which piece and rotation is required for each configuration in a lookup map.
This approach is similar to marching cubes where you need a lookup map to know how to construct the faces of a cube.
After writing down 30 entries of the lookup map I came up with the following idea (which I will call "Tile Strings").
Instead of checking for all 256 configurations, we only look at a 2x2 section of the neighborhood.
We start with the 2x2 patch in the upper left corner and determine the character it represents.
This character represents whether the left side of the tile needs a wall, a corner or needs to be empty.
The 2x2 patch is than rotated around the center to determine the characters for the other sides.
After the full rotation we have a 4 character string representing the configuration of the center tile, for example "WCCE".
This is our tile string.
Example code for a single 2x2 check (written in GDScript):
if cell(p + Vector3(-1, 0, 0)):
if cell(p + Vector3(0, 0, -1)) and not cell(p + Vector3(-1, 0, -1)):
tile_str += "C"
else:
tile_str += "E"
else:
tile_str += "W"
With the calculated tile string we can start to search for a suitable sprite or model in a library (our library should consist of 15 assets named by their tile string).
We still have to manipulate the tile string and determine the rotation, as we most likely only want to create 15 assets.
As the tile string represents a unique configuration we only have to rotate it (at most 3 times) to find a fitting configuration in our library.
We start by checking if the tile string already fits an element in our library. If this is the case we can just use it!
If no element fits we rotate by 90 degrees, by moving the last character of the string to the front, "WCCE" is transformed to "EWCC".
The number of rotations are counted.
We do this at most 3 times.
If you didn't find a fitting element after 3 rotations your library is not yet complete.
Once the rotated element fits, it can be inserted into our scene with the determined rotation.
Example code for finding an element in the library (written in GDScript):
var rotation = 0
for i in range(4):
if tile_str in library:
add_part(position, rotation, tile_str)
break
rotation += 90
cfg_str = cfg_str[3] + cfg_str[0] + cfg_str[1] + cfg_str[2]
Your library does not have to be limited to 15 elements.
Maybe corridors running north-south should have a different design than east-west corridors.
Just add a new element with the corresponding tile string to your library.
This approach only requires a few lines of code.
There is probably a lot of potential for improvement but it works perfectly for my use case.
The process of developing this once again showed me that it is worthwhile to take a step back and think about your problem.
The first two approaches showed me properties of the problem and implementing them (partially) deepened my knowledge, which ultimately led to the "Tile String" algorithm.
Momentan sterben täglich etwa 800 Menschen an COVID-19.
Eine Zahl unter der ich mir nichts vorstellen kann weil mir der Vergleich fehlt.
Was bedeutet es wenn ~800 Menschen pro Tag sterben?
einwohner = 83_000_000
tote_pro_tag = 800
prozent_tote_pro_tag = tote_pro_tag / einwohner
print(f"{prozent_tote_pro_tag * 100:.4f}%\tder Bevölkerung stirbt pro Tag")
print(f"{prozent_tote_pro_tag * 100 * 7:.4f}%\tder Bevölkerung stirbt pro Woche")
print(f"{prozent_tote_pro_tag * 100 * 30:.4f}%\tder Bevölkerung stirbt pro Monat")
print(f"{prozent_tote_pro_tag * 100 * 365:.4f}%\tder Bevölkerung stirbt pro Jahr")
0.0010% der Bevölkerung stirbt pro Tag
0.0067% der Bevölkerung stirbt pro Woche
0.0289% der Bevölkerung stirbt pro Monat
0.3518% der Bevölkerung stirbt pro Jahr
Das ganze in Prozenten auszudrücken macht es nicht viel besser.
Wie sieht es also aus wenn wir die COVID-19 Sterblichkeit auf andere Situationen übertragen?
Wie riskant wäre es zu fliegen?
fluggaeste_deutschland = 227_000_000 # Quelle: https://de.statista.com/themen/1060/flugpassagiere/
tote_fluggaeste_pro_tag = prozent_tote_pro_tag * fluggaeste_deutschland
print(f"{int(tote_fluggaeste_pro_tag)} Menschen würden täglich beim fliegen sterben")
print(f"{int(tote_fluggaeste_pro_tag * 7)} Menschen würden wöchentlich beim fliegen sterben")
print(f"{int(tote_fluggaeste_pro_tag * 30)} Menschen würden monatlich beim fliegen sterben")
2187 Menschen würden täglich beim fliegen sterben
15315 Menschen würden wöchentlich beim fliegen sterben
65638 Menschen würden monatlich beim fliegen sterben
zuggaeste_deutschland = 2_600_000_000 # https://de.statista.com/statistik/daten/studie/13626/umfrage/reisende-im-schienenpersonenverkehr-der-db-ag/
tote_zuggaeste_pro_tag = prozent_tote_pro_tag * zuggaeste_deutschland
print(f"{int(tote_zuggaeste_pro_tag)} Menschen würden täglich bei Zugfahrten sterben")
print(f"{int(tote_zuggaeste_pro_tag * 7)} Menschen würden wöchentlich bei Zugfahrten sterben")
print(f"{int(tote_zuggaeste_pro_tag * 30)} Menschen würden monatlich bei Zugfahrten sterben")
25060 Menschen würden täglich bei Zugfahrten sterben
175421 Menschen würden wöchentlich bei Zugfahrten sterben
751807 Menschen würden monatlich bei Zugfahrten sterben
Es ist schrecklich wie viele Menschen gerade an COVID-19 sterben.
Wenn man diese Werte in Relation setzt wird einem das Ausmaß erst richtig bewusst.
Niemand von uns würde in einen Zug oder Flugzeug steigen wenn es genau so gefährlich wäre wie es gerade in dieser Pandemie ist.
I've recently migrated my tools project from an old the server to a new one.
In the process I've decided to change the used database from MySQL to PostgreSQL.
To do so I've used this amazing guide from calazan.com.
As the guide was written for django 1.6 some minor changes were necessary when working with newer versions (I've used django 3.1.4).
Setup for migration
Steps 1 + 2 work as described in the guide above. A new database is created and added to the settings.py.
syncdb is no longer available in newer django versions and was replaced by migrate.
The flag --no-initial-data is no longer available and I didn't find a substitution.
Clean Up the new database
Some migrations will create initial data in your database. This will probably create conflicts, as we are migrating existing data into this database.
I did this step by hand, but the command python manage.py sqlflush --database=postgresql will give you the SQL query to do it automatically.
Copy data to new database
In order to copy the data we use dumpdata and loaddata.
When dumping the data it is important to use the flag --natural-foreign, otherwise the import process cannot import data with foreign keys.
The dumped data can be loaded into the new database. This process can take a long time. Ensure that your machine executing this command is as close as possible to the database, ideally running on the same machine. First, I started this command on my local machine. After 30 minutes I decided that it took too long and uploaded the dump to the server running the database, which finished the command in about a minute. My dump file was only 16 MB big.
Um die Ergebnisse der Kommunalwahlen in Aachen besser zu verstehen habe ich die Ergebnisse der einzelnen Stimmbezirke in einer Kartenansicht visualisiert. Hierbei habe ich für jede Partei eine Grafik erstellt, die zeigt wo die Partei besonders stark ist.









This is my pizza recipe for an easy to prepare lunch. It takes 15 minutes to prepare the dough. I typically prepare enough dough for 4 servings. The dough can be stored for several days and improves each day ;).
Add water and oil to the dry ingredients and mix everything
Once all liquid is absorbed start kneading the dough until you reach an even consistency
Put your dough in the fridge overnight
Cooking
In the morning take 275g of your dough out of the fridge. Fold or knead it shortly to create a round ball. Put the ball into a bowl and cover it.
After 1-3 hours fold the dough once. Be careful to keep the air building up!
Preheat your oven to 250°C (20-30 minutes before your lunch).
Put the dough ball on a floured surface and carefully push and pull it into shape. Be gentle and keep as much air as possible inside the dough! Put the pizza dough on your baking sheet.
Coat the pizza lightly with olive oil. Add 3-5 tablespoon passata and spread it evenly. You don't need a lot of sauce, only cover the dough lightly.
Season the sauce with salt, pepper and oregano (I also add chili). Add your ingredients and cheese.
Paul Graham wrote an article about wealth tax. In the article he 'models' the effect of a wealth tax on the fortune of a person. His assumption for the modeling is a person who earned a lot of money with a startup in her 20s. Paul Graham shows how much of the earned stocks/money would be taken by the government by a wealth tax.
Paul Graham comes to the conclusion that wealth taxes have "dramatic effects" and that "even a .5% wealth tax would start to keep founders away from a state or country that imposed it."
I think this conclusion is wrong. His model assumes that the earned money just lies on a big pile and is not used for 60 years. A more reasonable model would include interest being earn with the money. For this I will use an extended model:
(growth * (1-wealth_tax)^years
If we assume a reasonable return of investment of 2% per year the number shifts dramatically. Instead of "losing" 25% at 0.5% wealth tax you end up with 242% of your original value after 60 years. Even a wealth tax of 3% would only half your wealth.
Wealth Tax
Graham Model
With 2% Interest
0.10%
94.17%
308.99%
0.50%
74.03%
242.88%
1.00%
54.72%
179.52%
2.00%
29.76%
97.63%
3.00%
16.08%
52.76%
4.00%
8.64%
28.33%
5.00%
4.61%
15.12%
Paul Graham's article also misses to mention that a wealth tax only affect people with ALOT of money. Elizabeth Warren's "Ultra-Millionaire Tax" would only tax assets over $50 million. Once you are affected by a wealth tax you have enough money to live a luxurious life (and your children will probably never have to work to live). Most startup founders never reach this amount of wealth.
As this tax only targets the super rich let's look at the effect this tax would have on Jeff Bezos (data source: Wikipedia):
Even a high wealth tax of 5% leaves Bezos the majority of his wealth. If Bezos stopped earning new wealth in 2018 he could bequeath $30 billion to his children in 2080 with a 2% wealth tax. With a 5% wealth tax his children would still inherit over $4 billion!
The questions I'm asking myself when thinking about a wealth tax are the following:
Should a person have virtually unlimited resources for the rest of her life, just because she had a clever idea in her 20s?
Should children have virtually unlimited resources for the rest of their lives, just because one of their parents had a clever idea in her 20s?
Should grandchildren have virtually unlimited resources for the rest of their lives, just because one of their grandparents had a clever idea in her 20s?