A View Inside My Head

Jason's Random Thoughts of Interest

NAVIGATION - SEARCH

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);

 

Metro: Introducing the Local and Web Contexts

I recently recorded an episode of The Tablet Show with Carl Franklin and Richard Campbell (it will be published at the end of July 2012) where I rambled on about discussed different concepts that are needed to construct a Geospatial Metro-style application.  Since I seem to do more web development these days than anything else, I naturally approached this from a HTML/JavaScript developer's point of view.

The geospatial part is really irrelevant.  I included it because I could speak to the subject matter, and it permitted me to establish some constraints around the otherwise huge topic of writing a Metro-style application.  From the web developer's point of view, though, there are existing JavaScript-based APIs that the developer will be interested in using while writing the Metro application (i.e., jQuery and OpenLayers comes to mind).  

Now, when you write a Metro application using .NET or C++, there's a compilation step that takes place to compile the source code into an executable (EXE and/or DLL).  The executable and any dependencies are packaged into an application package (an .appx file), which is really just a renamed .zip file that contains the files, a manifest, and cryptographic information to ensure that the contents were not tampered with.  Aside from WinRT libraries, everything that is needed to run the application must be included in the package.

HTML/JavaScript Metro applications, by contrast, actually run as a web page inside of an Internet Explorer 10 process.  The source files are stored within the application package, much as they would be on a web server.  But, instead of downloading HTML, JavaScript, CSS, and images from a web server across a network, the resources are retrieved from the .appx file on the user's hard drive (much faster load times, and the application is still accessible when there is no network connectivity).

Metro-style applications built using HTML/JavaScript still have access to the Windows Runtime and can do just about anything that their compiled-counterparts can.  In order to allow such privileged access, however, certain common practices in the web world had to be explicitly prohibited.  Specifically, anything that attempts to inject HTML or script into the DOM of a Metro-style application will result in an exception (to prevent third-party script injection attacks).  More details can be found here: http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx

This safe HTML filtering causes a problem with a lot of existing JavaScript libraries.  So, how is a developer supposed to use such a library inside of a Metro application?  It turns out that in the case of Metro-style applications, Internet Explorer 10 will assume two different personalities: Local context and Web context.  

The application bootstraps into the Local context.  This mode is what you'll find most people talking about when they discuss building Metro-style applications using HTML/JavaScript because it has full access to WinJS (and WinRT). Local context URIs start with the "ms-appx" protocol, and the resources must exist in the .appx file.

The Web context is totally isolated from the Local context, and cannot access WinRT and a lot of other things that the Local context can.  As a result, code running in the Web context behaves pretty much like a normal web application today.  This means that developers can continue using those existing JavaScript libraries that don't work in the Local context!

Web context URIs start with the "ms-appx-web" protocol (if the resource exists in the .appx file), or the "http" protocol (if the resource is to be loaded from a web server).  Specific differences between Local and Web contexts is documented here: http://msdn.microsoft.com/en-us/library/windows/apps/hh465373.aspx

In practice, an IFRAME is used to introduce Web context content into a Metro application.  In this way, the outermost web page runs in the Local context, while the IFRAME's content runs in the Web context.  It's possible for the IFRAME to be styled to fill the entire screen, if needed (and the outermost web page becomes just a thin hosting shell).

A common scenario is that data in the Local context will need to be sent to the web context (and vice versa).  For instance, code running in the Local context may listen for events fired by the device's Compass sensor.  When a new directional heading is established, the Local context code will need to send the new data to the Web context code for further processing.

HTML5 defines a means to do this cross-document communication using the window.postMessage() function.  In the case of the new Compass reading, the Local context code would post a message to the IFRAME.  The Web context code would need to register an event listener for the window's "message" event.

The messages themselves are strings, and the developer is left with the task of implementing a data protocol.  JavaScript Object Notation (JSON) will often be used to serialize JavaScript object to a string representation for the purpose of transferring across the contexts (the sending side will use JSON.stringify() to serialize the object, while the receiving side will use JSON.parse() to deserialize it).

The hybrid Local-Web context architecture allows an existing HTML5/JavaScript web application to be converted into a Metro-style application without the need to modify third-party JavaScript libraries.  Though, even after such a conversion, there will still likely be some clean-up needed to make the existing application behave more like a Metro-style application, such as implementing the App Bar for commands, and taking advantage of the Search and Sharing contracts.  But, the reward for going through this effort is an application that can then be distributed or offered for sale on the Windows Store to an audience of millions of potential users.

Want to try these things out today before Windows 8 launches this Fall?  Release candidates are available for free:

Windows 8 Download: http://aka.ms/JenWin8

Visual Studio 2012 Download: http://aka.ms/JenVS2012