High-stakes Quasar: AKA, free money in Mass Effect

This is documented other places on the web, but I had fun with it, so I figured I'd write it up.

I've been replaying Mass Effect 1 recently. I noticed that in a club called Flux on the Citadel, there's a casino game called "Quasar". It's essentially a blackjack style game; you want to get as close to 20 points as possible without going over, and each round you can either "stay" and cash out for a known cash prize, or you can "hit" to add a random number of points to your score, but then you risk busting. The minor novelty to Quasar is that when you hit you can choose to add either 1-8 points or 4-7 points to your score.

To be more concrete, the game costs 200 credits to play, and has the following payouts:

0-14: 0
15:  50
16: 100
18: 250
17: 200
19: 300
20: 400
21+:  0

I played a few rounds and lost, when I realized that I'm a programmer! I can make the compute figure out the optimal strategy, and whether it's worth playing!

I whipped up a little dynamic programming algorithm, and it turns out casino owners in Mass Effect aren't very savvy businessmen. Assuming all the dice rolls are uniform, here's what the optimal strategy looks like:

0: hit 4-7 244.60
1: hit 4-7 244.61
2: hit 4-7 238.44
3: hit 1-8 235.73
4: hit 1-8 237.23
5: hit 1-8 242.82
6: hit 4-7 247.19
7: hit 4-7 251.15
8: hit 4-7 237.30
9: hit 1-8 218.13
10: hit 1-8 221.67
11: hit 1-8 230.37
12: hit 1-8 249.22
13: hit 4-7 287.50
14: hit 4-7 237.50
15: hit 4-7 175.00
16: hit 1-8 143.75
17: stay 200.00
18: stay 250.00
19: stay 300.00
20: stay 400.00

The first column is your score, the middle is the action you should take, and the last is your expected return. As you can see, the odds are pretty freaking good. You generally start out at somewhere between zero and five points, where the expected profit is greater than 30 credits per round.

Following this strategy, I went back to the machines and quickly won 1000 credits. Finally that programming knowledge is paying off!

Anyways, here's the code for the curious:

def payout(n):
    if n <= 14 or n > 20:
        return 0
    return {
        15: 50,
        16: 100,
        17: 200,
        18: 250,
        19: 300,
        20: 400

def avg(x):
    return float(sum(x)) / len(x)

res = dict()

def expected(n):
    if n > 20:
        return ('stay', 0)

    if n in res:
        return res[n]

    stay = payout(n)

    hit1 = avg([expected(n + x)[1] for x in range(1, 9)])
    hit2 = avg([expected(n + x)[1] for x in range(4, 8)])

    m = max([stay, hit1, hit2])

    if m == stay:
        res[n] = ('stay', m)
    elif m == hit1:
        res[n] = ('hit 1-8', m)
    elif m == hit2:
        res[n] = ('hit 4-7', m)

    return res[n]


for k, (a, e) in res.iteritems():
    print '%d:\t%s\t\t%0.2f' % (k, a, e)

Sleep Metronome, now free in the Android Market!

A few weeks ago I posted about a little Python script I wrote to help me get to sleep. I'm pleased to say that I've been using it every night since and it's been working great for me.

After a couple weeks of setting up my laptop next to me before bed, I decided that it'd be way better as an Android app, so I wrote it up. Now you too can experience the clicking sensations: Sleep Metronome

Try it out! Leave comments! Make reviews! Share with friends!

I was very impressed with how pleasant the experience of writing an app was. I went from having not touched a single line of Android code to having a published app in the space of 24 hours. A++ would code again.

The code is available at http://android-sleep-metronome.googlecode.com. Patches are welcome!