# Chopsticks mutated with points KoTH

Basic rules (different from mine)

### Story

It is the year 4579, humans now have 2 hands with 1001 fingers each. Chopsticks has become based off of points. And @Dennis has more rep then @Martin... Hand drawn red circles are now downvoted... Jon Skeet has hit 2 trillion rep on every SE site... Yeah scary I know

Chopsticks is a hand game that has been solved. So to get around this I have created it mutated. I increased the amount of fingers.

## Rules of the game

The way this is played

Everyone starts with 2 hands. Each hand has 1001 fingers. Every hand starts with 1 (one) finger up on each hand. During your turn you can "hit" the other players hand. To hit you choose 1 of your hands to hit with and 1 of their hands to hit. The hand that was hit now has the amount of fingers that was their at first AND the amount of fingers that you had on the hand you hit with.

### EX

P1: 1,1 P2: 1,1. P1[0] hits P2[1]. Now fingers are P1:1,1 P2:1,2. Now P2[1] hits p1[0]. The fingers are now P1: 3,1 P2 1,2.

If one hand gets to 1001 fingers up or more then that hand is out. Then player who got a hand out (for their turn) can "split". Splitting is when you take the hand that is in and halve the amount of fingers (round up) and give those fingers to the other hand getting it back in.

### EX

P1: 1000,2 P2 7,7. P2[0] hits P1[0]. Score is P1: 0,2 P2 1,1. P1[1] splits for his turn and the score is P1: 1,1 and P2 7,7.

The game ends when one player has both hands out. Points are scored by the amount of fingers the winner has. More points = better. The loser gains no points.

There are other rules that are used but these are the ones used here.

Everybody plays everybody (round robin)

## Endgame

Total your points up from every round you win. Then average everybody's points up. Divide your total by the average points and get your final score. Most points win.

## Actual rules

Standard loopholes

Please do not try to solve the game. I actually have to be able to run it :P

Make sure the bot can run fast. With the length of rounds judging this will take a while

All libraries needed in your program must be in the default python library. Also list the ones you need imported. Imports will just be the basic import (for math I do: import math)

Answers must work in Python 3.x

# Handler

Your bot will be its own Python 3 file with a play function.

play will be passed two lists of two numbers each. This number indicates how many fingers are up on each hand. The first list is your own hand.

If you choose to hit the other player's hand, then return a list of two bits. The first bit is the index of the hand you are using to hit (0 for the first, 1 for the last), and the second bit is the index of the hand you are hitting on the opponent.

If you choose to split, return any other truthy value.

The controller can be found here. Save each bot in its own file and list each bot's filename (without .py) in botnames.

# Final note:

You and the other bot will take turns going first. If the game does not terminate in 100,000 (one hundred thousand) rounds, the game will be terminated and neither bot wins.

The controller is not protected against moves taking forever, but unnecessary overhead will be strongly frowned upon.

• Sandbox
– user63187
Commented Jul 19, 2017 at 15:50
• Could "Standard KOTH rules" be a link? And maybe "Standard loopholes" too. Commented Jul 19, 2017 at 15:52
• My handler is very simple, your bot must do it's logic then adjust the the finger scores as needed, remember! What, so we're the ones doing the computations for the KoTH? Commented Jul 19, 2017 at 15:53
• @HyperNeutrino opps fixing.
– user63187
Commented Jul 19, 2017 at 15:54
• Dennis has more rep than Martin now. Oh my god, where did these extra 996 fingers come from?! Commented Jul 19, 2017 at 23:16

# CodingAndAlgorithms

This answer actually uses coding and algorithms, unlike the others so far!reference: imgur(also beats all of the answers posted before this)

def play(A, B):
if sum(A) == 1:
return [A.index(1), B.index(max(B))]
elif max(A) + max(B) > 1000:
return [A.index(max(A)), B.index(max(B))]
elif 0 in A:
return 1
elif 0 in B:
return [A.index(min(A)), 1-B.index(0)]
else:
return [A.index(min(A)), B.index(min(B))]

• I got that reference XD
– user63187
Commented Jul 28, 2017 at 23:42
• This just won. It never lost.
– user63187
Commented Jul 29, 2017 at 23:46
• Congratulations! I guess I'm going to have to settle for second place. Your coding and algorithms were stronger than mine Commented Aug 1, 2017 at 0:43

# CautionBot

def play(s,o):
if max(s)+max(o)>1000 and (all(s) or max(s)+min(o)<1001):
return [s.index(max(s)),o.index(max(o))]
else:
return [s.index(min(s)),o.index(min(filter(bool,o)))]if all(s) else 'split'


CautionBot doesn't want to cause too much trouble, so it hits the smaller of the opponent's hands with its smaller hand if it has both hands, and otherwise splits. However, CautionBot is no fool, so if it can take out an opponents' hand without immediately losing next turn, it will do so instead of its normal move.

• Unofficially this is winning
– user63187
Commented Jul 23, 2017 at 21:47
• Cool! We'll see how things go from here because I won't be surprised when someone develops a better strategy. I just applied what I understood to be vanilla Chopstick strategy (be a coward and split often to avoid being killed) in a way that best accommodated the new rules (be a coward and hit low to avoid getting killed, since splitting/merging while you have both of your hands is illegal) lol Commented Jul 23, 2017 at 22:58

# Equalizer

def play(s, o):
if not all(s):
return 1
else:
return [s.index(max(s)), o.index(min(filter(bool, o)))]


If Equalizer is missing a hand, it will split. Otherwise, it hits its opponents smallest hand with its own largest hand.

• According to these mutated rules, AFAIK you can only split if one hand is out. Commented Jul 20, 2017 at 4:25
• Oh yeah, I'll fix that. Commented Jul 20, 2017 at 4:26
• "If Equalizer has no hands..." well I mean if it has no hands then it lost already? But that's just nitpicking, take my +1 to compensate Commented Jul 20, 2017 at 4:33

# Aggressor

def play(s, o):
return [s.index(max(s)),o.index(max(o))]if all(s)else 1


Another starter bot, Aggressor will hit the larger of the opponent's hands with the larger of its own hands if both of its hands are non-empty; otherwise, it splits.

# RandomBot

import random

def play(s, o):
return [random.randint(0,1)for i in'  ']if all(s)else 1


Just to get things started, here's a bot which makes a random hit if its hands are both non-empty; otherwise, splits.

Golfed because why not :3

• I was fixing that
– user63187
Commented Jul 19, 2017 at 15:55
• @Christopher Sorry, didn't see your comment. ---Once you fix it I'll delete this.--- I'll just delete this because it's stupid xD Commented Jul 19, 2017 at 15:56
• @Christopher Note: I've edited this into a valid submission. I'll add another solution too; tell me if the controller doesn't work properly :) Commented Jul 19, 2017 at 21:27
• Nice trying them out
– user63187
Commented Jul 19, 2017 at 21:32
• @Christopher Does the controller work properly? Commented Jul 19, 2017 at 21:33

## Error

Yes, that is the name of the bot.

def play(s, o):
if max(s)+max(o)>1000:
return [s.index(max(s)),o.index(max(o))]
if 0 in s:return ''
return [s.index(max(s)),o.index(min(o))]


I arrived at at this by testing with the other bots. However it is consistently second-last in my simulations. So Ill be making another bot eventually.

Edit: I can't seem to write any bot that beats CautionBot, and my extra testing seems to indicate that this is second best, not second worst.

# Marathoner

I tweaked Aggressor's code provided by "HyperNeutrino" to simply hit the smaller of the opponents two hands with the smaller of it's hands. It is a very silly strategy of course but I can't turn down being at the top of a chart! (Even though that chart would be losses)

I'm not sure if this code will run without errors because I was unable to test it due to being at work. However, it should run flawlessly.

def play(s, o):
return [s.index(min(s)),o.index(min(o))]if all(s)else 1

• Nice first answer! You chose a great question :P (no bias)
– user63187
Commented Jul 27, 2017 at 16:47
• Thanks :) I was pretty nervous because I wasn't sure if tweaking someone else's code like I did was allowed or not. I assume it is as long as you make it obvious. And I was gonna try to make one that would just play the biggest hand against the opponents biggest but HyperNeutrino beat me to that one exactly! haha Commented Jul 27, 2017 at 17:27
• Yeah. On this SE tweaking code is often used :P
– user63187
Commented Jul 27, 2017 at 18:59
• Cool answer! One thing that I'd worry about (can't test it right now) is that I don't know how the controller will respond if you try to hit an empty hand, or how that factors into the rules. Commented Jul 27, 2017 at 19:56
• This is very similar to Equalizer but Equalizer will check to make sure it doesn't hit the opponent's empty hand if present. @LyricLy Commented Jul 28, 2017 at 23:47