Spider-Man PS4

16. September, 2018

Spider-Man is currently one of the best and worst games for the PS4.

Visually, it’s stunning. Swinging through the city is amazing. Different city parts are replicated in great detail, people are going to work, hailing taxis, using the tube.

Missions are varied and complex. You get the collect air samples, detox areas, fight infections of animals, help the police with crime and tech problems.

Well done, Insomniac.

But.

The fights. I’m playing on “friendly” (the easiest game mode) and I die about every 30 seconds in a fight. Enemies surround me and dead. I mash all the buttons but after some minutes of pure frustration, I abort the mission because I clearly can’t do it. No, I’m not talking about the boss fights, I’m talking about the usual street brawls. Apparently Spidey has tons of moves but he stumbles around like a drunk cat, collecting all the bullets, always getting stuck somewhere, L2+R2 rarely finds a target and if it does, they just shot me down from a distance. In Batman games, you could hide in a corner and collect your wits, not so here. I hit an enemy while someone else bludgeons my head with an iron while two or three colleagues use their machine guns on me and I die in a nice exploding cloud of a rocket. While I try to wrestle a gun from an enemy, his 20 friends clobber me dead. I stay in a place for more than 2 seconds, dead.

Another problem with the button combos: They don’t work and you have no clue why not. The game displays the combo to press and … nothing happens. You press the evade button during a fight, nothing happens. You press L1+R1 to pick up something to throw, you get interrupted. Or nothing happens.

I’ve played a lot of Insomniac games in the past. Ratchet & Clank. Resistance. I can finish most of them. I finished Andromeda. Many Batman games. That’s why I think it’s not me, it’s the game. On top of that, it creates this fake urgency – you can complete most missions at your leisure, no matter how panicked the voices are.

So. If you like to be frustrated, if you love to learn 50 button combinations just to advance to the next level, the game is for you. For everyone else, wait for the play-through on Youtube.


The Benevolent AI

1. August, 2018

There is a lot of argument how AI will kill us all. Some argue that AI will see us a threat and wipe us out, just in case (the Skynet faction). Other argue AI will pamper us to death. The third group hopes that AI will just get bored and leave.

But how about the benevolent AI? Imagine a life which is fulfilling and demanding. It has highs and lows, disasters and triumphs. How about we create an AI with the goal to give such a life to everyone?

Of course, everyone has a different idea what such a life would be. That would make such an effort more complicated but not impossible.

It would also be very expensive to give everyone their perfect life. This factor depends on the amount of people (which will go down by itself) and how close we want everyone to get to the goal of “perfect”. In the beginning, the AI will both be immature and low on resources. Over time, it will learn from mistakes and people will start supporting the idea to give it more money and power when the idea works. So this is a problem which will resolve itself over time.

Then there are people who are never happy with what they have. People who can never get enough. Which I think translates to “the people around such persons don’t know how to teach them to be satisfied”. I think an AI could nudge those greedy people to become more complacent and enjoy their lives more.

This approach would put an end to mobbing. On one hand, people don’t like being mobbed, so the AI would have to put an end to it. On the other hand, I’m pretty sure the mobbers aren’t happy with their lives as well. So making them more satisfied might already be enough to put an end to mobbing.


Avoid Publishing SNAPSHOTs to Nexus

3. July, 2018

Once in a while I’m running into people who deploy SNAPSHOT versions of Maven dependencies to a company-wide Nexus server with a job on a CI server. This is usually a very bad idea, especially when using branches.

Scenario: Two developers, John and Mary, each working in their own branch. They push their branches, CI builds them and they end up on Nexus.

Problem: Nexus doesn’t know or care about branches. Whichever job finishes last wins.

Often, this is not a problem. Now let’s add another project B. B depends on A.

As long as B depends on a release of A, everything is fine.

Now, John needs to make some changes in A. So he updates the dependency in B to A-x.y.z-SNAPSHOT. Everything is still fine, since Mary still uses the latest release of A.

Then Mary also creates a feature branch in her clone of A. That still doesn’t break anything because Maven caches SNAPSHOTs for a day.

The next morning, John makes a change to B and builds it.

This build might break when Mary’s CI job finished last!

The problem here, which can go unnoticed for years, is that Maven silently downloaded Mary’s version of A onto John’s computer and used that to compile. John will see the source code from his branch of A but the binaries will be something else.

Eventually, one of them will make a small changes which affects the others project. They will see MethodNotFoundException or get strange compile errors while the source code (which isn’t affected by this) will look perfectly fine or unit tests will break in odd ways.

That is the main reason why you shouldn’t deploy SNAPSHOT branches to a shared Maven repository: It creates a small chance for subtle bugs which will take a long time to find since your mental model (“I see the source, this is what I get”) will be wrong.

You can get away with publishing the master branch to Nexus (i.e. only a single branch with SNAPSHOTs will ever be published to Nexus).

Note: If your CI server shares local Maven repositories between projects, your builds can fail on the CI server for the same reason. Configure your CI server for per-project local repositories and wipe them before the build to avoid such issues for sure.


Binding one Instance to Two Interfaces in Guice

15. June, 2018

Sometimes, you need to bind one instance to two interfaces in Guice, for example:

interface Foo { ... }

interface Bar extends Foo { ... }

class FooBarImpl implements Bar { ... }

Let’s imaging FooBarImpl is a stateful bean which is saved in a session scope:

bind(Bar.class)
    .to(FooBarImpl.class)
    .in(Session.class);

This works when someone injects Bar but injecting Foo fails. There are two solutions for this: Bind Foo to Bar or use a provider method to transform the type.

Solution 1: Binding Interfaces

bind(Foo.class)
    .to(Bar.class);

This will use the mapping for Bar to satisfy requests for Foo.

Solution 2: Provider Method

Provider methods are a nice way to build complex objects from bound instances. In our case, we can map the types like so:

@Provides
@Session
public Foo fooProvider(Bar impl) {
    return impl;
}

Note: These approaches will put two keys into your scope but they will point to the same instance.


I’m Not a Robot (Rant)

31. December, 2017

Google’s “I’m not a robot” CAPTCHA is freaking me out.

I often spend minutes clicking stupid images only to be presented with more fucking images. It feels like it takes half an hour or more to just get the stupid thing to get out of the way so I can do whatever I came to do.

My main complaints:

  1. Is the frame of a street sign part of a street sign?
  2. Why do I get another page of images when I complete a task? Is the thing playing Sisyphus with me?
  3. Why does the thing suddenly change the game? First, I have to select pieces and click “Continue” and suddenly, it replaces pieces as I click and the button at the bottom behaves differently.
  4. Why can’t the thing remember me? Google and his friends know that it’s me! That’s their fucking business model! They make billions by tracking our movements on the web.
  5. The Google site boasts “Low friction, effortless interaction for your users.” There is no “File complaint” or support link anywhere. If it’s broken, guess who doesn’t care because they never hear about it? It’s one of these “it’s perfect – no one ever complained” situations.
  6. It puts me in an unbearable helpless situation where everything becomes a problem.

Just seeing the box turns me off by now. I’m starting to avoid web sites that use this. Patreon is about the last one where I force myself to endure the pain so I can help people. The support guys were nice and supportive, but there is little that they can do.


Stop on specific NullPointerException in Eclipse

20. December, 2017

TL;DR: Find the line where the exception occurs and then add a conditional breakpoint which checks the local variables for values that would trigger the exception.

In Eclipse, you can stop on any exception by using the menu Run -> “Add Java Exception Breakpoint…“.

That’s great but it doesn’t help when you want to stop on a certain exception on a certain line. It’s a big problem with code that uses exceptions for control flow – you could have thousands of those exceptions before you get to the one which you care about.

In my case, I had a NullPointerException in java.util.concurrent.ConcurrentHashMap:

    public V get(Object key) {
        Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
        int h = spread(key.hashCode()); <-------- key is null
        ...

I tried to add a conditional breakpoint here with the condition key == null but Eclipse complained that it couldn’t compile the expression (probably missing debug information).

The method was called from Jetty’s ClassInheritanceHandler, so I added a conditional breakpoint there.

That’s another reason to copy method results into local variables before using them.


Code Formatting by Example

15. December, 2017

People are starting to use Machine Learning to write better code.

One example is code formatting. Instead of painstakingly writing a parser and then rules which are to be applied to each node of the Abstract Syntax Tree (AST), the guys from Codebuff are using the “learn by example approach”. Just feed Codebuff with a couple of examples and it will learn to apply those implied rules to source code.

If you find something that looks bad, you don’t have to dig through dozens of pages of code formatter options or code formatter config files, just add more examples.

If you’re using Xtext, you can use the tool to write code formatters for you DSL: “Machine Learning Formatting with Xtext