Episode 2: Modeling basic data

Julien Truffaut image

Julien Truffaut

30 September 2025

Let’s kick things off with the most difficult task in any project: what do we call it?

In Dofus, players like to call themselves “opti” when they’re fully maxed out with the best gear. So, why not go with:

cargo new dofus-opti

Worst case, if we change our minds later, Git renames are free.

Modeling the Domain

The main goal of this tool is to find good combinations of gear. So, let’s start with the obvious: modeling a piece of gear.

struct Gear {
  name: String,
  gear_type: GearType,
  level: u32
}

enum GearType {
    Amulet,
    Hat,
    Ring,
    Shield,
    // TODO add all other types
}

Looks simple enough. But of course, gear in games isn’t just about style — it also comes with magical bonuses.

Characteristics

Here’s what an item looks like in-game: Crocoshield

The green numbers are the bonuses. For example, this shield grants +250 in Vitality and +50 in Power. On the right of each bonus, there’s a range (e.g. [201 to 250] for Vitality). That’s because the characteristics are randomized when the item is generated. Lucky me, my shield rolled a perfect 250! (Actually I didn’t, there is an advanced game feature to rework an object - maybe we will talk about that later).

Now the question is: which number shall we model?

  1. The actual value (e.g. 250),
  2. The possible range (201–250),
  3. Or both?

I don’t know yet, but to start, I’ll go with the range. That way we can at least build an encyclopedia of all existing items.

struct CharacteristicRange {
    kind: CharacteristicType,
    min: i32,
    max: i32
}

enum CharacteristicType {
    Vitality,
    Power,
    // TODO add all other types
}

And then update our Gear to store a list of these:

struct Gear {
  name: String,
  gear_type: GearType,
  level: u32,
  characteristics: Vec<CharacteristicRange>
}

Example

Now we can partially encode one of the items from the game:

let crocoshield = Gear {
  name: String::from("Crocoshield"),
  gear_type: GearType::Shield,
  level: 200,
  characteristics: vec!(
    CharacteristicRange {
        kind: CharacteristicType::Vitality,
        min: 201,
        max: 250
    },
    CharacteristicRange {
        kind: CharacteristicType::Power,
        min: 41,
        max: 50
    },
  ),
};

Nice! It works. But… It’s also painfully tedious and error-prone to encode every single item in the game by hand. And Dofus has hundreds of them. Clearly, this approach isn’t sustainable.

What’s Next?

In the next episode, we’ll go hunting for a data source so we can generate these gears automatically.

All the code from this post is available here. I’ll be creating a tag for each post so it’s easy to follow the project’s progress.