Ladder tournament

Someone in my office decided to setup a table-tennis tournament recently. This got us all talking about various tournament types. I’ve been interested in ladder tournaments since I learned about them, but have never had the opportunity to actually take part in one. The basic idea is that you get a list of participants and you initially rank them in whatever way you like (random is fine). Once you have your ranked list, then the games begin. Players lower on the list can challenge players above them as frequently as they want (as long as they don’t challenge the same person two times in a row). If a challenger beats a defender, their ranks swap. That’s the gist.

Ultimately our office decided to go with a standard bracket that’s seeded by preliminary pseudo-random challenge groups. And that’s fine, but I was still curious about ladder tournaments. So this got me thinking it’d be a fun thing to model in python. So I did that.

I assumed that given enough time/games, players would sort out and the ‘best’ player would filter to the top. What I discovered was that this is not the case at all.

Full disclosure: I am not a statistician and I’m mostly talking out of my ass here, but I think the basic stuff I’m working with is sound (I welcome any and all corrections and comments at @samteebee on Twitter).

The basic rules by which the script operates are these:

The game is played over a specified number of rounds provided to the script.
A random challenger is chosen each round.
Challengers can only challenge players ranked higher than them (first place player can’t challenge anyone).
A challenger may not challenge the same defender two times in a row.
If a challenger defeats a defender, they swap ranks (ties go to the defender).
Both players roll a 10 sided die (0-9) then multiply that value by their current strength value to determine their fight value.
Challenger gains 10 strength for winning.
Both challenger and defender always gain 1 strength for match participation.
Player ranking is initialized in reverse-player order (Player1 == rank 1, Player2 == rank 2, etc…)
All players start with a Strength value of 1

Here’s an example of the output from a 100,000 match run:

player6 -- Final strength:86036 -- Final rank:1 -- # of times initiated challenges:12641 -- Total rounds played:25045 -- # of rounds ended in 1st place:2839
player4 -- Final strength:86920 -- Final rank:2 -- # of times initiated challenges:11911 -- Total rounds played:24979 -- # of rounds ended in 1st place:3387
player3 -- Final strength:86811 -- Final rank:3 -- # of times initiated challenges:12350 -- Total rounds played:24840 -- # of rounds ended in 1st place:2904
player7 -- Final strength:86490 -- Final rank:4 -- # of times initiated challenges:12246 -- Total rounds played:25039 -- # of rounds ended in 1st place:3031
player2 -- Final strength:84600 -- Final rank:5 -- # of times initiated challenges:13037 -- Total rounds played:24969 -- # of rounds ended in 1st place:2733
player8 -- Final strength:84929 -- Final rank:6 -- # of times initiated challenges:13163 -- Total rounds played:25038 -- # of rounds ended in 1st place:2614
player5 -- Final strength:88058 -- Final rank:7 -- # of times initiated challenges:11727 -- Total rounds played:24977 -- # of rounds ended in 1st place:3483
player1 -- Final strength:85334 -- Final rank:8 -- # of times initiated challenges:12925 -- Total rounds played:25113 -- # of rounds ended in 1st place:2770

What strikes me here is how uniform the numbers are. There are no significant spikes. The “strongest” player does not end in first place. The first place ‘winner’ doesn’t even have the highest tally of rounds ending in 1st place. The most potentially useful info here: the strongest player also has the largest 1st place tally (though they ended in next-to-last place!)

My wife, Steff, gave me the idea of having challengers default to challenging first position by default (and only challenging someone else if they’d just previously lost to that defender). The theory being that strong players might filter up to (and stay at) the top position more rapidly/consistently. Surprisingly, these are the results of that experiment:

player3 -- Final strength:78925 -- Final rank:1 -- # of times initiated challenges:12965 -- Total rounds played:23514 -- # of rounds ended in 1st place:7456
player4 -- Final strength:88070 -- Final rank:2 -- # of times initiated challenges:12584 -- Total rounds played:25239 -- # of rounds ended in 1st place:9781
player6 -- Final strength:83148 -- Final rank:3 -- # of times initiated challenges:12417 -- Total rounds played:24117 -- # of rounds ended in 1st place:8631
player8 -- Final strength:85669 -- Final rank:4 -- # of times initiated challenges:12761 -- Total rounds played:24748 -- # of rounds ended in 1st place:8919
player2 -- Final strength:94001 -- Final rank:5 -- # of times initiated challenges:12023 -- Total rounds played:26820 -- # of rounds ended in 1st place:11870
player7 -- Final strength:82322 -- Final rank:6 -- # of times initiated challenges:12875 -- Total rounds played:24171 -- # of rounds ended in 1st place:8254
player1 -- Final strength:90241 -- Final rank:7 -- # of times initiated challenges:12069 -- Total rounds played:25980 -- # of rounds ended in 1st place:11054
player5 -- Final strength:87912 -- Final rank:8 -- # of times initiated challenges:12306 -- Total rounds played:25411 -- # of rounds ended in 1st place:10137

the weakest player who’d played the fewest games and had the fewest turns in 1st place ended the tournament in first. And the strongest, arguably best player, who kept 1st place for the greatest number of rounds ended up in 5th place.

This has convinced me that a ladder tournament is probably not a very good way of sorting a group of competitors into anything meaningful (Wikipedia agrees with me here).

I’ve played around a bit more with the script, too, trying to force it to resolve to something that resembles a best-to-worst sorting device, but I’ve not made much headway.

If you’re interested in checking out the script, you can grab it here:

2014 Year in Review

2014 was a good year! It feels odd saying it. It felt like an uphill battle a lot of the time. I think that battle was mostly in my head though, as some really great stuff happened. So I wanted to take a moment to acknowledge all the good stuff.

The good stuff in brief: I started a new job. I started (and finished!) a bunch of projects in python, woodworking and writing. I was generally quite healthy. I started biking to work. Over all I’m feeling like I’m finishing the year on an upswing.

The details:

I built a bench
A child’s seat
A stool

I also built a bat house, a gate and some shelves, none of which I have decent pictures of though.

I wrote somewhere around 12 short stories. Most of them were as part of a class I took, but I also wrote some after the class. I’m really happy about that.
Here’s one of the stories: Olivia’s Good Morning

I spent a lot of time this year trying to improve my coding skills – most of that time was spent on Python. This lead to some cool projects:

I participated in NaNoGenMo this year. NaNoGenMo is like NaNoWriMo (National Novel Writing Month) only the goal is instead of writing a novel during the month of November, one attempts to write a program to generate a novel. My entry was a python script that generated a book titled “A Full and Complete Reckoning of Uncommon Mythical and Monstrous Creatures.
You can see the code here:
You can see the full-book output here: creatures.txt.
The full list of NaNoGenMo entries is here, if you’re curious:

I made some Twitter Bots: – A new brainstorming/creativity idea every three hours. – A brief plot/story is tweeted every three hours. – A new imaginary animal is created every three hours. – A horrible bit of tech/venture startup-speek “advice” is generated every three hours.

I made a python script that calculates the distances between frets on a stringed instrument (hopefully I’ll actually build a stringed instrument sometime so I can use this calculator)

I also made a little script that pokes me every day to do something productive/creative – it auto tweets to my twitter account every morning at 7am.

Man, this was a good year for me and reading. I read 40 books this year (some were quite short, indeed). That’s more than twice as many as last year. Goodreads claims I read 10,858 pages this year (4600 last year). Here are this year’s books, in the order in which I read them:
The Summer is Ended and We Are Not Yet Saved – by Joey Comeau
Lockpick Pornography – by Joey Comeau
Life After Life – by Kate Atkinson
Creative Thinkering: Putting Your Imagination to Work – by Michael Michalko
Sand Omnibus (Sand, #1-5) – by Hugh Howey
The Fault in Our Stars – by John Green
Claire DeWitt and the City of the Dead – by Sara Gran
The Encyclopedia of Early Earth – by Isabel Greenberg
The Night Circus – by Erin Morgenstern
Show Your Work! – by Austin Kleon
Ashfall (Ashfall, #1) – by Mike Mullin
Divergent – by Veronica Roth
The Cat Who Walked a Thousand Miles – by Kij Johnson
A Man Came Out of a Door in the Mountain – by Adrianne Harun
Unclean Jobs for Women and Girls – by Alissa Nutting
The King of Limbo: Stories – by Adrianne Harun
Forty Stories – by Donald Barthelme
Ashen Winter (Ashfall, #2) – by Mike Mullin
Moonwalking with Einstein – by Joshua Foer
The Devil in the White City – by Erik Larson
The Martian – by Andy Weir
ZZT (Boss Fight Books, #3) – by Anna Anthropy
By the Silver Water of Lake Champlain – by Joe Hill
Candyfreak – by Steve Almond
Boy Proof – By Cecil Castellucci
Uglies – by Scott Westerfeld
Blue is the Warmest Color – by Julie Maroh
Rogues – Various authors
The Magicians (re-read) – by Lev Grossman
The Magician King (re-read) – by Lev Grossman
The Magician’s Land – by Lev Grossman
The Slow Regard of Silent Things – by Patrick Rothfuss
The End of Everything – by Megan Abbott
Sunrise (Ashfall, #3) – by Mike Mullin
The Lies of Locke Lamora – by Scott Lynch
Right Body, Wrong Junk – by Avery Edison
The Enchanted – by Rene Denfeld
The Shell Collector – by Hugh Howey
Clipping Through – by Leigh Alexander
We Were Ugly So We Made Beautiful Things – by David Barringer
This list, with ratings and short reviews I wrote for each book is here, if you’re interested:

I got better at running this year, too. It wasn’t exactly a conscious effort to improve, but I think it was simply a result of my efforts to run more/consistently throughout the year. I did have one goal: to run a sub-20-minute 5k. I got very close (20:21, I believe), and I’m blown away by that.

This seems like it would be a good time to make some resolutions or plans for next year, but I’m not going to do that. I’ve gotten into the habit of keeping a rolling list of projects I want to do and/or skills I want to gain or improve on. I’m going to keep that up. Maybe I’ll do another review like this next December. We’ll see how next year goes. You can keep up with me on twitter if you’re at all curious.