Prolog:编写rpg stat打印程序时的算术问题
Prolog: arithmetic problems while writing rpg stat printing program
我一直在尝试编写(作为练习 - 以了解一些关于序言的知识)一个小代码片段,它打印 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).
但是,我 运行 遇到了几个与处理 numbers/arithmetics 有关的问题。
首先,我希望
raceAttributes(human, Str, Dex, Con, Int, Wis, Cha).
将打印参数组合。相反,我得到 false
。
其次,我无法以优雅的方式处理 raceAttribCost
和 statDiffCost
中的数字参数。
基本上,我必须创建两个版本的 raceAttribCost
,因为根据我指定的参数,其中一个将需要比较右侧的 "instantiated" 个变量。
所以,我想知道如何
- 调用
raceAttributes
确实有效。
- 删除
raceAttribCost
的一个版本,只保留其中一个
- (可选)用更紧凑的东西替换
statDiffCost
。
这三个都是同一个问题的一部分,混合了符号 "calculations" 和数值算术。
建议?
P.S。我在 windows 7.
上使用 SWI-PL 64 位
使用 CLP(FD) 约束非常容易求解。
关于您的第一个问题(为什么会失败):is/2
不适用于左侧的复合词。您需要 =:=/2
来比较算术表达式的求值。尽管如此,由于未实例化的变量,简单地将 is/2
替换为 =:=/2
对您的情况不起作用。
要解决这个问题,只需将程序中出现的所有 is/2
替换为 CLP(FD) 约束 #=/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.
在所有方向上都完全符合预期。
您可以这样进行:
使用 clpfd 进行关系整数运算:
:- use_module(library(clpfd)).
将所有 is
替换为 #=
。
删除所有 number/1
个目标。
重新运行您原来的查询并反馈:)
我一直在尝试编写(作为练习 - 以了解一些关于序言的知识)一个小代码片段,它打印 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).
但是,我 运行 遇到了几个与处理 numbers/arithmetics 有关的问题。
首先,我希望
raceAttributes(human, Str, Dex, Con, Int, Wis, Cha).
将打印参数组合。相反,我得到 false
。
其次,我无法以优雅的方式处理 raceAttribCost
和 statDiffCost
中的数字参数。
基本上,我必须创建两个版本的 raceAttribCost
,因为根据我指定的参数,其中一个将需要比较右侧的 "instantiated" 个变量。
所以,我想知道如何
- 调用
raceAttributes
确实有效。 - 删除
raceAttribCost
的一个版本,只保留其中一个 - (可选)用更紧凑的东西替换
statDiffCost
。
这三个都是同一个问题的一部分,混合了符号 "calculations" 和数值算术。
建议?
P.S。我在 windows 7.
上使用 SWI-PL 64 位使用 CLP(FD) 约束非常容易求解。
关于您的第一个问题(为什么会失败):is/2
不适用于左侧的复合词。您需要 =:=/2
来比较算术表达式的求值。尽管如此,由于未实例化的变量,简单地将 is/2
替换为 =:=/2
对您的情况不起作用。
要解决这个问题,只需将程序中出现的所有 is/2
替换为 CLP(FD) 约束 #=/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.
在所有方向上都完全符合预期。
您可以这样进行:
使用 clpfd 进行关系整数运算:
:- use_module(library(clpfd)).
将所有
is
替换为#=
。删除所有
number/1
个目标。重新运行您原来的查询并反馈:)