Camel Up Cup 2K18


Wait, what?

Camel Up is a board game I was playing with some buddies. While arguing about what move should have been made someone remarked "someone should write a program to play this game". That sparked the idea that became Camel Up Cup 2K18 - the premier bot creation tournament of the year. The idea is simple, make a digital bot that is able to play the game Camel Up better than all competitors.

The box art for Camel Up (not Camel Cup!)

The game was chosen for several reasons: it has a relatively small pool of options to select from (roughly 20 choices per turn, easily narrowed down to usually about 3-4), games are short and there is an element of luck (makes it so even the "bad" bots can win). After conveniently bringing the game to a few game nights and gauging interest I made the game moderator, a few basic example bots and sent out invitations.


Humans playing Camel Up


The details

The bots would be written in a language that interfaces with Python 3.x. They would take in the gamestate (camel positions, current bets, player money values, etc) and return their move. Bot creators had access to the game's code so could point out bugs and test their bots locally.

The trophy, to be awarded to the winner


The event itself

On the day of the event plenty of people showed up... but not very many bots - there were two serious bots and two joke bots, along with a bot that was supposed to be a joke but was accidentally a jpeg image (don't ask me how). We agreed to a best of four with a rotating player order (ABCD, BCDA, CDAB, BCDA) - figuring out a tiebreak if we ran into it.


The event itself (bots not pictured)

Initially a bug that had the game in a test "move-from-the-bottom-always" mode resulted in "trashbot", one of the joke bots, absolutely crush the other bots.

The bug was correct and we found the two competative bots TimeCamel [made by Libby and Jack] and Sir_Humpfree_Bogart [made by myself] well ahead of trashbot [made by Charles] and randobot [made by Sean]. TimeCamel took the first game in which it was first up but Sir_Humpfree_Bogart took the next three games to pull home the win.


Sir_Humpfree_Bogart's owner, Tyler Barron (me)


How the bots work

Both bots work in a similar fashon. First, they look at all the possible configurations that the camels could end up at the end of the round. Then they determine the expected value of betting on a camel winning the round using

EV_roundwin = (chance_1st)*(payout) + (chance_2nd)*(payout) - (chance_3rd_or_worse)*(cost)

Then they move camels randomly until a camel wins. After doing this a few thousand times you can estimate the chance each camel will win and lose. Again, we get the expected value of these using

EV_gamewin = (chance_1st)*(payout) - (chance_2nd_or_worse)*(cost)

The only other options are moving a camel (which always yields one coin, so its expected value is one) and placing a trap. Both teams felt placing a trap was a weak enough option to ignore it entirely. With this information the bots chose the option with the highest expected value.

Addendum: Since our tournament viewed a second place finish the same as a last place finish it makes sense if you are behind to take chances to get into first place. SBH used distance_from_first_place and nearness_to_end to determine how risky the bot should be, where if you are far from first and close to the end then riskiness would be high and if you are in first or far from the end of the game the riskiness would be low. With a low riskiness the bot would decide on an action with a high expected value option and a high riskiness yielding the option with a high upshot. The exact equation was

Functional_EV = EV + (upshot-EV) * riskiness

where upshot is the highest payout you can get from a decision and riskiness ranges from 0 to 1.



Further Testing

With such a small sample size it was natural to extend the tests to be more rigorous.

 Test 1: TimeCamel vs SHB

This test was for more trials under a more controlled environement. I alternated between a game with [Randobot, SHB, Randobot, TimeCamel] and [Randobot, TimeCamel, Randobot, SHB], with TimeCamel and SHB switching places as there is a pretty large advantage to going first.

Sir_Humpfree_Bogart's vs TimeCamel
Camel
Wins (#)
Wins (%)
Randobot 1 1 0.1
TimeCamel 445 44.5
Randobot 2 3 0.3
SHB 551 55.1

SHB had about a 10 point lead over many trials. It should be noted that they took approximately the same amount of time per turn.



 Test 2: The disorder of Trashbot

This test was to determine the effects of Trashbot. This bot was made the day of the tournament - it always bets for a camel in the lead to win the round. However this is usually one of the best options, so while it may not have won it greatly diminished the choices the following player could make. I alternated between a game with [Trashbot, SHB, Randobot, TimeCamel] and [Trashbot, TimeCamel, Randobot, SHB], with TimeCamel and SHB alternating being right behind Trashbot.

Trashbot preceeding TimeCamel
Camel
Wins (#)
Wins (%)
Trashbot 22 7.3
TimeCamel 64 21.3
Randobot 0 0
SHB 214 71.3

Trashbot preceeding SHB
Camel
Wins (#)
Wins (%)
Trashbot 35 11.5
SHB 79 26.0
Randobot 1 0.3
TimeCamel 189 62.2

As you can see the taking of round bets was a huge gamechanger. From what I could see, the taking of round winners forced the next bot to move camels which gives modest return and, more importantly, plenty of information for the next "smart" bot. Still, just the taking away of that option made the other bot get a 50 point upper hand and even led Trashbot to winning ~10% of games. Amazing for four lines of code.

 Test 3: Effects of Riskiness

If you look at how each of our bots are made they implement a very similar structure and method to finding the correct move. The main feature that mine had that his did not was a concept called "Riskiness". For this test I hardcoded my riskiness to be 0. I then again alternated between [Randobot, SHB, Randobot, TimeCamel] and [Randobot, TimeCamel, Randobot, SHB].

Sir_Humpfree_Bogart without risk vs TimeCamel
Camel
Wins (#)
Wins (%)
Randobot 1 0 0
TimeCamel 95 45.0
Randobot 2 1 0.5
SHB 115 54.5

It seems like riskiness didn't have much an effect as I'd guessed. How I gain an edge then is a mystery to me... maybe my game_winner_bets better take into effect the case in which opponents have bet for which camels? Maybe my higher tolerance for betting helped? 10 percentage points is quite a lot... Maybe we'll learn more in the future!




The aftermath

Thanks for reading! It was a quirky experiment that led to a fun day with buddies -- can't ask for much more. See my github for the game and my bot and here for TimeBot's code.