Some good friends of mine own (too) many board games. To keep track of their stash and play sessions they track everything on Board Game Geek (BGG). Board Game Geek is a site for board game hobbyists and a game database that allows board game enthusiasts to rate and review games and maintain collections.
So I thought to myself: What if I create a game based on their games.
The card generator can be found on GitHub where you can get the three main scripts and generate your own version of this game.
But where to start? First define some goals, what can this game be used for:
- Plain as a card game for playing quartets
- As a „decider helper“, what game to play next
- It should function as a „legacy“ game, as in you can update the card game game with your data
- Expandable (there is always the next birthday) and there are more games to cover
And then the main steps in order to get things done
- Collect game and game collection data from the BGG API
- Select the four groups of cards from the bunch of boardgames
- Generate the card images
- Design a box for the game
- Order the game
Step one: Getting the data
To get the data there is luckily an API that can be used the BoardGameGeek XML API using this we can get a user collection that contains all owned games by that user. After looking into the data for a bit it was clear that this request was not containing every statistic I wanted to print on the card to have a good quartet card game each card needs to have some statistics to compare. What I got so far was statistics about the name, year it was published, the image, a thumbnail and ratings that where given by all the users of BGG and the rating as well as the number of plays of the collection owner (my friends in this case). So to get more game data I had to do a second pass where I would fetch the game data for each entry in the collection. This could be also done by using the XML API.
Step two: Select some games
But where to start? To help me here I wrote a little routine that would dump the combined collection and game data into a CSV file. This format is great to open in a tabular tool like LibreOffice Calc. Here I could quickly sort rows and come up with some criteria that would help me to pick a few cards. The print service I have selected has the option to print custom cards in sets of 33, 55 or 110. I decided to go for 55 playing cards and thus had to select 52 games to print as cards (13*4 + 2 Joker + one top card).
One thing was clear that any change to data itself would require me to do the selection again using this CSV to Calc method. So I after settling on my four quartet groups I decided to implement a script to automate the selection process. This would ensure that 52 unique cards where picked, would allow me to have configuration option like exclusion of certain games (expansions for example), add extra joker cards that are not part of the game, perform cleanup of game statistics or do per-formatting if required and lastly I could dump the final output into a single combined YAML file. Using this format the readability was improved in comparison to XML. Now I could review the values in a single file before the cards where generated.
The final categories I settled for where:
- Best rank
- Games for two
- Games for many
- Most played
An example for data per-processing done to the game statistics is the recommended player count suggestion. This suggestion is displayed on a game page on BGG as combined value but the results I got from the XML API was presented as raw user voting data. This voting is done by the community and is a great feature of BGG as it is usually more precise than the player count suggestion a manufacturer gives on the box, especially as there is the voting distinguishes between best, recommended and not recommended.
The following is an example of the result YAML file.
groups: A: category: Best rank color: '#F44336' top-color: '#c62828' games: - _id: '342942' age: 14+ image: https://cf.geekdo-images.com/....jpg name: Arche Nova owners: 30K players: 1-4 players_recommended: 1-3 / 2 playtime: 90-150 rating: '8.60' user_play_count: 2 user_rating: '10' weight: '3.71' year: '2021'
Step three: Generate the cards
Now as all the data was prepared the cards could be generated. To star here I created a first draft to position the game statistics and image.
And after some playing around with the Python image library the following card was created.
As things are often not that simple I quickly want to list some findings, mistakes and implementations I have made during the creation of this game in no particular order:
- API data is cached in a temp folder to reduce API calls. Same with game images
- Some game images had a bad aspect ratio or some artifacts this was easily cleaned up in the cache images
- Created a helper dpi helper function to scale the image up or down without breaking the layout
- Played around with the GitHub copilot. This is a AI helper that suggests code snippets and can be used for example to generate implementations of methods that only exist as prototype.
- The snippets produced by copilot did correctly use my dpi helper function
- Created two meta cards as joker a card containing a cake and a game card for the game itself.. how meta.
- Started by parsing the HTML page, should have used the API first
- Started with JSON as data storage output, here no comments could be made and overall YAML was the better decision. Also storing the XML as JSON was just another unnecessary step
- Copilot can even help with code comments. It will suggest a line and you can just continue from there and add details (that he will also further suggest)
- Player count is displayed as lines if the count is > 9 so adding another session to the count can be done quiet easily using a pen
Step four: Design a box
This step was pretty straight forward: Using the provided template I came up with a simple solution that works quiet well as a box art.
Step five: Order the game
As manufacturer I selected meinspiel.de as they offer good price to card performance and the order experience as well as the customer support was good. The cards where printed fast and arrived only some days later. They also offer different other custom games.
Mistakes where made
But not all is good two issues I managed to use the wrong input format and a too high resolution for the game card image. This did result in some artifacts in places where the contrast is high, mainly the text boxes. This is probably linked to some compression and transformation done on the manufacturers side that could have been avoided by using the right format and size with proper quality settings on my end.
The handy template for generating the box art has some lines to guide during image creation. Here I did forget to hide the lines before upload and due to a bad preview option during order this mistake was not spotted. Well have to do better next time.
This all was fun project and was also very well received. I like such projects where even if the effort his high the outcome is really great and in this case super fitting. Some mistakes where made but if you don’t tell they are hard to spot. In case of commercial products this would be solved by ordering a review copy as prove to ensure the result is printed right and no mistakes are left in the final product.
Playing around with copilot was fun, It is a great tool to quickly suggest the right code snippet without leaving the IDE but I’m certain that it is currently not able to replace my Job.
To avoid some hassle and mistakes during the production the target output should have been a PDF file. Yet here other obstacles will be faced I did not want to face this time. For example defining the color range and file properties must be taken into consideration. On the other side I can use proper vectorized images for the icons and lines on the card and for the fonts. This should improve the print quality by a bit.
As stated earlier: The card generator can be found on GitHub