Back to the talks Previous by track: The browser in a buffer Next by track: Emacs MultiMedia System (EMMS) Track: General

Speedcubing in Emacs

Vasilij "wasamasa" Schneidermann (he/him) - Pronunciation: [vɐˈsʲilʲɪj] [vazamaza] [ˈʃnaɪ̯dɐman], IRC: wasamasa, Website: https://emacsninja.com Fediverse: @wasamasa@lonely.town, mail@vasilij.de

Format: 14-min talk; Q&A: IRC
Status: All done

00:00.000 Introduction 01:35.400 Cubing in Emacs 02:01.160 Prior art 02:32.040 The name 03:16.520 What's in wca-prep 03:49.240 Demo 05:15.340 Challenges: Representing the cube 07:09.220 Scrambling 08:09.500 Visualization 08:56.420 UI with Transient 09:55.580 Book-keeping with SQLite 11:12.580 Conclusion

Duration: 13:35 minutes

Description

Emacs is well-known for its kitchen-sink nature and sheer extensibility. However, its utility for tasks beyond text manipulation is still disputed. While it is possible to do most of your computing inside Emacs, the existing solutions are of varying quality. Sometimes it is necessary to create a custom solution tailored to one's personal needs and I believe Emacs to be a worthwhile platform for this.

In this talk I present my journey of building a package to assist me with speedcubing, a competitive sport with the goal of solving the Rubik's Cube as fast as possible. Along with a demo, useful Emacs features and challenges that came up during development will be shown.

Discussion

Questions and answers

  • Q: I see that there is a way to document the time it took to complete the puzzle; however, what about other things such as the date and time, and potentially a note on technique or warm up routine etc? It seems like an interface that included these things would also help people who are practicing and trying to improve. It would help answer the question... what kinds of things do I need to do to improve. ;;Thank you for your answer.
    • A: Currently, only the timestamp and completion time are recorded for the puzzle/label. However, I've looked at twisty-timer and it does record both the used scramble and a comment field as well, so I plan adding those once the other features work properly. This would allow keeping track of particularly good/bad solves for example.
  • Q: As a side-note, could you say something about how you use emacs to help with your cybersecurity or CTF actifivities? Are there some recommended packages or do you use all of your own templates and procedures to speed your activity? Maybe just post a link to your homepage or GH repositories.
    • A: It's pretty much only Org usage to document my activities in a way that I know what I did 3 weeks ago and can pick up my research from then. I do not use Emacs for source code review specifically (depending on the target environment, there are better suited tools). The thing with the field is that often, one has to resort to work with whatever tools are at hand and to make the most of them, which is kind of at odds with using Emacs first and foremost as an integrated environment for everything. Other than Org, I use it as an editor for pretty much any programming language I encounter.
  • Q: What are the biggest challenges to using transient?
    • A: The documentation was very high-level compared to what I'm used to, so I had to skim it a lot to find out how to use it for basic tasks. I think it would be useful to have some slightly more hands-on examples for common tasks. One issue I've run into a few times was the code using generic functions, so it was difficult to debug errors (like using a non-interactive lambda form when a command was expected and getting an unhelpful error message).
  • Q: Very cool project.  Alas I'm not a cuber, so my question is merely, what did you learn in the process of making this presentation?
    • A: I've never recorded a demo video happening outside of my laptop before, so getting the external recording setup right was... fun. It involved a ladder, several cardboard boxes and my phone. After five attempts (one of which ended up with the cube rolling off the desk loudly), I finally got an okayish recording to use for the presentation.
  • Q: Does svg.el support tap events? 
    • A: svg.el is only responsible for generating valid SVG documents and one can put whichever tags/attributes there they wish. From my understanding, anything interactive usually solved with JS in the browser would need to be rewritten using Emacs Lisp instead. Tap events for example could be solved with the ":map" property put on the image and would work for other image formats than SVG as well.

Notes

  • There's probably quite a few cubers in here. =) I tend to average 50s on 3x3, the kiddo is usually a bit faster.
  • I've recently got a 45s best with LBL
  • I have some code in my config to draw last-layer diagrams as SVGs and an Org link thing like #+LINK: pll https://alg.cubing.net/?stage=PLL&type=alg&setup=x_y_z&view=playback&alg=%s to link to algs quickly; https://sachachua.com/blog/2023/02/using-org-babel-to-learn-rubik-s-cube-algorithms/
  • speaker: ah yes, I've had the idea to try out roofpig or cubing.js for doing that in org documents, nice to see it has been done before
  • FWIW transient just had a v0.5.0 release which adds and fixes things. It continues to improve thanks to tarsius's tireless work.
  • i'm glad you're exploring Emacs UI wasamasa , i've also been confounded trying to write a transient, and its nice to see that sqlite is working for ya
  • to be fair, I've considered to just stick to my usual approach of writing boring code that does work on as many machines as possible, but there were so many new features that would help making a nice looking and working package that I decided to just depend on emacs 29.1

Transcript

[00:00:00.000] Introduction

Hello, everyone, and welcome to Speedcubing in Emacs. First of all, a little bit about myself. My name is Vasilij Schneidermann. Online, I go by wasamasa. I'm 31 years old. I work in information security, and I do consulting and hacking and stuff like figuring out how to break into other people's computers and how to secure their systems basically. You can reach me by email. I do have a self-hosted code repository thingy going on. I have a blog, and you can find me in some other places online, like IRC for example. So about the talk itself, I used to be into the Rubik's cube when I was in school. I forgot about it, though, because these cubes were not very good. Recently I did find some cheap looking cube at a shop. Did not pay terribly much for it. It was so, so much better than my old cube, it was unreal. This motivated me to get back into this really weird kind of hobby. For this, you need to be good at producing a truly random scramble and timing your attempts to get any better at it. There is, of course, existing software to do the scrambling for you and the recording and the timekeeping and such, but all the good options seem to be either web or mobile, for example the cstimer software or the twisty-timer app on Android.

[00:01:35.400] Cubing in Emacs

To my surprise, I did not find a single decent option inside Emacs, so this is basically a case study how to do better. For this, I wanted to make use of all the cool new Emacs features that appeared, like the SVG library; Transient, the library used for the Magit-style interfaces; and the recently added sqlite-mode. And most importantly it was about having fun.

[00:02:01.160] Prior art

So here's a full list of prior art, I will not go into detail about this, but basically we have things solving very different parts of this, but not all of it. For example: we have several, we have a timer. We have several solvers. We have some scramblers. We have some whole-cube simulators, including a 3D one. We have something for making it easier to enter your algorithms in the notation. But nothing that does all of those things in one package, which kind of surprised me. So I present the wca-prep package.

[00:02:32.040] The name

So the name, I found it difficult to come up with a good name and so I looked and I saw, well there's this World Cube Association that holds these competitions where you compete. They do this for the Rubik's cube but also a few others, so there's like a standardized list of events they have for this. There is a standard notation for this and rules and everything. And the goal of my package is basically to help prepare myself for such a competition and in fact a week ago I went to my first one which was wild, but pretty cool. So for this reason I chose this name wca-prep, because it helps me prepare for this kind of competition and this limited the scope significantly,

[00:03:16.520] What's in wca-prep

I have a scrambler, visualization of the scramble, timer, and statistics. I excluded pretty much everything else I've seen. For this reason, I only tried to focus on some very basic puzzles I can solve comfortably, and did not want to do anything else that may complicate things significantly. No other kinds of puzzles, no simulation, no solving, no exotic events, and no specialized scrambles that are only good for practicing specific algorithms.

[00:03:49.240] Demo

So at this point the organizer should hopefully show a small video I've prepared, a one minute video showing how I actually use this to solve a cube and to time my solve.

[00:05:15.240] Challenges: Representing the cube

Okay, so building this thing, there were several challenges. The first one was how do I even represent the state of a Rubik's cube. For this there are many possible representations, no obvious best solution. I did not, well, what helped me was that I did not have to programmatically solve this thing, so I picked the easiest possible representation which is just an array of every single facelet. For a 3x3 cube you have 9 facelets on one side, so times 6 sides you would have 54 elements in this array. So with this representation, it's very simple, but it's kind of weird to do scrambles with this. But otherwise, it worked very, very well. In the future, I plan to learn some group theory, pick a better representation and do this in a much, much more elegant way without compromising speed too much. Yes. Once I had the representation, the scrambling itself should not be too hard. For this, it's important to consider that basically if you do a face turn you end up swapping some facelets with other facelets, that's the easiest way to think about this. To determine which one goes into which one's position, it was pretty confusing to figure this out. For this I went through a few papers, and I found one which suggested to just build a cube out of paper, number every facelet, and turn it and keep track of which facelet moved into which position. And programmatically, the cl-rotatef macro was very, very useful for doing this kind of in-place swapping you need for this operation. So in the future, group theory would hopefully make this a bit less awkward. Here's a photo of this paper cube I made along with a real cube. As you can see mathematically speaking, they are the same thing, they just look very, very different.

[00:07:09.269] Scrambling

So the scramble algorithm itself, I pondered how this would even be done. In the competitions, They do this in a very, very elaborate way. They generate a random cube, they try to solve it, and if it's solvable they use these solution moves to turn into a scramble basically. And they also make sure to canonicalize the moves, so if you have subsequent moves that can be simplified, they do simplify these as much as possible. For example, if you have two subsequent rotations in one direction, it's turned into a different kind of rotation, so 90 and 90 equals 180. And the other Elisp scramblers I looked at, they generate random moves. Some of them do canonicalize. Not all of them. This one tries to do the best low-fi thing, that is, generating random moves, canonicalizing and repeating until enough have been generated.

[00:08:09.549] Visualization

For the visualization I had to figure out something else too complicated. For this, I tried to figure out where every facelift would end up in the puzzle view when you would unfold it. And for this, I did not consider the facelet orientation. This may be important later for some other puzzles where you can end up with very twisted faces, but for simple cubes, it's not a problem. My initial prototype used colored text, but later, I used the SVG library. It turned out to be easy enough to use, actually. Currently, I have hard-coded face-color mappings, but I plan to replace this so that theming is possible. For example, if you happen to have a cube that does not have the same color mappings as I do, then you should be able to fix this.

[00:08:56.469] UI with Transient

Next challenge was to build a beautiful intuitive UI with Transient. The reason why I chose this is because it would be self-documenting and Magit-style, and everyone knows how Magit works basically. Since Transient has become part of Emacs, there is really no reason to not try it out. The problem was documentation is difficult to understand. It's very abstract and high level, and it's hard to figure out. "Okay, I want to do something, how am I supposed to do this?" I did find transient-showcase, which has lots of examples, but they don't really feel finished and not realistic enough. When I tried to use the package, I got plenty of unhelpful error messages when using it incorrectly. I did manage to figure it out, but I plan to find more actual examples of it, to have an executable reference basically and try to improve my use of it.

[00:09:55.629] Book-keeping with SQLite

For the book-keeping, I used SQLite. This is a very recent addition to Emacs, it only appeared in the current major version. It's still very early days. I found some oddities, one of them turned out to be a bug in the transaction macro. Like basically, if you do an SQL transaction and an error happens, then every helper I found does a rollback on an error. But this one did not. It actually committed on an error, and this was very weird to figure out. I reported a bug. Eli was nice enough to send me a patch. We did some patch review, and he ended up fixing it properly. So yes, there's still a lot to be done there, and yeah, the API is very basic. You don't have convenience helpers like fetch the first row or fetch the first value or anything, but they're easy enough to write yourself. And the biggest challenge with this bookkeeping part was figuring out a decent schema, like how to organize data correctly so that it would not be awkward to manipulate. And with this, you can finally build a package that remembers its state properly and don't have to run into foot guns with Lisp-style serialization, deserialization.

[00:11:12.629] Conclusion

So yes, that concludes it so far. So what did I learn from this exercise? Well, there are still plenty of packages for Emacs to be written. If you think everything you can think of or you need has already been written, well, guess what? No. These are still plenty of specialized things that could need your help. These cubes do not require advanced mathematics, contrary to what you may think. Yes, you can apply advanced mathematics to them if you want to, but you don't have to. What surprised me about this is basically group theory. I've heard of it before. It seemed to be a meme, basically, because it has been like mostly Haskell people being very excited about this and it seemed kind of, like, divorced from reality, basically. But this puzzle, it actually proves that yes, it has its use. It definitely has. You just have to find the right problem matching it, and yeah. So yeah, once I understand it better, the topic, I expect to write better code. These new Emacs features, they work well enough. There are some rough edges. They definitely need more testing. So please, please, everyone, if you write Elisp, please try SQLite or Transient or anything else that looks cool and shiny. Report bugs. Find ways to improve them, anything. And yeah, I'm sure that if we do this, then Emacs will continue to get even better. So yeah, what's next for this package? Well, I could... There are lots of obvious UI improvements and testing to be done. I basically want to reach feature parity with the twisty-timer app, which this is very much inspired by. I want nice-looking stats like graphical ones instead of just a simple list of times. And I want support for more puzzles, of course, not just the simple cubes, but as I progress learning these puzzles, I want to have Emacs supporting me for this. But generally, it's a very open-ended package. And this concludes the talk. Thank you very much.

Captioner: sachac

Questions or comments? Please e-mail mail@vasilij.de

Back to the talks Previous by track: The browser in a buffer Next by track: Emacs MultiMedia System (EMMS) Track: General