# 三方四正 (/zh/docs/go/surpalaces)

SurroundedPalaces 的四个宫位与五个判断方法。



三方四正是斗数最常用的取象范围。看一件事不能只看本宫，
对宫与两个三合宫的星耀同样作用其上，四宫合看才完整。

<Callout type="info">
  本页示例统一用 `"zh-CN"` 排盘，因此输出里的展示值都是中文。
</Callout>

## 四个宫位 [#四个宫位]

| 字段         | 相对本宫 | 传统称呼 | 意义             |
| ---------- | ---- | ---- | -------------- |
| `Target`   | +0   | 本宫   | 事情本身           |
| `Opposite` | +6   | 对宫   | 与本宫相对的一面，影响最直接 |
| `Career`   | +4   | 官禄位  | 三合之一           |
| `Wealth`   | +8   | 财帛位  | 三合之一           |

四个字段都是 `*Palace`，[宫位对象](/zh/docs/go/palace)的全部方法都能用。

<Callout type="info" title="财帛位、官禄位是相对称呼">
  `Wealth` 与 `Career` 指的是「相对本宫的三合位置」，不是十二宫里那两个固定的宫名。
  以命宫起算时它们恰好落在财帛宫与官禄宫（+8 与 +4），名字就是这么对上的；
  以别的宫起算则是别的宫。
</Callout>

## 四种取法 [#四种取法]

```go
// 从星盘按宫名取
byName := chart.SurroundedPalaces(iztro.PalaceSoul)

// 从星盘按索引取
byIndex := chart.SurroundedPalacesByIndex(4)

// 从宫位取
fromPalace := chart.Palace(iztro.PalaceSoul).SurroundedPalaces()

// 从星耀取（该星所在宫的三方四正）
ziwei, _ := chart.Star(iztro.StarZiweiMaj)
fromStar := ziwei.SurroundedPalaces()

fmt.Println(byName.Target.Name, byIndex.Target.Name,
    fromPalace.Target.Name, fromStar.Target.Name)
```

**输出**

```text
命宫 命宫 命宫 命宫
```

命宫落在索引 4、紫微又正坐命宫，因此四种取法在这张盘上给出同一组三方四正；
选哪个取决于手上已有什么。

<Callout type="warn" title="按索引取会对 12 取模，按名字取不会">
  `SurroundedPalacesByIndex` 对索引取模，因此 `-1`、`12` 都能正确回绕；
  但**零值星盘**（未经排盘构造出来的 `Astrolabe`）没有十二宫，此时返回 `nil`。
  `SurroundedPalaces` 收名字，拼错返回 `nil`。两者都要判空再取字段。
</Callout>

***

## Have / NotHave / HaveOneOf [#have--nothave--haveoneof]

**用途**　判断四宫合起来有没有指定星耀。

**斗数含义**　「三方四正见紫微」这类说法，问的正是这四宫里出没出现某颗星，
而不问具体落在其中哪一宫。

**签名**

```go
func (sp *SurroundedPalaces) Have(stars ...string) bool
func (sp *SurroundedPalaces) NotHave(stars ...string) bool
func (sp *SurroundedPalaces) HaveOneOf(stars ...string) bool
```

**参数**

| 参数      | 类型          | 必填 | 默认 | 说明        |
| ------- | ----------- | -- | -- | --------- |
| `stars` | `...string` | 是  | —  | 星耀标识，可变参数 |

**返回值**

| 方法          | 语义                   |
| ----------- | -------------------- |
| `Have`      | 列出的每一颗都出现在这四宫（不要求同宫） |
| `NotHave`   | 列出的一颗都没出现            |
| `HaveOneOf` | 列出的至少一颗出现            |

**示例**

```go
sp := chart.SurroundedPalaces(iztro.PalaceSoul)

fmt.Println(sp.Have(iztro.StarZiweiMaj, iztro.StarTianxiangMaj))
fmt.Println(sp.HaveOneOf(iztro.StarQishaMaj, iztro.StarPojunMaj))
fmt.Println(sp.NotHave(iztro.StarHuoxingMin))
```

**输出**

```text
true
false
true
```

紫微在命宫、天相在财帛宫，分处两宫但都在这四宫内，因此 `Have` 为真。

**边界与陷阱**

<Accordions>
  <Accordion title="Have 不要求同宫">
    `Have(A, B)` 的语义是「A 和 B 都出现在这四宫里」，
    不要求它们坐在同一宫。要判断同宫，用宫位的 [`Has`](/zh/docs/go/palace#has--nothave--hasoneof)。
  </Accordion>

  <Accordion title="不传星耀时的返回值">
    `Have` 与 `NotHave` 返回 `true`，`HaveOneOf` 返回 `false`。
  </Accordion>
</Accordions>

***

## HaveMutagen / NotHaveMutagen [#havemutagen--nothavemutagen]

**用途**　判断四宫里有没有某种生年四化。

**斗数含义**　「三方四正见忌」意味着这组宫位里坐着一颗被生年干化忌的星，
是判断压力来源的常用条件。

**签名**

```go
func (sp *SurroundedPalaces) HaveMutagen(mutagenKey string) bool
func (sp *SurroundedPalaces) NotHaveMutagen(mutagenKey string) bool
```

**参数**

| 参数           | 类型       | 必填 | 默认 | 说明     |
| ------------ | -------- | -- | -- | ------ |
| `mutagenKey` | `string` | 是  | —  | 四化标识之一 |

**返回值**　`bool`。

**示例**

```go
sp := chart.SurroundedPalaces(iztro.PalaceSoul)

fmt.Println("三方四正见禄:", sp.HaveMutagen(iztro.MutagenLu))
fmt.Println("三方四正见忌:", sp.HaveMutagen(iztro.MutagenJi))
fmt.Println("三方四正不见科:", sp.NotHaveMutagen(iztro.MutagenKe))
```

**输出**

```text
三方四正见禄: false
三方四正见忌: false
三方四正不见科: true
```

这张盘的生年四化落在子女、迁移、疾厄三宫，都不在命宫的三方四正内。

**边界与陷阱**

<Callout type="info">
  这里看的是**生年四化**打在星上的标记，与宫干飞出的四化无关。
  后者请用宫位的飞星族方法。
</Callout>

***

## 语义化文本 [#语义化文本]

三方四正文本不在 `*SurroundedPalaces` 上，而是星盘方法
[`SurroundedPalacesToText`](/zh/docs/go/astrolabe#totext--palacetotext--surroundedpalacestotext)：

```go
text, _ := chart.SurroundedPalacesToText(iztro.PalaceTarget{Key: iztro.PalaceSoul})
withNotes, _ := chart.SurroundedPalacesToTextWith(iztro.PalaceTarget{Key: iztro.PalaceSoul},
    iztro.TextOptions{Knowledge: iztro.BuiltinKnowledge()})

fmt.Println(strings.Split(text, "\n")[0])
fmt.Println(utf8.RuneCountInString(text), utf8.RuneCountInString(withNotes))
```

**输出**

```text
## 命宫 三方四正
924 6312
```

文本以 `## 命宫 三方四正` 起，下接本宫、对宫、财帛位、官禄位四段，每段标题带角色前缀
（`### 本宫 · 命宫 (壬午) · 大限 3-12`、`### 对宫 · 迁移 (戊子) · 大限 63-72`），事实行与本命文本里该宫的段落一致；
`SurroundedPalacesToTextWith` 在每宫事实行之后紧跟该宫星耀的释义，
`opts` 见 [TextOptions](/zh/docs/go/knowledge#textoptions)。
