In the meantime, I thought I'd share some code examples I put together the other month; well, one now, one next time I write here.
Today's bit of code will be for what IF lingo calls a "bag of holding." I'd say they were first popularized in late era commercial IF although they first showed up a bit earlier than that. Players still had set carrying capacities so object-management was required, but one object in the game- usually a bag or knapsack- could carry a limitless number of objects. As soon as you couldn't pick up anything more, you'd stick stuff in the bag of holding and, yay, looting can recommence!
Bags of holding got even cooler when the game would automatically stick stuff in them for you. Today's code sample will be an automatic bag of holding system in Hugo.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global bag_of_holding | |
replace Acquire(newparent, newchild) | |
{ | |
local p,h | |
CalculateHolding(newparent) | |
if newparent.#holding | |
h = newparent.holding | |
else | |
h = holding_global | |
if (h + newchild.size > newparent.capacity) | |
{ | |
if not BagOfHolding(newparent, newchild) | |
return false | |
} | |
p = parent(newchild) | |
move newchild to newparent | |
CalculateHolding(p) | |
#ifset MULTI_PCS | |
MakeMovedVisited(newchild) | |
#else | |
newchild is moved | |
#endif | |
newchild is not hidden | |
if newparent.#holding | |
newparent.holding = newparent.holding + newchild.size | |
return true | |
} | |
routine BagOfHolding(newparent, newchild) | |
{ | |
local x | |
if newparent ~= player or bag_of_holding not in player | |
return false | |
x = child(newparent) | |
while x | |
{ | |
if (x is not worn or (x is not clothing and x is worn)) and | |
x is not light and | |
(x.size + newparent.capacity >= newchild.size) and | |
x ~= bag_of_holding | |
{ | |
if Acquire(bag_of_holding,x) | |
{ | |
print "(Putting "; The(x); " into "; The(bag_of_holding) ; \ | |
" to make room)" | |
return true | |
} | |
} | |
x = younger(x) | |
} | |
return false | |
} |
Just set the bag_of_holding global to your bag of holding object, and there you go! Now, admittedly, this system is pretty simple. It only allows for swapping one object that, when moved, will create enough space for the new object. I considered writing another pass if the first one didn't find a suitable most, but I figured that this behavior would fit most games. If a game has large variance in object sizes, the large objects probably should get special treatment through before routines and such. Plus, it's always kind of ugly when you try to pick something up and then half of your inventory is moved to the bag of holding so I didn't want to encourage that.
No comments:
Post a Comment