Community

SCI Programming => SCI Syntax Help => Topic started by: MusicallyInspired on May 05, 2010, 04:11:18 PM

Title: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on May 05, 2010, 04:11:18 PM
I guess this should have been in the Syntax Help forum. My bad.

I know you've given up on the parser, Cloudee, but if you or anyone else has any insight into how this works I'm all ears. I'm trying to handle some said strings to do different things for "get silver key" and "get gold key". But I can't seem to figure out how to use qualifying adjectives. Sentences are split into three parts and so only two "/"'s are allowed. Any ideas? Can you use the semantic operator "<"?

EDIT: Apparently the semantic operator doesn't work either. Here's my code. Any idea how I can script in adjectives? Just putting a space between the words makes the compiler complain that there is no "gold key" or "silver key" word in the vocabulary list. But it's impossible to have 2-word words in the vocabulary list. So I'm stumped.

Here's the code I have that doesn't work:

Code: [Select]
(if(Said('get>'))
(if(Said('/gold<key'))
(if(not send gEgo:has(INV_GOLDKEY))
(if(== gCoffinOpen TRUE)
(if(== gCoffinOccupied FALSE)
(if(send gEgo:has(INV_PILLOW))
(if(<= send gEgo:distanceTo(Coffin) 5)
PrintOK()
(send gEgo:get(INV_GOLDKEY))
++gKeyQuest
(send gGame:changeScore(5))
)(else
PrintNotCloseEnough()
)
)(else
PrintDontSeeIt()
)
)(else
PrintDontSeeIt()
)
)(else
PrintDontSeeIt()
)
)(else
PrintAlreadyTookIt()
)
)
(if(Said('/silver<key'))
(if(not send gEgo:has(INV_SILVERKEY))
(if(== gCoffinOpen TRUE)
(if(== gCoffinOccupied FALSE)
(if(== gDraculaDead TRUE)
(if(<= send gEgo:distanceTo(Coffin) 5)
PrintOK()
(send gEgo:get(INV_SILVERKEY))
(send gGame:changeScore(2))
)(else
PrintNotCloseEnough()
)
)(else
PrintDontSeeIt()
)
)(else
PrintDontSeeIt()
)
)(else
PrintDontSeeIt()
)
)(else
PrintAlreadyTookIt()
)
)
)
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on May 07, 2010, 04:54:05 PM
I still can't figure this out so for the moment I'm going to just make him pick up both keys when you type "get key". If anybody ever has any ideas on figuring this out, please let me know.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Cloudee1 on May 07, 2010, 05:07:24 PM
Yeah, maybe I should rename the board to something besides how to, your not the first to post a question in there, no biggie. Anyway I'll fiddle around with it some this weekend, hopefully, and see if I can't come up with something. It's been a while since I've played kq2 are the keys in the same spot? like on a table together or something...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on May 07, 2010, 05:18:48 PM
Yes. In Dracula's coffin there are (potentially) two keys. The gold key that opens the final door to the tower realm is underneath the pillow. The silver key appears after you kill Dracula with a stake and mallet while he's sleeping in his coffin, after which he disintegrates into a pile of ashes. If you kill Dracula and pick up the pillow there are two keys that you are able to pick up. I've programmed in every other state. I just need to figure out how I can program "get silver key" and "get gold key".
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Cloudee1 on May 07, 2010, 07:50:55 PM
I havenlt tried it yet, but my first inclinations would be to make 3 said phrases. Turn gold and silver into nouns and if said gold, if said silver, and if said key. I think as long as the gold or silver comes before the just key phrase in an if else statement then it would return them? but I don't know it might not like two nouns in the users parse phrase. But that is the direction I would try.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on May 07, 2010, 08:25:05 PM
I'll try it. But it still bugs me. Why is there a Qualifying Adjective flag in Vocabs.000 at all?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Cloudee1 on May 07, 2010, 09:19:35 PM
Yeah so I couldn't get it to work right. I managed to get it to respond correctly to "get key gold" and silver, but that really doesn't help. I'm out of ideas right now but I'll keep mulling it over. It's almost as if only the first and last word are recognised and everything else is ignored. I remember having similar trouble trying to do a top and bottom drawer. I think in the end I tossed out the idea and went with one drawer. ;P    For now, I guess my best suggestion would be to give them whichever key is visible and if they both are then give them both...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on May 07, 2010, 10:01:24 PM
It's still going to be frustrating for players who will instinctively type "get gold key" only to have it fail on them. I had the same problem with trying to type "get basket of goodies" at the mailbox. In the end I had to just do "get basket" and "get goodies". ANNOYING!
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 16, 2010, 11:08:30 PM
Hey, so I've been building a vocab.000 file from scratch and I think it is possible to have 'multiple part' words.  I discovered this with mokalus's utility which I found on the agigames site for converting a words.tok file (agi) to a vocab.000 (sci).  I ran it against an agi game and imported the resulting file into SCI Comp, and sure enough, I have words like 'bolt of lightning'.

I'm still in the process of building a vocab.000 file from scratch, and I'm thinking of perhaps making a utility which allows you to construct an entire vocab file from a spreadsheet.  Alternately, you could always create a 'multi part' word in the vocab file with all the spaces replaced with an arbitrary printable character, then export the resource & edit it with a hex editor, replacing your bogus character references with a 0x20 (space character) and then re-import the file into your game. 

The one thing that I'm not clear on is if the parser can handle these words.  Part of me thinks that it probably chops a sentence up using the spaces, but maybe not necessarily?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Collector on August 16, 2010, 11:34:57 PM
This may seem like a silly response, given that I have not really looked at SCI scripting, but is it possible to declare a global variable that could be assigned a two word value?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 17, 2010, 08:22:30 AM
Yes, you can declare a global variable that can contain any characters (I *think*).  What did you have in mind?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 17, 2010, 10:44:15 AM
Wow! If you manage to get this working it would be INVALUABLE to my KQ2 remake! I have to settle with things like "basket" and "goodies" instead of "basket of goodies" or "girl" instead of "red riding hood".
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 17, 2010, 11:02:30 PM
Okay, I've had more time to do some testing with this.  It appears that despite the fact the vocab will support a multi-part word, the Said() string doesn't (it looks like it parses each word individually).  I'm now hoping that perhaps I can substitute the spaces in the Said() string with an equivalent escape sequence.

I used some code like:
Code: [Select]
(if(Said('bolt of lightning'))
   Print("You can't do that!!!")
 )

and I couldn't get it to match it (it is interesting to note that each word *individually* needs to be in the vocab for the sentence to even parse, otherwise you get the response "I don't know the word 'xxx'").  All I get is the boiler-plate "You've left me responseless".

I'm really starting to dislike the parser...

Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 18, 2010, 01:34:49 AM
I'm starting to think that the parser interface in the SCI template game is unfinished. Other Sierra games have no problem using adjectives. The function is even there in SCI Studio/Companion, but there is no explanation as to how to use it!
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 18, 2010, 11:23:40 PM
Okay, I haven't given up on this yet.  Going back to your original post, I was able to get 'take gold key' and 'take silver key' to work properly.   Here's what I did:

Code: [Select]
(if(Said('take/key<gold'))
      Print("Ahh!  The gold key!")
)

(if(Said('take/key<silver'))
      Print("Ahh!  The silver key!")
)

Typing simply 'take key' resulted in neither response being displayed.  I ran this test against a brand-new template game, didn't have the touch to vocab at all.  Does this help?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 18, 2010, 11:50:51 PM
Thank you! I will test this!
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 19, 2010, 10:44:59 AM
Didn't work for me. Even though I had take/key<gold and take/key<silver after take/key it still decided to ignore both of them and gave me the take/key description.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 19, 2010, 11:19:04 AM
Huh.  Did you run this on a brand new template game? Maybe if 'gold' and 'silver' are not described as *only* qualifying adjectives in your vocab it might not work?  Oh I should have mentioned that I put my 'take/key' logic after the 'take/key<gold' and 'take/key<silver'.  I'll try it again when I get home (I was pretty tired late last night) - maybe if it still isn't working for you I could just upload the game to this thread and you could give it a go.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 19, 2010, 12:23:52 PM
Oh I should have mentioned that I put my 'take/key' logic after the 'take/key<gold' and 'take/key<silver'.

Ah! That did it! :) Thanks for figuring this out. Why this stuff isn't properly documented I'll never know....this should go in the How To tutorial thread.

Unfortunately, I can't figure out how to use this for stuff like "basket of goodies". I can make it work with "take goodies basket" in-game but "take basket of goodies" isn't recognized....I thought the parser was smart enough to figure this stuff out.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 19, 2010, 12:38:48 PM
Right, I was concerned about the 'basket of goodies' as well.  That's why I tackled the keys first.  I'll give it a shot, but I think part of the problem is that 'basket' and 'goodies' are both nouns.  What about some permutation of this (total shot in the dark - untested)
Code: [Select]
(if(Said('take/basket<(of goodies)'))
   Print ("ah, the goodies!")
)
Maybe the grouping using the parenthesis might help in this case?  Or could you make the 'basket' and 'goodies' synonyms so they would collapse to a single noun?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 19, 2010, 12:49:44 PM
Then you'd basically be saying "take basket basket" in-game which would return an error. And, in your example, words in brackets are just a collected series of "ORs". It doesn't acknowledge both of them at the same time. At any rate, I tried it and it fails.

I just wish Brian would have documented the parser a lot more than he did. He basically through a simple tutorial together and expected everyone else to understand it. In fact, he had that attitude for almost everything script related. Not everyone's a natural programmer...maybe that's why SCI Studio never really garnered much attention.

As a side note, it's nice to have active members tackling problems again. Feels like 3 years ago again :).
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 19, 2010, 10:24:53 PM
I've tried a few other things and I'm stumped.  I actually started researching English parts of speech to better understand what we are up against.  Here is what I found:

'Basket of goodies' - the word basket is actually a 'collective noun', whereas 'goodies' is the noun (plural of course), and 'of' is a 'containing preposition'.  Lesson over.

My take on it is that the failure is in the parser building a correct parse tree or the Said() function properly interpreting it (covered my bases there).  I'd bet that the whole mess just doesn't support the collective nouns.  I think it's just not handled in the SCI spec, rather than it being a failure of Brian to properly implement the parser/Said() function within Companion/Studio.

My only idea is to scour other SCI games to see if they have anything with the same/similar sentence structure that is handled properly.  Then at least we would know if this is even possible - maybe contact the author for some insight (if they can be found).

The good news is that you can actually type 'take basket of goodies' into the user input box & it *does* parse successfully.  I guess there might be the outside possibility that we could override the Said() function and handle it ourselves (that might take a bit of doing).
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 20, 2010, 11:12:02 AM
Why is the word 'of' in the vocab then? It also seems silly that (once again) the SCI engine is incapable of something AGI did with ease.

Also, In King's Quest I SCI you can type "get four leaf clover" and it will work. There's no prepositions, but it's there. I'll look for other examples as well.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 21, 2010, 03:37:01 PM
Hey, anybody have a copy of Space Quest 3 handy?  I had an idea to test:  Does the parser work with 'take orat on a stick' or 'eat orat on a stick' (or even more complex sentences, possibly involving an additional noun)?  This seems pretty darn close to our test case.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on August 21, 2010, 11:10:42 PM
you can't "take" it but you do "buy" it from Fester's store. And on a recent playthrough test for ScummVM I did indeed type "buy orat on a stick" and it worked.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Cloudee1 on August 22, 2010, 02:56:12 AM
It might also be useful to check out the times Sierra's parser gave them trouble too. Those few times when "the" had to be used to make the sentence work. Maybe your basket of goodies fits under the same situation. I'm not sure though since I can't think of one of those times.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 22, 2010, 08:47:35 AM
Okay, I've starting coding to fix this problem.  Here is my process and thoughts behind it:

1.  Intercept the user input text event (I've found where this is in the User.sc script)
2.  Go through the string input, looking for our problematic phrase (basket of goodies) - I hope the string kernel functions will play nice...
3.  Replace our phrase with a simpler noun (replace 'basket of goodies' with 'basketofgoodies' or something like it - it will have to be in our vocab file)
4.  Throw a new user input text event with our crafted string (I have an inkling of a clue here, please if anyone has done something similar to this before, chime in).

So instead of making the parser do what we want, I'm thinking of boiling down the inputted text to something the parser can deal with, so we can have a Said() string like this:
Code: [Select]
(if(Said('take/basketofgoodies'))
   Print('Finally!  You've taken the basket of goodies!')
)
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Collector on August 22, 2010, 03:26:29 PM
3.  Replace our phrase with a simpler noun (replace 'basket of goodies' with 'basketofgoodies' or something like it - it will have to be in our vocab file)
This is what I was thinking about when I asked if a variable could be declared from a string of more than one word.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 22, 2010, 03:34:13 PM
Gotcha.  So right, we will need a pair of variables for each phrase we want to intercept & handle specially:  one string to represent the phrase that the user inputs and a second string to what it maps to.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on August 26, 2010, 09:03:17 AM
Progress report:  I've got everything working with the exception of the procedure that actually performs the find and replace.  I've trapped the event, parsed the input, modified the input and re-fired the event.  This will absolutely work, but I need the create the last piece;  It looks as if must play with the string kernel functions - these are maddeningly under-documented.  The only source of documentation is the SCI Studio html docs and anything I can gleam from forums.

I did some searching here & on the Mega-Tokyo forum looking for anyone who had already created a find-and-replace string function, but it was slim pickings.  I'll ask the question anyway:  Has anyone run into or developed on their own string function/procedure?  Does anyone have any related string manipulation code to share?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 21, 2010, 05:15:39 AM
After another 3-4 hours, current score is....

Character arrays/kernel string functions: 3
me: 0

I'm getting irritated...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 21, 2010, 09:04:07 AM
Ah!  6 hours did it.  Brain death complete.

Hey MI, looks like X-Mas came a bit early this year for the both of us!  I think this problem is solved.  Here is the complete solution for the 'basket of goodies' problem:

First, modify the User.sc (you should be able to find the (existing) outer if statement)
Code: [Select]
   (if( (self:getInput(pEvent)) and Parse(@inputStr pEvent))
   = teststr @inputStr
   (if( == STRINGS_EQUAL StrCmp(teststr "take basket of goodies")) 
                  findAndReplace(teststr "basket of goodies" "basketofgoodies")
                  = pEvent (Event:new())
                   Parse(@findAndReplaceStr pEvent)
            )
            (send pEvent:type(evSAID))
            (self:said(pEvent))
   )

Also add these new procedure in the User.sc
Code: [Select]
(procedure public (getChar inputStr index)
   (var indexChar)
   Format(indexChar "%c" StrAt(inputStr index) )
   return(indexChar)
)


(procedure public (findAndReplace sourceStr findStr replaceStr)
  (var i, findStrIndex, returnStrIndex)

  StrCpy(@findAndReplaceStr "")
  = findStrIndex 0
  = returnStrIndex 0
  (for (=i 0) (<i StrLen(sourceStr)) (++i)
    (if (<> StrAt(sourceStr i) StrAt(findStr findStrIndex) )
          StrCat(@findAndReplaceStr getChar(sourceStr i))
          = findStrIndex 0
  ) (else
    (while (== StrAt(sourceStr (+ i findStrIndex)) StrAt(findStr findStrIndex))
       ++findStrIndex
  )

  (if (== findStrIndex (+ StrLen(findStr) 1))
  StrCat(@findAndReplaceStr replaceStr)
  = i (+ i findStrIndex)
  ) (else
             StrCat(@findAndReplaceStr getChar(sourceStr i))
             ++returnStrIndex
             = findStrIndex 0      
  )
  )
  )
)

Then add a new global variable in the Main.sc script
Code: [Select]
  findAndReplaceStr    // This is for holding our modified parsed input

Oh, and don't forget to add 'basketofgoodies' into the vocab - otherwise the User.sc won't compile.  Any time you've got a new 'compound noun' to add, just throw additional find-and-replace logic in the User.sc & also update the vocab.

Now you can do this in your room scripts:
Code: [Select]
        (if(Said('take/basketofgoodies'))
            Print("You got the goodies basket!")
        )     

Improvements can be made here, obviously we don't really want to have to specify every possible Said string - what I should do is fix that 2nd if statement that determines if the user types 'take basket of goodies' & change it to just detect if the words 'basket of goodies' are in it.  Guess I'll do that next...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on November 21, 2010, 10:05:05 AM
Nice! I'll give this a try later today if I have time! Sweet!
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 21, 2010, 04:26:42 PM
Uh-oh.  After executing the findAndReplace function, if navigation of the ego is attempted, the game crashes after a few steps are taken (ego gets totally corrupted on-screen & game locks up).  Hmmmm...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 21, 2010, 04:55:41 PM
All fixed!   I've also added a 'contains string' function so we can use 'basket of goodies' in ANY context.

User.sc - note that the 'getChar' function is removed - it was causing the crashing
Code: [Select]
(if( (self:getInput(pEvent)) and Parse(@inputStr pEvent))
= teststr @inputStr
(if (containsStr(teststr "basket of goodies"))
               findAndReplace(teststr "basket of goodies" "basketofgoodies")
               = pEvent (Event:new())
               Parse(@findAndReplaceStr pEvent)
         )

(send pEvent:type(evSAID))
(self:said(pEvent))
)

...

(procedure public (findAndReplace sourceStr findStr replaceStr)

  (var i, findStrIndex char )

  StrCpy(@findAndReplaceStr "")
  = findStrIndex 0
  (for (=i 0) (<i StrLen(sourceStr)) (++i)
    (if (<> StrAt(sourceStr i) StrAt(findStr findStrIndex) )
      Format(char "%c" StrAt(sourceStr i))
      StrCat(@findAndReplaceStr char)
          = findStrIndex 0
  ) (else
    (while (== StrAt(sourceStr (+ i findStrIndex)) StrAt(findStr findStrIndex))
       ++findStrIndex
  )
  (if (== findStrIndex (+ StrLen(findStr) 1))
  StrCat(@findAndReplaceStr replaceStr)
  = i (+ i findStrIndex)
  ) (else
             Format(char "%c" StrAt(sourceStr i))
             StrCat(@findAndReplaceStr char)
             = findStrIndex 0      
  )
  )
  )
)

(procedure public (containsStr sourceStr findStr)

  (var i, findStrIndex )
 
   = findStrIndex 0
  (for (=i 0) (<i StrLen(sourceStr)) (++i)
    (if (== StrAt(sourceStr i) StrAt(findStr findStrIndex) )
    (while (== StrAt(sourceStr (+ i findStrIndex)) StrAt(findStr findStrIndex))
       ++findStrIndex
  )
  (if (== findStrIndex (+ StrLen(findStr) 1))
  = i (+ i findStrIndex)
  return TRUE
  ) (else
             = findStrIndex 0      
  )
  )
  )
  return FALSE
)


And now, in the room scripts we can do this:
Code: [Select]
(if(Said('take/basketofgoodies'))
       Print("You got the goodies basket. It's pretty heavy...")
)         
(if(Said('eat/basketofgoodies'))
       Print("You eat the whole basket of goodies, and promptly toss your cookies!")
)

The last improvement that I see is to perhaps put the mapping of 'basket of goodies' to 'basketofgoodies' in a text resource, or a global array, or something so that we can define and iterate through all the 'complex nouns', rather than have to repeat the if-blocks over-and-over for each one.

Anyone got any ideas on that one?  Here is the specific section of code that needs 'generalization':
Code: [Select]
(if (containsStr(teststr "basket of goodies"))
               findAndReplace(teststr "basket of goodies" "basketofgoodies")
               = pEvent (Event:new())
               Parse(@findAndReplaceStr pEvent)
         )

(if (containsStr(teststr "pieces of eight"))
               findAndReplace(teststr "pieces of eight" "piecesofeight")
               = pEvent (Event:new())
               Parse(@findAndReplaceStr pEvent)
         )

         ... etc, etc, etc...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Collector on November 22, 2010, 03:13:54 AM
What about recognizing different phrases the user might input, such as "goodies basket", basket of stuff, etc.? Would you repeat the same function for every possibility? If so, would that lead to heap errors? Perhaps it could be modified in a way that you could list all possible strings within the same function.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 22, 2010, 10:38:22 AM
What about recognizing different phrases the user might input, such as "goodies basket", basket of stuff, etc.? Would you repeat the same function for every possibility? If so, would that lead to heap errors? Perhaps it could be modified in a way that you could list all possible strings within the same function.
Yeah, every single combination of words that we would want to 'collapse' (i.e. basket of goodies to basketofgoodies) would have to be set up, which would result in a pretty big (and possibly heap error-prone) User.sc script.

However, your statement made me think of just generalizing this even more.  Maybe we could just look for the keyword 'of' and grab the words on either side of it & collapse it.  Then it would be just one statement.  I'm thinking something like this:

Code: [Select]
(if (containsStr(teststr " of "))  // Make sure you have the leading & trailing space so we truly are matching the 'of' word (avoid matching to 'roof' for example)
               findAndReplace(teststr " of " "of")  // Replace ' of ' with just 'of', which would effectively collapse our word
               = pEvent (Event:new())
               Parse(@findAndReplaceStr pEvent)
         )

Hey, this might work great!  However, now 'of' cannot be used in ANY other context.  The use of the word 'of' in the user input would always result in a collapse.  But that might be ok in this case.  Thoughts??  Oh, and can anyone think of other words we want to do this to?
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Collector on November 22, 2010, 02:31:32 PM
Remember, not all modifiers will use "of". A player could type "take goodies basket." What if you replaced the string with a variable that could be replaced by all possible strings? Does the SCI scripting include an "OrIf" that could allow a list of  all of the possible strings that fit the variable.

Perhaps a better way would be to treat the modifier as another noun, i.e. either "take goodies" or "take basket" would also place the item in the inventory.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 22, 2010, 03:05:35 PM
Remember, not all modifiers will use "of". A player could type "take goodies basket."
Yeah, hadn't considered phrases that don't utilize a modified (or if the user omitted it).

What if you replaced the string with a variable that could be replaced by all possible strings? Does the SCI scripting include an "OrIf" that could allow a list of  all of the possible strings that fit the variable.
I don't think there is an OR operation that works against a set of data (or a string of delimited values).  Also, I'd probably have to change the 'findAndReplace' function call, because the parameters would need to be correlated which we can't do with OR logic.

Now I'm leaning toward putting all possible combinations in a text resource & iterating over it to get the results we want.  Dunno.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on November 22, 2010, 05:16:29 PM
"Get Goodies Basket" is already possible at this point in the same way that "Get Silver Key" is possible. It's the addition of the word "of" that's the most problematic.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 22, 2010, 07:36:37 PM
But, for example, would the phrase "put goodies basket on table" work ok?  I guess if 'goodies' is classified as an adjective it would?  Yeah, I guess it would.  I'm just thinking about the '3 part maximum' that the parser splits the phrase into...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 22, 2010, 10:12:41 PM
Quick update:  The 'of' logic I previously posted with did not work.  I'm not going to bother looking into it.  I'm moving forward with implementing a text resource.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on November 23, 2010, 01:12:14 AM
Man what an annoying fix this is. I wish Brian was here and cared enough to explain it...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 23, 2010, 08:03:59 AM
Man what an annoying fix this is. I wish Brian was here and cared enough to explain it...
I think the problem I was running into most recently ('of') is due to whitespace comparison (but I was doing it before and it was/is working!).  It's not a big deal and now the pain has been felt & I think I've got decent handle on string manipulation.  Hopefully we will have a full solution buttoned up in the next few days...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 24, 2010, 04:34:11 PM
Here is the final result.  I've moved (almost) all the logic out of the User.sc & Main.sc to keep it cleaner.  I did find out the problem I was having earlier was due to the null-termination of the strings which totally fouled up my matching process.

1)  Create a new text resource file & put the full text of the nouns to be handled there
    Examples:  basket of goodies, pieces of eight, pile of bodies

2)  Add new nouns to the vocab.000 file according to what you put in the text resource, without any whitespace
    Examples:  basketofgoodies, piecesofeight, pileofbodies

3)  In the game.sh file, define a new constant COMPLEXNOUN_TEXT and assign it the number corresponding
    to your text resource file above

4)  Add the following code into the User.sc script
Code: [Select]
(use "ComplexNoun") // add this near the top, we'll create this script in step 5

// Then find this code block below & insert the line for the 'handleComplexNoun' procedure call
    (if( (self:getInput(pEvent)) and Parse(@inputStr pEvent))
          handleComplexNoun(@inputStr pEvent)
  (send pEvent:type(evSAID))
  (self:said(pEvent))
    )

 
5)  Create a new script file called ComplexNoun.sc and include the following code
 
Code: [Select]
(include "sci.sh")
(include "game.sh")
/******************************************************************************/
(script 972)             // This may need to be changed if this number is already in use
/******************************************************************************/
(use "main")
(local
   findAndReplaceStr
)

(procedure public (handleComplexNoun inputStr pEvent)
  (var i,complexNounFull[50], complexNounStripped[50])
 
  = i 0
  (do
    GetFarText( COMPLEXNOUN_TEXT i @complexNounFull)
    (if (containsStr(inputStr @complexNounFull))
  findAndReplace(@complexNounFull " " "")                             
  StrCpy(@complexNounStripped @findAndReplaceStr)
  findAndReplace(inputStr @complexNounFull @complexNounStripped)
  Parse(@findAndReplaceStr pEvent)
    )      
     ++i
  ) while ( > StrLen(@complexNounFull) 0) 
)

(procedure public (findAndReplace sourceStr findStr replaceStr)
  (var i, findStrIndex char )

  StrCpy(@findAndReplaceStr "")
  = findStrIndex 0
  (for (=i 0) (<i StrLen(sourceStr)) (++i)
     (if (<> StrAt(sourceStr i) StrAt(findStr findStrIndex) )
         Format(char "%c" StrAt(sourceStr i))
         StrCat(@findAndReplaceStr char)
         = findStrIndex 0
     ) (else
(while (== StrAt(sourceStr (+ i findStrIndex)) StrAt(findStr findStrIndex))
    ++findStrIndex
)
         // >= comparison to handle match at end of string (null terminator)
(if (>= findStrIndex StrLen(findStr))
    StrCat(@findAndReplaceStr replaceStr)
    = i (+ i (- findStrIndex 1))
    = findStrIndex 0
) (else
            Format(char "%c" StrAt(sourceStr i))
            StrCat(@findAndReplaceStr char)
            = findStrIndex 0      
         )
     )
  )
)

(procedure public (containsStr sourceStr findStr)
  (var i, findStrIndex )
 
  = findStrIndex 0
  (for (=i 0) (<i StrLen(sourceStr)) (++i)
      (if (== StrAt(sourceStr i) StrAt(findStr findStrIndex) )
(while (== StrAt(sourceStr (+ i findStrIndex)) StrAt(findStr findStrIndex))
     ++findStrIndex
         )
         (if (== findStrIndex (+ StrLen(findStr) 1))
    return TRUE
) (else
            = findStrIndex 0      
         )
      )
  )
  return FALSE
)

6)  Don't forget to recompile the User.sc script.  You can now use logic like this in your room scripts (or whereever):

Code: [Select]
  (if(Said('move/pileofbodies'))
      Print("Probably better to just leave those poor souls alone."
  )   
  (if(Said('eat/basketofgoodies'))
      Print("You eat the basket of goodies, and promptly toss your cookies!")
  )
  (if(Said('take/piecesofeight'))
      Print("You pick up the pieces of eight")
  )
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Cloudee1 on November 26, 2010, 11:57:04 AM
If it workd, you should definately post that in the how to section
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 26, 2010, 01:13:29 PM
Yeah, it works, but consumes all of the heap (or pretty close).  Found that out this morning.  I don't see how it possible, going from 20K heap size to 0 with that code.  I'm going to beat up on it more today...

EDIT:  Got it fixed.  Now utilizes minimal heap space (less than 1K). Who knows what the problem was.  Will post complete write-up in the how-to section soon
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Cloudee1 on November 26, 2010, 05:38:22 PM
...  Got it fixed.  Now utilizes minimal heap space (less than 1K). Who knows what the problem was.  Will post complete write-up in the how-to section soon

Sweet, that's about what the guage script costs to run.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on November 26, 2010, 05:44:24 PM
Nice! I need to find time to implement this...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Cloudee1 on November 27, 2010, 03:18:05 PM
Very nice tutorial indeed. I see you've got some of your check actor code in there. Now if we can get Brandon, or was it you, that figured out the gold/silver key syntax to stick it in there quick, the two topics will always show up together. 
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 27, 2010, 03:42:09 PM
Very nice tutorial indeed. I see you've got some of your check actor code in there. Now if we can get Brandon, or was it you, that figured out the gold/silver key syntax to stick it in there quick, the two topics will always show up together. 
Whoops!  I didn't mean to have the actor stuff in there.  I'm going to do another how-to for that.  I'll throw in the stuff about the keys too...
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on November 30, 2010, 10:10:40 PM
I just love it.  After I have a solution to this problem, I can't still can't let it go.  It is solvable without any special code...

Code: [Select]
    (if(Said('take/goodies<basket<of'))
       Print("You got the goodies basket!")
    )

Here is how the vocab needs to be defined:
basket - noun
goodies - noun
of - preposition & noun

There are a few tricky things I ran into.  Leave both 'basket' and 'goodies' as nouns.   You can (optionally) make the 'basket' an adjective, but don't make 'goodies' an adjective.  Then you have to make 'of' a noun (you can leave it a preposition).

I figured this out through a brute-force technique.  I was able to get 'take/goodies<basket' working first (just like the other example 'take/key<gold') then started inserting 'of' at all possible positions in the string.  When I exhausted all possible combinations, started changing the word classes.

We desperately need some deep working knowledge of the parser dumped into a how-to.  I mean all possible combination of said string examples possible.  Nobody should ever have to figure this stuff out on their own.  Not like this.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on December 01, 2010, 12:07:58 AM
Dear God, YES. Absolutely ridiculous. If there's one thing about SCI0 game development that needed to be thoroughly documents from day one it's the parser. So cool that you figured it out, though (somewhat)! It's just too bad that "Take goodies basket" can't also work. You'd think that since "of" is a proposition that it would automatically accept "Take basket of goodies" as an alternative to "Take goodies basket". In the same way, it should also accept "Take basket with goodies" since with is also a preposition and it still makes sense. Maybe it's a bug in the implementation. I guess we won't really know until someone reverse engineers or decrypts a game script from an existing Sierra game.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: Collector on December 01, 2010, 01:02:29 AM
Too bad that we couldn't ask one of the old Sierra developers for input. Scott Murphy can be contacted on Facebook, but he would probably be too keen about it.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on December 01, 2010, 07:55:41 AM
I have half a mind to write a utility that allows you to enter an input string, specify what (ideally) you would like the word class of each word to be, and it would try every possible permutation of said strings, shuffling tokens around until it would be able to parse the input string.  And the result would be the syntax of the said string.

This feels like all sorts of laziness to me.  Not from a development standpoint, but an unwillingness on my part to fully understand the parser front-to-back.  However, I'm not sure that I care.  Do I want to be spending my time messing with trying to get the parser to take my input, or do I want to be working on more rewarding game-development endeavors?

Rant complete.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on December 01, 2010, 12:21:30 PM
I have half a mind to write a utility that allows you to enter an input string, specify what (ideally) you would like the word class of each word to be, and it would try every possible permutation of said strings, shuffling tokens around until it would be able to parse the input string.  And the result would be the syntax of the said string.

Oh yeah, it's on.  I've already started coding this.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on December 01, 2010, 10:04:57 PM
It's just too bad that "Take goodies basket" can't also work. You'd think that since "of" is a proposition that it would automatically accept "Take basket of goodies" as an alternative to "Take goodies basket". In the same way, it should also accept "Take basket with goodies" since with is also a preposition and it still makes sense.

The tool I'm developing is already paying off.

All your examples solved with 'normal' (if one can call it that...) parsing.  First, set up the vocab:

  with - preposition
  of - preposition & noun
  basket - noun
  goodies - noun

Code: [Select]
// responds to 'take basket of goodies'
(if(Said('take/goodies<basket<of'))
    Print("take/goodies<basket/of")
)

// responds to 'take goodies basket'
(if(Said('take/basket<goodies'))
    Print("take/basket<goodies")
)

// responds to 'take basket with goodies'
(if(Said('take<with/basket/goodies'))
    Print("take<with/basket/goodies")
)

And my favorite one that I was originally testing with:
Code: [Select]
// responds to 'take large sword from troll'
(if(Said('take<from/sword<large/troll'))
    Print("take<from/sword<large/troll")
)

I don't think I ever would have figured that one out.  I just don't find it intuitive.  It had 24 permutations & worked on the first try.  I can't wait until we have a library of examples documented.

The pattern I see emerging is that prepositions are 'semantically applied' to verbs & adjectives (and nouns) are 'semantically applied' to other nouns.  We'll get this figured out yet.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on December 01, 2010, 11:41:29 PM
Niiiice.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on December 02, 2010, 08:06:12 AM
Now that I reflect upon it, the whole idea of a 'complex noun' falls apart (except perhaps from a Said() string simplification).  It sure appears that a complex noun can be accomplished by linking multiple nouns together with the semantic reference  The part we were missing was just making the individual words all nouns.

I'll update the how-to.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: gumby on December 02, 2010, 10:25:24 PM
Okay, the app is completed.  It accepts a user input string of 5 words or less (I wish it could be more, but 5 words creates 240 different said() strings - 6 words creates 1800 - heap space gone).  It will output a rm001 script, which can be copied into a fresh template game, and run.  When run, the user inputs the same input string they specified with the utility, and the correct said() string syntax is printed to the screen.  Pretty cool.

But I'm still not satisfied.  I just realized after completing this that it is simply the beginning of another application.  After we figure out the parser, the next application will accept any length user input and will output the correct said() string (without the parsers' help) straight out of the command line app.

I've uploaded it to mediafire (it will live here soon...).
http://www.mediafire.com/?9xlq64vquvb8c5v
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: MusicallyInspired on December 02, 2010, 11:01:49 PM
Whoa.
Title: Re: How to use Qualifying Adjectives with the parser?
Post by: troflip on June 10, 2016, 11:42:49 PM
Another very old topic, but:

assuming basket is a noun, and goodies is a noun.:
'get/basket/goodies'   will respond to "get basket of goodies"

and if goodies is also qualifying adjective, then
'get/basket<goodies' will respond to "get goodies basket"

Not sure how to have a single said spec match both of those...