- Announcements: new competition at COG 2025
- Scripts of Tribute Project
- Setup
- Implementing AI Agent
- References
- Legal Notice
- Tales of Tribute AI Competition has been accepted for IEEE Conference on Games 2025.
- Deadline for the agent submission is August 10.
- More details about participating, including updates in the game, here.
- In particular, our framework currently supports multiple programming languages.
- Important note - engine uses .NET 8.0 now, instead of .NET 7.0, as NET 7.0 is not supported by Microsoft anymore.
Scripts of Tribute (SoT) framework is a Tales of Tribute simulator, implemented in C# .NET Core and allowing to write AI agents and play against them.
A short video describing the 2023 competition is available HERE (most info remain up-to-date).
To play against the existing bots, download the most recent GUI binary release for your OS.
To start developing your own AI agents, check the documentation in this section and download SoT-Core project.
Dockerfile for competition environment is available here
Extended version of the COG 2024 paper describing the competition is available on arXiv.
Tales of Tribute is a deck-building game that launched with The Elder Scrolls Online High Isle expansion.
As a source of information about the game, we find the following links helpful (some information in the descriptions might be outdated due to the game patches):
- Introducing Tales of Tribute AI Competition, Section IV
- game rules
- list of cards and patrons (up-to-date)
- patron strategies
- deck guides
The current SoT release is compatible with Tales of Tribute from ESO PC/Mac Patch 10.3.5 (10.03.2025). All patron deck cards are fully upgraded.
Cards data used is available in the cards.json file.
Come to our Discord and talk to us.
Jakub Kowalski, Dominik Budzki, Damian Kowalik, Katarzyna Polak, Radosław Miernik (University of Wrocław, Institute of Computer Science).
As ScriptsOfTribute Engine is based on the .NET framework, we recommend using Windows as a developing platform.
You can download the source code of the SoT engine from this repository.
Any you like. If you choose Visual Studio, make sure that you choose Visual Studio 2022, which supports .NET 8.
Skip this if you've chosen Visual Studio.
To build our engine and create bots with it, you need to install .NET 8 SDK compatible with your operating system. Go to the official page Download .NET 8.0, download, and then install the latest version.
If you are using Linux - here is the link to the tested tutorial; just change the version in commands from 6.0 to 8.0.
You should familiarize yourself with them before implementing a bot.
-
AI.cs - abstract class from which your agent should inherit. You have to implement the
SelectPatron
andPlay
methods. In theEndGame
method, you can add code that should be run after the end of the game, and inLog
method you can add some logs. -
All files in Serializers folder - by using these classes you can gain access to all visible data of the game - board, hand, tavern, etc. You can start with the
GameState
class - the object of this class you get from thePlay
method.
Useful files if you want to get access to some important information (cost of a card, amount of power of the opponent, ...) and types of cards, effects, etc:
This section introduces some objects that are used in the engine and knowing them is important for understanding other sections.
EndGameState
– contains information about how the game ended. It has aReason
field that indicates why the game ended, which can, for example, beTURN_TIMEOUT
orINCORRECT_MOVE
. It also containsID
of the winning player (unless the game ended to a reason such as an internal failure) and a string containing additional context about why the game ended, for example, in case of an incorrect move, it contains the move and a list of all other correct moves that were possible and should have been played instead. API functions often returnEndGameState?
– in most cases it is null, but in case the player makes a mistake or his move ends the game, this object is returned to indicate this.Move
– represents a move that a player can make. It contains aType
field, which can be, for example,PLAY_CARD
,END_TURN
, orACTIVATE_PATRON
. Depending on the type, it also contains additional information, such as the card that is to be played in case ofPLAY_CARD
move. Moves can be created using static methods inMove
class, for example:Move.PlayCard(card)
.Choice
– represents a choice that the player has to make. It can be, for example, a choice of which card to discard. Either cards or effects can be chosen, depending on the card played. This object also contains some information about the choice, including all possible items to choose, how many items need to be chosen, or what the effect of the choice will trigger (for example: destroy the chosen cards).ChoiceContext
– this object lives inside theChoice
and holds additional context, including the card and effect, or the patron that triggered the choice.
-
You can either download
dll
library file from here and use it as normal .NET library or you can clone engine repository and create a file inScriptsOfTribute-Core\Bots\src
folder e.g.MyFirstAgent.cs
. Please remember that your class (in this case,MyFirstAgent
) should inherit from AI abstract class. -
Implement the body of
SelectPatron
method. Arguments of this method are a list of available patrons and which round of selection of patron it is (first or second). Your method should returnEnum
object of the typePatronId
. -
Implement a body of
Play
method This method will be run in a loop until you don't return a move that will end your turn, or your bot will try to do not allowed move. The method receives aGameState
and a list of possible moves and should return one move from that list. -
[Optional] Implement the body of GameEnd This method is called after the game has ended. The purpose of this function is to allow the programmer to analyze the data from the
EndGameState
object as they wish. -
[Optional] Add logs To add logs to your bot, call the method
Log
with a string that you want to put in your log. Logs can be shown in the GUI during play. -
Compile your bot:
In case you use our engine throughdll
file just compile your project as library, but if you work inside the reposity just rundotnet build
inScriptsOfTribute-Core\Bots
folder. Createddll
file is now ready to use either by GameRunner or GUI app.
Our engine supports gRPC connection for external languages. For now we've prepared Python pip package that covers whole communication, for details please check repository with the source code and provided examples there on how to use this library.
There's a possibility to use different language than C# to create a bot thanks to ExternalAIAdadpter. For now engine is built to work with Python files, but enabling other languages is easy. In such cases please contact us.
If you plan to create a bot in different language you have to parse game state from stdin which will come in json format ending with EOT string as an "End of Transmission" sign. Forming this object is done in Game State class in SerializeGameState
method. To understand more how these objects look please check tests. In case of any problem fastest way to get help or any information is through our discord.
Feel free to study our example agents, to familiarize yourself more with the infrastructure of the project. You can also use code from them to create your own code.
Bots whose understanding can help you implement your own agents:
- RandomBot
- MaxPrestigeBot Focus on the usage of
gameState.ApplyMove()
- this function allows you to simulate a move. If you provide a seed, you can simulate a random playout based on that seed. When running this method without a seed you will receiveGameState
and available moves without any random events (like a card that you could draw, a new card in the tavern after buying/removing the card, etc.)
Game Runner is a command-line application that allows the user to load bots from DLLs and run games between them.
Usage: GameRunner <NameOfBot1> <NameOfBot2> <flags>
for example: GameRunner RandomBot RandomBot -n 1000 -t 2
will run 1000 games between two RandomBot
s using two threads
For more flags and usage help, run GameRunner -h
To run game with bot made in different language, for example python via gRPC use grpc:
before bot's name. For example: GameRunner RandomBot grpc:RandomBot -n 1000 -t 2
It is available for download here for Windows, Linux and MacOS
The Tales of Tribute AI Competition has been described in this article.
Please cite as follows:
@inproceedings{Kowalski2024IntroducingTales,
author = {Kowalski, J. and Miernik, R. and Polak, K. and Budzki, D. and Kowalik D.},
title = {{Introducing Tales of Tribute AI Competition}},
booktitle = {IEEE Conference on Games},
pages = {1--8},
year = {2024},
}
Initial version of the ScriptsOfTribute has been described in engineer's thesis.
@mastersthesis{Budzki2023ImplementingTalesOfTribute,
title={{Implementing Tales of Tribute as a Programming Game}},
author={Budzki, Dominik and Kowalik, Damian and Polak, Katarzyna},
type={Engineer's Thesis},
year={2023},
school={University of Wroc{\l}aw}
}
This competition is neither directly nor indirectly related to Bethesda Softworks, ZeniMax Online Studios, nor parent company ZeniMax Media, in any way, shape, or form.
It is based on the Scripts of Tribute framework, which mimics the game Tales of Tribute and provides access points for the development of AI agents. The framework does not allow to play the original game, nor does it connect to the game’s servers in any way.
The Elder Scrolls® Online developed by ZeniMax Online Studios LLC, a ZeniMax Media company. ZeniMax, The Elder Scrolls, ESO, Bethesda, Bethesda Softworks and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the US and/or other countries. All Rights Reserved.