Multi-Character Bots¶
Run multiple characters at the same time using async and
asyncio.gather().
Note
Multi-character requires the async client (AsyncArtifactsClient).
If you’re not familiar with async, check Your First Bot first.
5 Fighters in Parallel¶
import asyncio
from artifacts import AsyncArtifactsClient
from artifacts.errors import ContentNotOnMapError
TOKEN = "your_token_here"
CHARACTERS = ["Fighter1", "Fighter2", "Fighter3", "Fighter4", "Fighter5"]
FIGHT_X, FIGHT_Y = 0, 1
MAX_FIGHTS = 20
REST_THRESHOLD = 0.4
async def combat_loop(char):
"""Combat loop for a single character."""
name = char.name
info = await char.get()
print(f"[{name}] Level {info.level} HP {info.hp}/{info.max_hp}")
# Move to fight spot
if info.x != FIGHT_X or info.y != FIGHT_Y:
await char.move(x=FIGHT_X, y=FIGHT_Y)
fights = 0
while fights < MAX_FIGHTS:
info = await char.get()
if info.hp < info.max_hp * REST_THRESHOLD:
rest = await char.rest()
print(f"[{name}] Rested +{rest.hp_restored} HP")
continue
try:
result = await char.fight()
except ContentNotOnMapError:
print(f"[{name}] No monster, stopping.")
break
fight = result.fight
cr = fight.characters[0]
fights += 1
print(f"[{name}] Fight #{fights}: {fight.result.value} +{cr.xp}xp")
print(f"[{name}] Done! {fights} fights completed.")
async def main():
async with AsyncArtifactsClient(token=TOKEN) as client:
print("=== Multi-Character Combat ===\n")
# Verify characters exist
my_chars = await client.my_account.get_characters()
my_names = {c.name for c in my_chars}
active = []
for name in CHARACTERS:
if name in my_names:
active.append(client.character(name))
else:
print(f"WARNING: '{name}' not found, skipping.")
if not active:
print("No valid characters!")
return
# Run all combat loops in parallel
await asyncio.gather(*[combat_loop(c) for c in active])
print("\n=== All done! ===")
asyncio.run(main())
How It Works¶
asyncio.gather()runs all character loops simultaneouslyEach character has its own independent cooldown
While one character waits for a cooldown, others keep fighting
The SDK tracks cooldowns per-character automatically
Mixed Roles (Fighter + Gatherer)¶
import asyncio
from artifacts import AsyncArtifactsClient
TOKEN = "your_token_here"
async def fighter_loop(char):
await char.move(x=0, y=1)
for i in range(10):
info = await char.get()
if info.hp < info.max_hp * 0.4:
await char.rest()
result = await char.fight()
print(f"[{char.name}] Fight {i+1}: {result.fight.result.value}")
async def gatherer_loop(char):
await char.move(x=2, y=0)
for i in range(10):
result = await char.skills.gather()
print(f"[{char.name}] Gather {i+1}: +{result.xp}xp")
async def main():
async with AsyncArtifactsClient(token=TOKEN) as client:
fighter = client.character("MyFighter")
gatherer = client.character("MyGatherer")
await asyncio.gather(
fighter_loop(fighter),
gatherer_loop(gatherer),
)
asyncio.run(main())
Tips¶
Each character can only do one action at a time (server-enforced)
Use
asyncio.gather()to run characters in parallel, not threadsShared cooldown tracking means no wasted time between actions
Start with 2 characters and scale up once you’re comfortable