Rules

Testing

Judging

The winner will be decided by selecting the person with the most win matches after 1000 full round-robin. Ties will be broken by matches tied.
1000 matches are being played rather than one because I expect a lot of randomness, and that way the randomness would be less relevant.

You can submit up to 5 bots.

The contest ends on JulyJune 4th (that will be the last day I'll accept any answer), and on JulyJune 5th I'll post the final stadings (might try to post an advancemnt before).

Since this is my first KOTH, I'm 100% opened to changing anything for improvement, such as the number of matches played against each bot.

Edited to 1000 matches, since I see there really is quite randomness involved.

\$\begingroup\$with some randomised bots, you actually want to make multiple games of multiple rounds\$\endgroup\$
– Destructible LemonMay 24 '17 at 8:31

\$\begingroup\$@DestructibleLemon I thought about making each bot play three times against each other bot rather than once. Seeing you think similarly, I'll do so.\$\endgroup\$
– MasclinsMay 24 '17 at 8:35

1

\$\begingroup\$(really you need a fair large number, since some probabilites do really extend over multiple matches. see my bot, where it could get trounced, but likely wouldn't with a fair amount of matches)\$\endgroup\$
– Destructible LemonMay 24 '17 at 8:39

1

\$\begingroup\$I'm glad my question helped you be able to run this, @AlbertMasclans!\$\endgroup\$
– GryphonMay 24 '17 at 12:44

2

\$\begingroup\$@AlbertMasclans Can you post the full testscript (including runcode and bots)?\$\endgroup\$
– CalculatorFelineMay 24 '17 at 18:53

\$\begingroup\$I really like this approach, and can understand why you'd want to be able to keep the state between rounds. Even though I see it a huge problem to change it given the number of submissions. I'll take that into account for further challenges (which I expect to do when this finishes).\$\endgroup\$
– MasclinsMay 25 '17 at 8:51

Weigher

I lost track of reasoning while experimenting with the code, but the basic idea is to estimate opponent's move probability by last 3 moves using some weights and multiply them by another weight which depends on loads. I thought that I can somehow use my_loaded too, but I couldn't decide how, so left it out.

Satan

Probably will be disqualified, because it's kind of cheating and it makes some assumptions about the testing function (it has to have opponent's function in a variable on its stack frame), but it doesn't technically break any current rules — it doesn't redefine or rewrite anything. It simply uses black magic to execute the opponent function to see what turn did/will they do. It cannot deal with randomness, but deterministic bots have no chance to defeat Satan.

\$\begingroup\$Without any doubt the best one in terms of Simplicity-Results\$\endgroup\$
– MasclinsMay 25 '17 at 12:38

\$\begingroup\$By the way, to use my_loaded you could add a weight that values the move that would lose against your last move(s). That is like assuming your opponent will do something similar to what you did, and therefore punishing him for assuming you will keep playing the same. Something like: for i, m in enumerate(reversed(my_history[-3:])): sc[(idx[m]+1)%3] += (K / (1 + i))\$\endgroup\$
– MasclinsMay 25 '17 at 14:01

\$\begingroup\$I really like the Satan one. But as you said, I believe it shouldn't qualify: Even if it doesn't break any explicit rule, it's clearly against the spirit of the game. Still, congratulations on your idea!\$\endgroup\$
– MasclinsMay 25 '17 at 23:14

Fitter

This Bot improves Pattern and fuses it with Economist (Pattern and Economist will no longer participate)

The improvement of Pattern is that the Bot now looks for two two kinds of patterns: Opponent reacting to his last play and opponent reacting to my last play. Then evaluates both predictions to use the one that fits the best.

From that pattern the Bot has now the probability for R, P and S. Taking that into account and the expected value of each play (as Economist did), the Bot plays the one that gives the most value.

Pattern (no longer playing)

The Pattern tries to find patterns on his opponent. It looks what the opponent had played after the last play he did (giving more weight to the latter plays).
Through that, it guesses what the opponent will play, and plays the countermatch to that.

Economist (no longer playing)

The Economist does the following:
Guesses the probability of each play by the opponent by watching what he had played the last 9 turns. From that, computes the expected benefit of each play and goes with the one that has the best expected value.

Yggdrasil

This is named "Yggdrasil" because it looks ahead in the game tree. This bot does not perform any prediction of the opponent, it simply attempts to maintain a statistical advantage if it is given one (by balancing current and future profits). It calculates an approximately ideal mixed strategy, and returns a move selected randomly with those weights. If this bot were perfect (which it's not, because the state valuation function is pretty bad and it doesn't look very far ahead), then it would be impossible to beat this bot more than 50% of the time. I don't know how well this bot will do in practice.

\$\begingroup\$@PhiNotPi I'm aware that I posted no time limitation, but Yggdrasil is taking more than a minute against each opponent. Would it be possible to optimize it a little bit?\$\endgroup\$
– MasclinsMay 25 '17 at 6:55

\$\begingroup\$@AlbertMasclans by minute per opponent do you mean 1 minute total for all games against an opponent? Also I can try to speed it up but I don't really know how to do it, it only looks 1 move ahead as is.\$\endgroup\$
– PhiNotPiMay 25 '17 at 10:50

Rockstar

Assassin

Explanation

not entirely true, these are actually based on idea, of amassing a huge bonus, and the enemy making a misstep and getting walloped with it.

now, these bots play very similarly to greedy, however, they are simpler, and do not randomly pick until they get a load on one weapon, they stick with their weapon of choice.

Another thing to note: these will each beat greedy around half the time, drawing a third of the time, and losing one sixth of the time. when they do win, they will tend to win by a lot. why is this?

Greedy, until he loses a round, will randomly pick a weapon. this means that when he does not win a round, he will pick a weapon randomly again, which could be a winning one again. if greedy draws or loses, he sticks with that weapon. if greedy wins at least one round, then picks the same weapon as the bot, greedy wins. if greedy picks the losing weapon at some point, our bot wins, because the load on our weapon would have been higher than the score greedy has.

Assuming greedy doesn't always just pick the winning weapon through grand chance, this will mean that the chances are:

1/3 : {
1/2 win (1/6 total).
1/2 lose (1/6 total).
}

1/3 draw

1/3 win

so: 1/3 chance to draw, 1/6 chance of a loss, 1/2 chance to win.

this probably shows that you need to do multiple games of multiple rounds

Artsy Child

This bot acts like a child playing arts and crafts, will start with paper and use either paper or scissors randomly, but will not use scissors after rock or scissors because she needs to use the scissors on paper. Will throw a rock back at anyone who throws a rock at her.

Returns the choice of the winner of the previous round. If the previous round was a tie, recursively checks the round before that. If it was only ties, or it is the first round, returns a random choice.

Randomly chooses between the three options in such a way that the opponent statistically has no preference between moves with regards to how much it scores; in other words, both Greedy and Not Hungry should have the same average expected score against it.

Explanations

Computing the probability for each of the opponent's next possible move

Using that figure and the loads to compute the expected value for each of R,P and S

Selecting the move that has the highest expected value

Randomly selecting a value if predicting failed

Probabilities are updated every ten moves. The number of past moves used to compute the probabilities has been set to 10 for each bot (so 20 features overall). This is probably overfitting the data, but I did not try to check further.

It relies on the scikit library to compute the opponent's move probabilities (i am saying it in case I misread the rules and it was in fact not allowed).

It easily wins against bots that always make the same choice. Surprisingly, it is quite effective against the random bot with a 93% win rate (I believe this is due to the fact that it limits the number of points his opponent can get while maximizing its own number of possible points for each round).

I made a quick try with 100 turn and only a limited number of bots, and this is what I got from result_standing:

\$\begingroup\$@DestructibleLemon This divides by 0: elif min(opp_history.count(i) for i in "RPS")/max(opp_history.count(i) for i in "RPS") >0.8 and len(my_history)>30:\$\endgroup\$
– MasclinsMay 25 '17 at 6:35

\$\begingroup\$@RobertFraser what exactly is outstanding about that code snippet?\$\endgroup\$
– Destructible LemonMay 25 '17 at 10:06

\$\begingroup\$@DestructibleLemon I'm not entirely sure what you wanted to do here: "RPS"[my_loaded.index(max(my_loaded))+len(my_history)%2] but it looks out of range (and so will the further lines).\$\endgroup\$
– MasclinsMay 25 '17 at 10:10

Weighted Random

Like RandomBot, but it picks only 2 to throw each time it is invoked. Will sometimes beat Rockstar or Assassin, but will pump up the scores of the other one (e.g., if it beats Rockstar, it gives Assassin a point boost).

Your Answer

If this is an answer to a challenge…

…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.

…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.

…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.

More generally…

…Please make sure to answer the question and provide sufficient detail.

…Avoid asking for help, clarification or responding to other answers (use comments instead).

Code Golf Stack Exchange is a site for recreational programming competitions, not general programming questions. Challenges must have an objective scoring criterion, and it is highly recommended to first post proposed challenges in the Sandbox.