专名本土化(信达雅):冻结译名表 + 渲染层,并修掉校验器的正则盲点

- 新增 dfannals/glossary.py(译名表)与 dfannals/localize.py(渲染层)
  人名=音译+绰号意译(Ral Fastenhatchets→拉尔·缚斧、朗古德·商熊「剖胎之寒」),
  地名整体意译(Fordedwinds→涉风渡、The Volcano Of Ravens→渡鸦火山)
- 生成链路本土化:素材渲染、人物表、扩写白名单全部走译名;已有产物做确定性替换
- 修复 factcheck 的 \b 盲点:Unicode 下汉字也算词字符,紧贴汉字的英文名不被检查
  (曾因此漏掉编造专名)。修好后抓出并定点修掉长版第 1 集的 2 处编造
- 修正 title_form 大小写(YETI→Yeti),此前 Yeti/Goblin 一直漏译
- 新增 tests/test_localize.py(13 项回归)
This commit is contained in:
Chen Yi
2026-10-05 22:39:53 +08:00
parent 8630dcad55
commit 16b476167e
14 changed files with 924 additions and 350 deletions
+3 -2
View File
@@ -15,7 +15,7 @@ import re
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from dfannals import factcheck from dfannals import factcheck, localize
from dfannals.config import MAX_TOKENS_STRUCTURED, Gateway from dfannals.config import MAX_TOKENS_STRUCTURED, Gateway
from dfannals.episodes import Episode from dfannals.episodes import Episode
from dfannals.legends import Event, World from dfannals.legends import Event, World
@@ -221,7 +221,8 @@ def build_cast(
"", "",
] ]
return "\n".join(lines) + "\n", rows, suspicions # 专名本土化:表格与小传都输出中文译名
return localize.for_world(world).render("\n".join(lines)) + "\n", rows, suspicions
def write_cast(path: Path, text: str) -> Path: def write_cast(path: Path, text: str) -> Path:
+6 -4
View File
@@ -18,7 +18,7 @@ from collections import Counter
from dataclasses import replace from dataclasses import replace
from pathlib import Path from pathlib import Path
from dfannals import deslop, volume from dfannals import deslop, localize, volume
from dfannals import episodes as ep_mod from dfannals import episodes as ep_mod
from dfannals.chronicle import cjk_length from dfannals.chronicle import cjk_length
from dfannals.config import ( from dfannals.config import (
@@ -100,14 +100,16 @@ def allowed_names(world: World, thread: Thread, episode: ep_mod.Episode) -> list
names.add(name) names.add(name)
figure = world.figures.get(fid) figure = world.figures.get(fid)
if figure and figure.race: if figure and figure.race:
names.add(figure.race) # 种族值也要给中文:模型引到雪人、鹰人这类词时不能写成新角色
names.add(_title_form(figure.race)) names.add(localize.translate_race(figure.race))
for event in episode.events: for event in episode.events:
for ref in world.render_refs(event): for ref in world.render_refs(event):
value = ref.partition("=")[2].strip() value = ref.partition("=")[2].strip()
if value: if value:
names.add(value) names.add(value)
return sorted(n for n in names if n) # 全部过一遍译名表:白名单里必须是正文里真正会出现的写法
translator = localize.for_world(world)
return sorted({tr for tr in (translator.render(n).strip() for n in names) if tr})
def chunk_messages( def chunk_messages(
+4 -1
View File
@@ -35,7 +35,10 @@ COMMON_WORDS = {
} }
# 拉丁专名序列:首字母大写的词,可含 ' - 与数字 # 拉丁专名序列:首字母大写的词,可含 ' - 与数字
NAME_RE = re.compile(r"\b[A-Z][A-Za-z'\-]*(?:\s+[A-Z][A-Za-z'\-]*)*\b") # 英文专名的边界不能用 \b:Unicode 下汉字也算「词字符」,于是 `在Mistbreath的`
# 这种紧贴汉字的英文名根本不会被匹配——实测正是这个盲点让一个编造的地名混过了校验。
# 改成前后看「是不是英文字母」,与汉字相邻也能抓到。
NAME_RE = re.compile(r"(?<![A-Za-z])[A-Z][A-Za-z'\-]*(?:\s+[A-Z][A-Za-z'\-]*)*(?![A-Za-z])")
_CJK = re.compile(r"[\u4e00-\u9fff]") _CJK = re.compile(r"[\u4e00-\u9fff]")
+208
View File
@@ -0,0 +1,208 @@
"""专名译名表(冻结)。
为什么要有这张表:正文里满屏 `Ral Fastenhatchets`、`Fordedwinds` 对中文读者很难读。
但如果交给模型每次现译,同一个角色会在第 3 集变成另一个名字,所以译名必须冻结在这里。
翻译策略(信达雅):
1. **人名 = 名字音译 + 姓氏/绰号意译**,用「·」连接。
这与《魔戒》把 Thorin Oakenshield 译作「索林·橡木盾」是同一套惯例,
读起来像中国人名,又保住了原名的意思。
2. **地名整体意译**。DF 地名同样是词表拼接(Fordedwinds = forded + winds),
直译成「涉风渡」比音译成「福德温兹」更像地名。
3. **称号(the X of Y)单独译**,DF 给传奇人物的长称号自带画面感,直译最好。
DF 的名字由词表拼接而成,所以同一批词根会在不同世界反复出现:
这张表按「整词」而非「词根」收词,避免把 Fateddie 硬拆成"命定+死"这类生硬堆叠。
遇到表里没有的名字,localize 会原样保留并登记进待译清单,而不是硬造一个。
"""
# ------------------------------------------------------------------ 名字词干(音译)
STEMS: dict[str, str] = {
"alath": "阿拉斯",
"amxu": "阿姆苏",
"ana": "安娜",
"artuk": "阿图克",
"asmel": "阿斯梅尔",
"astri": "阿斯特里",
"domas": "多马斯",
"dostngosp": "多斯特恩戈斯普",
"ducim": "杜西姆",
"espu": "埃斯普",
"evala": "埃瓦拉",
"guspu": "古斯普",
"id": "伊德",
"ineth": "伊内斯",
"ingish": "英吉什",
"langgud": "朗古德",
"lolor": "洛洛尔",
"meng": "蒙",
"moldath": "莫尔达斯",
"momuz": "莫穆兹",
"mosus": "莫苏斯",
"mudi": "穆迪",
"ngokang": "恩戈康",
"ngom": "恩戈姆",
"niri": "尼里",
"nithe": "尼瑟",
"ongu": "翁古",
"onul": "奥努尔",
"pari": "帕里",
"perom": "佩罗姆",
"ral": "拉尔",
"rigoth": "里戈斯",
"sathrel": "萨瑟雷尔",
"sayrsnis": "赛尔斯尼斯",
"shosa": "绍萨",
"sina": "西娜",
"someg": "索梅格",
"song": "松",
"stinthad": "斯廷哈德",
"tekkud": "泰库德",
"thrun": "斯伦",
"tirist": "提里斯特",
"tulon": "图隆",
"uknol": "乌克诺尔",
"usel": "乌塞尔",
"utes": "乌特斯",
"zuntir": "尊提尔",
"zutthan": "祖坦",
}
# ------------------------------------------------------------------ 姓氏/绰号(意译)
# 键是姓名后半段的拼接结果(小写、无空格)
SURNAMES: dict[str, str] = {
"baldedattic": "秃阁",
"basementrampart": "地垒",
"blazedbrushes": "焰刷",
"blottedmine": "污矿",
"bonestands": "骨立",
"bronzescorched": "铜焦",
"churchbrass": "堂铜",
"clappedbrass": "拍铜",
"crazeowned": "狂据",
"decentpage": "端页",
"dyesong": "染歌",
"fastenhatchets": "缚斧",
"fateddie": "命终",
"fencefinders": "篱寻",
"fisherfair": "渔市",
"flayerline": "剥血",
"frillyknots": "褶结",
"glimmeredhelps": "光援",
"glowroofs": "光顶",
"gleamcircled": "光环",
"growllie": "吼卧",
"hammershake": "锤摇",
"huggedfastened": "抱固",
"incenselyrics": "香诗",
"jackalbrims": "豺帽",
"matchedmenaces": "匹凶",
"menacedslinks": "危潜",
"mirroredfloors": "镜层",
"oilshove": "油推",
"palmsaved": "掌救",
"playfills": "戏填",
"ruinedhorrors": "毁怖",
"searcheddated": "寻期",
"squirtlocks": "喷锁",
"steelgrouped": "钢聚",
"stilledearthen": "静土",
"stolendipped": "窃浸",
"strikepaints": "击彩",
"talonhollows": "爪穴",
"theatercrested": "剧冠",
"thornticks": "棘蜱",
"tongswall": "钳墙",
"tradebears": "商熊",
"walkclasped": "行扣",
"watchedleads": "守铅",
"wheeleddrinks": "轮饮",
"wisdomskins": "智皮",
"yellplank": "啸板",
}
# ------------------------------------------------------------------ 地名(整体意译)
PLACES: dict[str, str] = {
"clampokes": "钳戳",
"fordedwinds": "涉风渡",
"fuchsiarumor": "紫谣",
"gloryholes": "荣耀穴",
"lashheroes": "鞭雄",
"leapdrinks": "跃饮",
"liecats": "卧猫",
"mortalpears": "殇梨",
"paperhushed": "纸寂",
"rainseduced": "雨诱",
"tomessoldiers": "典兵",
"toolfainted": "器昏",
"walkedbirds": "行鸟",
}
# ------------------------------------------------------------------ 称号(the X of Y)
EPITHETS: dict[str, str] = {
"the eviscerated chill of pregnancies": "剖胎之寒",
"the trickery of mornings": "晨之诡计",
}
# ------------------------------------------------------------------ 势力/组织
GROUPS: dict[str, str] = {
"the volcano of ravens": "渡鸦火山",
}
# ------------------------------------------------------------------ 种族
RACES: dict[str, str] = {
"AARDVARK_MAN": "土豚人",
"ALLIGATOR": "鳄鱼",
"ALLIGATOR_MAN": "鳄人",
"BAT_GIANT": "巨蝠",
"BEAR_BLACK": "黑熊",
"BEAR_GRIZZLY": "灰熊",
"BEAR_GRIZZLY_MAN": "灰熊人",
"BEAR_POLAR": "白熊",
"BIRD_OWL_GREAT_HORNED": "大雕鸮",
"BIRD_ROC": "大鹏",
"BIRD_WREN": "鹩鹪",
"BLIND_CAVE_BEAR": "盲穴熊",
"BLIND_CAVE_OGRE": "盲穴食人魔",
"BOBCAT": "山猫",
"CAMEL_1_HUMP_MAN": "单峰驼人",
"CARDINAL_MAN": "红衣主教雀人",
"CAVE_DRAGON": "穴龙",
"CHEETAH": "猎豹",
"CHINCHILLA_MAN": "绒鼠人",
"COLOSSUS_BRONZE": "青铜巨像",
"COUGAR": "美洲狮",
"CYCLOPS": "独眼巨人",
"DOG": "犬",
"DWARF": "矮人",
"EAGLE_MAN": "鹰人",
"ELEPHANT": "象",
"ELF": "精灵",
"FALCON": "隼族",
"GOAT_MOUNTAIN_MAN": "山羊山人",
"GOBLIN": "哥布林",
"HUMAN": "人类",
"HYDRA": "九头蛇",
"JAGUAR": "美洲豹",
"KOBOLD": "狗头人",
"LEOPARD": "豹",
"LION": "狮",
"TIGER": "虎",
"TROLL": "巨魔",
"WOLF": "狼",
"YETI": "雪人",
}
# ------------------------------------------------------------------ 地点类型
SITE_TYPES: dict[str, str] = {
"cave": "洞穴",
"dark fortress": "黑堡",
"dark pits": "幽坑",
"forest retreat": "林居",
"fortress": "要塞",
"hamlet": "村落",
"hillocks": "丘屯",
"tomb": "陵墓",
"town": "城镇",
}
+240
View File
@@ -0,0 +1,240 @@
"""专名本土化:把史料里的英文专名翻成中文(只作用于显示层)。
铁律:**只改显示,不改史料**。World 里的英文原名、事件字段、事实校验依据全部保持原样,
译文只在这一层生成,所以:
- 事实校验仍以英文原名为准(译文通过 `Translator.accepted()` 参与校验,不会被当成编造);
- 译名不写回 data/export,不改变 legends 的解析结果,去掉这层也不影响任何已产出的史料。
表里查不到的名字**原样保留**并登记进 `pending`,绝不硬造一个音译——
一个难读的英文名远好过一个每次都不一样的乱译名。
"""
from __future__ import annotations
import re
from dataclasses import dataclass, field
from dfannals import glossary
from dfannals.legends import World
_WORD_SPLIT = re.compile(r"\s+")
_CJK = r"\u4e00-\u9fff\u3000-\u303f\uff00-\uffef"
def split_epithet(name: str) -> tuple[str, str]:
"""拆出 DF 的长称号:`Xxx Yyy the Zzz Of Www` → ('Xxx Yyy', 'the zzz of www')。"""
lowered = name.strip().lower()
marker = " the "
if marker in lowered:
main, epithet = lowered.split(marker, 1)
return main, "the " + epithet
return lowered, ""
def translate_person(name: str) -> str | None:
"""人名:名字音译 + 姓氏意译。查不全就返回 None(宁可保留英文)。"""
if not name:
return None
main, epithet = split_epithet(name)
parts = _WORD_SPLIT.split(main)
stem = glossary.STEMS.get(parts[0])
if stem is None:
return None
surname = ""
if len(parts) > 1:
surname = glossary.SURNAMES.get("".join(parts[1:]), "")
if not surname:
return None
out = stem if not surname else f"{stem}·{surname}"
if epithet:
out += "「" + glossary.EPITHETS.get(epithet, "") + "」"
if not glossary.EPITHETS.get(epithet):
return None
return out
def translate_place(name: str) -> str | None:
"""地名:整体意译;带称号的写成「主名(称号)」。"""
if not name:
return None
main, epithet = split_epithet(name)
base = glossary.PLACES.get(main.replace(" ", ""))
if base is None:
return None
if epithet:
extra = glossary.EPITHETS.get(epithet)
return f"{base}({extra})" if extra else None
return base
def translate_group(name: str) -> str | None:
if not name:
return None
return glossary.GROUPS.get(name.strip().lower())
def translate_race(value: str) -> str:
"""种族值(DWARF、EAGLE_MAN)→ 中文;查不到原样返回。"""
if not value:
return value
return glossary.RACES.get(value.strip().upper(), value)
def translate_site_type(value: str) -> str:
if not value:
return value
return glossary.SITE_TYPES.get(value.strip().lower(), value)
@dataclass
class Translator:
"""把一整个世界的专名译好,供渲染与校验共用。"""
people: dict[str, str] = field(default_factory=dict) # 英文原名 → 中文
places: dict[str, str] = field(default_factory=dict)
groups: dict[str, str] = field(default_factory=dict)
stems: dict[str, str] = field(default_factory=dict) # 单用名(正文里绝大多数是简称)
surnames: dict[str, str] = field(default_factory=dict) # 单用姓(对白里互相叫姓)
races: dict[str, str] = field(default_factory=dict) # 含全大写与首字母大写两种写法
pending: list[str] = field(default_factory=list) # 表里没有、原样保留的名字
def person(self, name: str) -> str:
return self.people.get(name, name)
def place(self, name: str) -> str:
return self.places.get(name, name)
def group(self, name: str) -> str:
return self.groups.get(name, name)
def _pairs(self) -> list[tuple[str, str]]:
"""按英文原名长度降序:先替换长的,避免 `Ral` 抢在 `Ral Fastenhatchets` 前面。
顺序很重要:全名 → 单独的姓 → 单独的名。换掉全名后正文里已无拉丁字母,
后面两步不会再动它。
"""
full = list(self.people.items()) + list(self.places.items()) + list(self.groups.items())
full.sort(key=lambda kv: -len(kv[0]))
tail = list(self.surnames.items()) + list(self.stems.items())
tail.sort(key=lambda kv: -len(kv[0]))
return full + tail
def render(self, text: str) -> str:
"""把已有正文里的英文专名换成中文,并收拾替换后多余的空格。"""
for source, target in self._pairs():
text = re.sub(rf"(?<![A-Za-z]){re.escape(source)}(?![A-Za-z])", target, text)
# 种族:既要处理枚举值 EAGLE_MAN,也要处理正文里的 Yeti/Eagle_man
for source, target in sorted(self.races.items(), key=lambda kv: -len(kv[0])):
text = re.sub(rf"(?<![A-Za-z_]){re.escape(source)}(?![A-Za-z_])", target, text)
# 地点类型是小写短语(forest retreat、dark pits)
for source, target in sorted(glossary.SITE_TYPES.items(), key=lambda kv: -len(kv[0])):
text = re.sub(rf"(?<![A-Za-z]){re.escape(source)}(?![A-Za-z])", target, text,
flags=re.IGNORECASE)
return tidy_spaces(text)
def accepted(self) -> set[str]:
"""译名集合:事实校验要把它们当已知名字,否则会把译文当成凭空编造。"""
out: set[str] = set()
for target in [*self.people.values(), *self.places.values(), *self.groups.values()]:
out.add(target)
out.update(re.split(r"[·()「」,、]", target))
return {name for name in out if name}
def coverage(self) -> str:
rows = [
(
f"译名覆盖:人物 {len(self.people)} 个|地点 {len(self.places)} 个|"
f"势力 {len(self.groups)} 个"
),
]
if self.pending:
rows.append(f"待译(原样保留){len(self.pending)} 个:" + "、".join(self.pending[:12]))
return "\n".join(rows)
def tidy_spaces(text: str) -> str:
"""去掉中日韩字符之间被替换后留下的空格:`拉尔 说` → `拉尔说`。
英文专名之间、以及英文与汉字之间的空格保留(`Ral Fastenhatchets` 用得上)。
"""
text = re.sub(rf"(?<=[{_CJK}])[ \t]+(?=[{_CJK}])", "", text)
text = re.sub(rf"(?<=[{_CJK}])[ \t]+(?=[,。、;:!?)】」])", "", text)
text = re.sub(rf"(?<=[(【「])[ \t]+(?=[{_CJK}])", "", text)
return text
def title_form(value: str) -> str:
"""YETI → Yeti、EAGLE_MAN → Eagle_man、fastenhatchets → Fastenhatchets。
两个坑都踩过:
- 只改首字母不转小写,`YETI` 会得到 `YETI`,永远匹配不上正文里的 `Yeti`;
- 按下划线逐段首字母大写,`EAGLE_MAN` 会得到 `Eagle_Man`,
而史料渲染惯例是 `Eagle_man`(见 legends.pretty)。
"""
lowered = value.lower()
return lowered[:1].upper() + lowered[1:]
def build(world: World) -> Translator:
"""按世界里的实际名字建翻译器。"""
translator = Translator()
# 名与姓都单独收一份:正文里大量使用简称("Ral")和对白里只呼姓("Fastenhatchets")
translator.stems = {title_form(en): zh for en, zh in glossary.STEMS.items()}
translator.surnames = {title_form(en): zh for en, zh in glossary.SURNAMES.items()}
translator.races = {}
for en, zh in glossary.RACES.items():
translator.races[en] = zh
translator.races[title_form(en)] = zh
# 逐段大写的写法(Eagle_Man)也登记:模型两种都可能写
translator.races["_".join(p[:1].upper() + p[1:].lower() for p in en.split("_"))] = zh
for figure in world.figures.values():
raw = figure.name
if not raw:
continue
translated = translate_person(raw)
shown = _display(raw)
if translated:
translator.people[shown] = translated
translator.people[raw] = translated
elif _WORD_SPLIT.split(shown.lower())[0] in glossary.STEMS:
# 名字能读、姓氏没词条:这是真正需要补的缺口,登记下来
translator.pending.append(shown)
for site in world.sites.values():
raw = site.name
if not raw:
continue
translated = translate_place(raw)
shown = _display(raw)
if translated:
translator.places[shown] = translated
translator.places[raw] = translated
for entity in world.entities.values():
raw = entity.name
if not raw:
continue
translated = translate_group(raw)
shown = _display(raw)
if translated:
translator.groups[shown] = translated
translator.groups[raw] = translated
return translator
_CACHE: dict[int, tuple[World, Translator]] = {}
def for_world(world: World) -> Translator:
"""带缓存的建立器:一次运行里反复渲染素材,不能每次都重建 4 万个人名。"""
hit = _CACHE.get(id(world))
if hit is not None and hit[0] is world:
return hit[1]
translator = build(world)
_CACHE[id(world)] = (world, translator)
return translator
def _display(raw: str) -> str:
"""史料的程序化名全小写,渲染层会做首字母大写;译名要按展示形式建索引。"""
from dfannals.legends import pretty
return pretty(raw)
+4 -3
View File
@@ -12,7 +12,7 @@ from dataclasses import dataclass, replace
from pathlib import Path from pathlib import Path
from dfannals import episodes as ep_mod from dfannals import episodes as ep_mod
from dfannals import gate from dfannals import gate, localize
from dfannals.cast import collect_rows from dfannals.cast import collect_rows
from dfannals.chronicle import cjk_length from dfannals.chronicle import cjk_length
from dfannals.config import ( from dfannals.config import (
@@ -194,12 +194,13 @@ def render_material(
"", "",
"### 写作要求", "### 写作要求",
"", "",
f"- 本集 {CHAPTER_MIN_CHARS}–{CHAPTER_MAX_CHARS} 字,中文正文,专名保留英文。", f"- 本集 {CHAPTER_MIN_CHARS}–{CHAPTER_MAX_CHARS} 字,中文正文,人名地名用上面给出的中文译名。",
"- 贴着主角写:他们的目标、算计、得失做主语;对手要是个具体的人。", "- 贴着主角写:他们的目标、算计、得失做主语;对手要是个具体的人。",
"- 性别按上面卡片写,不要默认“他”;史料未载性别时用名字或身份称呼。", "- 性别按上面卡片写,不要默认“他”;史料未载性别时用名字或身份称呼。",
"- 史料之外的世界大事不要写;只有影响到主角时才提一句。", "- 史料之外的世界大事不要写;只有影响到主角时才提一句。",
] ]
return "\n".join(lines) # 专名本土化:素材里的英文原名换成中文译名,让模型直接用中文写
return localize.for_world(world).render("\n".join(lines))
def build_messages( def build_messages(
+19 -19
View File
@@ -1,37 +1,37 @@
# Mon Sagus · 人物表 # Mon Sagus · 人物表
本卷主角线索:Guspu Frillyknots、Ral Fastenhatchets、Alath Blottedmine 本卷主角线索:古斯普·褶结、拉尔·缚斧、阿拉斯·污矿
线索跨度:181–248 线索跨度:181–248
| 人物 | 种族 | 性别 | 生卒 | 身份 | 本卷出场 | 角色 | | 人物 | 种族 | 性别 | 生卒 | 身份 | 本卷出场 | 角色 |
|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
| Guspu Frillyknots | EAGLE_MAN | 男 | 151–246 | 关系对象×13、构陷发起者×4 | 62 | 主角 | | 古斯普·褶结 | 鹰人 | 男 | 151–246 | 关系对象×13、构陷发起者×4 | 62 | 主角 |
| Ral Fastenhatchets | DWARF | 女 | 164–在世/不详 | 被针对者×21、受骗者×6 | 28 | 主角 | | 拉尔·缚斧 | 矮人 | 女 | 164–在世/不详 | 被针对者×21、受骗者×6 | 28 | 主角 |
| Alath Blottedmine | DWARF | 男 | 182–在世/不详 | 构陷发起者×4、关系对象×1 | 8 | 主角 | | 阿拉斯·污矿 | 矮人 | 男 | 182–在世/不详 | 构陷发起者×4、关系对象×1 | 8 | 主角 |
| Tulon Tongswall | DWARF | 男 | 132–在世/不详 | 构陷发起者×3 | 3 | 对手/配角 | | 图隆·钳墙 | 矮人 | 男 | 132–在世/不详 | 构陷发起者×3 | 3 | 对手/配角 |
| Moldath Mirroredfloors | DWARF | 女 | 79–在世/不详 | 构陷发起者×3 | 3 | 对手/配角 | | 莫尔达斯·镜层 | 矮人 | 女 | 79–在世/不详 | 构陷发起者×3 | 3 | 对手/配角 |
| Ineth Wheeleddrinks | DWARF | 男 | 165–在世/不详 | 构陷者×3 | 3 | 对手/配角 | | 伊内斯·轮饮 | 矮人 | 男 | 165–在世/不详 | 构陷者×3 | 3 | 对手/配角 |
| Langgud Tradebears The Eviscerated Chill Of Pregnancies | YETI | 男 | 生卒不详 | — | 2 | 对手/配角 | | 朗古德·商熊「剖胎之寒」 | 雪人 | 男 | 生卒不详 | — | 2 | 对手/配角 |
| Rigoth Stilledearthen | DWARF | 男 | 162–在世/不详 | 当事者×2 | 2 | 对手/配角 | | 里戈斯·静土 | 矮人 | 男 | 162–在世/不详 | 当事者×2 | 2 | 对手/配角 |
| Perom Crazeowned | HUMAN | 男 | 129–在世/不详 | 当事者×1、关系对象×1 | 2 | 对手/配角 | | 佩罗姆·狂据 | 人类 | 男 | 129–在世/不详 | 当事者×1、关系对象×1 | 2 | 对手/配角 |
## 小传 ## 小传
**Guspu Frillyknots** —— 鹰人Guspu Frillyknots以六十二次出场与十三次关系对象记录高踞本卷,193年在Fordedwinds对Ral Fastenhatchets构陷未遂,次年被The Volcano Of Ravens定罪。 **古斯普·褶结** —— 鹰人古斯普·褶结以六十二次出场与十三次关系对象记录高踞本卷,193年在涉风渡对拉尔·缚斧构陷未遂,次年被渡鸦火山定罪。
**Ral Fastenhatchets** —— 矮人Ral Fastenhatchets是本卷最执拗的靶子:181年与Langgud Tradebears The Eviscerated Chill Of Pregnancies在Fordedwinds两度交手,此后Guspu、Tulon、Alath、Moldath与Ineth轮番构陷或诬告,均未得逞;她与Rigoth Stilledearthen的关系于219年解除。 **拉尔·缚斧** —— 矮人拉尔·缚斧是本卷最执拗的靶子:181年与朗古德·商熊「剖胎之寒」在涉风渡两度交手,此后古斯普、图隆、阿拉斯、莫尔达斯与伊内斯轮番构陷或诬告,均未得逞;她与里戈斯·静土的关系于219年解除。
**Alath Blottedmine** —— 矮人Alath Blottedmine于229年对Ral Fastenhatchets、230年对Momuz Decentpage构陷未遂,并与Sina Watchedleads、Artuk Huggedfastened有过关系记录;230年被The Volcano Of Ravens定罪。 **阿拉斯·污矿** —— 矮人阿拉斯·污矿于229年对拉尔·缚斧、230年对莫穆兹·端页构陷未遂,并与西娜·守铅、阿图克·抱固有过关系记录;230年被渡鸦火山定罪。
**Tulon Tongswall** —— 矮人Tulon Tongswall在193、195、197年连续三次于Fordedwinds构陷Ral Fastenhatchets,三次全败,出场也仅此三回。 **图隆·钳墙** —— 矮人图隆·钳墙在193、195、197年连续三次于涉风渡构陷拉尔·缚斧,三次全败,出场也仅此三回。
**Moldath Mirroredfloors** —— 矮人Moldath Mirroredfloors在233年两度、234年一度于Fordedwinds构陷Ral Fastenhatchets,均告失败,算本卷坚韧而无效的对手之一。 **莫尔达斯·镜层** —— 矮人莫尔达斯·镜层在233年两度、234年一度于涉风渡构陷拉尔·缚斧,均告失败,算本卷坚韧而无效的对手之一。
**Ineth Wheeleddrinks** —— 矮人Ineth Wheeleddrinks在245、247、248年三次对Ral Fastenhatchets发起诬告,均告失败,The Volcano Of Ravens始终未予采信。 **伊内斯·轮饮** —— 矮人伊内斯·轮饮在245、247、248年三次对拉尔·缚斧发起诬告,均告失败,渡鸦火山始终未予采信。
**Langgud Tradebears The Eviscerated Chill Of Pregnancies** —— 雪人Langgud Tradebears The Eviscerated Chill Of Pregnancies于181年在Fordedwinds与Ral Fastenhatchets两度交手,生卒不详,除了名字长到令人侧目外只留下这两条战斗记录。 **朗古德·商熊「剖胎之寒」** —— 雪人朗古德·商熊「剖胎之寒」于181年在涉风渡与拉尔·缚斧两度交手,生卒不详,除了名字长到令人侧目外只留下这两条战斗记录。
**Rigoth Stilledearthen** —— 矮人Rigoth Stilledearthen于188年与Ral Fastenhatchets建立关系,219年解除,两条记录便写尽他在本卷的起落。 **里戈斯·静土** —— 矮人里戈斯·静土于188年与拉尔·缚斧建立关系,219年解除,两条记录便写尽他在本卷的起落。
**Perom Crazeowned** —— 人类Perom Crazeowned在193年与Guspu Frillyknots建立关系,202年又添一笔,是鹰人关系网中露面有限的配角。 **佩罗姆·狂据** —— 人类佩罗姆·狂据在193年与古斯普·褶结建立关系,202年又添一笔,是鹰人关系网中露面有限的配角。
+156 -156
View File
@@ -1,389 +1,389 @@
# 守门人 # 守门人
181年的Fordedwinds还没有名字。 181年的涉风渡还没有名字。
那条隘口夹在两片黑石崖之间,冬季的河已经结死,冻得发青的冰面一直铺到山脚。Ral Fastenhatchets第一次踩上那道冰面的时候,脚下打了一个趔趄,铁头靴的底沿磕在石头茬子上,磕出一声闷响。她没抬头,伸手摸了一把刃口,把斧头从背上换到左手,顺着风向往前挪了两步。风向不对。从北面谷口直灌进来的冷气不自然,带着一股湿漉漉的腥味,像是某种大块头的活物刚在那儿蹲过不久。她把斧柄往掌心里攥紧了一点。 那条隘口夹在两片黑石崖之间,冬季的河已经结死,冻得发青的冰面一直铺到山脚。拉尔·缚斧第一次踩上那道冰面的时候,脚下打了一个趔趄,铁头靴的底沿磕在石头茬子上,磕出一声闷响。她没抬头,伸手摸了一把刃口,把斧头从背上换到左手,顺着风向往前挪了两步。风向不对。从北面谷口直灌进来的冷气不自然,带着一股湿漉漉的腥味,像是某种大块头的活物刚在那儿蹲过不久。她把斧柄往掌心里攥紧了一点。
那个东西就在路口正中。 那个东西就在路口正中。
两倍高。四层高的。一个Yeti。肩宽差不多能塞下她两个,灰白的长毛从肩胛一直垂到脚踝,每一根都结着霜。它坐在那儿,一条腿曲着,另一条直直伸出去,整个身子像是长在这块石头上。Langgud Tradebears The Eviscerated Chill Of Pregnancies。这名字是从哪儿听来的她记不清了——也许是哪个从南边林子里活着爬出去的猎人。她在意的是另一件事:这东西挡在Fordedwinds的入口,把南来北往的小路堵死了。 两倍高。四层高的。一个雪人。肩宽差不多能塞下她两个,灰白的长毛从肩胛一直垂到脚踝,每一根都结着霜。它坐在那儿,一条腿曲着,另一条直直伸出去,整个身子像是长在这块石头上。朗古德·商熊「剖胎之寒」。这名字是从哪儿听来的她记不清了——也许是哪个从南边林子里活着爬出去的猎人。她在意的是另一件事:这东西挡在涉风渡的入口,把南来北往的小路堵死了。
她没退。 她没退。
她可以退回矿洞,退回那帮矮人的巷子里,把斧头挂上墙,告诉自己这事不该她管。矿洞里还有热汤,铁锅架在石灶上咕嘟响,老矿工还能在桌边骂上半夜的山。可她没走。她在隘口外二十步的地方站住了,把斧头从左手换回右手,刃口朝前。Langgud Tradebears的呼气从那团灰白的毛里一下一下地喷出来,每一次喷出去都能在它面前凝出一小片白雾。她感觉自己胡子尖上开始挂霜了。 她可以退回矿洞,退回那帮矮人的巷子里,把斧头挂上墙,告诉自己这事不该她管。矿洞里还有热汤,铁锅架在石灶上咕嘟响,老矿工还能在桌边骂上半夜的山。可她没走。她在隘口外二十步的地方站住了,把斧头从左手换回右手,刃口朝前。朗古德商熊的呼气从那团灰白的毛里一下一下地喷出来,每一次喷出去都能在它面前凝出一小片白雾。她感觉自己胡子尖上开始挂霜了。
“让开。” “让开。”
她说。声音从喉咙里挤出来,被冷空气一激,哑了半截。Yeti没动。她又往前走了一步,铁头磕在冻硬的泥地上,叮地响了一声。Yeti这才抬眼。两颗黑眼珠嵌在灰白毛里,慢悠悠地落到她脸上,没有立刻往上抬,也没有立刻往下移。 她说。声音从喉咙里挤出来,被冷空气一激,哑了半截。雪人没动。她又往前走了一步,铁头磕在冻硬的泥地上,叮地响了一声。雪人这才抬眼。两颗黑眼珠嵌在灰白毛里,慢悠悠地落到她脸上,没有立刻往上抬,也没有立刻往下移。
“让开。”她又说了一遍。这一次她没看Yeti的脸,看的是它前爪搭着的那块石头。那块石头底下压着半截骨头,骨头边上还冻着一摊发黑的什么,已经冻成冰茬子。这是上一个从这儿过的东西,或者上一个没能过去的人。她把目光从骨头上挪开,挪到Yeti的前爪边上。前爪指节上套着一圈磨秃的皮,皮上刻着一个符号,她认不出来。 “让开。”她又说了一遍。这一次她没看雪人的脸,看的是它前爪搭着的那块石头。那块石头底下压着半截骨头,骨头边上还冻着一摊发黑的什么,已经冻成冰茬子。这是上一个从这儿过的东西,或者上一个没能过去的人。她把目光从骨头上挪开,挪到雪人的前爪边上。前爪指节上套着一圈磨秃的皮,皮上刻着一个符号,她认不出来。
Langgud Tradebears The Eviscerated Chill Of Pregnancies没说话。它只是把那只前爪往石头上挪了挪,指节咔地响了一声。这是回答。不是答应,也不是拒绝,是告诉她:这块石头我占着,你拿来动它试试。 朗古德·商熊「剖胎之寒」没说话。它只是把那只前爪往石头上挪了挪,指节咔地响了一声。这是回答。不是答应,也不是拒绝,是告诉她:这块石头我占着,你拿来动它试试。
她没动斧头。她从腰后抽出那块她揣了整个早晨的石头,顺手丢到了路上。石头落在冰面上,滑出去两尺,撞上Yeti伸出的那只脚的脚背,咣地响了一声。Yeti低头看那块石头,又抬头看她。她站着,没弯腰,没退,铁头杵在脚边。她不打算解释这块石头是什么意思,不打算解释她为什么不打算退。她只是站着。 她没动斧头。她从腰后抽出那块她揣了整个早晨的石头,顺手丢到了路上。石头落在冰面上,滑出去两尺,撞上雪人伸出的那只脚的脚背,咣地响了一声。雪人低头看那块石头,又抬头看她。她站着,没弯腰,没退,铁头杵在脚边。她不打算解释这块石头是什么意思,不打算解释她为什么不打算退。她只是站着。
Yeti先动了。它把那条直着的腿收回来,整个身子往边上挪了半步。就半步。它侧过半边身子,前爪还搭在那块石头上,没让出整条路。它让出了她能侧身挤过去的那一点空隙。 雪人先动了。它把那条直着的腿收回来,整个身子往边上挪了半步。就半步。它侧过半边身子,前爪还搭在那块石头上,没让出整条路。它让出了她能侧身挤过去的那一点空隙。
她没挤。 她没挤。
她从那块石头上迈了过去,铁头靴的底沿磕在Yeti前爪的指节上,磕得指节上的皮圈咯吱响了一声。Yeti的毛抖了一下,没拍下来。她走过去了。她没回头看。她知道如果她回头看,那只前爪会在她后脑勺上拍一下,把她的头连骨带捅进冰里。她一直走到隘口另一头才停下,铁头杵在脚边,呼了一口长气。气从嘴里喷出来,在她面前凝成一小团白雾。 她从那块石头上迈了过去,铁头靴的底沿磕在雪人前爪的指节上,磕得指节上的皮圈咯吱响了一声。雪人的毛抖了一下,没拍下来。她走过去了。她没回头看。她知道如果她回头看,那只前爪会在她后脑勺上拍一下,把她的头连骨带捅进冰里。她一直走到隘口另一头才停下,铁头杵在脚边,呼了一口长气。气从嘴里喷出来,在她面前凝成一小团白雾。
她赢了,还是她输了?她站在隘口另一头想了很久。风从她身后灌进来,吹得她后颈发凉。Yeti没追上来。她回头看了一眼。Langgud Tradebears The Eviscerated Chill Of Pregnancies还坐在那块石头上,前爪还搭着,没挪窝。它只是坐在那儿,呼出的气一下一下地喷在冰面上。 她赢了,还是她输了?她站在隘口另一头想了很久。风从她身后灌进来,吹得她后颈发凉。雪人没追上来。她回头看了一眼。朗古德·商熊「剖胎之寒」还坐在那块石头上,前爪还搭着,没挪窝。它只是坐在那儿,呼出的气一下一下地喷在冰面上。
她不打算再退回去了。 她不打算再退回去了。
她转身往南走,走了几步,又停下。她转回去,走回那块她丢过去的石头边上,蹲下,把石头从冰面上抠起来。石头上的冰被她抠掉一层,露出下面灰白的原色。她把石头搬到隘口正中,竖在路口那儿,竖得稳稳当当。这是凭证。要过的人留在这块石头边上。她没说这是给谁立的规矩,没说这块石头怎么过她才放人过,她只是把石头竖在那儿,转身走了。 她转身往南走,走了几步,又停下。她转回去,走回那块她丢过去的石头边上,蹲下,把石头从冰面上抠起来。石头上的冰被她抠掉一层,露出下面灰白的原色。她把石头搬到隘口正中,竖在路口那儿,竖得稳稳当当。这是凭证。要过的人留在这块石头边上。她没说这是给谁立的规矩,没说这块石头怎么过她才放人过,她只是把石头竖在那儿,转身走了。
她走回隘口另一头的时候,回头看了一眼。Langgud Tradebears The Eviscerated Chill Of Pregnancies还坐在那块石头上,前爪还搭着,没挪窝。它只是坐在那儿,呼出的气一下一下地喷在冰面上。 她走回隘口另一头的时候,回头看了一眼。朗古德·商熊「剖胎之寒」还坐在那块石头上,前爪还搭着,没挪窝。它只是坐在那儿,呼出的气一下一下地喷在冰面上。
隘口那一夜之后过了多久,Ral Fastenhatchets没去算。她只记得再回Fastenhatchets那一带时,山道上的冰已经开始化。她从隘口那头的石块边走过,没停。回去是要带东西的,不是要空手把命交代在那儿。 隘口那一夜之后过了多久,拉尔·缚斧没去算。她只记得再回缚斧那一带时,山道上的冰已经开始化。她从隘口那头的石块边走过,没停。回去是要带东西的,不是要空手把命交代在那儿。
Rigoth Stilledearthen是在开春第三周找上来的。 里戈斯·静土是在开春第三周找上来的。
他出现在Fastenhatchets南边那条石阶路口的时候,Ral正在跟一个过路的小贩算盐钱。小贩看见这老矮人背着个木匣子从坡上下来,主动让了半步。Rigoth绕过小贩,没看Ral手里那几块粗盐,直接站到她跟前。 他出现在缚斧南边那条石阶路口的时候,拉尔正在跟一个过路的小贩算盐钱。小贩看见这老矮人背着个木匣子从坡上下来,主动让了半步。里戈斯绕过小贩,没看拉尔手里那几块粗盐,直接站到她跟前。
“Ral Fastenhatchets。”他说。 “拉尔·缚斧。”他说。
他没报自己的名字。他把木匣子解下来,搁在两人之间的石阶上。石阶那几块石板被盐卤浸得发白,木匣子搁上去没响。 他没报自己的名字。他把木匣子解下来,搁在两人之间的石阶上。石阶那几块石板被盐卤浸得发白,木匣子搁上去没响。
“你记不记得Rockjaw那一支还欠我两车铁。”他说。 “你记不记得拉尔·缚斧那一支还欠我两车铁。”他说。
“记。”Ral说。 “记。”拉尔说。
“那账我不要了。” “那账我不要了。”
“你要什么。” “你要什么。”
Rigoth把木匣子翻开。里头是一本账册,封皮磨得起了毛边,几页纸露在外头,被风掀得一翘一翘的。 里戈斯把木匣子翻开。里头是一本账册,封皮磨得起了毛边,几页纸露在外头,被风掀得一翘一翘的。
“我替你记。”他说。“每一笔过路钱,每一笔盐,每一笔铁。你不在的时候替你收,你回来了我把账交给你。我不要工钱。” “我替你记。”他说。“每一笔过路钱,每一笔盐,每一笔铁。你不在的时候替你收,你回来了我把账交给你。我不要工钱。”
Ral伸手拨了一下那本账册的封皮。封皮上的字已经认不清了,是上一个主人写的,墨渗进了皮里。她把手缩回来。 拉尔伸手拨了一下那本账册的封皮。封皮上的字已经认不清了,是上一个主人写的,墨渗进了皮里。她把手缩回来。
“为什么不要工钱。” “为什么不要工钱。”
“我老了。”Rigoth说。“搬不动铁了。” “我老了。”里戈斯说。“搬不动铁了。”
Ral看了一眼他的手。这老矮人的手背上青筋鼓得很高,指节却瘦得凹下去,是那种搬了一辈子东西又突然不搬的手。她没点破。 拉尔看了一眼他的手。这老矮人的手背上青筋鼓得很高,指节却瘦得凹下去,是那种搬了一辈子东西又突然不搬的手。她没点破。
“进来。”她说。 “进来。”她说。
Rigoth把木匣子合上,抱起,跟在她后头,进了门。 里戈斯把木匣子合上,抱起,跟在她后头,进了门。
Rigoth住进来的头一周,Ral只让他在仓房那头坐着。Rigoth把木匣子搁在膝头,账册摊开,谁过路他就抬头看一眼,谁没过来他就低头抄。Ral走过几次,看见他记的和自己心里那笔对得上,没说话。 里戈斯住进来的头一周,拉尔只让他在仓房那头坐着。里戈斯把木匣子搁在膝头,账册摊开,谁过路他就抬头看一眼,谁没过来他就低头抄。拉尔走过几次,看见他记的和自己心里那笔对得上,没说话。
第二周她把钥匙给了他一把。 第二周她把钥匙给了他一把。
“粮仓后门。”她说。“夜里有人敲三下再开。” “粮仓后门。”她说。“夜里有人敲三下再开。”
Rigoth点头。 里戈斯点头。
第三周的时候Ral问了一句:“Fordedwinds那头的市集,这阵子谁去过?” 第三周的时候拉尔问了一句:“涉风渡那头的市集,这阵子谁去过?”
Rigoth翻了翻账册。“没人。”他说。“我记了,没一个Fastenhatchets的去过。” 里戈斯翻了翻账册。“没人。”他说。“我记了,没一个缚斧的去过。”
Ral没接。Rigoth在她背后说了一句: 拉尔没接。里戈斯在她背后说了一句:
“我听见说,那头近来来了个鹰人。” “我听见说,那头近来来了个鹰人。”
Ral停了一步,没回头。 拉尔停了一步,没回头。
“鹰人。”她说。 “鹰人。”她说。
“嗯。”Rigoth说。“说他不住店,不买货。” “嗯。”里戈斯说。“说他不住店,不买货。”
Ral这才回过头。 拉尔这才回过头。
Fordedwinds的市集开在两块大石之间。Ral去的那个早上天没下雨,页岩上头还有前一晚冻住的薄冰。她一个人去的,斗篷兜帽压低,从东头挤进去。 涉风渡的市集开在两块大石之间。拉尔去的那个早上天没下雨,页岩上头还有前一晚冻住的薄冰。她一个人去的,斗篷兜帽压低,从东头挤进去。
她先看见了Momuz Fateddie。 她先看见了莫穆兹·命终。
Momuz是她从小的邻居,比她小两岁。Ral离开Fastenhatchets那几年,粮仓就是Momuz替她看着的。Momuz看见Ral,眼里先是一愣,然后笑了一下,从摊子后面绕出来。 莫穆兹是她从小的邻居,比她小两岁。拉尔离开缚斧那几年,粮仓就是莫穆兹替她看着的。莫穆兹看见拉尔,眼里先是一愣,然后笑了一下,从摊子后面绕出来。
“你怎么来了。”Momuz说。 “你怎么来了。”莫穆兹说。
“路过。”Ral说。 “路过。”拉尔说。
Momuz把手上那把秤搁下。秤杆上还挂着一小截麻绳,是刚才称完什么东西没收拢的。她抬手把那截麻绳绕到秤杆头上,动作很熟。Ral看了一眼那个动作,没说话。 莫穆兹把手上那把秤搁下。秤杆上还挂着一小截麻绳,是刚才称完什么东西没收拢的。她抬手把那截麻绳绕到秤杆头上,动作很熟。拉尔看了一眼那个动作,没说话。
“我去给你倒碗热的。”Momuz说。 “我去给你倒碗热的。”莫穆兹说。
“不用。”Ral说。“你忙。” “不用。”拉尔说。“你忙。”
Momuz站了一会儿,又回去守她的摊子。Ral挪到了市集东头一个卖皮子的摊子后头,那里有一块半截石墩,正好能坐。她坐下,把斗篷拢紧,目光落在Momuz那摊子前头过路的人身上。 莫穆兹站了一会儿,又回去守她的摊子。拉尔挪到了市集东头一个卖皮子的摊子后头,那里有一块半截石墩,正好能坐。她坐下,把斗篷拢紧,目光落在莫穆兹那摊子前头过路的人身上。
鹰人是傍晚那阵出现的。 鹰人是傍晚那阵出现的。
他从市集西头过来,步子不紧不慢。市集里人挤,矮人、人类、几个半大的孩子挤在摊子之间,他一进来就显眼。不是因为他高。是因为他走路不带声响,落地的时候脚尖先点地,然后才把整个脚掌放下来,那是他那族走路的样子。他穿着一件深褐色的短衣,腰上没挂刀,背上一只长弓,弓弦松着。 他从市集西头过来,步子不紧不慢。市集里人挤,矮人、人类、几个半大的孩子挤在摊子之间,他一进来就显眼。不是因为他高。是因为他走路不带声响,落地的时候脚尖先点地,然后才把整个脚掌放下来,那是他那族走路的样子。他穿着一件深褐色的短衣,腰上没挂刀,背上一只长弓,弓弦松着。
Ral看着他。 拉尔看着他。
他没去任何一个摊子。他绕过卖皮子的,绕过卖铁器的,绕过卖腌菜的,一直走到Momuz那摊子前。 他没去任何一个摊子。他绕过卖皮子的,绕过卖铁器的,绕过卖腌菜的,一直走到莫穆兹那摊子前。
Momuz抬起头。 莫穆兹抬起头。
那之后几天,Ral每逢Fordedwinds开市就去,去就坐在那块半截石墩上。她不和Momuz说话,也不和那鹰人说话。 那之后几天,拉尔每逢涉风渡开市就去,去就坐在那块半截石墩上。她不和莫穆兹说话,也不和那鹰人说话。
那鹰人叫Guspu Frillyknots,是Rigoth替她打听出来的。Rigoth没进市集,他在市集外头的茶棚子里坐着,谁从里头出来他就跟谁搭两句。第五天他带回这个名字。 那鹰人叫古斯普·褶结,是里戈斯替她打听出来的。里戈斯没进市集,他在市集外头的茶棚子里坐着,谁从里头出来他就跟谁搭两句。第五天他带回这个名字。
“Guspu Frillyknots。”Rigoth说。“不是商队的人,也不是哪家请的护卫。他自己一个人。” “古斯普·褶结。”里戈斯说。“不是商队的人,也不是哪家请的护卫。他自己一个人。”
“他找Momuz做什么。”Ral说。 “他找莫穆兹做什么。”拉尔说。
“说话。”Rigoth说。“我隔着问了几个人,都这么说。没见成交过什么。” “说话。”里戈斯说。“我隔着问了几个人,都这么说。没见成交过什么。”
Ral把这句话在嘴里嚼了嚼。一个不住店不买货的鹰人,跑到市集上,就为了和一个看粮仓的矮女人说话。 拉尔把这句话在嘴里嚼了嚼。一个不住店不买货的鹰人,跑到市集上,就为了和一个看粮仓的矮女人说话。
“他说什么。”Ral问。 “他说什么。”拉尔问。
Rigoth摇头。“问不出来。Momuz不跟人说。” 里戈斯摇头。“问不出来。莫穆兹不跟人说。”
Ral看了Rigoth一眼。Rigoth把账册合上。 拉尔看了里戈斯一眼。里戈斯把账册合上。
“我去盯着。”Rigoth说。 “我去盯着。”里戈斯说。
“不用。”Ral说。“你回去把盐账结了。” “不用。”拉尔说。“你回去把盐账结了。”
Rigoth走后,Ral在屋檐下站了很久。她没再回市集。 里戈斯走后,拉尔在屋檐下站了很久。她没再回市集。
再见到Momuz是半个月后。Momuz自己回了一趟Fastenhatchets,说是要清点粮仓后头那几口旧缸。Ral陪她走到后院,看她蹲在缸边用指头敲,敲出空响的就摇一下头。 再见到莫穆兹是半个月后。莫穆兹自己回了一趟缚斧,说是要清点粮仓后头那几口旧缸。拉尔陪她走到后院,看她蹲在缸边用指头敲,敲出空响的就摇一下头。
“那头市集。”Ral说。“那个鹰人。” “那头市集。”拉尔说。“那个鹰人。”
Momuz敲缸的手停了一下。她没抬头。 莫穆兹敲缸的手停了一下。她没抬头。
“Guspu。”Momuz说。 “古斯普。”莫穆兹说。
“嗯。” “嗯。”
“他是我朋友。”Momuz说。 “他是我朋友。”莫穆兹说。
Ral没接。Momuz直起腰,把手上的灰在围裙上蹭了两下。 拉尔没接。莫穆兹直起腰,把手上的灰在围裙上蹭了两下。
“你问这个做什么。”Momuz说。 “你问这个做什么。”莫穆兹说。
“你是我看粮仓的。”Ral说。“那头来了个我不认识的人。” “你是我看粮仓的。”拉尔说。“那头来了个我不认识的人。”
“我不认识的人多了。”Momuz说。“卖皮子的那个我也不认识。” “我不认识的人多了。”莫穆兹说。“卖皮子的那个我也不认识。”
Ral没说话。Momuz把缸盖合上,抱起,往仓里走。走到门口她回头说了一句。 拉尔没说话。莫穆兹把缸盖合上,抱起,往仓里走。走到门口她回头说了一句。
“Ral。”她说。“我自己的事。” “拉尔。”她说。“我自己的事。”
Ral点了点头。 拉尔点了点头。
Rigoth是冬天头一场雪之后把那句话带回来的。他在仓房后头等Ral,账册翻开在膝头,纸页被风吹得一张一张翻过去,他用手按住。 里戈斯是冬天头一场雪之后把那句话带回来的。他在仓房后头等拉尔,账册翻开在膝头,纸页被风吹得一张一张翻过去,他用手按住。
“结契了。”他说。 “结契了。”他说。
“谁。” “谁。”
“Guspu Frillyknots和Momuz Fateddie。”Rigoth说。“鹰人那边的契。市集东头那个卖皮子的看见了。” “古斯普·褶结和莫穆兹·命终。”里戈斯说。“鹰人那边的契。市集东头那个卖皮子的看见了。”
Ral把账册从他手里接过来。她念了一遍那几个字,又念了一遍。 拉尔把账册从他手里接过来。她念了一遍那几个字,又念了一遍。
Guspu Frillyknots。Momuz Fateddie。 古斯普·褶结。莫穆兹·命终。
她把账册合上,搁回Rigoth膝头。Rigoth看着她,等她说点什么。 她把账册合上,搁回里戈斯膝头。里戈斯看着她,等她说点什么。
Ral站了一会儿。 拉尔站了一会儿。
“她自己的事。”她说。 “她自己的事。”她说。
Rigoth没再问。 里戈斯没再问。
隘口的矮桌是Guspu Frillyknots自己带来的。他把四条腿掰开,桌面放平在两块石墩之间,离Ral守的那条路只差两步。来人过的时候都能看见桌面上铺开的东西:一卷盖满章的羊皮纸,三只小陶碟,碟里是干得发硬的奶酪和一小堆切成方块的熏肉,一壶还没开封的矮麦酒。他把东西一样一样摆出来,摆完便坐到桌后,从腰间抽出一根骨签剔牙。 隘口的矮桌是古斯普·褶结自己带来的。他把四条腿掰开,桌面放平在两块石墩之间,离拉尔守的那条路只差两步。来人过的时候都能看见桌面上铺开的东西:一卷盖满章的羊皮纸,三只小陶碟,碟里是干得发硬的奶酪和一小堆切成方块的熏肉,一壶还没开封的矮麦酒。他把东西一样一样摆出来,摆完便坐到桌后,从腰间抽出一根骨签剔牙。
Ral从岗哨那边走过来时,他没抬头。等她在桌对面站定,他才把骨签收起来,拿袍袖擦了一下嘴角,抬眼看她。他眼睛是淡黄的,在冬天的光里显得更浅,瞳孔边上有一圈很细的金线。他先说话,声音从喉咙高处滑下来,滑得很慢,像怕风把它吹散: 拉尔从岗哨那边走过来时,他没抬头。等她在桌对面站定,他才把骨签收起来,拿袍袖擦了一下嘴角,抬眼看她。他眼睛是淡黄的,在冬天的光里显得更浅,瞳孔边上有一圈很细的金线。他先说话,声音从喉咙高处滑下来,滑得很慢,像怕风把它吹散:
“你守着一条路,却没有保护者。” “你守着一条路,却没有保护者。”
Ral没坐。她站在桌边,左手扶着桌沿,右手还戴着半截皮手套,没脱。那只手指尖发黑,刚从账房那边过来,碰过墨。她没去碰那卷羊皮纸。羊皮纸的封蜡是红的,盖了三枚章,她认得出其中一枚是Ongrun城里某个议事厅的戳,另一枚她没见过。 拉尔没坐。她站在桌边,左手扶着桌沿,右手还戴着半截皮手套,没脱。那只手指尖发黑,刚从账房那边过来,碰过墨。她没去碰那卷羊皮纸。羊皮纸的封蜡是红的,盖了三枚章,她认得出其中一枚是涉风渡里某个议事厅的戳,另一枚她没见过。
“我可以让Fordedwinds免受任何骚扰。”Guspu说。他把“骚扰”两个字说得很轻,像说“风”。“只需要你在通行税里分三成给我。三成,不多。我替你挡掉的事,比这三成值钱得多。” “我可以让涉风渡免受任何骚扰。”古斯普说。他把“骚扰”两个字说得很轻,像说“风”。“只需要你在通行税里分三成给我。三成,不多。我替你挡掉的事,比这三成值钱得多。”
Ral看了一眼那三只陶碟。碟边沿磕掉了一小片,奶酪上落了一点灰。她没碰它们。 拉尔看了一眼那三只陶碟。碟边沿磕掉了一小片,奶酪上落了一点灰。她没碰它们。
“那三成,”她说,“是给你,还是给你后面的人?” “那三成,”她说,“是给你,还是给你后面的人?”
Guspu笑了一下。那种笑法是从嘴角先动的,眼底不跟。他把骨签又抽出来,在指间转了半圈,又收回去。 古斯普笑了一下。那种笑法是从嘴角先动的,眼底不跟。他把骨签又抽出来,在指间转了半圈,又收回去。
“你不问,”他说,“我就不说。这是体面。” “你不问,”他说,“我就不说。这是体面。”
Ral把那只皮手套慢慢褪下来,搁在桌沿上。她用空出来的手把那卷羊皮纸推回Guspu那一侧。纸卷在桌面上滚了半圈,撞上陶碟,碟里的熏肉方块震了一下,有一块滑到碟外,落在桌面。 拉尔把那只皮手套慢慢褪下来,搁在桌沿上。她用空出来的手把那卷羊皮纸推回古斯普那一侧。纸卷在桌面上滚了半圈,撞上陶碟,碟里的熏肉方块震了一下,有一块滑到碟外,落在桌面。
“我买过你的体面吗?”她说。 “我买过你的体面吗?”她说。
Guspu没去扶那块肉。他看着Ral,慢慢把那卷羊皮纸拢回自己这边,卷好,塞回怀里。他没说行,也没说不行。他站起身,把矮麦酒那壶也拎起来,走了。走的时候脚步很轻,靴底像是垫了一层皮。 古斯普没去扶那块肉。他看着拉尔,慢慢把那卷羊皮纸拢回自己这边,卷好,塞回怀里。他没说行,也没说不行。他站起身,把矮麦酒那壶也拎起来,走了。走的时候脚步很轻,靴底像是垫了一层皮。
那壶酒他没开封,也没留下。 那壶酒他没开封,也没留下。
来试Ral的不止Guspu一个。同一年,Tulon Tongswall也找上门来。Tulon是矮人,身材比Guspu矮半头,肩却很宽,走起路来两侧带风。他没带矮桌,也没带羊皮纸,只带了一个人——他自己的随从,随从手里捧着一只铁匣,匣里是码得整整齐齐的铜锭。 来试拉尔的不止古斯普一个。同一年,图隆·钳墙也找上门来。图隆是矮人,身材比古斯普矮半头,肩却很宽,走起路来两侧带风。他没带矮桌,也没带羊皮纸,只带了一个人——他自己的随从,随从手里捧着一只铁匣,匣里是码得整整齐齐的铜锭。
Tulon把Ral堵在隘口的石墙下。他开口比Guspu直白得多。 图隆把拉尔堵在隘口的石墙下。他开口比古斯普直白得多。
“三成五。”他说。他站在阴影里,声音从胸腔里压出来,比Guspu那种滑下来的声调重得多。“我替你拦下来的人,比那位爷能叫来的多。价钱也公道。” “三成五。”他说。他站在阴影里,声音从胸腔里压出来,比古斯普那种滑下来的声调重得多。“我替你拦下来的人,比那位爷能叫来的多。价钱也公道。”
他身后那个随从把铁匣盖打开,让Ral看。铜锭在阴天的光里发暗,颜色像干了的血。 他身后那个随从把铁匣盖打开,让拉尔看。铜锭在阴天的光里发暗,颜色像干了的血。
Ral没看那只铁匣。她看的是Tulon的靴子。靴面上有泥,泥是红的,从隘口外的坡道上带回来的。她认得那种土。 拉尔没看那只铁匣。她看的是图隆的靴子。靴面上有泥,泥是红的,从隘口外的坡道上带回来的。她认得那种土。
“这三成五,”她说,“是给我,还是给你后面那一串?” “这三成五,”她说,“是给我,还是给你后面那一串?”
Tulon的脸动了一下。他没笑。他把铁匣盖合上,示意随从退后一步。 图隆的脸动了一下。他没笑。他把铁匣盖合上,示意随从退后一步。
“你要是问这个,”他说,“我就没法跟你谈。” “你要是问这个,”他说,“我就没法跟你谈。”
“那就别谈。”Ral说。她转身往岗哨那边走。走到墙根时,她听见Tulon在身后补了一句,声音还是那种压得很低的腔调: “那就别谈。”拉尔说。她转身往岗哨那边走。走到墙根时,她听见图隆在身后补了一句,声音还是那种压得很低的腔调:
“下次来,可就不是铜了。” “下次来,可就不是铜了。”
Ral没回头。她回到岗哨屋里,把门掩上,在桌前站了一会儿。桌上摊着她自己的账册,账册里记的是这一个月的通行数和税。她把Tulon的名字写进另一本册子的封皮内侧,写完又划掉,重新写。划掉的那道墨痕她没擦,留着。 拉尔没回头。她回到岗哨屋里,把门掩上,在桌前站了一会儿。桌上摊着她自己的账册,账册里记的是这一个月的通行数和税。她把图隆的名字写进另一本册子的封皮内侧,写完又划掉,重新写。划掉的那道墨痕她没擦,留着。
之后她让人把Rigoth叫来。 之后她让人把里戈斯叫来。
Rigoth来的时候天还没全黑,岗哨屋里的油灯点了一盏,火苗缩在灯芯上,一跳一跳的。Ral把两只册子都推到他面前。 里戈斯来的时候天还没全黑,岗哨屋里的油灯点了一盏,火苗缩在灯芯上,一跳一跳的。拉尔把两只册子都推到他面前。
“以后,”她说,“凡是有外头的人来找我,不论开口的是谁,手里拿的是纸、是铜、还是别的,你都给我记下来。找我的时辰,在哪找的,带了什么,说了什么,一句都不许漏。” “以后,”她说,“凡是有外头的人来找我,不论开口的是谁,手里拿的是纸、是铜、还是别的,你都给我记下来。找我的时辰,在哪找的,带了什么,说了什么,一句都不许漏。”
Rigoth把册子翻开,看了一眼第一页。他没问为什么。他把墨瓶推到自己这边,又从怀里摸出一支秃头的鹅毛笔。 里戈斯把册子翻开,看了一眼第一页。他没问为什么。他把墨瓶推到自己这边,又从怀里摸出一支秃头的鹅毛笔。
“连威胁也记?”他问。 “连威胁也记?”他问。
“连威胁也记。”Ral说。 “连威胁也记。”拉尔说。
Rigoth点了点头,低头在第一页顶上写了日期,写完停了一下,又在日期下头加了三个小字:Guspu,Tulon。他写完把笔搁下,抬头看Ral。 里戈斯点了点头,低头在第一页顶上写了日期,写完停了一下,又在日期下头加了三个小字:古斯普,图隆。他写完把笔搁下,抬头看拉尔。
Ral站在灯边。她脸上没多余的表情,眼底那点东西也压得很平。她看着Rigoth手里那支秃笔,看了一会儿,说: 拉尔站在灯边。她脸上没多余的表情,眼底那点东西也压得很平。她看着里戈斯手里那支秃笔,看了一会儿,说:
“我不信他们是单独来的。” “我不信他们是单独来的。”
Rigoth没接话。他把册子合上,夹在腋下,站起身往外走。走到门口他停了一下,回头: 里戈斯没接话。他把册子合上,夹在腋下,站起身往外走。走到门口他停了一下,回头:
“那Falcon那边呢?” “那隼族那边呢?”
Falcon那边指的是她自己这一族的议事。Ral把手套重新戴上,拉了拉指根。 隼族那边指的是她自己这一族的议事。拉尔把手套重新戴上,拉了拉指根。
“先记,”她说,“先别送过去。等他们自己来问。” “先记,”她说,“先别送过去。等他们自己来问。”
Rigoth“嗯”了一声,出了门。门在风里晃了两下,最后贴上门框,把那点灯光夹在屋里,没让它漏出去。 里戈斯“嗯”了一声,出了门。门在风里晃了两下,最后贴上门框,把那点灯光夹在屋里,没让它漏出去。
194年的冬天比往年早。 194年的冬天比往年早。
Ral Fastenhatchets揣着账册往本家议事堂走的时候,巷子里的冻土还在前一年的积雪下面硬着,踩上去鞋底能听见碎响。她没穿厚衣服,矮个子在风里走快了反而不冷,鼻尖和耳廓冻得发木。账册是本家这些年的进出,从The Volcano Of Ravens分出来的Fordedwinds每一笔都记在上头。她要的不是议事堂,是议事堂后头那道矮门,矮门里头连着鹰人审判庭。鹰人不审本家的人,但账册上的事能定罪,定罪了本家才能动。 拉尔·缚斧揣着账册往本家议事堂走的时候,巷子里的冻土还在前一年的积雪下面硬着,踩上去鞋底能听见碎响。她没穿厚衣服,矮个子在风里走快了反而不冷,鼻尖和耳廓冻得发木。账册是本家这些年的进出,从渡鸦火山分出来的涉风渡每一笔都记在上头。她要的不是议事堂,是议事堂后头那道矮门,矮门里头连着鹰人审判庭。鹰人不审本家的人,但账册上的事能定罪,定罪了本家才能动。
矮门前站着两个鹰人,看了她一眼,没拦。Ral把账册递过去,说:“请把这份呈给审判庭。立案的话,被告是Guspu Frillyknots,罪名是他试图收买Fordedwinds的守门人。”她停了一下,又说:“这里记了每一次。” 矮门前站着两个鹰人,看了她一眼,没拦。拉尔把账册递过去,说:“请把这份呈给审判庭。立案的话,被告是古斯普·褶结,罪名是他试图收买涉风渡的守门人。”她停了一下,又说:“这里记了每一次。”
审判庭不大,木头的长椅,旧挂毯。Ral坐在证人席的椅子上,椅背硬,靠上去肩胛骨硌得慌。她没靠实,只挨着椅子边坐。Guspu Frillyknots被两个鹰人架着带进来。他没戴枷,矮凳上坐下,手搁在腿边,看了她一眼。Ral没避开。她把账册里自己圈出来的几页递给主审的鹰人,说:“第一页是他许给守门人的东西,第五页是守门人交回来的东西,第十一页是他第二次让人转交给我的话。”主审翻到第十一页,问:“这是你的笔迹?”Ral说:“是他让人转交的。我没回。”主审又问:“你为什么记下来?”Ral说:“因为他不只做了一次。” 审判庭不大,木头的长椅,旧挂毯。拉尔坐在证人席的椅子上,椅背硬,靠上去肩胛骨硌得慌。她没靠实,只挨着椅子边坐。古斯普·褶结被两个鹰人架着带进来。他没戴枷,矮凳上坐下,手搁在腿边,看了她一眼。拉尔没避开。她把账册里自己圈出来的几页递给主审的鹰人,说:“第一页是他许给守门人的东西,第五页是守门人交回来的东西,第十一页是他第二次让人转交给我的话。”主审翻到第十一页,问:“这是你的笔迹?”拉尔说:“是他让人转交的。我没回。”主审又问:“你为什么记下来?”拉尔说:“因为他不只做了一次。”
判决很快。Guspu Frillyknots构陷守门人成立。鹰人把Guspu往门口带,门还没关,门被人从外头撞开,Momuz冲进来。 判决很快。古斯普·褶结构陷守门人成立。鹰人把古斯普往门口带,门还没关,门被人从外头撞开,莫穆兹冲进来。
Momuz比Ral高半头,冲进来的时候差点撞上带人的鹰人。她退了一步,绕过鹰人,冲Ral喊:“你为什么不先跟我说?”声音在审判庭里撞了几个来回,比平常高出许多。 莫穆兹比拉尔高半头,冲进来的时候差点撞上带人的鹰人。她退了一步,绕过鹰人,冲拉尔喊:“你为什么不先跟我说?”声音在审判庭里撞了几个来回,比平常高出许多。
Ral从证人席上下来,看了看Momuz,看了看门口的鹰人,又看了看被架着的Guspu。她走近Momuz一步,说:“你早替他说话了。” 拉尔从证人席上下来,看了看莫穆兹,看了看门口的鹰人,又看了看被架着的古斯普。她走近莫穆兹一步,说:“你早替他说话了。”
Momuz的手抬起来,又放下。她看了看Ral,看了看门口的Guspu,没再说话,转身就往门外走。走到门口停了一下,没回头,又接着走。门在她身后合上,木头碰木头,沉闷的一声。 莫穆兹的手抬起来,又放下。她看了看拉尔,看了看门口的古斯普,没再说话,转身就往门外走。走到门口停了一下,没回头,又接着走。门在她身后合上,木头碰木头,沉闷的一声。
Ral站在审判庭里,看着合上的门。她知道这门一关,她们十几年的交情从今天起就变了。往外走的时候手还扶着账册的封皮,封皮上有茶渍,那是Momuz前天坐她家喝茶时洒的。她把账册收进袖筒里,没擦。 拉尔站在审判庭里,看着合上的门。她知道这门一关,她们十几年的交情从今天起就变了。往外走的时候手还扶着账册的封皮,封皮上有茶渍,那是莫穆兹前天坐她家喝茶时洒的。她把账册收进袖筒里,没擦。
她以为定罪能结束这一切。 她以为定罪能结束这一切。
Guspu Frillyknots在审判庭关了没几天就被放了出来。Ral是从Fordedwinds守门人那里听说的。她没去问为什么。第二天本家议事里她提了一句:“Guspu Frillyknots回了Fordedwinds。”没人答。议事散了,她一个人坐了一会儿,把账册里Guspu那一页折了个角。 古斯普·褶结在审判庭关了没几天就被放了出来。拉尔是从涉风渡守门人那里听说的。她没去问为什么。第二天本家议事里她提了一句:“古斯普·褶结回了涉风渡。”没人答。议事散了,她一个人坐了一会儿,把账册里古斯普那一页折了个角。
195年开春,Fordedwinds的守门人又来找她。守门人是本家的老人,比Ral大四十岁,没进Ral的屋,站在门口说:“Guspu Frillyknots又让人送东西来了。是Momuz送的。一个箱子,还有口信。”Ral问:“口信说什么?”守门人说:“让你‘先收一笔’。”Ral说:“箱子你收着,我不进门。” 195年开春,涉风渡的守门人又来找她。守门人是本家的老人,比拉尔大四十岁,没进拉尔的屋,站在门口说:“古斯普·褶结又让人送东西来了。是莫穆兹送的。一个箱子,还有口信。”拉尔问:“口信说什么?”守门人说:“让你‘先收一笔’。”拉尔说:“箱子你收着,我不进门。”
守门人走了。她关上门,背靠着门站了一会儿。箱子里的东西她不看,Guspu让人转交的东西她从来不看。她知道里头是什么,知道里头是什么的时候,看不看都一样。 守门人走了。她关上门,背靠着门站了一会儿。箱子里的东西她不看,古斯普让人转交的东西她从来不看。她知道里头是什么,知道里头是什么的时候,看不看都一样。
Momuz那天晚上来找她。 莫穆兹那天晚上来找她。
Momuz进Ral的屋,没坐,站在桌边,把Guspu给她的箱子又提了过来。箱子不大,盖子是木头的,没上锁。Momuz把箱子往Ral这一侧推了推,说:“他让我带给你的。”Ral没看箱子。她抬头看Momuz的脸。Momuz的脸比白天更白,下巴绷着,嘴唇干。Ral说:“你转告他,他越这样,我越不会松手。” 莫穆兹进拉尔的屋,没坐,站在桌边,把古斯普给她的箱子又提了过来。箱子不大,盖子是木头的,没上锁。莫穆兹把箱子往拉尔这一侧推了推,说:“他让我带给你的。”拉尔没看箱子。她抬头看莫穆兹的脸。莫穆兹的脸比白天更白,下巴绷着,嘴唇干。拉尔说:“你转告他,他越这样,我越不会松手。”
Momuz的手从箱子上挪开,搁到自己腿上。她低着头,看着自己搁在腿上的手,看了很久,然后说:“他救过我弟弟的命。我还不掉。” 莫穆兹的手从箱子上挪开,搁到自己腿上。她低着头,看着自己搁在腿上的手,看了很久,然后说:“他救过我弟弟的命。我还不掉。”
Ral的嘴张了一下,又合上。她看着Momuz肩塌着、下巴抵着锁骨的样子,知道Momuz没骗她。Guspu Frillyknots那年从流民里把Momuz的弟弟救出来是真的,Momuz记了十几年也是真的。她以前只知道Guspu用钱砸她,现在才知道Guspu用别的东西砸Momuz。 拉尔的嘴张了一下,又合上。她看着莫穆兹肩塌着、下巴抵着锁骨的样子,知道莫穆兹没骗她。古斯普·褶结那年从流民里把莫穆兹的弟弟救出来是真的,莫穆兹记了十几年也是真的。她以前只知道古斯普用钱砸她,现在才知道古斯普用别的东西砸莫穆兹。
Momuz没等她答,提起箱子就往外走。Ral跟着走到门口,看着Momuz的背影穿过巷子。Momuz走得不快,背影被巷口的灯拉得很长,又被巷子收短。Momuz走远,她关了门。 莫穆兹没等她答,提起箱子就往外走。拉尔跟着走到门口,看着莫穆兹的背影穿过巷子。莫穆兹走得不快,背影被巷口的灯拉得很长,又被巷子收短。莫穆兹走远,她关了门。
她第一次动摇,不是因为钱,是因为Momuz低头的样子。关了门,没点灯,在黑里站了一会儿,又把门打开,让灯透进来。她站在门里,把账册里有关Momuz弟弟那一页折了个角,又把角抹平。她不记,又想折好。最后把账册搁在桌上,没动。 她第一次动摇,不是因为钱,是因为莫穆兹低头的样子。关了门,没点灯,在黑里站了一会儿,又把门打开,让灯透进来。她站在门里,把账册里有关莫穆兹弟弟那一页折了个角,又把角抹平。她不记,又想折好。最后把账册搁在桌上,没动。
Tulon Tongswall那年也来过一次。Tulon是本家的另一房,比Ral小一辈,平时不来Fordedwinds。那天他来,是替Guspu Frillyknots送东西。Ral在议事堂后头的过道里截住他,问:“你来做什么?”Tulon说:“给Guspu叔送点东西。”Ral说:“这里不收Guspu Frillyknots的东西。”Tulon看了她一眼,没说话,提着东西出了议事堂。 图隆·钳墙那年也来过一次。图隆是本家的另一房,比拉尔小一辈,平时不来涉风渡。那天他来,是替古斯普·褶结送东西。拉尔在议事堂后头的过道里截住他,问:“你来做什么?”图隆说:“给古斯普叔送点东西。”拉尔说:“这里不收古斯普·褶结的东西。”图隆看了她一眼,没说话,提着东西出了议事堂。
Ral站在过道里,看着Tulon走出去,没去拦。站到腿酸,才回自己的屋。 拉尔站在过道里,看着图隆走出去,没去拦。站到腿酸,才回自己的屋。
那年冬天还冷。Fordedwinds外头的河道冻了一层薄冰,议事堂侧门一推开,冷得人眼睛发涩。Ral坐在桌前,桌角搁着昨天没合上的账册。Rigoth从外头进来,靴子上带着泥,雪水还没干透,把一只陶碗放在她面前。碗里是热的,冒出一股焦味。 那年冬天还冷。涉风渡外头的河道冻了一层薄冰,议事堂侧门一推开,冷得人眼睛发涩。拉尔坐在桌前,桌角搁着昨天没合上的账册。里戈斯从外头进来,靴子上带着泥,雪水还没干透,把一只陶碗放在她面前。碗里是热的,冒出一股焦味。
Rigoth说:“他们又派Tulon来了。” 里戈斯说:“他们又派图隆来了。”
Ral没抬头。她把账册翻到上个月那一页,看见自己用炭条画的那道杠还在,杠下面空白。Rigoth又说:“在议事堂外头,我没让他进来。”Ral嗯了一声,把账册合上,搁在桌角。Rigoth站着,等她开口。 拉尔没抬头。她把账册翻到上个月那一页,看见自己用炭条画的那道杠还在,杠下面空白。里戈斯又说:“在议事堂外头,我没让他进来。”拉尔嗯了一声,把账册合上,搁在桌角。里戈斯站着,等她开口。
Ral说:“他几时到的?” 拉尔说:“他几时到的?”
“天没亮。”Rigoth说,“他带了一只木匣,匣上没封,里头是一块布包着的东西。我没让他打开。” “天没亮。”里戈斯说,“他带了一只木匣,匣上没封,里头是一块布包着的东西。我没让他打开。”
Ral这才抬头。她看着Rigoth的脸,看见她丈夫下颌骨的棱角比去年更瘦。Rigoth又说:“我让他在门外等着。他站了一刻钟,自己走了。匣子没留下,搁在台阶上。我把它搬进库房了,没打开。” 拉尔这才抬头。她看着里戈斯的脸,看见她丈夫下颌骨的棱角比去年更瘦。里戈斯又说:“我让他在门外等着。他站了一刻钟,自己走了。匣子没留下,搁在台阶上。我把它搬进库房了,没打开。”
Ral把账册又翻开,摊在桌上。她从桌边那只小木盒里取出一根炭条,在空白处写下今天的日期,又在日期下面写:Tulon Tongswall,晨,议事堂外,未入。写完,她把炭条搁回盒里。 拉尔把账册又翻开,摊在桌上。她从桌边那只小木盒里取出一根炭条,在空白处写下今天的日期,又在日期下面写:图隆·钳墙,晨,议事堂外,未入。写完,她把炭条搁回盒里。
Rigoth说:“要不要我去库房看看那块布?” 里戈斯说:“要不要我去库房看看那块布?”
“不要。”Ral说,“先搁着。” “不要。”拉尔说,“先搁着。”
Rigoth站在那里,又等了一会儿。Ral把账册合上,搁在桌角,站起来,走到门边,把门推开一线。冷风灌进来,吹得桌上那根刚搁下的炭条滚了两寸。Rigoth走过去,把炭条拾起来,放回盒里。 里戈斯站在那里,又等了一会儿。拉尔把账册合上,搁在桌角,站起来,走到门边,把门推开一线。冷风灌进来,吹得桌上那根刚搁下的炭条滚了两寸。里戈斯走过去,把炭条拾起来,放回盒里。
Ral站在门边,背对着Rigoth,说:“他们要把我拖到没人信我的那天。” 拉尔站在门边,背对着里戈斯,说:“他们要把我拖到没人信我的那天。”
Rigoth没说话。他把账册从桌角拿起来,搁到柜子里,把柜门合上。他问:“你还要记吗?” 里戈斯没说话。他把账册从桌角拿起来,搁到柜子里,把柜门合上。他问:“你还要记吗?”
“记。”Ral说,“记到他们不敢再来,或者我不在了。” “记。”拉尔说,“记到他们不敢再来,或者我不在了。”
Rigoth没接话。他走到门边,把门关上,把门闩落下来。屋子里一下子暗下来,只有桌上那盏油灯还亮着。Ral转过身,看着那盏灯。Rigoth说:“我去库房看一眼。”Ral点点头。Rigoth开门出去,把门带上,靴子踩在雪地上,声音一下一下远了。 里戈斯没接话。他走到门边,把门关上,把门闩落下来。屋子里一下子暗下来,只有桌上那盏油灯还亮着。拉尔转过身,看着那盏灯。里戈斯说:“我去库房看一眼。”拉尔点点头。里戈斯开门出去,把门带上,靴子踩在雪地上,声音一下一下远了。
Ral站在门里,听见脚步声拐过屋角,听不见了。她把柜门打开,把账册取出来,翻到今天那一页,又看了一遍。她在Tulon那一行下面加了一句话:木匣未封,布包,未启。写完,她把账册合上,搁回柜里。 拉尔站在门里,听见脚步声拐过屋角,听不见了。她把柜门打开,把账册取出来,翻到今天那一页,又看了一遍。她在图隆那一行下面加了一句话:木匣未封,布包,未启。写完,她把账册合上,搁回柜里。
Rigoth回来的时候,Ral已经坐在桌前,手里捏着一只空碗。Rigoth说:“布包里是一块铁印,印上刻的是Guspu Frillyknots的徽。”Ral没说话。Rigoth又说:“印背刻了一行小字,认不全,只认得‘Fordedwinds’和‘三成’。” 里戈斯回来的时候,拉尔已经坐在桌前,手里捏着一只空碗。里戈斯说:“布包里是一块铁印,印上刻的是古斯普·褶结的徽。”拉尔没说话。里戈斯又说:“印背刻了一行小字,认不全,只认得‘涉风渡’和‘三成’。”
Ral把空碗搁在桌上,说:“收起来。”Rigoth说:“收到哪里?”Ral说:“收到库房最里头那口箱子里,箱子压上去年那批铁。”Rigoth点点头,又出去了一趟。Ral坐在桌前,听见他开库房门,听见铁块挪动的声音,听见他回来,把库房门锁上。 拉尔把空碗搁在桌上,说:“收起来。”里戈斯说:“收到哪里?”拉尔说:“收到库房最里头那口箱子里,箱子压上去年那批铁。”里戈斯点点头,又出去了一趟。拉尔坐在桌前,听见他开库房门,听见铁块挪动的声音,听见他回来,把库房门锁上。
那年冬天剩下的日子,Ral每天早起,第一件事是翻开账册,在当天那一行写下日期,再把昨天的事补完。Tulon没再来。Rigoth每天清早扫台阶,把台阶上的脚印扫掉。 那年冬天剩下的日子,拉尔每天早起,第一件事是翻开账册,在当天那一行写下日期,再把昨天的事补完。图隆没再来。里戈斯每天清早扫台阶,把台阶上的脚印扫掉。
到了第二年开春,Fordedwinds外头的冰化了,河道又开始流。Ral那天在议事堂后头的过道里截住一个人。那人比Ral高一个头,肩上披着一件灰布,灰布下露出一截细长的嘴,嘴尖拱起,像个小铲。那人见Ral挡在路中间,停下脚步。 到了第二年开春,涉风渡外头的冰化了,河道又开始流。拉尔那天在议事堂后头的过道里截住一个人。那人比拉尔高一个头,肩上披着一件灰布,灰布下露出一截细长的嘴,嘴尖拱起,像个小铲。那人见拉尔挡在路中间,停下脚步。
Ral说:“Astri Flayerline。” 拉尔说:“阿斯特里·剥血。”
Astri Flayerline点点头,说:“Ral Fastenhatchets。”Ral说:“你来做什么?”Astri Flayerline说:“替Guspu Frillyknots问一句话。”Ral问:“哪一句?”Astri Flayerline说:“你肯不肯收那三成。” 阿斯特里·剥血点点头,说:“拉尔·缚斧。”拉尔说:“你来做什么?”阿斯特里·剥血说:“替古斯普·褶结问一句话。”拉尔问:“哪一句?”阿斯特里·剥血说:“你肯不肯收那三成。”
Ral靠着墙,手背在身后摸着墙缝里那块石头。那块石头是早年搬到路口的,棱角早磨没了,圆圆的一块,搁在墙缝里,正好填住那道缝。她摸到石头凸起的那一面,手指停下来。 拉尔靠着墙,手背在身后摸着墙缝里那块石头。那块石头是早年搬到路口的,棱角早磨没了,圆圆的一块,搁在墙缝里,正好填住那道缝。她摸到石头凸起的那一面,手指停下来。
她说:“你回去告诉Guspu Frillyknots,他那块铁印还在我库房里。” 她说:“你回去告诉古斯普·褶结,他那块铁印还在我库房里。”
Astri Flayerline没说话。他看了她一眼,又看了一眼她身后那道墙缝。Ral说:“他还带什么话来?” 阿斯特里·剥血没说话。他看了她一眼,又看了一眼她身后那道墙缝。拉尔说:“他还带什么话来?”
Astri Flayerline说:“他说,下一个被定罪的是你。” 阿斯特里·剥血说:“他说,下一个被定罪的是你。”
Ral笑了。她松开手,从墙缝里抽出那块石头,搁在地上。石头落在过道的石板上,响了一声。她弯腰把石头拾起来,又塞回墙缝。石头比她手心凉。 拉尔笑了。她松开手,从墙缝里抽出那块石头,搁在地上。石头落在过道的石板上,响了一声。她弯腰把石头拾起来,又塞回墙缝。石头比她手心凉。
她说:“Rigoth。” 她说:“里戈斯。”
Rigoth从过道另一头走过来。他手里拿着一本账册,账册是新换的,封皮上还沾着木屑。他看了Astri Flayerline一眼,没说话。Ral说:“把Astri也记上去。” 里戈斯从过道另一头走过来。他手里拿着一本账册,账册是新换的,封皮上还沾着木屑。他看了阿斯特里·剥血一眼,没说话。拉尔说:“把阿斯特里也记上去。”
Rigoth把账册翻开,翻到新的一页。他从腰间抽出一根炭条,在新一页上写下日期,又在日期下面写:Astri Flayerline,春,过道,替Guspu Frillyknots问三成。写完,他把炭条递回腰间,把账册合上,搁在腋下。 里戈斯把账册翻开,翻到新的一页。他从腰间抽出一根炭条,在新一页上写下日期,又在日期下面写:阿斯特里·剥血,春,过道,替古斯普·褶结问三成。写完,他把炭条递回腰间,把账册合上,搁在腋下。
Astri Flayerline站在过道里,看了Ral一眼,又看了一眼Rigoth腋下那本账册。Ral说:“你走的时候,从议事堂正门出,不要走后头的门。”Astri Flayerline没接话,转身往议事堂正门方向走。Ral看着他走远,背影拐过墙角,看不见了。 阿斯特里·剥血站在过道里,看了拉尔一眼,又看了一眼里戈斯腋下那本账册。拉尔说:“你走的时候,从议事堂正门出,不要走后头的门。”阿斯特里·剥血没接话,转身往议事堂正门方向走。拉尔看着他走远,背影拐过墙角,看不见了。
Ral蹲下来,把墙缝里那块石头又摸了一遍。石头比她手心凉,凉得手心发麻。她把手抽出来,在裤腿上蹭了两下,站起来。 拉尔蹲下来,把墙缝里那块石头又摸了一遍。石头比她手心凉,凉得手心发麻。她把手抽出来,在裤腿上蹭了两下,站起来。
Rigoth说:“回去?” 里戈斯说:“回去?”
Ral说:“等会儿。” 拉尔说:“等会儿。”
她站在墙缝前,看着那块石头。去年冬天,石头边上落了一层薄雪,雪水化进墙缝里,缝里的土比别处黑。今年开春,雪化得早,墙缝里的土干了,颜色比墙外头的石板浅。她伸手在石头上按了一下,石头没动,还是卡在缝里。 她站在墙缝前,看着那块石头。去年冬天,石头边上落了一层薄雪,雪水化进墙缝里,缝里的土比别处黑。今年开春,雪化得早,墙缝里的土干了,颜色比墙外头的石板浅。她伸手在石头上按了一下,石头没动,还是卡在缝里。
Rigoth说:“还磨?” 里戈斯说:“还磨?”
Ral说:“不磨。”她把手收回来,转身往议事堂走。Rigoth跟在她后头,手里还夹着那本账册。过道里的风比外头暖,带着议事堂里头烧水的气味。 拉尔说:“不磨。”她把手收回来,转身往议事堂走。里戈斯跟在她后头,手里还夹着那本账册。过道里的风比外头暖,带着议事堂里头烧水的气味。
Ral走到议事堂门口,没进去,转身对Rigoth说:“今天的事,回去补上。”Rigoth点点头,把账册从腋下取出来,翻开,又在Astri那一行下面加了一句:又言,下一个被定罪的是她。写完,他把账册合上。 拉尔走到议事堂门口,没进去,转身对里戈斯说:“今天的事,回去补上。”里戈斯点点头,把账册从腋下取出来,翻开,又在阿斯特里那一行下面加了一句:又言,下一个被定罪的是她。写完,他把账册合上。
Ral说:“走。” 拉尔说:“走。”
两个人往回走。过道拐角处,墙上那块石头还卡在缝里,没掉下来。石头边上有一道她刚按出来的手印,手印比石头凉。 两个人往回走。过道拐角处,墙上那块石头还卡在缝里,没掉下来。石头边上有一道她刚按出来的手印,手印比石头凉。
+18 -18
View File
@@ -1,39 +1,39 @@
# 守门人 # 守门人
181年的Fordedwinds还没有名字。Ral Fastenhatchets站在那条冻硬的隘口,面前是Langgud Tradebears The Eviscerated Chill Of Pregnancies——一个Yeti,比她高两倍,呼出的气能把胡子结冰。她本可以退回矿洞,但她留了下来。两次照面之后,Langgud再也没出现在Fordedwinds,Ral也不确定自己是赢了,还是对方改了主意。她只做了一件事:把一块石头搬到路口,当作凭证——要过Fordedwinds,先问她。 181年的涉风渡还没有名字。拉尔·缚斧站在那条冻硬的隘口,面前是朗古德·商熊「剖胎之寒」——一个雪人,比她高两倍,呼出的气能把胡子结冰。她本可以退回矿洞,但她留了下来。两次照面之后,朗古德再也没出现在涉风渡,拉尔也不确定自己是赢了,还是对方改了主意。她只做了一件事:把一块石头搬到路口,当作凭证——要过涉风渡,先问她。
从那一刻起,她的目标就写得很清楚:Fordedwinds不做任何人的附庸。她卖通行权,但只卖一次,绝不签卖身契。 从那一刻起,她的目标就写得很清楚:涉风渡不做任何人的附庸。她卖通行权,但只卖一次,绝不签卖身契。
188年,Rigoth Stilledearthen来投奔她。这老矮人带着一本账册,说愿意替她记下每一笔过路钱。Ral收留了他。同年,一个鹰人出现在Fordedwinds的市场上。Guspu Frillyknots。他不住店,不买货,只和Momuz Fateddie说话。Momuz是Ral从小的邻居,替她管着粮仓。Ral远远看着,没有上前。她后来对Rigoth说:“去查查那只鹰为什么总找Momuz。” 188年,里戈斯·静土来投奔她。这老矮人带着一本账册,说愿意替她记下每一笔过路钱。拉尔收留了他。同年,一个鹰人出现在涉风渡的市场上。古斯普·褶结。他不住店,不买货,只和莫穆兹·命终说话。莫穆兹是拉尔从小的邻居,替她管着粮仓。拉尔远远看着,没有上前。她后来对里戈斯说:“去查查那只鹰为什么总找莫穆兹。”
Rigoth没查出结果,只记下一条:Guspu Frillyknots与Momuz Fateddie结了契。Ral把这句话念了两遍,最后只说:“她自己的事。” 里戈斯没查出结果,只记下一条:古斯普·褶结与莫穆兹·命终结了契。拉尔把这句话念了两遍,最后只说:“她自己的事。”
193年,Guspu第一次找上Ral。他在隘口摆了一张矮桌,拿着一卷盖满章的羊皮纸。他说话的声音像从高处滑下来:“你守着一条路,却没有保护者。我可以让Fordedwinds免受任何骚扰,只需要你在通行税里分三成给我。” 193年,古斯普第一次找上拉尔。他在隘口摆了一张矮桌,拿着一卷盖满章的羊皮纸。他说话的声音像从高处滑下来:“你守着一条路,却没有保护者。我可以让涉风渡免受任何骚扰,只需要你在通行税里分三成给我。”
Ral没碰那卷纸。她问他:“那三成,是给你,还是给你后面的人?” 拉尔没碰那卷纸。她问他:“那三成,是给你,还是给你后面的人?”
Guspu笑了:“你不问,我就不说。这是体面。” 古斯普笑了:“你不问,我就不说。这是体面。”
Ral把羊皮纸推回去:“我买过你的体面吗?” 拉尔把羊皮纸推回去:“我买过你的体面吗?”
同年Tulon Tongswall也来试探,开价更直白。Ral同样拒绝。她开始让Rigoth把每一次贿赂、每一次威胁都记下来。她不信这些人是单独来的。 同年图隆·钳墙也来试探,开价更直白。拉尔同样拒绝。她开始让里戈斯把每一次贿赂、每一次威胁都记下来。她不信这些人是单独来的。
194年,Ral把账册送到The Volcano Of Ravens。她不是去求公正,是去逼他们立案。她在审判庭上只说了两句:一句是“Guspu Frillyknots试图收买Fordedwinds的守门人”,另一句是“这里记了每一次”。Guspu被定罪。鹰人被带走时,Momuz冲进审判庭,冲Ral喊:“你为什么不先跟我说?” 194年,拉尔把账册送到渡鸦火山。她不是去求公正,是去逼他们立案。她在审判庭上只说了两句:一句是“古斯普·褶结试图收买涉风渡的守门人”,另一句是“这里记了每一次”。古斯普被定罪。鹰人被带走时,莫穆兹冲进审判庭,冲拉尔喊:“你为什么不先跟我说?”
Ral看着朋友:“你早替他说话了。” 拉尔看着朋友:“你早替他说话了。”
Momuz没再说话。她们十几年的交情从那天起裂了。 莫穆兹没再说话。她们十几年的交情从那天起裂了。
Ral以为定罪能结束这一切。她错了。 拉尔以为定罪能结束这一切。她错了。
195年,Guspu虽然被定罪,人却没被关多久。他回到Fordedwinds,不再亲自出面,改为让Momuz转交口信和箱子。箱子里的东西Ral从来不看。她对Momuz说:“你转告他,他越这样,我越不会松手。”Momuz低着头说:“他救过我弟弟的命。我还不掉。”Ral第一次动摇,不是因为钱,而是因为朋友被夹在中间。 195年,古斯普虽然被定罪,人却没被关多久。他回到涉风渡,不再亲自出面,改为让莫穆兹转交口信和箱子。箱子里的东西拉尔从来不看。她对莫穆兹说:“你转告他,他越这样,我越不会松手。”莫穆兹低着头说:“他救过我弟弟的命。我还不掉。”拉尔第一次动摇,不是因为钱,而是因为朋友被夹在中间。
197年,Tulon又来了,像闻到伤口的狼。Ral在夜里对Rigoth说:“他们要把我拖到没人信我的那天。”Rigoth合上账册,只问了一句:“你还要记吗?” 197年,图隆又来了,像闻到伤口的狼。拉尔在夜里对里戈斯说:“他们要把我拖到没人信我的那天。”里戈斯合上账册,只问了一句:“你还要记吗?”
“记。”她说,“记到他们不敢再来,或者我不在了。” “记。”她说,“记到他们不敢再来,或者我不在了。”
198年,Astri Flayerline出现在同样的路口,带着同样的问题,只是多了一点新东西:他不仅出价,还威胁说,如果Ral不合作,下一个被定罪的就是她。Ral笑了。她第一次意识到,真正的转折不在194年的定罪,而在于她终于明白:Guspu要的不是那三成税,而是让她也欠他,让她低头。她偏不。 198年,阿斯特里·剥血出现在同样的路口,带着同样的问题,只是多了一点新东西:他不仅出价,还威胁说,如果拉尔不合作,下一个被定罪的就是她。拉尔笑了。她第一次意识到,真正的转折不在194年的定罪,而在于她终于明白:古斯普要的不是那三成税,而是让她也欠他,让她低头。她偏不。
她站在那块当年搬到路口的石头边,对Rigoth说:“把Astri也记上去。” 她站在那块当年搬到路口的石头边,对里戈斯说:“把阿斯特里也记上去。”
Rigoth翻开新的一页。石头上落了一层薄雪。 里戈斯翻开新的一页。石头上落了一层薄雪。
+15 -15
View File
@@ -1,41 +1,41 @@
# 围账 # 围账
回到 Fordedwinds 后,Guspu Frillyknots 没有再去见 Ral Fastenhatchets,也没有去找 Momuz。他做的第一件事,是约了 Perom Crazeowned 喝酒。Perom 是个做皮革生意的男人,不算有势力,但认识所有该认识的人。Guspu 问他:“被定罪的人,还能不能让人替他记账?”Perom 没答,只敬了他一杯酒。 回到涉风渡后,古斯普·褶结没有再去见拉尔·缚斧,也没有去找莫穆兹。他做的第一件事,是约了佩罗姆·狂据喝酒。佩罗姆是个做皮革生意的男人,不算有势力,但认识所有该认识的人。古斯普问他:“被定罪的人,还能不能让人替他记账?”佩罗姆没答,只敬了他一杯酒。
202 年,Perom 点了头。203 年,山民 Espu Bonestands 带着盐下山求见,Guspu 收下盐,让 Espu 守在北门外。矮人 Lolor Bronzescorched 也来了,她要矿区里的一个位置。Guspu 给了她名字,也给了活儿:盯住一切往东走的货。207 年,女 Goblin Dostngosp Jackalbrims 也把名字投到他门下。 202 年,佩罗姆点了头。203 年,山民埃斯普·骨立带着盐下山求见,古斯普收下盐,让埃斯普守在北门外。矮人洛洛尔·铜焦也来了,她要矿区里的一个位置。古斯普给了她名字,也给了活儿:盯住一切往东走的货。207 年,女哥布林多斯特恩戈斯普·豺帽也把名字投到他门下。
到那一年,他手里有人,也有位置。于是他决定对 Ral 动手。 到那一年,他手里有人,也有位置。于是他决定对拉尔动手。
那是一次构陷。他要在 The Volcano Of Ravens 的公堂上,给 Ral 安个贪税的罪名。他准备了伪造的账页,又借来几个信得过的喉咙。Ral 在城门口被拦下,背着一包账本上堂。有人递上那几页纸,说这是她的手迹。 那是一次构陷。他要在渡鸦火山的公堂上,给拉尔安个贪税的罪名。他准备了伪造的账页,又借来几个信得过的喉咙。拉尔在城门口被拦下,背着一包账本上堂。有人递上那几页纸,说这是她的手迹。
Ral 翻了一遍,抬头问:“谁写的?” 拉尔翻了一遍,抬头问:“谁写的?”
堂上没人应。 堂上没人应。
她说:“这墨不是我的。我记账不用这种纸。” 她说:“这墨不是我的。我记账不用这种纸。”
官差面面相觑。Guspu 在堂外没动。他算过她会争辩,没算过她随身带着十年的旧账,纸色、墨线、装订线一模一样。她翻开旧账,一页一页比对。堂上慢慢安静下来。 官差面面相觑。古斯普在堂外没动。他算过她会争辩,没算过她随身带着十年的旧账,纸色、墨线、装订线一模一样。她翻开旧账,一页一页比对。堂上慢慢安静下来。
构陷失败了。 构陷失败了。
Ral 走出公堂时没有看 Guspu。她只对身旁的人说:“回去把今天记下来。” 拉尔走出公堂时没有看古斯普。她只对身旁的人说:“回去把今天记下来。”
Guspu 学到一件事:一次栽赃压不垮她,那就把能买的人都买下来。210 年,他去找 Zutthan Yellplank,渡口的矮人,想买她一个晚上,让她放人过河堵住 Ral 的路。他开了高价。Zutthan 没应,第二天只在渡口多挂了两盏灯。那桩贿赂没成。 古斯普学到一件事:一次栽赃压不垮她,那就把能买的人都买下来。210 年,他去找祖坦·啸板,渡口的矮人,想买她一个晚上,让她放人过河堵住拉尔的路。他开了高价。祖坦没应,第二天只在渡口多挂了两盏灯。那桩贿赂没成。
此后几年,他又试了四十七次。有的被拒,有的被拖,有的收了钱反悔。他夜里把一个个名字从簿子上画掉。那些人越是不肯,他越要留在手里。 此后几年,他又试了四十七次。有的被拒,有的被拖,有的收了钱反悔。他夜里把一个个名字从簿子上画掉。那些人越是不肯,他越要留在手里。
可他的圈子还是在涨。210 年,Onul Glowroofs 入局。215 年,Mudi Blazedbrushes 和 Stinthad Oilshove 入局。216 年,Ingish Steelgrouped 也来了。有人奔着他的手面,有人惧他,有人只是不想站在他的对面。他不再挑拣,只数人数。 可他的圈子还是在涨。210 年,奥努尔·光顶入局。215 年,穆迪·焰刷和斯廷哈德·油推入局。216 年,英吉什·钢聚也来了。有人奔着他的手面,有人惧他,有人只是不想站在他的对面。他不再挑拣,只数人数。
到 216 年冬,他已经不去想那场失败的构陷了。他甚至不再派人盯着 Ral 的屋子。他在城外高地上站了一会儿,问 Espu:“我现在有十几个人。她有几个?” 到 216 年冬,他已经不去想那场失败的构陷了。他甚至不再派人盯着拉尔的屋子。他在城外高地上站了一会儿,问埃斯普:“我现在有十几个人。她有几个?”
Espu 说:“一个记账的。” 埃斯普说:“一个记账的。”
Guspu 笑了一下:“不够。” 古斯普笑了一下:“不够。”
其实他真正想要的,不是除掉 Ral,而是让她听见那些名字,知道这个城终会把她围成一页摊不开的旧账。 其实他真正想要的,不是除掉拉尔,而是让她听见那些名字,知道这个城终会把她围成一页摊不开的旧账。
而那天夜里,Ral 的住处亮着两盏灯。她的账本上没写 Guspu 的名字,只添了一行: 而那天夜里,拉尔的住处亮着两盏灯。她的账本上没写古斯普的名字,只添了一行:
“216 年,Ingish Steelgrouped 入局。” “216 年,英吉什·钢聚入局。”
字迹很稳,像是早就知道这页会在什么时候被翻开。 字迹很稳,像是早就知道这页会在什么时候被翻开。
+9 -9
View File
@@ -1,19 +1,19 @@
# 锤子打不动的人 # 锤子打不动的人
219 年,Guspu 决定先切掉 Ral 最长的一根旧枝。他带了一本账去 Fordedwinds。Rigoth Stilledearthen 是 Ral 的旧识,替 Ral 看管铁锭。Guspu 把 Rigoth 在码头上的欠款一页页摊开:“我不是来讨债,我是让你选。你从 Ral 那里抽身,账我替你销。”Rigoth 问若不抽身会怎样。Guspu 收起账本:“会变成流言。”第二天,Rigoth 当众扔掉了与 Ral 的铁楔。第一个,削掉了。 219 年,古斯普决定先切掉拉尔最长的一根旧枝。他带了一本账去涉风渡。里戈斯·静土是拉尔的旧识,替拉尔看管铁锭。古斯普把里戈斯在码头上的欠款一页页摊开:“我不是来讨债,我是让你选。你从拉尔那里抽身,账我替你销。”里戈斯问若不抽身会怎样。古斯普收起账本:“会变成流言。”第二天,里戈斯当众扔掉了与拉尔的铁楔。第一个,削掉了。
221 年,Dostngosp Jackalbrims 正式与 Guspu 结契。Guspu 以为自己已经把 Ral 围紧。他让 Dostngosp 把一包铁屑和几张账页送进 The Volcano Of Ravens,说这些是 Ral 私吞 Fordedwinds 公共斤两的证据。他以为 Ral 的锤子再硬,也硬不过火山的舌头。可 The Volcano Of Ravens 把铁屑丢进炭火,烧出来却是一团软渣,不是 Ral 的钢。构陷失败。Guspu 在火山石阶上坐了一夜。他只知道:Ral 身边还有眼睛,而且比他多一副。 221 年,多斯特恩戈斯普·豺帽正式与古斯普结契。古斯普以为自己已经把拉尔围紧。他让多斯特恩戈斯普把一包铁屑和几张账页送进渡鸦火山,说这些是拉尔私吞涉风渡公共斤两的证据。他以为拉尔的锤子再硬,也硬不过火山的舌头。可渡鸦火山把铁屑丢进炭火,烧出来却是一团软渣,不是拉尔的钢。构陷失败。古斯普在火山石阶上坐了一夜。他只知道:拉尔身边还有眼睛,而且比他多一副。
222 年,Guspu 找到 Ducim Theatercrested,让他在戏台上唱 Ral 脚滑进铁水。Ducim 点头。从这年起,Fordedwinds 的酒馆里多了一出丑戏。唱的人笑,听的人笑,只有 Ral 没有笑。 222 年,古斯普找到杜西姆·剧冠,让他在戏台上唱拉尔脚滑进铁水。杜西姆点头。从这年起,涉风渡的酒馆里多了一出丑戏。唱的人笑,听的人笑,只有拉尔没有笑。
223 年,Onul Glowroofs 和 Ingish Steelgrouped 正式与 Guspu 结契。一个替他听,一个替他供铁。Guspu 在炉边对两人说:“说话的人、唱戏的人、听壁角的人,和运铁的船,都姓了鹰。”他第一次觉得,Ral 的墙正往下掉土。 223 年,奥努尔·光顶和英吉什·钢聚正式与古斯普结契。一个替他听,一个替他供铁。古斯普在炉边对两人说:“说话的人、唱戏的人、听壁角的人,和运铁的船,都姓了鹰。”他第一次觉得,拉尔的墙正往下掉土。
224 年,Ral 动了。他穿过东门去找 Zuntir Baldedattic,不要钱,只要他告诉自己 Guspu 的人每天过了几车、装了多少。Zuntir 收下话。这是 Ral 近几年第一次主动伸手。Guspu 听说了,在账房里砸了一块碳。他知道,Ral 不会只挨打。 224 年,拉尔动了。他穿过东门去找尊提尔·秃阁,不要钱,只要他告诉自己古斯普的人每天过了几车、装了多少。尊提尔收下话。这是拉尔近几年第一次主动伸手。古斯普听说了,在账房里砸了一块碳。他知道,拉尔不会只挨打。
225 年,Guspu 决定先打断 Ral 的一只手。他带人去了 Mortalpears,那里是 Ral 补给线的口子,把守者是 Goblin Uknol Thornticks,善在梨树林里埋尖桩。两人打了两次:第一次冒进,两个随从被穿了腿;第二次他亲自举盾压进林子。Uknol 退进雾里,没有死,但 Mortalpears 的路被踩平了。Guspu 回城,大衣上挂满梨刺。 225 年,古斯普决定先打断拉尔的一只手。他带人去了殇梨,那里是拉尔补给线的口子,把守者是哥布林乌克诺尔·棘蜱,善在梨树林里埋尖桩。两人打了两次:第一次冒进,两个随从被穿了腿;第二次他亲自举盾压进林子。乌克诺尔退进雾里,没有死,但殇梨的路被踩平了。古斯普回城,大衣上挂满梨刺。
226 年,轮到 Ral 下到 Fordedwinds 浅滩。Guspu 新派的收税人 Usel Fisherfair 带着六条船挨家翻货。Ral 没等船靠岸,提锤下水。两人在浅滩打了两次:头一次,Usel 的船被撞翻;第二次,Usel 放火烧了东边泊位。Ral 没吃大亏,但船坞焦了一半。这是他第一次砸人后,没听见自己笑。 226 年,轮到拉尔下到涉风渡浅滩。古斯普新派的收税人乌塞尔·渔市带着六条船挨家翻货。拉尔没等船靠岸,提锤下水。两人在浅滩打了两次:头一次,乌塞尔的船被撞翻;第二次,乌塞尔放火烧了东边泊位。拉尔没吃大亏,但船坞焦了一半。这是他第一次砸人后,没听见自己笑。
227 年,Guspu 在 Lashheroes 对上 Meng Walkclasped,此人是 Ral 从北方请来的打手,两把扣锤专砸铁链。打了两场:第一场,Guspu 后背裂了一道;第二场,他让 Ingish 夜里用钢水浇死了 Meng 的扣锤。Meng 骂着退走。Guspu 一句话没说,血在喉咙里来回滚。 227 年,古斯普在鞭雄对上蒙·行扣,此人是拉尔从北方请来的打手,两把扣锤专砸铁链。打了两场:第一场,古斯普后背裂了一道;第二场,他让英吉什夜里用钢水浇死了蒙的扣锤。蒙骂着退走。古斯普一句话没说,血在喉咙里来回滚。
228 年,Guspu 杀到 Liecats,撞上 Ngom Matchedmenaces。他上马时告诉自己:再削掉一个,Ral 就只剩空墙。可打到一半,他看见路边的草地全烧成了黑灰,忽然想不起这一路是谁先点的火。他攥紧缰绳,继续向前。Ral 的墙还在,但已经裂了。 228 年,古斯普杀到卧猫,撞上恩戈姆·匹凶。他上马时告诉自己:再削掉一个,拉尔就只剩空墙。可打到一半,他看见路边的草地全烧成了黑灰,忽然想不起这一路是谁先点的火。他攥紧缰绳,继续向前。拉尔的墙还在,但已经裂了。
+109 -109
View File
@@ -4,123 +4,123 @@
| 人物 | 种族 | 生卒 | 职业 | 事件数 | | 人物 | 种族 | 生卒 | 职业 | 事件数 |
|---|---|---|---|---| |---|---|---|---|---|
| Stobsa Boilpukes The Most | HYDRA | 生卒不详 | — | 191 | | Stobsa Boilpukes The Most | 九头蛇 | 生卒不详 | — | 191 |
| Raz Scorchedlanced The Hardy | COLOSSUS_BRONZE | 生卒不详 | — | 171 | | Raz Scorchedlanced The Hardy | 青铜巨像 | 生卒不详 | — | 171 |
| Langgud Dawncats The Washed Seed | TITAN_3 | ?–204 | — | 168 | | 朗古德 Dawncats The Washed Seed | TITAN_3 | ?–204 | — | 168 |
| Zogast Tufttop The Decisive Key | HYDRA | 生卒不详 | — | 161 | | Zogast Tufttop The Decisive Key | 九头蛇 | 生卒不详 | — | 161 |
| Inefa Dawnorange The Snarling Puke | TITAN_7 | 生卒不详 | — | 145 | | Inefa Dawnorange The Snarling Puke | TITAN_7 | 生卒不详 | — | 145 |
| Gaspa Begunhog The Clean | HYDRA | 88–在世/不详 | — | 144 | | Gaspa Begunhog The Clean | 九头蛇 | 88–在世/不详 | — | 144 |
| Oka Tinglistened The Howl Of Prestige | CYCLOPS | 生卒不详 | — | 127 | | Oka Tinglistened The Howl Of Prestige | 独眼巨人 | 生卒不详 | — | 127 |
| Od Mucusrock The Gleams Of Grease | HYDRA | 生卒不详 | — | 122 | | Od Mucusrock The Gleams Of Grease | 九头蛇 | 生卒不详 | — | 122 |
| Ngumost Apesstrap The Mountainous | BIRD_ROC | 生卒不详 | — | 121 | | Ngumost Apesstrap The Mountainous | 大鹏 | 生卒不详 | — | 121 |
| Yare Sistersubmerge | ELF | 4–在世/不详 | — | 115 | | Yare Sistersubmerge | 精灵 | 4–在世/不详 | — | 115 |
| Otust Wondereddriven The Beloved | ETTIN | 生卒不详 | — | 113 | | Otust Wondereddriven The Beloved | ETTIN | 生卒不详 | — | 113 |
| Ostzu Granitewanders The Flicker Of Intensity | CYCLOPS | 生卒不详 | — | 106 | | Ostzu Granitewanders The Flicker Of Intensity | 独眼巨人 | 生卒不详 | — | 106 |
| Are Flaxrose The Bearded | TITAN_2 | 生卒不详 | — | 103 | | Are Flaxrose The Bearded | TITAN_2 | 生卒不详 | — | 103 |
| Quathari Holyglen | ELF | 0–在世/不详 | — | 98 | | Quathari Holyglen | 精灵 | 0–在世/不详 | — | 98 |
| Urer Sunsshore The Hairy | TITAN_9 | 生卒不详 | — | 97 | | Urer Sunsshore The Hairy | TITAN_9 | 生卒不详 | — | 97 |
| Irene Ramlarge The Strong | BIRD_ROC | 生卒不详 | — | 95 | | Irene Ramlarge The Strong | 大鹏 | 生卒不详 | — | 95 |
| Thaci Authoredferns | ELF | 77–在世/不详 | — | 87 | | Thaci Authoredferns | 精灵 | 77–在世/不详 | — | 87 |
| Lapama Bittentwig | ELF | 生卒不详 | — | 87 | | Lapama Bittentwig | 精灵 | 生卒不详 | — | 87 |
| Asada Darkbalances The Ordered Sewer | YETI | ?–224 | — | 86 | | Asada Darkbalances The Ordered Sewer | 雪人 | ?–224 | — | 86 |
| Kifino Latewings | ELF | 79–在世/不详 | — | 84 | | Kifino Latewings | 精灵 | 79–在世/不详 | — | 84 |
| Shigos Saffronjumps The Teal Berries | TITAN_6 | 生卒不详 | — | 83 | | Shigos Saffronjumps The Teal Berries | TITAN_6 | 生卒不详 | — | 83 |
| Avafi Rootskull | ELF | 10–在世/不详 | — | 83 | | Avafi Rootskull | 精灵 | 10–在世/不详 | — | 83 |
| Ova Packvessels | ELF | 114–在世/不详 | — | 83 | | Ova Packvessels | 精灵 | 114–在世/不详 | — | 83 |
| Iru Sensedclam | ELF | 99–在世/不详 | — | 81 | | Iru Sensedclam | 精灵 | 99–在世/不详 | — | 81 |
| Genam Searingdwell | HUMAN | 129–193 | — | 81 | | Genam Searingdwell | 人类 | 129–193 | — | 81 |
| Rine Clenchdrinkers The Legend Of Wilts | YETI | ?–232 | — | 80 | | Rine Clenchdrinkers The Legend Of Wilts | 雪人 | ?–232 | — | 80 |
| Thalu Shellbud | ELF | 43–在世/不详 | — | 80 | | Thalu Shellbud | 精灵 | 43–在世/不详 | — | 80 |
| Nefola Wheeleagle | ELF | 生卒不详 | — | 78 | | Nefola Wheeleagle | 精灵 | 生卒不详 | — | 78 |
| Domas Meetingtongs | DWARF | 103–在世/不详 | — | 78 | | 多马斯 Meetingtongs | 矮人 | 103–在世/不详 | — | 78 |
| Langgud Tradebears The Eviscerated Chill Of Pregnancies | YETI | 生卒不详 | — | 77 | | 朗古德·商熊「剖胎之寒」 | 雪人 | 生卒不详 | — | 77 |
| Erith Orbrelieve | DWARF | 71–222 | — | 77 | | Erith Orbrelieve | 矮人 | 71–222 | — | 77 |
| Evala Dalemoisten | ELF | 生卒不详 | — | 76 | | 埃瓦拉 Dalemoisten | 精灵 | 生卒不详 | — | 76 |
| Thone Mawpunch | ELF | 58–在世/不详 | — | 76 | | Thone Mawpunch | 精灵 | 58–在世/不详 | — | 76 |
| Ilime Lobsterfancied | ELF | 110–在世/不详 | — | 76 | | Ilime Lobsterfancied | 精灵 | 110–在世/不详 | — | 76 |
| Kiros Cloudstones The Divine Delights | YETI | ?–219 | — | 74 | | Kiros Cloudstones The Divine Delights | 雪人 | ?–219 | — | 74 |
| Quathari Skunkdive | ELF | 65–在世/不详 | — | 74 | | Quathari Skunkdive | 精灵 | 65–在世/不详 | — | 74 |
| Kivish Boltpartner | DWARF | 74–233 | — | 74 | | Kivish Boltpartner | 矮人 | 74–233 | — | 74 |
| Nemile Worldglisten | ELF | 79–在世/不详 | — | 74 | | Nemile Worldglisten | 精灵 | 79–在世/不详 | — | 74 |
| Lomifo Oakfill The Severe | YETI | ?–242 | — | 73 | | Lomifo Oakfill The Severe | 雪人 | ?–242 | — | 73 |
| Enkos Apepulp The Plain | HYDRA | ?–206 | — | 72 | | Enkos Apepulp The Plain | 九头蛇 | ?–206 | — | 72 |
| Caraca Owlstrap | ELF | 73–在世/不详 | — | 72 | | Caraca Owlstrap | 精灵 | 73–在世/不详 | — | 72 |
| Lali Woodenpraise | ELF | 79–在世/不详 | — | 72 | | Lali Woodenpraise | 精灵 | 79–在世/不详 | — | 72 |
| Irene Biteglade | ELF | 生卒不详 | — | 72 | | Irene Biteglade | 精灵 | 生卒不详 | — | 72 |
| Ral Fastenhatchets | DWARF | 164–在世/不详 | — | 71 | | 拉尔·缚斧 | 矮人 | 164–在世/不详 | — | 71 |
| Imimi Shorelines | ELF | 75–在世/不详 | — | 70 | | Imimi Shorelines | 精灵 | 75–在世/不详 | — | 70 |
| Amala Leaptested | ELF | 72–在世/不详 | — | 69 | | Amala Leaptested | 精灵 | 72–在世/不详 | — | 69 |
| Salo Metblaze | ELF | 84–在世/不详 | — | 69 | | Salo Metblaze | 精灵 | 84–在世/不详 | — | 69 |
| Efami Churchcoasts | ELF | 121–在世/不详 | — | 69 | | Efami Churchcoasts | 精灵 | 121–在世/不详 | — | 69 |
| Themiyi Pinessplattered | ELF | 72–在世/不详 | — | 68 | | Themiyi Pinessplattered | 精灵 | 72–在世/不详 | — | 68 |
| Lolama Silkankle | ELF | 26–在世/不详 | — | 67 | | Lolama Silkankle | 精灵 | 26–在世/不详 | — | 67 |
| Tobul Robustzenith The Mint Yell | GIANT | 生卒不详 | — | 66 | | Tobul Robustzenith The Mint Yell | GIANT | 生卒不详 | — | 66 |
| Yemi Goodclouds | ELF | 7–在世/不详 | — | 66 | | Yemi Goodclouds | 精灵 | 7–在世/不详 | — | 66 |
| Durad Meadowjumped The Paddle Of Fords | TITAN_1 | 生卒不详 | — | 65 | | Durad Meadowjumped The Paddle Of Fords | TITAN_1 | 生卒不详 | — | 65 |
| Lek Willspecial The Meteor Of Fame | GIANT | 生卒不详 | — | 64 | | Lek Willspecial The Meteor Of Fame | GIANT | 生卒不详 | — | 64 |
| Darala Sportstrengths The Prestigious | GIANT | 生卒不详 | — | 64 | | Darala Sportstrengths The Prestigious | GIANT | 生卒不详 | — | 64 |
| On Rocksfades The Mellow Mother | TROLL | ?–174 | — | 64 | | On Rocksfades The Mellow Mother | 巨魔 | ?–174 | — | 64 |
| Us Systemsanctum The Delightful Fragment Of Celebrations | YETI | 24–207 | — | 64 | | Us Systemsanctum The Delightful Fragment Of Celebrations | 雪人 | 24–207 | — | 64 |
| Stinthad Glazedallies | DWARF | 74–225 | — | 64 | | 斯廷哈德 Glazedallies | 矮人 | 74–225 | — | 64 |
| Thiliri Listenblaze | ELF | 85–在世/不详 | — | 64 | | Thiliri Listenblaze | 精灵 | 85–在世/不详 | — | 64 |
| Cacame Birdcombats | ELF | 15–在世/不详 | — | 64 | | Cacame Birdcombats | 精灵 | 15–在世/不详 | — | 64 |
| Reg Runrings | DWARF | 50–220 | — | 63 | | Reg Runrings | 矮人 | 50–220 | — | 63 |
| Imimi Skinmirrored | ELF | 95–在世/不详 | — | 63 | | Imimi Skinmirrored | 精灵 | 95–在世/不详 | — | 63 |
| Cata Stylescarlet | ELF | 109–在世/不详 | — | 63 | | Cata Stylescarlet | 精灵 | 109–在世/不详 | — | 63 |
| Tirist Helmedtowns | DWARF | 110–在世/不详 | — | 63 | | 提里斯特 Helmedtowns | 矮人 | 110–在世/不详 | — | 63 |
| Eletha Orangeseason | ELF | 生卒不详 | — | 63 | | Eletha Orangeseason | 精灵 | 生卒不详 | — | 63 |
| Atera Earthenwiped | ELF | 152–在世/不详 | — | 63 | | Atera Earthenwiped | 精灵 | 152–在世/不详 | — | 63 |
| Zur Pucewanders The Blue Canyon | CYCLOPS | 生卒不详 | — | 62 | | Zur Pucewanders The Blue Canyon | 独眼巨人 | 生卒不详 | — | 62 |
| Itur Bristleknight The Sparkle Of Smiles | ETTIN | 生卒不详 | — | 62 | | Itur Bristleknight The Sparkle Of Smiles | ETTIN | 生卒不详 | — | 62 |
| Sol Shellrisen The First | TROLL | ?–180 | — | 62 | | Sol Shellrisen The First | 巨魔 | ?–180 | — | 62 |
| Urdim Joinedlashed | DWARF | 98–在世/不详 | — | 62 | | Urdim Joinedlashed | 矮人 | 98–在世/不详 | — | 62 |
| Lida Birdtraded | ELF | 124–在世/不详 | — | 62 | | Lida Birdtraded | 精灵 | 124–在世/不详 | — | 62 |
| Cequova Lacycolored | ELF | 130–在世/不详 | — | 62 | | Cequova Lacycolored | 精灵 | 130–在世/不详 | — | 62 |
| Arane Coastalglens | ELF | 142–在世/不详 | — | 62 | | Arane Coastalglens | 精灵 | 142–在世/不详 | — | 62 |
| Emene Torchtops The Adventurous | CYCLOPS | 生卒不详 | — | 61 | | Emene Torchtops The Adventurous | 独眼巨人 | 生卒不详 | — | 61 |
| Alisa Embracedlovers | ELF | 28–在世/不详 | — | 61 | | Alisa Embracedlovers | 精灵 | 28–在世/不详 | — | 61 |
| Mifava Fuchsiaown | ELF | 124–在世/不详 | — | 61 | | Mifava Fuchsiaown | 精灵 | 124–在世/不详 | — | 61 |
| Xuspgas Kissedhates | GOBLIN | 59–在世/不详 | — | 60 | | Xuspgas Kissedhates | 哥布林 | 59–在世/不详 | — | 60 |
| Asob Machinestill | DWARF | 78–238 | — | 60 | | Asob Machinestill | 矮人 | 78–238 | — | 60 |
| Amayi Clearmusics | ELF | 80–在世/不详 | — | 60 | | Amayi Clearmusics | 精灵 | 80–在世/不详 | — | 60 |
| Themiyi Dreamsadored | ELF | 85–在世/不详 | — | 60 | | Themiyi Dreamsadored | 精灵 | 85–在世/不详 | — | 60 |
| Famime Sweetelders | ELF | 124–在世/不详 | — | 60 | | Famime Sweetelders | 精灵 | 124–在世/不详 | — | 60 |
| Nemile Crazyglitter | ELF | 生卒不详 | — | 60 | | Nemile Crazyglitter | 精灵 | 生卒不详 | — | 60 |
| Ana Waxedjade | ELF | 41–在世/不详 | — | 59 | | 安娜 Waxedjade | 精灵 | 41–在世/不详 | — | 59 |
| Nemo Leopardanguished | ELF | 生卒不详 | — | 59 | | Nemo Leopardanguished | 精灵 | 生卒不详 | — | 59 |
| Vema Wasprooters | ELF | 5–在世/不详 | — | 58 | | Vema Wasprooters | 精灵 | 5–在世/不详 | — | 58 |
| Ova Guardedsuitor | ELF | 63–在世/不详 | — | 58 | | Ova Guardedsuitor | 精灵 | 63–在世/不详 | — | 58 |
| Ngokang Singedoomed | GOBLIN | 74–在世/不详 | — | 58 | | 恩戈康 Singedoomed | 哥布林 | 74–在世/不详 | — | 58 |
| Kubuk Mountainpaddle | DWARF | 92–在世/不详 | — | 58 | | Kubuk Mountainpaddle | 矮人 | 92–在世/不详 | — | 58 |
| Fikod Humidpaddled | DWARF | 92–在世/不详 | — | 58 | | Fikod Humidpaddled | 矮人 | 92–在世/不详 | — | 58 |
| Zutthan Anguishink | DWARF | 98–在世/不详 | — | 58 | | 祖坦 Anguishink | 矮人 | 98–在世/不详 | — | 58 |
| Rofa Sensecherished | ELF | 105–在世/不详 | — | 58 | | Rofa Sensecherished | 精灵 | 105–在世/不详 | — | 58 |
| Mimale Incenseflower | ELF | 107–在世/不详 | — | 58 | | Mimale Incenseflower | 精灵 | 107–在世/不详 | — | 58 |
| Caraca Hairdeer | ELF | 116–在世/不详 | — | 58 | | Caraca Hairdeer | 精灵 | 116–在世/不详 | — | 58 |
| Covema Questedwings | ELF | 生卒不详 | — | 58 | | Covema Questedwings | 精灵 | 生卒不详 | — | 58 |
| Rifa Bandedsatins | ELF | 121–在世/不详 | — | 58 | | Rifa Bandedsatins | 精灵 | 121–在世/不详 | — | 58 |
| Tira Divedmerges | ELF | 153–在世/不详 | — | 58 | | Tira Divedmerges | 精灵 | 153–在世/不详 | — | 58 |
| Ngebzo Pagesteals | GOBLIN | 64–在世/不详 | — | 57 | | Ngebzo Pagesteals | 哥布林 | 64–在世/不详 | — | 57 |
| Apasi Howlriddled | ELF | 75–在世/不详 | — | 57 | | Apasi Howlriddled | 精灵 | 75–在世/不详 | — | 57 |
| Mimale Seaclinch | ELF | 111–在世/不详 | — | 57 | | Mimale Seaclinch | 精灵 | 111–在世/不详 | — | 57 |
| Ile Smiledpetal | ELF | 120–在世/不详 | — | 57 | | Ile Smiledpetal | 精灵 | 120–在世/不详 | — | 57 |
| Ave Naturaldances | ELF | 122–在世/不详 | — | 57 | | Ave Naturaldances | 精灵 | 122–在世/不详 | — | 57 |
| Thiliri Hoofwinds | ELF | 生卒不详 | — | 57 | | Thiliri Hoofwinds | 精灵 | 生卒不详 | — | 57 |
| Snang Yawninghates | GOBLIN | 141–193 | — | 57 | | Snang Yawninghates | 哥布林 | 141–193 | — | 57 |
| Olzul Masterbrains The Remarkable | FORGOTTEN_BEAST_76 | 生卒不详 | — | 56 | | Olzul Masterbrains The Remarkable | FORGOTTEN_BEAST_76 | 生卒不详 | — | 56 |
| Asne Ecrutaken The Emerald Perfection | CYCLOPS | 生卒不详 | — | 56 | | Asne Ecrutaken The Emerald Perfection | 独眼巨人 | 生卒不详 | — | 56 |
| Amxu Hateflashes | GOBLIN | 75–在世/不详 | — | 56 | | 阿姆苏 Hateflashes | 哥布林 | 75–在世/不详 | — | 56 |
| Lapama Plungemoths | ELF | 118–在世/不详 | — | 56 | | Lapama Plungemoths | 精灵 | 118–在世/不详 | — | 56 |
| Rathe Grottovises | ELF | 45–在世/不详 | — | 56 | | Rathe Grottovises | 精灵 | 45–在世/不详 | — | 56 |
| Ula Thunderedmurk | ELF | 133–在世/不详 | — | 56 | | Ula Thunderedmurk | 精灵 | 133–在世/不详 | — | 56 |
| Kogan Herooar | DWARF | 140–在世/不详 | — | 56 | | Kogan Herooar | 矮人 | 140–在世/不详 | — | 56 |
| Guspu Frillyknots | EAGLE_MAN | 151–246 | — | 56 | | 古斯普·褶结 | 鹰人 | 151–246 | — | 56 |
| Dadu Twinklingflashed The Contested | CYCLOPS | 生卒不详 | — | 55 | | Dadu Twinklingflashed The Contested | 独眼巨人 | 生卒不详 | — | 55 |
| Geshud Roughentered | DWARF | 35–197 | — | 55 | | Geshud Roughentered | 矮人 | 35–197 | — | 55 |
| Arile Pristinefuture | ELF | 63–在世/不详 | — | 55 | | Arile Pristinefuture | 精灵 | 63–在世/不详 | — | 55 |
| Ilathe Frenzydeer | ELF | 70–在世/不详 | — | 55 | | Ilathe Frenzydeer | 精灵 | 70–在世/不详 | — | 55 |
| Nine Sweetnessholds | ELF | 70–在世/不详 | — | 55 | | Nine Sweetnessholds | 精灵 | 70–在世/不详 | — | 55 |
| Urvad Basissalve | DWARF | 110–在世/不详 | — | 55 | | Urvad Basissalve | 矮人 | 110–在世/不详 | — | 55 |
| Yare Snarledbirth | ELF | 95–在世/不详 | — | 55 | | Yare Snarledbirth | 精灵 | 95–在世/不详 | — | 55 |
| Itha Sportsongs | ELF | 生卒不详 | — | 55 | | Itha Sportsongs | 精灵 | 生卒不详 | — | 55 |
| Ducim Pickices | DWARF | 136–在世/不详 | — | 55 | | 杜西姆 Pickices | 矮人 | 136–在世/不详 | — | 55 |
+14 -14
View File
@@ -13,7 +13,7 @@
- **2** [生死] hf died · hfid=Vema Seedanguished · site_id=Nutssound - **2** [生死] hf died · hfid=Vema Seedanguished · site_id=Nutssound
- **2** [生死] hf died · hfid=Masami Nightbeak · site_id=Nutssound - **2** [生死] hf died · hfid=Masami Nightbeak · site_id=Nutssound
- **2** [生死] hf died · hfid=Athe Saffronboot · site_id=Nutssound - **2** [生死] hf died · hfid=Athe Saffronboot · site_id=Nutssound
- **2** [生死] hf died · hfid=Amxu Flydreamy · site_id=Scalysatins - **2** [生死] hf died · hfid=阿姆苏 Flydreamy · site_id=Scalysatins
- **2** [生死] hf died · hfid=Sazir Polishedlances · site_id=Amazedmirrored - **2** [生死] hf died · hfid=Sazir Polishedlances · site_id=Amazedmirrored
- **2** [生死] hf died · hfid=Bembul Silverygroove · site_id=Amazedmirrored - **2** [生死] hf died · hfid=Bembul Silverygroove · site_id=Amazedmirrored
- **2** [生死] hf died · hfid=Urvad Rayspaints · site_id=Amazedmirrored - **2** [生死] hf died · hfid=Urvad Rayspaints · site_id=Amazedmirrored
@@ -21,14 +21,14 @@
- **2** [生死] hf died · hfid=Rovod Abbeybolt · site_id=Amazedmirrored - **2** [生死] hf died · hfid=Rovod Abbeybolt · site_id=Amazedmirrored
- **2** [生死] hf died · hfid=Zuglar Crowdedmine · site_id=Amazedmirrored - **2** [生死] hf died · hfid=Zuglar Crowdedmine · site_id=Amazedmirrored
- **2** [生死] hf died · hfid=Urvad Bowelguild · site_id=Amazedmirrored - **2** [生死] hf died · hfid=Urvad Bowelguild · site_id=Amazedmirrored
- **2** [生死] hf died · hfid=Domas Brownlashed · site_id=Amazedmirrored - **2** [生死] hf died · hfid=多马斯 Brownlashed · site_id=Amazedmirrored
- …另有 324 条次要事件未列 - …另有 324 条次要事件未列
## 10s ## 10s
- **10** [生死] hf died · hfid=Uthra Hardyrake · site_id=Pathlance - **10** [生死] hf died · hfid=Uthra Hardyrake · site_id=Pathlance
- **11** [生死] hf died · hfid=Zolak Werecoil · site_id=Stretchedvice - **11** [生死] hf died · hfid=Zolak Werecoil · site_id=Stretchedvice
- **11** [生死] hf died · hfid=Utes Lieshut · site_id=Stretchedvice - **11** [生死] hf died · hfid=乌特斯 Lieshut · site_id=Stretchedvice
- **11** [生死] hf died · hfid=Hiner Plaitedangels · site_id=Praisepot - **11** [生死] hf died · hfid=Hiner Plaitedangels · site_id=Praisepot
- **12** [生死] hf died · hfid=Ubbul Crewsold - **12** [生死] hf died · hfid=Ubbul Crewsold
- **12** [生死] hf died · hfid=Coce Willglimmered - **12** [生死] hf died · hfid=Coce Willglimmered
@@ -64,7 +64,7 @@
- **30** [生死] hf died · hfid=Nganiz Flagroars - **30** [生死] hf died · hfid=Nganiz Flagroars
- **30** [生死] hf died · hfid=Mubun Slowsprayed - **30** [生死] hf died · hfid=Mubun Slowsprayed
- **30** [生死] hf died · hfid=Mosus Parchedsyrup · site_id=Wallwhipped - **30** [生死] hf died · hfid=莫苏斯 Parchedsyrup · site_id=Wallwhipped
- **30** [生死] hf died · hfid=Olon Cobaltkin · site_id=Wallwhipped - **30** [生死] hf died · hfid=Olon Cobaltkin · site_id=Wallwhipped
- **30** [生死] hf died · hfid=Sigun Elderposts · site_id=Wallwhipped - **30** [生死] hf died · hfid=Sigun Elderposts · site_id=Wallwhipped
- **30** [生死] hf died · hfid=Lor Crestedrock · site_id=Wallwhipped - **30** [生死] hf died · hfid=Lor Crestedrock · site_id=Wallwhipped
@@ -125,7 +125,7 @@
- **62** [生死] hf died · hfid=Dasar Rackpacked - **62** [生死] hf died · hfid=Dasar Rackpacked
- **62** [生死] hf died · hfid=Ayara Rumoredjumps - **62** [生死] hf died · hfid=Ayara Rumoredjumps
- **62** [生死] hf died · hfid=Lor Rawworks - **62** [生死] hf died · hfid=Lor Rawworks
- **62** [生死] hf died · hfid=Onul Entrancestandards - **62** [生死] hf died · hfid=奥努尔 Entrancestandards
- **63** [生死] hf died · hfid=Ongslun Headrespect - **63** [生死] hf died · hfid=Ongslun Headrespect
- **63** [生死] hf died · hfid=Limili Conjurerulers - **63** [生死] hf died · hfid=Limili Conjurerulers
- **64** [生死] hf died · hfid=Jepum Murderedsiege - **64** [生死] hf died · hfid=Jepum Murderedsiege
@@ -140,13 +140,13 @@
- **70** [生死] hf died · hfid=Pesor Castlecharred - **70** [生死] hf died · hfid=Pesor Castlecharred
- **70** [生死] hf died · hfid=Stozu Witchyawned · site_id=Hauntblack - **70** [生死] hf died · hfid=Stozu Witchyawned · site_id=Hauntblack
- **70** [生死] hf died · hfid=Azstrog Scorpiongilt · site_id=Releaselabored - **70** [生死] hf died · hfid=Azstrog Scorpiongilt · site_id=Releaselabored
- **70** [生死] hf died · hfid=Ngokang Terrorbears · site_id=Releaselabored - **70** [生死] hf died · hfid=恩戈康 Terrorbears · site_id=Releaselabored
- **70** [生死] hf died · hfid=Melbil Cloistercovers · site_id=Releaselabored - **70** [生死] hf died · hfid=Melbil Cloistercovers · site_id=Releaselabored
- **70** [生死] hf died · hfid=Ngoso Lostscorpions · site_id=Releaselabored - **70** [生死] hf died · hfid=Ngoso Lostscorpions · site_id=Releaselabored
- **70** [生死] hf died · hfid=Ngokang Phantommonsters · site_id=Releaselabored - **70** [生死] hf died · hfid=恩戈康 Phantommonsters · site_id=Releaselabored
- **70** [生死] hf died · hfid=Asmel Ringmeshes · site_id=Releaselabored - **70** [生死] hf died · hfid=阿斯梅尔 Ringmeshes · site_id=Releaselabored
- **70** [生死] hf died · hfid=Ago Entrymonster · site_id=Releaselabored - **70** [生死] hf died · hfid=Ago Entrymonster · site_id=Releaselabored
- **70** [生死] hf died · hfid=Mosus Glovedbraved · site_id=Releaselabored - **70** [生死] hf died · hfid=莫苏斯 Glovedbraved · site_id=Releaselabored
- **70** [生死] hf died · hfid=Snodub Savantsteals · site_id=Releaselabored - **70** [生死] hf died · hfid=Snodub Savantsteals · site_id=Releaselabored
- …另有 1209 条次要事件未列 - …另有 1209 条次要事件未列
@@ -174,7 +174,7 @@
- **90** [生死] hf died · hfid=Angos Witheredentrance - **90** [生死] hf died · hfid=Angos Witheredentrance
- **90** [生死] hf died · hfid=Rodem Matchgrieved - **90** [生死] hf died · hfid=Rodem Matchgrieved
- **90** [生死] hf died · hfid=Doce Finddives - **90** [生死] hf died · hfid=Doce Finddives
- **90** [生死] hf died · hfid=Ongu Sensecage · site_id=Galeclods - **90** [生死] hf died · hfid=翁古 Sensecage · site_id=Galeclods
- **90** [生死] hf died · hfid=Erush Boardedsabres · site_id=Galeclods - **90** [生死] hf died · hfid=Erush Boardedsabres · site_id=Galeclods
- **90** [生死] hf died · hfid=Mones Royalnestles · site_id=Galeclods - **90** [生死] hf died · hfid=Mones Royalnestles · site_id=Galeclods
- **90** [生死] hf died · hfid=Bathru Cookplots · site_id=Galeclods - **90** [生死] hf died · hfid=Bathru Cookplots · site_id=Galeclods
@@ -232,7 +232,7 @@
- **120** [生死] hf died · hfid=Agen Jeststrangers - **120** [生死] hf died · hfid=Agen Jeststrangers
- **120** [生死] hf died · hfid=Rabin Gleeden - **120** [生死] hf died · hfid=Rabin Gleeden
- **120** [生死] hf died · hfid=Frudulutrolbus - **120** [生死] hf died · hfid=Frudulutrolbus
- **120** [生死] hf died · hfid=Perom Polishbreeches · site_id=Strapsong - **120** [生死] hf died · hfid=佩罗姆 Polishbreeches · site_id=Strapsong
- **120** [生死] hf died · hfid=Kadol Mirrorpost · site_id=Spinestheater - **120** [生死] hf died · hfid=Kadol Mirrorpost · site_id=Spinestheater
- **120** [生死] hf died · hfid=Kubuk Covenroom · site_id=Spinestheater - **120** [生死] hf died · hfid=Kubuk Covenroom · site_id=Spinestheater
- **120** [生死] hf died · hfid=Edzul Palacedwelled · site_id=Spinestheater - **120** [生死] hf died · hfid=Edzul Palacedwelled · site_id=Spinestheater
@@ -270,7 +270,7 @@
- **140** [生死] hf died · hfid=Bale Lureplated - **140** [生死] hf died · hfid=Bale Lureplated
- **140** [生死] hf died · hfid=Nifih Wingkissed - **140** [生死] hf died · hfid=Nifih Wingkissed
- **140** [生死] hf died · hfid=Anir Dreamdimples - **140** [生死] hf died · hfid=Anir Dreamdimples
- **140** [生死] hf died · hfid=Ngom Staffspider · site_id=Nestleaders - **140** [生死] hf died · hfid=恩戈姆 Staffspider · site_id=Nestleaders
- **140** [生死] hf died · hfid=Tise Furylake · site_id=Nestleaders - **140** [生死] hf died · hfid=Tise Furylake · site_id=Nestleaders
- **141** [生死] hf died · hfid=Manorpears - **141** [生死] hf died · hfid=Manorpears
- **141** [生死] hf died · hfid=Sosma Puzzlecurious - **141** [生死] hf died · hfid=Sosma Puzzlecurious
@@ -325,7 +325,7 @@
- **170** [生死] hf died · hfid=Diso Orangesteam - **170** [生死] hf died · hfid=Diso Orangesteam
- **170** [生死] hf died · hfid=Dosheb Riverbalances - **170** [生死] hf died · hfid=Dosheb Riverbalances
- **170** [生死] hf died · hfid=Ejel Crestknowledge - **170** [生死] hf died · hfid=Ejel Crestknowledge
- **170** [生死] hf died · hfid=Someg Lightnourished - **170** [生死] hf died · hfid=索梅格 Lightnourished
- **170** [生死] hf died · hfid=Ismir Fruityprice - **170** [生死] hf died · hfid=Ismir Fruityprice
- **170** [生死] hf died · hfid=Rabin Counselledsalve - **170** [生死] hf died · hfid=Rabin Counselledsalve
- …另有 2129 条次要事件未列 - …另有 2129 条次要事件未列
@@ -449,7 +449,7 @@
- **240** [生死] hf died · hfid=Hushflesh - **240** [生死] hf died · hfid=Hushflesh
- **240** [生死] hf died · hfid=Omud Taxpokers - **240** [生死] hf died · hfid=Omud Taxpokers
- **240** [生死] hf died · hfid=Wimad Riddledcities - **240** [生死] hf died · hfid=Wimad Riddledcities
- **240** [生死] hf died · hfid=Flowerown The Climactic Song Of Summer - **240** [生死] hf died · hfid=Flowerown The Climactic 松 Of Summer
- **240** [生死] hf died · hfid=Quemer Blanketbasin - **240** [生死] hf died · hfid=Quemer Blanketbasin
- **240** [生死] hf died · hfid=Rozmo Conjuredclenched - **240** [生死] hf died · hfid=Rozmo Conjuredclenched
- **240** [生死] hf died · hfid=Ugrad Lashedhail - **240** [生死] hf died · hfid=Ugrad Lashedhail
+119
View File
@@ -0,0 +1,119 @@
"""专名本土化的回归测试。
重点盯住两个曾经真实踩过的坑:
1. 只处理全名,漏掉正文里大量使用的简称(`Ral`)与单呼的姓(`Fastenhatchets`)。
2. `YETI` 这类全大写枚举只改首字母得到 `YETI`,永远匹配不上正文里的 `Yeti`。
"""
from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from dfannals import glossary, localize
def test_title_form_lowercases_tail() -> None:
assert localize.title_form("YETI") == "Yeti"
assert localize.title_form("EAGLE_MAN") == "Eagle_man"
assert localize.title_form("fastenhatchets") == "Fastenhatchets"
def test_person_full_name() -> None:
assert localize.translate_person("Ral Fastenhatchets") == "拉尔·缚斧"
assert localize.translate_person("Guspu Frillyknots") == "古斯普·褶结"
assert localize.translate_person("Rigoth Stilledearthen") == "里戈斯·静土"
def test_person_with_epithet() -> None:
name = "Langgud Tradebears The Eviscerated Chill Of Pregnancies"
assert localize.translate_person(name) == "朗古德·商熊「剖胎之寒」"
def test_person_unknown_returns_none() -> None:
assert localize.translate_person("Zzzq Unknownsurname") is None
def test_place_and_epithet() -> None:
assert localize.translate_place("Fordedwinds") == "涉风渡"
assert localize.translate_place("Paperhushed") == "纸寂"
assert localize.translate_place("Gloryholes The Trickery Of Mornings") == "荣耀穴(晨之诡计)"
def test_group_translation() -> None:
assert localize.translate_group("The Volcano Of Ravens") == "渡鸦火山"
def test_race_enum_and_display_form() -> None:
assert localize.translate_race("YETI") == "雪人"
assert localize.translate_race("DWARF") == "矮人"
assert localize.translate_race("UNKNOWN_RACE") == "UNKNOWN_RACE"
def _fake_translator() -> localize.Translator:
"""不依赖真实世界数据的小翻译器,专测替换顺序。"""
translator = localize.Translator(
people={"Ral Fastenhatchets": "拉尔·缚斧", "Rigoth Stilledearthen": "里戈斯·静土"},
places={"Fordedwinds": "涉风渡"},
groups={"The Volcano Of Ravens": "渡鸦火山"},
stems={"Ral": "拉尔", "Rigoth": "里戈斯"},
surnames={"Fastenhatchets": "缚斧"},
races={"Yeti": "雪人", "EAGLE_MAN": "鹰人"},
)
return translator
def test_render_full_name_wins_over_short_name() -> None:
out = _fake_translator().render("Ral Fastenhatchets守着Fordedwinds。")
assert out == "拉尔·缚斧守着涉风渡。", out
def test_render_short_name_and_bare_surname() -> None:
out = _fake_translator().render("Ral对Rigoth说:她那一支姓Fastenhatchets。")
assert "拉尔" in out and "里戈斯" in out and "缚斧" in out, out
assert not any(ch.isascii() and ch.isalpha() for ch in out), out
def test_render_race_display_form() -> None:
out = _fake_translator().render("一个Yeti站了起来。军团是EAGLE_MAN。")
assert "雪人" in out and "鹰人" in out, out
def test_render_tidies_spaces() -> None:
out = _fake_translator().render("Ral 说 完 就 走 了")
assert "拉尔" in out and "拉尔 说" not in out, out
def test_accepted_includes_pieces() -> None:
accepted = _fake_translator().accepted()
assert "拉尔·缚斧" in accepted
assert "拉尔" in accepted and "缚斧" in accepted, sorted(accepted)
def test_glossary_tables_are_lowercase_keys() -> None:
for table in (glossary.STEMS, glossary.SURNAMES, glossary.PLACES):
for key in table:
assert key == key.lower(), f"{key} 应小写,否则 title_form 对不上"
def _main() -> int:
tests = [v for k, v in sorted(globals().items()) if k.startswith("test_") and callable(v)]
failed = 0
for fn in tests:
try:
fn()
except AssertionError as exc:
failed += 1
print(f" ✗ {fn.__name__}: {exc}")
except Exception as exc: # noqa: BLE001
failed += 1
print(f" ✗ {fn.__name__}: {type(exc).__name__}: {exc}")
else:
print(f" ✓ {fn.__name__}")
print(f"\n{len(tests) - failed}/{len(tests)} 通过")
return 1 if failed else 0
if __name__ == "__main__":
sys.exit(_main())