Prolog:编写rpg stat打印程序时的算术问题

Prolog:编写rpg stat打印程序时的算术问题,prolog,clpfd,Prolog,Clpfd,我一直在尝试编写一个小代码片段(作为一个练习——学习一点prolog),它可以打印出纸笔RPG中特定种族的所有可能的统计组合 相关代码片段: %abilities ability(X) :- member(X, [str, dex, con, int, wis, cha]). race(tiefling, planetouched, [[dex, 2], [int, 2], [cha, -2]], [infernalResistance,darkvision,skillAffinity

我一直在尝试编写一个小代码片段(作为一个练习——学习一点prolog),它可以打印出纸笔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

其次,我无法优雅地处理
raceAttribCost
statDiffCost
中的数值参数

基本上,我必须创建两个版本的
raceAttribCost
,因为根据我指定的参数,其中一个需要在比较的右侧使用“实例化”变量

所以,我想知道如何

  • 调用
    raceAttributes
    实际工作
  • 删除
    raceAttribCost
    的一个版本,只保留其中一个版本
  • (可选)将
    statDiffCost
    替换为更紧凑的
  • 这三个问题都属于同一个问题,即混合符号“计算”和数值算术

    建议


    另外,我在windows 7上使用SWI-PL 64位。

    这在CLP(FD)约束下非常容易解决

    对于第一个问题(为什么失败):
    is/2
    不适用于左侧的复合词。您需要
    =:=/2
    来比较算术表达式的计算结果。但是,由于未实例化的变量,简单地用
    =:=/2
    替换
    is/2
    在您的情况下是不起作用的

    要解决此问题,只需在程序中用CLP(FD)约束替换所有出现的
    is/2
    ,并在程序开始时添加
    :-使用_模块(库(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.
    

    在各个方向上都能完全按照预期工作。

    您可以这样操作:

  • 用于关系整数算术:

      :- use_module(library(clpfd)).
    
  • is
    的所有用法替换为
    =

  • 删除所有
    number/1
    目标

  • 重新运行原始查询并返回报告:)


  • 关于你的命名惯例,我还有一个额外的评论:你会发现使用下划线更容易阅读更长的名字!在C++中使用CAMELASH之后,我不太可能切换到其他任何东西,抱歉。习惯的问题,请参见C++发明者。值得注意的是:“我更喜欢用下划线来分隔标识符中的单词(例如,代码> EntEngEngult),而不是替代方案,如<代码> EntaleCuth和 EntaltCalue。”@ Mat:嗯,我不必同意C++的发明人。关于camelcase,好的方面是按下left shift键是“自由的”(左手几乎不会离开该点),而下划线需要额外的按键。此外,在camelcase(正确使用时)中,前导字母的大小写用于区分类型和变量/方法/函数。在camelcase之后,下划线表示法看起来很奇怪,相比之下过于冗长。这是合乎逻辑的。如果您感兴趣,请获取Qt4/5源代码并研究它们。他们有非常干净的编码风格。@mat:不管怎么说,这是品味的问题,这是我给了很多东西,这是习惯,所以习惯保持不变。下划线在不区分大小写的语言中可以正常工作。谢谢你的帮助。不过我会接受mat的回答,因为它更详细。它很有效,谢谢你的帮助/快速回复。有趣的是,我在发布之前偶然提到了clfpd,但出于某种原因没有尝试:-\。我强烈建议在程序中对所有整数算术使用CLP(FD)约束。您通常会得到更通用的程序,而额外成本通常可以忽略不计。例如,对于SWI Prolog,我在初始化文件中有
    :-use_module(library(clpfd))。
    ,以便CLP(FD)约束在顶层自动对我可用,这与GNU Prolog和B-Prolog等其他知名系统中非常相似。