1

私はプロローグの初めてのユーザーで、ここからさまざまな基本について学び、約 1 週間使用しており、ある程度役に立ちました。私は、架空のゲーム タイトルのデータベース ルックアップを設計してきました。ユーザーは、ゲーム内の特定のキャラクターの統計情報を取得するために獣医師を参照できます。あなたが私に尋ねるなら、素晴らしいプロジェクトのように聞こえます:)

私はノードを記述する「フレーム」とその使用方法について学習してきたので、使用する形式はこれらの線に沿ったものになるでしょう。私が学んでいる最新の項目は、プロローグの「Numbers」とその仕組みです。チュートリアルでは、より動的な方法で使用するまでは非常に単純に見えました。

データノード用に次のように設定しました。(疑似コード)

フレーム: 名前(キャラクター)、親(なし)、base_stat(8.0)。

フレーム:名前(npc)、親(キャラクター)。

フレーム:名前(敵)、親(npc)。

フレーム: 名前(red_faction)、親(敵)、atk_bonus(1.5)、spd_bonus(1.25)、def_bonus(0.25)。

フレーム: name(blue_faction)、parent(enemy)、atk_bonus(1)、spd_bonus(1)、def_bonus(1)。

フレーム: 名前(fire_warrior)、親(red_faction)、レベル(1.0)、保持(なし)。

フレーム: 名前(water_consort)、親(blue_faction)、レベル(1.0)、保持(何もない)。

相談したときに、次の統計をユーザーに返したいと思います: 攻撃 (?)、速度 (?)、防御 (?)。

私は方程式を使って「?」を計算したいと思っていました。「(base_stat + level) * stat_bonus」という式が使用される私のプログラムの領域。だからこのようなもの: -

compute(attribute) :-
    stat_bonus(stat bonus from parent node for required stat example:atk_bonus)
    base_stat(value from the character node's base_stat)
    level(value from the character we are looking up: eg water_consort lvl1)
    attribute is (level+base_stat) * stat_bonus

プロローグで数への代数的アプローチについてチューターから簡単な説明を受けた後、この構造を思いつきました。例は次のようになりました:-

student(jack, 25).
student(jill, 21).

avg_Score(Z) :-
    student(jack, X),
    student(jill, Y),
    Z = (X + Y)/2.

X と Y の値を抽出する必要があることは理解しています。これらの値を再確認したい場合は、その抽出を繰り返して使用する必要があります。

私の小さなプロジェクトに戻ると、いくつかの派閥ノードがあります (完全な図には 3 つありますが、必要なプロセスを N 回適用できると想定しているため、2 つを超える意味はありません)。私の計算のための情報?

火の戦士のデータを要求すると仮定すると、私のシステムは統計 (攻撃としましょう) を計算する必要があり、私が持っている方程式を参照します。次の情報が必要です。

  1. 親ノード「red_faction」によって与えられる攻撃ボーナス
  2. gggrandparent ノードの「character」によって指定された base_stat
  3. インスタンス ノードのレベル

私の家庭教師が私に与えた例は、すべてのリクエストでハードコーディングする場合にのみ機能し、非常に限られています。「N」派閥と各派閥の「M」文字インスタンスに使用できる方法はありますか? 私はまた彼女に迷惑をかけますが、彼女はイースターが終わるまで自由ではありません。私が言えることから、Prolog は継承を非常にうまく行っていますが、これを解決する方法がわかりません。

建設的なご意見をお寄せいただきありがとうございます。

4

1 に答える 1

3

プロローグへようこそ!試してみてよかったです。たくさんの想像力を持っているように見えるので、それがあなたの想像力に役立つことを願っています!

ここでは、Prolog に対して多くの奇妙な用語を使用しています。「フレーム」、「ノード」、または「抽出」の意味がよくわかりません。また、「相談」を間違った方法で使用していると確信しています。これはチュートリアルが SICStus 用に書かれているためなのか、それとも単に混乱しているだけなのかはわかりません。また、Prolog で継承を行うことは通常考えませんが、その部分は実際に理解していると思います。それで、あなたが一緒に遊んでくれることを願っています.とにかくあなたの質問に答えることができるかどうか見てみましょう.

まず最初に。大したことではありませんが、平均スコアは次のように実装する必要があります。

avg_score(Z) :-
  student(jack, X),
  student(jill, Y),
  Z is (X + Y) / 2.   % <-- note the use of 'is' instead of '='

これはよくある初心者の間違いです。Prolog はデフォルトで代数を評価しないので、何かを言うとき、(X + Y) / 2実際に行っているのは式を作成することだけであり、div(plus(X, Y), 2). 実際の違いの 1 つは、 が のようisな代数式を評価する方法を知っていることです。(最初から Prolog を使用し、代わりにを使用すると、Prolog の方がはるかに理にかなっていることがわかると事前に警告します。)(X + Y) / 2div(plus(X, Y), 2)clpfd#=is

avg_scoreいいえ、もちろん、 が役に立たないのは、jackjillがその中に埋め込まれていることです。いつか、すべての生徒の平均点を計算したくなるでしょう。まず、平均を計算しましょう。

average(L, Average) :-
  sum(L, Sum),
  length(L, Length),
  Average is Sum / Length.

% this is overly complex because I wanted to show you 
% the tail recursive version
sum(L, Sum) :- sum(L, 0, Sum).

sum([], Sum, Sum).
sum([X|Xs], Acc, Sum) :- Acc1 is X + Acc, sum(Xs, Acc1, Sum).

これで、次のようにすべての学生の平均を取得できます。

avg_score(Z) :-
  findall(X, student(_, X), Scores),
  average(Scores, Z).

これがあなたが求めていることに関連しているかどうかはわかりませんが、参考になるかもしれないので、そこにあります。

もちろん、もう 1 つの可能性は、パラメータ化することです。元のコードを取得して、生徒ごとにパラメーター化できます。

avg_score(Student1, Student2, Z) :-
  student(Student1, X),
  student(Student2, Y),
  Z is (X + Y) / 2.

これは、動物誌を照会するのにより適しているようです。あなたが尋ねるのではなく、尋ねるattack(X)でしょうattack(fire_warrior, X)

Prolog を初めて使うあなたを Logtalk に送り込むのは嫌ですが、探している答えのいくつかが含まれているのではないかと思います。バニラの Prolog がおそらくそうではない方法で、継承を処理するのが特に得意です。しかし、それは大きな気分転換になる可能性があります。たとえば、次のように攻撃統計を照会するための継承チェーンを処理できます。

% this is the inheritance tree
parent_class(character, base).
parent_class(npc, character).
parent_class(enemy, npc).
parent_class(red_faction, enemy).
parent_class(blue_faction, enemy).
parent_class(fire_warrior, red_faction).
parent_class(water_consort, blue_faction).

% these are the attack bonuses
attack_bonus(base, 0).
attack_bonus(red_faction, 1.5).
attack_bonus(blue_faction, 1).

calc_attack_bonus(X, Bonus) :-
  attack_bonus(X, Bonus), !.
calc_attack_bonus(X, Bonus) :-
  \+ attack_bonus(X, Bonus),
  parent_class(X, Parent),
  calc_attack_bonus(Parent, Bonus).

これは、いくつかの基本的なクエリで機能するようです。

?- calc_attack_bonus(fire_warrior, Bonus).
Bonus = 1.5.

?- calc_attack_bonus(character, Bonus).
Bonus = 0.

この動作が必要かどうかはわかりません:

?- calc_attack_bonus(tree, Bonus).
false.

そうでない場合は簡単に修正できます (parent_class失敗した場合はボーナスを 0 に統一し、そうでない場合は再発します)。

ただし、これだけでは拡張できません。より拡張可能なアプローチは次のようになります。

% these are the attack bonuses
attribute(attack_bonus, base, 0).
attribute(attack_bonus, red_faction, 1.5).
attribute(attack_bonus, blue_faction, 1).

% base stats
attribute(base_stat, character, 8.0).

attribute(level, fire_warrior, 1.0).

これで、必要なルールをあまり苦労せずに書くことができます。

calc_attribute(X, Attribute, Value) :-
  attribute(X, Attribute, Value), !.
calc_attribute(X, Attribute, Value) :-
  \+ attribute(X, Attribute, Value),
  parent_class(X, Parent),
  calc_attribute(Parent, Attribute, Value).

そして今、攻撃は簡単になります:

attack(X, Value) :-
  calc_attribute(X, attack_bonus, Bonus),
  calc_attribute(X, base_stat, Base),
  calc_attribute(X, level, Level),
  Value is (Level + Base) * Bonus.

compute理想的には、compute(fire_warrior, attack, Value). それが起こるためには、それattack_bonusが関連していることを知る必要がありますが、attack私たちはそれを知りません. attribute少し再構成してみましょう。

% these are the attack bonuses
attribute(base,         bonus(attack), 0).
attribute(red_faction,  bonus(attack), 1.5).
attribute(blue_faction, bonus(attack), 1).

% base stats
attribute(character, base_stat, 8.0).

attribute(fire_warrior, level, 1.0).

今、私たちは料理しています:

compute(X, Attribute, Value) :-
  calc_attribute(X, bonus(Attribute), Bonus),
  calc_attribute(X, base_stat, Base),
  calc_attribute(X, level, Level),
  Value is (Level + Base) * Bonus.

そして見よ:

?- compute(fire_warrior, attack, Value).
Value = 13.5.

それがあなたの望んだものであることを願っています。:)

大きな編集

楽しみのために、これがProlog のオブジェクト指向拡張言語であるLogtalkでどのようになるか見てみようと思いました。私はLogtalkに非常に慣れていないので、これは良いアプローチかもしれませんし、そうでないかもしれませんが、「トリックを実行」したので、あなたが望んでいるものに沿っているかどうか見てみましょう. まず、基本オブジェクト:

:- object(base).

  :- public(base_stat/1).
  :- public(attack/1).
  :- public(bonus/2).
  :- public(level/1).
  :- public(compute/2).

  bonus(attack, 0).
  base_stat(0).
  level(0).

  compute(Attribute, Value) :-
      ::bonus(Attribute, Bonus),
      ::base_stat(Base),
      ::level(Level),
      Value is (Level + Base) * Bonus.

:- end_object.

これは基本的に、それぞれについて保存する事実と、関心のあるプロパティを計算する方法を定義しています。次に、オブジェクト階層を確立します。

:- object(character, extends(base)).
    base_stat(8.0).
:- end_object.

:- object(npc, extends(character)).
:- end_object.

:- object(enemy, extends(npc)).
:- end_object.

:- object(red_faction, extends(enemy)).
    bonus(attack, 1.5).
    bonus(speed, 1.25).
    bonus(defense, 0.25).
:- end_object.

:- object(blue_faction, extends(enemy)).
    bonus(attack, 1).
    bonus(speed, 1).
    bonus(defense, 1).
:- end_object.

:- object(fire_warrior, extends(red_faction)).
    level(1.0).
    holding(nothing).
:- end_object.

:- object(water_consort, extends(blue_faction)).
    level(1.0).
    holding(nothing).
:- end_object.

これを使用するのはかなり簡単です。

?- fire_warrior::compute(attack, X).
X = 13.5.

?- water_consort::compute(attack, X).
X = 9.0.

これが役立つことを願っています!

于 2013-03-21T22:55:38.437 に答える