DDRPad.com dance pad under Linux

I had quite a struggle getting this pad working under linux. Here's how I did it on USB.

First, get rid of the built-in xpad module, which doesn't work.

sudo modprobe -r xpad
echo "blacklist xpad" | sudo tee /etc/modprobe.d/xpad.conf

Then install and test xboxdrv

sudo pacman -S xboxdrv
sudo xboxdrv --detach-kernel-driver --dpad-as-button

You can test with evtest. Pick the XBox controller. If it shows up and shows events when you press buttons, that's good. Especially test holding left and right at the same time -- you should see two "1" events. There's a bug in most USB adapters, because most controllers don't let you hold dpad left and dpad right at the same time. You want to make sure both work at the same time for DDR.

Assuming that works fine, you can play now! Let's add it to systemd. Make these two files as root in any text editor.

# /etc/udev/rules.d/99-dancepad.rules
ACTION=="add", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0268", ATTRS{product}=="PLAYSTATION(R)3 Controller", TAG+="systemd", ENV{SYSTEMD_WANTS}="xboxdrv-dancepad.service"

 

# /etc/systemd/system/xboxdrv-dancepad.service
[Unit]
Description=Xbox controller driver for dance pad

[Service]
Type=simple
ExecStart=/usr/bin/xboxdrv --detach-kernel-driver --dpad-as-button
Restart=on-failure

[Install]
WantedBy=multi-user.target

And then you need to restart or run:

sudo systemctl daemon-reload
sudo udevadm control --reload-rules

It should work now. If you have the EXACT same pad and it doesn't, drop me a comment/email and I'll try to help.

Some failed attempts:

  • The raphnet controller sold on DDRPad.com doesn't add anything -- it shows up as XBox. I didn't actually re-check after the above, but you shouldn't need to order it.
  • The Wingman FGC retro (ZPP006M) didn't work. Nothing showed up.
  • The very cheap Amazon controllers (mine was sold as "Xahpower" but the hardware presents as SHANWAN). They work, but they can't do left+right together.
  • I even tried a kernel patch, which does seem like it works, but not on this pad (not that it's needed).

Debugged with help from Claude.

Tagged ,
leave comment

Computercraft Turtle Replication Challenge

I'm throwing my hat in the ring for the Computercraft Competition to make a self-replicating turtle. It's a bit of late entry -- the deadline was Nov 1, 2012, and the forum has long closed. But I love computercraft, so who cares!

Computercraft is a mod for minecraft. In it you program Lua code to control little turtles.

 turtles can only interact with these three blocks
turtles can only interact with these three blocks

They can:

  • Move up, down, and forward. This costs 1 fuel.
  • Look up, down, and forward (1 block) -- they can't see their environment
  • Mine blocks up, down, and forward.
  • Place blocks up, down, and forward.
  • Turn left or right.
  • Look in and manage an inventory of 16 slots
  • Craft items, assuming their inventory is completely empty other than the craft.
  • Refuel, using any item that can be used as fuel in a smelter.
  • Take the FIRST item out of a chest, or dump items in a chest

So... they can mine and turn for free, but moving costs fuel. And the biggest problem is the list of things they can't do:

  • They don't know their position or location
  • They have no idea what's in any block around them, other than directly in front of them
  • They can't interact with a chest other than the very first slot

They have a few capabilities added since the 2012 post, which I'm taking full advantage of

  • They can move an item from one slot in a chest to another slot, and generally look at the list of items in a chest
  • They can detect what item is in their inventory, or what's in front of them. So they learn it's "oak_planks". Previously, all they could do was check whether it was the same as another item in their inventory! Much harder.

This brings us to the challenge, which is to use a computercraft turtle... to build two computercraft turtles. Possible in theory, but in practice I've only seen maybe 1 completion of the challenge. You're guaranteed that the turtle starts at the bottom of an oak tree. There are various additional requirements for the challenge, which I've basically ignored, but I did display the status for the human watcher.

Here's a video of it happening. There's no sound or audio commentary. Sorry!

I proceed in hardcoded phases:

  • Chop a single log, craft it into planks, and consume it for fuel, so the turtle can move.
  • Chop down the first tree. Place a block at the top, so only small oak trees grow (not large oaks, which are more complicated to chop down). Also craft a chest to store materials we gather.
  • Note: At this point I speed up tick speed and place an automatic bonemeal machine to grow the tree, so it's more fun to watch.
  • Continue to chop down trees until we build up enough planks and fuel for later phases. We also add a sign to the left, to update the player on where we're at (phase, fuel, material-gathering progress).
  • Determine the turtle's height by going to some known height and counting back to where we were. We could either go down to bedrock, or up to world height. Since bedrock is bumpy, I picked world height.
  • Dig at ideal gold ore height, gather gold. Along the way, we've gotten some cobblestone.
  • Dig just above bedrock, gathering diamonds and redstone
  • Dig sideways at sea level in a straight line, looking for sand. Note that I temporarily slow down tick speed, because if the turtle moves itself out of loaded chunks, it shuts off and forgets everything.
  • Craft and place a furnace. Smelt the gold and sand.
  • Craft: a glass pane, a computer, a pickaxe, a crafting table, a turtle, and finally a crafting-mining turtle, same as we started it.

Along the way, the turtle refuels when it gets low on fuel, and deposits items in the chest or drops them to clear space for crafting and more gathering.

How long does it take to make two copies? Well, in a deep sense it doesn't matter, because you can keep doubling indefinitely. But just for amusement, let's find out. I added some logging profiling code to find out what the slow steps are, and they tell us the answers.

  • I sped up the tick rate, but luckily the internal clock also gets adjusted the same way, so we can measure what would have been the clock time no problem: main (1 times): 6959 seconds
  • We also bonemealed the trees! So we better take that into account too: awaitTree (22 times): 175 seconds. Let's change that to a more average value. A minecraft tree takes an average of 16 minutes to grow (provided there's space and light -- we actually set it to perpetual noon, but since it would be easy to place a torch, I'll ignore that)

So the real time is 5.8 hours waiting for trees to grow, plus 1.9 hours for everything else -- a total of 7.75 hours.

If you kept re-placing the turtles, that means you'd have over 1 million turtles in a week. (Well, you wouldn't, because chunkloading--but that's something you could do with turtles too, in theory.)

Tagged ,
leave comment

Minecraft Villager Trading Halls: Probability Math

Recently I was making a villager trading hall in minecraft.

One of the main goals of a trading hall is to collect all villager trades. One of the trickiest is books, provided by a librarian. I got to wondering -- how long is this going to take?

Well, we can do some math to find out.

There are currently (as of Minecraft Java Edition 1.21.11) 40 trade-able books. 36 of them are available from the enchanting table, treasure chests[1], or trading.

4 are available only from treasure chests and trading. These are called Treasure enchantments.

  • Curse of Binding
  • Curse of Vanishing
  • Frost Walker I and II
  • Mending

There's also three books, which can be found only from treasure chests. We don't care about them for trading halls:

  • Soul Speed
  • Swift Sneak
  • Wind Burst

There are no books available only from enchanting and not trading.


The core mechanic of searching for book trades is resetting. If we look at a librarian and find it has a trade we don't want, we reset it.

Villagers remember their profession and trades forever after trading. But if we haven't traded with a villager, we simply remove its profession, and then give it a profession again. Then we can see if we like the new starting trades better.

This is very useful for librarians, because they have every book available as a starting trade, so there's no need to investigate later trades for books.

These are the options to make the villager forget their profession I'm aware of:

  • Ignore the villager and get a new one (for example with a breeder), moving or killing the old one. This isn't a "reset" per se, but it acts similarly.
  • Break the profession block manually. In the case of a librarian, the lectern. When breaking the block, the villager loses their profession instantly.
  • Block the path between the villager and their profession block. I haven't seen this documented, but they reset at the same time as trades reset (twice per minecraft day). I did this by dropping the villager 1 block using a piston.
  • Move the villager at least 48 taxicab blocks from their profession block. (Not tested)
  • Move the profession block with a piston. This is an instant reset, but you can't do it for a lectern in Java edition. (Not tested)

Some of these are instant, some take longer. Once villagers are shown a profession block, it only takes them a couple seconds to get their new profession, so that part is easy.

I found breaking and re-placing blocks to be annoying, so I settled on moving librarians up and down with pistons. It takes about 5 real-time minutes for them to reset, so I used about 50 librarians to counteract that. By the time I finished checking all 50 librarians, they were ready to reset again because 5 minutes had passed.

Then the question is: How many librarians do we need to look at, to get every book?


Well, the first question is: what are we interested in? Let's say we're interested in getting each of the 40 enchantments.

Well, it turns out each enchantment is equally likely: there's a 1/40 chance of getting it. Well actually, 1/60 -- there's a chance that no book trade is offered at all.

Then this is the coupon collector's problem, a classic math problem.

The number of trades to look at turns out to be: 3/2 x n x H(n) where H(n) is the n-th harmonic number. For n=40, H(40) = 1/1 + 1/2 + 1/3 + ... + 1/39 + 1/40 = 4.2785. So we need to check 257 librarians on average to get every enchantment.


But, are we really okay with that result? Given that Efficiency V is available as a starting trade, I want a librarian with Efficiency V, not Efficiency I!

There are:

Enchantment Level
Aqua Affinity I
Channeling I
Curse of Binding I
Curse of Vanishing I
Flame I
Infinity I
Mending I
Multishot I
Silk Touch I
Fire Aspect II
Frost Walker II
Knockback II
Punch II
Depth Strider III
Fortune III
Looting III
Loyalty III
Luck of the Sea III
Lunge III
Lure III
Quick Charge III
Respiration III
Riptide III
Sweeping Edge III
Thorns III
Unbreaking III
Blast Protection IV
Breach IV
Feather Falling IV
Fire Protection IV
Piercing IV
Projectile Protection IV
Protection IV
Bane of Arthropods V
Density V
Efficiency V
Impaling V
Power V
Sharpness V
Smite V
  • 9 tradable enchantments with a max level of I
  • 4 with a max level of II
  • 13 with a max level of III
  • 7 with a max level of IV
  • 7 with a max level of V

What's the chance of getting each level of enchantment? It's equal. So for Mending, there's a 1/60 chance to get Mending I, because it's the only choice. For Efficiency, there's a 2/3 * 1/40 x 1/5 = 1/200 chance to get Efficiency I, Efficiency II, or Efficiency V.

How do we calculate the coupon collector's problem for un-equal probabilities? Well... it's really complicated[2].

But the answer is that we will have to talk to an average of 933 librarians to get all enchants at max level.


But hey. We can buy Efficiency V for 17 emeralds, if we get the right trade. Are we really okay getting a 64 emerald trade? What if we want only the best trades?

Enchantment Level Cost
Aqua Affinity I 5-19
Bane of Arthropods V 17-71
Blast Protection IV 14-58
Breach IV 14-58
Channeling I 5-19
Curse of Binding I 10-38
Curse of Vanishing I 10-38
Depth Strider III 11-45
Density V 17-71
Efficiency V 17-71
Feather Falling IV 14-58
Fire Aspect II 8-32
Fire Protection IV 14-58
Flame I 5-19
Fortune III 11-45
Frost Walker II 16-64
Impaling V 17-71
Infinity I 5-19
Knockback II 8-32
Looting III 11-45
Loyalty III 11-45
Luck of the Sea III 11-45
Lunge III 11-45
Lure III 11-45
Mending I 10-38
Multishot I 5-19
Piercing IV 14-58
Power V 17-71
Projectile Protection IV 14-58
Protection IV 14-58
Punch II 8-32
Quick Charge III 11-45
Respiration III 11-45
Riptide III 11-45
Sharpness V 17-71
Silk Touch I 5-19
Smite V 17-71
Sweeping Edge III 11-45
Thorns III 11-45
Unbreaking III 11-45

Mostly, the price range is based only on the level, but there are a few minor complications:

  • Some price ranges go above 64! In the game, these get capped. For this reason, you're 8 times more likely to get Efficiency V for 64 emeralds than any other number.
  • Treasure enchantments (in bold above) are double the price of any other enchantment. This is actually a double -- they're never offered for odd numbers of emeralds. Interesting!

The chance of getting an Efficiency V book at the best possible price is: 1/16,500 = 2/3 x 1/40 x 1/5 x 1/55 (because there are 55 possible different prices -- counting ones above 64).

To get every book at the best price, we'd need to talk to 45,594 librarians[2] to get every max-level enchant at the best price.

[1]: I think [2]: Source code here. This uses the inclusion-exclusion principle to estimate set sizes, together with optimizations to take care of repeat probabilities.

Tagged ,
leave comment

Hack-a-Day, Day 25: Command line book publishing

Hack-a-Day is my self-imposed challenge to do one project a day, for all of November.

This is my first exception this year - a project that took TWO days (despite best efforts). About 15 hours.

I wrote a program which can take a PDF, and then get it self-published (through lulu.com), and sent to my house.

Source code is on github. This project was co-written with AI, with Claude doing the heavy lifting.

I learned some Playwright along the way.

Expect to see me posting about a bunch of wacky books in the future. Today's is reasonable -- just my recent cookbook update

 This book was ordered by a computer with no human interaction.
This book was ordered by a computer with no human interaction.
Tagged , , ,
leave comment

Hack-a-Day, Day 15: Vibe Chat

Today's project was a vibe-coded chat program. For those unfamiliar, "vibe coding" is programming where an AI does the majority of the coding, and in fact is often undertaken by non-programmers. In my case I took an approach a bit closer to "architect" than entirely hands-off, but an LLM did all the heavy lifting.

The code is here -- roughly one commit per interaction, with a few combined. The prompts are not included.

I've mostly been using AI very little during hack-a-day... sometimes to help debug, and in one case to write another "boring bit" (convert Minecraft world to JSON, for the voxel engine). It might get stuff done, but it's not going to improve the same set of skills to do stuff with an AI. And I'm generally a bit wary of using AI, because it can really just spew some absolute bullshit, which is in my head afterwards.

I've had a relatively better experience using Anthropic's Claude than most other products (for which I have a paid plan). Unfortunately they have very opaque usage caps, and I'd hit limits repeatedly during this project. Then it would say "please try again at 4pm" (in 3 hours). So I pretty much ran out of LLM usage on this one.

Overall I'd say I got to do some coding I usually wouldn't. The project was a curses frontend for a chat (and backend, but that didn't really get done yet). Something like making a curses interface would usually be a bit too boring for me--being able to collaborate with an LLM, who doesn't find such things boring, is great. Other than tooling issues, the main problem is that Claude doesn't write the best code. It generally has a very "junior programmer" vibe, with no use of abstraction, and tends toward the verbose.

My general take on AI though is that someone showed me a horse than can write an essay, and I'm complaining its penmanship is atrocious. It's pretty amazing stuff, and we're probably all going to be dead soon.

In the meantime it's pretty fun to mess about with.

PS: I do plan to update this one further, it just will require a bit of work each day given the rate limits. I had really grand plans, but we only got the bare minimum done.

Peace out!

Tagged , , , ,
leave comment

Hack-a-Day, Day 07: Pokédex

Today's hack-a-day project was the Pokédex -- the fictional companion that tells you about pokemon in the game. My main goal was just to get the info into a reasonable database format, but along with way I built a little viewer too.

The plan is to make some kind of art game where you do pokemon fanart, a coloring book, or even a tracing game in the coming days. And now I'm ready, with art of each pokemon on hand.

Tagged , , ,
leave comment

Hack-a-Day, Day 04: Reverse Vibe Coding

Yikes, been having some back pain, and the past few days it's been tougher to work. I've started four projects in four days, without too much to show for it.

  • Day 01 project is waiting on computation to run; overall I'm happy with it but will post when I get the results.
  • Day 02 project I barely started and won't finish, most likely. It takes a photo of a Go board and tries to output the game. I'd learn some image processing doing it, but I'm sure there's plenty of existing and better tools to do the same thing.
  • Day 03 project was a bit ambitious. Will post it if I finish (and hopefully I will, it's cool!)

Today's hack-a-day project was Reverse Vibe Coding. I sometimes use LLMs such as Claude for "vibe coding", mostly on throwaway type projects. It didn't seem fair for that to go only one way, so today I offered to vibe code for Claude -- it picks what I should make, and I code it up for Claude.

The result is the Conversation Flow Visualizer. This graphs when new topics come up in conversation, and what they are.

Frankly I think it's dumb and useless, but Claude is the boss, so there ya go! Can't pick who you work fo... okay, I guess I could this time.

In any case, it was pretty relaxing to be a junior dev and just do as I'm told for a bit, honestly. Easy win.

I honestly think this would be a good way to learn a new programming language or a new library.

Peace out!

Tagged , , ,
leave comment

Hack-A-Day, Day 03: Voxel Rendering

Hack-a-Day is my self-imposed challenge to do one project a day, for all of November.

How do you render 3D graphics? Here's a picture of a cube:

 a 3D cube
a 3D cube

But when you draw it on paper or a screen, it's flattened. All you see are these three faces.

 a 2D cube
a 2D cube

In fact, if you turn off your brain, it's just three weird polygons. And we can figure out the corners of the polygon. For example, I figured out these with a ruler, measuring they they are on the paper in centimeters.

 some polygons
some polygons

So to draw a cube, we just need to draw polygons. That's the essence of today's project.


Here's a minecraft world.

 my minecraft base
my minecraft base

Here's the same thing in my voxel engine. If you squint, you might be able to recognize they're the same thing. Ignore the stripe at the top.

 my "minecraft" base
my "minecraft" base

Here's a much simpler scene. If you click, you can explore it online

 some 3d stuff
some 3d stuff

The source code is on github.


This hack wasn't perfect. There's some significant problems, and I worked on it 3 different days. Oh well, live and learn! I had fun.

Thanks to Claude for the code to extract minecraft data -- that was not the exciting part of this project.

Tagged , ,
leave comment

Hack-A-Day, Day 01: Go Analysis

The board game Go has been revolutionized in recent years by computer play. In 2016, AlphaGo beat Lee Sedol, a top Go player. This was the equivalent of what happened in Chess in 1997.

Since then, computers have continued to outstrip human players, but we have been learning a lot from Go engines. In this article I did some investigation using KataGo, which I understand to essentially be an open-source clone of the AlphaGo architecture.

This article assumes familiarity with the board game. If you're not familiar, I encourage you to give it a try sometime! Find a local try, or play online.


We have only one operation we can do. We can ask KataGo to analyze a position, and tell us how good that position is. That's the only operation we'll use in this article. And we're supposed to tell KataGo what the komi is.

KataGo returns two pieces of information for a position. An estimate of the score, and a percentage win chance.

 Score is B+12, black win rate is 99.8%
Score is B+12, black win rate is 99.8%

The estimate of the score is determined (according to my very poor understanding), using an estimator which looks at the board, but doesn't try any moves. This is a fast, but low-quality metric.

On the other hand, the win rate is detemined by, simplifying some details, trying playing the game a bunch of times really fast and seeing how often black wins. It's slower, but more accurate.


Our first question is: How much should komi be?

Using only our one tool, let's figure out what KataGo thinks.

Well, in theory, what does a "good" komi mean? It means black and white should both win about 50% of the time. So let's just guess every possible komi, and find the one with the closest to 50% win rate.

Or, we could use the fast score estimator on an empty board with zero komi. If it thinks black is ahead by 6.0, maybe we could set komi to 6.0.

size komi estimate (winrate) komi estimate (neural)
3 +14.0 +4.4
4 +0.5 +2.4
5 +25.5 +23.3
6 +3.0 +4.3
7 +8.0 +8.7
8 +9.0 +6.6
9 +6.0 +6.0
10 +6.0 +5.6
11 +6.0 +5.5
12 +6.0 +5.5
13 +6.0 +5.6
14 +6.0 +5.5
15 +6.0 +5.7
16 +6.0 +5.8
17 +6.0 +5.9
18 +6.0 +6.1
19 +6.5 +6.2

It turns out both methods give similar results. We're going to use the win rate method going forward, because in general I've been told it's more accurate for many board positions.

In fact, we can use the same method to evaluate any board position accurately. We can figure out what komi would make that board position 50-50 for white or black to win. And then we can treat that as the "value" of the position.

For the rest of the article, we're going to simplify, and only ask the value of board positions. We don't care which method we use, but I'll mark the fast-and-simple method as "neural", and the winrate method as "komi" or "winrate" in pictures.


Our next question is, what are different starting moves worth? Well, let's just play every one and see what KataGo says the score is.

 estimating score by finding win rates around 50%
estimating score by finding win rates around 50%
 estimating score with the fast neural estimator
estimating score with the fast neural estimator

Note that all scores are relative to +6.5 for the empty board, which is why some values are negative.


Okay, easy enough. What about different numbers of handicap stones? Using standard placements, we get:

size handicap value estimate (winrate) value estimate (neural)
19 1 +6.5 +6.2
19 2 +20.0 +19.2
19 3 +32.5 +32.5
19 4 +47.5 +46.6
19 5 +59.5 +58.3
19 6 +72.5 +71.8
19 7 +86.0 +85.1
19 8 +100.5 +100.3
19 9 +115.5 +114.7
13 1 +6.0 +5.6
13 2 +19.5 +18.6
13 3 +32.5 +30.7
13 4 +48.0 +47.4
13 5 +59.0 +58.6
13 6 +75.0 +74.5
13 7 +87.0 +84.0
13 8 +100.5 +96.1
13 9 +109.5 +102.3
9 1 +6.0 +6.0
9 2 +16.0 +16.0
9 3 +27.5 +27.1
9 4 +75.0 +53.5
9 5 +74.5 +79.0

Now let's make things more spicy. I keep winning every 1-stone game, but losing every 2-stone game. I want a 1.5 stone handicap. Well we can't add fractional stones, but we can look for something worth between 6.5 and 20 points.

Or, let's find something worth 0.0 points. I want a board position we can start with and not need that dumb komi rule.

Let's do the full analysis. Every possible starting board positions. Then we'll look for one that KataGo says is worth around... say, 12 points.

Of course, we can't really analyze every board position, so I just did ones with up to 2 stones. I included ones with white stones, because why not?

Here's what the ones with two black stones on 19x19 look like. It might take a bit to load, and you'll need to zoom in.


The full set of pictures is online.

  • 19x19, 1-stone positions (black) winrate neural
  • 19x19, 1-stone positions (white) winrate neural
  • 19x19, 2-stone positions (black-black) winrate
  • 19x19, 2-stone positions (black-white) winrate
  • 19x19, 2-stone positions (white-white) winrate
  • 19x19, positions closest to exact point values winrate

  • 9x9, 1-stone positions (black) winrate neural

  • 9x9, 1-stone positions (white) winrate neural
  • 9x9, 2-stone positions (black-black) winrate
  • 9x9, 2-stone positions (black-white) winrate
  • 9x9, 2-stone positions (white-white) winrate
  • 9x9, positions closest to exact point values winrate

You can also get the raw score of 2-stone (and lower) positions on 9x9 and 19x19 boards. The code to do analysis and generate the pictures is on github, as are details on exact software settings used.

Thanks to Google for AlphaGo, and to lightvector for Katago (and Katago support).


Addendum.

After doing this project, I found it had already been done (better) at katagobooks.com. Apparently what I've done is called an "opening book", even if my goal was a bit different.

Tagged ,
leave comment