我想将国际象棋 AI 移植到 iPhone,但我不知道该怎么做。显然 iPhone 不支持多线程,所以你不能只单独编译 AI,而必须以某种方式将其合并到代码中。
我有一个 sjeng 引擎实现的 GPL 副本,但我不知道他们是如何做到的,因为它是用 c 和 c++ 编写的,而我只知道苹果 objc。
有人对如何做到这一点有任何建议吗?我需要为独立程序制作某种包装器。
包含我将尽可能长时间保留的代码的文件。
我想将国际象棋 AI 移植到 iPhone,但我不知道该怎么做。显然 iPhone 不支持多线程,所以你不能只单独编译 AI,而必须以某种方式将其合并到代码中。
我有一个 sjeng 引擎实现的 GPL 副本,但我不知道他们是如何做到的,因为它是用 c 和 c++ 编写的,而我只知道苹果 objc。
有人对如何做到这一点有任何建议吗?我需要为独立程序制作某种包装器。
包含我将尽可能长时间保留的代码的文件。
我已成功将国际象棋引擎移植到 iPhone。移植并不难。大多数流行的国际象棋引擎采用通用国际象棋接口协议或国际象棋引擎通信协议。有关每个协议的更多详细信息,请阅读 Wikipedia。
现在,假设您采用开源 UCI 国际象棋引擎之一,它可以在 C 或 C++ 上编译。XCode 原生支持 C 和 C++,因此您只需将源代码复制到 XCode 即可编译。
下一阶段是将引擎连接到您的界面。同样,这并不难。您需要向引擎发送协议命令,引擎会将结果返回到标准输出。您需要使用 UNIX 的 pipe() 来传递结果。阅读我在 iPhone 上的另一个线程 Fork()了解更多详细信息。
例子:
假设 engine_loop 是你的引擎的游戏循环(所有引擎都必须有一个循环)。
engine_loop(int fd[])
{
dup2(fd[1], STANDARD_OUTPUT);
while(true)
{
printf("e4\n"); // This is dumb, we always make the same move, but you get the idea
}
}
my_objective_c_function()
{
int fd[2];
pipe(fd);
engine_loop(fd);
char buffer[1024];
read(fd[0], buffer, 1024);
// buffer == "e4"
// Send "e4" to the interface
}
代码片段向您展示了如何将结果从引擎发送到您的界面。现在,您需要反其道而行之。这与上面的代码非常相似。在一个真实的场景中,一旦你的连接建立,你将需要发送 UCI 命令,我给你一个例子:
ucinew
isready
go infinite
stop
请仔细阅读 UCI 国际象棋引擎协议文档。你会需要它。
Objective C 是 C 的超集,所以如果库是用 C 编写的,你可以用剩下的 Objective-C 代码编译它,而不需要任何包装器。
iPhone OS 确实支持多线程;请参阅 NSThread 类。但是,您不会从中获得任何额外的性能 - iPhone CPU 是单核的,几乎没有多任务处理。
是的,您可以从 Objective C 代码轻松调用 C 和 C++ 代码,反之亦然。对于 C++ 交互,将源代码重命名为 .mm;然后它们被编译为Objective C++。
我有丰富的将 C++ 代码移植到 iPhone 的经验。奇迹般有效。
你的问题实际上比它需要的更复杂,因为我认为你遇到的基本问题与专门为 iPhone 编译无关。
如果您说您已经有一些国际象棋 AI 代码,那么在某处调用了一个评估函数,该函数获取游戏状态(棋盘位置和玩家移动)并返回移动。这就是您需要深入研究和发现的内容,因为这本质上是驱动您的应用程序的“引擎”,无论您正在为什么平台编译。
现在,我的猜测是,这个国际象棋 AI 假设移动搜索是在自己的线程中运行的,这可能是一个设计决定,以便随时“中断”搜索并让它发挥自己的移动变得容易。您当然可以在 iPhone 上的不同线程中运行代码,因此您的问题是弄清楚如何梳理出该代码以将其从现有的平台依赖项中释放出来。
它可以帮助您首先解决这个问题,就像您正在用 C 语言编写一个命令行实用程序以在 Mac OS X 上运行一样。这将使您摆脱许多依赖关系并为您简化情况。我的猜测是,一旦你这样做了,你就会立即对如何使它在(Cocoa)iPhone 环境中工作有一个很好的想法。