Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 73 additions & 45 deletions logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
isnumber, issequence, Expr, expr, subexpressions
)
import agents
from search import astar_search, PlanRoute

import itertools
import random
Expand Down Expand Up @@ -763,7 +764,7 @@ def location(x, y, time = None):
def implies(lhs, rhs):
return Expr('==>', lhs, rhs)

def implies_and_implies(lhs, rhs):
def equiv(lhs, rhs):
return Expr('<=>', lhs, rhs)

# Helper Function
Expand Down Expand Up @@ -811,8 +812,8 @@ def __init__(self,dimrow):
pits_in.append(pit(x, y - 1))
wumpus_in.append(wumpus(x, y - 1))

self.tell(implies_and_implies(breeze(x, y), new_disjunction(pits_in)))
self.tell(implies_and_implies(stench(x, y), new_disjunction(wumpus_in)))
self.tell(equiv(breeze(x, y), new_disjunction(pits_in)))
self.tell(equiv(stench(x, y), new_disjunction(wumpus_in)))


## Rule that describes existence of at least one Wumpus
Expand All @@ -837,8 +838,8 @@ def __init__(self,dimrow):
self.tell(location(1, 1, 0))
for i in range(1, dimrow+1):
for j in range(1, dimrow + 1):
self.tell(implies(location(i, j, 0), implies_and_implies(percept_breeze(0), breeze(i, j))))
self.tell(implies(location(i, j, 0), implies_and_implies(percept_stench(0), stench(i, j))))
self.tell(implies(location(i, j, 0), equiv(percept_breeze(0), breeze(i, j))))
self.tell(implies(location(i, j, 0), equiv(percept_stench(0), stench(i, j))))
if i != 1 or j != 1:
self.tell(~location(i, j, 0))

Expand Down Expand Up @@ -903,13 +904,13 @@ def add_temporal_sentences(self, time):
## current location rules
for i in range(1, self.dimrow+1):
for j in range(1, self.dimrow+1):
self.tell(implies(location(i, j, time), implies_and_implies(percept_breeze(time), breeze(i, j))))
self.tell(implies(location(i, j, time), implies_and_implies(percept_stench(time), stench(i, j))))
self.tell(implies(location(i, j, time), equiv(percept_breeze(time), breeze(i, j))))
self.tell(implies(location(i, j, time), equiv(percept_stench(time), stench(i, j))))

s = list()

s.append(
implies_and_implies(
equiv(
location(i, j, time), location(i, j, time) & ~move_forward(time) | percept_bump(time)))

if i != 1:
Expand All @@ -929,72 +930,79 @@ def add_temporal_sentences(self, time):

## add sentence about safety of location i,j
self.tell(
implies_and_implies(ok_to_move(i, j, time), ~pit(i, j) & ~wumpus(i, j) & wumpus_alive(time))
equiv(ok_to_move(i, j, time), ~pit(i, j) & ~wumpus(i, j) & wumpus_alive(time))
)

## Rules about current orientation

a = facing_north(t) & turn_right(t)
b = facing_south(t) & turn_left(t)
c = facing_east(t) & ~turn_left(t) & ~turn_right(t)
s = implies_and_implies(facing_east(time), a | b | c)
s = equiv(facing_east(time), a | b | c)
self.tell(s)

a = facing_north(t) & turn_left(t)
b = facing_south(t) & turn_right(t)
c = facing_west(t) & ~turn_left(t) & ~turn_right(t)
s = implies_and_implies(facing_west(time), a | b | c)
s = equiv(facing_west(time), a | b | c)
self.tell(s)

a = facing_east(t) & turn_left(t)
b = facing_west(t) & turn_right(t)
c = facing_north(t) & ~turn_left(t) & ~turn_right(t)
s = implies_and_implies(facing_north(time), a | b | c)
s = equiv(facing_north(time), a | b | c)
self.tell(s)

a = facing_west(t) & turn_left(t)
b = facing_east(t) & turn_right(t)
c = facing_south(t) & ~turn_left(t) & ~turn_right(t)
s = implies_and_implies(facing_south(time), a | b | c)
s = equiv(facing_south(time), a | b | c)
self.tell(s)

## Rules about last action
self.tell(implies_and_implies(move_forward(t), ~turn_right(t) & ~turn_left(t)))
self.tell(equiv(move_forward(t), ~turn_right(t) & ~turn_left(t)))

##Rule about the arrow
self.tell(implies_and_implies(have_arrow(time), have_arrow(t) & ~shoot(t)))
self.tell(equiv(have_arrow(time), have_arrow(t) & ~shoot(t)))

##Rule about Wumpus (dead or alive)
self.tell(implies_and_implies(wumpus_alive(time), wumpus_alive(t) & ~percept_scream(time)))
self.tell(equiv(wumpus_alive(time), wumpus_alive(t) & ~percept_scream(time)))


def ask_if_true(self, query):
return pl_resolution(self, query)


# ______________________________________________________________________________


class WumpusPosition():
def __init__(self, X, Y, orientation):
self.X = X
self.Y = Y
def __init__(self, x, y, orientation):
self.X = x
self.Y = y
self.orientation = orientation


def get_location(self):
return self.X, self.Y

def set_location(self, x, y):
self.X = x
self.Y = y

def get_orientation(self):
return self.orientation

def equals(self, wumpus_position):
if wumpus_position.get_location() == self.get_location() and \
wumpus_position.get_orientation()==self.get_orientation():
def set_orientation(self, orientation):
self.orientation = orientation

def __eq__(self, other):
if other.get_location() == self.get_location() and \
other.get_orientation()==self.get_orientation():
return True
else:
return False

# ______________________________________________________________________________


Expand Down Expand Up @@ -1041,9 +1049,8 @@ def execute(self, percept):
goals = list()
goals.append([1, 1])
self.plan.append('Grab')
actions = plan_route(self.current_position,goals,safe_points)
for action in actions:
self.plan.append(action)
actions = self.plan_route(self.current_position,goals,safe_points)
self.plan.extend(actions)
self.plan.append('Climb')

if len(self.plan) == 0:
Expand All @@ -1059,9 +1066,8 @@ def execute(self, percept):
if u not in unvisited_and_safe and s == u:
unvisited_and_safe.append(u)

temp = plan_route(self.current_position,unvisited_and_safe,safe_points)
for t in temp:
self.plan.append(t)
temp = self.plan_route(self.current_position,unvisited_and_safe,safe_points)
self.plan.extend(temp)

if len(self.plan) == 0 and self.kb.ask_if_true(have_arrow(self.t)):
possible_wumpus = list()
Expand All @@ -1070,26 +1076,23 @@ def execute(self, percept):
if not self.kb.ask_if_true(wumpus(i, j)):
possible_wumpus.append([i, j])

temp = plan_shot(self.current_position, possible_wumpus, safe_points)
for t in temp:
self.plan.append(t)
temp = self.plan_shot(self.current_position, possible_wumpus, safe_points)
self.plan.extend(temp)

if len(self.plan) == 0:
not_unsafe = list()
for i in range(1, self.dimrow+1):
for j in range(1, self.dimrow+1):
if not self.kb.ask_if_true(ok_to_move(i, j, self.t)):
not_unsafe.append([i, j])
temp = plan_route(self.current_position, not_unsafe, safe_points)
for t in temp:
self.plan.append(t)
temp = self.plan_route(self.current_position, not_unsafe, safe_points)
self.plan.extend(temp)

if len(self.plan) == 0:
start = list()
start.append([1, 1])
temp = plan_route(self.current_position, start, safe_points)
for t in temp:
self.plan.append(t)
temp = self.plan_route(self.current_position, start, safe_points)
self.plan.extend(temp)
self.plan.append('Climb')

action = self.plan[0]
Expand All @@ -1100,12 +1103,37 @@ def execute(self, percept):
return action


def plan_route(current, goals, allowed):
raise NotImplementedError
def plan_route(self, current, goals, allowed):
problem = PlanRoute(current, goals, allowed, self.dimrow)
return astar_search(problem).solution()



def plan_shot(current, goals, allowed):
raise NotImplementedError
def plan_shot(self, current, goals, allowed):
shooting_positions = set()

for loc in goals:
x = loc[0]
y = loc[1]
for i in range(1, self.dimrow+1):
if i < x:
shooting_positions.add(WumpusPosition(i, y, 'EAST'))
if i > x:
shooting_positions.add(WumpusPosition(i, y, 'WEST'))
if i < y:
shooting_positions.add(WumpusPosition(x, i, 'NORTH'))
if i > y:
shooting_positions.add(WumpusPosition(x, i, 'SOUTH'))

# Can't have a shooting position from any of the rooms the Wumpus could reside
orientations = ['EAST', 'WEST', 'NORTH', 'SOUTH']
for loc in goals:
for orientation in orientations:
shooting_positions.remove(WumpusPosition(loc[0], loc[1], orientation))

actions = list()
actions.extend(self.plan_route(current, shooting_positions, allowed))
actions.append('Shoot')
return actions


# ______________________________________________________________________________
Expand Down
104 changes: 104 additions & 0 deletions search.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,110 @@ def h(self, node):

return sum(s != g for (s, g) in zip(node.state, self.goal))

# ______________________________________________________________________________


class PlanRoute(Problem):
""" The problem of moving the Hybrid Wumpus Agent from one place to other """

def __init__(self, initial, goal, allowed, dimrow):
""" Define goal state and initialize a problem """

self.dimrow = dimrow
self.goal = goal
self.allowed = allowed
Problem.__init__(self, initial, goal)

def actions(self, state):
""" Return the actions that can be executed in the given state.
The result would be a list, since there are only three possible actions
in any given state of the environment """

possible_actions = ['Forward', 'TurnLeft', 'TurnRight']
x, y = state.get_location()
orientation = state.get_orientation()

# Prevent Bumps
if x == 1 and orientation == 'LEFT':
if 'Forward' in possible_actions:
possible_actions.remove('Forward')
if y == 1 and orientation == 'DOWN':
if 'Forward' in possible_actions:
possible_actions.remove('Forward')
if x == self.dimrow and orientation == 'RIGHT':
if 'Forward' in possible_actions:
possible_actions.remove('Forward')
if y == self.dimrow and orientation == 'UP':
if 'Forward' in possible_actions:
possible_actions.remove('Forward')

return possible_actions

def result(self, state, action):
""" Given state and action, return a new state that is the result of the action.
Action is assumed to be a valid action in the state """
x, y = state.get_location()
proposed_loc = list()

# Move Forward
if action == 'Forward':
if state.get_orientation() == 'UP':
proposed_loc = [x, y + 1]
elif state.get_orientation() == 'DOWN':
proposed_loc = [x, y - 1]
elif state.get_orientation() == 'LEFT':
proposed_loc = [x - 1, y]
elif state.get_orientation() == 'RIGHT':
proposed_loc = [x + 1, y]
else:
raise Exception('InvalidOrientation')

# Rotate counter-clockwise
elif action == 'TurnLeft':
if state.get_orientation() == 'UP':
state.set_orientation('LEFT')
elif state.get_orientation() == 'DOWN':
state.set_orientation('RIGHT')
elif state.get_orientation() == 'LEFT':
state.set_orientation('DOWN')
elif state.get_orientation() == 'RIGHT':
state.set_orientation('UP')
else:
raise Exception('InvalidOrientation')

# Rotate clockwise
elif action == 'TurnRight':
if state.get_orientation() == 'UP':
state.set_orientation('RIGHT')
elif state.get_orientation() == 'DOWN':
state.set_orientation('LEFT')
elif state.get_orientation() == 'LEFT':
state.set_orientation('UP')
elif state.get_orientation() == 'RIGHT':
state.set_orientation('DOWN')
else:
raise Exception('InvalidOrientation')

if proposed_loc in self.allowed:
state.set_location(proposed_loc[0], [proposed_loc[1]])

return state

def goal_test(self, state):
""" Given a state, return True if state is a goal state or False, otherwise """

return state.get_location() == tuple(self.goal)

def h(self, node):
""" Return the heuristic value for a given state."""

# Manhattan Heuristic Function
x1, y1 = node.state.get_location()
x2, y2 = self.goal

return abs(x2 - x1) + abs(y2 - y1)


# ______________________________________________________________________________
# Other search algorithms

Expand Down