Squirrely Scripts

For builders to discuss and ask building questions.
Post Reply
Enig
Sword Grand Master
Sword Grand Master
Posts: 787
Joined: Wed Dec 20, 2006 5:28 pm
Location: The Frozen North (Canada!)

Squirrely Scripts

Post by Enig » Thu Feb 14, 2008 6:35 am

Well, I've been putting it off for a while now, procrastinating and hiding from it, if you will, but there's very little to do for the area I'm building besides the scripted aspect, so I figured I should get started. That said, I think you poor fellows can probably expect to find a number of questions from me in the near future, so thanks in advance for putting up with them :)

Question #1!

Is it possible to trigger a script on container X when object Y is put inside it? If so, what would be the best way to go about doing it?

What I'm trying to do with the script, if it helps, is fashion a riddle. A little blurb on a sign, typical riddle stuff, and then at the end the player has to put the appropriate item into a bowl to prove that they've solved it.

Anyways, thanks again! :)
Dalvyn
Sword Grand Master
Sword Grand Master
Posts: 4708
Joined: Tue Jul 15, 2003 9:26 pm
Location: House of Wonder, Waterdeep

Post by Dalvyn » Thu Feb 14, 2008 11:30 am

There is no program trigger for putting an object in a container.

What you could do instead is code the container as a mob and ask the player to use "give" instead of "put". Then use a >give_prog on the mob.
Image
User avatar
Raona
Staff
Staff
Posts: 4944
Joined: Fri Aug 19, 2005 3:40 pm
Location: Waterdeep - Halls of Justice
Contact:

Post by Raona » Thu Feb 14, 2008 11:33 am

Any chance you could have one of those invisible mobs look inside the container? (I have no idea, the thought just came to mind before I read Dalvyn's reply!)
Dalvyn
Sword Grand Master
Sword Grand Master
Posts: 4708
Joined: Tue Jul 15, 2003 9:26 pm
Location: House of Wonder, Waterdeep

Post by Dalvyn » Thu Feb 14, 2008 6:03 pm

That's not possible currently. Mobs can only look on the ground in the room or in a PC's inventory.
Image
Enig
Sword Grand Master
Sword Grand Master
Posts: 787
Joined: Wed Dec 20, 2006 5:28 pm
Location: The Frozen North (Canada!)

Post by Enig » Fri Feb 15, 2008 6:50 pm

Rather than make a bunch of new threads, I'll keep adding my questions about programs to this one if you guys don't mind!

Anyways! I've been reading over help files and I want to make sure I properly understand the concept of 'bits'. I've never done anything quite like this before and it's all a bit confusing so I hope you guys will bear with this :P

If I use the command mpmset $n 0 1 x, it'll give one bit for the quest and so I'll only be able to make a simple two-stage thing.

Then if I want to do another quest in the same area, I could use something like mpmset $n 1 2 x and that will allocate two bits to the second quest, giving it the possibility of being done in four stages?

And the third quest could be something like mpmset $n 2 x x?


Also! I wrote this up and I'm curious if you guys think it would work.

Code: Select all

give_prog i1111~
if quest (0,2,$n)==0
	sayto $n This is definitely what I'm looking for!  Good job!
	mpmset $n 0 2 1
end if
~
|
if quest (0,2,$n)==1
	sayto $n This is okay, but you've already passed the test.
end if
~
|
Thanks in advance! :)
Dalvyn
Sword Grand Master
Sword Grand Master
Posts: 4708
Joined: Tue Jul 15, 2003 9:26 pm
Location: House of Wonder, Waterdeep

Post by Dalvyn » Fri Feb 15, 2008 10:36 pm

Enig wrote:If I use the command mpmset $n 0 1 x, it'll give one bit for the quest and so I'll only be able to make a simple two-stage thing.
Roughly correct.

Using "mpmset" does not tell the mud that a quest is going to use one bit though, it just sets a value for this bit. What I mean is that there is no protection : if you use for example "mpmset $n 0 4 12" to set a value of 12 for your first quest, using 4 bits, and later you type in "mpmset $n 0 3 5" by mistake (i.e., using only 3 bits this time and not 4), the mud will not consider it a mistake.

So ... intuitively, yes, that means that you are using 1 bit for your first quest, but there is no coded "support" to this. For the mud, it just means that you want to set a value of x in the first bit, nothing more.
Then if I want to do another quest in the same area, I could use something like mpmset $n 1 2 x and that will allocate two bits to the second quest, giving it the possibility of being done in four stages?
Correct again (with the same note as above)

"mpmset $n 1 2 x" means "please put value x in quest bits number 1 and 2" (= in the quest bits starting with number 1, using 2 quest bits).
And the third quest could be something like mpmset $n 2 x x?
Ah. First mistake :)

Your second quest used 2 quest bits : quest bits number 1 and 2 (because 1 2 means 2 quest bits, starting with quest bit number 1). That means that the first free quest bit is ... number 3 !

Your third quest should thus use something like "mpmset $n 3 x y" : use x quest bits to store value y, starting with quest bit number 3.
Also! I wrote this up and I'm curious if you guys think it would work.

Code: Select all

give_prog i1111~
if quest (0,2,$n)==0
	sayto $n This is definitely what I'm looking for!  Good job!
	mpmset $n 0 2 1
end if
~
|
if quest (0,2,$n)==1
	sayto $n This is okay, but you've already passed the test.
end if
~
|
It's "endif" in one word, not "end if".

The first part of the program is correct. The second part is not, because | denotes the end of the program, so it will never reach the second "if". What you can do in this case is something like this:

Code: Select all

if quest (0,2,$n)==0
  sayto $n This is definitely what I'm looking for!  Good job!
  mpmset $n 0 2 1
else
  sayto $n This is okay, but you've already passed the test.
endif
You will most likely need to have the mob junk the object (so its inventory does not get full) in the first part, and simply drop the object (or give it back to $n) in the second part. That will become ...

Code: Select all

if quest (0,2,$n)==0
  sayto $n This is definitely what I'm looking for!  Good job!
  mpmset $n 0 2 1
  mpjunk $o
else
  sayto $n This is okay, but you've already passed the test.
  drop $o
endif
$o" is "the object" in a give_prog. Also, just a note : use 2 spaces instead of a tabulation to indent inner commands (inside "if" structures).

Good questions ! Keep them coming !
Image
Enig
Sword Grand Master
Sword Grand Master
Posts: 787
Joined: Wed Dec 20, 2006 5:28 pm
Location: The Frozen North (Canada!)

Post by Enig » Sat Feb 16, 2008 10:47 pm

First of all, let me say that was quite helpful!

Actually, I was looking at the variables in mpmset incorrectly, because I had thought that for 'mpmset x y z' it used a range of bits from x-y, and that each program had its own allotment of 32 bits. I think I've got a handle on it now, though. For 'mpmset x y z', there are y amount of bits being used starting at x, and they hold the value z.

ie. 'mpmset 4 4 9' uses bits 4, 5, 6, and 7 and assigns them the value 9.

Assuming that's all correct (I'm crossing my fingers! :P), I've written together two programs which I plan to use for a chef mob in my area to introduce a quest line that will guide a character through the MUD's cooking code. I'm hoping that if you fellows have time, you can critique it.

Code: Select all

greet_prog 100~
if quest (0, 4, $n)==0
  sayto $n You there!  Fetch me a carrot, will you?
  mpmset $n 0 4 1
or quest (0, 4, $n)==1
  sayto $n Have you got that carrot yet?
or quest (0, 4, $n)==2
  sayto $n Have you decided to be an apprentice chef?
or quest (0, 4, $n)==11
  if dex > 12
    if con > 12
      mpechoat $n The gnomish chef looks you over critically.
      mpechoaround $n The gnomish chef looks $n over critically.
      sayto $n You look like you've been working out!
      sayto $n You know, I think you might make a good fit for my kitchen.
      sayto $n You could become an apprentice chef of the Blue Fountain Cafe.
      sayto $n Being a chef requires dedication and isn't a job for the faint hearted,
      sayto $n but I think you have potential!  So, what do you say, $n?
      mpmset $n 0 4 2   
    else
      mpechoaround $n The gnomish chef doesn't spare $n a second glance.
      mpechoat $n The gnomish chef doesn't spare you a second glance.
    endif
  else
    mpechoaround $n The gnomish chef doesn't spare $n a second glance.
    mpechoat $n The gnomish chef doesn't spare you a second glance.
  endif
endif

give_prog i1111
if quest (0, 4, $n)==1
  mpjunk $o
  sayto $n This carrot looks good enough, I guess.
  mpechoat $n The gnomish chef looks you over critically.
  mpechoaround $n The gnomish chef looks $n over critically.
  if dex > 12 
    if con > 12
      sayto $n You look like you'd make a good fit for my kitchen.
      sayto $n You could become an apprentice chef of the Blue Fountain Cafe.
      sayto $n Being a chef requires dedication and isn't a job for the faint hearted,
      sayto $n but I think you have potential!  So, what do you say, $n?
      mpmset $n 0 4 2 
    else
      sayto $n You know, we're always looking for apprentice chefs.
      sayto $n We prefer them to be a bit thicker-skinned than you look though.
      sayto $n Excuse me.
      mpmset $n 0 4 11 
    endif
  else
    if con > 12  
      sayto $n You know, we're always looking for apprentice chefs.
      sayto $n We prefer they be a bit faster than you seem to be, though.
      sayto $n Excuse me.
      mpmset $n 0 4 11  
    else
      sayto $n You know, we're always looking for apprentice chefs.
      sayto $n We prefer they be a bit faster and thicker-skinned than
      sayto $n you look to be, though.  Excuse me.
      mpmset $n 0 4 11    
    endif
  endif
else
  sayto $n Thank-you.  I can put this in some stew.
endif
Dalvyn
Sword Grand Master
Sword Grand Master
Posts: 4708
Joined: Tue Jul 15, 2003 9:26 pm
Location: House of Wonder, Waterdeep

Post by Dalvyn » Sun Feb 17, 2008 11:03 am

Enig wrote:ie. 'mpmset 4 4 9' uses bits 4, 5, 6, and 7 and assigns them the value 9.
Correct !
...Programs...
Two reminders: programs begin with a header that starts with > and ends with ~ and they end with ~. After the LAST program on an object/mob/room, you should have a | (even if there is only one program).

The "if" structure can work like this:

Code: Select all

if (condition)
.."what-to-do"
endif
or like this:

Code: Select all

if (condition)
.."what-to-do"
else
.."what-to-do-otherwise"
endif
(where .. are indentation spaces).

What if you have several "cases", that is, "if condition1 is satisfied, dothis; if condition2 is satisifed, dothat"? Then, you have to use 2 "if"s, like this:

Code: Select all

if condition1
..dothis
endif
if condition2
..dothat
endif
What happens though if, in "dothis", condition2 is established? For example, if condition1 checks that a quest bit value is 0, if condition2 checks that a quest bit value is 1, and if "dothis" sets the value to 1, like this:

Code: Select all

if (quest bit value == 0)
..set bit value to 1
endif
if (quest bit value == 1)
..dothat
endif
Let's assume that we start with a bit value of 0. What happens? Condition1 is true, so "dothis" is run. But "dothis" sets the value to 1 ... so, after the first "if" structure (that is, after the first 3 lines of the programs), the bit value is 1 ! That means that Condition2 is true ! And thus, "dothat" is also run. It means that, in one go, both "dothis" and "dothat" are run ... but that's not what I wanted !

There are 2 solutions for this. First solution is ... to imbricate the "if" structures.

Code: Select all

if condition1
..dothis
else
..if condition2
....dothat
..endif
endif
With imbricated "if", the "else" part is only visited if "condition1" is not satisfied. Intuitively, the program above means:
  • If condition1 is satisfied, "dothis".
  • Otherwise ... check condition2, if it is true, then "dothat".
Another way to "solve" the above problem is to switch the two "if" structures. The problem above comes from the fact that "dothis" makes "condition2" true. If we make sure that "condition2" is checked BEFORE and not after, the problem is no more !

Code: Select all

if condition2
..dothat
endif
if condition1
..dothis
endif
With the example above, that means:

Code: Select all

if (quest bit value == 1)
..dothat /does not set the bit value to 0/
endif
if (quest bit value == 0)
..set bit value to 1
endif
Three other remarks.

Stat checking. The correct syntax is dex($n) and con($n) : you need to tell the mud whose dexterity/constitution you want to check. Also, dex($n) and con($n) checks the current dex/con (possibly modified by temporary spells); if you want the "base" value, you can use perm_dex($n) and perm_con($n).

Echoes. As a rule of thumb, always try to colourise your echoes (mpecho, mpechoat, mpechoaround, ...) by adding a colour code at the beginning of the text (check "help feral colours" in game).

Mpechoaround. In echoes, $n is the name of the character, while $N is $n's description. What does that mean? It means that, for people who have been greeted by $n, $N and $n are the same. For people who have NOT been greeted by $n though, $N will be something like "a tall blue-haired elf". In general, it's always better to use the capital letter in mpechoaround and mpecho, so as to not give out $n's name.

Also ... mpechoaround was recently modified, and requires @ variables instead of $ variables. That means, instead of "mpechoaround $n {30}The earth opens and swallows $N!", you need "mpechoaround $n {30}The earth opens and swallows @N!".

With those small remarks, you should be able to fix your programs above. I'll let you have a try at it. Don't worry about mistakes; everybody makes some when they start!

If something is not clear, feel free to ask for more details!
Image
Enig
Sword Grand Master
Sword Grand Master
Posts: 787
Joined: Wed Dec 20, 2006 5:28 pm
Location: The Frozen North (Canada!)

Post by Enig » Mon Feb 18, 2008 1:34 am

Okay! I hadn't really been thinking about the programs running from start to finish, just from start to when I wanted them to finish :P I think I've got *that* sorted out now, but I do still have a few questions.

1) Is it possible to use > or < with an if check? Ie.
if quest (0, 4, $n)>1

2) Does each object and mob have a full set of 32 bits to be used for quests?

Here's my attempt to fix my programs!

Code: Select all

>greet_prog 100~
if quest (0, 4, $n)==1
  sayto $n Have you got that carrot yet?
endif
if quest (0, 4, $n)==0
  sayto $n You there!  Fetch me a carrot, will you?
  mpmset $n 0 4 1
endif
if quest (0, 4, $n)==2
  sayto $n Have you decided to be an apprentice chef?
endif
if quest (0, 4, $n)==11
  if perm_dex($n) > 10
    if perm_con($n) > 10
      mpechoat $n {60}The gnomish chef looks you over critically.
      mpechoaround $n {60}The gnomish chef looks @N over critically.
      sayto $n You look like you've been working out!
      sayto $n You know, I think you might be a good fit for my kitchen.
      sayto $n You could become an apprentice chef of the Blue Fountain Cafe.
      sayto $n Being a chef requires dedication and isn't a job for the faint hearted,
      sayto $n but I think you have potential!  So, what do you say?
      mpmset $n 0 4 2   
    else
      mpechoaround $n {60}The gnomish chef doesn't spare @N a second glance.
      mpechoat $n {60}The gnomish chef doesn't spare you a second glance.
    endif
  else
    mpechoaround $n {60}The gnomish chef doesn't spare @N a second glance.
    mpechoat $n {60}The gnomish chef doesn't spare you a second glance.
  endif
endif
~
>give_prog i1111~
if quest (0, 4, $n)==1
  mpjunk $o
  sayto $n This carrot looks good enough, I guess.
  mpechoat $n {60}The gnomish chef looks you over critically.
  mpechoaround $n {60}The gnomish chef looks @N over critically.
  if perm_dex($n) > 10 
    if perm_con($n) > 10
      sayto $n You look like you'd be a good fit for my kitchen.
      sayto $n You could become an apprentice chef of the Blue Fountain Cafe.
      sayto $n Being a chef requires dedication and isn't a job for the faint hearted,
      sayto $n but I think you have potential!  So, what do you say?
      mpmset $n 0 4 2 
    else
      sayto $n You know, we're always looking for apprentice chefs.
      sayto $n We prefer them to be a bit thicker-skinned than you look though.
      sayto $n Excuse me.
      mpmset $n 0 4 11 
   endif
  else
    if perm_con($n) > 10  
      sayto $n You know, we're always looking for apprentice chefs.
      sayto $n We prefer they be a bit faster than you seem to be, though.
      sayto $n Excuse me.
      mpmset $n 0 4 11  
    else
      sayto $n You know, we're always looking for apprentice chefs.
      sayto $n We prefer they be a bit faster and thicker-skinned than
      sayto $n you look to be, though.  Excuse me.
      mpmset $n 0 4 11    
    endif
  endif
else
  sayto $n Thank-you.  I can put this in some stew.
  mpjunk $o
endif
~
|
Thanks again for your time :)
Dalvyn
Sword Grand Master
Sword Grand Master
Posts: 4708
Joined: Tue Jul 15, 2003 9:26 pm
Location: House of Wonder, Waterdeep

Post by Dalvyn » Mon Feb 18, 2008 6:24 am

Enig wrote:1) Is it possible to use > or < with an if check? Ie.
if quest (0, 4, $n)>1
Yup, that's possible to use >, >=, <, <=, and != (for "is not").
2) Does each object and mob have a full set of 32 bits to be used for quests?
Each character has a set of 32 bits (numbered from 0 up to 31) for each area (or, more precisely, for each 100-vnum block).

That means that an area with 100 vnums has 32 bits for quests. An area with 50 vnums has 16 bits for quests (either numbered from 0 up to 15, or from 16 up to 31, depending if it uses vnums ending in 00 up to 49 - that is, the first half of a 100 vnum block -, or vnums ending in 50 up to 99 - that is, the second half of a 100 vnum block).

Areas with more than 100 vnums have more than 32 bits for quests.

[More on that later]

Mobiles have 32 bits of their own, not associated to any area, and those vnums are shared by ALL mobs with the same vnums. For example, if you set "mpmset m123 quest 0 1 1" on a mob #123 (let's say, an orc soldier), then ALL orc soldiers of vnum 123 will have their quest bit 0 1 set to 1. Mobs only have ONE set of 32 bits, not one set per area.
Here's my attempt to fix my programs!
Perfect! The program as it is will work fine!

Here's just an option to improve some parts: The condition of an "if" can be a complex condition like "Condition1 AND Condition2", or "Condition1 OR Condition2"; this can sometimes shorten the program.

For example, you could safely replace

Code: Select all

if quest (0, 4, $n)==11
  if perm_dex($n) > 10
    if perm_con($n) > 10
      mpechoat $n {60}The gnomish chef looks you over critically.
      mpechoaround $n {60}The gnomish chef looks @N over critically.
      sayto $n You look like you've been working out!
      sayto $n You know, I think you might be a good fit for my kitchen.
      sayto $n You could become an apprentice chef of the Blue Fountain Cafe.
      sayto $n Being a chef requires dedication and isn't a job for the faint hearted,
      sayto $n but I think you have potential!  So, what do you say?
      mpmset $n 0 4 2   
    else
      mpechoaround $n {60}The gnomish chef doesn't spare @N a second glance.
      mpechoat $n {60}The gnomish chef doesn't spare you a second glance.
    endif
  else
    mpechoaround $n {60}The gnomish chef doesn't spare @N a second glance.
    mpechoat $n {60}The gnomish chef doesn't spare you a second glance.
  endif
endif
with

Code: Select all

if quest (0, 4, $n)==11
  if perm_dex($n) > 10
  and perm_con($n) > 10
    mpechoat $n {60}The gnomish chef looks you over critically.
    mpechoaround $n {60}The gnomish chef looks @N over critically.
    sayto $n You look like you've been working out!
    sayto $n You know, I think you might be a good fit for my kitchen.
    sayto $n You could become an apprentice chef of the Blue Fountain Cafe.
    sayto $n Being a chef requires dedication and isn't a job for the faint hearted,
    sayto $n but I think you have potential!  So, what do you say?
    mpmset $n 0 4 2   
  else
    mpechoaround $n {60}The gnomish chef doesn't spare @N a second glance.
    mpechoat $n {60}The gnomish chef doesn't spare you a second glance.
  endif
endif
Thanks again for your time :)
You are welcome! It's always a great pleasure to see that, after a few words of explanations, new builders can create working programs!

Just an additional word about quest bits and how they depend on the area.

As I wrote above, each character has a set of 32 bits for each area in the game (or each 100-vnum block). When you want to state which set of 32 bits you are modifying/checking, you need to use questr instead of quest. Here's how they work:

"Quest" versions:

Code: Select all

mpmset $n quest 0 1 1
if quest(0,1,$n) == 1
"Questr" versions:

Code: Select all

mpmset $n questr 8000 0 1 1
if questr(8000,0,1,$n) == 1
(where I used 8000 as an example; if you do not have your vnums set yet, you can use QQ00, so we can perform a file-wide search and replace on QQ to turn them into your effective vnums once they have been chosen)

Code: Select all

mpmset $n questr QQ00 0 1 1
if questr(QQ00,0,1,$n) == 1
When to use quest or questr?

Well, obviously, when you need to check or modify quest bits "belonging to"/associated with another area, you need to use questr. But there are other cases when it's better to use questr instead of quest.

How does the mud determines what set of 32 bits to use? When a program uses quest (not questr), how does the mud determine what area to use? In those cases, it uses the area where the player is. It could have used the area where the object/room/mobile who is running the program is defined, but that's not what it does.

What does it mean? It means that, if a wandering mobile uses "quest" instead of "questr", its program will behave differently (will use different areas) as the wandering mobile moves from one area to another area. Thus, for wandering mobiles, it's always safer to use "questr" instead of "quest".

Now, from time to time, imms also move mobiles out of their starting area, or mobs sometimes move on their own (to report a crime or chase an attacker for example). Thus ... as a rule of thumb, it's always safer to use "questr" for mobile programs.

Objects ... well, objects that can be carried and moved around certainly need to use "questr" since they can be brought to other areas. Objects that cannot be picked up (e.g., fountains) can use "quest" ... though, once again, imms might load them up in another area. So, there too, it's safer to use "questr".

The only place where it's 100% safe to use "quest" is in room programs (programs attached to a room), because we know for sure that a room is not going to be "pulled out" of its area.

Hope that helps. Good to see you making good progress!
Image
Post Reply