From 19e66dbd8fd3bd66f286bbbcd7ce842d727a4422 Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Fri, 4 Apr 2014 01:48:43 +1100 Subject: Makefile added, files reorganised --- agent.prolog | 278 ----------------------------------------------------- bin/.gitignore | 5 + command.prolog | 47 --------- main.prolog | 34 ------- makefile | 20 ++++ map.prolog | 135 -------------------------- misc.prolog | 20 ---- parser.prolog | 77 --------------- src/agent.prolog | 278 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/command.prolog | 47 +++++++++ src/main.prolog | 34 +++++++ src/map.prolog | 135 ++++++++++++++++++++++++++ src/misc.prolog | 20 ++++ src/parser.prolog | 77 +++++++++++++++ 14 files changed, 616 insertions(+), 591 deletions(-) delete mode 100644 agent.prolog create mode 100644 bin/.gitignore delete mode 100644 command.prolog delete mode 100644 main.prolog create mode 100644 makefile delete mode 100644 map.prolog delete mode 100644 misc.prolog delete mode 100644 parser.prolog create mode 100644 src/agent.prolog create mode 100644 src/command.prolog create mode 100644 src/main.prolog create mode 100644 src/map.prolog create mode 100644 src/misc.prolog create mode 100644 src/parser.prolog diff --git a/agent.prolog b/agent.prolog deleted file mode 100644 index 4085bf9..0000000 --- a/agent.prolog +++ /dev/null @@ -1,278 +0,0 @@ - -:- module(agent, [init, look/0, move/1, take/1, shoot/1, hazardAt/1, somethingAt/1]). - - -:- consult('misc.prolog'). -:- consult('parser.prolog'). -:- consult('map.prolog'). - - - - -% initialisation - -init :- - initPos, - initPits, - initWumpus, - initGold, - initBats, - roomList(Rooms), - filter(Rooms, hazardAt, Walkable), - isConnected(Walkable) *-> !; init. - - -initPos :- - retractall(moves(_)), - asserta(moves(0)), - retractall(here(_)), - roomList(Rooms), - filter(Rooms, somethingAt, Emptyrooms), - random_member(X,Emptyrooms), - asserta(here(X)). - - -initPits :- - retractall(pitAt(_)), - insert(5,pitAt). - - -initWumpus :- - retractall(wumpusAt(_)), - roomList(Rooms), - filter(Rooms, somethingAt, Emptyrooms), - random_member(X,Emptyrooms), - asserta(wumpusAt(X)). - - -initGold :- - retractall(goldAt(_)), - retractall(haveGold(_)), - insert(3,goldAt), - asserta(haveGold(0)). - - -initBats :- - retractall(batsAt(_)), - insert(2,batsAt). - - -insert(N,Thing) :- - N > 0, - Nx is N - 1, - insert(Nx,Thing), - roomList(Rooms), - filter(Rooms, somethingAt, Emptyrooms), - random_member(X,Emptyrooms), - P =.. [Thing,X], - asserta(P). -insert(0,_) :- true. - - - - -% command functions - -look :- - here(Location), - writeSenses(Location), - writeExits(Location). - - -move(Direction) :- - here(Location), - connects(Location, New, Direction), - retract(here(Location)), - asserta(here(New)), - join(['You move to the ',Direction,'.\n\n'],W), - write(W), - checkHazards, - incrementMoves, - look, !. - - -move(_) :- - write('Unknown direction.\n\n'). - - -take(gold) :- - here(Location), - goldAt(Location), - retract(goldAt(Location)), - haveGold(G), - Gx is G + 1, - retract(haveGold(G)), - asserta(haveGold(Gx)), - write('You find some gold. Lucky you.\n\n'), - incrementMoves, !. - - -take(_) :- - write('You cannot take that.\n\n'). - - -shoot(Direction) :- - here(Location), - connects(Location, Target, Direction), - wumpusAt(Target), - write('You hear an unearthly scream.\n\n'), - retract(wumpusAt(Target)), - incrementMoves, - win. - - -shoot(Direction) :- - here(Location), - connects(Location, Target, Direction), - not(wumpusAt(Target)), - write('Thunk. Missed.\n\n'), - incrementMoves, - moveWumpus. - - -shoot(_) :- - write('Unknown target.\n\n'). - - - - -% letting the player know what's going on - -writeSenses(Location) :- - glitter(Location), - breeze(Location), - bats(Location), - stench(Location). - - -glitter(Location) :- - current_predicate(goldAt/1), - goldAt(Location), - write('You see a glitter along the sandy floor of the cave.\n'). -glitter(_) :- true. - - -breeze(Location) :- - current_predicate(pitAt/1), - connects(Location, ConnectedRoom, _), - pitAt(ConnectedRoom), - write('A cold breeze blows through the room, making you shiver slightly.\n'). -breeze(_) :- true. - - -bats(Location) :- - current_predicate(batsAt/1), - connects(Location, ConnectedRoom, _), - batsAt(ConnectedRoom), - write('All available surfaces are covered in guano. How unsanitary.\n'). -bats(_) :- true. - - -stench(Location) :- - current_predicate(wumpusAt/1), - connects(Location, ConnectedRoom, _), - wumpusAt(ConnectedRoom), - write('An overpowering stench fills your nose.\n'). -stench(_) :- true. - - -writeExits(Location) :- - findall(X, connects(Location,_,X), Exits), - intercalate(Exits, ', ', O), - join(['There are exits to the ',O,'.\n'],W), - write(W). - - - - -% modifying things and checking the ramifications - -moveWumpus :- - wumpusAt(Old), - findall(X, connects(Old,X,_), PossibleNews), - random_member(New, PossibleNews), - retract(wumpusAt(Old)), - asserta(wumpusAt(New)), - checkWumpus. - - -checkHazards :- - checkWumpus, - checkBats, - checkPit. - - -checkWumpus :- - current_predicate(wumpusAt/1), - here(Location), - wumpusAt(Location), - lose(eaten). -checkWumpus :- true. - - -checkBats :- - current_predicate(batsAt/1), - here(Location), - batsAt(Location), - write('A giant bat swoops down, picks you up, and deposits you elsewhere in the cave.\n\n'), - roomList(Rooms), - random_member(NewLocation, Rooms), - retract(here(Location)), - asserta(here(NewLocation)), - checkHazards. -checkBats :- true. - - -checkPit :- - current_predicate(pitAt/1), - here(Location), - pitAt(Location), - lose(pit). -checkPit :- true. - - - - -% winning, losing, and otherwise - -incrementMoves :- - moves(N), - retractall(moves(_)), - Nx is N + 1, - asserta(moves(Nx)). - - -win :- - write('*** YOU WIN ***\n'), - moves(M), - haveGold(G), - join(['\nWin accomplished in ',M,' moves with ',G,' gold found\n'],W), - write(W), - halt(0). - - -lose(eaten) :- - write('You have been eaten by the wumpus.\n'), - write('*** GAME OVER ***\n'), - halt(0). - - -lose(pit) :- - write('You have fallen into a bottomless pit.\n'), - write('*** GAME OVER ***\n'), - halt(0). - - - - -% miscellaneous clauses - -somethingAt(X) :- current_predicate(here/1), here(X). -somethingAt(X) :- current_predicate(goldAt/1), goldAt(X). -somethingAt(X) :- hazardAt(X). - - -hazardAt(X) :- current_predicate(wumpusAt/1), wumpusAt(X). -hazardAt(X) :- current_predicate(pitAt/1), pitAt(X). -hazardAt(X) :- current_predicate(batsAt/1), batsAt(X). - diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..ce82cfb --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1,5 @@ + +# directory for binaries; no files will be tracked here + +* +!.gitignore diff --git a/command.prolog b/command.prolog deleted file mode 100644 index f897735..0000000 --- a/command.prolog +++ /dev/null @@ -1,47 +0,0 @@ - - -:- module(command, [getCommand/2]). - - -:- consult('parser.prolog'). - - - - -% functions for parsing a list of words into a recognised command - -getCommand(['quit'],C) :- C =.. [quit]. -getCommand(['exit'],C) :- C =.. [quit]. - - -getCommand(['go',X],C) :- C =.. [move,X]. -getCommand(['move',X],C) :- C =.. [move,X]. - - -getCommand(['n'],C) :- C =.. [move,north]. -getCommand(['north'],C) :- C =.. [move,north]. -getCommand(['s'],C) :- C =.. [move,south]. -getCommand(['south'],C) :- C =.. [move,south]. -getCommand(['e'],C) :- C =.. [move,east]. -getCommand(['east'],C) :- C =.. [move,east]. -getCommand(['w'],C) :- C =.. [move,west]. -getCommand(['west'],C) :- C =.. [move,west]. - - -getCommand(['nw'],C) :- C =.. [move,northwest]. -getCommand(['northwest'],C) :- C =.. [move,northwest]. -getCommand(['ne'],C) :- C =.. [move,northeast]. -getCommand(['northeast'],C) :- C =.. [move,northeast]. -getCommand(['sw'],C) :- C =.. [move,southwest]. -getCommand(['southwest'],C) :- C =.. [move,southwest]. -getCommand(['se'],C) :- C =.. [move,southeast]. -getCommand(['southeast'],C) :- C =.. [move,southeast]. - - -getCommand(['take',X],C) :- C =.. [take,X]. -getCommand(['shoot',X],C) :- C =.. [shoot,X]. - - -getCommand(['l'],C) :- C =.. [look]. -getCommand(['look'],C) :- C =.. [look]. - diff --git a/main.prolog b/main.prolog deleted file mode 100644 index ef23f4f..0000000 --- a/main.prolog +++ /dev/null @@ -1,34 +0,0 @@ - - -:- consult('parser.prolog'). -:- consult('agent.prolog'). -:- consult('command.prolog'). - - - - -play :- - init, - look, - playLoop. - - -playLoop :- - prompt(Line), - evalLine(Line). - - -evalLine(Line) :- - getCommand(Line,Command), - Command, - playLoop. - - -evalLine(_) :- - write('What?\n\n'), - playLoop. - - -quit :- - halt(0). - diff --git a/makefile b/makefile new file mode 100644 index 0000000..2adaf2a --- /dev/null +++ b/makefile @@ -0,0 +1,20 @@ + +OUTPUTDIR = bin +SOURCEDIR = src + +EXECUTABLES = ${OUTPUTDIR}/wumpus + + + +all: huntthewumpus + + +clean: + +distclean: + rm ${EXECUTABLES} + + + +huntthewumpus: + prolog --goal=play --stand_alone=true -o ${OUTPUTDIR}/wumpus -c ${SOURCEDIR}/main.prolog diff --git a/map.prolog b/map.prolog deleted file mode 100644 index f5bb863..0000000 --- a/map.prolog +++ /dev/null @@ -1,135 +0,0 @@ - -:- module(map, [roomList/1, isConnected/1, connects/3]). - - -:- consult('misc.prolog'). - - - - -% map has 20 rooms, labelled a through t -% connections between rooms inscribe a dodecahedron, with the rooms -% corresponding to the vertices and the connections between them to -% the edges - - -roomList(X) :- X = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]. - - -isConnected([]) :- true. -isConnected(X) :- - head(Y,X), - tail(Z,X), - connectTail([Y],Z). - -connectTail(_,[]) :- true. -connectTail([],_) :- false. -connectTail(Open,G) :- - head(X,Open), - tail(Y,Open), - findall(N, connects(X,N,_), Ns), - subtract(G,Ns,Gx), - subtract(G,Gx,Nx), - append(Y,Nx,Yx), - connectTail(Yx,Gx). - - -% loop around the middle - -connects(a,b,northeast). -connects(b,c,southeast). -connects(c,d,northeast). -connects(d,e,southeast). -connects(e,f,northeast). -connects(f,g,southeast). -connects(g,h,northeast). -connects(h,i,southeast). -connects(i,j,northeast). -connects(j,a,southeast). - - -% loop in the other direction around the middle - -connects(a,j,northwest). -connects(j,i,southwest). -connects(i,h,northwest). -connects(h,g,southwest). -connects(g,f,northwest). -connects(f,e,southwest). -connects(e,d,northwest). -connects(d,c,southwest). -connects(c,b,northwest). -connects(b,a,southwest). - - -% connections from the middle loop up to the top pentagon - -connects(b,k,north). -connects(d,l,north). -connects(f,m,north). -connects(h,n,north). -connects(j,o,north). - - -% connections from the top pentagon down to the middle loop - -connects(k,b,south). -connects(l,d,south). -connects(m,f,south). -connects(n,h,south). -connects(o,j,south). - - -% connections around the top pentagon - -connects(k,l,east). -connects(l,m,east). -connects(m,n,east). -connects(n,o,east). -connects(o,k,east). - - -% connections around the top pentagon in the other direction - -connects(l,k,west). -connects(m,l,west). -connects(n,m,west). -connects(o,n,west). -connects(k,o,west). - - -% connections from the middle loop to the bottom pentagon - -connects(a,p,south). -connects(c,q,south). -connects(e,r,south). -connects(g,s,south). -connects(i,t,south). - - -% connections from the bottom pentagon up to the middle loop - -connects(p,a,north). -connects(q,c,north). -connects(r,e,north). -connects(s,g,north). -connects(t,i,north). - - -% connections around the bottom pentagon - -connects(p,q,east). -connects(q,r,east). -connects(r,s,east). -connects(s,t,east). -connects(t,p,east). - - -% connections around the bottom pentagon in the other direction - -connects(q,p,west). -connects(r,q,west). -connects(s,r,west). -connects(t,s,west). -connects(p,t,west). - diff --git a/misc.prolog b/misc.prolog deleted file mode 100644 index 6d8ad68..0000000 --- a/misc.prolog +++ /dev/null @@ -1,20 +0,0 @@ - -:- module(misc, [filter/3, head/2, tail/2]). - - - - -filter(List, Predicate, Result) :- - Test =.. [Predicate,X], - findall(X, Test, No), - subtract(List, No, Result). - - -head(X,[Y]) :- X = Y. -head(X,[Y|_]) :- X = Y. - - -tail(X,[]) :- X = []. -tail(X,[_]) :- X = []. -tail(X,[_|Y]) :- X = Y. - diff --git a/parser.prolog b/parser.prolog deleted file mode 100644 index c9f9771..0000000 --- a/parser.prolog +++ /dev/null @@ -1,77 +0,0 @@ - -:- module(parser, [prompt/1, readList/1, readLine/1, split/2, join/2, intercalate/3]). - - -% functions for dealing with lines of text -% eg obtaining one, parsing it into a list of words, and rejoining it - -% prompt provides the user with a '>' prompt -% readList merely obtains and parses the input -% readLine obtains a raw line of input -% split parses a line of text into words -% join takes a list of words and joins them into one string - - -prompt(L) :- - write('> '), - readList(L). - - -readList(L) :- - readLine(X), - split(X,L). - - -readLine(L) :- - get_char(C), - readLine_tail(C,L). - - -readLine_tail('\n',[]) :- !. -readLine_tail(C,[C|X]) :- - get_char(C2), - readLine_tail(C2,X). - - -split(X,R) :- - wordList(R,X,[]), !. - - -join([X|Y],R) :- - join(Y,Rx), - atom_concat(X,Rx,R). -join([X],R) :- - R = X. - - -intercalate([X|Y], Spacer, Result) :- - intercalate(Y, Spacer, Tail), - atom_concat(X, Spacer, Head), - atom_concat(Head, Tail, Result). -intercalate([X], _, Result) :- Result = X. - - -wordList(X) --> whitespace, wordList(X). -wordList([X]) --> word(X). -wordList([X]) --> word(X), whitespace. -wordList([X|Y]) --> word(X), whitespace, wordList(Y). - - -word(W) --> charList(X), {atom_chars(W,X)}. - - -charList([X|Xs]) --> char(X), charList(Xs). -charList([X]) --> char(X). - - -whitespace --> whsp, whitespace. -whitespace --> whsp. - - -whsp --> oneOf(_,[' ', '\r', '\n', '\t']). -char(X) --> noneOf(X,[' ', '\r', '\n', '\t']). - - -oneOf(X,L) --> [X], {member(X,L)}. -noneOf(X,L) --> [X], {not(member(X,L))}. - diff --git a/src/agent.prolog b/src/agent.prolog new file mode 100644 index 0000000..4085bf9 --- /dev/null +++ b/src/agent.prolog @@ -0,0 +1,278 @@ + +:- module(agent, [init, look/0, move/1, take/1, shoot/1, hazardAt/1, somethingAt/1]). + + +:- consult('misc.prolog'). +:- consult('parser.prolog'). +:- consult('map.prolog'). + + + + +% initialisation + +init :- + initPos, + initPits, + initWumpus, + initGold, + initBats, + roomList(Rooms), + filter(Rooms, hazardAt, Walkable), + isConnected(Walkable) *-> !; init. + + +initPos :- + retractall(moves(_)), + asserta(moves(0)), + retractall(here(_)), + roomList(Rooms), + filter(Rooms, somethingAt, Emptyrooms), + random_member(X,Emptyrooms), + asserta(here(X)). + + +initPits :- + retractall(pitAt(_)), + insert(5,pitAt). + + +initWumpus :- + retractall(wumpusAt(_)), + roomList(Rooms), + filter(Rooms, somethingAt, Emptyrooms), + random_member(X,Emptyrooms), + asserta(wumpusAt(X)). + + +initGold :- + retractall(goldAt(_)), + retractall(haveGold(_)), + insert(3,goldAt), + asserta(haveGold(0)). + + +initBats :- + retractall(batsAt(_)), + insert(2,batsAt). + + +insert(N,Thing) :- + N > 0, + Nx is N - 1, + insert(Nx,Thing), + roomList(Rooms), + filter(Rooms, somethingAt, Emptyrooms), + random_member(X,Emptyrooms), + P =.. [Thing,X], + asserta(P). +insert(0,_) :- true. + + + + +% command functions + +look :- + here(Location), + writeSenses(Location), + writeExits(Location). + + +move(Direction) :- + here(Location), + connects(Location, New, Direction), + retract(here(Location)), + asserta(here(New)), + join(['You move to the ',Direction,'.\n\n'],W), + write(W), + checkHazards, + incrementMoves, + look, !. + + +move(_) :- + write('Unknown direction.\n\n'). + + +take(gold) :- + here(Location), + goldAt(Location), + retract(goldAt(Location)), + haveGold(G), + Gx is G + 1, + retract(haveGold(G)), + asserta(haveGold(Gx)), + write('You find some gold. Lucky you.\n\n'), + incrementMoves, !. + + +take(_) :- + write('You cannot take that.\n\n'). + + +shoot(Direction) :- + here(Location), + connects(Location, Target, Direction), + wumpusAt(Target), + write('You hear an unearthly scream.\n\n'), + retract(wumpusAt(Target)), + incrementMoves, + win. + + +shoot(Direction) :- + here(Location), + connects(Location, Target, Direction), + not(wumpusAt(Target)), + write('Thunk. Missed.\n\n'), + incrementMoves, + moveWumpus. + + +shoot(_) :- + write('Unknown target.\n\n'). + + + + +% letting the player know what's going on + +writeSenses(Location) :- + glitter(Location), + breeze(Location), + bats(Location), + stench(Location). + + +glitter(Location) :- + current_predicate(goldAt/1), + goldAt(Location), + write('You see a glitter along the sandy floor of the cave.\n'). +glitter(_) :- true. + + +breeze(Location) :- + current_predicate(pitAt/1), + connects(Location, ConnectedRoom, _), + pitAt(ConnectedRoom), + write('A cold breeze blows through the room, making you shiver slightly.\n'). +breeze(_) :- true. + + +bats(Location) :- + current_predicate(batsAt/1), + connects(Location, ConnectedRoom, _), + batsAt(ConnectedRoom), + write('All available surfaces are covered in guano. How unsanitary.\n'). +bats(_) :- true. + + +stench(Location) :- + current_predicate(wumpusAt/1), + connects(Location, ConnectedRoom, _), + wumpusAt(ConnectedRoom), + write('An overpowering stench fills your nose.\n'). +stench(_) :- true. + + +writeExits(Location) :- + findall(X, connects(Location,_,X), Exits), + intercalate(Exits, ', ', O), + join(['There are exits to the ',O,'.\n'],W), + write(W). + + + + +% modifying things and checking the ramifications + +moveWumpus :- + wumpusAt(Old), + findall(X, connects(Old,X,_), PossibleNews), + random_member(New, PossibleNews), + retract(wumpusAt(Old)), + asserta(wumpusAt(New)), + checkWumpus. + + +checkHazards :- + checkWumpus, + checkBats, + checkPit. + + +checkWumpus :- + current_predicate(wumpusAt/1), + here(Location), + wumpusAt(Location), + lose(eaten). +checkWumpus :- true. + + +checkBats :- + current_predicate(batsAt/1), + here(Location), + batsAt(Location), + write('A giant bat swoops down, picks you up, and deposits you elsewhere in the cave.\n\n'), + roomList(Rooms), + random_member(NewLocation, Rooms), + retract(here(Location)), + asserta(here(NewLocation)), + checkHazards. +checkBats :- true. + + +checkPit :- + current_predicate(pitAt/1), + here(Location), + pitAt(Location), + lose(pit). +checkPit :- true. + + + + +% winning, losing, and otherwise + +incrementMoves :- + moves(N), + retractall(moves(_)), + Nx is N + 1, + asserta(moves(Nx)). + + +win :- + write('*** YOU WIN ***\n'), + moves(M), + haveGold(G), + join(['\nWin accomplished in ',M,' moves with ',G,' gold found\n'],W), + write(W), + halt(0). + + +lose(eaten) :- + write('You have been eaten by the wumpus.\n'), + write('*** GAME OVER ***\n'), + halt(0). + + +lose(pit) :- + write('You have fallen into a bottomless pit.\n'), + write('*** GAME OVER ***\n'), + halt(0). + + + + +% miscellaneous clauses + +somethingAt(X) :- current_predicate(here/1), here(X). +somethingAt(X) :- current_predicate(goldAt/1), goldAt(X). +somethingAt(X) :- hazardAt(X). + + +hazardAt(X) :- current_predicate(wumpusAt/1), wumpusAt(X). +hazardAt(X) :- current_predicate(pitAt/1), pitAt(X). +hazardAt(X) :- current_predicate(batsAt/1), batsAt(X). + diff --git a/src/command.prolog b/src/command.prolog new file mode 100644 index 0000000..f897735 --- /dev/null +++ b/src/command.prolog @@ -0,0 +1,47 @@ + + +:- module(command, [getCommand/2]). + + +:- consult('parser.prolog'). + + + + +% functions for parsing a list of words into a recognised command + +getCommand(['quit'],C) :- C =.. [quit]. +getCommand(['exit'],C) :- C =.. [quit]. + + +getCommand(['go',X],C) :- C =.. [move,X]. +getCommand(['move',X],C) :- C =.. [move,X]. + + +getCommand(['n'],C) :- C =.. [move,north]. +getCommand(['north'],C) :- C =.. [move,north]. +getCommand(['s'],C) :- C =.. [move,south]. +getCommand(['south'],C) :- C =.. [move,south]. +getCommand(['e'],C) :- C =.. [move,east]. +getCommand(['east'],C) :- C =.. [move,east]. +getCommand(['w'],C) :- C =.. [move,west]. +getCommand(['west'],C) :- C =.. [move,west]. + + +getCommand(['nw'],C) :- C =.. [move,northwest]. +getCommand(['northwest'],C) :- C =.. [move,northwest]. +getCommand(['ne'],C) :- C =.. [move,northeast]. +getCommand(['northeast'],C) :- C =.. [move,northeast]. +getCommand(['sw'],C) :- C =.. [move,southwest]. +getCommand(['southwest'],C) :- C =.. [move,southwest]. +getCommand(['se'],C) :- C =.. [move,southeast]. +getCommand(['southeast'],C) :- C =.. [move,southeast]. + + +getCommand(['take',X],C) :- C =.. [take,X]. +getCommand(['shoot',X],C) :- C =.. [shoot,X]. + + +getCommand(['l'],C) :- C =.. [look]. +getCommand(['look'],C) :- C =.. [look]. + diff --git a/src/main.prolog b/src/main.prolog new file mode 100644 index 0000000..ef23f4f --- /dev/null +++ b/src/main.prolog @@ -0,0 +1,34 @@ + + +:- consult('parser.prolog'). +:- consult('agent.prolog'). +:- consult('command.prolog'). + + + + +play :- + init, + look, + playLoop. + + +playLoop :- + prompt(Line), + evalLine(Line). + + +evalLine(Line) :- + getCommand(Line,Command), + Command, + playLoop. + + +evalLine(_) :- + write('What?\n\n'), + playLoop. + + +quit :- + halt(0). + diff --git a/src/map.prolog b/src/map.prolog new file mode 100644 index 0000000..f5bb863 --- /dev/null +++ b/src/map.prolog @@ -0,0 +1,135 @@ + +:- module(map, [roomList/1, isConnected/1, connects/3]). + + +:- consult('misc.prolog'). + + + + +% map has 20 rooms, labelled a through t +% connections between rooms inscribe a dodecahedron, with the rooms +% corresponding to the vertices and the connections between them to +% the edges + + +roomList(X) :- X = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]. + + +isConnected([]) :- true. +isConnected(X) :- + head(Y,X), + tail(Z,X), + connectTail([Y],Z). + +connectTail(_,[]) :- true. +connectTail([],_) :- false. +connectTail(Open,G) :- + head(X,Open), + tail(Y,Open), + findall(N, connects(X,N,_), Ns), + subtract(G,Ns,Gx), + subtract(G,Gx,Nx), + append(Y,Nx,Yx), + connectTail(Yx,Gx). + + +% loop around the middle + +connects(a,b,northeast). +connects(b,c,southeast). +connects(c,d,northeast). +connects(d,e,southeast). +connects(e,f,northeast). +connects(f,g,southeast). +connects(g,h,northeast). +connects(h,i,southeast). +connects(i,j,northeast). +connects(j,a,southeast). + + +% loop in the other direction around the middle + +connects(a,j,northwest). +connects(j,i,southwest). +connects(i,h,northwest). +connects(h,g,southwest). +connects(g,f,northwest). +connects(f,e,southwest). +connects(e,d,northwest). +connects(d,c,southwest). +connects(c,b,northwest). +connects(b,a,southwest). + + +% connections from the middle loop up to the top pentagon + +connects(b,k,north). +connects(d,l,north). +connects(f,m,north). +connects(h,n,north). +connects(j,o,north). + + +% connections from the top pentagon down to the middle loop + +connects(k,b,south). +connects(l,d,south). +connects(m,f,south). +connects(n,h,south). +connects(o,j,south). + + +% connections around the top pentagon + +connects(k,l,east). +connects(l,m,east). +connects(m,n,east). +connects(n,o,east). +connects(o,k,east). + + +% connections around the top pentagon in the other direction + +connects(l,k,west). +connects(m,l,west). +connects(n,m,west). +connects(o,n,west). +connects(k,o,west). + + +% connections from the middle loop to the bottom pentagon + +connects(a,p,south). +connects(c,q,south). +connects(e,r,south). +connects(g,s,south). +connects(i,t,south). + + +% connections from the bottom pentagon up to the middle loop + +connects(p,a,north). +connects(q,c,north). +connects(r,e,north). +connects(s,g,north). +connects(t,i,north). + + +% connections around the bottom pentagon + +connects(p,q,east). +connects(q,r,east). +connects(r,s,east). +connects(s,t,east). +connects(t,p,east). + + +% connections around the bottom pentagon in the other direction + +connects(q,p,west). +connects(r,q,west). +connects(s,r,west). +connects(t,s,west). +connects(p,t,west). + diff --git a/src/misc.prolog b/src/misc.prolog new file mode 100644 index 0000000..6d8ad68 --- /dev/null +++ b/src/misc.prolog @@ -0,0 +1,20 @@ + +:- module(misc, [filter/3, head/2, tail/2]). + + + + +filter(List, Predicate, Result) :- + Test =.. [Predicate,X], + findall(X, Test, No), + subtract(List, No, Result). + + +head(X,[Y]) :- X = Y. +head(X,[Y|_]) :- X = Y. + + +tail(X,[]) :- X = []. +tail(X,[_]) :- X = []. +tail(X,[_|Y]) :- X = Y. + diff --git a/src/parser.prolog b/src/parser.prolog new file mode 100644 index 0000000..c9f9771 --- /dev/null +++ b/src/parser.prolog @@ -0,0 +1,77 @@ + +:- module(parser, [prompt/1, readList/1, readLine/1, split/2, join/2, intercalate/3]). + + +% functions for dealing with lines of text +% eg obtaining one, parsing it into a list of words, and rejoining it + +% prompt provides the user with a '>' prompt +% readList merely obtains and parses the input +% readLine obtains a raw line of input +% split parses a line of text into words +% join takes a list of words and joins them into one string + + +prompt(L) :- + write('> '), + readList(L). + + +readList(L) :- + readLine(X), + split(X,L). + + +readLine(L) :- + get_char(C), + readLine_tail(C,L). + + +readLine_tail('\n',[]) :- !. +readLine_tail(C,[C|X]) :- + get_char(C2), + readLine_tail(C2,X). + + +split(X,R) :- + wordList(R,X,[]), !. + + +join([X|Y],R) :- + join(Y,Rx), + atom_concat(X,Rx,R). +join([X],R) :- + R = X. + + +intercalate([X|Y], Spacer, Result) :- + intercalate(Y, Spacer, Tail), + atom_concat(X, Spacer, Head), + atom_concat(Head, Tail, Result). +intercalate([X], _, Result) :- Result = X. + + +wordList(X) --> whitespace, wordList(X). +wordList([X]) --> word(X). +wordList([X]) --> word(X), whitespace. +wordList([X|Y]) --> word(X), whitespace, wordList(Y). + + +word(W) --> charList(X), {atom_chars(W,X)}. + + +charList([X|Xs]) --> char(X), charList(Xs). +charList([X]) --> char(X). + + +whitespace --> whsp, whitespace. +whitespace --> whsp. + + +whsp --> oneOf(_,[' ', '\r', '\n', '\t']). +char(X) --> noneOf(X,[' ', '\r', '\n', '\t']). + + +oneOf(X,L) --> [X], {member(X,L)}. +noneOf(X,L) --> [X], {not(member(X,L))}. + -- cgit