Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Pong Wars (koenvangilst.nl)
490 points by vnglst on Jan 27, 2024 | hide | past | favorite | 120 comments



The code links this tweet as the source of the idea: https://twitter.com/nicolasdnl/status/1749715070928433161 [nitter: https://nitter.net/nicolasdnl/status/1749715070928433161]

Quote: "The endless fight for #genuary23 #genuary #genuary2024

It's not an original idea, I've seen this before but couldn't put a hand on it."

It says the battle is endless. I wonder if there's any way to mathematically prove that.


I think further back, part of the idea may have been mine.

https://hachyderm.io/deck/@bazzargh/111829275276749971

Originally I saw https://twitter.com/CasualEffects/status/1390290306206216196 which the author says was based on a pico8 original (which I remember seeing, but can't find now). Those earlier ones had the pong bats as well, but when I did the demake in basic, I couldn't fit the code into a tweet to get the bbcmicrobot to run it. So, I removed the bats.

Mine is a bit slow and janky, @rheolism (I think?) posted back a much faster, smoother version using custom characters instead of plotting, and then I saw a remake of the demake in processing? These things take a life of their own.

Anyway, long ago deleted my twitter account, but dug it out of the archive.


Each ball will occupy a minimum area of 1x1, so the opposing ball can never occupy 100%


The smaller the area, the more bounces its ball gets per time unit compared to the opponent and more chances to expand the area. So any extreme case of one ball being super-confined will be very short-lived.


But it seems that the balls speed increases with a bigger are.


From what I can see from a quick glance at the code, you have the causality backwards. Each bounce adds a small random variation to each ball's velocity, and if one of them randomly ends up moving faster, then it will tend to gain more territory.



You can see what happens when the left ball has one tile and the right ball has the rest of the tiles:

    x1 = y1 = y3 = squareSize, x2 = canvas.width - squareSize
    squares = Array.from({ length: numSquaresX }, (_, i) =>
        Array.from({ length: numSquaresY }, (_, j) => 
            i === 0 && j === 0 ? TEAM1 : TEAM2))


Well, it seems like there must be a relatively stable equilibrium. As the owned area decreases, the rate of annexation increases.


Mine seems to have reached a meta-stable state after running for a few hours around 320/704, where the ball with less area is bouncing almost vertically, and a nearly flat border between the two.

https://i.ibb.co/7bNTtsK/daynight.png


This is very interesting, mine did too, but with an even narrower dark patch.

It is like an attacker-defender equilibrium situation where the vertical guy runs up and down a trench and the attacker tries different paths for orthogonal attacks.


It would be interesting if this distribution found use in military theory!


The first time I opened the link, I kept watching until both balls ended up in a point where they blocked each other between opposite side’s tiles. The was no way to go and they kept bouncing off each other in a tiny space. I wouldn’t call it an end but there was no progress anymore either.


I got to a similar place, but it only lasted one or two seconds, then they got separated and the game continued


Its running now for a few days, still ponging hard.


I didn’t grab a screenshot, but I did see how the simulation can end. The day and night balls collided with each other at the boundary and got locked in place in a tight infinite loop, and never moved again.


I saw this as well. Shall we call it “entanglement “?


>mathematically prove

I'll give it a rough swing. I probably overcomplicated the endgame I describe below, and maybe make some assumptions that aren't actually how the mechanics work, but hopefully it's understandable.

The balls are about the same size as the blocks. Lets say they are infinitesimally smaller, so they can still fit down a 1 block wide tunnel.

Imagine the gameplay somehow gets into the condition that both balls are in tunnels, but white in the worst way (perfectly aligned, so it just bounces off the far ends) and black in the best way (barely zigzagging in a nearly straight line, killing all wall blocks, leaving a 3 block wide tunnel in it's wake).

This would result in whites tunnel rapidly shrinking. Even if white exists in a 2x1 tunnel and is getting kills, black is still killing at almost 2x the rate.

White will be in their 2x1 tunnel, make it into a 3x1 tunnel, but it will become a 2x1 tunnel again by the time it's bounced a little over a block. Now suppose black then reaches the (white) end of their tunnel, scoring 3 kills in almost the same instant. There's nowhere to spawn those three that doesn't clash. The app will either crash with a null value error, or some other result that qualifies as an end condition since it would break the fundamental rules of the game.


It would be interesting to know if it can get into a looping state after which it just repeats previous moves forever. I guess that would be an “end” of sorts.


Because there are a finite number of states, it will always loop.

An interesting question might be around how many distinct loops there are and whether there's some pattern to the loop lengths.


> Because there are a finite number of states, it will always loop.

No it wouldn't. The fact that it will pass through every state infinite times doesn't mean it will do it in the same order each time. Each digit of pi has only 10 possible states, but it never loops.


If the state evolution:

(a) is deterministic

(b) depends only on the current state, and

(c) can only occupy a finite number of states

then it will loop.

Pi digits do not satisfy this because while the digit space is finite (10), the next digit depends on more than just the prior digit.

Related (but not the same): https://en.wikipedia.org/wiki/Poincaré_recurrence_theorem


The speed of the balls are changed by a small random amount when they hit a tile, so it's not deterministic.


If it's a deterministic RNG then it just means the state space is very large.


Ooh that’s cool I’ve never seen that before.


It should suffice to check out what happens (code-wise) if one of the "players" has only one square left. Does the "winning" player have a chance to hit that square and conquer it? Or does the program immediately register a collision for the "losing" player, who goes back to two squares?


That could show that it’s endless, but it wouldn’t necessarily show that an end is possible.


I don't believe an end is possible. As one player's territory sprinks, it should quite naturally follow that it will have less travel time, hence more collisions.


s/sprinks/shrinks


I expected a side to win or score a point once it hit the ‘goal line’ of its opponent.

Would make a nice game if there was a way for players to have some control over the ball. Could be as easy as standard pong paddles, with some time delay whenever your ball passes your own goal line.


By definition… if there’s no end condition, it won’t end ;)


On top of this there's a negative feedback loop. The ball whose territory gets smaller has less distance to travel between hits.

This means that even if there was anything resembling a "win" condition it would be hard to achieve.


You'd think, but I'm currently looking at a 161/863 split which has been pretty stable for a while now. I thought at first that ball speed is being scaled by territory size to cancel out the negative feedback, and the "winning" ball is moving noticeably faster than the losing one, but I can't see that being deliberate in the code. (There is some randomization of speed on a bounce, but it ought to be pure noise.)

EDIT: 120/904 now.


One possible win condition would be a ball reaching the opponent's side. That happened in my case, with "night" eventually breaking through to the left-most edge.


That just explains why it tends towards balance. It's just like all the air molocules in a room reliably bouncing around where you can inhale them. There's no hard law of nature saying all the air wont move to one side, suffocating you. It's just statically extremely improbable.

But they asked for proof for or against a possibility at all, not whats probable.


It's ambiguous. The end condition could be a pixel spawning with overlap on a ball because there's nowhere else to go. What will happen when there's no room left to add one more pixel, and it tries to add one more pixel? Will it place it with the collision boundaries on the wrong sides? Will it crash with a null value error because there's no good spot to place it? Can't know without understanding the code. But there are many possible end conditions.

They're asking if one can prove that you never reach any situation where an end condition (intended or not) could ever exist.

Imagine black has a long horizontal 1 pixel tunnel, but it's zigzagging down hitting every side pixel rapidly, while white has a long white tunnel and it's bouncing perfectly horizontally, taking a long time to hit each end. As the ends close in on white, is there some perfectly aligned timespan where black can hit a pixel while white doesn't have a full pixel of open space on either side? It would be interesting if someone can articulate logically why or why not that would ever happen.


Which makes the name War even better. There is no winner in war and the cycle repeats itself.


I'm greatly fascinated by this kind of thing, but I have to call it "this kind of thing" because I don't even know if there are genre terms to categorize and analyze them.

They're inspired by game algorithms, but they aren't games; Conway's "Game of Life" was a misnomer. They're animated, but they aren't scripted like animations. In the real world we have someone like David C. Roy, who calls his art "kinetic sculptures".

Algorithmic motion pictures? Game simulators? Autonomous automatons?


I have seen the term "zero player game" used for this. There is even a short Wikipedia article: https://en.wikipedia.org/wiki/Zero-player_game.


I'm a fan of the term "toy", in a similar lens as "executive toy"


Chaotic systems? As in, fully deterministic systems that are highly sensitive to initial conditions?

EDIT: browsed the code a bit and there is some randomness in the bounce dynamics, so it's only "fully deterministic" if you count the PNRG seed as part of the initial conditions.


If it's chaotic, is it still fully deterministic?


Chaotic means "small change in initial conditions lead to big changes in long term behavior". Best examples of this are double pendulums.

It is still fully deterministic.


"Simulation" probably covers it.


I call them simulations in my own internal vernacular.

There is time, rules, etc...

And an important element is the outcome not being known.

It is that last bit which makes these kinds of programs interesting to write and run.


Algorithm haiku


My 12 year old son just made it in Scratch:

https://scratch.mit.edu/projects/957461584/


You are rightfully proud!


It is really cool. It would be interesting to make the speed proportional to the either the number of squares owned or the square root of that. Because right now as the area the ball owns gets smaller, the number of hits will increase at the same speed.


Like the card game, "War", it seems to self-regulate that way. I assume neither side will ever win.


With "War" it's indeed possible to win, though.


The only winning move is not to play?


War is also entirely deterministic and contains no choices, so some don't consider it a game


Hmm! Because once the cards are shuffled everything is a fixed series of events?

Would Snakes and Ladders be the same then if we replaced a die with a randomized deck of cards of the numbers 1-6? And in that sense: any “game” that’s purely random is also not a game then?


Agree but I think these things can be considered games in the sense that it gives younger kids practice in following rules and interacting within a group. Also is an activity for them to spend time and there is a concept of 'winning' even if the participants cannot impact that.


This is genuinely beautiful on a few levels. Esthetically it is pleasing to just sit and watch. Philosophically it is interesting in that it is a digital metaphor for an ongoing struggle.

Lastly, and most interestingly, it remixes two really simple old ideas into something new. This is an exceedingly rare thing to do well.

Kudos. Many kudos.


Also, it sort of models yin-yang both in what the game is simulating as well as what is presented visually


Ya, that's true. Really beautiful.


3 colors would get interesting, because as the other two bully one into a corner, the small space causes rapid block zapping, quickly bringing it back from the brink of defeat.



In that one balls seem to be able to punch through (and flip) squares (when going almost vertical) instead of bouncing on every square they hit.


It's a bug/choice that is present in the original as well.


That's definitely cool to watch, the patterns of territories get a lot more complex.


Spent a fair bit of time watching that one last night, thanks. I can definitely see why computer scientists were entranced by Conway's Game of Life.


I was inspired by this and created a version with customizable ball count, accessible code... and a speed slider, to satisfy the less patient among us.

https://explorers.toxicode.fr/?remoteWorkspace=pong-war


See also OP’s post on Mastodon: https://hachyderm.io/@vnglst/111828811496422610


Just did an implementation of this in C++ with Qt Scene Graph as a learning experience in case someone is interested https://invent.kde.org/carlschwan/warpong/-/blob/master/src/...



€0.02 another pong variant, desktop only tho... https://www.obfusco.com/pn0gjs/index.html


There's beauty in knowing that one could be ported and run perfectly fine on any old 8 bit computer! So simple yet mesmerizing...


Now I want to try this on my Commodore 64. I should already have some code I could reuse as I was already working on a breakout type of game. So the “clearing a block and bounce the ball back in the right direction” should be somewhat reusable.


Darn, I wish they had named it breakout wars instead.


What if it has real paddles? left-hand (using A,Z) vs. right-hand mode (K,M)? :-)


Hey, I can see an addictive mini game being developed pretty soon… I’m sure one of the bright minds of HN will offer us this game so we can alter/control/influence this never ending battle of the two pongs :-)


Seeing "day" and "night", I thought the site was taking the local time reported by browsers of all the visitors, and rendering a "pie graph" of the proportion of visitors currently with daylight and visitors without daylight...

Although I suppose with the planet's unequal distribution of population (and then the distribution of HN visitors), such a graph would have a correspondence with the time of day.

Now I'm wondering if there is a visualization of time of day at Z vs number of world population in daylight (assuming good weather and no smog...)


Hold my beer.


Done, I opened a pull request for this.

https://github.com/vnglst/pong-wars/pull/5


Hosted it here: https://identity.pub/pong-wars-web/

Control the paddles with:

- Q (Player 1, Up)

- A (Player 1, Down)

- P (Player 2, Up)

- L (Player 2, Down)


It’s like staring into a mirror for the soul. It’s just dots and square why should it feel so dramatic


Only a single HTML file. All you need.


I thought this comment was saying they only used html like this other HN post was talking about https://www.htmhell.dev/adventcalendar/2023/2/ . But no, the comments just saying they put all the .js and .css inside the .html file.


There’s a universe in which it will reach a yin-yang configuration.




So hypnotizing... I was waiting for something magical to happen when the two balls touch.


I was hoping that something would happen when the ball made it to the other side of the screen.


The dividing line slowly shifted to diagonal and then horizontal.


Saw them get kind of intertwined briefly.


I wish the speed of the balls didn't change. I would prefer that randomness come from slight changes to the bounce angle.


So cool I had to spend an hour replicating it in EndBASIC: https://repl.endbasic.dev/?run=jmmv/pongwars.bas -- Super-hacky and buggy, but it works for a quick demo! Make sure to press any key while this runs to drop into the interpreter and play around :)


Oh man - I love this, but I thought it was going to be a loving write up of the freeware “mortal kombat but it’s pong” game from 1994 https://archive.org/details/msdos_Pong_Kombat_1994



Would love to be able to speed this up!


I had the same thought... If you drop this in the console you can speed things up:

    dx1*=2;dx2*=2;dy1*=2;dy2*=2;
edit: someone else in the thread figured out a better way, I updated mine, but credit to them.

Although it has accuracy issues when you get too fast...


Setting the with to 1200 in

   <canvas id="pongCanvas" width="1200" height="800">
give flatter bounces off the long walls. This makes for some interesting 'drill' patterns


Interesting, but is it possible to speed up, or change the color scheme?


Can someone explain what is use of this ? Is there something I am missing?

More confined the area ball bounces more Other ball always occupies 1 spot at time

These two conditions make this game never ending


It does not have to have a use or a point, it is up to you to decided what it represents. I see at as an interactive yin and yang!


It represents a statistical distribution.

Probably not a a bell curve but something related.

The use of it? Humanity has yet to find out, but there are lots of uses for other statistical distributions.

Maybe it finds it use in a machine that calculates the optimal route for autonomous robot drones to take in a warehouse? (Just making it up)

Meanwhile it is there for you to enjoy. A toy.


Neat. Isn't it a bug that sometimes the ball drills deeper?


I don’t thinks so. It’s a bit like in a breakout game where the ball gets “stuck” behind some blocks and clears a ton of them by bouncing back and forth between them.


I think there is.

The ball can wedge itself between cells that are touching and then it penetrates 5-6 cells in clearing the whole path instantly (probably as it's bouncing between the 0 pixel gap between cells).

I had just started the sim and the left ball on its first or second bounce suddenly took a major section of the right side.


Interesting, I wonder if randomness and jitter as its source play a part here. Than, is this the visualisation of a True Random Number Generator?


dx1*=2; dy1*=2; dx2*=2; dy2*=2;


This reminds me of a blog post a while advocating less state, as a demo they implement the infamous DVD screensaver completely stateless.


Tooo cool. I sat and watched it play for a length of time that's longer than I'm comfortable admitting last night.


I love how the “losing” side has a shorter distance to go to “fight back” so it is a somewhat endless battle.


This would look great running on a HUB75 LED panel driven by an ESP32!


Great idea, but watching it makes me feel terribly anxious.


It look like the white ball is faster..


The code introduces some speed variation on each bounce, either positive or negative so it's possible that over time one ball ends up a lot faster?


It does seem to have an advantage. I started it over several times and haven't seen the day side ever get ahead.


This is unexpectedly hypnotizing.


haha cool, reminds me of kid cudi day 'n' night


very cool! reminds me of Arkanoid


Not trying to steal anyone's thunder here, but I was so taken with this little program when I saw it earlier today on Twitter that I thought it might be fun to make it somewhat interactive, so that the players could actually influence the path of the balls using the keyboard, and also activate a "speedup" (mode but at the expense of their ability to influence the path). I also added some charts to track the state over time. You can "play" it here:

https://dicklesworthstone.github.io/ball_fighters/

And code is here:

https://github.com/Dicklesworthstone/ball_fighters

I give full credit to the original author of this post FWIW.


I just did my own mod, hosted here:

https://identity.pub/pong-wars-web/

Control the paddles with:

- Q (Player 1, Up)

- A (Player 1, Down)

- P (Player 2, Up)

- L (Player 2, Down)

Pull request opened:

https://github.com/vnglst/pong-wars/pull/5

> I give full credit to the original author of this post FWIW.

Ditto :)


Sometimes a ball gets stuck behind the paddle in your version.


Something seems off in the behaviour, at least on mobile. The bouncing doesn’t seem to be the same.


The original collision behavior glitched (the ball would skip through blocks of the opposite color)when the velocity was higher, so I tweaked it a bit so that wouldn’t happen. That probably explains the difference.




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: