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

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



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

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

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

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

四个字段的类型都是 `&'a PalaceData`（不是 `PalaceRef`）：
字段可以直接读，[宫位对象](/zh/docs/rust/palace)上那些不需要星盘上下文的方法
（`has`、`is_empty`、`has_mutagen`、`mutagen_stars`）也都能调；
要用 `opposite_palace`、`surrounded_palaces` 这类需要回溯星盘的方法，
拿 `sp.target.index` 再走 `chart.palace(...)` 换成 `PalaceRef`。

<Callout type="info" title="别按结构体里的字段顺序理解偏移">
  `SurroundedPalaces` 声明时 `wealth` 写在 `career` 前面，但偏移是
  `career = +4`、`wealth = +8`。以命宫起算时 +4 落在官禄宫、+8 落在财帛宫，
  名字与偏移是这样对上的。
</Callout>

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

## 三种取法 [#三种取法]

```rust
// 从星盘取
let sp = chart.surrounded_palaces(Palace::Soul).unwrap();

// 从宫位取
let sp = chart.palace(Palace::Soul).unwrap().surrounded_palaces();

// 从星耀取（该星所在宫的三方四正）
let sp = chart.star(StarKey::ZiweiMaj).unwrap().surrounded_palaces();
```

三者结果相同，选哪个取决于手上已有什么。

***

## have / not\_have / have\_one\_of [#have--not_have--have_one_of]

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

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

**签名**

```rust
pub fn have(&self, stars: &[StarKey]) -> bool
pub fn not_have(&self, stars: &[StarKey]) -> bool
pub fn have_one_of(&self, stars: &[StarKey]) -> bool
```

**参数**

| 参数      | 类型           | 必填 | 默认 | 说明     |
| ------- | ------------ | -- | -- | ------ |
| `stars` | `&[StarKey]` | 是  | —  | 星耀标识列表 |

**返回值**

| 方法            | 语义                   |
| ------------- | -------------------- |
| `have`        | 列表中每一颗都出现在这四宫（不要求同宫） |
| `not_have`    | 列表中一颗都没出现            |
| `have_one_of` | 列表中至少一颗出现            |

**示例**

```rust
use x_iztro::StarKey::*;

let sp = chart.surrounded_palaces(Palace::Soul).unwrap();

println!("{}", sp.have(&[ZiweiMaj, TianxiangMaj]));
println!("{}", sp.have_one_of(&[QishaMaj, PojunMaj]));
println!("{}", sp.not_have(&[HuoxingMin]));
```

**输出**

```text
true
false
true
```

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

**边界与陷阱**

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

  <Accordion title="空列表的返回值">
    `have` 与 `not_have` 在空列表下返回 `true`，`have_one_of` 返回 `false`。
  </Accordion>
</Accordions>

***

## have\_mutagen / not\_have\_mutagen [#have_mutagen--not_have_mutagen]

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

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

**签名**

```rust
pub fn have_mutagen(&self, mutagen: Mutagen) -> bool
pub fn not_have_mutagen(&self, mutagen: Mutagen) -> bool
```

**参数**

| 参数        | 类型        | 必填 | 默认 | 说明                             |
| --------- | --------- | -- | -- | ------------------------------ |
| `mutagen` | `Mutagen` | 是  | —  | `Lu` / `Quan` / `Ke` / `Ji` 之一 |

**返回值**　`bool`。

**示例**

```rust
let sp = chart.surrounded_palaces(Palace::Soul).unwrap();

println!("三方四正见禄: {}", sp.have_mutagen(Mutagen::Lu));
println!("三方四正见忌: {}", sp.have_mutagen(Mutagen::Ji));
println!("三方四正不见科: {}", sp.not_have_mutagen(Mutagen::Ke));
```

**输出**

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

这张盘的生年四化落在四宫：太阳化禄在子女、武曲化权在财帛、太阴化科在仆役、天同化忌在疾厄。
命宫的三方四正是命宫、迁移、财帛、官禄——只有化权那一颗落在里面，
因此查禄、查忌都是 `false`，查权则会是 `true`。

**边界与陷阱**

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

***

## to\_text [#to_text]

**用途**　三方四正的语义化文本：`## 本宫名 三方四正` 标题之下，本宫、对宫、财帛位、官禄位各一段，
每段标题带角色前缀（`### 本宫 · 命宫 (壬午) · 大限 3-12`），事实行与本命盘文本中该宫的段落一致。

**签名**

```rust
pub fn to_text(&self) -> String
```

按星盘排盘语言输出；要指定语言用自由函数 `text::surrounded_palaces_to_text(&sp, lang)`。

**示例**

```rust
let sp = chart.surrounded_palaces(Palace::Soul).unwrap();

println!("{}", sp.to_text().lines().next().unwrap());
```

**输出**

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

完整格式见[语义化文本](/zh/docs/guide/guides/to-text)。

***

## to\_text\_with [#to_text_with]

**用途**　四宫每段事实之后紧跟该宫星耀的释义，与单宫的 `to_text_with` 逐段相同。

**签名**

```rust
pub fn to_text_with(&self, opts: &TextOptions) -> String
```

**参数**

| 参数     | 类型             | 必填 | 默认 | 说明                                                                                                                                     |
| ------ | -------------- | -- | -- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `opts` | `&TextOptions` | 是  | —  | 输出选项；`TextOptions::new().knowledge(pack)` 带释义，`TextOptions::default()` 与 `to_text` 等价。见 [TextOptions](/zh/docs/rust/astro#textoptions) |

要指定语言用自由函数 `text::surrounded_palaces_to_text_with(&sp, opts, lang)`。
插入位置见[带释义的文本](/zh/docs/guide/guides/to-text#带释义的文本)。

**示例**

```rust
let pack = KnowledgePack::builtin(Language::ZhCN).unwrap();
let sp = chart.surrounded_palaces(Palace::Soul).unwrap();
let text = sp.to_text_with(&TextOptions::new().knowledge(pack));

println!("{} {}", sp.to_text().chars().count(), text.chars().count());
```

**输出**

```text
924 6312
```
