File: README.programming

package info (click to toggle)
perlmoo 0.045
  • links: PTS
  • area: main
  • in suites: slink
  • size: 404 kB
  • ctags: 242
  • sloc: perl: 5,211; makefile: 111; sh: 77
file content (140 lines) | stat: -rw-r--r-- 6,100 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
Tutorial: Adding verbs to objects online:
----------------------------------------

Perlmoo can be programmed online, by adding new verbs to objects.

The basics:
----------

Suppose we have a ball object, and we want to make it be able to bounce.
This is a two-step process - first we add the verb to the object, then we
add the actual code to the moo to make the bounce happen.

Adding the verb to the object is just a matter of using the "teach" command:
	teach ball to bounce this none none

(See 'help teach' in the moo for the full syntax to this command.)

"teach ball to bounce this none none" means that for the bounce verb to take
effect, the user must enter the following command:
	"bounce ball"

Now to tell the moo what to do if the ball is bounced:
	verbcode ball bounce "return 'It bounces!'"

(See 'help verbcode' in the moo for the full syntax to this command.)

Now when someone types "bounce ball", they get back "It bounces!". How'd
that work? Well, verbcode is a command that adds code into the moo to be run
when a verb is called. The code, "return 'It bounces!'", is run inside a
subroutine. Anything returned from the subroutine is displayed to the user.

More complex code:
-----------------

Let's get a little bit more complicated, and make the name of the ball be
output when it bounces:
	verbcode ball bounce "$this=shift; return 'The '.$this->name.' bounces!'"

Remember, this code is running inside a subroutine. The subroutine is passed
at least 2 parameters - the first is the object that the subroutine is a
verb of. (The second is a VerbCall, which lets you see what parameters the
user entered.) So, when we do:
	$this=shift;
$this is now set to be the ball object. And so $this->name will call the name
method of the ball, and return the ball's name.

Let's try one more thing - it'd be nice if when the ball bounced, everyone
else in the same room as it saw it bounce. I've written this as a multi-line
construct so you can follow it easily, but you'll have to flatten the code
ont into 1 single line to enter it into the moo:
	verbcode ball bounce "
		$this=shift;
		$verbcall=shift;
		$room=$verbcall->caller->location;
		if ($room) {
			$room->announce($verbcall->caller,
				$verbcall->caller->name.
				  ' bounces the '.$this->name.'.')
		};
		return 'The '.$this->name.' bounces!'
	"

Notice that I'veused the verbcall object here to find out the name of who
bounced the ball (the caller), and where the caller is located.

See the contrib directory for more complex examples of objects.

Inheritance:
-----------

Every object in the moo has a parent, and will by default inherit all verbs
from the parent. That includes verbs that are coded online. For example:
	create ball named egg
	bounce egg

The egg inherited the ball's bounce verb. Of course, eggs are different than
balls - they don't bounce very well. So we could override the egg's bounce
verb to make it do something different:
	verbcode egg bounce "$this=shift; return 'The '.$this->name.' cracks.'"

Now when we bounce the egg, we see it crack. But suppose we want to see it
bounce first - we can pull in the code from our parent object using the
super() method, as follows:
	verbcode egg bounce "
		$this=shift;
		$verbcode=shift;
		return $this->super($verbcode), 'The '.$this->name.' cracks.'
	"

Now when the egg is bounced, the ball's bounce code is run first, and
returns "The egg bounces!". To that is added "The egg cracks.".

Moo infrastructure:
------------------

Here are a few things you should know about the moo infrastructure (very
sketchy right now):

* Every object in the moo is also a perl object.
* Every verb in the moo corresponds to a method in an object named verb_<name>.
* Any method of an object whose name ends in _safe, is a special "in-db"
  method, that is actually contained in the moo database, and can be modified
  online.
* There is a special object called a VerbCall that contains a parsed
  command line. These get passed into verb methods to tell the methods what
  to do. A verbcall basically contains the text the user entered in, parsed
  some, so we can easily find the direct object, indirect object, etc.
* Another special object is a Verb. Each object in the moo may contain
  several Verbs. A Verb is like a subroutine definition - it lets the moo
  match lines of text entered by users to verb methods in objects.
* Finally, we have the Error object. Any function in the entire moo can
  legally return an erro object, so be sure to test for them with
  Error::iserror($ret). Error objects are basically how you raise an exception
  to say something's not right. (Ie, return Error->new("whoops!"))
* Any property of an object that ends in _msg is intended to be a message
  parsed by Text::subst.
* The file basedb.pl is to set up properties for base objects in the moo
  core (as well as add verbs, help texts, etc). If you edit it, you may
  need to change the moo db version number (in Db.pm), and run
  perlmoo-dbconvert to get the changes into db.pl.
* Never use SUPER in perlmoo. This is because SUPER doesn't seem to work
  when called from inside a safe. That's probably because of namespace
  problems. There are currently 2 solutions:
  
  1. For dealing with code that runs outside of a safe, ie, the core perlmoo
     code, the crummy workaround I've came up with is to explicitly call your
     parent package's method, ie, 'Container::location($this)'. Note though that
     this means that if your parent package doesn't implement the method, but
     _it's_ parent does, then, instead of the grandparren't method being called,
     your parent actually inherits AUTOLOAD, which is called instead. So to work
     around this, I have to add stub functions here and there. It's a mess.

  2. For code that runs inside a safe, I actually have a much cleaner
     solution. Just use $thing->super(@params) to call the overridden method.

Programming outside the moo:
---------------------------

I'm always greatful to those who send me patches and new code for the moo.
See the TODO and WISHLIST for ideas of stuff to work on.