public Action choose(WumpusWorld.Hunter hunter, Set<Action> options) { System.out.format("%n%n"); updateInternal(hunter); Room here = worldToPrivate.get(hunter.location()); // check to see if we need to make a new decision if (decision != null && !decision.done(options)) { return decision.step(options); } // kill any adjacent, known wumpuses for (Room wumpus : here.adjacent) { if (wumpusKB.known(wumpus) && wumpusKB.evaluate(wumpus)) { System.out.println("DIE!"); decision = new KillDecision(hunter, wumpus); return decision.step(options); } } // find any known wumpuses to kill for (Room wumpus : privateToWorld.keySet()) { if (wumpusKB.known(wumpus) && wumpusKB.evaluate(wumpus)) { Set<Room> safeRooms = safeRooms(); safeRooms.add(wumpus); List<Room> path = path(here, wumpus, safeRooms); path.remove(wumpus); System.out.println("I've got it!"); decision = new PathDecision(hunter, path); return decision.step(options); } } // find safe rooms to explore { System.out.println(safeRooms()); List<Room> path = path(here, safeRooms()); if (path != null) { System.out.println("Walking!"); decision = new PathDecision(hunter, path); return decision.step(options); } } // find bats to exploit for (Room bat : privateToWorld.keySet()) { if (batKB.known(bat) && batKB.evaluate(bat)) { Set<Room> safeRooms = safeRooms(); safeRooms.add(bat); System.out.println("Find a Bat!"); List<Room> path = path(here, bat, safeRooms); return decision.step(options); } } // otherwise, take your 3 chances... they're only arrows! decision = new KillDecision(hunter, Groups.any(here.adjacent)); return decision.step(options); }
private Set<Room> safeRooms() { Set<Room> safeRooms = new HashSet<Room>(); for (Room room : privateToWorld.keySet()) { if (safe(room)) { safeRooms.add(room); } } return safeRooms; }
public class LogicalWumpusBrain implements Agent<WumpusWorld.Hunter> { // mappings between model and internal structures private final ReversibleMap<Node, Room> worldToPrivate = new ReversibleMap<Node, Room>(); private final ReversibleMap<Room, Node> privateToWorld = worldToPrivate.reverse(); // knowledge bases for logical inference private BoolTable wumpusKB = new BoolTable(); private BoolTable batKB = new BoolTable(); private BoolTable pitKB = new BoolTable(); // current decision Decision decision = null; /* */ public Action choose(WumpusWorld.Hunter hunter, Set<Action> options) { System.out.format("%n%n"); updateInternal(hunter); Room here = worldToPrivate.get(hunter.location()); // check to see if we need to make a new decision if (decision != null && !decision.done(options)) { return decision.step(options); } // kill any adjacent, known wumpuses for (Room wumpus : here.adjacent) { if (wumpusKB.known(wumpus) && wumpusKB.evaluate(wumpus)) { System.out.println("DIE!"); decision = new KillDecision(hunter, wumpus); return decision.step(options); } } // find any known wumpuses to kill for (Room wumpus : privateToWorld.keySet()) { if (wumpusKB.known(wumpus) && wumpusKB.evaluate(wumpus)) { Set<Room> safeRooms = safeRooms(); safeRooms.add(wumpus); List<Room> path = path(here, wumpus, safeRooms); path.remove(wumpus); System.out.println("I've got it!"); decision = new PathDecision(hunter, path); return decision.step(options); } } // find safe rooms to explore { System.out.println(safeRooms()); List<Room> path = path(here, safeRooms()); if (path != null) { System.out.println("Walking!"); decision = new PathDecision(hunter, path); return decision.step(options); } } // find bats to exploit for (Room bat : privateToWorld.keySet()) { if (batKB.known(bat) && batKB.evaluate(bat)) { Set<Room> safeRooms = safeRooms(); safeRooms.add(bat); System.out.println("Find a Bat!"); List<Room> path = path(here, bat, safeRooms); return decision.step(options); } } // otherwise, take your 3 chances... they're only arrows! decision = new KillDecision(hunter, Groups.any(here.adjacent)); return decision.step(options); } // internal decision making mechanism private interface Decision { public boolean done(Set<Action> options); public Action step(Set<Action> options); } private class KillDecision implements Decision { private final WumpusWorld.Hunter hunter; private final Room target; private int count = 0; public KillDecision(WumpusWorld.Hunter hunter, Room target) { this.hunter = hunter; this.target = target; } public boolean done(Set<Action> options) { // TODO verify still valid return count == 2; } public Action step(Set<Action> options) { count++; if (count == 1) { BoolTable newWumpusKB = new BoolTable(); for (Room room : privateToWorld.keySet()) { if (wumpusKB.known(room) && wumpusKB.evaluate(room) == false) { newWumpusKB.assign(room, false); } if (!wumpusKB.known(room)) { System.out.format("Suspicious Room: %s!%n", room); for (Room adj : room.adjacent) { System.out.format(" Resetting: %s!%n", adj); room.visited = false; } } } wumpusKB = newWumpusKB; } if (count == 1) { return hunter.create(privateToWorld.get(target), WumpusWorld.Arrow.class, options); } return null; } } private class PathDecision implements Decision { private final WumpusWorld.Hunter hunter; private final List<Room> path; public PathDecision(WumpusWorld.Hunter hunter, List<Room> path) { this.hunter = hunter; this.path = path; } public boolean done(Set<Action> options) { // TODO verify still valid return path == null || path.isEmpty(); } public Action step(Set<Action> options) { Room here = worldToPrivate.get(hunter.location()); if (path == null || path.isEmpty()) { return null; } Room next = path.remove(0); return hunter.move(privateToWorld.get(next), options); } } // private void updateInternal(WumpusWorld.Hunter hunter) { // initialization (unknown -> start building internal representation) if (!worldToPrivate.containsKey(hunter.location())) { worldToPrivate.put(hunter.location(), new Room()); } // update local information Room here = worldToPrivate.get(hunter.location()); here.visited = true; wumpusKB.assign(here, false); batKB.assign(here, false); pitKB.assign(here, false); // update adjacent rooms for (Edge edge : hunter.location().edges) { if (!worldToPrivate.containsKey(edge.end)) { worldToPrivate.put(edge.end, new Room()); } here.adjacent.add(worldToPrivate.get(edge.end)); worldToPrivate.get(edge.end).adjacent.add(here); } // update knowledge base regarding adjacent rooms boolean rebuild = false; for (Room room : here.adjacent) { if (!hunter.scent() && wumpusKB.conflicts(room, false)) { rebuild = true; } } if (rebuild) { /* BoolTable newWumpusKB = new BoolTable(); for(Room room : privateToWorld.keySet()) { if(wumpusKB.known(room) && wumpusKB.evaluate(room) == false) { newWumpusKB.assign(room, false); } if(!wumpusKB.known(room)) { System.out.format("Suspicious Room: %s!%n", room); for(Room adj : room.adjacent) { System.out.format(" Resetting: %s!%n", adj); room.visited = false; } } } wumpusKB = newWumpusKB; */ } for (Room room : here.adjacent) { if (!hunter.scent()) { wumpusKB.assign(room, false); } if (!hunter.flapping()) { batKB.assign(room, false); } if (!hunter.wind()) { pitKB.assign(room, false); } } Map<Room, Boolean> possible = new HashMap<Room, Boolean>(); for (Room room : here.adjacent) { possible.put(room, true); } if (hunter.scent()) { wumpusKB.assign(possible); } if (hunter.flapping()) { batKB.assign(possible); } if (hunter.wind()) { pitKB.assign(possible); } System.out.format("Wumpus KB : %s%n", wumpusKB); System.out.format("Bat KB : %s%n", batKB); System.out.format("Pit KB : %s%n", pitKB); } // internal graph structure with mappings to the real structure private class Room { public Set<Room> adjacent = new HashSet<Room>(); public boolean visited = false; } private boolean safe(Room room) { if (!wumpusKB.known(room) || wumpusKB.evaluate(room)) { return false; } if (!batKB.known(room) || batKB.evaluate(room)) { return false; } if (!pitKB.known(room) || pitKB.evaluate(room)) { return false; } return true; } private Set<Room> safeRooms() { Set<Room> safeRooms = new HashSet<Room>(); for (Room room : privateToWorld.keySet()) { if (safe(room)) { safeRooms.add(room); } } return safeRooms; } // pathing private List<Room> path(Room start, Room destination, Set<Room> travelable) { Queue<Room> frontier = new LinkedList<Room>(); frontier.add(start); Map<Room, Room> visited = new HashMap<Room, Room>(); visited.put(start, null); while (!frontier.isEmpty()) { Room current = frontier.poll(); System.out.println("\n---\n" + frontier + "\n\n" + travelable + "\n---\n"); if ((destination == null && current.visited == false) || current == destination) { List<Room> path = new ArrayList<Room>(); Room next = current; while (visited.get(next) != null) { path.add(0, next); next = visited.get(next); } System.out.println("Returning: " + path); return path; } for (Room next : current.adjacent) { if (!visited.containsKey(next) && travelable.contains(next)) { frontier.add(next); visited.put(next, current); } } } System.out.println("Returning: null"); return null; } private List<Room> path(Room start, Set<Room> travelable) { return path(start, null, travelable); } }
private void updateInternal(WumpusWorld.Hunter hunter) { // initialization (unknown -> start building internal representation) if (!worldToPrivate.containsKey(hunter.location())) { worldToPrivate.put(hunter.location(), new Room()); } // update local information Room here = worldToPrivate.get(hunter.location()); here.visited = true; wumpusKB.assign(here, false); batKB.assign(here, false); pitKB.assign(here, false); // update adjacent rooms for (Edge edge : hunter.location().edges) { if (!worldToPrivate.containsKey(edge.end)) { worldToPrivate.put(edge.end, new Room()); } here.adjacent.add(worldToPrivate.get(edge.end)); worldToPrivate.get(edge.end).adjacent.add(here); } // update knowledge base regarding adjacent rooms boolean rebuild = false; for (Room room : here.adjacent) { if (!hunter.scent() && wumpusKB.conflicts(room, false)) { rebuild = true; } } if (rebuild) { /* BoolTable newWumpusKB = new BoolTable(); for(Room room : privateToWorld.keySet()) { if(wumpusKB.known(room) && wumpusKB.evaluate(room) == false) { newWumpusKB.assign(room, false); } if(!wumpusKB.known(room)) { System.out.format("Suspicious Room: %s!%n", room); for(Room adj : room.adjacent) { System.out.format(" Resetting: %s!%n", adj); room.visited = false; } } } wumpusKB = newWumpusKB; */ } for (Room room : here.adjacent) { if (!hunter.scent()) { wumpusKB.assign(room, false); } if (!hunter.flapping()) { batKB.assign(room, false); } if (!hunter.wind()) { pitKB.assign(room, false); } } Map<Room, Boolean> possible = new HashMap<Room, Boolean>(); for (Room room : here.adjacent) { possible.put(room, true); } if (hunter.scent()) { wumpusKB.assign(possible); } if (hunter.flapping()) { batKB.assign(possible); } if (hunter.wind()) { pitKB.assign(possible); } System.out.format("Wumpus KB : %s%n", wumpusKB); System.out.format("Bat KB : %s%n", batKB); System.out.format("Pit KB : %s%n", pitKB); }