Prolog assert/retract не работает (?)

Я пытаюсь создать простую программу на прологе, но у меня есть проблема:

:- dynamic at/2, i_am_holding/1, i_am_at/1.

/* some lines of code */

i_am_at(room1).

at(revolver, room1).

take(revolver) :- write('You picked up the revolver.'),nl.

take(X):- i_am_at(Place),
      assert(i_am_holding(X)),
      retract(at(X,Place)).

/* some lines of code */

Я хочу, чтобы пользователь поднял револьвер, а затем (револьвер) был убран из того места, где он находится, поэтому он не сможет снова его поднять.

Когда я запускаю свой код, выполняется запрос take(revolver), а take(X) — нет.


person Shevliaskovic    schedule 19.10.2013    source источник
comment
Когда вы говорите, когда я запускаю свой код... что именно вы имеете в виду? Что вы вводили? Я играл с кодом, который вы показали, и он ведет себя так, как я и ожидал. Если вы наберете take(revolver)., вам нужно помнить, что существует несколько решений. Первый напишет, Вы взяли револьвер, а затем второй (если вы попросите его с помощью ;) изменит данные.   -  person lurker    schedule 19.10.2013
comment
Когда я запускаю код, револьвер убирается из Place , но как я могу предотвратить повторное отображение сообщения You picked up the revolver., когда пользователь снова использует запрос take(revolver)?   -  person Shevliaskovic    schedule 19.10.2013
comment
take(X):- i_am_holding(X), write('Ты уже держишь!'), nl. Я понял. в любом случае спасибо   -  person Shevliaskovic    schedule 19.10.2013
comment
Ваше первое take правило просто гласит: Каждый раз, когда вы берете в руки револьвер, пишите... Это должно быть жестко закодировано в револьвере, или вы хотите, чтобы оно говорило: "Вы взяли... за то, что вы берете в руки". ? В случае с револьвером вам нужно правило перед write, которое проверяет, есть ли у вас уже револьвер.   -  person lurker    schedule 19.10.2013
comment
да, совсем забыл об этом. Извините   -  person Shevliaskovic    schedule 19.10.2013


Ответы (1)


Марк прав в деньгах. Вероятно, вы захотите заменить весь свой код чем-то вроде этого:

:- dynamic at/2, holding/1.

at(player, room1).
at(revolver, room1).

take(X) :-
    at(player, Place),
    at(X, Place),
    !,
    format('You pick up the ~a.~n', [X]),
    retract(at(X,Place)),
    assert(holding(X)).

take(X) :-
    holding(X),
    !,
    format('You''re already holding the ~a!~n', [X]).

Есть много интересных способов, которыми вы могли бы пойти дальше. Оператор is_at может сделать код более читабельным:

take(X) :-
  player is_at Place,
  X is_at Place,
  ...

У вас также могут быть хорошие аргументы, основанные на прецедентах, для получения статей и многого другого:

subject(X, Some_X) :- mass_noun(X), !, atom_concat('some ', X, Some_X).
subject(X, The_X)  :- atom_concat('the ', X, The_X).

mass_noun(water).

то вы можете интегрировать их в процедуры вывода:

take(X) :- 
  ...
  subject(X, Subj),
  format('You take ~a.~n', [Subj]),
  ...

Вы также можете делать забавные вещи с DCG, чтобы генерировать выходные данные:

:- use_module(library(dcg/basics)).

success(take(X)) --> "You took ", subject(X).
subject(X) --> "the ", atom(X).

Вы можете сделать это еще более общим с некоторыми театральными действиями, такими как:

success_term(Command) --> { Command =.. CommandList }, success(CommandList).
success([Command, DirectObject]) --> 
  "You ", past_tense(Command), " ", subject(DirectObject), ".".

subject(Noun) --> "the ", atom(Noun).
past_tense(X) --> { past_tense(X, Y) }, atom(Y).

past_tense(take, took).
past_tense(X, Xed) :- atom_concat(X, 'ed', Xed).

Затем запустите это так: phrase(success_term(take(revolver)), X), format('~s~n', [X]), и вы получите You took the revolver., что довольно аккуратно.

Эти текстовые приключения очень весело программировать. Я рекомендую вам ознакомиться с руководством по поиску Amzi Prolog Nani, если вы еще этого не сделали. Там много отличных идей!

person Daniel Lyons    schedule 20.10.2013
comment
Я не очень хорошо разбираюсь в прологе, поэтому я действительно не знаю, что делает ~. Я почти ничего не понял из того, что вы написали :P - person Shevliaskovic; 20.10.2013
comment
@NickShev ~ используется format/2 для введения кодов форматирования. Без format/2 это ничего не значит, поэтому, если вы не используете SWI, это вам не поможет. Что конкретно вас смущает? Я хотел бы объяснить все, что неясно. Моя цель состояла в том, чтобы просто проиллюстрировать некоторые направления, в которых вы могли бы использовать код. Пролог обладает большой мощью, может быть трудно понять, что происходит в коде, на один уровень выше. - person Daniel Lyons; 21.10.2013
comment
Есть где поговорить без комментариев? - person Shevliaskovic; 21.10.2013