专名本土化(信达雅):冻结译名表 + 渲染层,并修掉校验器的正则盲点
- 新增 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:
+3
-2
@@ -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
@@ -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(
|
||||||
|
|||||||
@@ -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]")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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": "城镇",
|
||||||
|
}
|
||||||
@@ -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
@@ -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
@@ -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年又添一笔,是鹰人关系网中露面有限的配角。
|
||||||
|
|
||||||
|
|||||||
@@ -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说:“走。”
|
拉尔说:“走。”
|
||||||
|
|
||||||
两个人往回走。过道拐角处,墙上那块石头还卡在缝里,没掉下来。石头边上有一道她刚按出来的手印,手印比石头凉。
|
两个人往回走。过道拐角处,墙上那块石头还卡在缝里,没掉下来。石头边上有一道她刚按出来的手印,手印比石头凉。
|
||||||
|
|||||||
@@ -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翻开新的一页。石头上落了一层薄雪。
|
里戈斯翻开新的一页。石头上落了一层薄雪。
|
||||||
|
|||||||
@@ -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 年,英吉什·钢聚入局。”
|
||||||
|
|
||||||
字迹很稳,像是早就知道这页会在什么时候被翻开。
|
字迹很稳,像是早就知道这页会在什么时候被翻开。
|
||||||
|
|||||||
@@ -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
@@ -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 |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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())
|
||||||
Reference in New Issue
Block a user