2010-03-10 53 views
2

我想將一個國際象棋AI移植到iPhone上,但我無法弄清楚如何去做。顯然iPhone不支持多線程,所以你不能單獨編譯AI,但必須以某種方式將它合併到代碼中。如何將國際象棋AI移植到iPhone

我有一個sjeng引擎的實現的GPL副本,但我無法弄清楚他們是如何做的,因爲它是用c和C++編寫的,而我所知道的只是蘋果objc。

有沒有人有關於如何做到這一點的建議?我需要爲什麼是獨立程序製作一些包裝。

code文件,我會盡可能長期留下。

+1

iPhone確實支持多線程,因此您需要對實際嘗試使用的內容進行更多研究。 – 2010-03-10 16:40:23

+0

我會建議試圖將其移植到Obj-C ..是用C **編寫的庫還是** C++ – Earlz 2010-03-10 16:44:42

+4

我並不是說聽起來很居高臨下,但你顯然沒有研究過這個平臺。另外,你的意思是:「顯然iPhone不支持多線程,所以你不能單獨編譯AI,但必須以某種方式將它合併到代碼中。」 - 多線程,編譯和合並都是完全獨立的操作,具有不同的工作流程,需求和結果。 – Jasarien 2010-03-10 16:50:58

回答

1

你的問題實際上比它需要更復雜,因爲我認爲你的基本問題與專門爲iPhone編譯無關。

如果你說你已經有了一些國際象棋AI代碼,那麼在某個地方有一個需要遊戲狀態(棋盤位置和玩家移動)的評估函數的調用,並且會返回一個移動。這就是你需要鑽取和查找的內容,因爲無論你在編譯什麼平臺,它本質上都是驅動你的應用的「引擎」。

現在,我的猜測是,這個國際象棋AI認爲移動搜索是在自己的線程中運行,可能是一個設計決定,以便隨時「中斷」搜索並讓它發揮自己的舉動。您當然可以在iPhone上的單獨線程中運行代碼,因此您的問題是要弄清楚如何從代碼中提取代碼以將其從現有的任何平臺依賴關係中解放出來。

它可能會幫助您第一次處理此問題,就好像您正在編寫一個命令行實用程序(在C中)以在Mac OS X上運行一樣。這將使您從很多依賴關係中解脫出來,併爲您簡化情況。我的猜測是,一旦你完成了這個任務,你就會立刻明白如何在(Cocoa)iPhone環境下工作。

1

Objective C是C的一個超集,所以如果庫是用C語言編寫的,那麼您可以在沒有任何包裝的情況下使用其餘的Objective-C代碼進行編譯。

+0

但是,我如何將它從自己的主循環移植到類似於某個對象之類的東西呢? – napierzaza 2010-03-10 17:07:00

+0

庫需要有一個接口,您可以使用它來獲取下一個AI移動。 – 2010-03-10 17:18:52

+0

圖書館如何接收輸入?它不直接向用戶說話,是嗎? – 2010-03-10 20:36:57

1

iPhone OS支持多線程;請參閱NSThread類。不過,你不會得到任何額外的性能 - iPhone CPU是單核心的,幾乎沒有多任務處理。

是的,從Objective C代碼中,您可以輕鬆調用C和C++代碼,反之亦然。對於C++交互,請將源重命名爲.mm;然後它們被編譯爲Objective C++。

我有充足的經驗將C++代碼移植到iPhone。奇蹟般有效。

+0

我需要AI持久性,我需要聯繫它,而不是隻接收回調。 – napierzaza 2010-03-10 17:06:07

3

我已成功將一個國際象棋引擎移植到iPhone。移植並不困難。大多數流行的國際象棋引擎採用通用象棋接口協議或國際象棋引擎通信協議。閱讀維基百科,瞭解每種協議的更多細節。

現在,假設您採用UCI國際象棋引擎的開放源碼之一,並且它在C或C++上編譯。 XCode本身支持C和C++,因此您只需將源複製到XCode,然後編譯即可。

下一階段將把引擎連接到您的界面。再次,這並不困難。您需要將協議命令發送到引擎,引擎會將標準輸出中的結果返回給您。你需要使用UNIX的pipe()來管理結果。閱讀我的其他線程 Fork() on iPhone瞭解更多詳情。

例子:

假設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國際象棋引擎協議文檔。你將需要它。