2015-05-14 62 views
2

我一直在試圖寫(作爲一個練習 - 學習一點關於序言)一個小代碼片段,打印所有可能的統計組合從筆和紙RPG 。序言:寫作RPG統計打印程序時的算術問題

相關的代碼片段:

%abilities 
ability(X) :- 
    member(X, [str, dex, con, int, wis, cha]). 

race(tiefling, planetouched, [[dex, 2], [int, 2], [cha, -2]], [infernalResistance,darkvision,skillAffinity(bluff),skillAffinity(hide)],rogue, 1, medium). 
race(human, human, [], [quickToMaster, skilled], any, 0, medium). 

racialAttributeBonus(Race, Stat, Bonus) :- 
    race(Race, _, BonusList, _, _, _, _), 
    member([Stat, Bonus], BonusList). 

racialAttributeBonus(Race, Stat, 0) :- 
    race(Race, _, BonusList, _, _, _, _), 
    \+ member([Stat, _], BonusList). 

%start ability points is 32 

%first 6 points - 1 point per increase 
%7, 8 - +2 per increase 
%9, 10 - +3 per increase 

statDiffCost(Diff, Cost) :- 
    Range = [Diff, Cost], 
    member(Range, [ 
      [0, 0], 
      [1, 1], 
      [2, 2], 
      [3, 3], 
      [4, 4], 
      [5, 5], 
      [6, 6], 
      [7, 8], 
      [8, 10], 
      [9, 13], 
      [10, 16] 
     ]). 

raceAttribCost(Race, AttrName, AttrValue, Cost) :- 
    number(AttrValue), 
    racialAttributeBonus(Race, AttrName, Bonus), 
    AttrDiff is AttrValue - Bonus - 8, 
    statDiffCost(AttrDiff, Cost). 

raceAttribCost(Race, AttrName, AttrValue, Cost) :- 
    number(Cost), 
    racialAttributeBonus(Race, AttrName, Bonus), 
    statDiffCost(AttrDiff, Cost), 
    AttrValue is AttrDiff + Bonus + 8. 

raceAttributes(Race, Str, Dex, Con, Int, Wis, Cha) :- 
    StrCost + DexCost + ConCost + IntCost + WisCost + ChaCost is 32, 
    raceAttribCost(Race, str, Str, StrCost), 
    raceAttribCost(Race, dex, Dex, DexCost), 
    raceAttribCost(Race, con, Con, ConCost), 
    raceAttribCost(Race, int, Int, IntCost), 
    raceAttribCost(Race, wis, Wis, WisCost), 
    raceAttribCost(Race, cha, Cha, ChaCost). 

不過,我碰到的幾個相關數字/算術的處理問題。

首先,我會期望

raceAttributes(human, Str, Dex, Con, Int, Wis, Cha). 

將打印的參數組合。相反,我得到false

其次,我一直無法以優雅的方式處理raceAttribCoststatDiffCost中的數值參數。

基本上,我不得不創建raceAttribCost的兩個版本,因爲根據我指定的參數,其中一個參數需要比較右側的「實例化」變量。

所以,我想知道如何

  1. 撥打電話到raceAttributes實際工作。
  2. 消除raceAttribCost的其中一個版本並僅保留其中一個
  3. (可選)用更緊湊的東西替換statDiffCost

所有三個是相同的問題,這是混合象徵性的「計算」和數值算術的一部分。

建議嗎?

P.S.我在Windows 7上使用SWI-PL 64位。

+1

iHaveOneAdditionalCommentRegardingYourNamingConvention:you_will_find_using_underscores_much_easier_to_read_for_longer_names! – mat

+0

經過多年的C++開發,我不太可能轉向其他任何東西,對不起。習慣的問題。 – SigTerm

+0

請參閱C++發明人的[命名約定](http://www.stroustrup.com/bs_faq2.html#Hungarian)。值得注意的是:「*我更喜歡用下劃線來區分標識符中的單詞(比如'element_count')而不是其他選項,比如'elementCount'和'ElementCount'。*」 – mat

回答

3

這對使用CLP(FD)約束非常容易解決。

對於第一個問題(爲什麼會失敗):is/2不適用於左側的複合術語。您需要=:=/2來比較算術表達式的評估。儘管如此,僅僅用is/2替換爲=:=/2由於沒有實際意義的變量而不起作用。

爲了解決這個問題,只需在你的程序中電(FD)的約束#=/2取代的is/2所有出現,並在必要時添加:- use_module(library(clpfd)).在程序的開始。這產生了一個更通用的程序。

然後,簡單地刪除那麼不必要的number/1目標,並刪除多餘的子句。

實例查詢,以及它與新版本的結果:

?- raceAttributes(human, Str, Dex, Con, Int, Wis, Cha). 
Str = Dex, Dex = Con, Con = Int, Int = 8, 
Wis = Cha, Cha = 18 ; 
Str = Dex, Dex = Con, Con = 8, 
Int = 11, 
Wis = 17, 
Cha = 18 ; 
Str = Dex, Dex = Con, Con = 8, 
Int = 11, 
Wis = 18, 
Cha = 17 ; 
etc. 

工程完全按照預期,在各個方向。

+1

我剛剛扭轉了這個:-) +1的緊湊和良好的答案! – mat

+0

它的工作原理,感謝您的幫助/快速響應。有趣的是,我在發帖前遇到過提到clfpd,但由於某種原因沒有嘗試: - \。 – SigTerm

+0

我強烈建議在您的程序中簡單地使用CLP(FD)約束來計算所有整數算術。您通常可以獲得更多的一般計劃,但費用通常可以忽略不計。例如,在SWI-Prolog中,我在我的初始化文件中使用了': - use_module(library(clpfd))',這樣CLP(FD)約束就可以自動在頂層提供給我,就像在其他衆所周知的系統中一樣如GNU Prolog和B-Prolog。 – mat

3

你可以這樣進行:

  1. 使用的關係整數算術:

    :- use_module(library(clpfd)). 
    
  2. #=替換的is所有用途。

  3. 刪除所有number/1目標。

  4. 重新運行原來的查詢,並彙報:)

+0

作品。謝謝您的幫助。儘管我會接受mat的答案,因爲它更詳細一些。 – SigTerm