Hint assignment
Hint assignment gives every target in a frozen scene a short keyboard label. It runs
once, inside HintSession::freeze in src/interaction/hints.cpp, when the user
activates a session. It does not run on the scene or display cadence.
The labels must satisfy one rule: no label is a prefix of another. Without that rule the session could not act on a short label immediately, because a longer label might still be forming. With it, every keystroke sequence resolves to exactly one target the moment its last symbol arrives.
Ordering
Targets are sorted before labels are assigned, so the shortest labels go to the targets the user is most likely to want. The reference point and seed are profile values supplied by the host at pipeline initialization or settings refresh, not sampled at activation:
pointerpriority sorts by Manhattan distance from the profile’s pointer position.scope_centerpriority sorts by distance from the profile’s center point, which the host currently supplies as the desktop center.randomizedpriority hashes each stable target id with the profile’s seed, so labels stay stable until the settings change.- Otherwise targets keep their scene order.
Ties always break on the stable target id so the same scene produces the same labels.
Label construction
Let A be the alphabet size and count the number of targets.
If count <= A, every target gets a single symbol and the construction ends.
Otherwise the code is built in two tiers:
depthis chosen so thatcapacity = A^depthis the largest power of the alphabet that does not exceedcount(withdepth >= 1). A full code of lengthdepthcan namecapacitytargets.- The shortfall
needed = count - capacityis covered by expanding parents. Expanding one length-depthcode into itsAchildren trades one usable label forAlonger ones, a net gain ofA - 1. Soexpanded_parents = ceil(needed / (A - 1)), and when the division is not exact the last parent is only partially expanded withremainder + 1children (+ 1because the parent also gives up its own label).
Ranks below shortest_count = capacity - expanded_parents receive their rank encoded
as a length-depth label. Higher ranks receive an expanded parent’s code plus one
child symbol, filling the partial parent first. The result is prefix-free because an
expanded parent’s bare code is never issued, and all other labels have equal length.
The arithmetic lives in HintSession::freeze (tier sizing) and assign_label
(rank-to-label mapping). Changing the alphabet size or the maximum target count only
requires that A >= 2 and that HintLabel::symbols can hold depth + 1 symbols.
Selection
Selection reduces the candidate set one symbol at a time with case-insensitive
comparison (prefix_matches). Because the code is prefix-free, a full match is
always unambiguous and can fire immediately.
Source: View the pinned source · Edit this source