DDC

### 基本介绍：

DDC由CC最早创立，具有比J更长甚至相当的历史。DDC实在是具有太过于强大的历史意义以至于甚至最早的圣纸就出自这里——当时由ZYY提出添加的护盾系统实在是太过于复杂，以至于我们不得不将它们写在纸上，一张餐巾纸上。

DDC在百家争鸣的原2班中不一会儿就过期了，不只是由于其玩法的复杂性，也由于其各方面更新实在是太快。后来在ZYY的主持下曾经复兴过许多版本的DDC，其名字DDC（Duck Duck Chess）也从此而来，但是其核心玩法“比长度”击杀敌军却始终没有过时。

### 规则及实现方法

DDC现在仍处于高速更新中，地图大小不等，一些细节性规则也并不同。我们在此讨论的是15\*19固定基地以及时空穿梭模式。

#### 核心

不同于历史上其他的ZYY垃圾核心，这个核心相当快！事实上，我们就是追求着快来的（尽管可能并非看起来那么稳定）

以下就是核心的全部（也许它无法跑动，但是很显然它可以简单地植入我们的人机——它整个地由函数构成，使得添加使它运行的程序十分简单）

* 定义数组地图
* 定义数组O在x方向上的力量（以下简称Ox，其余同）
* 定义Oy
* 定义Xx
* 定义Xy
* 定义函数：摆放O
	+ 数据输入包含：y，x（表示在这个地方摆放方块）
	+ 在地图的（y，x）位置标记O（在目前的核心中，用整数1来存储）
	+ （y，x）位置的Ox等于它左右格子的Ox之和
	+ 向左循环：
		- 当循环到不再是O时，循环停止
		- 否则将循环到的格子的Ox设置成位置为（y，x）的Ox
	+ 若循环结束时，指针位于X上：
		- 击杀指针位置的X（程序遵循下文“击杀X”函数）
	+ 向右的过程基本与向左相同
	+ （y，x）位置的Oy等于它上下格子的Oy之和
	+ 向上向下循环，与向左向右类似
* 定义函数：摆放X
	+ 具体操作接近摆放O（可大量抄写）
* 定义函数：击杀O
	+ 数据输入包含：y，x（表示击杀位置（y，x）位置的方格）
	+ 检测（y，x）是否是自己基地的位置：
		- 如果是：
			* 立起flag以让大家都知道你寄了
			* return
	+ 将地图的（y，x）位置的O标记抹除（在目前的核心中，将这个格子变成0）
	+ 将（y，x）的Ox，Oy均变成0
	+ 定义变量n=0
	+ 向左循环：
		- 终止条件：指针不再指着O
		- 把循环所到之处的Ox均变成0
		- n加一
	+ 若循环结束时指针指着X
		- 把循环指针向右一格的O杀掉（程序遵循函数“击杀O”）（没错，就是递归）
			* 备注：建议在此进行检测指针向右一格的O是不是自己（即最开始输入的位置），不然可能导致自己递归自己导致爆炸（这个bug困扰了ZYY三天并最终把整个击杀函数搞得乱七八糟）
	+ 将指针慢慢向右拨回（y，x）
		- 在途中将指针所到之处的Ox变成n
	+ n=0
	+ 向右循环，类似于向左
	+ 向上向下循环
* 定义函数：击杀X
	+ 动作接近O
* 定义函数：tpx：
	+ （注：该函数的功能是使x盲目+1+1时不会跑到地图外面导致崩溃，时空穿梭的功能就是这样体现出来的）
* 定义函数：tpy

#### 人机

实现方法很简单，但是需要大量的数组可能并不便于理解（C++可用结构体）

* 创建数组Os（三维，包含【层数】【y】【x】）（注释：表示神经网络第几层那个位置状态怎么样）
* 创建数组Ocx（四维，包含【层数】【y】【x】【i】）（注释：表示神经网络第几层哪个位置的第i根连接要连接到下一层的位置的x坐标）
* 创建数组Ocy（基本同上）
* 创建数组Ock（四维，包含【层数】【y】【x】【i】）（注释：表示神经网络第几层哪个位置第i根连接的传导力是多少（若为0~1的真小数显然较为合理，但是使用极大整数也不是不可以看个人喜好））
* 创建数组Xs
* 创建数组Xcx
* 创建数组Xcy
* 创建数组Xck
* 给Ocx，Ocy，Ock，Os填充自己喜欢的数（若数量太多或无法决策，可以随机生成）
* 定义函数：O的进化：（原理：毁灭自己，学习比自己更优秀的敌人，并随机变异）
	+ 数据输入：无需任何数据输入
	+ 沿着层数f，y，x的顺序，遍历
		- 随机生成0~99的数
		- 若小于某个值：（说明：变异）
			* 将指针所指位置对应着的Ocx，Ocy，Ock随机生成
		- 否则：
			* 直接将该位置的Xcx，Xcy，Xck投射到O上（没错是X）
* 定义函数：X的进化
* 运行一遍X的进化（很好这样X里也有东西了）
* 定义函数：O的更新：（不要与“进化”搞混）
	+ 数据输入：
		- f，y，x，a（注释：a是数据变化量，可加可减）
		- 将Os的第f层（y，x）处加上a
		- 若层数不是最大层，则更新f+1层的所有连接到的节点，方法照函数“O的更新”（递归）
			* 其中f位置输入f+1，y位置输入该位置该连接（指位于层f的发射节点而非f+1层的接受节点）的Ocy，x输入该位置该连接的Ocx，a位置输入a乘该位置该连接的Ock
* 定义函数：X的更新

#### 人机的生成和训练

实际上只要做好了上面的人机和核心的部分，人机的训练就很简单了，只需少量的步骤以及对上述人机和核心的程序稍作修改：

* 将上述所有核心与人机的代码复制过来
* 定义两个变量（在下面决策时会用到）
* 定义函数：O的决策：
	+ 无需任何数据输入（你可以仍然输入数据以供娱乐）
	+ 遍历Os的最顶层，找出周围**有O棋子**的最大值的位置（y和x）并用上面定义出的两个变量存储进去
	+ 摆放O（位置就是刚刚决出的变量，分别是y和x）
* 定义函数：X的决策
* 对核心的某些函数稍作修改，包括：
	1. 在函数“摆放O”与“摆放X”中，第一行添加更新O和更新X（两个都要加，**不是**O只加O，X只加X），输入为f=0，y，x即摆放的O（或X）的位置。如果是O，则a=10，如果是X，则a=20
	2. 在函数“摆放O”的结尾添加一行“X的决策”，在函数“摆放X”的结尾添加一行“O的决策”
	3. 在函数“击杀O”和“击杀X”的开头添加一行更新O和更新X，输入f=0，y，x即为死去的O（或X）的位置。如果是O，a=-10，如果是X，a=-20
	4. 定义一个变量“步数”，并在“摆放O”与“摆放X”的开头添加一行“步数+1”
		+ 如果步数达到1000步，但是还是没有决出胜负，那就直接跳出然后宣布平局
* 大循环（人机的“代”数，即generation）：
	+ 初始化地图、Ox、Oy、Xx、Xy、初始化OS、XS
		- 记得初始化后加入基地位置，手动摆放基地（而不要使用摆放函数，否则它会启动递归然后就自己下下去了）
	+ 步数归0
	+ 备注：第一轮：O开局
	+ 运行一遍决策O
	+ 空一行来打量一下自己的精彩成果（它会自己递归下去，直到有人的基地报废！）
	+ 查看：是谁寄了
	+ O寄了：
		- 给X加1分
	+ X寄了：
		- 给O加1分
	+ 谁都没寄：
		- 都加一分（干得漂亮！）
	+ 备注：第二轮，X先开始
	+ 初始化（同上）
	+ 清零步数
	+ 运行决策X
	+ 等待它自己递归到底
	+ 查看谁寄了，统计方法同上
	+ 统计双方得分：
	+ O赢：运行“进化X”
	+ X赢：运行“进化O”
	+ 平手：随机进化
	+ 把双方的分数都清零
* 备注：好了，人机现在肯定已经进化到相当优秀的程度了
* 将O的神经网络连接配置（即Ocx，Ocy，Ock）保存在文件里
	+ 备注：X是个很好的陪练！
* 完成，把人机的网络配置文件发给ZYY，标明地图大小以及基地位置