Oh no! Where's the JavaScript?
Your Web browser does not have JavaScript enabled or does not support JavaScript. Please enable JavaScript on your Web browser to properly view this Web site, or upgrade to a Web browser that does support JavaScript.

bitset inventory example 2

Last updated on 9 years ago
SamuraiCrow
In our last lesson, we showed how to do a simple 64 item bitset. Now we're going to make it more flexible and object-oriented. I'll discuss the changes I've made in a later post.

Here are the new codes:

inventorybase.e
OPT MODULE

CLASS item
  itemnum:INT
  pad1:INT
ENDCLASS

DEF nextitem:INT,itemlist[SIZEOF BIGVALUE*8]:ARRAY OF PTR TO item

PROC makeitem() NEW OF item
  self.itemnum:=nextitem
  itemlist[nextitem]:=self
  ++nextitem
  IF nextitem>(SIZEOF BIGVALUE*8) THEN Raise("ARG")
ENDPROC

PROC getmask() OF item RETURNS mask:BIGVALUE IS 1 SHL self.itemnum

PROC getdescription() OF item IS EMPTY

CLASS inventory
  mask:BIGVALUE
ENDCLASS

PROC makeinventory() NEW OF inventory
  self.mask:=0
ENDPROC

PROC additem(myitem:PTR TO item) OF inventory
  self.mask:=self.mask OR myitem.getmask()
ENDPROC

PROC removeitem(youritem:PTR TO item) OF inventory
  self.mask:=self.mask AND NOT youritem.getmask()
ENDPROC

PROC hasitem(myitem:PTR TO item) OF inventory RETURNS ret:BOOL
  ret:= (self.mask AND myitem.getmask()=myitem.getmask())
ENDPROC

PROC hasany(items:PTR TO inventory) OF inventory RETURNS ret:BOOL
  ret:=(self.mask AND items.mask <> 0)
ENDPROC

PROC hasall(items:PTR TO inventory) OF inventory RETURNS ret:BOOL
  ret:=(self.mask AND items.mask = items.mask)
ENDPROC

PROC getitem(source:PTR TO inventory, theitem:PTR TO item) OF inventory RETURNS ret:BOOL
  ret:=FALSE
  IF source.hasitem(theitem)
    source.removeitem(theitem)
    self.additem(theitem)
    ret:=TRUE
  ENDIF
ENDPROC

PROC giveitem(destination:PTR TO inventory, theitem:PTR TO item) OF inventory RETURNS ret:BOOL
  ret:=destination.getitem(self,theitem)
ENDPROC

PROC useall(items:PTR TO inventory) OF inventory RETURNS ret:BOOL
  ret:=FALSE
  IF self.hasall(items)
    self.mask:=self.mask AND NOT items.mask
    ret:=TRUE
  ENDIF
ENDPROC

PROC list() OF inventory
  DEF count:INT,current:PTR TO item
  FOR count:=0 TO nextitem-1
    current:=itemlist[count]
    IF self.hasitem(current)
      current.getdescription()
      Print('\n')
    ENDIF
  ENDFOR
ENDPROC


textitem.e
OPT MODULE

MODULE '*inventorybase'

CLASS textitem OF item
  description:STRING
ENDCLASS

PROC getdescription() OF textitem IS Print('\s',self.description)

PROC maketextitem(describe:STRING) NEW OF textitem
  SUPER self.makeitem()
  self.description:=describe
ENDPROC


inventorybasetest.e

MODULE '*textitem', '*inventorybase'

DEF lamp:PTR TO textitem, torch:PTR TO textitem, bag:PTR TO textitem,
  room:PTR TO inventory, mystuff:PTR TO inventory, lights:PTR TO inventory,
  allstuff:PTR TO inventory

PROC getit(what:PTR TO textitem)
  IF mystuff.getitem(room,what)
    Print('You\'ve picked up ')
    what.getdescription()
  ELSE
    Print('You aleady have ')
    what.getdescription()
  ENDIF
  Print('.\n')
ENDPROC

PROC main()
  DEF in[4]:STRING

  NEW lamp.maketextitem(NEW 'a lamp')
  NEW torch.maketextitem(NEW 'a torch')
  NEW bag.maketextitem(NEW 'a bag')
  NEW room.makeinventory()
  NEW mystuff.makeinventory()
  NEW lights.makeinventory()
  NEW allstuff.makeinventory()
  room.additem(lamp)
  room.additem(torch)
  room.additem(bag)
  lights.additem(lamp)
  lights.additem(torch)
  allstuff.additem(lamp)
  allstuff.additem(torch)
  allstuff.additem(bag)

  REPEAT
    IF mystuff.hasany(lights)
      Print('You are in a room with no doors and no windows.\n')
      Print('You see:\n')
      room.list()
    ELSE
      Print('It\'s dark.  You are likely to be eaten by a grue.\n')
    ENDIF
    Print('\nWhat do you grab?\n')
    PrintFlush()
    ReadStr(stdin,in)
      SELECT in[0]
        CASE "l"; getit(lamp)
        CASE "t"; getit(torch)
        CASE "b"; getit(bag)
        DEFAULT; Print('I don\'t see it here.\n')
      ENDSELECT
  UNTIL mystuff.hasall(allstuff)
  Print('You have everything!  You win!\n')
  PrintFlush()
FINALLY
  PrintException()
ENDPROC
SamuraiCrow
Ok. Now notice the way that the description is no longer embedded in the item class? It is now accessed by the getdescription() method. But wait! The getdescription() method is EMPTY in the item class. This means that item is an abstract class. You can't use it by itself but you can use child classes of it. The textitem.e file has all of the stuff in it that allows us to define an item and still expect it to work.

Let's look at textitem.e for a while. It is a module which allows it to be reused. The textitem class definition is of the item class. This is called inheritance in object-oriented terminology. The getdescription() method is defined here using a print statement that prints the description. This is called "overloading" the method definition. Lastly, the constructor of textitem has to call the makeitem constructor as well as initialize the description string so it uses the SUPER keyword to indicate that the computer is to call the parent class's version of the constructor. This is called "chaining" the constructors.

What inheritance means is that everything that can be done to an item can be done to a textitem since it is a child class. This also means that the item class fields are present in the child class even though we didn't have to copy and paste them. This saves us typing and also saves memory since we can have several kinds of items with different ways to describe themselves. The tradeoff in such an arrangement is that the code will execute more slowly since methods have to look up a pointer in a table to find which function they are supposed to be calling while functions that are not object-oriented methods can be called directly.

There have been changes here and there in the itembasetest.e file from the itemtest.e file from the previous lesson. The main difference is that everything that used to be an item is now a textitem and every NEW call to the constructor makeitem() now calls maketextitem() instead. Since the description string is not expected to have a newline character at the end, I also made adjustments to the usage of every call to the getdescription() method. Did you notice that I had to call both the textitem and inventorybase modules from within the inventorybasetest.e file? This is because I call the inventory class objects from within the inventorybasetest program directly. Otherwise I could have let textitem.e chain call the inventorybase.e module since the item class is needed by the testitem child class.

Feel free to ask any questions.
You can view all discussion threads in this forum.
You can start a new discussion thread in this forum.
You cannot reply in this discussion thread.
You cannot start on a poll in this forum.
You cannot upload attachments in this forum.
You can download attachments in this forum.