-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
36 changed files
with
2,198 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
* text eol=lf | ||
|
||
# Denote all files that are truly binary and should not be modified. | ||
*.png binary | ||
*.jpg binary | ||
*.ico binary |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
*.class | ||
*.jar | ||
*.zip | ||
*.tmp | ||
*.out | ||
junit*.properties | ||
/*.bat | ||
/*.sh | ||
|
||
.classpath | ||
.project | ||
.settings | ||
|
||
/bin | ||
/build | ||
/lib | ||
/tmp | ||
/src/prolog/tmp | ||
/temp | ||
/projogGeneratedClasses | ||
/target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
dist: trusty | ||
language: java | ||
jdk: | ||
- oraclejdk8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,65 @@ | ||
# prolog-wumpus-world | ||
Wumpus world simulator using Prolog for agent logic and Java for UI. | ||
|
||
## About | ||
|
||
This project contains a simulator and agent for a Wumpus World. Wumpus World is a problem discussed in [Artificial Intelligence: A Modern Approach](https://en.wikipedia.org/wiki/Artificial_Intelligence:_A_Modern_Approach), a university textbook on artificial intelligence. | ||
|
||
The simulator and user interface is written in Java. The logic for controlling the agent is implemented in [Prolog](https://en.wikipedia.org/wiki/Prolog). The open source [Projog](http://projog.org "Prolog interpreter for Java") library is used to integrate Java with Prolog. | ||
|
||
The images used by the application are taken from [Bootstrap Icons](https://icons.getbootstrap.com/), which is licensed under the MIT license. | ||
|
||
## Rules | ||
|
||
|
||
### Components | ||
The world consists of a 4x4 grid of squares. The squares can contain the following items: | ||
|
||
1. Agent. The agent moves around the 4x4 grid. The agent has an arrow that they can fire once. | ||
2. Gold. If the agent enters a square that contains the gold then the agent can take it. | ||
3. A wumpus. If the agent enters the square that contains the wumpus, and the wumpus is alive, then the agent is eaten and cannot continue. If the agent fires the arrow and the square immediately in front of the agent contains the wumpus then the wumpus dies. | ||
4. Pits. If the agent enters a square that contains a pit then the agent falls into it and cannot continue. | ||
5. Walls. If the agent attempts to enter a square that contains a wall then they will not be able to. | ||
|
||
The wumpus, pits and walls are static - they remain in the same square they were allocated to when the world was created. | ||
|
||
### Goal | ||
The aim of the problem is to navigate the agent around the world to: | ||
|
||
1. Find the square that contains the gold. | ||
2. Take the gold. | ||
3. Return to the square that the agent started from. | ||
4. Climb out of the world. | ||
|
||
### Actions | ||
To interact with the world the agent can perform the following actions: | ||
|
||
1. `FORWARD` Move into the square directly in front of where the agent is facing. | ||
2. `RIGHT` Turn right. | ||
3. `LEFT` Turn left. | ||
4. `TAKE` Take the gold. Can only do this if in the same square as the gold. | ||
5. `FIRE` Fire the arrow. Can only do this if have not already fired the arrow. | ||
6. `CLIMB` Climb out of the world. Can only do this if located in the square the agent started from. | ||
|
||
### Percepts | ||
To help the agent reason about the world it receives percepts. The percepts the agent can receive are: | ||
|
||
1. `STENCH` Indicates that the agent is next to a square that contains the wumpus or in the square that contains the wumpus. | ||
2. `BREEZE` Indicates that the agent is next to a square that contains a pit. | ||
3. `GLITTER` Indicates that the agent is in the same square as the gold. | ||
4. `BUMP` Indicates that the agent's previous action (to move forward) caused them to bump into a wall. | ||
5. `BREEZE` Indicates that the agent's previous action (to fire the arrow) killed the wumpus. | ||
|
||
## Reusing the simulator | ||
|
||
If someone would like to implement their own logic to navigate the agent around the world then they can do so by: | ||
|
||
### Implementing the agent logic in Prolog | ||
If implementing the logic using Prolog then they can replace the logic in `src/main/resources/prolog/wumpus.pl`. They will need to provide a `init/0` predicate which resets the agent's game state and a `process/2` predicate. The first argument of `process/2` will be a list of percepts. The second argument will be a variable that should be unified with an atom that indicates which action the agent should perform next. | ||
|
||
### Implementing the agent logic in Java (or another JVM language) | ||
If implementing the logic in a different language than Prolog then they will need to implement their own version of `org.projog.wumpus.GameController`. They will then need to alter `org.projog.wumpus.WumpusWorld` to create an instance of their implementation instead of `PrologGameController`. | ||
|
||
## Resources | ||
|
||
- [Calling Prolog from Java](http://projog.org/calling-prolog-from-java.html) | ||
- [Bootstrap Icons GitHub](https://github.com/twbs/icons) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>org.projog</groupId> | ||
<artifactId>prolog-wumpus-world</artifactId> | ||
<packaging>jar</packaging> | ||
<version>0.1.0-SNAPSHOT</version> | ||
<name>prolog-wumpus-world</name> | ||
<url>http://projog.org</url> | ||
|
||
<properties> | ||
<maven.compiler.source>8</maven.compiler.source> | ||
<maven.compiler.target>8</maven.compiler.target> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.projog</groupId> | ||
<artifactId>projog-core</artifactId> | ||
<version>0.4.0</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.13.1</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.projog.wumpus; | ||
|
||
import java.io.PrintStream; | ||
import java.util.Set; | ||
|
||
import org.projog.wumpus.model.Action; | ||
import org.projog.wumpus.model.Percept; | ||
|
||
/** Logic used to control the agent. */ | ||
public interface GameController { | ||
/** Set output stream so debug from controller can be displayed in UI. */ | ||
void setOut(PrintStream out); | ||
|
||
/** Reset agent state back to the starting state. */ | ||
void reset(); | ||
|
||
/** | ||
* Determines the next action that the agent should perform. | ||
* | ||
* @param percepts the inputs the agent can perceive | ||
* @return the action the agent should perform | ||
*/ | ||
Action process(Set<Percept> percepts); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package org.projog.wumpus; | ||
|
||
import static java.util.stream.Collectors.toList; | ||
|
||
import java.io.PrintStream; | ||
import java.util.Set; | ||
|
||
import org.projog.api.Projog; | ||
import org.projog.api.QueryPlan; | ||
import org.projog.api.QueryStatement; | ||
import org.projog.wumpus.model.Action; | ||
import org.projog.wumpus.model.Percept; | ||
|
||
/** Facade to prolog code that contains the logic used to control the agent. */ | ||
class PrologGameController implements GameController { | ||
private final Projog projog; | ||
private final QueryPlan initQuery; | ||
private final QueryPlan updateQuery; | ||
|
||
PrologGameController() { | ||
projog = new Projog(); | ||
projog.consultResource("prolog/wumpus.pl"); | ||
initQuery = projog.createPlan("init."); | ||
updateQuery = projog.createPlan("process(Percepts,Action)."); | ||
|
||
reset(); | ||
} | ||
|
||
/** Set output stream so debug from controller can be displayed in UI. */ | ||
@Override | ||
public void setOut(PrintStream out) { | ||
projog.setUserOutput(out); | ||
} | ||
|
||
/** Reset agent state back to the starting state. */ | ||
@Override | ||
public synchronized void reset() { | ||
initQuery.executeOnce(); | ||
} | ||
|
||
/** | ||
* Determines the next action that the agent should perform. | ||
* | ||
* @param percepts the inputs the agent can perceive | ||
* @return the action the agent should perform | ||
*/ | ||
@Override | ||
public synchronized Action process(Set<Percept> percepts) { | ||
try { | ||
QueryStatement updateStatement = updateQuery.createStatement(); | ||
// Percept names of enum are upper-case but wumpus.pl expects lower-case versions, so convert here. | ||
updateStatement.setListOfAtomNames("Percepts", percepts.stream().map(p -> p.toString().toLowerCase()).collect(toList())); | ||
String action = updateStatement.findFirstAsAtomName(); | ||
return Action.valueOf(action.toUpperCase()); | ||
} catch (RuntimeException e) { | ||
projog.printProjogStackTrace(e); | ||
throw e; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.projog.wumpus; | ||
|
||
import org.projog.wumpus.model.World; | ||
import org.projog.wumpus.view.UserInterface; | ||
|
||
public class WumpusWorld { | ||
public static void main(String[] args) { | ||
GameController controller = new PrologGameController(); | ||
World state = new World(); | ||
new UserInterface(controller, state); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.projog.wumpus.model; | ||
|
||
/** An action that the agent can perform. */ | ||
public enum Action { | ||
/** Move forward in the direction the agent is facing. */ | ||
FORWARD, | ||
/** Turn to the right. */ | ||
RIGHT, | ||
/** Turn to the left. */ | ||
LEFT, | ||
/** Fire the arrow. */ | ||
FIRE, | ||
/** Take the gold. */ | ||
TAKE, | ||
/** Climb out of the maze. */ | ||
CLIMB | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package org.projog.wumpus.model; | ||
|
||
/** Mutable object representing the current location and state of the agent. */ | ||
class Agent { | ||
private Coordinate location; | ||
private Direction direction = Direction.NORTH; | ||
private AgentState state = AgentState.ACTIVE; | ||
private ArrowState arrow = ArrowState.UNUSED; | ||
private boolean hasGold; | ||
|
||
Agent(Coordinate home) { | ||
this.location = home; | ||
} | ||
|
||
AgentState getState() { | ||
return state; | ||
} | ||
|
||
void setState(AgentState state) { | ||
this.state = state; | ||
} | ||
|
||
Coordinate getLocation() { | ||
return location; | ||
} | ||
|
||
void setLocation(Coordinate location) { | ||
this.location = location; | ||
} | ||
|
||
Direction getDirection() { | ||
return direction; | ||
} | ||
|
||
void setDirection(Direction direction) { | ||
this.direction = direction; | ||
} | ||
|
||
boolean isHasGold() { | ||
return hasGold; | ||
} | ||
|
||
void setHasGold(boolean hasGold) { | ||
this.hasGold = hasGold; | ||
} | ||
|
||
void turnLeft() { | ||
this.direction = direction.left(); | ||
} | ||
|
||
void turnRight() { | ||
this.direction = direction.right(); | ||
} | ||
|
||
void setHasMissed() { | ||
this.arrow = ArrowState.MISSED; | ||
} | ||
|
||
void setHasKilledWumpus() { | ||
this.arrow = ArrowState.HIT; | ||
} | ||
|
||
boolean haveArrow() { | ||
return arrow == ArrowState.UNUSED; | ||
} | ||
|
||
boolean haveNotKilledWumpus() { | ||
return !haveKilledWumpus(); | ||
} | ||
|
||
boolean haveKilledWumpus() { | ||
return arrow == ArrowState.HIT; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.projog.wumpus.model; | ||
|
||
/** State of the agent. */ | ||
public enum AgentState { | ||
/** The agent is alive and navigating the maze. */ | ||
ACTIVE, | ||
/** The agent is dead because they have fallen into a pit or been eaten by the wumpus. */ | ||
DEAD, | ||
/** The agent has climbed out of the maze. */ | ||
ESCAPED | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.projog.wumpus.model; | ||
|
||
/** The state of the arrow that can be used to kill the wumpus. */ | ||
enum ArrowState { | ||
/** The agent is carrying the arrow. */ | ||
UNUSED, | ||
/** The arrow has been fired but it missed the wumpus. */ | ||
MISSED, | ||
/** The arrow has been fired and it hit the wumpus. */ | ||
HIT | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package org.projog.wumpus.model; | ||
|
||
/** A specific location within the maze. */ | ||
public class Coordinate { | ||
private final int x; | ||
private final int y; | ||
|
||
public Coordinate(int x, int y) { | ||
this.x = x; | ||
this.y = y; | ||
} | ||
|
||
Coordinate move(Direction d) { | ||
return new Coordinate(x + d.getX(), y + d.getY()); | ||
} | ||
|
||
public Coordinate minus(Coordinate c) { | ||
return new Coordinate(x - c.x, y - c.y); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return x + "," + y; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (o instanceof Coordinate) { | ||
Coordinate other = (Coordinate) o; | ||
return x == other.x && y == other.y; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return x + (31 * y); | ||
} | ||
} |
Oops, something went wrong.