QE bot contest

From: GeekNights Tuesday - Exercise Games - #19 by Starfox

@Apreche and @Starfox were there talking about QE, and Apreche suggested that

It would be more interesting to try to make an AI that play QE well.

Well, I’ve been fascinated with the idea of bot making contests recently. Watching people build bots with strategies and seeing how they compete with each other is cool. It also reminds me of class contests in High Performance Computing a bit. It also comes from a more complicated interest in removing the playing part of ccgs, but that’s another story. In that vein, I started working on a framework for a QE contest.

I have started some source code started here: https://github.com/benjamintf1/QE. It’s not complete, but I think it’s a decent start. I need to check some of the logic on bidding again when I’m less tired, and I forgot to show the auctioneer all the bids each time(which will probably change the interface of that and results). At some point I need to decide on a value function for placing, and how to figure out number of players, and which players to include(but having bots first would be nice). Making player be reachable by http could be a goal if people want it, but I wanted to get something running quick so ignored that.

Let me know if you’re interested(/ if you have improvements/requests).

I have one suggestion from giving it a quick look. I think having a serialization format for game state is really important. Just making something up without too much thought, something like

    num_players: 4,
    card_order: [6, 1, 0, 9, 11, ...],
    rounds: [
            'auctioneer': 2,  # player number 2
            bids: {0: 100, 1: 25, 2: 10, 3: 69},
            'auctioneer': 3,
            bids: {0: 2, 1: 11, 2: 18, 3: 1},

Then the API for getting a bid from a player could be something like

get_bid(game_state, your_player_number)

And leave parsing the game state and figuring out what to bid up to players. For example, you might ignore everything, and then this is the entire implementation:

class AlwaysBids25Bot(BasePlayer):
    def get_bid(game_state, player_number):
        return 25

And then the core loop of the engine would look something like

while len(game['rounds']) <= len(game['card_order']):
    bid = players[auctioneer_player_number].get_bid(game, auctioneer_player_number)
    new_game = add_bid_to_game(bid, auctioneer_player_number)

    for player in players_that_arent_auctioneer:
        bid = player.get_bid(new_game, player_number)
        new_game = add_bid_to_game(bid, player_number)

    auctioneer_player_number = (auctioneer_player_number + 1) % num_players
    game = new_game

You would have to hide the appropriate information for each player before you pass them the game state, you could replace those values with None or something.

This structure has the advantage of being able to test and modify bots without them needing to track game state, or coordinate a bunch of them to play together, etc.


TY for the input. I do want to be careful to not show information to bots they shouldn’t see(I think not having to trust in that sense is probably valuable, hense why there’s duplicative information for industry and country). I’ll probably do some refactoring later tonight.I think part of that might be making the information given to bots more friendly.

edit: probubly won’t do anything today, soon though

Did a big refactor that hopefully should help making some of the logic easier. Now storing state more often and have more objects. I keep confusing myself about some of the rules(particularly, what happens on ties), but I think I have it down in my mind now. Need to store historical bids, come up with a method to create a gamestate object(as requested) based on what a particular player should be able to see, and bring back the peak functionality for 5 player games. Might still take a bit till I’m satisfied and feel confident telling people(including/especially anyone here, but might also mention it in some personal circles outside this forum) that it would be a reasonable to make a bot for competing.

Things left to do:

  • make sure game state objects aren’t able to be mutated by bots
  • add peeking for 5 player games
  • add tie breaking maybe? Also, determine a scoring function for bots(winner take all? lower rankings count? score matter? negatives for busting?)
  • Maybe tell more people about it, and maybe post a blogpost sumerizing concept and giving a place to submit bots
  • (If there’s demand) I know there was feedback on isolation, perhaps run bots it docker containers via a http/rest interface? Would allow isolation, and allow differing choices of solution for coding, but also not require the barrier of entry of having a web server.

Create an example template bot. Then people can clone the basic bot project to create their own bots more easily. Make sure to include some type of automated tests, so people can verify their bots are working before they submit. Also document the API the bots will be using.

I say this because that’s the minimum you have to provide to get someone like me to consider participating.

1 Like

Will do. 15 characters

There should now be a simple readme. Main.py runs the game with a number of players specified by a command line argument. When run against game, the example bot will dump the game state to standard out, and then return a bid of 1-3. ExamplePlayer can be replaced with own implimentation, and run using main.py. Right now testing just by making sure it doesn’t fall over. Not super in tune with python, so haven’t done unit testing in it before and don’t know if it’s necessary, not fall over testing might be sufficient? The interface is quite simple/hard to mess up.

More sophistication to come.

Peeking has been added, tie breaking has not. Modification of state is probably still possible.

Still unsure if python3 is a dealbreaker, chose it because iirc all the machine learning frameworks are written in python, so I figured people would want to use that. Not sure if it’s a deal breaker though, if so will work hard to develop other interface(or other interface option).

Still have a bunch to do in general, but I hope that addresses your current concerns, if not, let me know. Wanted to act quickly to address these concerns(I hope @Starfox’s concerns are met too).

Edit: If I keep with python, I might make an interface to dynamically load packages somehow rather then requiring hard coding in the init. If yall want something different, I’m thinking switching to rest over/to docker containers?

Edit 2: I’ll probably make some more substantial bots at some point. Just wanted to get framework out real quick.

  • Is this just the bidding part of QE?
  • Will a given player/bot’s number be consistent across all runs for the contest or just a given game?
  • Will a bot be stateless/reset between games or can it store a history? How best to store that history if you’re hosting/running the bot?

What other parts are there?

Honestly, I havn’t gotten to the stage of running multiple game yet. Shuffling players is probably something I’d imagine happening in some form or another though.

Are you talking about trying to learn specific player strategies, or just general learning. I was thinking stateless on run, but imagining people would possibly train them as well in some form just using the code base and possibly other bots?

Victory points, Industry bonuses, Monopoly bonuses… the rules in the rulebook.

If BOT25 always bids 25, then it would be advantageous for my bot to recall the historical bids on BOT25 through every game it’s played with BOT25, assuming I get a consistent identifier for BOT25.

But stateless keeps everything simpler, and you’ll probably get more submissions that way.

Oh yes, scoring. Those are all in there.

That’s fair. Maybe I should consider that more. My initial perception was that it was more accurate to the game to not know details about the other players.

IMHO there should not be any information carried over from game to game. Bots should not know which bots they are playing against, or if they have faced certain bots before. Start each game of QE with a blank slate.


I’m of Scott’s approach. I’m personally interested in intra-game strategy rather than meta strategy. How does the information you gain in the course of the game inform play?

THAT’s the question I want to answer.

1 Like

Consider me another vote for independent games.

Pass in a copy of it. Then the players can’t alter the Game’s copy, and only know what you tell them.

Oh yes, that is indeed the thing. However a copy is something I’ll have to take work to do/quantify that I haven’t yet. Copies in python tend to be…shallow? I would need to make sure that whatever copy I make is at the right level for each and every object, you know? It’s probably 15 mins of work tops, I just haven’t done it yet.

Edit: I usually code in golang lately and learned in c++, so the default of “reference type” instead of “value type” that comes with something like java and python often messes with me.

edit2: fixed in the laziest way possible.


https://github.com/Benjamintf1/QE/commit/1b95112241f8ad68bf0c8cf1e773cb66e6d26429 Yup, that’s what I did

oh man, it’s been a month. I’m really bad at continuing this project. I’m sorry if there was anyone desperatly waiting for more updates(don’t think that’s the case, but 🤷). It’s probubly fine though. Interesting expirience writing something slightly gamelike. Havn’t ever done it before.

1 Like