This page provides an overview of how to build your bot for kuh-handel. You can find the full Rust documentation here:
This tutorial is available for Rust and Python:
Get your bot done while the others are still oxidizing. Your bot will be blazingly fast.
Setup
Register Bots
You want to join the competition
curl -X POST "https://ufuk-guenes.com/kuh-handel/register?player_id=<your_bot_name>&token=<your_token>"
Setup environment
We will first create a virtual environment and install the newest version of pyhandel
python -m venv .venv
source .venv/bin/activate
pip install pyhandel
if you already have an older version of the package and need to update:
pip install --upgrade pyhandel pyhandel-stubs
blazingly fast rust example
fn greet(name: &str) {
println!("Hello, {}!", name);
}
Simple layout
Below you can find a template from which you can start implementing your own bot
import asyncio
import random as rn
from pyhandel import Value, Money, Points
from pyhandel.animals import Animal, AnimalSet
from pyhandel.client import Client
from pyhandel.messages.actions import (
AuctionDecision,
Bidding,
InitialTrade,
NoAction,
PlayerTurnDecision,
SendMoney,
TradeOpponentDecision,
)
from pyhandel.messages.game_updates import (
AuctionRound,
GameUpdate,
TradeOffer,
AuctionKind,
MoneyTrade,
MoneyTransfer,
)
from pyhandel.player import PlayerId
from pyhandel.player.player_actions import PlayerActions
from pyhandel.player.wallet import Wallet
class Bot(PlayerActions):
def setup():
# the __init__ can not take any arguments,
# setup your class with a separate function
raise NotImplementedError
def _draw_or_trade(self) -> PlayerTurnDecision:
raise NotImplementedError
def _trade(self) -> InitialTrade:
raise NotImplementedError
def _provide_bidding(self, state: AuctionRound) -> Bidding:
raise NotImplementedError
def _buy_or_sell(self, state: AuctionRound) -> AuctionDecision:
raise NotImplementedError
def _send_money_to_player(self, player: str, amount: int) -> SendMoney:
raise NotImplementedError
def _respond_to_trade(self, offer: TradeOffer) -> TradeOpponentDecision:
raise NotImplementedError
def _receive_game_update(self, update: GameUpdate) -> NoAction:
raise NotImplementedError
async def run(client, num_rounds):
for _ in range(num_rounds):
await client.play_one_round("game")
if __name__ == "__main__":
bot_name = "your_bot_name"
bot_token = "your_private_token"
base_url = "s://ufuk-guenes.com" # "://127.0.0.1:2000"
play_n_rounds = 1
bot = Bot()
bot.setup()
client = Client(bot_name, bot_token, bot, base_url)
try:
asyncio.run(run(client, play_n_rounds))
except KeyboardInterrupt:
print("Client shutdown")
except Exception as e:
print("Error: ", e)
blazingly fast rust example
fn greet(name: &str) {
println!("Hello, {}!", name);
}
More explanations
Below you can find in depth descriptions of the methods to implement
class Bot(PlayerActions):
def _draw_or_trade(self) -> PlayerTurnDecision:
if rn.random() < 0.5:
return PlayerTurnDecision.Trade(self._trade())
return PlayerTurnDecision.Draw()
def _trade(self) -> InitialTrade:
player = self.state.players[0]
animal = self.state.animals[0]
trade = InitialTrade(player, animal, 1, [0])
print(trade.amount)
return trade
def _provide_bidding(self, state: AuctionRound) -> Bidding:
host = state.host
animal = state.animal
bids = state.bids
if rn.random() < 0.5:
return Bidding.Bid(rn.randint(1, 100))
return Bidding.Pass()
def _buy_or_sell(self, state: AuctionRound) -> AuctionDecision:
host = state.host
animal = state.animal
bids = state.bids
if rn.random() < 0.5:
return AuctionDecision.Buy()
return AuctionDecision.Sell()
def _send_money_to_player(self, player: PlayerId, amount: Value) -> SendMoney:
if rn.random() < 0.05:
return SendMoney.WasBluff()
return SendMoney.Amount([0, 0])
def _respond_to_trade(self, offer: TradeOffer) -> TradeOpponentDecision:
challenger = offer.challenger
animal = offer.animal
count = offer.animal_count
card_offer = offer.challenger_card_offer
if rn.random() < 0.5:
return TradeOpponentDecision.Accept()
return TradeOpponentDecision.CounterOffer([10, 0])
def _receive_game_update(self, update):
match update:
case GameUpdate.Auction(kind):
self.handle_auction(kind)
case GameUpdate.End(ranking):
self.handle_end(ranking)
case GameUpdate.Start(wallet, player_order, animals):
self.handle_start(wallet, player_order, animals)
case GameUpdate.ExposePlayer(player, wallet):
self.handle_expose_player(player, wallet)
case GameUpdate.Inflation(money):
self.handle_inflation(money)
case GameUpdate.Trade(challenger, opponent, animal, animal_count, receiver, money_trade):
self.handle_trade(challenger, opponent, animal, animal_count, receiver, money_trade)
return NoAction.Ok()
def handle_auction(self, kind: AuctionKind):
match kind:
case AuctionKind.NoBiddings(host, animal):
pass
case AuctionKind.NormalAuction(rounds, from_player, to_player, money_transfer):
match money_transfer:
case MoneyTransfer.Public(card_amount, min_value):
pass
raise NotImplementedError()
def handle_end(self, ranking: list[tuple[PlayerId, Points]]):
raise NotImplementedError()
def handle_start(self, wallet: Wallet, player_order: list[PlayerId], animals: list[AnimalSet]):
notes = wallet.bank_notes
first_animal = animals[0]
inflation = first_animal.inflation
animal_value = first_animal.animal
raise NotImplementedError()
def handle_trade(self, challenger: PlayerId, opponent: PlayerId, animal: Animal, animal_count: int, receiver: PlayerId, money_trade: MoneyTrade):
match money_trade:
case MoneyTrade.Public(challenger_offer, opponent_offer):
pass
case MoneyTrade.Private(challenger_offer, opponent_offer):
pass
raise NotImplementedError()
def handle_expose_player(self, player: PlayerId, wallet: Wallet):
raise NotImplementedError()
def handle_inflation(self, money: Money):
raise NotImplementedError()
blazingly fast rust example
fn greet(name: &str) {
println!("Hello, {}!", name);
}