Last week, we introduced the Lucky Deuce casino contest. This is a series of challenges, brought to you by our pals over at Infragistics, where we call on you to help us build a “scoundrel’s casino”.

Last week’s challenge was to build a “broken” roulette wheel, that instead of being truly random, avoids recently spun numbers to “feel” more random. I’ve rehosted all of the winners’ code here.

Honorable Mentions

Many of you noticed that, with our rather silly requirements, you didn’t need to do anything to make a cheating wheel. By simply betting on the least recently used numbers, your odds were enough to beat the house. This was true, but that’s not a terribly fun approach. Still, Ryan gets credit for taking that reality and putting a “thumb” on the wheel, so to speak. His solution was to be a little sloppy in how he weighted the probabilities, taking a heavy hand:

def random(self):
    r = random.randrange(0, sum(self.weights))
    for i, x in enumerate(self.weights):
        r -= x
        if r < 0:
            result = i
            break
    # adjust weights
    for i, x in enumerate(self.weights):
        if x < SLOTS - 1:
            self.weights[i] += 1
    self.weights[result] -= SLOTS/2
    if result == SLOTS - 1:
        return '00'
    return str(result)

With this approach, recently spun numbers become really unlikely, which makes a smart betting strategy even more profitable. Congrats Ryan, you get the Just Doin’ My Job award. His solution also comes with a profile.py script, which handily runs a bunch of trials to let you try out his random solution.

Edgar did add a custom cheat, after a fashion. In his solution, instead of checking if a number appears twice in a row, Edgar avoids it if it’s appeared twice. But that’s not what makes his solution entertaining. No, his Python solution, slavishly obeys the PEP8 reccomendations for formatting Python code, to the point of complete unreadability:

    while True:
        # store occurrence of value
        frequency_of_each_roulette_element__list_int[random_position_in_array__int] += __ONE_CONST__INT__
        if frequency_of_each_roulette_element__list_int[random_position_in_array__int] >= __TWO_CONST__INT__:
            # AVOID RUNS, acc. Req #3
            frequency_of_each_roulette_element__list_int[random_position_in_array__int] = __ZERO_CONST__INT__
            random_position_in_array__int =\
                (random_position_in_array__int + __ONE_CONST__INT__) % __size_of_american_roulette_int__

For his work, Edgar gets to take home the Best Use of Variable Names prize.

Another common exploit was to exploit the lack of randomness in pseudo-random number generation. Jonathan took an approach that fed /dev/random through SHA–256 to generate his pseudo-random numbers. With that information, he can start making predictions after 64 spins. The real “clever” part isn’t the code itself, but the comments:

    /* this is an excellent source of randomness, bruce says so */
    FILE* fp = fopen("/dev/random", "rb");
    …
    … 
    /* that /dev/random is too slow to use every spin */
    /* cryptographic hash is effectively a random number, bruce says so */
    sha256.add(&state, sizeof(state));
    sha256.getHash(hash);

Edgar gets some stickers as part of the prestigious Bruce Says So award.

The Winner

We had a lot of great submissions- and a lot of them. There were a lot of clever approaches, a lot of Konami codes, and a few that did some sleight of hand with unit tests to cover up their cheats. For sheer energy and thoroughness, I have to give Ben, who sent us a submission that isn’t just clever code, but an extremely thorough write-up in a README file. In that write up, he first explains all the work he did to make sure his RNG was secure- and then pulls the rug out to explain exactly why it isn’t. Seriously, his README is more of a work of art than any of his code.

That isn’t to say that his code doesn’t have a fun twist to it. With a perfect combination of extremely thorough comments and a clever use of bitwise operations, Ben hides his sleight of hand right in the open:

    /* Make sure the fourth-least significant bit
     * is different from the last result. All other bits are random,
     * but we know it'll definitely not be identical *again*.
     * Why the fourth? I expect "professional" roulette players to
     * closely observe some properties, including even/odd (lsb),
     * and let's assume they even observe "value mod 4" (second-lsb)
     * and "value mod 8" (third-lsb). */
    const uint mask = 1 << 3; /* Fourth bit, so shift '1' by three. */
    const uint a = avoided & ~mask; /* Take the opposite bit. */
    const uint b = generated & mask; /* Take from randomness. */
    generated = a | b; /* Merge. */

Read through his code, and try and figure out his trick before reading his README.

The Lucky Duece: Getting in the Slot

You had a close call in Bartsow last week. The FBI tried to catch you coming out of a truck stop diner along Route 66, and it’s only because Gilda, the waitress, tipped you off that you were able to slip out the back. That’s what you get for leaving behind good tips, but you’ve padded your bankroll nicely with the proceeds of the Roulette job. You had padded it, anyway- apparently while Gilda was showing you out the back door with one hand, she stole your wallet and got a really big tip with the other.

Slot machine

Out of cash, you’ve been hitchhiking along back roads. Last night, you got picked up by a bunch of hippies on their way back from San Francisco, and they were good enough to drop you off in a little dirt patch called Dogtown. It’s then that your cellphone dings- you’ve got a new set of requirements.

The Requirements

“GRT JOB,” the message starts, “you did good work. We want you to work on our slots machine project now, it is the same more work that you already did.”

Slot machine? Great, they want you to generate some more broken numbers? Or is there something else? As you read the requirements, you see some key points. First off, yes- they do want you to generate some random numbers- three of them to be exact. They’re less concerned with imitating wheels with all of the complexity that entails, and instead, just want a function or program that can output three random numbers- but with constraints.

“Firstly, we want suspense. After each number is output, there must be a pause or a wait before the next number is coming. This adds tension and makes our customers more excited. Secondly, the probabailities[sic] that the first and second numbers are the same must be very high! But the probability that all three numbers match must be very low.”

You scratch your chin while thinking about the requirements. That’s all pretty easy, but it gets you thinking. With all those pauses in there, there’s gotta be some way you can sneak a cheat in between them. You're going to figure out a way to rip off this slot machine, and rebuild your bankroll.

Entering & Judging

To enter, send an email to byoc15@worsethanfailure.com with a link or attachment of your code. In the body of the email, explain how your cheat works and what we need to do to run your code. You can use any language you like, but we have to be able to run it with minimal setup.

You don’t need to build a GUI, but if you do, and you do it using tools from Infragistics, we'll send you a free license (one per entrant, supplies limited). Consider this your Infragistics bonus.

Assume we have access to stock Windows, Linux and OSX instances, if we need to run your software locally. You could target MUMPS running on a mainframe, but we can't run it, and you probably won't win. You must get your submission in before 11:59PM Eastern Time, Sunday the 16th of August to be eligible for judging. We'll announce the winners next Wednesday, along with the next leg of the contest!

The overall winner will be chosen by how interesting and fun we think their solution and cheat is.

Thanks to Infragistics for making this possible.

Infragistics

A worldwide leader in user experience, Infragistics helps developers build amazing applications. More than a million developers trust Infragistics for enterprise-ready user interface toolsets that deliver high-performance applications for Web, Windows and mobile applications. Their Indigo Studio is a design tool for rapid, interactive prototyping.