前言

哎,狼人杀的逻辑好难实现,这毕竟不是大模型,给几个目标让他们自己练就可以,首先得我自己搞懂狼人杀的发言逻辑,所以今天还是先从比较简单的真假游戏开始,相信看完这篇,你也会和我一样眼前一亮,完整代码见 https://github.com/zong4/AILearning。

游戏规则

同样的简单讲一下规则,这游戏我第一次接触是小学学奥数的时候。

简单来说,就是会有几个人,他们要么是骑士要么是恶魔,骑士只能说真话,而恶魔可以是假话也可以是真话,我们需要从他们说的话来判断他们的身份。

所以我们首先创建所有会用到的 Symbol。

1
2
3
4
5
6
7
8
AKnight = Symbol("A is a Knight")
AKnave = Symbol("A is a Knave")

BKnight = Symbol("B is a Knight")
BKnave = Symbol("B is a Knave")

CKnight = Symbol("C is a Knight")
CKnave = Symbol("C is a Knave")

游戏逻辑

OK,这一块的话就是重中之重了,来举个简单的例子先,考虑下面这个问题。

1
2
假设只有一个 A。
A 说:“我即是骑士又是恶魔。”

大家可以先想一下这个问题的 KB 应该怎么表示再往下看。

答案一共是四句,首先要说明 A 只能是骑士或者恶魔,然后再用推理来表示 A 说的话,如果 A 是骑士,那么他说的话就为真,反之则不一定。

1
2
3
4
5
6
7
knowledge0 = And(
Or(AKnight, AKnave), # A is a knight or A is a knave
Not(And(AKnight, AKnave)), # A is not a knight and a knave

Implication(AKnight, And(AKnight, AKnave)), # If A is a knight, then A is a knight and a knave
Implication(AKnave, Not(And(AKnight, AKnave))) # If A is a knave, then A is not a knight and a knave
)

同样的,接下来还有三个问题,大家可以尝试自行解决,然后再看看我的代码 https://github.com/zong4/AILearning。

1
2
3
4
5
6
7
8
9
10
11
12
13
# Puzzle 1
# A says "We are both knaves."
# B says nothing.

# Puzzle 2
# A says "We are the same kind."
# B says "We are of different kinds."

# Puzzle 3
# A says either "I am a knight." or "I am a knave.", but you don't know which.
# B says "A said 'I am a knave'."
# B says "C is a knave."
# C says "A is a knight."

后记

哈哈哈,今天文章好像有点水,但是今天是除夕,应该大家也不介意。

不过这个游戏要实现还是挺耗脑子的,因为你需要仔细思考如何原封不动的转述给 AI,比如那个例子,你可能一看到就知道 A 是恶魔,但是你不能直接给 KB 里面放一个 A 是恶魔,你必须得用那些连接符和 Symbols 来解释,还是挺痛苦的。

不过大家现在看完应该也发现了,狼人杀的发言跟这个就是异曲同工,所以明天一定给大家端出来。

最后给大家讲一段挺有意思的代码,就是下面这个判断每个人的角色。

1
2
3
4
5
6
7
8
for puzzle, knowledge in puzzles:
print(puzzle)
if len(knowledge.conjuncts) == 0:
print(" Not yet implemented.")
else:
for symbol in symbols:
if model_check(knowledge, symbol):
print(f" {symbol}")

这代码妙就妙在,通过 model_check 只打印了 symbol 为真的情况,这样就不需要二次修改输出了,直接就能出现这样的结果。

1
2
3
Puzzle 1
A is a Knave
B is a Knight