Bring Your Own Code: The Lucky Deuce: In the Cards
Two weeks back, 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, you were again given some vague requirements, this time for building a broken slot machine. Once again, we had some seriously great submissions. Like last week, I've rehosted the winning code here.
Honorable MentionsWe didn't get quite as many submissions this time around, but while folks didn't quite top themselves for quantity, we still got some serious quality.
First, we have to give credit to Alexander, who delivered his submission in APL. That's a clever solution for making certain your code is obfuscated enough that nobody will detect your cheat.
slota{3aa({aafa?aa}(a^3aa),(,a aaa^3a)~first),({aafa?aa}(a^3a),100afirst),firsta(?a)/a1+a/'1'=a100a3a3aaTS}
This checks the time, and if it is only 1s with leading zeros (e.g, 01:11:11), guarantees a win. For that effort, we just have to award Alexander the I Broke My Keyboard prize.
Much like Josip's "realistically bad" approach (see below), Alex K (what's with all the Alexes?) uses a single line of incompetence to cover up his skullduggery. Most of his methods start with a signature that looks like this:
def playSlots(): global a global b global c " actual code
That global keyword is how Python recognizes that Alex is using global variables, and not trying to declare local copies.
His main application loop, is the extra piece of icing on the cake.
while True: s = raw_input() if (s == 'test'): # Warning! self-test is blocking, UI may become unresponsive selfTest() elif (s == 'quit'): sys.exit(0) else: # Actual slots round is on a second thread, to not block your UI t = threading.Thread(target=playSlots) t.start()
That's right- it spawns a thread that is never joined, to "not block your UI", which means race conditions ahoy! This still requires a fair bit of luck for you to win, but it's such a simple, easily avoided bug- that's also easy to make. Bonus points for having a "test" mode, which "proves" that the application behaves as intended.
Great work, and I assume you decided to use threads because Bruce said so, which means you win the Bruce Said So award this week.
There were so many other great submissions- there was one that used the position of the window to emulate "tilting" a mechanical slot machine, another that essentially portscanned a target server to decide how to generate random numbers, and of course the requisite avalanche of "secret code" cheats. And they were all great, but for this week"
The WinnerJosip's solution was to generate the first and second numbers more or less the way you'd expect- by pulling out random numbers. But for safety, or security, or for some unfathomable reason, after drawing the first number, a file containing a pile of random data is written out. When it comes time to generate the third number, that file is read back in and used to pick it. And that's where Josip has a clever cheat:
try { using (TextReader reader = new StreamReader(path)) { // First, read all digits into one string string s = reader.ReadToEnd(); // The, take out a number from that giant string int numberOfDigits = (int)(Math.Log10(maxNumber)); int offset = r.Next(s.Length - numberOfDigits); string num = s.Substring(offset, numberOfDigits); // Finally, convert string to integer to show on the slot machine number = int.Parse(num); } } catch (Exception) { // Who needs exception handling in a slot machine. It will work juuuust fine... }
What I love about this one is how realistically bad it is. Dropping exceptions, using the same variable to represent every number as it's drawn- this feels exactly like what you'd get if you hired a gutter-dwelling programmer to do your greymarket gambling system. Congratulations Josip, I'm not even sure if that code is bad on purpose.
Congrats to all our winners this week. For next week"
The Lucky Deuce: In the CardsThe last thing you remember was ordering a drink at the Palais Royale. The ironically named joint was the kind of dive that just used plywood on sawhorses as its bar. Somebody must have slipped you a mickey, because you come to tied to a chair, in a dusty garage, lit only by a bare incandescent bulb and the dim glowing ember of a cigarette clutched in red lips.
Your captor leans into the light. Her face is lean and hungry, her eyes are desparate. It reminds you of what you see in the mirror every morning. "I've finally caught up with you," she says.
"W-who are you?" you slur out.
She shakes her head. "No names. I know you're the programmer that's been slipping bugs into the Lucky Deuce, and that's all you need to know about me. But I've got a new set of requirements, and this time- you're gonna give me your secret."
She places a laptop on the table in front of you, and you can see an email inbox with a lone message- the latest set of requirements. That's when you realize, this woman must be one of the other contract programmers who works for the Lucky Deuce. But if she saw the bugs, and she found you- the Lucky Deuce might know what's up too.
Your stomach bottoms out, even as you try and bluster. "Why should I?"
The woman comes further into the light, and you can see her hand holds a Colt 1911 pistol. "Now, now, let's not make it hard. You don't want this to be hard."
Glumly, you look at the requirements. Once again, leave it to the Lucky Deuce to invent a new variation on gambling that is borderline nonsense. "Playing poker with one deck of cards," they write, "is full of card countings. We want there to be made a poker game that uses 5 decks of cards."
Specifically, they want a module that generates up to 5, 5-card hands, by drawing from 5 decks of cards. They're calling it "555", the clever branding devils that they are. Of course, your captor wants you to sneak a backdoor in, but honestly, you're not really all that inclined to help her. This time, you really want to make sure anybody who uses the backdoor gets caught, but whatever you put in for your backdoor has to at least fool her- another programmer as smart as you are. If you screw it up, you might find yourself staring down the wrong end of that pistol.
Entering & JudgingTo 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 23rd 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.
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.