Author Topic: Loading External Scripts on the Fly?  (Read 877 times)

0 Members and 1 Guest are viewing this topic.

Offline NilG

Loading External Scripts on the Fly?
« on: June 09, 2019, 09:48:07 PM »
This may be a stupid question, but I've got a couple of rooms that are on the edge in terms of heap space, and it's causing some issues already (like can't open Inventory at times).  The rooms are basically done, but the game itself will probably have more quite a few more global variables and things that will end up pushing them over.  I'm looking into tightening things up, but I was wondering if there is any way to load an external script on the fly?

What I'd really like to do is have, say, one script that deals with 'ask' responses and one that deals with 'look' responses for this room.  I'm trying to account for as much user input as I can, and if I could take even just these two subsets of user inputs and set it in some way that an external script is called when the user 'asks' something then disposed immediately after, for example, I feel like it could go a long way to alleviating heap issues.  It's hacky, but it would get the memory where it needs to be if just the handling of these two inputs could be offloaded and put into memory only on-demand.

I may be grossly misunderstanding things here, but just checking on the possibilities.  I'm looking for ways to legit tighten up and rein in the script as well.  I'm hoping not to have to cut things, though that will probably be the only alternative for at least one of the rooms at this point, if I can't figure something else out, so figured I'd ask at least.



Offline Kawa

Re: Loading External Scripts on the Fly?
« Reply #1 on: June 10, 2019, 08:23:33 AM »
I'm thinking...

In your minimal room's handleEvent, check if the event type is "said". Check if you (Said 'look>'), and if so do something like... ((ScriptID 42 0) handleEvent: pEvent), I'm really not sure on the syntax, where 42 is the script# for the separate "looking in this room" script, which in turn can check for (Said '<at/example') and all that, then dispose of script 42 again.

Offline Charles

Re: Loading External Scripts on the Fly?
« Reply #2 on: June 10, 2019, 11:35:28 AM »
QFG1EGA did this in a couple places. Here's a snippet from the tavern:

TownTavern.sc: (script 331) in the Room's handleEvent:
Code: [Select]
(method (handleEvent event)
(cond
((super handleEvent: event))
((!= (event type?) evSAID))
(Said 'look>')
(SaidLookTavern event)
)
;snip a bunch more cond's
)
)

Then in an external script file, which I named RM331_Look.sc (script 339)
Code: [Select]
(script# TAVERN_LOOK)
(public
SaidLookTavern 0
)

(procedure (SaidLookTavern)
(cond
((Said '[<at,around][/!*,room,building,tavern,establishment]')
(HighPrint 339 22)
)
((Said '/barrel,barrel')
(HighPrint 339 0)
)
((Said '/dirt')
(HighPrint 339 1)
)
;etc...
)
(DisposeScript TAVERN_LOOK)
)

Offline NilG

Re: Loading External Scripts on the Fly?
« Reply #3 on: June 10, 2019, 01:31:41 PM »
Nice, thank you both, I'm going to try some of these out.

I kid you not, I took a peek at QFG1 last night thinking they might have done this, including your uploaded decompile files, Charles.  For some reason I looked at "ask" (which seems to occur pretty consistently internally, though I hadn't thought to check with the chatty castle guard) instead the more likely "look."  Probably should have been a little more thorough there.

Offline NilG

Re: Loading External Scripts on the Fly?
« Reply #4 on: June 10, 2019, 02:45:25 PM »
Excellent, so parsing the input as with the QFG1 sample and Kawa's

((ScriptID 301 0) handleEvent: pEvent)

syntax which was correct, I do seem to be able to do this now.  DisposeScript works after to seemingly free up the space again.

Copied over all the looks for one room; I am receiving a compiler error for events which include variables from the originating script (Undeclared identifiers, Unknown variables, etc).  I can probably chop it so that the bulk of these events are taken care of externally while the ones requiring local variables remain in the original script.  Is that probably the best way to go?  It should certainly help with the space, but I wouldn't be adverse to keeping all of the responses themselves confined to the one script if possible.

Offline Charles

Re: Loading External Scripts on the Fly?
« Reply #5 on: June 10, 2019, 11:50:03 PM »
Two ways come to mind:
I simplified the Tavern example, for simplicity's sake.  The Look external script (again, script 339) is actually:
Code: [Select]
(public
SaidLookTavern 0
TavernLookAround 1
TavernLookAtStool 2
)

(procedure (SaidLookTavern)
(cond
((Said '[<at,around][/!*,room,building,tavern,establishment]')
(TavernLookAround FALSE FALSE)
)
;snip
)
(DisposeScript TAVERN_LOOK)
)

(procedure (TavernLookAround firstTime doDispose)
(HighPrint 339 22)
;The grimy window lets little light into this tavern.  It smells like stale ale and other more unpleasant things.
;The floor is covered with dirt, and the bar with sticky beer.
(HighPrint 339 23)
;Smoke appears to be rising from the center cask behind the bar.  To your right, two gamblers are playing cards.
(if firstTime
(HighPrint 339 24)
;The bartender glares at you as you enter, and so does the ugly goon on the left. You get the impression that you are not welcome.
)
(if doDispose
(DisposeScript TAVERN_LOOK)
)
)

Then in the main Tavern.sc (script 331), when you enter the tavern for the first time, it will call (TavernLookAround TRUE TRUE), which will add the extra bit about the bartender glaring at you, then will unload itself from memory.  So you might be able to rework your local variables enough that you can call global procedures passing those local variables as references. I don't honestly know the memory impact global procedures have vs global variables, but I would assume procedures is less.

The other thing that comes to mind is using Btst, Bset, Bclr global flags, instead of global variables. You may have some global variables that are only used for TRUE/FALSE values, which could be condensed into flags instead.  A flag only uses 1 bit of memory, whereas a global variables uses 16 bits.

Offline NilG

Re: Loading External Scripts on the Fly?
« Reply #6 on: June 11, 2019, 12:42:19 AM »
 That's interesting, I'll have to read through and see; that certainly seems like it could be a way of going about it.  Passing a few var copies should still be kinder on the memory for the room in general than a couple lines of logical operations.

I'll have to check into the flag trio, too.  I'm not familiar with them, but see the code bit pasted in the QFG1 thread.  Most of the global variables I've created are TRUE/FALSE so far, so if there's that wide a gap in memory usage, it could definitely be worth implementing, assuming I can sort through it.  A generous assumption, to be sure, but...

Offline EricOakford

Re: Loading External Scripts on the Fly?
« Reply #7 on: August 10, 2019, 09:33:40 PM »
Loading external scripts on the fly... that's the approach that I've been using for my templates recently. Instead of cramming things like the game's icon bar, control panel, and inventory into MAIN.SC, why not just put them in their own individual scripts? That's what Sierra did later on, and it makes the main script (which will always be loaded in memory) use significantly less memory. In the case of a game intialization script (so long as it doesn't need to use objects in the main script), it can just erase itself from memory afterwards, since it will not need to be used again.
My SCI templates
SCI0 SCI0.1 SCI1.0 SCI1.1

Offline lskovlun

Re: Loading External Scripts on the Fly?
« Reply #8 on: August 12, 2019, 03:19:24 PM »
cramming things like the game's icon bar, control panel, and inventory
All of these will be required often to semi-often in normal use. There's a risk in not being able to pull them up if you're low on memory because their memory footprint was not accounted for earlier. What if you're prevented from saving/restoring/quitting? Putting up a death message? Using a critical object?

Offline EricOakford

Re: Loading External Scripts on the Fly?
« Reply #9 on: August 12, 2019, 11:57:15 PM »
cramming things like the game's icon bar, control panel, and inventory
All of these will be required often to semi-often in normal use. There's a risk in not being able to pull them up if you're low on memory because their memory footprint was not accounted for earlier. What if you're prevented from saving/restoring/quitting? Putting up a death message? Using a critical object?

They will still be initialized in the game's init using the ScriptID kernel function (so they will still be loaded in heap at startup), so I don't think that will be a problem.
I just thought it was a good idea given that by the time of SCI1, it became standard for the inventory to be placed in its own script, and the control panel soon followed, then the icon bar in the SCI32 era.

Though, admittedly, from SCI01 on, the way heap was stored had been changed.

08/13/2019 UPDATE: I've decided to just move the inventory for SCI0 and SCI01 back into MAIN.SC. It's more memory-efficient that way.
I've further been making sure that the free heap and largest pointer are as close as possible (only a 2 byte difference!)
« Last Edit: August 13, 2019, 09:26:48 PM by EricOakford »
My SCI templates
SCI0 SCI0.1 SCI1.0 SCI1.1

Offline lskovlun

Re: Loading External Scripts on the Fly?
« Reply #10 on: August 14, 2019, 02:00:49 AM »
Though, admittedly, from SCI01 on, the way heap was stored had been changed.
Let alone SCI1.1 (file format redesign) and SCI32 (complete memory manager redesign).


SMF 2.0.14 | SMF © 2017, Simple Machines
Simple Audio Video Embedder

Page created in 0.119 seconds with 23 queries.