I'm obsessed. I admit it. I play pinball like a madman. hours and hours a day of it; I never stop. Sometimes, when I go away from the chatterbox and miss stuff, it's because I'm playing a game or two. More often, it's five or six. But the other day I reached a new low: I stopped playing. I made perl do it for me.

To explain a little better, I own a pinball machine (Medieval Madness, Williams 1997), so I really do play an insane amount of pinball. And I've gotten fairly high scores; but not every game is a new high; not every game is exciting. So i wanted to come up with a meta-game to play over the course of many pinball games. originally, it started as just "how long can i keep getting a better score than i did the previous game?" -- but monotonic increase does not encourage playing to the best of ones ability (because a really good game can break a streak early), and i didn't like that.

So I came up with a few other ideas, and i wanted to test them out -- but they'd take hundreds of games to see if they were fair and interesting. Which is, finally, where perl comes in.

first, i needed to model a single game of pinball. now, my top score is 178 million, and some games come in as low as (approximately) 178 thousand, but it's not a linear scale; the average is not 89 million, or even 17.8 million, but about 10 million. and, of course, i'v emade 178 million my top score in under 2000 games; given 10000 or 100k games, there's no hard upper limit. so just using rand() was right out of the question. on the other hand, i didn't want to map out every switch on the table and figure out probabilities for everything. so a model is in order. it turns out that the score increases faster thee longer you play, with a few large jumps which also get bigger as you go. i poked and tweaked, and here is what i ended up with:

sub score { # score is reported in millions. my $t = .1; # there is an actual minimum score. my $b = 0; # this counts the balls. my $round = 0; while (++$round) { # it's a 3 ball table, so ... last if $b > 3; # get some points, $t += int(rand $round*10)/10; # risk draining (++$b && redo) if (int rand int sqrt (9*$round)); # possibly get an extra ball $b-- unless int rand(5); # get the big points if we made it this far $t += 2 * $round; # the rest of this isn't interesting # let me know if something too unlikely happens... print ("Divine Intervention: $t points in $round rounds.\n") and last if not $round % 20; # ... and stop it if it gets out of hand print ("Apocolypse!") and last if $round > 400; } # point out statistically unlikely games; # otoh, they should range up to 200 ~ .01% of the time, # and some real games do fail to get off the ground. warn "Great game: $t in $round!\n" if ($round > 12 or $t > 150); warn "Horrid try: $t in $round!\n" if ($round < 1 or $t < .2); return $t; }

a simple "run this a million times and tell me the average" eventually revealed that it was doing pretty much what i wanted. so i wrote a few meta-games, and ended up with this as my basic game:

### # # this sub was originally separated out so i could try averages vs. # weighting the averages toward the most recent game. # i chose to weight them because it won't allow any one game to be too + hard. sub game { my $historic = shift; my $game = score; return (($historic+$game)/2); } ### the meta game itself. # # basically, each round you are trying to keep your (weighted) average + score above # the target (set at the start of the metagame, and incremented with e +ach game). # $spares is the number of games you can "do over"; # pretend that didn't happen and play that game again. sub meta { my ($historic, $target, $spares) = @_; my $games = 0; my $archive = 0; do { { $archive = $historic; ($historic) = game($historic); if ($historic < $target and $spares) { --$spares; $historic = $archive; redo; } } } while (++$games and $historic > $target and ++$target); return ($archive, --$target, $games); }

i usually play meta(score+score, 10, 0);

.

Clarification: this isn't a whole program, this is just a couple subs. if you want to see what it's doing, you need a wrapper of some sort. this one will play the meta-game as i currently play it on my real machine, and tell you some stuff:

sub show_meta { my ($first, $target, $spares) = @_; my ($lastgood, $made, $games) = meta (@_); print <<OUTPUT; First two games averaged to $first. Played for $games (using $spares spares) (Making target $made with $lastgood and then having a bad game) OUTPUT } show_meta (((score + score)/2), 10, 0);
of course, if you really want to see what's going on, you can add prints into the game and meta subroutines.

.

In reply to Virtually Pinball by Vynce

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.