Prolog中的自然语言解释器不起作用

时间:2015-04-12 23:14:00

标签: prolog

我在Prolog遇到问题。我正在尝试编写一个转换器,将简单的英语句子转换为Prolog中的命令。 我正在尝试使用教程here创建一个文本冒险游戏。

我的问题是:在启动主命令循环后,当输入一个句子并点击“输入”按钮时,Prolog将只是跳到下一行,似乎根本没有执行命令。无论我多久进入一次全站。在使用这种语言转换器之前,一切正常,游戏可以使用命令播放。问题必须在代码的这一部分内。更确切地说,我认为阅读行或get_command(X)函数的部分很可能无效。 顺便提一下,我正在使用SWI-Polog(如果有重要的话(有些人将这些信息添加到他们的问题中)。 由于我自己无法发现错误,我会尝试发布相关代码。

首先是主命令循环:

command_loop:- 
  write('Welcome to Nani Search'), nl,
  look,nl,
  repeat,
  write('>nani> '),
  get_command(X),
  do(X), nl,
  end_condition(X).

现在转换器(get_command(X)功能位于最底层):

% Natural language converter

command([V], InList):- verb(V, InList-[]).

verb(look, [look|X]-X).
verb(look, [look,around|X]-X).
verb(look, [glotz,ma,alde|X]-X).
verb(list_possessions, [inventory|X]-X).
verb(end, [end|X]-X).
verb(end, [quit|X]-X).
verb(end, [good,bye|X]-X).

command([V,O], InList) :-
  verb(Object_Type, V, InList-S1),
  object(Object_Type, O, S1-[]).

verb(place, goto, [go,to|X]-X).
verb(place, goto, [go|X]-X).
verb(place, goto, [move,to|X]-X).

 % Exceptions for rooms with two words
verb(place, goto, [X|Y]-[X|Y]):- room(X).
verb(place, goto, [dining,room|Y]-[dining,room|Y]).

verb(thing, take, [take|X]-X).
verb(thing, drop, [drop|X]-X).
verb(thing, drop, [put|X]-X).
verb(thing, turn_on, [turn,on|X]-X).
verb(thing, turn_off, [turn,off|X]-X).

object(Type, N, S1-S3) :-
  det(S1-S2),
  noun(Type, N, S2-S3).
object(Type, N, S1-S2) :-
  noun(Type, N, S1-S2).

det([the|X]- X).
det([a|X]-X).
det([an|X]-X).

 % Exceptions for rooms with two words
noun(place, R, [R|X]-X):- room(R).
noun(place, 'dining room', [dining,room|X]-X).

 % Exceptions for things with two words
noun(thing, T, [T|X]-X):- location(object(T,_),_).
noun(thing, T, [T|X]-X):- have(object(T,_)).
noun(thing, 'washing machine', [washing,machine|X]-X).

noun(thing, flashlight, [light|X]-X):- have(object(flashlight,_)).
noun(thing, light, [light|X]-X).

% read a line of words from the user

read_list(L) :-
  write('> '),
  read_line(CL),
  wordlist(L,CL,[]), !.

read_line(L) :-
  get0(C),
  buildlist(C,L).

buildlist(13,[]) :- !.
buildlist(C,[C|X]) :-
  get0(C2),
  buildlist(C2,X).

wordlist([X|Y]) --> word(X), whitespace, wordlist(Y).
wordlist([X]) --> whitespace, wordlist(X).
wordlist([X]) --> word(X).
wordlist([X]) --> word(X), whitespace.

word(W) --> charlist(X), {name(W,X)}.

charlist([X|Y]) --> chr(X), charlist(Y).
charlist([X]) --> chr(X).

chr(X) --> [X],{X>=48}.

whitespace --> whsp, whitespace.
whitespace --> whsp.

whsp --> [X], {X<48}.

% Return a command

get_command(C) :-
  read_list(L),
  command(CL,L),
  C =..  CL, !.
get_command(_) :-
  write('I don''t understand'), nl, fail.

最后,来自命令循环的do-function:

do(goto(X)):-goto(X),!.
do(go(X)):-goto(X),!.
do(take(X)):-take(X),!.
do(put(X,Y)):-put(X),!.
do(turn_on(X)):-turn_on(X),!.
do(turn_off(X)):-turn_off(X),!.
do(inventory):-inventory,!.
do(list_things(X)):-list_things(X),!.
do(look):-look,!.
do(end).
do(_) :-
 write('Invalid command').

通过将自然语言句子转换为这些命令,程序应该启动相应的功能。它应该像这样工作:当你输入go to the office.时,转换器应该将frase转换为命令goto(office)。当一个人写take the flashlight时,它应该将其转换为take(flashlight)。当一个人写look around时。它应该转换为look。然后应该将转换后的命令发送到命令循环并通过do(X)执行(如do-function中所示,X必须是goto(office)之类的命令。 我希望很清楚我的问题是什么。

我也做了一个追踪。命令循环正常启动。这是在命令循环结束后发生的事情(write('>nani> ')仍然是它的一部分。)

 Call: (7) write('>nani> ') ? creep
>nani> 
   Exit: (7) write('>nani> ') ? creep
   Call: (7) get_command(_G3903) ? creep
   Call: (8) read_list(_G3903) ? creep
   Call: (9) write('> ') ? creep
> 
   Exit: (9) write('> ') ? creep
   Call: (9) read_line(_G3903) ? creep
   Call: (10) get0(_G3903) ? creep
|: 

然后我就可以输入一个新命令了。只需按下Enter按钮而不提供任何输入,它将始终执行以下操作:

   Exit: (10) get0(10) ? creep
   Call: (10) buildlist(10, _G3904) ? creep
   Call: (11) get0(_G3906) ? creep
|: 

只要我按下回车,就会重复此操作。当我在按Enter键之前输入一个随机字母或多个字母时,第一个get0的值将会改变,但没有别的。

根据我写的字母,有时会有不同的结果。这是两个例子: 例如,当我尝试编写 dsf 时,会发生这种情况:

|: dsf

   Exit: (10) get0(100) ? skip
   Call: (10) buildlist(100, _G3904) ? fail
   Fail: (9) read_line(_G3903) ? creep
   Fail: (8) read_list(_G3903) ? creep
   Redo: (7) get_command(_G3903) ? creep
   Call: (8) write('I don\'t understand') ? creep
I don't understand
   Exit: (8) write('I don\'t understand') ? creep
   Call: (8) nl ? creep
   Exit: (8) nl ? creep
᠀   Call: (8) fail ? creep
   Fail: (8) fail ? creep
   Fail: (7) get_command(_G3903) ? creep
   Redo: (7) repeat ? creep
   Exit: (7) repeat ? creep
   Call: (7) write('>nani> ') ? creep
>nani> 
   Exit: (7) write('>nani> ') ? creep
   Call: (7) get_command(_G3903) ? creep
   Call: (8) read_list(_G3903) ? creep
   Call: (9) write('> ') ? creep
> 
   Exit: (9) write('> ') ? creep
   Call: (9) read_line(_G3903) ? creep
   Call: (10) get0(_G3903) ? creep
|: 

apg 等其他输入将产生以下结果:

|: apg

Exit: (17) get0(97) ? print
   Exit: (17) get0(97) ? goals
 [17] get0(97)
 [16] buildlist(10, [10|_G3915])
 [15] buildlist(10, [10, 10|_G3915])
 [14] buildlist(10, [10, 10, 10|_G3915])
 [13] buildlist(10, [10, 10, 10, 10|_G3915])
   Exit: (17) get0(97) ? creep
   Call: (17) buildlist(97, _G3915) ? creep
   Call: (18) get0(_G3927) ? creep

当输入更长的命令,随机或类似go to the office.之类的命令时,程序将完全关闭,而不会发表评论。仅在激活跟踪时才会发生此关闭。如果不是这样,像go to the office.这样的命令将再次使程序跳转到下一行,似乎没有做任何事情。 可能还有趣的是,在启动命令循环后,程序需要很长时间才能关闭。显示以下消息:

Waiting for Prolog. Close again to force termination ..

由于我是Prolog的新手,我不太清楚如何解释这个。对我来说,对随机字母作为输入的反应是完全随机的。也许别人有线索。

如果有人可以帮助我的话,我会非常感激。我希望这不是一个错误。

问候:)

0 个答案:

没有答案