Daydreams Logo
Guides

Building a Gigaverse Game Agent

This guide will walk you through creating an AI agent that can play the Gigaverse dungeon crawler game using Daydreams.

This guide will walk you through creating an AI agent that can play the Gigaverse dungeon crawler game using Daydreams.

Prerequisites

Before starting, make sure you have:

  1. A Gigaverse account
  2. The following environment variables set up:
    • ANTHROPIC_API_KEY: Your Anthropic API key
    • GIGA_TOKEN: Your Gigaverse authentication token (Bearer token from browser)

Creating the Agent

First, let's create a basic Gigaverse agent:

import { anthropic } from "@ai-sdk/anthropic";
import {
  createDreams,
  context,
  render,
  action,
  validateEnv,
  LogLevel,
  type Agent,
} from "@daydreamsai/core";
import { cliExtension } from "@daydreamsai/cli";
import { string, z } from "zod";
 
// Validate environment variables
const env = validateEnv(
  z.object({
    ANTHROPIC_API_KEY: z.string().min(1, "ANTHROPIC_API_KEY is required"),
    GIGA_TOKEN: z.string().min(1, "GIGA_TOKEN is required"),
  })
);
 
// Define the goal-oriented context
const goalContexts = context({
  type: "goal",
  schema: z.object({
    id: string(),
    initialGoal: z.string(),
    initialTasks: z.array(z.string()),
  }),
 
  key({ id }) {
    return id;
  },
 
  create(state) {
    return {
      goal: state.args.initialGoal,
      tasks: state.args.initialTasks ?? [],
      currentTask: state.args.initialTasks?.[0],
    };
  },
 
  render({ memory }) {
    return render(template, {
      goal: memory.goal,
      tasks: memory.tasks.join("\n"),
      currentTask: memory.currentTask ?? "NONE",
    });
  },
});
 
// Create the Gigaverse agent
createDreams({
  logger: LogLevel.INFO,
  model: anthropic("claude-3-7-sonnet-latest"),
  extensions: [cliExtension],
  context: goalContexts,
  actions: [
    // Actions will be defined below
  ],
}).start({
  id: "gigaverse-agent",
  initialGoal: "Successfully complete a dungeon run in Gigaverse",
  initialTasks: [
    "Start a new dungeon run",
    "Make strategic combat decisions using rock-paper-scissors mechanics",
    "Select optimal loot after defeating enemies",
    "Progress as far as possible in the dungeon",
  ],
});

How It Works

The Gigaverse agent is built using several key components:

  1. Context Template: Defines the agent's understanding of the game and its current state:
const template = `
# Gigaverse Dungeon Game
 
You are an AI agent playing a rock-paper-scissors dungeon crawler game.
 
## Game Rules:
- Combat is resolved through rock-paper-scissors mechanics
- You can collect loot after defeating enemies
- Your goal is to progress as far as possible in the dungeon
 
## Current Status:
Goal: {{goal}} 
Tasks: {{tasks}}
Current Task: {{currentTask}}
 
Make strategic decisions based on enemy patterns and your current state.
`;
  1. Game Actions: The agent can perform several actions in the game:

    • attackInDungeon: Make combat decisions (rock, paper, scissors) or select loot
    • getPlayerState: Retrieve the current game state
    • startNewRun: Begin a new dungeon run

Understanding Gigaverse Game Mechanics

Gigaverse is a dungeon crawler game with the following key mechanics:

  1. Rock-Paper-Scissors Combat: Battles are resolved using the classic rock-paper-scissors game:

    • Rock beats Scissors
    • Scissors beats Paper
    • Paper beats Rock
  2. Dungeon Progression: Players advance through the dungeon by defeating enemies.

  3. Loot System: After defeating enemies, players can select one of three loot options to enhance their character.

  4. Health Management: Players must manage their health throughout the dungeon run.

Core Game Actions

Let's implement the three main actions needed for the Gigaverse agent:

1. Attack in Dungeon

This action handles both combat (rock-paper-scissors) and loot selection:

action({
  name: "attackInDungeon",
  description: "Attack in the dungeon using rock-paper-scissors game mechanics",
  schema: z
    .object({
      action: z
        .enum([
          "rock",
          "paper",
          "scissor",
          "loot_one",
          "loot_two",
          "loot_three",
        ])
        .describe("The attack move to make"),
      dungeonId: z
        .number()
        .default(0)
        .describe("The ID of the dungeon"),
    })
    .describe(
      "You use this to make an action in a dungeon. If the lootPhase == true then you can select the Loot option, which will then take you to the next phase. If the lootPhase == false then you can select the Rock, Paper, Scissors option."
    ),
  async handler(data, ctx, agent) {
    try {
      const { action, dungeonId } = data;
 
      const payload = {
        action: action,
        actionToken: new Date().getTime().toString(),
        dungeonId: dungeonId,
      };
 
      const response = await fetch(
        "https://gigaverse.io/api/game/dungeon/action",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${env.GIGA_TOKEN}`,
          },
          body: JSON.stringify(payload),
        }
      );
 
      if (!response.ok) {
        throw new Error(`Attack action failed with status ${response.status}`);
      }
 
      const result = await response.json();
      return {
        success: true,
        result,
        message: `Successfully performed ${action} attack in dungeon ${dungeonId}`,
      };
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      return {
        success: false,
        error: errorMessage,
        message: "Attack action failed",
      };
    }
  },
}),

2. Get Player State

This action retrieves the current state of the player in the dungeon:

action({
  name: "getPlayerState",
  description: "Get the current state of the player in the dungeon",
  schema: z.object({}),
  async handler(data, ctx, agent) {
    try {
      const response = await fetch(
        "https://gigaverse.io/api/game/dungeon/state",
        {
          method: "GET",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${env.GIGA_TOKEN}`,
          },
        }
      );
 
      if (!response.ok) {
        throw new Error(`Fetch player state failed with status ${response.status}`);
      }
 
      const result = await response.json();
      return {
        success: true,
        playerState: result,
        message: "Successfully fetched player's dungeon state",
      };
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      return {
        success: false,
        error: errorMessage,
        message: "Failed to fetch player's dungeon state",
      };
    }
  },
}),

3. Start New Run

This action initiates a new dungeon run:

action({
  name: "startNewRun",
  description: "Start a new dungeon run. Use this when the player dies or wants to start a new run from outside the dungeon.",
  schema: z.object({
    dungeonId: z
      .number()
      .default(1)
      .describe("The ID of the dungeon to start. Default is 1."),
  }),
  async handler(data, ctx, agent) {
    try {
      const { dungeonId } = data;
 
      const payload = {
        action: "start_run",
        actionToken: new Date().getTime().toString(),
        dungeonId: dungeonId,
      };
 
      const response = await fetch(
        "https://gigaverse.io/api/game/dungeon/action",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${env.GIGA_TOKEN}`,
          },
          body: JSON.stringify(payload),
        }
      );
 
      if (!response.ok) {
        throw new Error(`Start new run failed with status ${response.status}`);
      }
 
      const result = await response.json();
      return {
        success: true,
        result,
        message: `Successfully started a new run in dungeon ${dungeonId}`,
      };
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      return {
        success: false,
        error: errorMessage,
        message: "Failed to start a new dungeon run",
      };
    }
  },
}),

Agent Decision Making

The agent uses the context and player state to make strategic decisions. Here's how the agent approaches the game:

  1. Analyzing Enemy Patterns:

    • The agent observes patterns in enemy moves over multiple encounters
    • It can identify if an enemy favors certain moves (like using "rock" more frequently)
    • This information helps the agent make counter-moves (like choosing "paper" against a "rock"-favoring enemy)
  2. Loot Selection Strategy:

    • After defeating enemies, the agent evaluates the three loot options
    • It considers the player's current health, inventory, and progression
    • The agent selects loot that complements the player's build or addresses weaknesses
  3. Adaptive Gameplay:

    • As the dungeon difficulty increases, the agent adjusts its strategy
    • It may prioritize health-restoring items when health is low
    • The agent can become more conservative or aggressive based on the player's current state
  4. Goal-Oriented Planning:

    • The agent maintains awareness of its overall goal and current tasks
    • It can reprioritize tasks based on the changing game state
    • This ensures the agent makes decisions that contribute to long-term success

Integrating with Daydreams

This example showcases several key Daydreams features:

  1. Goal-Oriented Context: The agent maintains a structured goal and task list.

  2. Action Definitions: Clear, typed actions with Zod schemas for validation.

  3. API Integration: Seamless interaction with external APIs (Gigaverse in this case).

  4. Error Handling: Robust error handling to manage API failures gracefully.

Next Steps

  • Customize the agent's strategy by modifying the context template
  • Add more sophisticated decision-making logic
  • Implement inventory management and character progression
  • Extend the agent to handle more complex game scenarios

For more examples and detailed API documentation, check out our API Reference.

You can find the complete Gigaverse example in the examples directory.

On this page