Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Space invaders, but the invaders evolve with genetic algorithm (github.com)
253 points by atum47 5 months ago | hide | past | web | favorite | 69 comments

I really liked how you justified the gameplay with story re: "When a InvaderZ dies, they upload their progress to the mothership, so it can generate more InvaderZ like the ones who did well before."

The evolving enemy concept made me look up an old boss-rushing shooter that selected the next boss's upgrades based on your performance[1]. Is this something you're interested in refining further?

[1]: https://en.wikipedia.org/wiki/Warning_Forever

The idea began with me wanting to generate space Invaders character design using genetic algorithm, so I thought, what the heck: if I do that I might as well do a sort of game play to justify they design. That's how this project was borned. Who knows what it becomes? But very nice of you to comment and leave a link.

Crossing the streams with the Valve/Proton thread of yesterday, Warning Forever still works a dream on Windows 10 and is an exceptionally fun game. Well worth finding and downloading.

Oh man, I remember that game. It was THE shit.

While this is very cool, using the distance each invader survives as the fitness score seems like maybe not the best choice for this scenario.

With so many invaders spawning at the same time, and the 'bullet' you shoot moving so slow, the last invader to be destroyed seems to me to be a result of random choice (which one did you get around to shooting last) rather than it being any 'healthier' than the other invaders.

I don't really have a suggestion on how to improve it other than maybe slow down the vertical progress of the invaders and speed up the bullet so that distance made vertically is actually tied more closely to it's ability to evade your shots.

I agree with you. When I play, the "best" invaders tend to be the easy targets that have drifted to one side of the screen.

Here is a proposal for another fitness score: everytime a bullet is shot, raise the score of every survivor, weighted by the distance between the survivor and the bullet. The closer the bullet the better the fitness.

Intuitively, I think this would select for better dodgers.

But dodging is just a subgoal and margin is not all that relevant. The actual goal is to defeat the player, if dodging by a slim margin happens to be the best strategy then that should not be penalized.

”the last invader to be destroyed seems to me to be a result of random choice”

There’s a simple strategy that guarantees you won’t be the first to die: hide behind the back of your biggest buddy.

I think that would be my strategy, plus “if a bullet that’s going to kill your ‘shield’ is on its way, figure out whether you can find a new shield; if not, make a run for it.

The existence of such a strategy shows the result isn’t completely random.

(Of course, there also is a prisoner’s dilemma here: if everybody follows that strategy, the swarm would run away from you, and nobody would gain any fitness)

Yes, and the last one who survived moved in a way that helped it survive. It's not the best one the ones who reproduce, they all can reproduce, the ones who got closer or went through have more chance.

No, I'm saying even if they didn't move, there would still be a last one to survive, just based on the time it takes to shoot them.

No, their fit score is how close they got to crossing the finish line. If they don't move, they got no score. If they move in a straight line and still manage to win, hey, that's life. I've observed that the ones who jiggle around are the ones that wins the most.

If they didn't move left to right I mean.

But do you agree that if they don't move, they will the ones easier to shoot? So, unless you are sparing them, they won't go very far and will have less chance of reproduction.

Of course, but I'm just saying there are so many of them and they are so hard to shoot due to the slow bullet time and only one bullet, that the left to right movement is not making as big of an impact as it could.

I would say just give a try at slowing down the vertical progress, remove the one bullet at a time restriction, and see how that goes.

Not trying to be negative at all, I think it's a great project and the code looks to be very clean. Nice work.

I'm inserted in a context that I don't have anyone to discuss this kind thing, so you don't have to be apologetic. It was very that you liked the project. I've been receiving many suggestions and I'll look into them with care. Thanks a lot.

On average, over many plays, the random aspects of the scoring you are concerned about will average away and the useful traits will be reinforced. Just like evolution.

Over many plays, sure, but how long should one person have to sit there to see results? As far as I can tell, there is no persistence between sessions. I'm saying making the game 'easier' for the player would decrease both the number of plays needed to get better evolutionary results and also decrease the time between each evolutionary cycle.

Who said evolution was fast?! ... Or easy?! :D

I've used GAs before in school. One example way to do even session-less evolution faster would be a distributed client/server model where the indivual survivors across all game instances who are lasting the longest are crossbred but that would take longer to code ....

The problem is that "over many plays" would be like thousands at this tempo. I played up until generation 20 or something and it was still completely random who I decided to kill last.

I tried to kill the ones on the sides and/or that moved around more first, which did seem to lead after ~10 generations to lots of static/slow opponents coming down in an easily-dispatched cluster that could be easily mopped up at the end of each round. Conversely I'd imagine prioritizing the slow ones would lead to enemies that tend to move around a lot.

Yup, it seems like you can game it by looking for the easiest one and waiting till the very end to hit it.

Isn't that part of the... game?

In other words, AI domestication. Interesting concept! (Allowing it to live longer being the equivalent of breeding.)

Well... they could learn to look "stupid" and be smart at the very end of the game

> using the distance each invader survives as the fitness score seems like maybe not the best choice for this scenario

> With so many invaders spawning at the same time, and the 'bullet' you shoot moving so slow, the last invader to be destroyed seems to me to be a result of random choice (which one did you get around to shooting last) rather than it being any 'healthier' than the other invaders.

I couldn't disagree more. The fitness score is correct, because the invader wins by covering distance.

What happens by chance early will happen by design late -- that is nearly the entire concept of evolutionary approaches. They always improve on their fitness function, and what matters is that you chose the right one. In this case, improving on the distance invaders travel is the point of being an invader, and the point of the game, so that distance is very obviously the correct fitness function.

> the invader wins by covering distance

The invader wins by crossing the baseline. This fitness function lets me use evolution against the invaders by letting the dumbest ones approach the baseline before killing them, making future waves easier than if I killed the easiest invaders first.

Perhaps the fitness score could include the number of projectiles that passed nearby without impacting, as a measure of difficulty to hit.

>> the invader wins by covering distance

> The invader wins by crossing the baseline.

Both are true, but covering distance is a better fitness function because it is continuous and crossing the baseline is discrete (and not just discrete -- binary). Your strategy can make the difficulty rise more slowly than otherwise, but it can't make the difficulty plateau or drop.

I said 'for this scenario', I suppose I should have been more clear. In my post I go on to list ways to change the scenario so it does fit the fitness function. I do agree the fitness function is probably correct, but the rest of the implementation doesn't match it.

This is very cool work! I particularly like the idea of a "human in the loop" as objective function for the GA.

Yes, it's slow and I didn't end up playing more than a few rounds, but the core idea is a Good One.

Thank you for making and sharing!

Cool stuff. Check out Quantum Pilot where the enemies literally mirror your previously recorded actions. Steam / Android / iOS

I tried the game you mentioned. Surprisingly hard!

I played through 70+ generations before I stopped, and it certainly seemed like they were getting more jiggly as it went on, albeit, very slowly.

It would be nice if there was genome display or something, so you could see how the population was evolving. Towards the generations that were multiples of 7, it would look like the population started to converge. So some sort of display information about that would be interesting.

It would negatively effect gameplay because it would be essentially a cheat for the human, but it would be an interesting visualization none the less.

The design of the InvaderZ is his genome and the way it behaves. It as vector of size 16 with zeros or ones. If it's a one it draws a "pixel". So you have to think of it as a 4x4 Matrix ```[ 0,0,1,1, 0,0,1,1, 1,1,1,1, 0,1,1,1 ]```

Yeah I get that, but I’d like more insight into the the semantics. Like “horizontal speed 16”, “move fequency 11” etc.

Really cool idea! Went to wave 32, had a lot of fun with it actually.

But, knowing the algorithm, I tried to shoot the hard ones first and wait as long as I could to shoot the easy ones by just letting them descent :)

It would have been interesting to see an evolving agent playing against these evolving invaders. Cool project!

I'm thinking about using a NN I made a while back to play it. =)

I just increased the player's speed, after a lot of requests.

the manifest.appcache should take care of the update; but if it don't, clear the storage and visit victorribeiro.com/invaderz again

Suggestion: support 'a' for left and 'd' for right.

The problem if you use "a" and "d" is that it will only work with qwerty keyboards. In azerty for instance the equivalent would be "q" and "d".

So for a small demo it's probably better to just use arrows as this will work everywhere, and there won't be a need to support all keyboard layouts out there.

When I do game-jam games I always make both "a" and "q" left, and "z" and "w" up... and I always get a comment or thanks from the french players ;)

Thats what charCode and keyCode are for. keyCode refers to the physical keys (named A and D on any keyboard, even if the printed letters are different), charCode refers to the character the key represents (which differs per keyboard layout)

Be real - what percent of people are using azerty, even on HN?

Ah, yes, the "fuck internationalisation, we're all living in America anyway" argument.

EDIT: Data point of 1: I'm German and use a QWERTZ layout because it's a hassle to type umlauts on QWERTY even with a compose key. If I were French that'd mean I'd be using AZERTY.

That's not the argument. They just seem to believe that it's a nerdy alternative layout like Dvorak ("...even on HN"). Not everyone is familiar with international layouts.

I would think the kind of people interested in technical posts on HN should better be aware of at least the most basic i18n issues.

Show HN: Space Invaders, but it doesn't work for French people

At least the majority of France / Belgium.

I switched to qwerty about 2 years ago, but almost everyone I know uses azerty here (as software engineers).

Personally, I don't expect it to be supported though. But it should at least have a fallback like the arrow keys.

63 generations later, I didn't get the impression the invaders were getting any better. Not consistently anyways, they would kind of vascillate between moving a lot and not much at all.

It's an interesting idea, but I think the implementation needs more tuning.

Live demo here: https://victorribeiro.com/invaderz/

I'm finding that I can barely last 7 generations to be able to see it 'evolving'. Handicapping the player by waiting for the previous shot to hit before firing again and making the move speed ridiculously slow makes this game too hard even before the genetic algorithm makes an impact.

Also, because the player's move speed is so slow, the easy tactic for the algorithm to head towards is to simply push each enemy to opposite ends of the screen -- ie: hug the wall. If you're clearing one side, the player won't be able to reach the other end of the board even if you move as fast as possible.

TLDR: Interesting concept but to really demo this concept you need to make the game a little easier for the player / don't handicap so much.

Agreed, this is a very cool concept but it's too hard for the player. As a workaround, run this in the console to double the player's speed and allow you to re-shoot the bullet while it's in motion.

    Player.prototype.shoot = function shoot() { this.bullet = {x: this.x+this.s/2, y: this.y, s: 3}; this.isShooting = true }; Player.prototype.update = function update() { if (this.x > 0 && this.isMovingLeft) { this.x -= 0.02 * dt; }; if (this.x < w/4-this.s && this.isMovingRight) { this.x += 0.02 * dt; }; if (this.isShooting) { this.bullet.y -= 0.1 * dt; if (this.bullet.y < 0) { this.isShooting = false; this.bullet = {}; } } }

Nice, haha.

I'm confused, I was able to get to generation 9 in my first go and that was with it taking me 2 rounds before I figured out I could use the keyboard to move and shoot instead of the mouse...

I will put a welcome informing the controls

I had no trouble getting to wave 30+, and I certainly didn't grow up with this kind of game. Using PC keyboard though - are you on mobile?

In any case, the real problem here is that either the player is good enough to last a long time (in which case most waves are probably killed very quickly, thus randomness dominating the fitness function and you won't see evolution) or the game won't last long enough to see a lot of evolution happening.

The author made the speed of the player much faster a few hours after my comment was posted so my concerns regarding speed/difficulty are no longer relevant. The max speed of the player was barely the speed of the enemies before the change.

I’ve also tried it on my iPhone and it’s easily playable too.

They evolve each generation. What happens after the 7 generation is that if no one could kill you until now, make a new wave of Invaders while keeping the best one from past generations.

This made me think that it'd be interesting to see a variant on Space Invaders where you play as the invaders - you would write a little program that takes the state of the world and determines the next move for each invader and play against an AI cannon. Does anybody know if something like this already exists?

Cute, but way too slow to be fun.

What if: - kill the "hard ones" first - wait for the easier one to get very close to atmosphere, and then kill it. - will the algorithm learn to evolve toward easy ones?

Is there a playable demo?

Not working for me

"victorribeiro.com’s server IP address could not be found"

I don't have a server; I pay a hosting service, it's what I can afford right now, and I called them and asked for more resource, cause it's been receiving a lot of visitors. Maybe it went down for a moment.

It's just static data, so you can host it on Github's servers using Github Pages: https://pages.github.com/ Gitlab even goes one better and allows you a build step if you ever wanted to use webpack, etc...

Here's fine.

I am in Kazakhstan, if that helps

Space Evaders?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact