Genshin Artifact Appraiser
Appraise Theorycraft Help

GAA is still in early closed alpha! Please do not share the link with others. There are probably a lot of bugs, so message Kokomi when you find them.

Intro to Theorycrafter

Theorycrafter does what the name says: it does calculations for a Genshin character. You enter a formula for an objective to optimize for, and the Theorycrafter simulates thousands of accounts for each weapon/artifact set combination. The Theorycrafter then automatically figures out which main stats are good, what sub stats to prioritize, and what is the distribution of values like stats or damage.

The result of the Theorycrafter can be saved and used in the Appraiser (TODO: not implmented yet). While the Appraiser is meant to be easy to use for anyone, the Theorycrafter is designed for more serious theorycrafters who are familiar with Genshin's damage formula and not afraid to get their hands dirty.

This tool's main motivations are the following:

Please be aware of these limitations of the theorycrafter before using it:


Example: Optimizing Fischl's Oz Damage

Let's walk through a simple example: optimizing Fischl's Oz damage, with the Skyward Harp as the weapon and the Golden Troupe 4-piece as the artifact set. You can copy this formula to the theorycrafter to see the output.

# Fischl's Oz damage
main {
    char fischl L90 C6 1/9/9
    weapon skyward_harp L90 R1
    artifact 4*golden_troupe
    talent skill Ozs_ATK_DMG = 88.80 95.46 102.12 111.00 117.66 124.32 133.20 142.08 150.96 159.84 168.72 177.60 188.70 199.80 210.90
}

maximize $Oz_Damage = talent.Ozs_ATK_DMG% * atk * Bonus% * (1+crit_rate%*crit_dmg%) * defense(100) * resist(10)
Bonus = bonus+electro+skill

$crit_dmg += skyward_harp.effect(20, 25, 30, 35, 40)
skill += 20*golden_troupe.piece_2
skill += 50*golden_troupe.piece_4

Let's break it down line by line:

After writing a formula like this, we can run the formula with the theorycrafter by clicking the Start Theorycrafting! button.


Writing a formula

A formula for GAA is written in a C-style syntax, which should be similar to Excel/Google Sheet formula syntax as well. A formula is a list of assignments, which consists of a variable name, an equal sign, and then an expression involving numbers and variables with arithmetic operations like + (add), - (subtract), * (multiply), and / (divide). The operators follow the standard order of arithmetic operations, and parentheses (()) can be used for grouping. The percentage sign (%) is used after a number or a variable as shorthand for "divide by 100". The equal sign (=) here means assigning the computed value from the right-hand side to the variable on the left-hand side, as typically used in programming languages. It's not an equality from mathematics.

Example

Kokomi_Crit_Rate  = 5 - 100
Hyperbloom_Damage = 300% * 1446.9 * (1+16*em/(em+2000)) * 0.9

Whitespaces (like spaces and line changes) are not meaningful, but they cannot be used inside a variable name. Comments (text you use to note things for humans but ignored by GAA) can be started with # and end at the end of the line. You can also add a comment inside an expression using ^{} syntax. An assignment can span multiple lines, but no two assignments can share a line.

Example

# This is a comment: both of these assignments are perfectly legal!
Sum_Of_Odd_Numbers=1+3+5+7+9+11
  Sum_Of_Even_Numbers =   2  + 4  + 6  +
                        8 + 10 + 12    # but don't write like this, it's annoying

# Example of in-line comments
Kokomi_Healing_Bonus = 25^{Kokomi passive} + 10^{Everlasting Moonglow passive} +
                       15^{Ocean-Hued Clam 2-piece} + 35.9^{circlet}

Variable names can be prefixed with a dollar sign ($) to make their distribution visible in the "Build Calculations" output. Variable names must be composed of upper/lower case alphabet, underscores, and/or digits from 0 to 9, and they cannot start with a digit. Variable names are case sensitive, so burst_damage and Burst_DAMAGE are two different variables. You can only use a variable in the right-hand side expression if it is defined once on the left side of an assignment. Some names are reserved so they cannot be used as variable names. Such reserved names are: char, weapon, artifact, talent, main (see Built-in Variables for a complete list), and all character, weapon, artifact set, and function names. All built-in names are in snake_case. It is recommended that all user-defined variable names be in Title_Case, i.e. capitalize the first letter of each word and separate the words with underscore (_).

Assignments can be ordered in any anyway, but the variable defined in the first assignment must be the maximizing objective value. GAA will try to maximize this value when choosing the artifacts. This first variable must be visible, i.e. prefixed by $.

GAA calculates the following automatically for you:

  1. Character's base stats, such as ATK, HP, and DEF
  2. Character's ascension stat
  3. C3 and C5 constellation effect
  4. Weapon's base ATK and main stat
  5. Artifact's main stat and sub stats

These must be manually implemented by you:

  1. Character kit, which includes skill, burst, A1, and A4 effects
  2. Weapon passive
  3. Artifact set passive (TODO: I'm considering automating 2-piece passives)
  4. All constellation effects except for C3 and C5

Naming Convention

All character/weapon/artifact set names in GAA follow a naming convention. It is always in lowercase snake_case, words separated by underscores (_). We replace dash (-) and space with an underscore (_), and any other non-alphabet letters are removed. For example, "Amos' Bow" becomes amos_bow and "Key of Khaj-Nisut" becomes key_of_khaj_nisut.

There is one exception to this rule: family names are not used for Inazuman characters. For example, Kamisato Ayaka is ayaka and Yae Miko is miko. However, Liyue characters keep their family name (e.g. Hu Tao is hu_tao). Another, but last special case is raiden for Raiden Shogun.

Traveler must be one of the following:

traveler_anemo
traveler_geo
traveler_electro
traveler_dendro
traveler_hydro
traveler_pyro
traveler_unaligned
Other gender-specific names like lumine_anemo do not work. The character help page provides the charged attack damage numbers for both genders.

See the "Characters" help page for reference.


Character Block

A formula must have one main character block, which is started by main { and ended by }. Inside the character block, we define the character, weapons, artifact sets, and talent multipliers.

char defines a character. Only one character can be defined in a character block. A character definition consists of the following words separated by whitespaces:

Example

char kokomi L90 C1 10/10/10

weapon defines a weapon. At least one weapon must be defined in a character block. GAA allows up to 12 weapons defined in a formula (TODO: GAA is in early alpha, so this number may go up or down). A weapon definition consists of the following words separated by whitespaces:

Example

weapon everlasting_moonglow L90 R1

artifact defines an artifact set to be used by the character. At least one artifact set must be defined in a character block. GAA allows up to 12 artifact sets defined in a formula (TODO: GAA is in early alpha, so this number may go up or down). It may be more accurate to say that the artifact definition defines the farming plan for the simulated accounts. For example, if you specify a 4-piece VV set, the theorycrafter will simulate each account to farm the VV domain for three weeks' worth of resin and strongbox bad artifacts into VV for three weeks as well. After that, the theorycrafter will look for the best 4-piece VV set to equip. An artifact set definition consists of the following words separated by whitespaces:

Example

artifact 4*ocean_hued_clam

How accounts are simulated

Theorycrafter simulates thousands of accounts for each weapon/artifact set pair in order to figure out main stats, sub stats, and variable distributions. This section describes how the simulation works.

A GAA simulated account reaches AR45 after the first 12 weeks and AR55 after another 12 weeks. We define an account to be "active" if they are not wasting any resin and are over AR45. The default "active" number of weeks is 40, which roughly represents a 1-year-old account. We also have a "farming" period where resin is mostly spent on an artifact domain for our specific character. By default, the farming period is 3 weeks. Each simulated account will obtain artifacts from six different sources:

  1. Normal bosses - which drop Wanderer's Troupe or Gladiator's Finale. The default value is 4 5-star artifacts per active week. The probability of a 4-line artifact is 33.3%.
  2. Weekly bosses - which drop Wanderer's Troupe or Gladiator's Finale. The default value is 3 weekly bosses per active week (the actual number of artifacts depends on luck. An extra 5-star artifact is assumed to drop 23% of the time). The probability of a 4-line artifact is 33.3%.
  3. Off-set farming from domain - which represents off-set artifacts that accumulated over the time the account was active. The probability of a 4-line artifact is 20%. The default value is 600 resin spent on artifact domain per active week (the actual number of artifacts depends on luck An extra 5-star artifact is assumed to drop 6.5% of the time), but this can be increased with resin recharge.
  4. Off-set strongbox - which are off-set artifacts that accumulated from strongboxing over the time the account was active. This also includes artifacts obtained from domain reliquaries, which results from Spiral Abyss clears. The probability of a 4-line artifact is 33.3%. The default value is 12 5-star artifacts per active week.
  5. On-set farming from domain - which are actively farmed for our specific character. The probability of a 4-line artifact is 20%. The default value is 1200 resin spent on the artifact domain per farming week (the actual number of artifacts depends on luck An extra 5-star artifact is assumed to drop 6.5% of the time), but this can be increased with resin recharge. This is not available for Wanderer's Troupe or Gladiator's Finale.
  6. On-set strongbox - which is only available for some sets. The probability of a 4-line artifact is 33.3%. The default value is 20 5-star artifacts per farming week.

Artifact quality is then evaluated by Appraiser Value (AV). All artifacts are fully leveled, then artifacts with low AVs are destroyed. (earlier versions of GAA did proper leveling simulations, but they were found to be slow and get to very similar numbers as this crude version). Using these artifacts, GAA looks for the best artifacts to equip that maximize the objective value.

Before the accounts can be simulated, AV weights (scores on main and sub stats) must be calculated. AV weights are computed iteratively by considering the linear gradient of the objective function at the optimal value, which is approximated by simply averaging a bunch of simulated results. Build optimizer is initially set to strict (looks at a lot of artifact combinations), but as AV weights get better, the build optimizer loosens up.

Our objective function is not truly differentiable or even continuous. For instance, crit rate is capped at 100%, so the damage usually climbs linearly as crit rate increases but flattens out at the cap. Also, if a build formula requires 160 ER, the value of the ER substat changes drastically depending on the discrete choice of equipping ER sands. Even so, this crude linear approximation seems to perform well in practice at ranking valuable artifacts. After AV converges, GAA is able to find the correct optimal set >99% of the time by only looking at ~700 combinations (for 4-piece sets).


Formula Version 3

After using version 2 for a few months myself, I would like to implement some new features. Below are some ideas for version 3. Some of these may get implemented, but nothing is set in stone right now. All examples provided below are just idea sketches and the syntax will likely change.

Rotation timing and time-dependent buffs

Some buffs gain/lose stacks as time goes on, such as Furina's fanfare or Mavuika's A4. Also it's annoying in version 2 to separate out attacks that receive certain buffs (e.g. Bennett's burst lasts 12 seconds, so not all damage in a rotation may benefit from it). It would be nice to be able to specify time for each attack instance and duration for each buffs. Sort of like how Kol's Calc Template list all the invisidual hits. Maybe gcsim samples can even be imported eventually.

damage 0 Burst_Damage = talent.Burst_DMG% * atk
buff 0-12 atk += talent.Burst_Buff% * base.atk

Random variables

The Widsith is incredibly annoying to implement right now. Also if an attack is known to vape 60% of the time, it's not nice to show in the build output, because we have to separately output the numbers. These problems can be solved by introducing a "random variable". It doesn't actually use any randomness in the calculation; instead the computation will take every possible realization of the random variable and take avarage (or maximum) at the end. Crits are already handled in a similar manner already, so this should not be too difficult to implement. However, too many random variables can exponentially affect performance. Random variables are pairwise independent and resolve in the reverse order of the declaration.

# widsith random buff. Objective is the maximum of the three (e.g. for screenshot build)
random Widsith_Buff = maximize Recitative Aria Interlude
atk_pct += the_widsith.effect(60 ) * Widsith_Buff.Recitative
hydro   += the_widsith.effect(48 ) * Widsith_Buff.Aria
em      += the_widsith.effect(240) * Widsith_Buff.Interlude

# 60% chance to vape. Objective is the expected damage
random Vape = average Yes(60%) No(40%)
Damage = talent.Hit_DMG% * atk * (Vape.Yes*vape_with_hydro(em) + Vape.No)

Team buff

Maybe team buffs can be parametized so it can actually use your support character's level/weapon/artifact set/talent level/constellation. This way, elemental resonance can be automatically checked as well. This could eventually lead to automatically calculating ER requirement by running energy simulation of the team.

sub {
    char furina L90 C0 9/9/9

	weapon splendor_of_tranquil_waters L90 R1
    weapon favonius_sword L90 R1

    artifact 4*golden_troupe

    talent burst Fanfare_to_DMG_Increase 0.07 0.09 0.11 0.13 0.15 0.17 0.19 0.21 0.23 0.25 0.27 0.29 0.31
}

bonus += furina.talent.Fanfare_to_DMG_Increase * 300
energy += furina.favonius_sword.effect()

Farming parameters

Artifact farming parameters can only be adjusted in the source code as of now. I want to move this out to be configured in the formula text.

main {
    char kokomi L90 C6 10/10/10
    weapon everlasting_moonglow L90 R5
    artifact 4*heart_of_depth

    farming {
        time_active  = 3 year,
        time_farming = 1 year,
        resin_recharge = 5,
        num_weeklies_per_active_week = 3,
        num_bosses_per_active_week = 4,
        num_condensed_domain_per_active_week = 15,
        num_strongbox_per_active_week = 12,
        num_condensed_domain_per_farming_week = 30,
        num_strongbox_per_farming_week = 20,
        farmed_domain = heart_of_depth+blizzard_strayer,
    }
}

Custom Character/Weapon/Artifact Set

GAA should be able to accomodate any character/weapon/artifact set you dream up with little effort.

main {
    char paimon L90 C0 9/9/9 = new char(
        stat_curve=5, atk_1=24.24, atk_90=333.77, hp_1=1234.56, hp_90=12345.67, def_1=50.00, def_90=600.00, 
        ascend_stat=crit_rate, C3=skill, C5=normal, weapon_type=catalyst
    )

    weapon emergency_power L90 R1 = new weapon(star=5, main_stat=atk_pct, main_value=674, weapon_type=catalyst)

    artifact 4*secrets_of_celestia = new artifact(star=5)

    talent normal Normal_DMG = ...
    talent skill Buffmon_Buff = ...
}

maximize Normal_Hit = talent.Normal_DMG% * atk * (bonus%+Light%+normal%) * (1+crit_rate%*crit_dmg%) * defense(100) * resist(10)

Num_Food_Eaten = 3  # eating adeptus temptation, light damage potion, any defense/recovery food
atk_pct += talent.Buffmon_Buff + 20*Num_Food_Eaten*paimon.a1
Light = 50*paimon.a4^{assuming traveller is in the party} + 15*secrets_of_celestia.piece_2 + 25^{light damage potion}
atk_flat += 372  # adeptus temptation
crit_rate += 12  # adeptus temptation

atk_pct += Num_Food_Eaten * emergency_power.effect(20)
bonus   += Num_Food_Eaten * emergency_power.effect(10)

crit_dmg += 70*secrets_of_celestia.piece_4

Localization

Allow outputing the variables names in different languages in preparation for supporting other languages.

# @title On-field Kokomi
# @title-ko 온필드 코코미

$Jelly_Heal^{@trans ko="해파리 힐량"} = (talent.Jelly_Heal_HP% * hp + talent.Jelly_Heal_Flat) * (1+heal%)

Setting

English
Korean

Hu Tao
Kokomi