Mutualdiscovery
Our goal is to foster mutual discovery among learners at all stages of cognitive and meta-cognitive growth. Project members take on shifting roles as teacher, student, facilitator, coach, peer and colleague.

Guests are welcome to view our materials. To subscribe, edit, view raw markup, etc., you'll need to register for an account. Accounts are free (and will always be free) - your involvement helps us directly and indirectly (by demonstrating that our work matters to our funders...) StartingPoints has more info.
Mutualdiscovery » WumpusLabSpr09StudentReports

Wumpus Lab Final Report

Introduction

We are been introduced to wumpus world that is a game. We are to execute the working of this game using python.

Preparation

First of all I am not able to understand what this lab is about. I read through professors lab description but still unable to figure out. Then I went through the Fall 08 lab reports, gave a fair idea about wumpus. Also did a bit of googling, which seems to explain to me much better. I understood the concept much better now, but still not completely wink

The Wumpus world is a grid of squares surrounded by walls, where each square can contain agents and objects. The agent (you) always starts in the lower left corner, a square that will be labeled [1,1]. The agent's task is to find the gold, return to [1,1] and climb out of the cave.

To specify the agent's task, we specify its percepts, actions, and goals. In the Wumpus World, these are as follows:

In the square containing the wumpus and in the directly (not diagonally) adjacent square the agent will perceive a stench

In the squares directly adjacent to a pit, the agent will perceive a breeze.

In the square where the gold is, the agent will perceive a glitter.

When an agent walks into a wall, it will perceive a bump.

When the wumpus is killed, it gives out a woeful scream that can be perceived anywhere in the cave.

There are actions to go right, left, up, and down. In addition, the action Grab can be used to pick up the gold, if it is in the same square as the agent. The action Shoot can be used to fire an arrow in a straight line in the direction the agent is facing. The arrow continues until it either hits and kills the wumpus or hits the wall. The agent only has one arrow, so only the first Shoot action has any effect. Finally the action Climb is used to leave the cave; it is effective only when the agent is in the start square.

The agent dies a miserable death if it enters a square containing a pit or a live wumpus. It is safe (but smelly) to enter a square with a dead wumpus.

The agent's goal is to find the gold and bring it back to the start as quickly as possible, without getting killed. To be precise, 100 points are awarded for climbing out of the cave while carrying the gold, but there is a 1-point penalty for each action taken, and a 1000-point penalty for getting killed.

The locations of the gold and the wumpus are chosen randomly.

Each square other than the start can be a pit, with a probability of 0.2.

In most environments there is a way for the agent to safely retrieve the gold. In some environments, the agent must choose between going home empty-handed or taking a chance that could lead to death or to the gold. And in about 21% of the environments (the ones where the gold is in a pit or surrounded by pits), there is no way the agent can get a positive score. Sometimes life is just unfair.

Lab

An agent can do the following actions (one at a time):

Turn(Right), Turn(Left), Forward, Shoot, Grab, Release, Climb

The agent can go Forward in the direction it is currently facing, or Turn Right, or Turn Left. Going Forward into a wall will generate a Bump percept. The agent has a single arrow that it can Shoot. It will go straight in the direction faced by the agent until it hits (and kills) the wumpus, or hits (and is absorbed by) a wall. The agent can Grab a portable object at the current square or it can Release an object that it is holding. The agent can Climb out of the cave if at the Start square.

The Start square is (1,1) and initially the agent is facing east. The agent dies if it is in the same square as the wumpus. The objective of the game is to kill the wumpus, to pick up the gold, and to climb out with it.

Example:

I was looking at Fall 08 reports and used one of theirs example code to work on.

import random import generatorTest

class Create:

""" This class creates the knowledge base for both the world and the agent"""

def __init__(self, d1 = None, d2 = None):

""" Instantiates the objects of the Create class. d1 and d2 are empty dictionaries used to create a nested dictionary yielding information about each square in the knowledge base"""

if d1 is None: d1 = {} if d2 is None: d2 = {}

self.d1 = d1 self.d2 = d2

def worldCreate(self): """ Creates a blank knowledge base for the agent and the world. listKey1 is a list characteristics used as keys. listData1 contains the initial value for each item and is set to n for no. listKey2 is a list of coordinate tupels of a 4 X 4 grid, but may be changed later if user input is considered. listData2 is a list of dictionaries created when listKey1 maps to listData1. A nested dictionary created via the mapping of listKey2 and listData2 is stored in d2 and is what the return value of the function. worldKB.worldCreate()."""

listKey1 = ('pitt', 'wumpus', 'gold', 'breeze', 'stench', 'glitter', 'visited', 'safeU', 'wf', 'wrv', 'wl', 'wri')

listData1 = ['n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n']

for q, w in map(None, listKey1, listData1): if not self.d1.has_key(q): self.d1[q] = w else: self.d1[q].append(w)

listKey2 = [(1,1), (1,2), (1,3), (1,4), (2,1), (2,2), (2,3), (2,4), (3,1), (3,2), (3,3), (3,4), (4,1), (4,2), (4,3), (4,4)]

listData2 = [self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict(), self.createInnerDict()]

for c, e in map(None, listKey2, listData2): if not self.d2.has_key(c): self.d2[c] = e else: self.d2[c].append(e) self.setWalls()

"print self.d2" return self.d2

def randomCoord(self, (x, y)):

""" x(row) and y(column) are values of a tupel coordinate system. dicPassedIn = self.randomCooord((x, y))."""

x = random.randint(1,4)

y = random.randint(1,4)

return (x, y)

def Wumpus(self, z):

""" This places a Wumpus into an existing knowledge base. z is a tupel containing random coordinates passed in. d2, again should be changed, but holds the dictionary passed containing the knowledge base. After the Wumpus insertion the Stench function is invoked to place stenches in the adjacent squares of the Wumpus. d2 is returned and contaings the knowledge base with the Wumpus inserted. worldKB = world.Wumpus(worldKB)."""

print z

self.d2[z]['wumpus'] = 'y'

"""self.d2 = self.wallCheck(z)"""

self.d2 = self.Stench(z)

self.d2 = self.d2

return self.d2

def Gold(self, z):

""" This places a Gold into an existing knowledge base, checking first for the Wumpus, so the Gold isn't placed in the same square as the Wumpus. To determine where to put the gold the randomCoord function is called and then a check occurs verifying no Wumpus is present. It recurses through the if statement until a coordinate is reached that doesn't contain a Wumpus. z contains tupel coordinates. d2, again should be changed, but holds the dictionary passed containing the knowledge base. Then the Glitter function is invoked to place glitter in the adjacent squares. d2 is returned and contains the updated knowledge base. worldKB = world.Gold(worldKB)."""

x = y = 0

z = self.randomCoord((x, y))

if self.d2[z]['wumpus'] == 'y': print z self.Gold(z) else:

self.d2[z]['gold'] = 'y'

"""self.wallCheck(z)"""

"""self.wallCheck(z)"""

self.Glitter(z)

return self.d2

def setWalls(self): a = [(1,1), (1,2), (1,3), (1,4), (2,1), (2,2), (2,3), (2,4), (3,1), (3,2), (3,3), (3,4), (4,1), (4,2), (4,3), (4,4)]

for item in a: self.wallCheck(item)

def createInnerDict(self):

"""here the function creates unique inner dictionaries for use in creating the nested dictionary. the purpose is that that self.d1 when used in creating the nested dictionary creates a nested dictionary where each coordinate points to the same d1. with this function new dictionaries are created when the function is called allowing for unique data for each square of the map. L1 is a list of keys that relay information about the square. L2 sets everything in the square equal to zero, so that blank knowledge bases are created. the mapping scheme is the same as in worldCreate(). d1 contains the newly created dictionary. a = self.createInnerDict()."""

d1 = {}

L1 = ('pitt', 'wumpus', 'gold', 'breeze', 'stench', 'glitter', 'visited', 'safeU', 'wf', 'wrv', 'wl', 'wri')

L2 = ['n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'n']

for q, w in map(None, L1, L2): if not d1.has_key(q): d1[q] = w else: d1[q].append(w)

return d1

def Pit(self, z):

""" This places a Pit into an existing knowledge base, checking first for the Wumpus and Gold, so the Pits aren't placed in the same square as the Wumpus. To determine where to put the pits the randomCoord function is called and then a check occurs verifying nothing else is present. It recurses through the if statement until a coordinate is reached that is empty. z contains a tupel with coordinates. the while statement makes sure that 3 wumpuses are placed in the world. d2, again should be changed, but holds the dictionary passed containing the knowledge base. Then the Breeze function is invoked to place breezes in the adjacent squares. d2 is returned and contains the updated knowledge base. worldKB = world.Pit(worldKB)."""

a = 3

print "the number of pits this round is a"

while a > 0:

x = y = 0

z = self.randomCoord((x, y))

if self.d2[z]['wumpus'] = 'y' or self.d2[z]['gold'] = 'y':

self.Pit(z)

else:

self.d2[z]['pitt'] = 'y'

"""self.wallCheck(z)"""

self.Breeze(z)

a = a - 1

return self.d2

def PrintFunc? ? (self, d3):

""" this is a simple print statement that is used for verifying items are inserted correctly. dic holds the value of the dictionary passed in and prints the corresponding data."""

for x in d3.keys(): print "KEY",'\t',"VALUE" print x,'\t',d3[x] print " key",'\t',"value" for y in d3[x].keys(): print " ",y,'\t',d3[x][y]

def wallCheck(self, z):

x, y = z

x = x + 1

if x > 4: self.d2[z]['wf'] = 'y' x = x - 2 if x < 1: self.d2[z]['wrv'] = 'y' y = y + 1 if y > 4: self.d2[z]['wl'] = 'y' y = y -2 if y < 1: self.d2[z]['wri'] = 'y'

return self.d2

def Stench(self, z):

""" z is a tupel containing the coordinates. x is a row value and y is a column value. the row value is extracted from the tupel and one is added to the value, retrieving the forward adjacent square. if the value is greater than 4 then we know a wall is present. the row value is then decreased by two to check for the backward adjacent square. if the value is less than 1 then a wall exists here. the same is done for the columns adjacent to the coordinates passed in. d2 contains the value a nested dictionary with the knowledge base and is updated and then returned. self.wallCheck(dicPassedIn, d2)."""

x, y = z

if self.d2[z]['wf'] = 'n': x = x + 1 z = (x, y) self.d2[z]['stench'] = 'y' x = x - 1 z = (x, y) if self.d2[z]['wrv'] = 'n': x = x - 1 z = (x, y) self.d2[z]['stench'] = 'y' x = x + 1 z = (x, y) if self.d2[z]['wl'] = 'n': y = y + 1 z = (x, y) self.d2[z]['stench'] = 'y' y = y - 1 z = (x, y) if self.d2[z]['wri'] = 'n': y = y - 1 z = (x, y) self.d2[z]['stench'] = 'y'

return self.d2

def Breeze(self, z):

"""z contains a tupel with the coordinates. walls are first checked for and if none are present then breezes are placed. the x and y variables are manipulated to check adjacent squares, then after the wall check and appropriate changes, the value is shifted to the opposing square. hence if we check forward by adding x + 1, then once the check and changes are complete, x is subracted by 2 to bring it to the backwards square. so if in (2,2) then (3, 2) is checked first then the subtraction brings up the square for (1, 2)."""

x, y = z

if self.d2[z]['wf'] = 'n': x = x + 1 z = (x, y) self.d2[z]['breeze'] = 'y' x = x - 1 z = (x, y) if self.d2[z]['wrv'] = 'n': x = x - 1 z = (x, y) self.d2[z]['breeze'] = 'y' x = x + 1 z = (x, y) if self.d2[z]['wl'] = 'n': y = y + 1 z = (x, y) self.d2[z]['breeze'] = 'y' y = y - 1 z = (x, y) if self.d2[z]['wri'] = 'n': y = y - 1 z = (x, y) self.d2[z]['breeze'] = 'y' return self.d2

def Glitter(self, z):

"""z contains a tupel with the coordinates. walls are first checked for and if none are present then glitter is placed in the appropriate squares. the x and y variables are manipulated to check adjacent squares, then after the wall check and appropriate changes, the value is shifted to the opposing square. hence if we check forward by adding x + 1, then once the check and changes are complete, x is subracted by 2 to bring it to the backwards square. so if in (2,2) then (3, 2) is checked first then the subtraction brings up the square for (1, 2)."""

x, y = z

if self.d2[z]['wf'] = 'n': x = x + 1 z = (x, y) self.d2[z]['glitter'] = 'y' x = x - 1 z = (x, y) if self.d2[z]['wrv'] = 'n': x = x - 1 z = (x, y) self.d2[z]['glitter'] = 'y' x = x + 1 z = (x, y) if self.d2[z]['wl'] = 'n': y = y + 1 z = (x, y) self.d2[z]['glitter'] = 'y' y = y - 1 z = (x, y) if self.d2[z]['wri'] = 'n': y = y - 1 z = (x, y) self.d2[z]['glitter'] = 'y' return self.d2

testCreate9.py

from Create9 import *

world = Create()

worldKB = world.worldCreate()

agent = Create()

agentKB = agent.worldCreate()

agent.PrintFunc(agentKB)

x = y = 0

y = z = world.randomCoord((x, y))

worldKB = world.Wumpus(z)

print "check in wumpus"

world.PrintFunc(worldKB)

agent.PrintFunc(agentKB)

z = ()

worldKB = world.Gold(z)

z = ()

worldKB = world.Pit(z)

agent.PrintFunc(agentKB)

world.PrintFunc(worldKB)

print 'test worked'

Conclusion

It was a good learning, the working on wumpus game, the implementation of the game in python and finally the execution!

-- PrabhanjanDeshpande - 15 Jun 2009

r1 - 15 Jun 2009 - 23:07:13 - PrabhanjanDeshpande
Guests are welcome to view our materials. To subscribe, edit, view raw markup, etc., you'll need to register for an account. Accounts are free (and will always be free) - your involvement helps us directly and indirectly (by demonstrating that our work matters to our funders...) StartingPoints has more info.
This site is powered by the TWiki collaboration platformCopyright 1999-2010 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Ahatwiki? Send feedback Syndicate this site RSSATOM