DEV Community

rkeeves
rkeeves

Posted on

How to write code like Christian Bale from Hollywood?

In earlier articles, we learned how to write code like:

This time we are going to learn how to write code like Christian Bale!

For this, we have to take off the GOG shelf an old yet captivating game called: Sid Meier's Civilization III Complete.

Civilization III is a turn-based strategy game for PC:

  • where you build cities,
  • those cities produce inudstrial output (shields), and money (gold coin), but...
  • Everybody's up to something, hiding something.
  • Everbody's got an angle
  • and everybody is guilty.

corruption

Yeah yeah, the fictional character Perry Mason is played by Matthew Rhys.

Matthew Rhys is NOT Christian Bale, but I pinky promise you that at the end of this post:

You'll learn how to do Christian Bale Oriented Programming.

But before that, we have to make a bit of a detour.

So back to Civilization III: What is happening with all that money?

Distance

Civilization III's developers decided that corruption is going to be a resource sink.

Corruption is a mechanism, so that building more cities offers diminishing returns.

The design goal is to stop the players from snowballing.

There are two kinds of corruption:

  • Distance corruption: Cities on the outskirts of your empire are less productive.
  • Rank corruption: The more cities you have the worse it gets. For example, your 10th city will be more corrupt than your 4th city.

Corruption is detailed in-depth on this beautiful page.

We are going to deal with Distance Corruption.

The beating heart of all that nonsense is "how to measure distance between two cities"?

The guide states that it is a simple oneliner:

d = max(x,y) + min(x,y)/2
Enter fullscreen mode Exit fullscreen mode

Someone might say it isn't Engineering Magic like for example a React App, or SpringBoot backend, or a Rust CLI tool, and it is not worth a code review.

But... just to be safe...

Let's take a closer look how this corruption thing works.

Deposition

In this section I will lay out statements (Exhibitions).

The goal of doing this is that we won't get any suprises during trial.

This will be really long and boring, sorry, but it serves a higher purpose:

In the later Trial section of this article (which comes after this Deposition), we don't want to misrepresent this case!

We want to arrive at the true, just and honest truth.

Exhibit 1 - Simple 2D Manhattan Distance

There's a thing called Von Neumann Neighborhood or 4-Neighborhood.

It simply means that in a square grid like graph, the following 4 purple nodes are the neighbors of the hollow one:

4neighborhood

We can ask a question based on this:

4neighborhood-question

There are a lot of routes, but each of them is a bit different. Quantifiably different:

4neighborhood-answer

But there are multiple 8 steps routes too:

manhattan-distance

You probably know this, but maybe not by the name "manhattan distance":

manhattan-distance-example

Exhibit 2 - Simple 2D Chebyshev Distance

There's a thing called Moore Neighborhood or 8-Neighborhood.

8neighborhood

We can ask a question based on this:

8neighborhood-question

There are a lot of routes, but each of them is a bit different. Quantifiably different:

8neighborhood-answer

This time, and for this pair of points, there's a unique route:

chebyshev-distance

You probably know this, but maybe not with the name "Chebyshev distance":

chebyshev-distance-example

Exhibit 3 - Minkowski Distance

The Manhattan and Chebyshev distances are well-known from funny 2D problems.

But, let's play a bit with Manhattan distance:

manhattan-minkowski

What's the purpose of that p in the Minkowski distance? It is a slider:

minkowski-p

What is in the middle? Can you guess?

Yes it is Euclidean distance:

minkowski-p-full

Euclidean distance:

  • fits our normal every day assumptions about distance,
  • but it does not align with our grid,
  • aka it results in non-integer distances.

Doing Euclidean would be illegal.

Exhibit 4 - The absolute lowest minimum bar to remain technically law abiding

The distance used for corruption technically should not abide measure theory or any other mathematical notions.

This "distance" should abide notions of the players' expectations, like:

1. Any city should be 0 distance from itself.
2. Should work "bird's eye distance" / "air flight distance" like.
3. It must "just work" like you know... how the world works, omg :D
Enter fullscreen mode Exit fullscreen mode

And that's the Jira ticket essentially.

Exhibit 5 - Cardinal and Intercardinal Steps

First, let's think of a compass:

compass

The key insight is the Cardinal vs. Intercardinal partitioning.

What is the shortest path between two points using 8-neighborhood?

shortestpath

Of course, there is no THE shortest path. There are MANY equally short paths.

But, if you look at it carefully, each route is just a permutation of the same number of Cardinal / Intercardinal steps.

Can we somehow... compute Cardinal steps and Intercardinal steps? Maybe we could do something with them later.

Let's look at two entirely different cases, side-by-side, and try coming up with something:

cardinal-intercardinal

The Cardinal and Intercardinal steps are computable separately.

Exhibit 5 - Halfway Happy Distance

With these new Cardinal and Intercardinal steps, I want to ask two questions from you.

I'd like to ask you, to please dumb yourself down to my level. These questions will be... quite... well, dumb.

First question:

chebyshev-ic

Second question:

manhattan-ic

The answer is of course pretty dumb too:

ic-answer

These two distances just assign different costs to Cardinal / Intercardinal steps.

These are special types of Chamfer AIRQUOTE Distances AIRQUOTE.

Airquotes are necessary because you cannot assign arbitrary weights, because our assumption about shortest paths would completely break down.

Aka: This is a DIRTY LOOPHOLE WHICH JUST BUGS OUT TO WORK IN CERTAIN CASES.

Now comes the One Billion Dollar Question. What is between them?

Before answering the question:

  • Remember that you are NOT doing math!
  • You are just doing lawyering.
  • If you are still stuck on primitive notions like "Good vs. Evil", please listen to the Curious Tale of Slippin' Jimmy.

ic-middle

The answer is 1.5!

What's wrong? What's the matter?

Ahhh, right! You are worried, dear Reader, because it is not going to be an int?! Somebody didn't sleep through ethics did they...

We'll just floor it, baby. Legally speaking it will be an int.

And morally speaking... is there even a big difference between, say, 3 and 4 anyways?

Let me present you the Halfway Happy Distance:

halfway-happy-distance

It isn't Manhattan.

It isn't Chebyshev.

It is something that's kind of inbetween, it's like halfway happy.

Exhibit 6 - d

The code which started all of this was:

d = max(x,y) + min(x,y)/2
Enter fullscreen mode Exit fullscreen mode

But what is d? Let's see:

minkowski-distance

That d is Halfway Happy Distance.

Exhibit 7 - The rabbit hole finally opens up

Below is d in all of its glory, so let's do a little playful code review!

Just look at it for 5-6 seconds:

1 |     d = max(x,y) + min(x,y)/2
2 |     where
3 |        max(x,y) denotes the maximum between x and y,
4 |        min(x,y) denotes the minimum between x and y,
5 |        x is the distance in the NW/SE direction,
6 |        y is the distance in the NE/SW direction,
7 |     and the integer division is rounded down.
Enter fullscreen mode Exit fullscreen mode

Yes indeed, Line 5 and 6 seem... odd.

Perhaps a bit... too weirdly odd:

rabbit-hole

Why would we do it that way? It does not make any sense!

Oh wait...

All this time, we've been looking at the world the wrong way:

isometric

But... we can adjust of course:

coordinates

But... wait... it does not... it does not work!!!!

coordinates-no

THAT RIGHT SIDE ISN'T HOW A GRID SHOULD BE NUMBERED!!!

Omg:

  • if distance is calculated based on NW-SE / NE-SW axes,
  • then why not number the grid cell along those axes?

Why would someone mess up a simple planar problem?!?!?!?!

Because technically... it isn't a planar problem.

Exhibit 8 - Mainlining the secret truth to the Universe

As Inception's city bending scene demonstrates, a Civ III game can be thought of as a cylinder.

But... the game is more general than that:

settings

Much more general:

world-torus

Earth? How about Earth Torus?

torusgif

The coordinates are not messed up. If we take a closer look, there's order and pattern in the coordinates:

coords

Yes! They are just regular x, y coordinates following the typical "x grows rightwards, y grows downwards" fashion from good old computer graphics CS 101:

coord-pattern

But... there's a slight issue with wrapping.

Wrapping messes with our notion of ordering, so shortest path is a bit more complicated:

shortest-modulo

Based on this our notion of "deltas" changes too, as we have to always pick the shorter from the two possible routes:

deltas

Exhibit 9 - Modified Halfway Happy Distance

With our fancy new deltas, let's think about how we could juggle somehow the Halfway Happy Distance into this weird world:

hhd-question

What actually happened up there is that Cardinals and Intercardinals were switched, so we can just adjust the formula easily by thinking about base vectors (Cardinals) and their simpleton dumb sum (Intercardinals):

hhd-answer

So without doing math, we came up with a modified Halfway Happy Distance which kind of bugs out to work in CS 101 screen coordinates.

Exhibit 10 - The Lawyer Tech Stack

I am a Lawyer, so of course I can make heavy computations!

That's what Excel spreadsheets, formulas and conditional formatting are for!

Of course I am a cheapoo so I use Libre Office.

Let's see all 3 distances in both Flat Earther and Inception Torus style:

Chebyshev:

chebyshev

Halfway Happy:

halfway

Manhattan:

manhattan

Basically all 3 distances "work" if we cheese the basis change good enough.

Exhibit 11 - High Level Lawyering

Now comes the most important part of Lawyer Oriented Programming: Diving into the Jira Dumpster.

After a lot of dumpster diving... Bingo! We hit the Jackpot:

Q: We have city A with coordinates (x1,y1) and city B with coordinates (x2,y2) with coordinates as found in the editor N/S and E/W coordinate system. What is distance between A and B in the corruption equation?

A: It's the same distance calculation in a different coordinate system. In the editor coordinate system the distance would be given by:
d = (X + Y) / 2 + |X - Y|/4
where Y = |y1-y2| and X = |x1-x2|
see ainwood's post in the original corruption thread.
Enter fullscreen mode Exit fullscreen mode

Unfortunately the link for ainwood's post does not work.

But at least, we fished out the "actual" d from the dumpster which must be used in the game!

This is the last exhibit.

Now it is time for Trial!

Are you ready?

I want to reiterate why we did this long journey:

  • We don't want to misrepresent this case!
  • We want to arrive at the true, just and honest truth.

We now have everything at our disposal to reveal the actual truth!

Let the Trial begin!

Trial

Your Honor, I believe that - until proven guilty - every man, woman and child in this country is innocent.

My client's rightful and legal business was wrongfully accused of mishandling funds, and it was grossly misrepresented in the eyes of the public by fabrications like this:

corruption

Your Honor, my client lives on the far reaches of our beautiful Country, far from the Capitol!

A third of my client's revenue is spent on traveling expenses alone!

Your Honor, from Exhibit 5 we already know certain facts:

basics

When calculating his travel expenses my client abided by the zoning rules as required by law, please see Exhibit 11:

dbug

Your Honor, based on just these Exhibits, we can clearly show that my client was adhering to state approved measures when computing allowable travel expenses:

rewrite

My client abided the zoning rules in the strictest sense, Your Honor!

Your Honor, please see the below picture:

  • my client's residence is located entirely in the red zone as you can see on the right,
  • far away from the Capital as you can see on the left,
  • the looong black line represents the route my poor client has to endure each and every day to get to the Capital,
  • strictly legally speaking of course based on the State-approved zoning rules as per Exhibit 11.

texture3

It is so far away from the Capital, that one third of the financial revenue of my poor client is spent on simply travelling expenses alone!

Do I see corruption, jakuzzis, mansions or partys?

No, Your Honor! I see a frail man, who works diligently, travels long hours, pays taxes, bookkeeps revenues, expenses and suddenly gets blamed for committing something he did not even do!

Your Honor, please understand that - strictly legally speaking - my client is living thousands of miles away from the Capital:

reality

Of course, strictly legally speaking, your Honor.

Yes you are right Your Honor, my client is technically living 10 yards away from the Capitolium, and his front porch is basically touching the foot of the Capitolium Hill, but...

But Your Honor, what matters in this Courthouse... in these sacred marble hallways of Justice... is the word and Code of Law.

Christian Bale Oriented Programming

Yeah, we have to address the elephant in the room:

There wasn't an inch of Christian Bale thus far :(

But, remember that we did a floor div-ed Chamfer Distance?

Below is a LibreOffice sheet which goes from Manhattan via Halfway-Happy to Chebyshev using a slider.

We are doing Chamfer Distance and are cycling Cardinal cost (⊕) over:

[0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1]

with a fixed Intercardinal cost (⨂) of 1:

chamfer

The above function returns ints which are then used in complex calculations to yield a Corrupted Gold Coins number for the user.

If you are just a random user who bought Civ III from GOG for a couple of bucks, you will enjoy the game and its Corruption Mechanics.

But, remember Minkowski distance?

Remember that it is parameterized by p?

Below is a LibreOffice sheet which goes from Manhattan via Euclidean to Chebyshev using a slider controller in our derpy little spreadsheet.

We are doing Minkowski and are cycling p over [1, 1.1, 1.3, 1.5, 1.8, 2, 3, 5, 6, 8, 10, 100]:

minkowski

Minkowski actually truly hits Euclidean. Euclidean is the "real distance" in a down to Earth sense.

Yeah-yeah if you compare Chamfer side-by-side with Minkowski the difference screams out but...

Yeah yeah yeah, Chamfer is just a replica of Minkowski even in the special "Halfway Happy" case, but simple users won't be able to tell.

Chamfer is just a slop replica, but Chamfer distance works and that makes users happy, and that's what matters.

Now, who is the Master?

The Minkowski or the Chamfer distance?

The Painter, or the Forger?

Okay now, hear me out on Christian Bale...

Mel Weinberg was a real con artist, charlatan involved in art forgery.

Hollywood actor Chrisitan Bale is not the real Mel Weinberg, as Mr. Bale just played a character based on Mel Weinberg.

Now, who is the Master? The Forger, or its Method Actor?

Summary

The guide stated that distance is a simple oneliner:

d = max(x,y) + min(x,y)/2
Enter fullscreen mode Exit fullscreen mode

To which, someone might say that oneliner isn't Engineering Magic.

But now, after everything, dear Reader...

I hope that I convinced you that, indeed, it is.

Don't let the "oneliner" simplicity fool you!

That oneliner does not even handle the screen-xy-style coordinates, wrapping, overflows and certain nastier edge cases yet!

Remember CS 101? Remember what it taught us?

No, this isn't just a scary story that Professors tell us before going to sleep!

Now, who is the Master? n1 or n3?

Top comments (0)