Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Hexagonal Minesweeper with multiplayer, geographic maps, zoom and pan (multisweeper.com)
92 points by _fp5w on Oct 14, 2020 | hide | past | favorite | 51 comments
For an architectural overview, view source of the page. Bottom has an ascii diagram of the geometry, and how the program works.

For example: "a hexagon is six equilateral triangles (length h) put together around a common center"

      ____                                _______
     /\  /\        « each bisected        \  |  /  (1/2, √3/2)  
    /__\/__\         triangle in it      h \ | /                
    \  /\  /         is defined by          \|/  60°            
     \/__\/ h        the unit circle »     (0,0)



Amazing! That's literally the prettiest code comment I've seen in my life. And a perfect way to document the inner working for the curious!

Thanks for doing it (and telling about it; I'd never guess it's there).


Very nice. Earlier this year I was hooked to this game, another variation on hexagonal minesweeper: https://store.steampowered.com/app/304410/Hexcells_Infinite/ .


Tametsi is another good Minesweeper clone: https://store.steampowered.com/app/709920/Tametsi/


Yeah the Hexcells games are great. It's much like the OP's in puzzle form.


This is pretty great! Like the original minesweeper, it's easy to get into a spot where you have a 50/50 chance, and some shapes are more likely to have more of those than others, but a lot of games have that element of luck.

Very good job!


Thanks, the beginner/intermediate/expert levels are the only ones that give a different difficulty. All the other maps are expert - hardcoded at about the % age of a classic minesweeper mine density. Trade off is you get three lives, though most people (sigh, like me) just reset when they hit their first daisy.

Plan is to rebuild the menu hexagon with these options so you can set it however you like, but this is a side hobby so won't be until next month that I'll get to it. If you spy on what's sent via socket.io, you can override the density parameter in console and request new games ;)

My favorite part of the game doesn't exist anymore, was actually the death screen animations but somewhere between code updates I tabled it and never reinstated it. Random tiles would minimize into the distance and then rotate every few seconds and everything would blur out except the correct numbers, spitting in your face sort of. Was eerie.


Side projects are hard to find time for, but that death screen sounds great! +1 for prioritizing that. :)


Removed it and other animations when render and animation speed became an issue and I focused on optimizing render speeds. Then I never got around to putting them back in. Like, a webgl version of this could probably have a hundred times more hexagons and you wouldn't lose any FPS. But in SVG, it's weird. Biggest surprise, Chrome is finally slow at something - SVG renders - whereas FireFox blazed right through it.

Then a very polite Canadian kid I met on a minecraft server helped me with it, tracing the fundamental issues (thanks, BubbyMK2!). Apparently using rectangles (svg:rect) is particularly slow in SVG, because it forces a redraw outside its clipping boundary. But if you draw a rectangle as a path, no sweat. Or some such.


It seems like end game condition here requires for all mines to be flagged. In classical minesweeper opening all the clean cells is enough for a win. That difference removes the fun and speed advantage of playing without flagging.


Hm. I'll make the end condition configurable so you can pick that as an option. Right now I'm stuck at a second refactoring but the idea is to give the player flexibility on structuring the game when they start it. Right now the end-game routine is a very dumb implementation.

    // meaning all tiles are touched or marked
    // and guesses are correct
    is_board_solved() {
        for( var k in this.board.public ) {
            
            // takes a single unguessed, unrevealed tile
            if(
                this.board.public[k].state === "unknown" &&
                this.board.public[k].guess === false
            ) {
                return( false );
            }

            // or one wrong mine guess
            if(
                this.board.public[k].guess === true &&
                this.board.private[k].mine === false
            ) {
                return( false );
            }
        }
        return( true );
    }


Thanks, cool game! Three lives is pretty challenging on larger fields with lots of unavoidable guess by the way.

Since there's no email adress to be found nor PMs open on Twitter, here is a bug report: there is a mine next to a field of revealed, blank hex fields which shouldn't be possible if blank fields mean that zero mines border to them.

The game is still open, let me know if I should look up a seed or extract whatever useful information for you.

Screenshot: https://i.imgur.com/H5YhfqA.png


> Three lives is pretty challenging on larger fields with lots of unavoidable guess by the way

Agreed. On boards like Flower where there's a long thin strip of tiles, it's very easy to get to a point where it's pretty much a 50/50 guess, no way to logic out of it.

I like the idea of the unique board shapes, but if there's no practical way to win because you just keep hitting wall after wall of 50/50, well, that kinda takes the fun out of it.

Maybe need to think beyond classic minesweeper mechanics for a way around this to keep it interesting?


Hey, thanks for the bug report and taking the time to SS this and track me down here. I'll trace it in memory logs to be sure, but, I think it's on a fence between a bug and a not-bug. Time to torque all the bolt heads for sure.

The recursive clearing routine honors your bad guesses and does not attempt to correct you. Confusing part is that the interface doesn't explain this when it proc's and a detonation occurs. But the maybe-new bug part here you found is likely that an edge detonation shouldn't trigger a clearing routine but I think it did in this case for some reason.

Part of this sort of thing tends to normally happen if you either accidentally do a near-simultaneous right-click and left-click on some sensitive mice, or TCP network latency causes commands to get transmitted in a fast burst. In that latter case, I don't think order of the clicking messages is messed up by network conditions, but, ... I'll double check that to be sure and keep an eye on it, so again, thanks for taking the time to report this.

My alpha tester has finished most of the large maps without hitting a single mine, after many grueling attempts. She started with the flower one and blew out her boyfriend's eardrum screaming about it when she won. We heard the scream bleed through on discord and then there was a man down in Overwatch.

Right now all the shaped maps are manually rasterized. I'm halfway to switching that process to a dynamic on-the-fly one since to my surprise and delight it turns out it's not computationally intensive. But all other than beginner/inter/expert are lazily set at that expert density, vaguely derived from the classic minesweeper's field percentages (20.625%).

The next update will let you select more granular game options, like exact difficulty per map, map tile size (dynamic rescaler), etc. Options right now are to play with multiple players, so you then have 3x lives per player, or of course cheat and invite yourself to the game in a different tab and finish the map ;)



Feature request: When I hit a hexagon with 0 it opens all the contiguous hexagons with 0, but it doesn't open the hexagons around it like the classic minesweeper. Can you add this?

Another more difficult: Can you add a zoom?


Thanks! I actually did it that way on purpose. Reason being is that in multiplayer, you get points clicking around the blurry shape. So, competitive function with multiple players, and there's a risk of misclicking in the rush and nailing a mine.

I do however have an update coming up (sigh after this ... month ... eventually) which will address what you just said, and also try to make sure your first click always hits a hole. But not sure how it'll turn out just yet. I'm a romantic when it comes to random number generators so I didn't want to mess with a pre-generated board just to create a hole. Plan is to shift the entire board by X,Y tiles from where you click, and as you can imagine geometry of irregular shapes is a bit tricky.


Two things from clicking around on the beginner map:

- Sometimes I get zeros with mines next to them

- Like in OG minesweeper, it would be really helpful to be able to click/two-button click/mouse wheel click (whatever you like) on a number tile (whose mines have already been flagged) to clear all the tiles around it.


> ...also try to make sure your first click always hits a hole.

No need to muck with generation - first click always clears the clicked tile, then reveals.


Thanks, I'll put this as an option when creating a new game. As for myself, I definitely like the feel of nailing a larger crystal of empty space and get that Pavlovian sound.

What's funny is that most of the server code is already in place in dev, it's just disabled. I just need to carve some time to pick a direction and work on it. When a board is generated, there's already an algorithm that locates the center of the biggest empty space on a board, and if it exists, it assigns its address to game.clearest_tile.

    // first click, surprise!
    if( game.click_count === 1 && game.clearest_tile !== false ) {
        // sigh, this is too inelegant
        // game.board.private[payload.parameters.address].mine = false;

        // sigh, and this looks like garbage when shifted
        // this is what i get for picking a hexagonal board
        // game.shift_mines_to_center(payload.parameters.address);

        // todo: fixplz
    }
Obviously I can just clear that tile on that first click and be done with it. Or, highlight the emptiest tile on game board render. But the shift_mines_to_center algorithm is something that needs tweaking.


How long does it take to generate boards?

An alternate approach would be to repeatedly generate the board after the first click, till the board has a hole under the click.


Yeah, totally get your point. Generating one is inexpensive, maybe 1 ms to get it cranking. It's entirely possible that looping through untampered RNG combinations until a hole opens is more efficient than scrolling the field around.

The algorithm to locate the biggest hole on a 1,200 tile board takes around 45ms and I'm stubbornly itching to use it one way or another. But I'll see what's a more sane solution over shifting fields.


Also, oops, missed this part. There is zoom.

Unfortunately it requires mousewheel or some magic combination of your trackpad and pinch which, I just hate mobile and macs apparently. Key Z is to zoom-all.


I want to zoom in the other direction, because in the big maps the small numbers are difficult to read.


Oh, I think I get you. You mean the static HUD isn't doing anything for you zooming in the board. That's an oversight on my part, thanks for the report.

Edit: also, you should be able to zoom in on the tiles, but, you're possibly running into an untested edge case, of which there are tons. Mac and mobile is under-developed as I'm a firefox/desktop curmudgeon. As you and others have noted, there is some interface goofery, but otherwise a mousewheel should let you zoom in until you see a moire pattern on a crt.


I'm using Chrome on Windows. No mouse wheel. (I don't even have a mouse, just a touchpad.)


Gotcha. Thanks for taking the time to explain. I'll add some hotkeys (+/-) to initiate a zoom, but otherwise this is a result of my pure laziness.

Not that you can zoom like this now, but you can pan if you hold the ctrl key down and left - click + drag.


Zoom is mouse wheel, says on the front page.


I like how this puts SVG elements directly in the page's DOM; seems like a great way of making interactive vector graphics in a browser. Unfortunately, in Firefox I occasionally get rendering errors when the tile I'm pointing at is highlighted. Sometimes weird things happen after clicking a tile and then pointing at a neighbour[0], but mostly it looks as if re-rendering ‘dirty’ areas and updating the framebuffer are somehow getting out of sync[1].

It's not super annoying, though, because moving the pointer over the affected tiles accusatorily[2] cleans them up.

On an even more hair-splitting note: The tile grid looks slightly wonky instead of perfectly regular. (The borders/gaps between hexes have different thicknesses.) I think this is because the coordinates of vertices are rounded to integer pixel coordinates before rasterisation? I'd suggest trying this: Instead of going for exactly regular hexagons, deform them very slightly so their vertices have integer pixel coordinates. Due to the zoom feature this isn't the most trivial fix ever, but on lower-resolution displays it would look a lot neater[3].

Oh, and a feature request: There should be alternatives to ‘mouse wheel’ and ’middle click & drag’[4] for zooming and panning. Input devices on which performing/emulating these actions is inconvenient (or even impossible) aren't all that uncommon. (E.g. how do you middle drag on a trackpad?) Panning could be done with a regular (left) drag. For zooming, there could be −/+ buttons in a corner, or hotkeys, or right dragging, or dragging while holding a modifier key. Not using scrolling for the zoom function would be nice for players with input devices that have omnidirectional scrolling: They could use that for panning instead. I think it would be fine to keep the defaults as-is, but an option to switch it up in the ‘ESC’ menu would be nice for accessibility.

[0] https://i.paste.pics/AE7L2.png [1] https://i.paste.pics/AE6X1.png [2] Fun fact: Firefox's spelling checker doesn't believe that this word exists and suggests ‘satisfactorily’ instead. [3] https://i.paste.pics/AE7JD.png [4] Which should actually be called ‘middle [button] drag‘, but I'll spare you the off-topic rant ;)


Ha, thanks for the feedback. I'll address all the things I can from your list. Of the visual artefacts, only the last one makes sense to me, a lost mouseout event overtaken by events (yes, I was lazy.) Think it's possible the first two weirdnesses have to do with browser / video driver render optimizations? If you give me your OS / browser / ver / possibly graphics card, I could see if I can replicate it or do something about it.

The first two kind of look like a glitch introduced by a boundary of a blur filter. The individual tiles, when blurred, have an SVG filter (feGaussianBlur stdDeviation="3,3" or "7,5") applied to them. As a performance optimization, think this SVG library (Snap, successor to RaphaelJS) sets that filter to just barely fit over the element in question.

But if the elements move or if the viewport is manipulated to accommodate pan and zoom, these filters visually glitch. You start seeing parts of the blur kind of weirdly clipped off in middle of nowhere. To counter this visual glitch, I overrode the sizes of these filters to an absurd amount, going from -10000,-10000 to 10000,10000, and that fixed the initial rendering problem. But what you're showing kind of looks like a browser or library isn't honoring the set size of the blur filters and render updates from a mouse over/out are triggering a bad restoration of appearance.

As to the wonky grid, think it might be partly due to scaling and integer precision of the hexagon positioning and how various transforms are applied. The positions of tiles are transforms, ints with no decimal precision, but the transformation matrix for the zoom function is very floaty. How a browser handles that intersection of numbers and precisions is magic. At some zoom levels or window proportions (when i fiddle with it), the spacing gets truncated this way and that and some of them look like they round up or down. Maybe I'll offset those pixels by 0.5 and see if there's improvement.


Twice I've started a new game and my first click is a mine.

Feature Request: can you ensure the first click is not a mine?


Ouch, bad luck! Incidentally, that's why the 'instant restart' option got put in. Had my alpha tester growl at me over it.

Thanks, that's already in the works and I'll put in an option for a safe first click. Wrote more about this to another person here, but suffice it to say I'm trying to shift the entire board's biggest randomly generated hole to your first click instead of (re)generating the board with an artificial hole. Because I don't want to tamper with RNG, and I'm a fool. This is the harder overcomplicated way of doing it, so it's taking some time, but it'll be in the next update.


Just swap the mine with any randomly chosen empty tile, no need to regenerate the board.


Hmm. Good thinking. But in case your first click lands in a dense field, that method won't cut a notch in the fabric for you to chisel at. Like a dummy, I'm taking the waiter-pulling-tablecloth-off approach here, but lets see if I get stuck on it.


If you read up on classic Minesweeper, that's what they do, is if your first click is a mine it relocates it to the first open spot off the top left corner.

It's also why you shouldn't click in the top left corner in the game if you're hoping for a good cascade, because you're less likely to get one.

https://web.archive.org/web/20180618103640/http://www.techus...


Annoyance: in classic minesweeper, it is impossible to click on a mine with the first click. If you were to, the game would regenerate itself with a different board that was not a mine there.

This game allows for first-click-failure.


Yep, that issue is a battle I've lost in the court of public opinion here, so mea culpa. Thanks- I'll see about improving it.

Though, in my defense this little clone is already very unlike like minesweeper in so many ways, starting with the geometry - less sides to touch a mine (6 instead of 8). Trade-off is that the number you see is more certain about its neighbors, so the quirk of the first strike grew on me.


Residing in the country with the "longest, continuous minefield in the world"[1], I very much appreciate the harsh reality of "your first click could be your last".

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


Cool Concept. Certainly harder to pigeon hole tiles than with the rectilinear variant. Also would be nice to automatically click the edges when there is an empty region. Overall great work.


If curious see also

yesterday's Minesweeper: https://news.ycombinator.com/item?id=24770616

pure HTLM/CSS Minesweeper (a few months ago): https://news.ycombinator.com/item?id=23920987

boot sector Minesweeper (ditto): https://news.ycombinator.com/item?id=23360133

Minesweeper with a twist (2019): https://news.ycombinator.com/item?id=21883875

infinite multiplayer Minesweeper (2019): https://news.ycombinator.com/item?id=21854494

Other threads: https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...


Midway through this project, I ran into that pure HTML one here and chuckled that someone else was making their variant as well. It really cracked me up! Then there was another, and then I ran into another (yesterday's), so I went ahead and shared mine.

Obviously programmers like to reconstruct things as a hobby, make their own implementations, clones. Just surprising how many of us picked minesweeper. For me it was probably the fact that it didn't come with Windows 10, maybe, when I was jonesing to play it. Also I wanted to see if hexagons would work, without knowing about or seeing similar variants.

I'm glad I did this because it gave me first-hand working experience in a few theoretical things I knew would work but I didn't know what their quirks were, like setting up websockets/socket.io to work with SSL, using multiple rotating apache backends with a graceful restart to perform upgrades without downtimes, responsive and fast SVG rendering techniques.


That's utterly awesome and I hope the links didn't come across as "this has already been done"—quite the contrary—the intention is just "here are cool similar things if anyone's curious". A hexagonal version is a noble and clever addition!


Bug report: during the game, the scroll left swipe to go back gesture is broken on macOS and it zooms in instead.


Thanks, adding to fix list! Though I gave it rudimentary testing and a grumbling Safari EventTarget shim, I didn't chain myself to a mac and play for any extended period. Being an old desktop machine/FF fart, I'm kind of eyeballing mailing mice to people instead of tackling this. Much appreciated!


Doesn't work on mobile :(


Yep :( Instead of firing up tethered Chrome in debug mode, grabbing a 7' St. Croix and going to a pier before sun sets ;) Time better spent, perhaps.

My hunch is it has to do with an implementation of EventTarget, the apparent source of all my Browser/JS problems this month. It did work on mobile prior to me refactoring things to the native event system, but, not since. My best suspect. I'll give it a look for an upcoming update, thanks for reminding me.

Though, honestly when it did work, the performance was ... garbage. I don't have too old of an Android phone or tablet, but it was still a performance struggle on both at simplest of settings and configurations. HTML5 + SVG + DND / touch libs simply weren't stellar for this sort of thing.


Adding geographic areas is such a nice touch. Well done!


Thanks. If the node.js program crashes, you'll see Italy rendered as the 403 error message.

Edit: after yelling at the engine room and upping MaxRequestWorkers, you can see the 403 error page at this lazy URL: https://www.multisweeper.com/apology.html - it was generated by my first rasterizer prototype.

Edit 2: Ach, I meant 503 error!

* turns in web badge and protractor


[deleted]


As long as I can't middle click it's a proof of concept for me, not a game.


Middle-click is the devil's button.

* Attempts to hide the 'middle click & drag' line.

Obviously you're referring to the rectilinear mechanics. But, would middle click work on a hex grid?


On this topic, a feature request: could you designate a letter key to perform the same function as a right click? Right click is difficult on my new laptop's touchpad...


Aye skipper, that's a good idea.




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

Search: