-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
toward P3 #83
Comments
Hi, Gordon! I'm really excited to see this.
Absolutely! There's Penrose slitherlink, why not pipes)). Regarding the rotations of rhombus tiles I thought of implementing them with some skew transform of a square tile. I made a REPL as a proof of concept that rotation transitions can look nice in this case. Of course the real difficulty is in figuring out correct transforms for different rhombus types and orientations. But maybe this is still less work than transitioning paths. I also must confess that I changed a lot about grid implementations while working on "octagons + squares" grid. Basically I abstracted away a
Maybe there could be a I've long wanted to have this "cubes" tiling - implementing this might be a way to try out rhombic tiles without the additional Penrose complications. Grid logic here can reuse the |
I had the related thought of doing some kind of periodic rhombus tiles next week to test the variable length arms and different angles. To make it easier I might do the simpler one-orientation rhombus first, even though it’s just squashed and rotated squares. I had not considered a skew transform—will check out your REPL, thanks! That might be cleaner than the path transitions. I have not looked at the octagon branch yet, but I will try to rebase on it before proceeding. It’s likely you will merge that before I finish this, and it sounds like you may have implemented some of the same abstractions I’ve been thinking about. |
The disadvantage of skewing a square tile in order to make a rhombus tile is that the pipes will bend at tile boundaries, if the tiles are oriented in different directions. The advantage is that the pipes still land in the center of the tile boundaries. Hard to say which looks better / clearer without trying. The new abstractions look very helpful! |
I am taking your advice and starting with cubes. This is... not working yet... but I think it's really close. not.working.cube.tiles.movFWIW the tiles need to be scaled as well as skewed, because otherwise the diagonals will be longer than 1. Here's a fork of your REPL. I think you scale first then skew, because that way the skew angle is correct. |
I tried to solve one but my clicks land too unpredictably 😂. Individual tiles are looking great though 👍. |
Display and gameplay mostly work for the cubes grid (demo). There are many bugs, among them:
Hope to continue this tomorrow. |
Excellent hints and feedback, thanks! I agree it would be much better to reuse Great point about the wrong opposites, knew I was missing something there. |
With the rotation and direction numbering & opposites all consistent, the cube grid is now working perfectly in non-wrap mode. (It's playable but difficult to complete in wrap mode, because of the off-by-one bug.) I think it's harder than squares but easier than hexagons. The false perspective is disorienting! 😱 Quite a lot still to fix and clean up - realistically probably won't do a PR until next week. |
Wow, I just love solving buggy puzzles. Edge issues on wraps make things more challenging)). Could you add a cubes option to the custom puzzle page? For experimenting with generator settings. I think that this puzzle would definitely benefit from bigger |
It looks like the P3 tiling rules have the same notion of "opposite sides". From the wikipedia page, with binary annotation: Hmm, no matter how you number it, the two rhombs will have directions in different order, though. So yeah, maybe opposites should be hidden away. |
My apologies, I probably won’t be able to clean up my code and contribute for a few weeks. I’m traveling to see my parents next week, and need to clean and pack and so on. I’ll be sure to rebase and continue the improvements we discussed. Very eager to get this in good shape and contribute, just ran out of time for now. |
No worries, have a good trip! |
Cubes are now completely working, including wrap and edge marks, although connecting marks do not work reliably on touchscreens (walls do). I also need to apply the transform for Orient / Lock mode, which I just tried for the first time. I got wrap working last week. I was on vacation, so I didn't mention it here. Reusing Since then I've played more than 100 of the 5 x 5 cube wrap puzzles (which has 75 tiles). I find it quite fun. I think the corners where 3 tiles come together make it slightly easier than square grid, so I'm usually able to prove and auto-lock almost till the end. Best time under 2 minutes but it often takes 10. I think the non-wrap should use the hexagon playing field shape so there aren't exposed corners. It's too easy with those. I'm using transformation-matrix to invert the tile transformation and detect edge marks in the original coordinate system of the polygon. Hope the extra dependency is okay. Needless to say, the transformation matrix approach is very general and will apply nicely to P3 tiles. So neat how the maze generation code works perfectly with no changes for this grid. The only thing that "puzzles" me is that occasionally it draws a fully connected X - does it run out of other ideas? I think this only happens on the non-wrap. I'll squash my commits into one and submit a PR tomorrow. Happy to refactor further. I wasn't sure about the responsibility of controls vs grid for doing transformation - putting the code in the controls seemed less repetitive than adding the transformation matrix stuff to every grid, but maybe there's a better way. Also the "grid tile" containing three actual tiles, each transformed its own way, is maybe not a good abstraction, just expedient. |
I played some 5x5 wraps, they're nice! Quite refreshing after the confusing evilness of etrat grid that I've been working on). It's neat how this grid has two distinct types of corners (with 3 and 6 squares meeting). All the others I've encountered so far have a constant number of tiles meeting in a corner (3 for hexagons and octagons, 4 for squares, 5 for etrat). Places where 3 tiles meet allow for some solver shortcuts but I don't yet know how to apply them to only some places in the grid. Re connection marks I think it would be cool if they could bend at the tile border like the pipes do. I drew a rough example on the pinkish pipe here. But this might be tricky to implement. Like each of the two tiles should draw its own half using its own transforms? Or maybe let's end the mark at tile border at least. The part that's hanging off doesn't look good to me.
There's a helper for that in hexagrid code, something like
Fully connected tiles can happen during pregeneration if there is no other way to complete a puzzle. Imagine the red part here is already visited, and the upper left green corner is not. Both neighbouring red tiles are already T-shaped. And the only way to connect to the green corner is to turn one of them into an X. I don't want to introduce backtracking into pregeneration so I just allow this. A less bumpy field shape (like a hexagon) should make X tiles less likely to appear. I haven't reviewed how the transformations work yet, I'll be able to do that once I finish with etrat branch. That grid is forcing me to learn about web workers because ensuring uniqueness takes too long to just leave it in the UI thread =). |
Etrat is tricky! I look forward to hours of figuring out proof patterns there. I agree that the connection edge marks sticking out are ugly. Wrapping around the edge would be great. I haven't figured out how to get both EdgeMark tiles to draw while only one should record. As an experiment, I added a flag to get_edgemark_line to shorten the mark, but this affected the walls as well, making them short and displaced. I've run out of time this week, so I'll leave it like that for now. I also reverted changes to the controls and created gridutils.js - so the grid has exclusive responsibility of the transform. This is needed for I want to fix everything before submitting a PR, so it's another week if not two. |
etrat-wrap is too difficult for me, and now I'm scared P3 is going to be too. 😭 Oh well, can't stop now... |
Penrose tiles can't wrap by design so they can't be too bad. I expect something around square or cube difficulty. I don't quite understand yet what makes etrat so bad. It must be the triangular tiles? With square tiles if you have a turn and know one connection then at least you can say that the opposite side is a wall. That's often handy. With triangular tiles a turn + one its connection gives... mostly nothing. It's kinda similar to low branching hexagonal wraps that are hard too. One other thing is that etrat puzzles tend to have hundreds and thousands of solutions at even moderate sizes. So even when a puzzle has a unique solution it likely has an obscene number of "almost solutions" that look very very plausible until one last part just doesn't connect. And lookups till you find a contradiction tend to be very long. |
Interesting that etrat has so many solutions! Yes I get stuck on “almost” solutions, even with the 10x10 non-wrap. There will be one extra piece or two closed components. I have no idea how to fix it so I start over or give up. I think you’re right that P3 should be like cubes only irregular, with 3-7 tiles meeting at a corner. |
I tried out the cubes code today and I think the transforms logic is currently a bit wasteful. On every click we compose a transform matrix, then invert it too... That's running a lot of the same computations again and again because we only have three distinct cube faces and so three distinct transforms. It should be enough to compute them only once! I think a better way to go about this would be to do
The I would also remove the translate part of the transform and just give each rhombus its own center coordinates instead. This just seems easier to reason about. Not that it's easy! I tried to implement something along these lines but got bogged down trying to understand transform computations. Can you think of any problems with this approach? I don't really know how many distinct transforms a P3 grid would have. Is there a sane number of them or infinite variety? =) |
I agree the transform should only be computed once per tile “type”, and I like this Also transforms should not be computed or used for the grids that do not use this feature. I think I can revert those changes and only keep a few small changes to the grid interface. As for removing the translate… Maybe? I have often wondered whether it is a good idea to have three tiles per grid position. It was the easiest way to reuse HexaGrid but it’s pretty messy. For P3, I think each tile will need its own transform. There are only two shapes, so the skew and scale will be the same for many tiles, but I doubt it’s worth it to count all the possible rotations of those two shapes. (I’ll check though.) Each tile’s transform and inverse could be computed once. These are 4x4 matrices so it’s not a lot of memory. |
Based on my coloring experiment there are 5 Rhomb offsets should be easy to do, I'd precompute |
Surprising! I guess that's because it's all multiples of 36⁰. |
Next step for me is to implement the P3 tiling itself. I think I’ll use the substitution / drill-down method detailed here: https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/aperiodic-tilings/ I’m more familiar with D3 for SVG, so I’ll probably implement the geometric algorithm standalone, and come back to the tiles in a couple weeks when I have a generator for coordinate and rotation data. |
I have a demo of producing an approximate number of P3 tiles which intersect a polygon. That Tatham paper says how to keep track of adjacency, and I've implemented coordinates for the Robinson triangles. (You can see them by adding At that point the only challenge to Penrose pipes is the neighbours and opposites problem we talked about before. Your solution of the grid returning the opposite when returning a neighbour sounded good and I may give that a try in a couple of weeks. |
I shouldn't jinx myself by talking as if I know what all the problems are. "Patching" the border will also be tricky. Take this example: We will prune any half-tiles when we coalesce triangles into rhombuses, but here that will cause such a jagged upper-left corner once the half-blue is removed that we should either drop the red or add in the other half-blue. Same in the upper-right corner. |
Nice, I played some already. Even got some quasi-wrap experience by starting a large puzzle from the middle)).
I don't get why it needs to be in progress, seems to me it should live in instance only. I haven't looked at the code yet but I'll review how Detached tiles strike again and my streak is dead. It was only six games long 🥲. At least the tab didn't hang). I also saw an example where two thin rhombs were detached from the rest of the grid. So we can't even use "tile with no neighbours" logic to detect this situation. I thought of declaring these tiles empty if the generator can't reach them. But sometimes the generator will choose to start from a detached tile and then the whole grid ends up empty. This is exactly what happened in the previous detached example. Tricky stuff)). |
You're right, the progress state doesn't need grid. I've switched to cull strategy, not as nice border in some cases but eliminates islands by repeatedly removing any rhombs with less than two neighbors. Chose the harder tiles, renamed to penrose. I think the walking stick is the major problem left. I'm looking at it now. |
In theory, I think you could have an infinite penrose pipes puzzle if the maze were generated on the fly as area is explored. Would be a huge endeavor though. |
So can we assign directions with consistent opposites now? |
We could. Since the order of sides in this sense is different for thin vs thick rhombs, there would have to be a mapping for one of them. On the other hand, what you did with the lesser index seems perfectly reasonable for any grid where you don't know the opposites, so maybe that's worth holding onto. |
Super glad to be rid of the walking stick! I hate the hack with inconsistent opposites too to be honest and I want to remove it. But I haven't managed to get consistent directions with the current code. There must be a bug with determining base polygons because when I tried jigsaw marks again I got this result. See two yellow stars made of fat rhombs. Base 0 and 10 rhombs correctly tell that they're flipped versions of each other. But the rest (base 1, 3, 4, 12) just think they are identical when they should be flipped. Instance data for debug purposes: penrose_5x5.json.txt. Downloading a puzzle should give this data but that's another todo along with importing a puzzle on custom page)). I noticed that rhombs data has a |
I agree, by the jigsaw marks those stars should be consistently 0 - 4 or 10 - 14. Instead the pieces seem to be interchangeable. Why then does the simple offset calculation work? That I'm out of time for this week. I'm sure there are many bugs but it runs nice. It's live at penrosepipes.vercel.app. |
I think I have an idea about the wrong rhomb numbers. I assumed that tatham coordinates would correspond to the jigsaw edges but this is apparently not the case. Will look into it next week. Also noted about saving the grid / geometry with the tiles to download. It's too bad the data is so bulky. For the example I had to put it in a separate file because it's much larger than It's useful to have redundancy for various calculations, but I think the saved form could deduplicate. |
It might sound like an overreaction, but I’ve taken down these deployments for now. On Saturday I played for a couple hours after I was too tired to work. I think the perspective distortion made me somewhat ill & gave me vertigo for a few hours after. Like I couldn’t tell which way was up. Not fun. And it comes back if I think about those twists and turns. Granted I’m susceptible to motion sickness from video games, but I don’t want to put something out that could harm people. I want to try somehow making the pipes of uniform dimension. I.e. the tiles still skewed and rotated but the pipes not. So let’s hold off on this a bit. |
Hi @gereleth! I combined the technique for animating arms independently (from the very beginning of this ticket) with clip polygons from PR #101 to produce a demo of Penrose Pipes with uniform pipe widths: I suspect that I solved this wrong, not that there is a bug in the maze. But I can't figure this one out. Now the shapes are completely unfamiliar, but I think this is fair - what do you think? https://penrosepipes-git-p3-gordonwoodhull.vercel.app/penrose/5 It has one severe bug where it is unable to draw arms that go off the grid. If you look closely you will see another glitch implied by arms going straight to neighbour but clipped by polygon. 😉 |
After playing a bunch of rounds, I'd say it's confusing but not disorienting: I'm not getting the vertigo I got from the previous version. But not having familiar or consistent piece shapes makes it more difficult. If the stats are correct it's taking me 5min for a puzzle that took 2min in the previous version. Lots of work before I can release this, even more work before it would be ready for PR. |
It's confusing all right, I can't tell a straight piece from a turn at a glance! You're drawing the pipe line to the center of neighbour, right? In my attempt above I was trying to go for edge middle. Maybe these two approaches could be combined - like we go for edge middle first and then towards neighbour center to ensure a smooth connection. That might make straights mostly straight (with some bendy ends). In your buggy-looking puzzle the tile on the left of the green deadend looks like it still has disconnects. So it's probably a sneaky T looking outside 😄. |
Definitely worth trying. I don't like adding extra bends but if it helps the pieces be more recognizable, that would be nice. I may also experiment with splines as it's a very wavy layout already. And yes that must have been a sneaky T. I am often getting tripped up by 3s on the border. I think every other piece is unambiguous there. |
Okay! I think this looks pretty nice. https://penrosepipes-git-p3-gordonwoodhull.vercel.app/penrose/7 There is an optical illusion where it looks like the narrow rhombs have swollen pipes, but I have measured it and it's not real, just one of those standard optical illusions. It has a knob Zero draws directly to the center of the next tile, as in last week's iteration. Values larger than 1 draw past the edge without splining (just for reference): It's not bad without Beziers, but a a little jittery: https://penrosepipes-git-p3-gordonwoodhull.vercel.app/penrose/7 I'm halfway to fixing the edge pieces; many other things to fix but I think it's quite playable now. |
The 0.7 variant looks awesome, I love it! The shapes are recognizable and the connections are smooth. Being closer to edge middles got rid of corner glitches too. I haven't looked at the code but the results are very nice =). |
Thanks! I still need to clean up, putting the changes safely under flags so they don't break the other grids. In particular clip paths should be enabled only for this grid and for iOS to fix #91. And there is a backlog of things to fix in the Penrose tiles generator that we have discussed before. (E.g. I had to reverse the list of rhombus points and then offset differently for thick vs thin rhombuses, the equivalent of your Given this will take some time, but I'm eager to get this out in the world, here's my plan:
Given my time constraints, this will take months. I'm so happy with how it turned out. The aesthetic is something greater than what I and you put into it - reminds me of fanciful fonts from the 19th century, with just a touch of psychedelia. Or maybe Art Deco. |
I made a quick fix for the missing legs problem in the A more sophisticated approach could use invisible neighbours for bend info but that would be overkill imho =). |
That's a nice solution! Indeed I was trying to look for the invisible neighbors, which is not necessary here. In fact I think it's better to go straight to emphasize that there is nothing there. I haven't tried slowing down the animation yet, but I think it will transition fine, since there are the same number of points per arm (and it's not trying to change between line and curve). I've been playing a lot this week and it really picks up in difficulty on larger grids. This means that if you are playing at your limit, the variation in grid sizes (from a little larger than NxN tiles to almost 3xNxN) can make the difficulty and play times of a particular size erratic. So I think I will shrink the polygon after generation and throw out tiles until the size is closer to NxN. Seems wasteful but it should be fast since I can use binary search and the triangle intersection code that I got from SO is wicked fast. |
I'm tired this weekend, so I've been messing with ragged border resolution rather than fixing the other grids. There was an obvious (in hindsight) bug in the - tri => find_tris.some(find => find.indexOf(tri.coord) === find.length - tri.coord.length),
+ tri => find_tris.some(find => find.endsWith(tri.coord)), With that corrected, the fill algorithm delivers less portion of tiles with two sides on the border 80% of the time, across many grid sizes. The drawback is that it isn't specifically looking at degree, so it delivers grids with some tiles with three sides on the border 2-6% of the time (worse for small grids). So we'll still need to run cull after fill. I've been playing a lot of Penrose Pipes at many sizes, and I remain very happy with the gameplay and the aesthetic. It will be fun to see the more difficult grids your solver produces. The dailies are very hard even with the cube grid, whereas Penrose is pretty easy with the current settings. I have to go to really big grids to get stuck at all in "proofs mode". |
Hi @gereleth - do you have linting or formatting tools I should apply so that merges are less messy? |
I use prettier for formatting, |
Okay, soft launch of penrosepipes.vercel.app is live! Please test to see if you find any more issues. I'll announce later this week. |
Posted on HN and X, please upvote: https://news.ycombinator.com/item?id=37842719
I changed the footer a little bit to add links to both repos and handles. Hopefully it's clear where to post feedback... will adjust if necessary. |
Hi @gereleth!
Since a couple months after you released hexapipes, I've been wondering what it would be like to play this game on Penrose tiles.
In particular, it looks like P3 with two different sizes of rhombuses would be a good match for this game.
Weird things about P3:
I am hoping that gameplay will also be weird but not broken. It should work, just different maze walls right?
I can only work on this on nights and weekends, so it may take me a while to build this. So I will share my progress in this ticket, rebase regularly, and publish the results from my fork at penrosepipes.vercel.app.
I will of course contribute back once something works, assuming it's still maintainable and makes sense to you. I think it will still be comprehensible. There may be something like a graph abstraction above the grid, the game using the graph instead of the grid.
I've published the first change, which is subtle but important. To handle P3 and other tiles that are not rotationally symmetric, we can imagine arms of different lengths and different angles going to points on the edge of the tile which are on a straight line to the center of the neighboring tile. 1
Now instead of rotating the
<g>
usingtransform:rotate(...)
, we can bitwise rotate the tile, obtain its directions, and return the corresponding deltas.We restore animation by applying the CSS transition to the path instead of the transform.
If you look closely, the animation is not as good, and we might consider adding keyframes so that the arms don't get as short during the animation. But I think it maintains the illusion well enough.
The transition only works on Chrome and Firefox; on WebKit Safari/iOS it degrades to no transition. I am sure there are workarounds for WebKit but I haven't looked into it yet.
grid.getDirections(...)
already has an optionalrotate
parameter, but there is a wrinkle: we need the arms to always be listed in the same order for the animation to make sense. So we also rotategrid.DIRECTIONS
by the same amount before filtering.At the current commit (ac09e1c) I haven't yet implemented arm identity for the square grid, and you can see the bug that arises if arm directions are not returned in "original" order.
Here's a screen recording. Believe it or not, the tile is rotating clockwise, but the animation is deceptive: .
I'll publish the fix for this next week!
Footnotes
I hope to find time to draw a diagram showing what arms will look like on P3. It will be weird, because the arms will rotate (and stretch) but the tile will not, but I think it will work. ↩
The text was updated successfully, but these errors were encountered: