Patterns
Pattern hits on natal and horoscope charts, the PatternConfig readings, the Pattern constants, and error handling.
A pattern (格局) is the recognition of a named star arrangement on a chart. The same 64 rules are judged on natal charts and on horoscope views. For what patterns are and each rule's condition and source, see the concept page.
chart, err := iztro.BySolar("1985-5-3", 9, iztro.GenderMale, true, iztro.LanguageEnUS, nil)
hits, err := chart.Patterns(nil)The examples on this page all start from an "en-US" natal chart, so the display values in the
output are the English translations.
Types
PatternHit
| Field | Type | Meaning |
|---|---|---|
Key | string | Language-independent pattern key; its values are the PatternXxx constants |
Name | string | Pattern name, translated to the chart's language |
Scope | string | The view it was judged in: ScopeOrigin for natal, otherwise that level |
PalaceIndex | int | Slot of the palace where the pattern formed (0-11, Yin palace is 0) |
PalaceName | string | That palace's name in this view |
PalaceNameKey | string | The palace key; its values are the PalaceXxx constants |
Variant | string | Which reading matched; empty for single-reading patterns |
Broken | bool | Whether the "spoiled by malefics" condition fired. The hit is reported either way; this is only a flag |
Stars | []PatternStar | The stars evidencing the pattern, with their palaces |
Three methods:
| Method | Meaning |
|---|---|
Is(patternKey string) bool | Whether this is the given pattern; pass a constant such as PatternShaPoLang |
InPalace(nameKeyOrName string) bool | Whether the forming palace is the given one; pass a palace key or the name in the chart's language |
String() string | Name(palace) or Name(palace,variant), for logs and debugging |
PatternStar
| Field | Type | Meaning |
|---|---|---|
Key | string | Language-independent star key |
Name | string | Star name, translated to the chart's language |
PalaceIndex | int | The slot the star actually occupies (when borrowed, not the borrowing palace) |
Brightness / BrightnessKey | string | Brightness display text and key; empty when the star has none |
Mutagen / MutagenKey | string | The mutagen in this view, and its key; empty when there is none |
PatternConfig
The reading switches. Anything that is merely a second form of the same pattern goes through
PatternHit.Variant; only data readings that change the finding of fact itself live here, which
is why there are just three fields.
type PatternConfig struct {
BrightnessSource string // BrightnessSourceTable (default) or BrightnessSourcePositional
Borrow *bool // whether an empty palace borrows the opposite palace's majors; nil takes the core default true
FlowStars *bool // whether flowing stars count as their natal counterparts; nil takes the core default true
}
func Bool(v bool) *bool // convenience: a bool literal's address
func DefaultPatternConfig() *PatternConfig // the default reading with every field explicitThe two booleans are *bool: nil means "not stated" and the core takes its default true;
switch one off explicitly with iztro.Bool(false). DefaultPatternConfig() returns
{BrightnessSourceTable, Bool(true), Bool(true)}, which means the same as passing nil.
BrightnessSourceTable follows the chart's brightness table (Miao and Wang bright, Xian and Bu dim —
matching iztro value for value); BrightnessSourcePositional follows the traditional placement (Sun
bright Yin–Wu, dim You–Chou; Moon bright You–Chou, dim Mao–Wei). The trade-off is explained on the
concept page.
The zero value is the default reading
All three fields of &iztro.PatternConfig{} are zero values (empty string and nil), which means
exactly what passing nil means. To change one thing, write a literal — whatever you leave out
keeps the core default:
cfg := &iztro.PatternConfig{BrightnessSource: iztro.BrightnessSourcePositional}
onlyNatal := &iztro.PatternConfig{FlowStars: iztro.Bool(false)}Pattern constants
Every one of the 64 pattern keys has a named constant, Pattern plus the pinyin in camel case:
PatternShaPoLang, PatternFuXiangChaoYuan, PatternFengYunJiHui and so on, valued exactly as
PatternHit.Key. Always test patterns against the constants, never against Name — Name follows
the chart's language, Key does not.
Patterns
Purpose Every pattern hit on the natal chart.
In Zi Wei terms Lists every named star arrangement that holds on this chart, together with the palace it formed in and the stars that evidence it.
Signature
func (a *Astrolabe) Patterns(config *PatternConfig) ([]PatternHit, error)
func (a *Astrolabe) PatternsContext(ctx context.Context, config *PatternConfig) ([]PatternHit, error)Parameters
| Parameter | Type | Required | Default | Meaning |
|---|---|---|---|---|
config | *PatternConfig | yes | — | The reading; pass nil for the default |
ctx | context.Context | for the Context form | — | Cancels the wait for a wasm instance |
Returns []PatternHit in the source page's entry order; an empty slice when nothing holds. The
two transit patterns (禄衰马困 lu_shuai_ma_kun, 风云际会 feng_yun_ji_hui) never appear on a natal chart.
Errors
| Case | Error |
|---|---|
| Nil astrolabe | iztro: patterns: nil astrolabe |
BrightnessSource is neither of the valid values | iztro: invalid patternConfig: unknown variant ... |
Both are of the ErrInvalidArgument class and match with errors.Is.
Example
chart, _ := iztro.BySolar("1985-5-3", 9, iztro.GenderMale, true, iztro.LanguageEnUS, nil)
hits, _ := chart.Patterns(nil)
for _, h := range hits {
fmt.Printf("%s %d %s broken=%v\n", h.Name, h.PalaceIndex, h.PalaceName, h.Broken)
}Output
General and Wolf Together 11 surface broken=false
Empress and Minister Facing the Palace 5 soul broken=false
Marshal, Rebel and Wolf 11 surface broken=false
Money and Horse Galloping Together 5 soul broken=false
Officer and Helper Flanking Life 5 soul broken=false
Literary Nobility and Brilliance 11 surface broken=false
Literary Stars Facing Life 5 soul broken=true
Literary Stars in Hidden Support 5 soul broken=false
Literary Stars in Hidden Support 5 soul broken=falseTaking one hit and reading its evidence:
for _, h := range hits {
if !h.Is(iztro.PatternFuXiangChaoYuan) {
continue
}
fmt.Println(h, h.Variant, h.InPalace(iztro.PalaceSoul))
for _, s := range h.Stars {
fmt.Printf(" %s %d %s %s\n", s.Name, s.PalaceIndex, s.Brightness, s.BrightnessKey)
}
}Empress and Minister Facing the Palace(soul,soul_empty) soul_empty true
empress 9 [+1] de
minister 1 [-3] xianJudging under an explicit reading:
chart, _ := iztro.BySolar("1985-1-5", 11, iztro.GenderFemale, true, iztro.LanguageEnUS, nil)
cfg := &iztro.PatternConfig{BrightnessSource: iztro.BrightnessSourcePositional}
a, _ := chart.Patterns(nil)
b, _ := chart.Patterns(cfg)
fmt.Println(names(a)) // names collects each hit's Name
fmt.Println(names(b))[Money and Horse Galloping Together Officer and Helper Flanking Life Sitting on and Facing Nobility]
[Sun and Moon Both Bright Money and Horse Galloping Together Officer and Helper Flanking Life Sitting on and Facing Nobility]Edges and traps
Horoscope.Patterns
Purpose Pattern hits in the view of one horoscope level.
In Zi Wei terms Takes that level's palace as the Soul palace, merges in that level's flowing stars and mutagens, and runs every rule again. This is how "if the natal chart has the arrangement and the decadal then arrives at it, its benefit is enjoyed" is computed.
Signature
func (h *Horoscope) Patterns(scope string, config *PatternConfig) ([]PatternHit, error)
func (h *Horoscope) PatternsContext(ctx context.Context, scope string, config *PatternConfig) ([]PatternHit, error)Parameters
| Parameter | Type | Required | Default | Meaning |
|---|---|---|---|---|
scope | string | yes | — | The level whose view to judge in; pass a constant such as ScopeDecadal |
config | *PatternConfig | yes | — | The reading; pass nil for the default |
Returns []PatternHit, each carrying the level passed in as its Scope. Passing ScopeOrigin
gives exactly what Patterns(nil) on the astrolabe gives.
Errors A horoscope not created by Astrolabe.Horoscope returns
iztro: horoscopePatterns: horoscope must be created by Astrolabe.Horoscope; an unrecognised
scope returns unknown scope.
Example
chart, _ := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageEnUS, nil)
h, _ := chart.Horoscope("2025-6-1", 0)
hits, _ := h.Patterns(iztro.ScopeDecadal, nil)
for _, x := range hits {
fmt.Printf("%s %s %q\n", x.Name, x.Scope, x.Variant)
}Output
Marshal, Rebel and Wolf decadal ""
Meeting of Wind and Cloud decadal ""
Meeting of Wind and Cloud decadal "yearly"The natal view of that same chart holds only "Empress and Minister Facing the Palace" — the Marshal-Rebel-Wolf pattern holds at this level only because the decadal moved the Soul palace.
Edges and traps
Serialisation
The JSON tags on PatternHit and PatternStar are the binding DTO's key names, so
encoding/json produces exactly the structure the Rust and Python sides produce:
chart, _ := iztro.BySolar("1985-5-3", 9, iztro.GenderMale, true, iztro.LanguageEnUS, nil)
hits, _ := chart.Patterns(nil)
for _, hit := range hits {
if !hit.Is(iztro.PatternFuXiangChaoYuan) {
continue
}
b, _ := json.MarshalIndent(hit, "", " ")
fmt.Println(string(b))
}{
"key": "fu_xiang_chao_yuan",
"name": "Empress and Minister Facing the Palace",
"scope": "origin",
"palaceIndex": 5,
"palaceName": "soul",
"palaceNameKey": "soulPalace",
"variant": "soul_empty",
"broken": false,
"stars": [
{
"key": "tianfuMaj",
"name": "empress",
"palaceIndex": 9,
"brightness": "[+1]",
"brightnessKey": "de"
},
{
"key": "tianxiangMaj",
"name": "minister",
"palaceIndex": 1,
"brightness": "[-3]",
"brightnessKey": "xian"
}
]
}PatternsToText / Horoscope.PatternsToText
Purpose The pattern hits as semantic text, one per line: pattern name, landing palace, forming
stars, with broken patterns marked [Broken].
Signature
func (a *Astrolabe) PatternsToText(config *PatternConfig) (string, error)
func (h *Horoscope) PatternsToText(scope string, config *PatternConfig) (string, error)Each has a Context variant. The same judgment as Patterns (including re-anchoring context and
judging criteria); the horoscope version writes palace names as re-laid out at that scope, and nil
for config takes the default criteria.
Example
text, _ := chart.PatternsToText(nil)
fmt.Print(text)Output
- Empress and Minister Facing the Palace(soul): empress([+3]), minister([+3])The chart's and the horoscope's ToText each already carry a patterns section; the standalone call
suits cases that want only the pattern summary.