Author Topic: SCI0: Varibles and changestates  (Read 585 times)

0 Members and 1 Guest are viewing this topic.

Offline robbo007

SCI0: Varibles and changestates
« on: November 21, 2024, 04:29:16 PM »
Hi guys,
I'm trying to create a script that mimics the LSL1 pimp door script in Lefty's Bar. I'm trying to understand what is the best approach.

Player types "knock on door", pimp replies "What's the password", player types password and its checked, if correct then opens door.

Would you use a variable to hold the text the player types in "ken sent me"? How do you then check this is the correct text entered against the variable?

When dealing with a script inside the RoomScript do you generally try and keep all the said statements inside that script? Or do you put the said statements in the RoomScript then declare the changeState you want to goto with that said statement ? I'm getting lost how to organise all my said statements and scripts in each room. What's the best approach?

Thanks,



Offline Kawa

Re: SCI0: Varibles and changestates
« Reply #1 on: November 21, 2024, 04:48:25 PM »
What I'd do is, whatever Script is responsible for handling the pimp at the door, you have an enum of states just to make things clear. In that script, have your handleEvent respond to "ken sent me" by checking if state is "waiting for the password". If so, cue the Script. If not, print a joke and don't cue anything.

Or, if you want the pimp to time out, set seconds in the "wait for password" state and have the next one(s) react to a failure to give the password, where the script Just Stops. Have another (enum-named) state after that which handleEvent can respond to by first clearing the Script's seconds and then changeState to the "password accepted" state.

Does that make sense?

As for getting lost organizing your scripts: that's why you define enums for your states. Sierra sure did, and it's an example that helped me a great deal so far.

Offline robbo007

Re: SCI0: Varibles and changestates
« Reply #2 on: November 24, 2024, 01:09:37 PM »
Hi,
Thanks for explaining a little more. I went back through the the LSL3 code to check how they used the enums. It seems a lot clearer when using them. Nice pointer. :)

So I was trying to use the StrCmp command to compare the GetInput text saved in the string @passwd matches but it does not seem to compare it. You can type anything in when prompted and it then moves to the GotPasswd changeState. Is it my syntax that is wrong? Or is there a simpler way to do it?

Code: [Select]
(enum ;** Pimp state values
OpenHole
AskForPasswd
GotPasswd
)
(local
    messageCount
peephole_open = 0
peephole_closed = 1
password = ken sent me
passwd
)

Code: [Select]
(method (handleEvent pEvent)
(super handleEvent: pEvent)
; handle Said's, etc...
(if (Said 'knock/door')
(if (& (gEgo onControl:) ctlBLUE)
(Print 102 0) ;You rap loudly on the naugahyde door. You wonder how many naugas had to give their all just to decorate this sleazehole.
(aDoorScript changeState: 0)

else
(PrintNotCloseEnough)
)
)
)

Code: [Select]
(instance aDoorScript of Script ;Peep hole script
(method (handleEvent event)
(if (or (!= (event type:) evSAID) (event claimed:))
(return)
)
)

(method (changeState newState)
(ShowState self newState 1 2)
(switch (= state newState)
      (OpenHole ; Peep hole door opens
      ;(ProgramControl)
  (= peephole_open 0)
  (aPeepHole cycleSpeed: 1 setLoop: 8 setCycle: End self)
)
(AskForPasswd ;The pimp speaks to ego
(= seconds 5)
(Print 102 1) ;"Yeah. Whatsda passwoid?"
(GetInput @passwd 45 {Whatsda passwoid?})
(if (== STRINGS_EQUAL (StrCmp @passwd "Ken send me"))
)
(self changeState: GotPasswd)
;;; else
;;; (Print {Scram Butthead})
;;; (aPeepHole setCel: 0 stopUpd:)
)
(GotPasswd ;Got password speak friend and enter.
(Print {Testing if reaching new state})
(aPeepHole setCel: 0 stopUpd:)

)
)
)
)

Offline Kawa

Re: SCI0: Varibles and changestates
« Reply #3 on: November 24, 2024, 01:59:49 PM »
See, if I was copying the LSL1 password, I'd not use GetInput but Said, like I, well, said. If only so you can time out or walk away. But also so it becomes case insensitive.

(But not spelling insensitive: it's "Ken sent me".)

Offline lskovlun

Re: SCI0: Varibles and changestates
« Reply #4 on: November 25, 2024, 12:46:35 AM »
There are several suspicious bits in the code you posted.
For example:
Code: [Select]
)
(local
    messageCount
peephole_open = 0
peephole_closed = 1
password = ken sent me
passwd
)
The "password =" line shouldn't even compile, and the passwd variable doesn't reserve enough space for a 45 character input. Then there is the STRINGS_EQUAL constant which I can't find in my Companion sources. If we're being sensible, it's defined to zero, but my sci.sh has only this:
Code: [Select]
(define STRING_LESSTHAN -1)
(define STRING_GREATER 1)
I'm not sure I agree with Kawa about using Said. I'd like a GetInput text box, as you have written.

Offline Kawa

Re: SCI0: Varibles and changestates
« Reply #5 on: November 25, 2024, 03:01:27 AM »
SCI StrCmp wraps around C strcmp when given two strings, or strncmp when given two strings and a max length. Therefore, equality is when it returns 0. So yeah, we are being sensible.

Offline lskovlun

Re: SCI0: Varibles and changestates
« Reply #6 on: November 25, 2024, 07:27:11 PM »
As for getting lost organizing your scripts: that's why you define enums for your states. Sierra sure did, and it's an example that helped me a great deal so far.
They did, and then they invented the switchto syntax for when the state machine is so straight-forward that no enum is nedded.

Offline robbo007

Re: SCI0: Varibles and changestates
« Reply #7 on: November 26, 2024, 09:59:03 AM »
Right this seems to work. Needs a little more work putting in delays etc.. But as Kawa mentioned its case sensitive. Doh. Is there any way around this using the GetInput command? To capture both Ken and ken when typed?

Code: [Select]
(method (changeState newState)
(ShowState self newState 1 2)
(switch (= state newState)
      (OpenHole ; Peep hole door opens
      ;(ProgramControl)
  (= peephole_open 0)
  (aPeepHole cycleSpeed: 1 setLoop: 8 setCycle: End self)
)
(AskForPasswd ;The pimp speaks to ego
(= seconds 20)
(Print 102 1) ;"Yeah. Whatsda passwoid?"
(GetInput @passwd 45 {Whatsda passwoid?})
(if (== STRINGS_EQUAL (StrCmp @passwd "Ken sent me"))
(self changeState: GotPasswd)
else
(Print {Scram Butthead})
(aPeepHole setCel: 0 stopUpd:)
)
)

(GotPasswd ;Got password speak friend and enter.
(Print {Testing if reaching new state})
(aPeepHole setCel: 0 stopUpd:)

)
)
)
)

Offline Charles

Re: SCI0: Varibles and changestates
« Reply #8 on: November 26, 2024, 10:17:46 AM »
QFG1 EGA uses a StringEquals function in script 802.
Code: [Select]
;;; Sierra Script 1.0 - (do not remove this comment)
(script# INPUTCOMP) ;INPUTCOMP = 802
(include system.sh) (include sci2.sh) (include game.sh)
(use _User)

(public
ToLower 0
StringEquals 1
EventEqualsString 2
)

(procedure (ToLower param1)
(return
(if (or (< param1 65) (> param1 90))
(return param1)
else
(return (+ (- param1 65) 97))
)
)
)

(procedure (StringEquals param1 param2 &tmp temp0 temp1 temp2 temp3)
(= temp1 (StrLen param2))
(= temp0 (- (= temp0 (StrLen param1)) temp1))
(while (>= temp0 0)
(= temp3 0)
(= temp2 temp0)
(while (< temp3 temp1)
(if
(!=
(ToLower (StrAt param2 temp3))
(ToLower (StrAt param1 temp2))
)
(break)
)
(++ temp3)
(++ temp2)
)
(if (== temp3 temp1) (return (+ temp3 1)))
(-- temp0)
)
(return FALSE)
)

(procedure (EventEqualsString event param2 &tmp i userInputLineAddr)
(if
(and
(User canInput?)
(not (event claimed?))
(== (event type?) keyDown)
(or
(== (event message?) (User echo?))
(and
(<= 32 (event message?))
(<= (event message?) 127)
)
)
)
(event claimed: TRUE)
(if (User getInput: event)
(= userInputLineAddr (User inputLineAddr?))
(= i 1)
(while (< i argc)
(if
(StringEquals userInputLineAddr [param2 (- i 1)])
(return i)
)
(++ i)
)
(event type: speechEvent)
(event claimed: FALSE)
(Parse userInputLineAddr event)
(User said: event)
)
)
(return FALSE)
)


an example of it being used is in script 29.
Code: [Select]
(if
(or
(StringEquals (User inputLineAddr?) {purple})
(StringEquals (User inputLineAddr?) {pink})
)
(askQuestions changeState: 0)
else
(WrongAnswer)
)
« Last Edit: November 26, 2024, 10:21:38 AM by Charles »

Offline Kawa

Re: SCI0: Varibles and changestates
« Reply #9 on: November 26, 2024, 10:23:23 AM »
Here's how PQ2 converts your input in the copy protection screen to uppercase for comparison:
Code: [Select]
(procedure (toUpper &tmp i ch)
(for ((= i 0)) (= ch (StrAt @passwd i)) ((++ i))
(if (and (>= ch 97) (<= ch 122))
(StrAt @passwd i (- ch 32))
)
)
)

Noting that 97 to 122 are 'a' to 'z', and 97-32='A'.

Offline robbo007

Re: SCI0: Varibles and changestates
« Reply #10 on: November 26, 2024, 04:24:08 PM »
Amazing. Thanks guys. This seems to do the trick forcing it all to caps. :)

Code: [Select]
(method (changeState newState)
(ShowState self newState 1 2)
(switch (= state newState)
      (OpenHole ; Peep hole door opens
      ;(ProgramControl)
  (= peephole_open 0)
  (aPeepHole cycleSpeed: 1 setLoop: 8 setCycle: End self)
)
(AskForPasswd ;The pimp speaks to ego
(= seconds 20)
(Print 102 1) ;"Yeah. Whatsda passwoid?"
(GetInput @passwd 45 {Whatsda passwoid?})(toUpper)
(if (== STRINGS_EQUAL (StrCmp @passwd "KEN SENT ME")
)
(self changeState: GotPasswd)
else
(Print {Scram Butthead})
(aPeepHole setCel: 0 stopUpd:)
)
)

Offline robbo007

Re: SCI0: Varibles and changestates
« Reply #11 on: November 28, 2024, 09:36:36 AM »
After implementing the super-dupper "peephole" script I'm now getting some oddities.

When ego runs the "peephole" script and leaves that room and comes back in, then when trying to exit either to the north (Hall) or south (outside Lefty's) I get the following lock ups. This only seems to happen if the peephole script has initiated. If not initiated both exits work as they should do.

Code: [Select]
(instance aDoorScript of Script ;Peep hole script
(properties)
(method (handleEvent event)
(if (or (!= (event type:) evSAID) (event claimed:))
(return)
)
)

(method (changeState newState)
(ShowState self newState 1 2)
(switch (= state newState)
      (OpenHole ; Peep hole door opens
      (ProgramControl)
  (aPeepHole cycleSpeed: 1 setLoop: 8 setCycle: End self)
)
(AskForPasswd ;The pimp speaks to ego
(Print 102 1) ;"Yeah. Whatsda passwoid?"
(PlayerControl)
(GetInput @passwd 45 {"Whatsda passwoid?"})(toUpper)
(if (== STRINGS_EQUAL (StrCmp @passwd "KEN SENT ME")
)
(self changeState: GotPasswd)
else
(Print 102 4) ;"Scram, dog breath!"
(aPeepHole setCel: 0 stopUpd:)
(self dispose:)
)
)

(GotPasswd ;Got password speak friend and enter.
(gGame changeScore: 5)
(Print 102 5) ;"Come on in."
(aPeepHole setCel: 0 stopUpd:)
;(aDoor open:)
;(self dispose:)
(gRoom newRoom: 103)

)
)
)
)

Offline lskovlun

Re: SCI0: Varibles and changestates
« Reply #12 on: November 28, 2024, 05:01:56 PM »
Have you fixed those things I pointed out with your variable declarations? Because those could result in memory corruption if you got them to compile somehow. If this is not a corruption bug, we'd need to see one or both room init methods.

Offline robbo007

Re: SCI0: Varibles and changestates
« Reply #13 on: November 28, 2024, 05:46:41 PM »
Have you fixed those things I pointed out with your variable declarations? Because those could result in memory corruption if you got them to compile somehow. If this is not a corruption bug, we'd need to see one or both room init methods.

I removed the ones that we not valid and I'm only using:
Code: [Select]
(local
    messageCount
passwd = 1 ;this is the password variable used for the Ken sent me password in the Door_script.
)

The init for Lefty's bar has:

Code: [Select]
(script# 102)
(include sci.sh)
(include game.sh)
(use main)
(use controls)
(use cycle)
(use game)
(use feature)
(use obj)
(use inv)
(use door)
(use rm797) ;showState debugging changestates script

(public
rm102 0
)
(procedure (GetInput str maxLen prompt &tmp [temp0 4]) ;The GetInput procedure. Does not seem to load form Main.sc. Noting that 97 to 122 are 'a' to 'z', and 97-32='A'.
(if (Print (if (>= argc 3) prompt else {}) #edit str maxLen &rest)
(StrLen str)
)
)
(procedure (toUpper &tmp i ch) ; This procedure turns all text into caps when using toUpper and GetInput statements.
(for ((= i 0)) (= ch (StrAt @passwd i)) ((++ i))
(if (and (>= ch 97) (<= ch 122))
(StrAt @passwd i (- ch 32))
)
)
)

(enum ;** Pimp state values
OpenHole
AskForPasswd
GotPasswd
)
(local
    messageCount
passwd = 1 ;this is the password variable used for the Ken sent me password in the Door_script.
)

(define LEFTY_LEFT 150)
(define LEFTY_RIGHT 243)
(define LEFTY_CENTRE 192)
(define LEFTY_Y 109)

(define vRoom 102
)
(define lPicture 0)
(define lDoor 1)
(define lFan 2)
(define lJukebox 3)
(define lPerson 4)
(define lPerson1 5)
(define lPerson2 6)
(define lPerson3 7)
(define lPeepHole 8)


(instance rm102 of Rm
(properties
picture 102
north 0
east 0
south 0
west 0
)

(method (init)
(super init:)
(self setScript: RoomScript)
(switch gPreviousRoomNumber
)
(cond
((== gPreviousRoomNumber 101) (gEgo posn: 86 128 loop: 2)
)
((== gPreviousRoomNumber 103) (gEgo posn: 286 168 loop: 1)
)
(else
(gEgo posn: 155 170 loop: 3)
)
)
(SetUpEgo)
(gEgo init:)
(aPicture init:)
(aFan init:)
(aJukebox init:)
(aPerson init:)
(aPerson1 init:)
(aPerson2 init:)
(aPerson3 init:)
(aLefty init:)
(aPeepHole init:)
(if (== gPreviousRoomNumber 103) (aDoor init: close:) ;this checks to see where ego has come from and if come from room 103 it will then close the door after
else
(aDoor init:)
)
)
)

And outside Lefty's where it crashes:

Code: [Select]
(script# 106)
(include sci.sh)
(include game.sh)
(use main)
(use controls)
(use cycle)
(use game)
;(use AutoDoor)
(use feature)
(use obj)
(use inv)
(use door)
;(use jump)
;(use dpath)
(use Sound)

(public
rm106 0
)

(define vRoom 106
)
(define lSign 0)
(define lSign2 1)
(define lSign3 2)
(define lDoor   3)


(instance rm106 of Rm
(properties
picture 106
north 102
east 108
south 0
west 107
)

(method (init)
(super init:)
(SetDebug) ;This forced game into debug.
(self setScript: RoomScript)
(switch gPreviousRoomNumber
)
(cond
((== gPreviousRoomNumber 105) (gEgo posn: 283 152 loop: 2)
)
((== gPreviousRoomNumber 102) (gEgo posn: 134 158 loop: 2)
)
((== gPreviousRoomNumber 107) (gEgo posn: 12 166 loop: 0)
)
((== gPreviousRoomNumber 108) (gEgo posn: 309 165 loop: 1)
)
  (else
(gEgo posn: 134 162 loop: 2)

)
)
(SetUpEgo)
(gEgo init:)(gEgo view: 705)
;(aSign init:)
(aSign2 init:)
(aSign3 init:)
(aSign4 init:)
(if (== gPreviousRoomNumber 102) (aDoor init: close:)
else
(aDoor init:)
)
)
)

Offline lskovlun

Re: SCI0: Varibles and changestates
« Reply #14 on: November 28, 2024, 07:18:23 PM »
OK, so this seems to be connected to the same issue as your earlier ego initialization problem (in the trite phrase thread). The debugger hits at a callb $1 instruction, which is the first instruction after the fault. callb $1 corresponds to (SetUpEgo), so the faulting instruction is one of the sends just before that line, which both send to gEgo. You can double-check by viewing the value of gEgo (global 0): In the debugger, press g then enter the number zero. The next input box after that lets you see the current value of global 0, and optionally to change it. I am guessing that gEgo is 0 at this point.

What did you do about the problem in the trite phrase thread?


SMF 2.0.19 | SMF © 2021, Simple Machines
Simple Audio Video Embedder

Page created in 0.069 seconds with 22 queries.