Thursday, November 1, 2018

Doing NaNoWriMo my own way

NaNoWriMo is something I've been vaguely aware of for several years now. I've seen it mentioned online, and my brother even participated in it once.

If you're not familiar with NaNoWriMo, it stands for National Novel Writing Month. The goal of the event is to write about 1600 words every day during the month of November. If you keep up your pace, you will have written a 50,000 word novel by the end of the month.

I've never had a huge appetite for literature. I rarely make it past the first hundred pages of a book, and have very little interest in writing fiction. But I do program. And there are projects that I've wanted to work on, but never gotten around to. So, instead of writing a novel, I'm going to spend every day in November working on a programming project.

Introducing, HamBot.

HamBot will be a Twitch chat bot intended to be run from a Raspberry Pi on your home network.

Twitch chat bots come in two basic flavors. There are chat bots like the StreamLabs chat bot that you run from your personal computer. The other flavor is a bot hosted and run by other people, like NightBot. The benefit of a hosted bot is that it is always on, even when you are not streaming. The downside is that you relinquish a lot of control. A streamer friend complained to me recently that the chat bot she uses has no way to export data, such as channel quotes or stream currency (fake internet points by viewers the longer they watch the stream).

HamBot's goal is to provide the benefits of a hosted solution, while leaving the streamer in full control of their chat bot. HamBot will be "hosted" on an inexpensive Raspberry Pi that a streamer can connect to their home router, do a bit of configuration, and then leave on 24/7.

The main design problem here will be to make installation and administration user friendly to the average streamer. This is the main thing I intend to solve by the end of November. HamBot itself will not have many advanced features. Those are fairly easy to add once the basic installation problem has been solved.

If you like, you can follow along here: https://github.com/haydenmuhl/hambot

Sunday, March 11, 2018

Fate and the Elusive Mental Conflict

This post assumes familiarity with the Fate role-playing game. The rules are available to read online for free if you'd like to learn more about it.

One part of Fate that has never sat well with me is mental conflicts. I love that the game supports a combat mechanic besides the typical brawl, but I've never been able to figure out where it would actually fit in to a game. Even when watching examples of mental conflicts in actual play videos, they felt off in a way I couldn't put my finger on, until recently. I think the key to all this is that we're applying the wrong mechanic. Instead of using conflicts, we should be using contests.

Let's look at a concrete example. Reddit user ParamedicAntic posted a thread with an example of a mental conflict between Spider-Man and Aunt May. The background is, Peter agreed to volunteer at the soup kitchen with Aunt May, then forgot and promised Mary Jane that he would spend time with her. Aunt May calls Peter to ask where he is, and the conflict ensues as Peter tries to get out of his obligation at the soup kitchen.

Right away, something feels wrong. As this phone conversation drags on, Spider-Man is going to be filling up his stress and consequence boxes as Aunt May guilts him into coming to the soup kitchen. Those consequences are the same consequences that would get filled if Spider-Man were in a fist fight with the Sandman or Doc Ock. This seems entirely incongruous. How could a phone conversation with Aunt May be as damaging or debilitating as getting body slammed by a super villain?

The short answer is, it wouldn't be, and we can turn to the rules to see why. Here's how the Fate Core rule book describes a conflict.
In a conflict, characters are actively trying to harm one another. It could be a fist fight, a shootout, or a sword duel. It could also be a tough interrogation, a psychic assault, or a shouting match with a loved one. As long as the characters involved have both the intent and the ability to harm one another, then you’re in a conflict scene.
That last sentence is the key. The characters involved need to have "both the intent and ability to harm one another" for this to be a conflict. I don't think Aunt May wants to hurt Peter. She just wants him to come help her at the soup kitchen. Peter doesn't want to hurt Aunt May, either. He just wants to go spend time with Mary Jane. No intent to harm means it's not a conflict.

So, let's look at contests instead.
Whenever two or more characters have mutually exclusive goals, but they aren’t trying to harm each other directly, they’re in a contest. Arm wrestling matches, races or other sports competitions, and public debates are all good examples of contests.
This really describes the situation perfectly. Aunt May and Peter have mutually exclusive goals (where Peter will spend the day), and they aren't trying to hurt each other.

If that's the case, then what is a mental conflict? The key ingredient is intent to harm. This could take a lot of different forms. The most obvious would be a direct insult ("You're ugly"). Maybe it's a lie ("I never loved you"). Maybe it's the truth ("I am your father"). Maybe it's poking an old wound ("It's your fault your partner died"). It could be destroying a beloved object ("No, not my collector's edition Fallout bobble head!").

I think the neat thing about this is that it also removes the need to strictly divide mental and physical conflicts. In the middle of a fist fight, you could decide to smash the bobble head instead of going for another punch. You could also have a conflict between something like a barbarian and a politician where one side is physical and the other side is mental. The barbarian is trying to smash his opponent's face, but the politician attacks by saying things like, "Your friends are already dead and it's your fault."

I think the culprit here is the use of the word "conflict." In colloquial terms, Aunt May and Spider-Man are absolutely in conflict with each other. But they're not in a Fate conflict, because they lack the intent to harm one another. I think by carefully inspecting the characters' motivations, it will allow us to better utilize the contest mechanic, and have richer conflicts by including mental or psychological attacks into what might otherwise be entirely physical brawl.

Wednesday, October 25, 2017

D&D 5e: What does the d20 do?

The main use of the twenty sided die in Dungeons and Dragons is to determine whether something does or does not happen. A d20 roll would determine the answer to these questions:
  • I shoot my bow at the dragon. Do I hit it?
  • I try to scale the wall of the castle. Do I climb it successfully?
  • The vampire tries to charm me. Do I resist the effect and retain my wits?
Now, there is a bit of nuance beyond simply using the d20 to answer yes/no questions. Each of these three examples represents one of the three different types of rolls you will make with your d20: attack rolls, ability checks and saving throws.

So, what's the difference between these three types of rolls? They apply in different circumstances.

Attack Rolls


Attack rolls are the easiest to understand. You make an attack roll when you are trying to physically hurt someone else. Trying to stab a goblin with a dagger? Attack roll. Trying to shoot a giant spider with a crossbow? Attack roll.

Some spells spells also require you to make an attack roll to see if you hit. The spell will say if that's the case. If the spell doesn't mention an attack roll, then the spell automatically hits.

Ability Checks


Ability checks are when your character is trying to accomplish a goal. Trying to push over a statue? Athletics check. Trying to follow the tracks of an owlbear? Survival check. Trying to stabilize a fallen comrade? Medicine check. Trying to threaten information out of someone? Intimidation check.

Saving Throws


Saving throws are when your character is trying to avoid a negative consequence. The negative consequence could be any number of things. Perhaps you've accidentally set off a trap, and you're trying to avoid getting caught in its steel jaws. Perhaps a medusa tried to turn you to stone, and you're trying to resist the effect. Perhaps you're walking through a desert and you're trying to resist the exhaustion of not having enough water. Perhaps you are mortally wounded, and you're trying to stave off death itself.

In each of these situations, you're trying to avoid something. Each of these will call for a saving throw.

For many spells that do not require attack rolls, instead, the target of the spell will have to make a saving throw. Spells that have an area of effect tend to work this way. Just like with attack rolls, the spell will explain who needs to make what kind of saving throw.

Saturday, March 12, 2016

The Yelverton

I was playing computer games and drinking whiskey gingers one weekend, when I ran out of ginger beer. I needed something else to mix with my whiskey. Of all the things I had on hand, Earl Grey tea was the least crazy. I gave it a shot (ha!), and it ended up being pretty amazing.

Here are the official ingredients of a Yelverton:
  • Tea, Earl Grey, hot
  • Irish whiskey
I realize I'm not the first person to come up with this, but I liked it enough, I decided it needed a name. After some digging around, I finally happened across the Wikipedia page of the Yelverton case. The Yelverton case was an important legal dispute in the 19th century that helped lead to the legal recognition of Irish and English intermarriage. Seemed fitting, given the ingredients.

Monday, August 11, 2014

Hollywood doesn't know how to computer

I thought I would share a funny clip from "Law and Order: SVU" I found.

In this clip, computer tech Reuben Morales shows detectives Benson and Stabler how he discovered a hidden message on a flash drive belonging to a pedophile. He finds "computer code hidden in a pixel" of a picture of a rainbow. He "cracks" the computer code to find a "hidden file" with thousands of pornographic images. In other pixels, he finds PDFs listing the names of the people in the pictures.

What's so disappointing about this scene is that the writers were a hair's breadth away from real methods for hiding information. There is a form of steganography where you use the low order bit of each pixel to hide a message. In an uncompressed image using 24-bit color, each pixel is encoded with three bytes, one byte each for red, green and blue. The human eye is not sensitive enough to distinguish colors that are adjacent to each other in this color space. That means an image with a message encoded into the lowest bit of each byte should not look strange when viewing it in a normal image viewer.

If the writers had consulted an actual engineer, they could have made some very minor tweaks to make that scene actually make sense. First, the hidden message should have been spread across multiple pixels. Steganography works by breaking up the secret message into tiny parts and sprinkling it throughout whatever message you're hiding your payload in.

The next mistake they made was to say that the thousands of images were actually stored within the one rainbow picture. One large image could probably hold a fair amount of data, but you are not going to hide a thousand images inside one image (let alone one pixel). It would have made more sense to hide something like a cryptographic key. Cryptographic keys are on the order of a couple hundred bytes and could easily be hidden, even in very small images. The cryptographic key could then be used to decrypt a hidden volume containing all the images and PDFs.

There you have it. Two small changes that could have made the world of difference. The writers could have even thrown in the word steganography to make themselves look extra smart. Instead, we have this.

Friday, February 7, 2014

Fixing a bonehead mistake in Solr

I was poking around in one of our Solr cores at work when I got this output from a query.
{
  "responseHeader": {
    "status": 0,
    "QTime": 248,
    "params": {
      "indent": "true",
      "q": "*:*",
      "_": "1391802519673",
      "wt": "json"
    }
  },
  "response": {
    "numFound": 36529751,
    "start": 0,
    "docs": [
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3304997"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645477"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645478"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645479"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645480"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3496486"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645481"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645482"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645484"
      },
      {
        "userId": "ERROR:SCHEMA-INDEX-MISMATCH,stringValue=3645485"
      }
    ]
  }
}
The reason for the error is that I reworked the schema of the core. I changed this field from a string to a long, and I forgot to delete all the existing records before reindexing.

Oops.

Okay, so how to fix it? I was able to determine that searching on the userId field with a numerical value would not return any of the corrupted records. A query like userId:[0 TO *] would select all valid records and exclude all corrupted records. I could invert that by doing *:* -userId:[0 TO *] to select all the corrupted records. A quick delete by query, and all the corrupted records disappeared.

Monday, November 18, 2013

Orange-ginger cranberry sauce

I think a lot of people don't realize how easy it is to make cranberry sauce from scratch. Here is my paraphrase of the cranberry sauce recipe that you will find on most packages of fresh cranberries.

  • 1 pound fresh cranberries
  • 1 cup sugar
  • 1 cup water
  1. Combine all ingredients in a sauce pan.
  2. Simmer until it looks like cranberry sauce.
This recipe is foolproof and will result in a solid, tasty cranberry sauce. However, it can be improved upon. I've been experimenting for the past few years, and I've finally hit on a really wonderful cranberry sauce recipe. It is a bit more involved, but I think it is well worth it.
  • 1 pound fresh cranberries
  • 3/4 cup sugar
  • 1 orange
  • 1/2 cup boiling water
  • 1 tablespoon grated fresh ginger
  1. Steep the grated ginger in the boiling water for 5 minutes. Strain the ginger and discard. Reserve the ginger water.
  2. Zest and juice the orange. Combine the orange juice with the ginger water. If the combined liquids are less than 1 cup in total, add water to bring it to 1 cup.
  3. Combine the orange zest, orange juice mixture, sugar and cranberries in a sauce pan.
  4. Simmer until it looks like cranberry sauce.
The addition of the orange and the ginger make a subtle, but tangible difference in the flavor of the sauce. The orange-ginger sauce has a brighter and tangier flavor. In a side by side comparison, most people should be able to tell that there is something different about the sauce, but I think it would take a discerning palate to be able to identify the specific flavors.

In my recipe, I've cut the sugar a bit, because I enjoy a tart cranberry sauce. This can be adjusted to taste. Steeping the ginger is a trick I learned from making ginger ale at home. I really wanted the fresh ginger flavor, but didn't want fibrous bits of ginger mixed into the sauce itself. The extra step of making a sort of ginger tea accomplishes this with minimal extra effort.