A View Inside My Head

Jason's Random Thoughts of Interest

NAVIGATION - SEARCH

Codestock Recap

Last week, I had the privilege of delivering two talks at Codestock in Knoxville, TN.  I was part of the very first Codestock years ago, and try to attend whenever I can (scheduling conflicts with other events made it so that I could only attend every other year).

One of the best parts of this conference is that it draws in speakers and attendees from such a wide geography.  The Great Lakes region was well represented, with the usual cast of characters from Michigan, Ohio, Kentucky, and Tennessee.  But, there were also a lot of presenters from New England, East Coast, and the Southern states as well!  I often run into these folks individually at various shows, but there's something about Codestock that brings everyone together in one venue.

The trip down started for me as many conference roadtrips do: picking up Mike Eaton, and then spending 8 hours in a car with him.  Along the way, we met another speaker from our area, Tim Wingfield, and provided him with transportation from Florence, KY in exchange for much needed harassment of Mike who was driving when we were nearly out of fuel and nowhere near a gas station.

I gave my first talk (Custom Graphics for your Web Application: The HTML5 Canvas and Kinetic.js) to a packed room at 8:30AM on Friday.  Despite having 70 minutes, I didn't have the delivery pace tuned well and really could have used about 5 more minutes this time to avoid rushing the last few demos.  The audience was great and asked many questions along the way.  One person shared details of a project that he was working on that involved the drag/drop of shapes into a process flow type of diagram within the browser.  The demos that I presented during this talk are hosted on GitHub: https://github.com/jfollas/CanvasKineticDemo

My second talk (Knave Blackjack: The Story of Writing a Window Store App for Sale) was another 8:30AM session on Saturday.  Despite the mantra "Pros Play Hurt", I did not partake in the normal conference tradition of drinking whisky until all hours of the evening the night before.  However, the lack of people in the venue that morning seemed to indicate that a lot of attendees did stay out late.  The handful of people that attended this talk, however, were very engaged and simply wanted to learn about my experience of submitting apps to the Windows Store because they were interested in writing apps themselves.

Since we needed to get home at a decent hour on Saturday, Mike, Tim, and I had to start back around lunchtime.  I managed to be in my bed by 10PM on Saturday, which is a really decent time for me at the end of a roadtrip like this.

This year's Codestock was organized by a new team of people (in the past, the effort was largely performed by Mike Neel himself, from what I understand).  There were little snafus leading up to the event, but the conference itself seemed to run very smoothly while I was there.  Kudos to the team, and I know that they'll nail all of the little details next year!

Knave 21 (Blackjack): The Fairness of Random Cards

Blackjack is one of my favorite games in the casino.  I'm a casual player, and certainly not an advantage player by any means.  To help me drill basic strategy, especially for things like soft hands and splits, I decided to write a version of Blackjack for Windows 8 and make it a game that *I* would like to play.  Since I'm not a high-roller, I also wanted to simulate the bankroll that casual players might use in an actual casino: $500 buy in at a $10 minimum table.

Thus, Knave 21 (soon to be renamed Knave Blackjack) was born after a couple of hundred hours of work in the evenings and weekends (the version in the Windows Store represents the third rewrite, and a version currently in development has undergone major refactoring recently as I prepare to add more features in the near future).  It's been a labor of love, and I hope that the attention to detail reveals that.  I've received a lot of positive feedback, and, recently, some negative feedback as well (which prompted this blog post).

One thing that every card game author likely struggles with is how to randomize the card selection so that it's fair to the player.  Knave 21 has the concept of a shoe, which is 2-6 decks of cards that are shuffled together.  It penetrates much deeper than a real casino (the reshuffle automatically occurs when 12 cards remain in the shoe), but the randomness of the deck is very dependent on whatever pseudo-random number generator can be coded in JavaScript.

Instead of relying on JavaScript's Math.random() function, Knave 21 utilizes the Alea library by Johannes Baagøe to provide a better distribution of random numbers.  And, since the shoe is serialized and saved to roaming storage (so you can resume a game on another computer), I didn't want to pre-shuffle the shoe.  Instead, a random card is selected and removed from the shoe upon demand.  If someone were to view the roaming state data, they could see what cards were left in the shoe, but not what the next card would be.  

More importantly (and in response to some recent negative feedback), the game doesn't care what cards have been played or how much you are betting when determining the next card - it simply picks a random number and that's the card that is drawn.  

I'm very concerned about Knave 21's reputation, especially since I have paying customers now that the app is listed in the Windows Store.  In the interest of openness, the code for the shoe implementation follows.  Note the "nextCard" function for the RNG implementation.

Knave.Shoe = (function (Alea, undefined) {

    var shoe = function (decks) {
        this.cards = [];

        for (var d = 0; d < decks; d++) {
            for (var s = 0; s < 4; s++) {
                for (var r = 0; r < 13; r++) {
                    this.cards.push(new Knave.Card("A23456789TJQK".charAt(r), "HDCS".charAt(s), true));
                }
            }
        }
    };

    shoe.prototype = {
        nextCard: function (facedown) {
            var random = new Alea();
            var index = random.uint32() % this.cards.length;
            
            var c = this.cards.splice(index, 1);

            if (c.length === 0)
                return undefined;

            var ret = c[0];

            if (facedown !== undefined)
                ret.facedown(facedown);

            return ret;
        },
        remaining: function () {
            return this.cards.length;
        }
    }

    return shoe;
})(Alea);