Working, but an utter mess of conflicting IFs and Flags

OurJud
01 Nov 2016, 23:24This works, but because I will never get my head around the logic of Quest's IF nesting etc, I suspect this is littered with conflicting rules and conditions.
Would anyone be kind enough to load it up and let me know just how bad it is?
<object name="Shelter">
<inherit name="editor_room" />
<exitslistprefix type="string"></exitslistprefix>
<description type="script">
stop sound
if (GetBoolean(player, "firelit")) {
play sound ("firecrackling3.mp3", false, true)
msg ("Inside a shack. Another winter is drawing in. Room is warm.")
MakeExitInvisible (firetrue)
}
else {
msg ("Inside a shack. Another winter is drawing in. Room is freezing.")
if (Got(fuel)) {
MakeExitVisible (firetrue)
}
else {
MakeExitInvisible (firetrue)
}
}
if (Got(fuel) and not Got(hunting bow)) {
MakeExitVisible (gotwood)
}
else {
MakeExitInvisible (gotwood)
}
if (GetBoolean(player, "gotfood")) {
MakeExitVisible (havefood)
}
</description>
<beforeenter type="script">
</beforeenter>
<beforefirstenter type="script">
</beforefirstenter>
<enter type="script">
if (Got(hunting bow)) {
MakeExitInvisible (gotwood)
}
</enter>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<exit name="firetrue" alias="Fire">
<runscript />
<visible type="boolean">false</visible>
<script type="script">
if (Got(fuel)) {
msg ("The dry wood begins to crack and pop in the fire and the room grows steadily warmer.")
play sound ("firecrackling3.mp3", false, true)
SetObjectFlagOn (player, "firelit")
MakeExitInvisible (firetrue)
}
else if (not Got(fuel)) {
msg ("No firewood.")
}
</script>
</exit>
<exit alias="Explore" to="forest" />
<exit name="gotwood" alias="Weapon">
<runscript />
<visible type="boolean">false</visible>
<script type="script">
if (Got(wood)) {
msg ("It's not great but should act as a deterent. Okay for small mammals.")
MoveObject (hunting bow, player)
MakeExitInvisible (gotwood)
MoveObject (wood, forest)
}
else if (not Got(wood)) {
msg ("No wood.")
}
else if (not Got(hunting bow)) {
MakeExitInvisible (gotwood)
}
</script>
</exit>
<object name="hunting bow">
<inherit name="editor_object" />
</object>
<exit name="havefood" alias="Eat">
<visible type="boolean">false</visible>
<runscript />
<script type="script">
if (GetBoolean(player, "firelit")) {
msg ("Not much, but hot and delicious.")
SetObjectFlagOff (player, "gotfood")
MakeExitInvisible (havefood)
MoveObject (hunting bow, bin)
SetObjectFlagOn (player, "villageunlocked")
}
else {
msg ("No means of cooking.")
}
</script>
</exit>
</object>
<object name="forest">
<inherit name="editor_room" />
<exitslistprefix type="string"></exitslistprefix>
<description type="script">
msg ("Forest. Most of the trees are dead or dying.")
play sound ("forest_wind.mp3", false, true)
if (Got(hunting bow)) {
MakeExitVisible (havebow)
}
if (GetBoolean(player, "villageunlocked")) {
MakeExitVisible (explore)
}
</description>
<enter type="script">
if (GetBoolean(player, "gotfood")) {
MakeExitInvisible (havebow)
}
</enter>
<object name="wood">
<inherit name="editor_object" />
<take />
<takemsg>Firewood collected</takemsg>
<dropmsg>Firewood dropped</dropmsg>
</object>
<exit name="woodnotneeded" alias="Gather">
<prefix type="string"></prefix>
<runscript />
<visible />
<script type="script">
msg ("Wood collected.")
MoveObject (fuel, player)
MoveObject (wood, player)
MakeExitInvisible (woodnotneeded)
</script>
</exit>
<exit alias="Shelter" to="Shelter" />
<exit name="havebow" alias="Hunt">
<runscript />
<visible type="boolean">false</visible>
<script type="script"><![CDATA[
msg ("It was a long day, but a {random:scrawny rabbit:small hare:fish:squirrel} was eventually caught.<br/>")
SetObjectFlagOn (player, "gotfood")
MakeExitInvisible (havebow)
MoveObject (hunting bow, player)
]]></script>
</exit>
<exit name="explore" alias="Explore" to="village">
<visible type="boolean">false</visible>
<runscript type="boolean">false</runscript>
<script type="script">
if (GetBoolean(player, "gotfood")) {
MakeExitVisible (explore)
}
</script>
</exit>
<object name="fuel">
<inherit name="editor_object" />
</object>
</object>
<object name="village">
<inherit name="editor_room" />
<description type="script">
if (GetBoolean(player, "villageunlocked")) {
msg ("No signs of life or infected. Cold winds. A dirt road slopes away into the distance.")
}
</description>
</object>
<object name="bin">
<inherit name="editor_room" />
</object>
<function name="ClearScreen">
request (ClearScreen, "")
OutputTextNoBr (game.css)
</function>
<function name="InitUserInterface"><![CDATA[
JS.setCommandBarStyle (GetCurrentTextFormat("") + ";border:" + game.defaultbackground)
JS.eval ("$('#status').hide();")
JS.SetBackgroundCol ("black")
JS.eval ("$('#txtCommandDiv').prepend('> ')")
JS.OutputTextNoBr (game.css)
OutputTextNoBr (game.css)
request (SetInterfaceString, "TypeHereLabel=")
if (GetBoolean(game, "inprogress")) {
}
else {
game.inprogress = true
}
]]></function>
<function name="HideCommandBar">
request (Hide, "Command")
</function>
<function name="ShowCommandBar">
request (Show, "Command")
</function>
</asl>
hegemonkhan
01 Nov 2016, 23:41Congrats on getting it to work! Revel (celebrate/be happy/be proud!) in your success! Understanding 'if' logic is not easy. If you're really bothered by it... then you learn more about coding and understand more 'if' and etc logic needed, to make better/clean'er/more-efficient code, but that isn't easy, to learn even more coding and its needed understanding of complex concepts/logic/ideas/structures.
Sometimes, nesting is just messy, and it's better to keep it simple and straight-forward, even if it might be more verbose codage.
In my quick/brief scan, the code looks good!
(yes, the code design/structure can be better, and the logic a little better too, but that means taking your ability up to another, or a few/many more, level/s)
(code can always be better... if you're like me, you get obsessed with it, and never just go with it and progress on with the rest of your game, lol)
Something I need to heed: if it works, that's all that matters! Move on to doing more things for your game-making completion. At a later time, if/when you're able to, then, you can come back and make your code/game-code, or parts of your code/game-code, better. Or, if you're code is needed for the rest of your game, but it's just too poor-inefficient/messy/spagetti to work with, then, well... you got to go clean it up, for you to then use/apply it to the other stuff it's needed for in your game.

OurJud
01 Nov 2016, 23:47Scary thing is this is probably about 3% of the whole game. Hopefully each new location will be treated as a separate game, so I can essentially put this first section to bed and forget about it.
hegemonkhan
01 Nov 2016, 23:51yep.. small steps... the famous quote, paraphrased: "A journey of a thousand miles, starts with a small single step, then another, and another, and another..."
EVERY SUCCESS IS A BIG SUCCESS!!! hehe :D (a good mindset to have)
more advanced coding, deals with scalability... how well does my code expand to other aspects of my game/program that requires it.
for example... does my combat code only works for a single monster or does it work for the entire game's monsters, scalability stuff like this... and other-like stuff
does it only work for physical/weapon damage, or is it able to handle all aspects of combat (physical/weapon, melee vs ranged, magic/casting, ST vs MT, friend vs foe, items, escaping, different weapons/magics-spells, etc etc etc).
if your code is such a hassle to figure out how to get it to work for the rest of your game's stuff or macro/game/global usage, then you need to go back and craft a better design of code. Or, if you have to keep writing new code for doing pretty much the same thing for different stuff in your game, then you want to go back and try to write a more universal/advanced/scalable code.
The Pixie
02 Nov 2016, 08:23I would put the bit in the enter
script into the description with the rest, to keep it together. That also needs an else
to hide the exit when the food is eaten.
An alternative approach would be to have a function that sets all the exits for the current room invisible, and then your code just checks which need to then be made visible
stop sound
ResetExits
MakeExitVisible (outside)
if (GetBoolean(player, "firelit")) {
play sound ("firecrackling3.mp3", false, true)
msg ("Inside a shack. Another winter is drawing in. Room is warm.")
}
else {
msg ("Inside a shack. Another winter is drawing in. Room is freezing.")
if (Got(fuel)) {
MakeExitVisible (firetrue)
}
}
if (Got(fuel) and not Got(hunting bow)) {
MakeExitVisible (gotwood)
}
if (GetBoolean(player, "gotfood")) {
MakeExitVisible (havefood)
}
if (GetBoolean(player, "gotfood")) {
MakeExitVisible (explore)
}
The ResetExits function looks like this:
foreach (exit, AllExits()) {
if (exit.parent = room) {
exit.visible = false
}
}
You would have to remember to set visible all permanent exits, like the one to outside. However, I think you would find it easier to follow the code without the (majority or) else
blocks.
A second alternative, which would require some re-thinking, would be to set the visibility when the action is performed. For example, when the firewood is picked up, you set the "Start fire" exit to be visible back in the shack, rather than in the room description.
The script for the gathering wood exit would then be this:
msg ("Wood collected.")
MoveObject (wood, player)
if (not GetBoolean(player, "firelit")) {
MakeExitVisible (firetrue)
}
if (not Got(hunting bow)) {
MakeExitVisible (gotwood)
}
While the script for the room would just be:
stop sound
if (GetBoolean(player, "firelit")) {
play sound ("firecrackling3.mp3", false, true)
msg ("Inside a shack. Another winter is drawing in. Room is warm.")
}
else {
msg ("Inside a shack. Another winter is drawing in. Room is freezing.")
}

OurJud
02 Nov 2016, 15:56Thank you, TP. I like the idea of not having to worry about all the ELSE blocks.
Where would that ResetExits function go, in my Game's Start Script?
Also, how would I over-ride that code so that the Shack and Outside exits remain permanently visible?
The Pixie
02 Nov 2016, 17:57You put ResetExits
at the start of the description (second line in the code above), then set the ones that are "permanently" visible to be visible (third line above), and then go though the rest and see if the conditions are right for them.

OurJud
02 Nov 2016, 19:00Sorry, I know I test patience around here with my inability to understand, but do you mean I just put ResetExits at the start of the description, or that I put the actual function code? And at the start of which description? All of them or just the Shack?
The Pixie
02 Nov 2016, 19:44You need to create the function first. Click on Functions at the left, then on Add, then type in ResetExits. Then paste in the code.
Then you can just put ResetExits at the start of the description. Do that every description. First turn off the sound it nercessary, then ResetExits, then show the message, then the always on exits, and then the if
s for the optional exits. Here is the code again with comments to make that clearer, but the general format should work in every room:
stop sound
// set all exits invisible
ResetExits
// Do the message
if (GetBoolean(player, "firelit")) {
play sound ("firecrackling3.mp3", false, true)
msg ("Inside a shack. Another winter is drawing in. Room is warm.")
}
else {
msg ("Inside a shack. Another winter is drawing in. Room is freezing.")
}
// This one should always be visible
MakeExitVisible (outside)
// The light fire exit
if (Got(fuel) and not GetBoolean(player, "firelit")) {
MakeExitVisible (firetrue)
}
// The make bow exit
if (Got(fuel) and not Got(hunting bow)) {
MakeExitVisible (gotwood)
}
// The eat food exit
if (GetBoolean(player, "gotfood")) {
MakeExitVisible (havefood)
}
// The explore exit
if (GetBoolean(player, "gotfood")) {
MakeExitVisible (explore)
}

OurJud
02 Nov 2016, 20:29Thanks for your patience. I'll try and implement it now.