Official Rock-Paper-Scissors Tournament

72
11

Rock, Paper, Scissors, Shoot!

See This Post for Live Tournament Info!

LAST RULES UPDATE: See This Post Post for Live Tournament Info!


Motivation

Rock-Paper-Scissors is a popular game all over the world. Let's have a competition where you get to build your own program that plays Rock-Paper-Scissors! If you don't know how the game works, you can read about it here.

The interesting thing about this game is that if you play completely randomly, on average you will do as well as your opponent, regardless of what your opponent does (i.e. you will win 33% of the time, lose 33% of the time, and tie 33% of the time). However, in practice the game is usually not completely random, because human players don't play randomly, and try to psychologically out-smart their opponents. That way it's actually a fun game! But don't worry: we'll use a mechanism to prevent you from making a random bot to spoil the fun! So let's get to the specifics.


The Program

Imagine you are playing rock, paper, scissors with someone, and you want to write a computer program to do your next move for you. You need to write a Python procedure (called player) that takes as input the sequence of your moves and the sequence of your opponents moves represented by a list consisting only of the strings 'rock', 'paper', and 'scissors', and produces as output, your next move (either 'rock', 'paper' or 'scissors'). Your program should only be one function (which can contain other functions), and should not store state (e.g. global variables). Here is an example program that just plays the last move your opponent played:

def player(my_moves, opp_moves):
    if opp_moves != []:
        return opp_moves[-1]
    else:
        return 'rock'

Competition Rules

The First Task

Your program will need to play against three programs I build that aren't very smart. It will play 1000 rounds against each of these bots, and we will let you test this (probably on an IDE quiz on our website before submitting your program). In other words, they will probably have patterns in what moves they do, and they won't try to take your program's moves into account. To get to the next level in the competition, your program will need to beat at least two of these programs with a win rate of at least 50% (if it played randomly, it would be around 33% of the time on average). Your code should take no more than 2 seconds to complete 1000 rounds. This is not a strict limit, but try to stay within that range. You can test your program against our bots here! (Note: This may have some bugs. If certain things aren't working, please tell us!)

The Second Task

If your program passes the first task, it will then enter a tournament with all of the other eligible programs. Each match will have approximately 1000 rounds that you won't see followed by a best 7 out of 13 match (i.e. whoever gets 7 wins first, wins the match). The first set of ~1000 rounds will give your algorithm a chance to learn your opponent's behavior. I haven't decided the logistics of the tournament, because it will depend on the number of submissions.

Your code should be submitted here by Thursday July 26th at 17:00 UTC. You are allowed to submit two programs. (Thank our friend @areke from CS 253 for the awesome submission form!)

There will be a live tournament on Saturday July 28th at 17:00 UTC. The tournament will be hosted on Cloud 9 IDE. I will give you a link to the workspace where you can join us on Saturday before the tournament begins. Check the forums before the tournament to get the link and instructions on what to do! You do not need to sign up for Cloud 9, you just open the link on your browser and enjoy!


Final Remarks

This is very experimental. Let us know what you what you think of this tournament, and if you like this idea, and want similar competitions in the future, let us know by voting this post up. Thanks!

If you want to test two different programs against each other, you can use the following code. Or you can write your own more elegant code.

def match(player1, player2):
    moves1 = []
    moves2 = []
    wins1 = 0
    wins2 = 0
    for i in range(1000):
        move1 = player1(moves1, moves2)
        move2 = player2(moves2, moves1)
        moves1.append(move1)
        moves2.append(move2)
        if winner(move1, move2) == 1:
            wins1 += 1
            # print "Player 1 wins! (%s vs. %s)" %(move1, move2)
        elif winner(move1, move2) == -1:
            wins2 += 1  
            # print "Player 2 wins! (%s vs. %s)" %(move1, move2) 
    print "Player 1 won %d games and Player 2 won %d games" %(wins1, wins2)
    return

def winner(move1, move2):
    dict = {'rock': 0, 'paper': 1, 'scissors': 2}
    a = dict[move1]
    b = dict[move2]
    if a == b:
        return 0
    elif a - b == 1 or a - b == -2:
        return 1
    else:
        return -1

asked 19 Jul '12, 20:42

Shayan%20Doroudi's gravatar image

Shayan Doroudi ♦♦
3.1k31032
accept rate: 22%

edited 28 Jul '12, 13:41

Anthony%20Teate's gravatar image

Anthony Teate ♦♦
6.7k523

4

Are multiple entries per person allowed?

(20 Jul '12, 08:09) Jin Koo Nier... ♦ Jin%20Koo%20Niersbach's gravatar image
2

I would also want you to consider setting a given number of iterations for the match and make it public. This is, if both players will play 1000 times as in the previous example, or 1e4 / 1e6 / 1e9 etc.

That would allow as to know (by input's length) how far we are in the match.

I would compare it to human vs human RPS tournaments where they play agains the other i.e. 10 times, or to any sports when they are given i.e. 90 minutes (scoccer) or a given structure of set and games (tennis).

(20 Jul '12, 12:03) Marcos Manue... Marcos%20Manuel%20Ortega%20Gonz%C3%A1lez's gravatar image
1

@Jin You are allowed two submissions. This is updated in the post.
@Marcos Manuel When you play against the bots in the first task it will be 1000 rounds. When you play against programs your peers have built, it will be best 5 out of 9 (i.e. first to 5 wins). This is to build excitement, but if people strongly disagree with this, I can change it. Sorry for not being clear on rules earlier! This is very experimental!

(20 Jul '12, 17:07) Shayan Doroudi ♦♦ Shayan%20Doroudi's gravatar image
2

I strongly disagree with the 5 out of 9 aspect. See my answer below.

(20 Jul '12, 17:20) Tuxianeer Tuxianeer's gravatar image
2

Is there a time limit? Since we're not allowed to store state, my agent has to re-do a lot of work each move, which takes a while...

(21 Jul '12, 05:50) DataWraith DataWraith's gravatar image
1

@Johannes the rules have been updated, so your agent is given his set of previous moves. There is also a time limit of 2 seconds for 1000 rounds.

(21 Jul '12, 13:49) Shayan Doroudi ♦♦ Shayan%20Doroudi's gravatar image

What should we name our program? 'player', or whatever we choose?

(25 Jul '12, 00:23) Tuxianeer Tuxianeer's gravatar image

There seems to be a bug with the submission form. Both the 'View your first entry' and 'View your second entry' buttons link to the second entry. As a result of this, I cannot edit my first entry. Am I the only one with this problem? Please fix this!

(25 Jul '12, 00:23) Tuxianeer Tuxianeer's gravatar image
1

I'm sorry about this problem, but I don't think it was because of me... My deployed version at arekelive.appspot.com doesn't seem to have this problem. @Shayan, @Anthony Try making sure that both your_entry, and your_entry2 are passed into the template and that the url for the first one is "/{{your_entry}}" and the second is "/{{your_entry2}}". It shouldn't be too hard of a fix.

(25 Jul '12, 05:30) Mark Mark's gravatar image
1

can we use functions inside of our function player()? and why aren't we allowed to store state? Not doing so requires redoing tons code and makes it take a while... Storing state makes it much, much quicker...

(25 Jul '12, 06:06) Mark Mark's gravatar image

Saturday, July 24th 21:28 UTC? Should be Tuesday!! or July 21th!!

(25 Jul '12, 16:45) Manuel Vidaurre Manuel%20Vidaurre's gravatar image

@areke @Manuel Vidaurre You cannot keep state. I'm sorry about this, but it's too late to change that now. I'll update the rules to make it more obvious. You can use functions inside of player. All of your code should be inside of player.

(25 Jul '12, 17:35) Shayan Doroudi ♦♦ Shayan%20Doroudi's gravatar image

@Manuel Vidaurre Thanks for pointing that out!

(25 Jul '12, 17:35) Shayan Doroudi ♦♦ Shayan%20Doroudi's gravatar image

Does it have to be within 2 seconds? Without storing state it takes much longer... Maybe even 15-20 seconds...

(25 Jul '12, 17:40) Mark Mark's gravatar image

@areke I would say that's too long. Try to get it down to less than 4 seconds or so. You might have to sacrifice your program's ability, but everyone has the same limitations. Sorry! You should keep your program though, in case we have a discussion about the best programs later on.

(25 Jul '12, 18:09) Shayan Doroudi ♦♦ Shayan%20Doroudi's gravatar image

Ok, I'll try my best.

(25 Jul '12, 18:21) Mark Mark's gravatar image

Are you able to say what the range of the number of games are? Like 750-1250 where the number of games won't go below 750, and won't go above 1250.

(25 Jul '12, 23:30) Mark Mark's gravatar image

@Shayan Doroudi: You said that all code should be inside of player. If my program has additional functions and imports outside of player(), and passes Task 1, will it be accepted? And if not, why?

(26 Jul '12, 06:34) Alexey Lebedev Alexey%20Lebedev's gravatar image

Really, what should we name our function, 'player', or whatever we want? I need to know before it is due!

(26 Jul '12, 11:06) Tuxianeer Tuxianeer's gravatar image

I named it player like in the quiz... I don't know if this is correct because there were no specifications.

(26 Jul '12, 12:55) Mark Mark's gravatar image
showing 10 of 20 show 10 more comments

41 Answers:

12345next »

Seems like I heard about udacity's rock scissor paper tournament too late. But anyway there is a rock scissor paper tournament ongoing on the net for python programmers at http://www.rpscontest.com

Everyone can try their luck there. Be warned though, the rsp bots over there are mean. Some use bayesian analysis, some neural nets, some markov chains, most use fancy meta strategies to decide which of their current strategies to choose...

link

answered 28 Aug '12, 22:05

Fabian%20Beyer's gravatar image

Fabian Beyer
42535

To make it even funnier, it should be the ˜Rock, Paper, Scissor, Lizard, Spock" game! :)

link

answered 24 Aug '12, 00:31

Daniel%20Ambrosio's gravatar image

Daniel Ambrosio
272

Hey, great idea! Does anybody know any other competitions basing on this kind of format? Unfortunately, I didn't have enough free time to participate here but the whole idea of programming a bot for playing some game against the others is really exciting. So, do you happen to know something similar elsewhere (as I don't suppose this kind of competition will be held here again anytime soon)?

link

answered 27 Jul '12, 07:15

Tigro-1's gravatar image

Tigro-1
10714

check out TopCoder.com

(28 Jul '12, 13:27) Rohit Dua Rohit%20Dua's gravatar image

Thank you! Would you mind giving me more precise direction, though? I'm having quite a hard time finding this in that vastness of TopCoder :D

(30 Jul '12, 09:49) Tigro-1 Tigro-1's gravatar image

Dan Egnor's Iocaine Powder is one of the strongest Roshambo bots ever written:
http://ofb.net/~egnor/iocaine.html

The C source code is open sourced:
http://ofb.net/~egnor/iocaine.c

I've always wanted to understand better how it works, so this contest has motivated be to invest a few hours into a Python port:
https://github.com/erdman/roshambo

However, there are one or more bugs in my port as I don't believe it is working properly (I don't really know C to begin with). It isn't regularly beating 'good ole rock'. I believe the port is extremely close, but I need one or more fresh set of eyes to find where I went wrong. I'd be grateful if someone could have a look and even submit a pull request to true it up. Thank you.

link

answered 25 Jul '12, 23:29

Travis%20Erdman's gravatar image

Travis Erdman
543

I wrote a bot based on his idea (didn't actually look at the code). It's a shame that I can't use it for the contest seeing that we can't store state. But oh well, at least I learned some cool stuff.

https://github.com/JFreegman/Udacity-Stuff/blob/master/buttdestroyer.py

(25 Jul '12, 23:47) JFreegman JFreegman's gravatar image

The bot sadly isn't allowed to store state so I don't think it will be allowed to be entered... If you managed to do it without it and within 2 seconds, you deserve to be the winner, even if you don't win.

(26 Jul '12, 02:10) Mark Mark's gravatar image

My code for this tournament is also based on the same idea as Iocaine Powder. It's choosing from a set of 16 strategies based on how they would have performed in the previous game. The time constraint together with not being allowed to store state was a real challenge. But with a few limitations I actually managed to let it run in just a few seconds for 1000 rounds. And it can even beat your bot @JFreegman, if not by much. ;-) I'm really curious whether it'll be any good in the tournament.

@erdman, I've looked at your port and I have to admit I can't quite follow it. :-) I've never done a port myself, so I was wondering if it wouldn't have been easier to make a "word-by-word translation" and add Python idioms later, once you have a running version? Like this it looks highly elaborate and nicely Pythonic but I find it hard to always see the corresponding elements of the two codes, let alone verifying that they're doing the same thing.

(27 Jul '12, 08:29) Emil-1 Emil-1's gravatar image

@Emil, thanks for taking a look. Here are the three biggest differences between my code and the original: (1) He sets off two general sections of the code with comment lines, the stats functions and data structures, and the predict functions and data structures. These fit very nicely into classes, so I just made them classes. (2) The C code relies on a lot of side-effects in his functions. I tried to remove side effects whenever I saw them, as I think they make code harder to understand and debug. You see this change most evident in in the do_history (I renamed match_history, sorry) and scan_predict functions. (3) Finally, I noticed the original do_history had repetitive copy-pasted code; I tried to follow DRY principle, and called the function three times instead.

(27 Jul '12, 18:52) Travis Erdman Travis%20Erdman's gravatar image

@Emil, btw, does your bot beat the original Iocaine Powder, or have you not been able to test that?

(27 Jul '12, 18:54) Travis Erdman Travis%20Erdman's gravatar image

@erdman: I haven't tested my bot against Iocaine Powder. I doubt it could beat it as it's really very limited. But if I've done everything right it should at least hold up in a direct match.

(28 Jul '12, 05:07) Emil-1 Emil-1's gravatar image
1

Actually, greenberg is stronger than iocaine (http://webdocs.cs.ualberta.ca/~darse/rsbpc.html , http://www.mathpuzzle.com/greenberg.c). It is based on Iocaine principle but extended a bit.

(28 Jul '12, 05:27) Cabuzel Thierry Cabuzel%20Thierry's gravatar image
1

@Cabuzel, thanks for the link. I didn't know the greenberg source code had been published. I just completed a port of greenberg to Python and added it to the same github repo listed in OP, if anyone wants to mess around with the strongest Roshambo bot ever published. The source is even more opaque than IP, but this port seems to be bug-free.

(28 Jul '12, 18:35) Travis Erdman Travis%20Erdman's gravatar image

6 minutes from 17:00, and still nothing ....

link

answered 28 Jul '12, 12:55

Cabuzel%20Thierry's gravatar image

Cabuzel Thierry
2343412

3 minutes now

(28 Jul '12, 12:58) anthony-4 anthony-4's gravatar image

aand it's time...

(28 Jul '12, 13:00) Silviu Danie... Silviu%20Daniel%20Ungureanu-1's gravatar image

Youuuhoouuuuu !!!!! Too much echoes here... Is there somebody ???? :-)

(28 Jul '12, 13:02) Cabuzel Thierry Cabuzel%20Thierry's gravatar image

It is time to go to bed in my country. How about yours?

(28 Jul '12, 13:07) Tran Duc Hieu-1 Tran%20Duc%20Hieu-1's gravatar image

It is 19:00 here

(28 Jul '12, 13:08) Cabuzel Thierry Cabuzel%20Thierry's gravatar image

6 O'Clock in the evening here in rainy Ireland

(28 Jul '12, 13:09) anthony-4 anthony-4's gravatar image

I will leave my robot to work on its part. I deserve a good night :D

(28 Jul '12, 13:14) Tran Duc Hieu-1 Tran%20Duc%20Hieu-1's gravatar image

Who has a bot in the comp?

(28 Jul '12, 13:14) anthony-4 anthony-4's gravatar image

Me. I have 2 bots. They could have at least put a message saying they will be late, I have cancelled a drink with a friend to be here :-/

(28 Jul '12, 13:34) Cabuzel Thierry Cabuzel%20Thierry's gravatar image

@Cabuzel, look here. :-)

(28 Jul '12, 13:39) Emil-1 Emil-1's gravatar image

echo! echo! is tournament live?

enter image description here

link

answered 28 Jul '12, 13:03

Rohit%20Dua's gravatar image

Rohit Dua
332

edited 28 Jul '12, 13:22

It seems like the tournament will be cancelled? There's no more update from officers.

Hello!!! Helloooo!!! Anybody here? J/k.

link

answered 28 Jul '12, 06:11

Tran%20Duc%20Hieu-1's gravatar image

Tran Duc Hieu-1
2.6k132744

2

The tournament is not cancelled. We are getting it set up currently. Check the forums before 17:00 UTC for more info!

(28 Jul '12, 09:24) Shayan Doroudi ♦♦ Shayan%20Doroudi's gravatar image

It should be 20 minutes from now. Will there be a delay?

(28 Jul '12, 12:42) Silviu Danie... Silviu%20Daniel%20Ungureanu-1's gravatar image

I just had an evil thought. The match() function as shown lets us modify the parameters. I'm not sure right now how I could take advantage of that, and honest cross-my-heart I wouldn't actually do it anyway, but I'd rather not have to worry about the possibility.

So even though it would slow down match() a bit, it seems better to pass us tuples.

link

answered 21 Jul '12, 21:20

Barbara%20Morris's gravatar image

Barbara Morris
1.3k1323

Oh the best way to use it would be to rewrite a part of your recent past so that it confuses the hell out of your opponent. Whatever you need of your past you can store it at the tail end :). This is really evil though. Hope this loophole is plugged.

(27 Jul '12, 22:27) srean list srean%20list's gravatar image

How many codes have been qualified to second round so far?

link

answered 27 Jul '12, 01:15

Tran%20Duc%20Hieu-1's gravatar image

Tran Duc Hieu-1
2.6k132744

I have been wondering that as well.

(27 Jul '12, 02:57) Mark Mark's gravatar image

import random
import pickle
try:
output = open('movement.pck','rb')
moves = pickle.load(output)
output.close()
except:
moves = []
dict_options = {}
reply = {'rock':'paper','paper':'scissors','scissors':'rock'}
dict_opt = {'rock': 0, 'paper': 1, 'scissors': 2}
answer = {'r':'rock','p':'paper','s':'scissors'}
count1,count2 = 0,0
p1,p2 = 0,0
def learn():
if len(moves) > 2:
two = moves[-1]
one = moves[-2]
if one == 'rock' and two == 'paper' or one == 'paper' and two == 'scissors' or one == 'scissors' and two == 'rock':
if two[0] == 'p':
d = answer['s']
elif two[0] == 'r':
d = answer['p']
d = answer['r']
return reply[d]
else:
return ''

def choice():
dict_options[moves.count('rock')] = 'rock'
dict_options[moves.count('paper')] = 'paper'
dict_options[moves.count('scissors')] = 'scissors'
return dict_options[max(dict_options)]

def choice2():
if not moves:
return choice()
my_choice = moves[-1]
return reply[my_choice]

def player():
"Hybrid version"
trick = random.randint(0,1)
smart = learn()
if smart:
return smart
elif trick:
return choice2()
return reply[choice()]

link

answered 27 Jul '12, 02:40

samuel%20muiruri-3's gravatar image

samuel muiru...
585

Your answer
Question text:

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×8,445
×2,260
×105
×22
×3

Asked: 19 Jul '12, 20:42

Seen: 13,344 times

Last updated: 28 Aug '12, 22:05