:- module(agent, [init, look/0, move/1, take/1, shoot/1]). :- consult('parser.prolog'). :- consult('map.prolog'). % initialisation init :- initPos, initPits, initWumpus, initGold, initBats, !. initPos :- retractall(here(_)), roomList(Rooms), filter(Rooms, somethingAt, Emptyrooms), random_member(X,Emptyrooms), asserta(here(X)). initPits :- true. initWumpus :- retractall(wumpusAt(_)), roomList(Rooms), filter(Rooms, somethingAt, Emptyrooms), random_member(X,Emptyrooms), asserta(wumpusAt(X)). initGold :- retractall(goldAt(_)), retractall(haveGold(_)), insertGold(3), asserta(haveGold(0)). insertGold(N) :- N > 0, Nx is N - 1, insertGold(Nx), roomList(Rooms), filter(Rooms, somethingAt, Emptyrooms), random_member(X,Emptyrooms), asserta(goldAt(X)). insertGold(0) :- true. initBats :- retractall(batsAt(_)), insertBats(2). insertBats(N) :- N > 0, Nx is N - 1, insertBats(Nx), roomList(Rooms), filter(Rooms, somethingAt, Emptyrooms), random_member(X,Emptyrooms), asserta(batsAt(X)). insertBats(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, !. 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'), !. 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)), win. shoot(Direction) :- here(Location), connects(Location, Target, Direction), not(wumpusAt(Target)), write('Thunk. Missed.\n\n'), moveWumpus. % 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 win :- write('*** YOU WIN ***\n'), 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(wumpusAt/1), wumpusAt(X). somethingAt(X) :- current_predicate(pitAt/1), pitAt(X). somethingAt(X) :- current_predicate(goldAt/1), goldAt(X). somethingAt(X) :- current_predicate(batsAt/1), batsAt(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. filter(List, Predicate, Result) :- Test =.. [Predicate,X], findall(X, Test, No), subtract(List, No, Result).