我一直在努力编写(作为练习 - 学习一些关于prolog的)一个小代码片段,打印Pen and Paper 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
。这三个都是同一个问题的一部分,它混合了象征性的"计算"和数字算术。
么?
P.S。我在Windows 7上使用SWI-PL 64bit。
答案 0 :(得分:3)
使用CLP(FD)约束非常容易解决。
关于你的第一个问题(为什么会失败):is/2
不适用于左侧的复合词。您需要=:=/2
来比较算术表达式的评估。但是,由于未经实例化的变量,仅仅将is/2
替换为=:=/2
在您的情况下无效。
要解决此问题,只需使用程序中的CLP(FD)约束is/2
替换所有出现的#=/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 :(得分:3)
你可以这样继续:
将clpfd用于关系整数算术:
:- use_module(library(clpfd)).
将is
的所有用途替换为#=
。
删除所有number/1
目标。
重新运行原始查询并向后报告:)