# NIKKE ASS — query syntax reference

ASS searches ~430k dialogue lines (main story, events, sudden stories, side
stories, bond episodes and advise scripts) across the EN, KO and JA scripts.
EN carries the full ~429k lines; KO and JA carry ~388k each. The filter
builder writes the syntax below for you, so power users can type it directly.

The search runs against **one language at a time** — the EN/KO/JA toggle, or
`lang:` in the query (which wins; anything else falls back to the toggle).
Speaker filters resolve from English data names and speaker keys in every
language.

## Free-text terms

    rapi                    lines containing the word "rapi"
    "counted the days"      exact phrase, adjacency preserved
    comm*                   prefix wildcard (commander, commands…)
    c?me                    ? matches one character (came, come…)

**English terms match whole words.** `rapi` matches the word *rapi*, not
*rapid*; `work` does not match *word*; `or` (quoted: `"or"`) matches only the
word itself, not *order* or *work*. Punctuation splits words, so `rapi` also
matches the possessive *rapi's*, but never a substring like *rapid*. This is
deliberate — substring matching used to flood results with lines merely
containing the same letters.

**KO/JA terms match substrings.** Korean and Japanese are not
whitespace-segmented, so those scripts use character-bigram matching that
behaves exactly like substring search.

- Plain English terms are case-insensitive whole words.
- Quoted phrases keep exact substring semantics (spaces, punctuation, and
  adjacency); a single-word quote behaves as a whole word.
- Wildcards run against the term dictionary: `*` is any run of characters,
  `?` is exactly one. `comm*` uses the index prefix; `*thing` scans it.
- Broad queries are budgeted: patterns or term soups that would expand to a
  large share of the corpus (`*a*`, `a*`, `the OR you OR …`) are rejected with
  `query too broad` — add a more specific word or filter. More than 24 terms
  or field filters is rejected as `query too complex`. Common words are still
  searchable on their own; they stream the release-ordered index.
- The Filters panel's **Text match** selector maps to: *Contains* (whole
  word), *Starts with* (prefix), *Ends with* (suffix), *Exact* (whole-line
  equality). It applies to plain terms only — quoted phrases and wildcards use
  their own semantics.
- Hyphenated and apostrophised terms (`BA-01`, `don't`) match as written;
  quote only phrases and operator words (`"or"`, `"not"`).

## Boolean operators

    space       AND (default)
    OR          either side
    NOT / - / ! exclude — NOT ark, -ark, !ark all work
    ( )         grouping

    speaker:chime to:crown
    (source:overzone OR source:redash) -ark
    kind:event NOT commander
    -kind:bond marian

Operators and field names are case-insensitive (`or`, `Or`, `OR`; `Speaker:`
and `speaker:` both work). To search for the literal word, quote it: `"or"`,
`"not"`.

## Fields

| Field              | Aliases      | Matches                                        |
| ------------------ | ------------ | ---------------------------------------------- |
| `speaker:`         | `from:`      | who is speaking                                |
| `to:`              | —            | who is being addressed                         |
| `portrait:`        | `skin:`      | a specific speaker variant                     |
| `kind:`            | —            | story category                                 |
| `chapter:`         | —            | main story chapter (or event code)             |
| `source:`          | —            | one specific chapter/event                     |
| `year:`            | `released:`  | release year of the source                     |
| `lang:`            | —            | which translation to search (global)           |
| `sort:`            | —            | result order (global)                          |

### speaker: / from:

Matches the speaking character. Characters include all their variants and
aliases:

    speaker:anis           Anis + Anis: Sparkling Summer + Anis: Star …
    speaker:marian         Marian, Modernia, and every variant
    speaker:commander      the player (Self / <Self> lines)

A few names alias into others: `modernia` (and the misspelling `modenia`)
finds Marian, and `lilith` finds Liliweiss.

Values are English data names or speaker keys (`crown_n`). `from:` is the
same field under the name the filter builder uses — handy next to `to:`.

### to:

Matches lines where the character is the **addressee**. ASS infers
addressees at ingest time from:

- **Scene pairing** — scenes with exactly two participants: every line one of
  them speaks is addressed to the other.
- **Vocatives** — lines that name someone: `Chime, watch out!`,
  `Hey Chime!`, `… right, Chime?`

Narration, monologue and choice lines are never matched as addressees.
Inference always runs on the English script, so results are the same in every
language. `to:` is a heuristic — great for "find where X talks to Y", not an
official script annotation.

    to:crown
    speaker:chime to:crown
    to:commander

### portrait: / skin:

Matches one specific variant rather than the whole character:

    portrait:crown_n       the Crown variant with key crown_n
    portrait:330           every variant sharing resource 330

### kind:

    kind:main              main story (also scene, story)
    kind:event             archive events (also events, archive)
    kind:sudden            sudden stories
    kind:side              side stories (also sidestory, sidestories)
    kind:bond              bond episodes (also bonds)
    kind:advise            advise / counsel scripts (also advice, counsel,
                           counseling)
    kind:relic             Lost Relics collectible lore (also relics,
                           memorial, memorials)

Advise scripts are searchable but are not one of the builder's Content
checkboxes — type `kind:advise` to reach them. Lost Relics have their own
Content checkbox and open in the relic browser rather than the transcript.

### chapter:

Numbers target main story chapters; text targets event codes:

    chapter:12             main story chapter 12
    chapter:[10 TO 20]     chapters 10–20 (inclusive)
    chapter:>=40           chapter 40 and up
    chapter:overzone       the Overzone event (same as source:overzone)

Ranges use `[ ]` for inclusive and `{ }` for exclusive bounds:
`chapter:{10 TO 20]`.

### source:

A single chapter or event:

    source:overzone        event code
    source:22              main story chapter 22 (by number)
    source:#139            internal id (shown when you filter from the reader)

### year: / released:

Filters by the release year of the chapter or event the line belongs to:

    year:2023              lines from sources released in 2023
    year:[2019 TO 2021]    inclusive year range
    year:>=2024            everything from 2024 on
    rapi year:<2021        early Rapi lines only

Caveat: sources without a known release date are ordered just after the
newest dated source, so the most recent years include undated material.

### lang: (global)

Overrides the language toggle for this search. Only one language is searched
per query:

    lang:ja 指揮官         search the JA script for 指揮官
    lang:ko rapi           search the KO script for "rapi"

### sort: (global)

    sort:new               newest release first (also desc, latest)
    sort:old               oldest first (the default)

## Combining fields

Fields are AND'd unless you group with `OR`:

    speaker:chime to:crown                  Chime speaking to Crown
    (speaker:anis OR speaker:neon) kind:event
    speaker:marian "BA-01" -kind:bond       the BA-01 line, not bond episodes

## Filter builder

The **Filters** panel builds these tokens for you: its From/To/Portrait/
Chapter/Release-year and Exclude inputs map to `from:`/`to:`/`portrait:`/
`source:`/`year:` and `-` terms, the Content checkboxes map to `kind:`, and
Sort maps to `sort:`. The query preview under the builder shows the text it
will produce.

**Convert to query** turns the current panel state into a text query you can
edit by hand. **Copy link** shares the same filters as a URL, so a filter-only
search (`/?kind=bond`, `?speaker=marian&kind=scene`) reproduces without any
text.

Two builder controls are global settings rather than query tokens: the
language toggle and **Text match**. Text match applies to plain terms only;
quoted phrases and wildcards use their own semantics.

## Gated content

Scenes from sources the game has not released yet are excluded from search
(snippets are spoilers) and locked in the reader until the acknowledgment
phrase is entered. Gated sources are badged in the sidebar; there is no query
syntax to unlock them — the gate lifts on its own at release.
