Opened Door Description?

Hey I finally finished the tutorial, but now I'm stuck in my first real game.

I want the player to be stuck in a locked room and I figured out the bit about the door and how to unlock it, but now I want to add a description to the door, to where the player gets a different message depending on weather the door is open or not or unlocked or not.

I know that I need to use the If script but after that I'm stuck. Which expression do I use? I've traded the one with the flag and if the door is open or not but I don't know if that will really be sufficient. Can anyone help me?


Hello!

Good to hear from you!

Now, let's get down to business.


I named my door door, so replace every instance of door with the name of your door.

Code View first:
NOTE: THIS CODE ORIGINALLY CONTAINED AN ERROR, WHICH HAS NOW BEEN FIXED (THANKS, HK!)

<!--
NOTE: Refer to the entire code (included below) to see where to plug these into the main file's code.
-->

<look type="script">
  if (door.isopen) {
    msg ("The door is ajar.")
  }
  else {
    msg ("The door is closed at the moment.")
  }
</look>

is the same as

 <look>{either door.isopen: The door is ajar.| The door is closed at the moment.}</look>

<!--
NOTE: Refer to the entire code (included below) to see where to plug these into the main file's code.
-->
<inroomdescription>{either door.isopen: The door is now open.| The door is closed at the moment.}</inroomdescription>

<!--
NOTE: Refer to the entire code (included below) to see where to plug these into the main file's code.
-->

Here's the entire sample game, so you can see it as a whole:

CLICK HERE TO VIEW THE CODE
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="a jar">
    <gameid>afadb32b-5937-43f9-b109-2b802cd508ff</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
    <appendobjectdescription />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="door">
      <inherit name="editor_object" />
      <inherit name="openable" />
      <inherit name="container_lockable" />
      <feature_container />
      <keycount type="int">1</keycount>
      <inroomdescription>{either door.isopen: The door is now open.| The door is closed at the moment.}</inroomdescription>
      <key type="object">Skellington Key</key>
      <look type="script">
        if (door.isopen) {
          msg ("The door is ajar.")
        }
        else {
          msg ("The door is closed.")
        }
      </look>
      <openscript type="script">
        if (this.locked) {
          if (this.autounlock and AllKeysAvailable(this)) {
            do (this, "unlock")
            if (not this.isopen) {
              OpenObject (this)
            }
          }
          else {
            msg (DynamicTemplate("LockedObject", this))
          }
        }
        else {
          OpenObject (this)
        }
      </openscript>
      <exit alias="up" to="room">
        <inherit name="updirection" />
      </exit>
    </object>
    <object name="Skellington Key">
      <inherit name="editor_object" />
      <take />
      <look type="string"></look>
    </object>
    <exit name="lockeddoor1" alias="in" to="another room">
      <inherit name="indirection" />
      <locked />
      <lockmessage>The door is locked.</lockmessage>
      <runscript type="boolean">false</runscript>
      <script type="script">
      </script>
    </exit>
  </object>
  <object name="another room">
    <inherit name="editor_room" />
    <exit name="locked door" alias="out" to="room">
      <inherit name="outdirection" />
      <locked />
    </exit>
  </object>
</asl>

Here's a link to using the text processor shortcuts (http://docs.textadventures.co.uk/quest/text_processor.html).

NOTE: the above example (the one just beneath Code View first) is the best way to code this.

The below example only works when entered into certain fields while using the editor (and in specific ways when entering in Code View):

It will work here:
image
NOTE: The 'In-room description' text will display along with the room description every time you LOOK or enter the room.


But it will NOT work like this (in Code View):

msg ("{either door.isopen:The door is ajar.| The door is closed.}")


The pic below shows you what you need to do to the 'door' container to make it work. In the look at description, you just need to use the IF 'object is open' script and select object door, then print message "the door is open"; ELSE print message "the door is closed"
A GUI look...

Remember, just because you 'open door', Quest doesn't know that the object door is now actually open. If you run a script as I did below, make sure you add the 'open object' door script. I've forgotten that many times!!
EDIT: And just an FYI if you haven't gotten to this yet - Remember to also lock and name the exit that is blocked by the door. In this case below, the exit lock is named 'doorclosed'


a quick correction to Richard's part of code (if you want to use/refer to code, just so you don't get an error with-if trying to use it):

<!--
NOTE: Refer to the entire code (included below) to see where to plug these into the main file's code.
-->

<look type="script">
  if (door.isopen) {
    msg ("The door is ajar.")
  }
  else {
    msg ("The door is closed at the moment.")
  }
</look>

this is a really useful link:

http://docs.textadventures.co.uk/quest/elements/object.html

these are most of the built-in Attributes for Objects


as has already been explained by the above posters:

(replace any of my full-capitolized stuff with the names you're using in your game for it)
(ALSO: my 'NAME_OF_OBJECT' can also be 'NAME_OF_EXIT' for the built-in 'locked' Boolean Attribute)

the actual control for whether a door is recognized by quest as being opened/closed is:

the built-in 'isopen' Boolean Attribute: http://docs.textadventures.co.uk/quest/attributes/isopen.html

NAME_OF_OBJECT.isopen = true // the Object is opened
NAME_OF_OBJECT.isopen = false // the Object is closed

and for the scripting of it:

// NAME_OF_OBJECT.isopen = false

if (NAME_OF_OBJECT.isopen) { // if (TRUE) // for Boolean Attributes, quest knows that 'if (NAME_OF_OBJECT.isopen)' is defaulted as being 'if (NAME_OF_OBJECT.isopen = true)'
  msg ("The " + NAME_OF_OBJECT.alias + " is opened.")
} else { // if (FALSE) // if this wasn't an 'if-else' (two choice only), we'd need to use this: 'if (not NAME_OF_OBJECT.isopen)' or 'if (NAME_OF_OBJECT.isopen = false) or 'if (NAME_OF_OBJECT.isopen <> true)'
  msg ("The " + NAME_OF_OBJECT.alias + " is closed.")
}

// output: The [NAME_OF_OBJECT.alias] is closed.

// ---------------------------------------------

// NAME_OF_OBJECT.isopen = true

if (NAME_OF_OBJECT.isopen) {
  msg ("The " + NAME_OF_OBJECT.alias + " is opened.")
} else {
  msg ("The " + NAME_OF_OBJECT.alias + " is closed.")
}

// output: The [NAME_OF_OBJECT.alias] is opened.

and it's the same for if loccked/unlocked too:

via the built-in 'locked' Boolean Attribute: http://docs.textadventures.co.uk/quest/attributes/locked.html

NAME_OF_OBJECT.locked = true // the Object is locked
NAME_OF_OBJECT.locked = false // the Object is unlocked

// NAME_OF_OBJECT.locked = false

if (NAME_OF_OBJECT.locked) { /
  msg ("The " + NAME_OF_OBJECT.alias + " is locked.")
} else {
  msg ("The " + NAME_OF_OBJECT.alias + " is unlocked.")
}

// output: The [NAME_OF_OBJECT.alias] is unlocked.

// ---------------------------------------------

// NAME_OF_OBJECT.locked = true

if (NAME_OF_OBJECT.locked) {
  msg ("The " + NAME_OF_OBJECT.alias + " is locked.")
} else {
  msg ("The " + NAME_OF_OBJECT.alias + " is unlocked.")
}

// output: The [NAME_OF_OBJECT.alias] is locked.

quest has a lot of helper Functions, such as displaying a message when something is opened/closed/locked/unlocked, but they may not actually set the 'locked/isopen' Boolean Attributes. So, opening/closing/locked/unlocked, causes a lot of people, a lot of issues with trying to get it right and working, including me, laughs.

some of the various helper Functions on locked/unlocked/opening/closing stuff:

(these the same as seen within the GUI/Editor, as its drop-downs and/or text boxes and/or script options and/or check/uncheck option boxes, either on the Object's various Tabs, and/or on the special 'game' Game Settings Object's various Tabs)

http://docs.textadventures.co.uk/quest/attributes/autoopen.html
http://docs.textadventures.co.uk/quest/attributes/autounlock.html
http://docs.textadventures.co.uk/quest/attributes/canlockopen.html
http://docs.textadventures.co.uk/quest/attributes/close.html
http://docs.textadventures.co.uk/quest/attributes/closescript.html
http://docs.textadventures.co.uk/quest/attributes/isopen.html
http://docs.textadventures.co.uk/quest/attributes/key.html
http://docs.textadventures.co.uk/quest/attributes/locked.html
http://docs.textadventures.co.uk/quest/attributes/lockmessage.html
http://docs.textadventures.co.uk/quest/attributes/nokeymessage.html
http://docs.textadventures.co.uk/quest/attributes/onclose.html
http://docs.textadventures.co.uk/quest/attributes/onlock.html
http://docs.textadventures.co.uk/quest/attributes/onopen.html
http://docs.textadventures.co.uk/quest/attributes/onunlock.html
http://docs.textadventures.co.uk/quest/attributes/open.html
http://docs.textadventures.co.uk/quest/attributes/openscript.html
http://docs.textadventures.co.uk/quest/attributes/unlockmessage.html

and the associated Object Types / Types:

http://docs.textadventures.co.uk/quest/attributes/openable.html

http://docs.textadventures.co.uk/quest/attributes/container.html
http://docs.textadventures.co.uk/quest/attributes/container_base.html
http://docs.textadventures.co.uk/quest/attributes/container_closed.html
http://docs.textadventures.co.uk/quest/attributes/container_lockable.html
http://docs.textadventures.co.uk/quest/attributes/container_open.html


remember, ONLY the built-in 'isopen' and 'locked' Boolean Attributes actually control/determine whether an Object is actually in the 'open/closed/locked/unlocked' states:

NAME_OF_OBJECT.isopen = true
NAME_OF_OBJECT.isopen = false
NAME_OF_OBJECT.locked = true
NAME_OF_OBJECT.locked = false


About Boolean Attributes:

these are also known as 'flags', (which I don't personally like, sighs), as 'flag' is used to name something that has only two states (dualism: opposites/adversarial):

Booleans: true/false
Binary: 1/0
Electrical/Polar Charges: +/-

standard comparison model:
1 = true = + = on/yes
0 = false = - = off/no

various other dualism toggle names: on/off, up/down, left/right, in/out, yes/no, innocent/guilty, fat/skinny, tall/short, stupid/smart, sexy/ugly, male/female, young/old, alive/dead, fast/slow, hot/cold, etc etc etc

Boolean Logic / Truth Tables:

Definitions:

true = TRUE
false = FALSE

Negation (not) / Complements:

not true = FALSE
not false = TRUE

'AND' logic:

true and true = TRUE
true and false = FALSE
false and true = FALSE
false and false = FALSE

'OR' logic:

true or true = TRUE
true or false = TRUE
false or true = TRUE
false or false = FALSE

some examples:

conceptual-logic understanding:

(for this example, choose to use either 'dead' or 'alive', whichever you prefer, but not both!!!, as they're the same thing, just slightly different way of thinking about it)

orc.dead_boolean_attribute = true // the orc is dead
orc.dead_boolean_attribute = false // the orc is alive

orc.alive_boolean_attribute = true // the orc is alive
orc.alive_boolean_attribute = false // the orc is dead

-----------------------------

if (orc.dead_boolean_attribute) {
  msg ("The orc is dead.")
} else {
  msg ("The orc is alive.")
}

--------

if (not orc.dead_boolean_attribute) {
  msg ("The orc is alive.")
} else {
  msg ("The orc is dead.")
}

----

<![CDATA[
  if (orc.dead_boolean_attribute <> true) {
    msg ("The orc is alive.")
  } else {
    msg ("The orc is dead.")
  }
]]>

---

<![CDATA[
  if (orc.dead_boolean_attribute <> false) {
    msg ("The orc is dead.")
  } else {
    msg ("The orc is alive.")
  }
]]>

-------

if (orc.poisoned_boolean_attribute and orc.dead_boolean_attribute) {
  msg ("The orc is: poisoned and dead")
} else if (orc.poisoned_boolean_attribute and not orc.dead_boolean_attribute) {
  msg ("The orc is: poisoned and alive")
} else if (not orc.poisoned_boolean_attribute and orc.dead_boolean_attribute) {
  msg ("The orc is: not poisoned and dead")
} else if (not orc.poisoned_boolean_attribute and not orc.dead_boolean_attribute) {
  msg ("The orc is: not poisoned and alive")
}

-----

if (orc.poisoned_boolean_attribute or orc.dead_boolean_attribute) {
  msg ("The orc is either: poisoned or dead")
} else if (orc.poisoned_boolean_attribute or not orc.dead_boolean_attribute) {
  msg ("The orc is either: poisoned or alive")
} else if (not orc.poisoned_boolean_attribute or orc.dead_boolean_attribute) {
  msg ("The orc is either: not poisoned or dead")
} else if (not orc.poisoned_boolean_attribute or not orc.dead_boolean_attribute) {
  msg ("The orc is either: not poisoned or alive")
}

--------------

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("test 1")
} else if (orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("test 2")
} else if (not orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 1

---------------------------

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("test 1")
} else if (orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("test 2")
} else if (not orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 4

-------------

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("test 1")
} else if (orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("test 2")
} else if (not orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 2

-------------

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else if (orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("")
} else if (not orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute and not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 3

------------

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 1")
} else if (orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 2")
} else if (not orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 4

----------

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 1")
} else if (orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 2")
} else if (not orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 1

-----

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 1")
} else if (orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 2")
} else if (not orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 3

---------

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 1")
} else if (orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 2")
} else if (not orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("test 3")
} else if (not orc.dead_boolean_attribute or not orc.poisoned_boolean_attribute) {
  msg ("test 4")
}

// output: test 2

-------------

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: TRUE

--------

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: FALSE

------

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: FALSE

-----

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute and orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: FALSE

-----

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: TRUE

-----

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: FALSE

----

// orc.dead_boolean_attribute = true
// orc.poisoned_boolean_attribute = false

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: TRUE

--------

// orc.dead_boolean_attribute = false
// orc.poisoned_boolean_attribute = true

if (orc.dead_boolean_attribute or orc.poisoned_boolean_attribute) {
  msg ("TRUE")
} else {
  msg ("FALSE")
}

// output: TRUE

HK,

Good catch!

<!--
NOTE: Refer to the entire code (included below) to see where to plug these into the main file's code.
-->

<look type="script">
if (door.isopen) {
  msg ("The door is ajar.")
}
else (The door is closed at the moment.) {     //<!-- MY ERROR  -->
}       //<!--THIS LINE CONTINUES THE SAME ERROR -->
 </look>
<!--
NOTE: Refer to the entire code (included below) to see where to plug these into the main file's code.
-->

<look type="script">
  if (door.isopen) {
    msg ("The door is ajar.")
  }
  else {        //<!-- HK'S CORRECTION -->
    msg ("The door is closed at the moment.")        //<!-- HK'S CORRECTION (CONTINUED)-->
  }            //<!-- HK'S CORRECTION (CONTINUED) -->
</look>

(slaps forehead)

I had it correct in the example of the complete game in that very same post. (I can only successfully copy & paste one time every day, apparently. After that, I'm just too worn out!)


I'm editing the first one, just in case someone tries it before reading on down to your post.


I don't think he's/she's going to be using code (and thus my code posts probably scared him/her big time, lol), just the GUI/Editor, but it's always good to have error free code, for those who are trying to use it. People who know code: "oh, this is just a typo or syntax mistake, easy fix", but for people who don't know code, they're freaking out as the code is not working and they're seeing these frightening error messages.


HK,

I'm all about being error free! (The whole point is for the code to work!)

If you find an an errror, pont it out! (Especialy if i mispell somethintg!)

It doth not hurt my pride, for I have none!

I want the information to be correct.

NOTE: This door swings both ways, everyone. If I ever point out an error, I'm not pointing out that YOU made an error, just that there IS an error.


This message has been brought to you by the KEEP THE FORUM ERROR FREE SOCIETY and the number 37.

(filler for updating my edited post)


I'm lazy and so I just free write my code, and since I don't test it, usually it doesn't work, so please let me know about it, and I'll try to not be lazy and get it fixed up so it's working. Yes, the door goes both ways, as I need help with having my code error-free and working, too, hehe


I think you can put code on one line too, for example:

if (xxx) {
  msg ("blah")
} else { msg ("blah blah blah") }

some people like doing this, if they just have a single code line/Attribute/Script, and/or especially, if they don't have a script or whatever, if they don't have anything at all being done:

(not the best example, as with quest, you have just leave off the 'else' part entirely, but hopefully you get the idea)

if (xxx) {
  msg ("blah")
} else {}

example of putting an entire code block on one line (but this isn't often done, as it's hard to read):

if (xxx) { msg ("blah") } else { msg ("blah blah blah") }

and you may be able to put your entire code on one line (horizontal: computer-friendly code, non-human-friendly code), but obviously we humans never do this:

<asl version="550"><include ref="English.aslx" /><include ref="Core.aslx" /><game name="example_game"><gameid>XXX</gameid><version>1.0</version><firstpublished>2017</firstpublished></game><object name="room"><inherit name="editor_room" /><object name="player"><inherit name="editor_object" /><inherit name="editor_player" /></object></object></asl>

as we humans can't read it, whereas:

vertical (and line spaced especially) coding, we can read easily:

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="example_game">

    <gameid>XXX</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>

  </game>

  <object name="room">

    <inherit name="editor_room" />

    <object name="player">

      <inherit name="editor_object" />
      <inherit name="editor_player" />

    </object>

  </object>

</asl>

Hey yall, thanks so much for the replies.

hegemonkhan
you're right that I'm not using the code view and so your post was quite intimidating. I tried to read through it and follow it but I was lost almost at the beginning. I definitely got lost at the part with the orc and poison example. I understood it for the most part but don't really know how to execute it the way I want. I mostly rely on the Editor but am trying to learn how to use the code viewer but its slow going. Your links and examples will help me a bunch.

Thanks so much XanMag and Richard Headkid for your replies as well.

For my game I want a door that is closed and locked to be opened by a key, with different descriptions for the door depending on if its locked and closed or opened and the player is trying to open it again if that makes sense. So far I've figured out that I need to probably do an if script within an if script but not much else.


(filler for getting my edited post updated)


it's not easy, but it does help with making games, you can do a lot more cool stuff and do it faster.

the main thing to learn is Attribute and the 'if' Script usage ("The two super scripts"), as this enables you to do 90% of everything that you want to do in/for your game. Next is learning List/Dictionary Attributes and iteration, which gives you 9% more, and now you know 99% of everything for making a game. Thus, learning more... is very diminishing returns.

That said, learning Attributes and the 'if' Script is a huge jump for people new to coding and from the tutorial, but it's neccessary if you want to make a cool/real/serious/good game.


I threw a lot at you and it's indeed overwhelming (I was overwhelmed too back when I was learning to use quest and to code for my first time), if you're interested in learning, we'll take it a step at a time.


again, using all of the built-in stuff for opening/closing/locking/unlocking is very confusing, we have had many people making threads for help on opening/closing/locking/unlocking doors, and I myself get confused by it too, lol.


The boolean stuff isn't easy as that's Logic, and the 'logic' field of science is not an easy field. It takes time to understand.


here's some links:

(remove the dot/period from the ht.tp in the links for for the url to work for them)

ht.tps://en.wikipedia.org/wiki/Truth_table
ht.tp://www.electronics-micros.com/electronics/venn-diagrams-and-boolean-algebra/ (Venn Diagrams are great for learning/understanding the truth tables / boolean logic)
ht.tps://en.wikipedia.org/wiki/Boolean_algebra
ht.tp://philosophy.lander.edu/logic/symbolic.html (there's more pages: click on the button for going to the next page)
ht.tps://www.youtube.com/watch?v=7_LgEvKPa2s
ht.tps://www.youtube.com/watch?v=SRzSZ_rEE_A
ht.tp://courses.umass.edu/phil110-gmh/MAIN/IHome-5.htm
ht.tps://en.wikipedia.org/wiki/Logic_gate
ht.tp://www.electronics-tutorials.ws/logic/logic_2.html
ht.tp://www.electronics-tutorials.ws/logic/logic_3.html


maybe using english sentences might make more sense for you with it:

'AND' logic:

I'll give you a million dollars if you mow the lawn and clean your room
// if you just clean your room (false and true), do you get a million dollars? NO (FALSE)
// if you just mow the lawn (true and false), do you get a million dollars? NO (FALSE)
// if you do neither (false and false), do you get a million dollars? NO (FALSE)
// if you do both (true and true), do you get a million dollars? YES (TRUE)

'OR' logic:

I'll give you a million dollars if you either: mow the lawn or clean your room
// if you just clean your room (false or true), do you get a million dollars? YES (TRUE)
// if you just mow the lawn (true or false), do you get a million dollars? YES (TRUE)
// if you do neither (false or false), do you get a million dollars? NO (FALSE)
// if you do both (true or true), do you get a million dollars? YES (TRUE)


// player.sex = "male"
// player.race = "human"

if (player.sex = "male" and player.race = " human") { /* scripting * / }

string comparison checking:

(let's just say it starts from the left)

player.sex ("male") = "male"
does: ("m") = "m" ----> true
does: ("a") = "a" -----> true
does: ("l") = "l" -----> true
does: ("e") = "e" ---> true
does: player.sex = "male" ----> true

player.race ("human") = "human"
does: ("h") = "h" ----> true
does: ("u") = "u" -----> true
does: ("m") = "m" -----> true
does: ("a") = "a" ---> true
does: ("n") = "n" ---> true
does: player.race = "human" ----> true

[player.sex = "human" (true)] and [player.race = "human" (true)]
[true] and [true] ----> TRUE

if (player.sex = "male" and player.race = " human") ----> TRUE ------> do ------> { /* scripting * / }


// player.sex = "male"
// player.race = "human"

if (player.sex = "male" and player.race = " humaN") { /* scripting * / }

string comparison checking:

(let's just say it starts from the left)

player.sex ("male") = "male"
does: ("m") = "m" ----> true
does: ("a") = "a" -----> true
does: ("l") = "l" -----> true
does: ("e") = "e" ---> true
does: player.sex = "male" ----> true

player.race ("human") = "humaN"
does: ("h") = "h" ----> true
does: ("u") = "u" -----> true
does: ("m") = "m" -----> true
does: ("a") = "a" ---> true
does: ("n") = "N" ---> false // quest is case sensitive
does: player.race = "humaN" ----> false

[player.sex = "human" (true)] and [player.race = "humaN" (false)]
[true] and [false] ----> FALSE

if (player.sex = "male" and player.race = " humaN") ----> FALSE ------> SKIP OVER / do NOT do ------> { /* scripting * / }


So Boolean attributes are basically it either is or it isn't. Such as the door is either closed to allow the scripting to open the door or open and skipping that script to print a message instead or just do nothing. It's still so confusing to me even with the links you provided, although they both helped and made me more confused. The second part of the truth table really confused me but this all made me realize that I'm trying to figure out something pretty redundant, I think. Honestly I'm a bit more confused and intimidated by the codes than before.

If scripts are really nice and I got a good grasp on them from the tutorial, but I don't understand how to differentiate from how to use the And/Or in the guide nor in coding, but I get the basic gist of it. So I guess my grasp on them isn't as strong as I thought. Right now I mostly figured out how to print the message I want and unlock the exit and open the door from using one script. But It doesn't print the message I want it to have when someone tries to open the door again. It only prints the default message, "It is already open." Which isn't a big deal as its only a few words off my own custom message but it still bugs me. Is this something that can be fixed or just one of the things in Quest that just is.


Hi NinjaNin,
The only way I can think of changing the default message on the open object, would affect all open objects, not just one door.
Here's how. Under the 'tree' stuff at the left-hand side of the screen, is the word filter, with an arrow. Click that, and tick the box 'Show Library Elements', basically, everything that goes into quest, some of which the adventure writer can change.
Now, in the top 'search' box, type 'already', and click search. It will come back with a list of 9 things with 'already' in the description. These are dynamic texts, texts that you can change. Click on 'AlreadyOpen', now you will have to click 'copy' at this point to put it into your game and then you are free to change the 'AlreadyOpen' object description, but it will change all open object descriptions. The same could be done for 'AlreadyClosed' too.
Hope this helps. Writing how to do something is more complicated than doing it, by the way, so don't be put off.


(filler for updating this edit)


@ Ninja Nin:

see if this post helps... HK crosses his fingers...


in quest programming, the '=' sign has 2 different meanings:

  1. Assignment operator/operation:

HK.sex = "male"

the String Value "male" is being STORED INTO (ASSIGNED TO/INTO) the 'HK' Object's 'sex' String Attribute VARIABLE

the Value (either as a simple value or a complex expression) must be on the right side of the '=' sign

the VARIABLE (either as a Variable, Attribute, or Parameter) (which is going to be holding the Value) must be on the left side of the '=' sign

so, this would produce an error: "male" = HK.sex


having a simple value for its stored Value, examples:

HK.sex = "male"
HK.damage = 75

having a complex expression-value for its stored Value, an example:

katana.damage = 50
HK.weapon = katana
HK.strength = 50
HK.damage = HK.weapon.damage + (HK.weapon.damage * (HK.strength / 100))
// HK.damage = (50) + (50 * (50/100)) = (50) + (50 * (1/2)) = (50) + (25) = 75

katana.damage = 50
HK.weapon = katana
HK.strength = 100
HK.damage = HK.weapon.damage + (HK.weapon.damage * (HK.strength / 100))
// HK.damage = (50) + (50 * (100/100)) = (50) + (50 * 1) = (50) + (50) = 100

katana.damage = 50
HK.weapon = katana
HK.strength = 0
HK.damage = HK.weapon.damage + (HK.weapon.damage * (HK.strength / 100))
// HK.damage = (50) + (50 * (0/100)) = (50) + (50 * 0) = (50) + (0) = 50

// -------

player.alias = "HK"
player.sex = "male"
player.age_string = "adult"
player.age_integer = 18
player.race = "human"
player.class = "warrior"
player.description = player.alias + " is a " + player.age_integer + " year old " + player.age_string + " " + player.sex + " " + player.race + " " + player.class + "."
// player.description = "HK is a 18 year old adult male human warrior."
// msg (player.description)
// output:
// HK is a 18 year old adult male human warrior.

// ---------------------------------------------------------

thus, the 'Assignment' programming operator/operation is very different from:

math's 'equal to / comparison' operator/operation:

2 + 5 = 7 // no error
7 = 2 + 5 // no error

N + 5 = 7 // no error
7 = N + 5 // no error

in programming, my 'HK.sex' Attribute VARIABLE is the exact same as the 'N' VARIABLE in the math equation (the only difference is that in programming, you can hold any data type value within your VARIABLE: strings, integers/non-decimal-numbers, doubles/floats/floating-points/decimal-numbers, etc etc etc, whereas, math can only hold two data types in its VARIABLES: integers/non-decimal-numbers and doubles/floats/floating-points/decimal-numbers), for example:

programming:
HK.sex = "male"
is conceptually the same as:
math:
N = 5
// ----------
math:
N = 5
N + 2 = ???
// N + 2 = 7
// ---------
pretend math example as programming's Assignment operator/operation:
N = 5
N = N + 2
// N = 7
// as if we were actually doing a math operation:
N = N + 2
-N -N
0 = 0 + 2
0 = 2
// ---------------------
programming:

(this particular example below of adding String Values, which is known as 'concatenation', which mean literally putting things together)

HK.sex = "male"
HK.sex = HK.sex + "(blah)"
// HK.sex = male (blah)

math addition vs concatenation:

5 + 5 = 10
55 + 55 = 110
"mama" + "mia" = ERROR! human and computer: can't compute the sum of: "mama" + "mia"
"mama" + 5 = ERROR! human and computer: can't compute the sum of: "mama" + 5
"5" + 5 = ERROR! human and computer: can't compute the sum of: "5" + 5

"5" + "5" = "55"
"55" + "55" = "5555"
"mama" + "mia" = "mamamia"
"mama" + "5" = "mama5"
"mama" + " " + "mia" = "mama mia"
"mama" + " " + "5" + " " + "mia" = "mama 5 mia"

// ---------------

Programming's 'Assignment' operator/operation:

N = 5 // the 'N' VARIABLE is holding the '5' Integer Value
N = 5 + 2 // the 'N' VARIABLE is holding the '7' Integer Value

HK.sex = "male" // the 'HK.sex' Attribute VARIABLE is holding the "male" String Value
HK.sex = HK.sex + "(blah)" // the 'HK.sex' Attribute VARIABLE is holding the "male (blah)" String Value

  1. comparison / equal to operator/operation:

https://en.wikipedia.org/wiki/Arity (unary: 'not' ---- binary: 'and', 'or', '>', '<', '=>', '=<', '=')
.
.
this will help you understand this: Boolean Logic / Truth Table, stuff, inside and out (I hope, lol):
.
.

// if (EXPRESSION) { msg ("yes") } else { msg ("no") }
//
// if (EXPRESSION_IS_TRUE) { ----> msg ("yes") }
// if (EXPRESSION_IS_FALSE) { ----> } else { msg ("no") }

// --------------------------------------------------------------------------------

if (true) { msg ("yes") } else { msg ("no") }
// if (TRUE) { ---> msg ("yes") }

if (false) { msg ("yes") } else { msg ("no") }
// if (FALSE) { ---> } else { msg ("no") }

// -------------------------------------------------------------------

if (not true) { msg ("yes") } else { msg ("no") }
// if (FALSE) { ---> } else { msg ("no") }

if (not false) { msg ("yes") } else { msg ("no") }
// if (TRUE) { ---> msg ("yes") }

// ----------------------------------------------------------------

if (5 = 5) { msg ("yes") } else { msg ("no") }
// if (TRUE) { ---> msg ("yes") }

if (3 = 5) { msg ("yes") } else { msg ("no") }
// if (FALSE) { ---> } else { msg ("no") }

if (5 = 3) { msg ("yes") } else { msg ("no") }
// if (FALSE) { ---> } else { msg ("no") }

// ------------------------------------------------

if (2 + 5 = 7) { msg ("yes") } else { msg ("no") }
// if (7 = 7) {
// if (TRUE) { ---> msg ("yes") }

if (7 = 2 + 5) { msg ("yes") } else { msg ("no") }
// if (7 = 7) {
// if (TRUE) { ---> msg ("yes") }

if (1 + 2 = 7) { msg ("yes") } else { msg ("no") }
// if (3 = 7) {
// if (FALSE) { ---> } else { msg ("no") }

if (7 = 1 + 2) { msg ("yes") } else { msg ("no") }
// if (7 = 3) {
// if (FALSE) { ---> } else { msg ("no") }

// ----------------------------------------------

N = 5
if (N = 5) { msg ("yes") } else { msg ("no") }
// if (5 = 5) {
// if (TRUE) { ---> msg ("yes") }

N = 5
if (5 = N) { msg ("yes") } else { msg ("no") }
// if (5 = 5) {
// if (TRUE) { ---> msg ("yes") }

N = 5
if (N = 9) { msg ("yes") } else { msg ("no") }
// if (5 = 9) {
// if (FALSE) { ---> } else { msg ("no") }

N = 5
if (9 = N) { msg ("yes") } else { msg ("no") }
// if (9 = 5) {
// if (FALSE) { ---> } else { msg ("no") }

N = 2
if (N = 5) { msg ("yes") } else { msg ("no") }
// if (2 = 5) {
// if (FALSE) { ---> } else { msg ("no") }

N = 2
if (5 = N) { msg ("yes") } else { msg ("no") }
// if (5 = 2) {
// if (FALSE) { ---> } else { msg ("no") }

// --------------------------------

player.damage = 5
if (player.damage = 5) { msg ("yes") } else { msg ("no") }
// if (5 = 5) {
// if (TRUE) { ---> msg ("yes") }

player.damage = 5
if (5 = player.damage) { msg ("yes") } else { msg ("no") }
// if (5 = 5) {
// if (TRUE) { ---> msg ("yes") }

player.damage = 5
if (player.damage = 9) { msg ("yes") } else { msg ("no") }
// if (5 = 9) {
// if (FALSE) { ---> } else { msg ("no") }

player.damage = 5
if (9 = player.damage) { msg ("yes") } else { msg ("no") }
// if (9 = 5) {
// if (FALSE) { ---> } else { msg ("no") }

player.damage = 2
if (player.damage = 5) { msg ("yes") } else { msg ("no") }
// if (2 = 5) {
// if (FALSE) { ---> } else { msg ("no") }

player.damage = 2
if (5 = player.damage) { msg ("yes") } else { msg ("no") }
// if (5 = 2) {
// if (FALSE) { ---> } else { msg ("no") }

// -------------------

HK.sex = "male"
if (HK.sex = "male") { msg ("yes") } else { msg ("no") }
// if ("male" = "male") {
// if (TRUE) { ---> msg ("yes") }

HK.sex = "male"
if ("male" = HK.sex) { msg ("yes") } else { msg ("no") }
// if ("male" = "male") {
// if (TRUE) { ---> msg ("yes") }

HK.sex = "male"
if (HK.sex = 5) { msg ("yes") } else { msg ("no") }
// if ("male" = 5) {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = "male"
if (5 = HK.sex) { msg ("yes") } else { msg ("no") }
// if (5 = "male") {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = "male"
if (HK.sex = "female") { msg ("yes") } else { msg ("no") }
// if ("male" = "female") {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = "male"
if ("female" = HK.sex) { msg ("yes") } else { msg ("no") }
// if ("female" = "male") {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = 5
if (HK.sex = "male") { msg ("yes") } else { msg ("no") }
// if (5 = "male") {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = 5
if ("male" = HK.sex) { msg ("yes") } else { msg ("no") }
// if ("male" = 5) {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = "female"
if (HK.sex = "male") { msg ("yes") } else { msg ("no") }
// if ("female" = "male") {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = "female"
if ("male" = HK.sex) { msg ("yes") } else { msg ("no") }
// if ("male" = "female") {
// if (FALSE) { ---> } else { msg ("no") }

// ------------------

orc.dead = true
if (orc.dead) { msg ("yes") } else { msg ("no") }
// if (true) {
// if (TRUE) { ---> msg ("yes") }

orc.dead = false
if (orc.dead) { msg ("yes") } else { msg ("no") }
// if (false) {
// if (FALSE) { ---> } else { msg ("no") }

// -------------------

orc.dead = true
if (orc.dead = true) { msg ("yes") } else { msg ("no") }
// if (true = true) {
// if (TRUE) { ---> msg ("yes") }

orc.dead = true
if (orc.dead = false) { msg ("yes") } else { msg ("no") }
// if (true = false) {
// if (FALSE) { ---> } else { msg ("no") }

orc.dead = true
if (true = orc.dead) { msg ("yes") } else { msg ("no") }
// if (true = true) {
// if (TRUE) { ---> msg ("yes") }

orc.dead = true
if (false = orc.dead) { msg ("yes") } else { msg ("no") }
// if (false = true) {
// if (FALSE) { ---> } else { msg ("no") }

orc.dead = false
if (orc.dead = true) { msg ("yes") } else { msg ("no") }
// if (false = true) {
// if (FALSE) { ---> } else { msg ("no") }

orc.dead = false
if (orc.dead = false) { msg ("yes") } else { msg ("no") }
// if (false = false) {
// if (TRUE) { ---> msg ("yes") } 

orc.dead = false
if (true = orc.dead) { msg ("yes") } else { msg ("no") }
// if (true = false) {
// if (FALSE) { ---> } else { msg ("no") }

orc.dead = false
if (false = orc.dead) { msg ("yes") } else { msg ("no") }
// if (false = false) {
// if (TRUE) { ---> msg ("yes") }

// ----------------------------

orc.dead = true
if (not orc.dead) { msg ("yes") } else { msg ("no") }
// if (not true) {
// if (FALSE) { ---> } else { msg ("no") }

orc.dead = false
if (not orc.dead) { msg ("yes") } else { msg ("no") }
// if (not false) {
// if (TRUE) { ---> msg ("yes") }

// --------------------

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "male" and HK.age = "adult") { msg ("yes") } else { msg ("no") }
// if ("male" = "male" and "adult" = "adult") {
// if (true and true) {
// if (TRUE) { ---> msg ("yes") }

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "male" and HK.age = "baby") { msg ("yes") } else { msg ("no") }
// if ("male" = "male" and "adult" = "baby") {
// if (true and false) {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "female" and HK.age = "adult") { msg ("yes") } else { msg ("no") }
// if ("male" = "female" and "adult" = "adult") {
// if (false and true) {
// if (FALSE) { ---> } else { msg ("no") }

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "female" and HK.age = "baby") { msg ("yes") } else { msg ("no") }
// if ("male" = "female" and "adult" = "baby") {
// if (false and false) {
// if (FALSE) { ---> } else { msg ("no") }

// ---------------------------

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "male" or HK.age = "adult") { msg ("yes") } else { msg ("no") }
// if ("male" = "male" or "adult" = "adult") {
// if (true or true) {
// if (TRUE) { ---> msg ("yes") }

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "male" or HK.age = "baby") { msg ("yes") } else { msg ("no") }
// if ("male" = "male" or "adult" = "baby") {
// if (true or false) {
// if (TRUE) { ---> msg (yes") }

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "female" or HK.age = "adult") { msg ("yes") } else { msg ("no") }
// if ("male" = "female" or "adult" = "adult") {
// if (false or true) {
// if (TRUE) { ---> msg ("no") }

HK.sex = "male"
HK.age = "adult"
if (HK.sex = "female" and HK.age = "baby") { msg ("yes") } else { msg ("no") }
// if ("male" = "female" or "adult" = "baby") {
// if (false or false) {
// if (FALSE) { ---> } else { msg ("no") }

example of door opening/closing scripting (and logic):

// for the 'open' Verb:

if (door.isopen) { // if the door is already open: door.isopen = true
  msg ("The door is already open, silly. You can't open a door that is already opened!")
} else { // if the door is closed: door.isopen = false
  door.isopen = true // you actually set the door to now being open
  msg ("You open the door")
}

// for the 'close' Verb:

if (door.isopen) { // if the door is open: door.isopen = true
  door.isopen = false // you actually set the door to now being closed
  msg ("You open the door")
} else { // if the door is already closed: door.isopen = false
  msg ("The door is already closed, silly. You can't close a door that is already closed!")
}

a full game code of it (actual working code, aside from my all-capitolized stuff and my use of an older version of quest: v550, as that needs to be replaced with correct code, and the current engine/quest.exe: v570), example:

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="example_game">

    <gameid>SOME_RANDOMLY_GENERATED_HASH_STRING</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>

  </game>

  <object name="room">

    <inherit name="editor_room" />

  </object>

  <object name="player">

    <inherit name="editor_object" />
    <inherit name="editor_player" />

    <attr name="parent" type="object">room</attr>

  </object>

  <object name="door">

    <inherit name="editor_object" />

    <attr name="parent" type="object">room</attr>

    <attr name="isopen" type="boolean">false</attr>

    <attr name="displayverbs" type="simplestringlist">my_look; my_open; my_close</attr>

    <attr name="my_look" type="script">
      msg ("Door Current State (true:open, false:closed): " + door.isopen)
    </attr>

    <attr name="my_open" type="script">
      if (door.isopen) {
        msg ("The door is already open, silly. You can't open a door that is already opened!")
      } else {
        door.isopen = true
        msg ("You open the door")
      }
    </attr>

    <attr name="my_close" type="script">
      if (door.isopen) {
        door.isopen = false
        msg ("You open the door")
      } else {
        msg ("The door is already closed, silly. You can't close a door that is already closed!")
      }
    </attr>

  </object>

</asl>

Thanks Doctor Agon for the info. Hm so I can't just have it change for each openable/closeable item? I do have the code set up as HK says with the door.is open even in code and I set it up multiple times. I even opened a new game to try and implement it without breaking my other one but it still gives me the default message.

Can I just delete the Dynamic Template for Always open or would that break the game hard core?

Thank you HK for all that info and examples. I think I have a grasp on the logic ( hopefully ), but it also seems like one of those things where if you think on it a lot then you'll get lost because its actually very simple? So AND means there must be both prerequisites to do the script and OR means that either or the prerequisites must be there to do the scripting. So If I wanted to do an IF script to open my door with a key it would be an AND If script. something like

if (Got(key)) {
   if (door.isopen) {
     msg ("You reach to open the door before remembering it's already open.")
}
   else {
     msg ("You slide the key into the lock and turn it hearing the lock click.")
     UnlockExit (lockedtest)
     HelperOpenObject (door)
}

This would be an AND script because the door both needs to be closed and have the key on the player for the scripting to open it to run right? What would an OR script look like then. Is that the Else If scripting?

I do use the guide a lot still (Its just so neat and nice). Is there a difference on if I do it with the HelperOpenObject or by setting the attribute via code?

Anyway I have written that exactly in the code view and it's still showing the default message instead of the message I wrote at the top of the code.


(filler for getting this edited post to update / be posted, grrr)
(again, filler for getting this edited post to update / be posted, grrr)


nested (layers of) 'ifs' is the same 'and' logic as is using the 'and' logic operator:

if (bedroom.clean and lawn.mowed and dishes.washed) {
  msg ("You can go play your video games now")
} else if (bedroom.clean and lawn.mowed) {
  msg ("Sorry, but you still have to wash the dishes first, before you can play your video games")
} else if (bedroom.clean and dishes.washed) {
  msg ("Sorry, but you still have to mow the lawn first, before you can play your video games")
} else if (dishes.washed and lawn.mowed) {
  msg ("Sorry, but you still have to clean your bedroom first, before you can play your video games")
} else if (bedroom.clean) {
  msg ("Sorry, but you still have to wash the dishes and mow the lawn, first, before you can play your video games")
} else if (dishes.washed) {
  msg ("Sorry, but you still have to clean your bedroom and mow the lawn, first, before you can play your video games")
}  else if (lawn.mowed) {
  msg ("Sorry, but you still have to wash the dishes and clean your bedroom, first, before you can play your video games")
}  else {
  msg ("Sorry, but you still have to wash the dishes, mow the lawn, and clean your bedroom, first, before you can play your video games")
}

is exact the same as:

if (bedroom.clean) {
  if (lawn.mowed) {
    if (dishes.washed) {
      msg ("You can go play your video games now")
    } else {
      msg ("Sorry, but you still have to wash the dishes first, before you can play your video games")
  } else if (dishes.washed) {
    msg ("Sorry, but you still have to mow the lawn first, before you can play your video games")
  } else {
    msg ("Sorry, but you still have to wash the dishes and mow the lawn, first, before you can play your video games")
} else {
  if (dishes.washed and lawn.mowed) {
    msg ("Sorry, but you still have to clean your bedroom first, before you can play your video games")  
  } else if (dishes.washed) {
    msg ("Sorry, but you still have to clean your bedroom and mow the lawn, first, before you can play your video games")
  } else if (lawn.mowed) {
    msg ("Sorry, but you still have to wash the dishes and clean your bedroom, first, before you can play your video games")
  } else {
    msg ("Sorry, but you still have to wash the dishes, mow the lawn, and clean your bedroom, first, before you can play your video games")
  }
}

as for why you're still having issues:

let's first see if this correction of your example code, fixes it for you (if it works or not):

(try using this fixed and expanded... sorry about all the logic combinations/possibilities that I added in lol ... code of yours, and let me know if it works or not. If you're still getting error messages or not. Try it in a new game too, and make sure you actually add in all the same Objects and Attributes as you named in your code)

if (Got(key)) {
   if (door.isopen) {
     msg ("You reach to open the door before remembering it's already open.")
   } else {
     msg ("You slide the key into the lock and turn it hearing the lock click.")
     UnlockExit (lockedtest)
     HelperOpenObject (door) // this should do this for you: door.isopen = true, but maybe it doesn't, if it doesn't, then you do it:
     // door.isopen (but remove the double forward slashes in front, so this is not a comment line, but an actual code line)
} else if (door.isopen and not lockedtest.locked) {
  msg ("Since you don't currently have the key for the door, you're very very very very glad that the door, is or still remains, open (and also that the Exit, is or still remains, unlocked, too) !"
} else if (door.isopen) {
  msg ("While the door is already open, the blasted Exit (which is the real door functionality), is locked or still locked... better hope you can find the key that you don't currently have...")
} else {
  msg ("The door is closed (and also the Exit is locked), and you don't currently have the key that is needed for opening it... you hope you can find that key again...")
}

what is the default message that it is still being displayed (and what action are you doing: opening or closing the door) ???
(as this can help us in knowing or in the correct direction/focus of how to help you)

my apologies if you already mentioned what the default message was (I missed it if you did)
(but-and again, could you post the default message again for me)


if it's still not working:

(if you haven't) do a new game (so we start with the default quest code: see the 'IMPORTANT' below) and try to get it to work, which if it doesn't: post your entire game code here

IMPORTANT: if you changed the built-in stuff within the GUI/Editor (filter -> show library elements -> copy), then quest engine (its library files) is NOT messed up, but if you actually physically went into the quest folder itself and opened up its library files, changed them and saved, then your quest is messed up, and so any new game will be messed up too. (you'll have to remove quest and re-download and install it).

as now, with your game code posted, we now got something to work with, and trouble shoot for you.


to post your (entire) game code (easiest way):

simply right click on your 'xxx.aslx' game file itself, and open it with a text editor software/program (notepad, wordpad, notepad++, Apple: text editor, etc etc etc)

this is your entire game code, so highlight all of it, copy it, and then paste it here... like this:

m```
(paste your game code here)
m```

those weird characters is the key above the left TAB key and to the left of the '1' key (the rows of number keys at the top of the keyboard, not the 3x3 numbers on the right side of the keyboard if it has them). If you do SHIFT+ 'this key', you get the tilde (~) character/symbol.

but without the m's in front, which produces this:

(paste your game code here)

the reason is by putting your game code into this post's 'code box', it preserves all of the formatting, which is very important for reading and trouble-shooting your code.


(filler for getting my edited post updated/posted)


nvm... found it:

"But It doesn't print the message I want it to have when someone tries to open the door again. It only prints the default message, "It is already open." Which isn't a big deal as its only a few words off my own custom message but it still bugs me. Is this something that can be fixed or just one of the things in Quest that just is. (Ninja Nin)"

ah.... this helps a lot! This is likely due to you using the built-in stuff, and it does the default response for you.

if you find the 'default response' Template involved and altering it, it is a global change (anytime you open/close anything)

I believe to just change an individual Object's Verb's 'default response', you need to do something like this (or find out how to access/find it for a built-in Verb) ...

// creating/adding a custom Verb directly in-code:

// and being able to set the 'default response' of it !!!!

<object name="npc">
  <attr name="dialogue" type="script">
    msg ("hi")
  </attr>
</object>

<verb>
  <property>dialogue</property>
  <pattern>dialogue</pattern>
  <defaultexpression>THIS IS HOW/WHERE YOU CHANGE THE DEFAULT RESPONSE</defaultexpression>
</verb>

you may be able to get at this 'defaultexpression' String Attribute, via:

'NAME_OF_OBJECT' Object -> 'Attributes' Tab -> 'Attributes' box -> (scroll through it looking for your Verb and hopefully a control for changing its 'defaultexpression' String Attribute)

OR

'NAME_OF_OBJECT' Object -> 'Verbs' Tab -> 'Verbs' box -> (scroll through it looking for your Verb and hopefully a control for changing its 'defaultexpression' String Attribute)

ALSO, note that Verbs and Commands are linked together, so you may have to look through your Commands... trying to find your Verb and hopefully a control for changing its 'defaultexpression' String Attribute

OTHERWISE, you can go into Code View (entire game code), and see if it has/created the 'Verb' Element creation tag of your Verb, which you can then change its defaultresponse:

<verb>
  <property>NAME_OF_YOUR_VERB</property>
  <pattern>NAME_OF_YOUR_VERB</patter>
  <defaultexpression>THIS IS ITS DEFAULT EXPRESSION, WHICH YOU CAN RE-WRITE INTO THIS HERE TO CHANGE IT</defaultexpression>
</verb>

try to get Pixie's help/attention (if you have to, you can pm him), as he can guide you through doing whatever you need, as he knows this built-in quest stuff well

or... probably Richard will figure all this out and help you too, lol. He's learning to code so fast... sighs (it took me 5 years).


let's look at the logic involved:

  1. set up: room_1A, door_1A is in room_1A, exit_1A is in room_1A taking you to room_1B, room_1B, door_1B is in room_1B, exit_1B is in room_1B taking you to room_1A, you start/are in room_1A, key_1 is in room_1A

initial settings: door_1A is closed (door_1A.isopen = false), exit_1A is locked (exit_1A.locked = true), door_1B is closed (door_1B.isopen = false), exit_1B is locked (exit_1B.locked = true)

  1. you find key_1 in room_1A

  2. you try to open door_1A in room_1A

(let's just create/add a new/custom 'my_open' Verb, as the built-in 'open: open door' and/or 'use/useon: use key on door' Verbs are just un-needed more complication)

(also, the Exit's 'unlocking/unlocking' will be done through the custom 'my_open/my_close' Verbs, to keep it simple and easily controlled, no need for more complication, lol): opening is unlocking and closing is locking

(and, since our rooms are connected both ways, we need to do the same actions to both doors/exits, in order for this to work correctly and not be/get stuck in a room, lol)

  1. first, we want to 'if check' if the door_1A is open/closed (as if it's already open, the key is irrelevant):
// the 'door_1A' Object's 'my_open' Verb:

if (door_1A.isopen) { // if door_1A is open
  msg ("The door_1A is already open (and the exit_1A is already unlocked), silly")
} else { // if door is closed
  // scripting
}
  1. then, if the door_1A is closed, we need to check if you got the right key:
// the 'door_1A' Object's 'open' Verb:

if (door_1A.isopen) { // if door is open
  msg ("The door_1A is already open (and the exit_1A is already unlocked), silly")
} else { // if door_1A is closed
  if (Got (key_1)) { // if you have the correct key
    // scripting
  } else // if you do NOT have the correct key
    msg ("Sorry, but you need the right key to open up the locked door_1A.")
  }
}
  1. if you got the right key, we need to handle the opening/unlocking correctly:
// the 'door_1A' Object's 'my_open' Verb:

if (door_1A.isopen) { // if door_1A is open
  msg ("The door_1A is already open (and the exit_1A is already unlocked), silly")
} else { // if door_1A is closed
  if (Got (key_1)) { // if you have the correct key
    door_1A.isopen = true // to open the door_1A, we have to set the door_1A to actually being open
    door_1B.isopen = true // to open the door_1B, we have to set the door_1B to actually being open // we need to do both doors at the same time so we can't get stuck in a room, lol
    exit_1A.locked = false // upon opening the door_1A, we unlock the exit_1A. To unlock the exit_1A, we have to set the exit_1A to actually being unlocked
    exit_1B.locked = false // upon opening the door_1A, we unlock the exit_1B. To unlock the exit_1B, we have to set the exit_1B to actually being unlocked // we need to do both exits at the same time so we can't get stuck in a room, lol
    // now that the exit_1A is unlocked (exit_1A.locked = false), I believe you can now, go-through / use, the exit_1A to go to room_1B (again, I'm not familiar with the built-in stuff like how Exits work, lol)
  } else // if you do NOT have the correct key
    msg ("Sorry, but you need the right key to open/unlock up the closed/locked door_1A/exit_1A.")
  }
}
  1. and now we need to handle the 'my_close' Verb:
// the 'door_1A' Object's 'my_close' Verb:

if (door_1A.isopen) { // if door_1A is open
  if (Got (key_1)) { // if you have the correct key
    door_1A.isopen = false // to close the door_1A, we have to set the door_1A to actually being closed
    door_1B.isopen = false // to close the door_1B, we have to set the door_1B to actually being closed // we need to do both doors at the same time so we can't get stuck in a room, lol
    exit_1A.locked = true // upon closing the door_1A, we lock the exit_1A. To lock the exit_1A, we have to set the exit_1A to actually being locked
    exit_1B.locked = true // upon closing the door_1A, we lock the exit_1B. To lock the exit_1B, we have to set the exit_1B to actually being locked // we need to do both exits at the same time so we can't get stuck in a room, lol
    // now that the exit_1A is locked (exit_1A.locked = false), I believe you can NO longer, go-through / use, the exit_1A to go to room_1B (again, I'm not familiar with the built-in stuff like how Exits work, lol)
  } else // if you do NOT have the correct key
    msg ("Sorry, but you need the right key to close/lock the open/unlocked door_1A/exit_1A.")
  }
} else { // if door_1A is closed
  msg ("The door_1A is already closed (and the exit_1A is already locked), silly")
}
  1. now, we just do the exact same thing for the 'door_1B' Object's 'my_open' Verb
// the 'door_1B' Object's 'my_open' Verb:

if (door_1B.isopen) { // if door_1B is open
  msg ("The door_1B is already open (and the exit_1B is already unlocked), silly")
} else { // if door_1B is closed
  if (Got (key_1)) { // if you have the correct key
    door_1B.isopen = true // to open the door_1B, we have to set the door_1B to actually being open
    door_1A.isopen = true // to open the door_1A, we have to set the door_1A to actually being open // we need to do both doors at the same time so we can't get stuck in a room, lol
    exit_1B.locked = false // upon opening the door_1B, we unlock the exit_1B. To unlock the exit_1B, we have to set the exit_1B to actually being unlocked
    exit_1A.locked = false // upon opening the door_1B, we unlock the exit_1A. To unlock the exit_1A, we have to set the exit_1A to actually being unlocked // we need to do both exits at the same time so we can't get stuck in a room, lol
    // now that the exit_1B is unlocked (exit_1B.locked = false), I believe you can now, go-through / use, the exit_1B to go to room_1A (again, I'm not familiar with the built-in stuff like how Exits work, lol)
  } else // if you do NOT have the correct key
    msg ("Sorry, but you need the right key to open/unlock up the closed/locked door_1B/exit_1B.")
  }
}
  1. now, we just do the exact same thing for the 'door_1B' Object's 'my_close' Verb:
// the 'door_1B' Object's 'my_close' Verb:

if (door_1B.isopen) { // if door_1B is open
  if (Got (key_1)) { // if you have the correct key
    door_1B.isopen = false // to close the door_1B, we have to set the door_1B to actually being closed
    door_1A.isopen = false // to close the door_1A, we have to set the door_1A to actually being closed // we need to do both doors at the same time so we can't get stuck in a room, lol
    exit_1B.locked = true // upon closing the door_1B, we lock the exit_1B. To lock the exit_1B, we have to set the exit_1B to actually being locked
    exit_1A.locked = true // upon closing the door_1B, we lock the exit_1A. To lock the exit_1A, we have to set the exit_1A to actually being locked // we need to do both exits at the same time so we can't get stuck in a room, lol
    // now that the exit_1B is locked (exit_1B.locked = false), I believe you can NO longer, go-through / use, the exit_1B to go to room_1A (again, I'm not familiar with the built-in stuff like how Exits work, lol)
  } else // if you do NOT have the correct key
    msg ("Sorry, but you need the right key to close/lock the open/unlocked door_1B/exit_1B.")
  }
} else { // if door_1B is closed
  msg ("The door_1B is already closed (and the exit_1B is already locked), silly")
}

do you see how this logic design, keeps it simple and under control, and thus it works, regardless of: what room you are in, whether you have the key or not, whether the door is opened/closed, whether the exit is unlocked/locked: (no errors, no getting stuck in a room during game play) ???


I was very confused by your last post. So I just make my own open verb? I'd have to call it something else right? Or Quest will get it confused with the official open verb? I tried it out in quest but got an error message trying to do an if script in the else in the guide. I tried it out in code view and it just broke for me. I don't know what I'm doing wrong.

<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="From the Forum">
    <gameid>2a541114-7ed5-4161-a061-707e8670825e</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
  </game>
  <object name="room1A">
    <inherit name="editor_room" />
    <alias>room</alias>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit name="room1Alock" alias="east" to="room1B">
      <inherit name="eastdirection" />
      <locked />
    </exit>
    <object name="door1A">
      <inherit name="editor_object" />
      <inherit name="openable" />
      <alias>door</alias>
      <feature_container />
      <myopen type="script">
        if (door1A.isopen) {
          msg ("The door is already open (and the exit is already unlocked) silly!")
        }
        else {
        }
      </myopen>
      <openscript type="script">
        if (door1A.isopen) {
          msg ("The door is already open and unlocked silly. ")
        }
        else {
          if (Got (key_1)) {
            UnlockExit (room1Alock)
            HelperOpenObject (door1A)
            UnlockExit (room1Block)
            msg ("You unlock and open the door. ")
          }
          else {
            msg ("sorry but you need the right key to open up the locked door.")
          }
        }
      }
      </openscript>
    </object>
    <object name="key_1">
      <inherit name="editor_object" />
      <take />
      <takemsg>You pick up the key</takemsg>
    </object>
  </object>
  <object name="room1B">
    <inherit name="editor_room" />
    <exit name="room1Block" alias="west" to="room1A">
      <inherit name="westdirection" />
      <locked />
    </exit>
    <object name="door1B">
      <inherit name="editor_object" />
      <inherit name="openable" />
      <alias>door</alias>
      <feature_container />
    </object>
  </object>
  <verb name="myopen">
    <pattern>myopen</pattern>
    <property>myopen</property>
    <defaulttext>You open the door</defaulttext>
  </verb>
</asl>

Here's my game code for the example that you set. I looked into it a bit and apparently dynamic templates, which is what the open script uses is different from a regular one, as in it's used with all open objects and can change dynamically depending on the objects gender and stuff. I can change the dynamic template and have found it already but I still want to try and do my own custom template if I can. Would Pixie or Richard mind if I shoot them a note?

A dumb question as well but do you need to code something in order? Like if I start writing my verbs first will it sort itself out or will it break the whole game?

Another question, What does an OR script look like then? Or can there only be AND scripts?


let me (not be my usual lazy-bum self and) test out my code saturday/tomarrow (its almost friday midnight here, need to sleep, lol), and get back to you on it (sometime saturday/tormarrow), as I likely made/have some stupid mistake/typo (90% of the time, an error in code, is some stupid small mistake/typo, the problem is finding it, lol), as that way, you'll have a working model/code, that you can take a look at in the GUI/Editor and play as a demo game, which is more familiar and recognizable/understandable, so you can see how the stuff is done and how it looks.


don't worry about my code, I'm throwing full coding at you, this stuff took myself 5 years to learn, it's not easy to pick up right away, it takes time to learn and understand how code work and how to read it. As you really got to train your brain in the logic and mindset/thinking required for coding, and its not natural, so it takes time to train your brain in it and learn/understand coding.


when I provide you the working copy tomorrow, you can study it in the GUI/Editor, which will be much more clear for you.

(once you learn to code, it's hard to not throw code at people, as it's much faster and easier to write/type/code than it is to try to do a step by step guide through using the GUI/Editor's script options and etc, so my apologies for scaring you with all of my code I've been throwing at you)


about your other questions:

  1. yes, you can create/add your own Verbs (and anything/everything else too, lol), and/or use the built-in Verbs (and all the other stuff too).

Some of the built-in Verbs (or whatever else) have their own scripting.

Some of the built-in Verbs have no scripting, as it is waiting for your scripting as its the type of stuff that you'd have to put in what you want (for example: 'talk/speak' Verb, it can be anything, its fully for you to customize/determine, so there's no set scripting obviously).

Also, there's a lot of "under the hood coding" that enables those Verbs (or whatever) to do their functionality.

For the Verbs that are for you to put in what scripting you want, they'll work as they were made to work for whatever you want put into them.

However, there's also some Verbs that do have set scripting which the "under the hood coding" needs for it to do its functionality, and if you over-ride/over-write it, you thus wipe out its "under the hood functionality" for it to work, as it needed that set scripting that you over-wrote/over-ridden.

  1. yes, in quest the 'name' (the 'name' String Attribute) is the ID, and so, all names MUST be unique, for example:
<object name="ball">
</object>

<object name="ball">
</object>

this will cause an error (or possibly quest will ask you to choose/specify which one you meant).

just as I and only I have my DNA/genetic-code, just as you and only you have your DNA/genetic-code, just as "that person/organism" has its DNA/genetic-code (and nothing else does, it and only it has that DNA/genetic-code). DNA/genetic-code is an organism's 'ID' in the real world. For quest, the 'name' String Attribute is it's ID.

whereas, many people can have the name of 'Mike', a person's name is NOT their ID (usually it works, so long as you're the only 'Mike' in the target group, but that's NOT the definition of 'ID', as identification is 100% and only 100%, else it's not identification)

a person's name in the real world is equivalent to quest's built-in 'alias' String Attribute, as really quest does NOT care one bit about what you type in for its Object's 'alias' String Attribute. Quest only cares about what you type in for its 'name' String Attribute. No two 'names' can be the same (not technically an exception, but Attributes can have the same name when they're contained within different Objects, but you can't have two Attributes with the same 'name' within the same Object: every Object can have an 'alias' String Attribute, but an Object can't have two 'alias' Attributes. The technicality of why this is not breaking the uniqueness rule of the 'name' String Attribute as the ID: an Attribute's actual full name and thus ID, is: NAME_OF_OBJECT.NAME_OF_ATTRIBUTE, so for example: Joe.alias = "joe" and John.alias = "john" isn't breaking the ID rule: Joe.alias is NOT equal to John.alias, and this is thus not breaking the rule either: Joe.alias = "joe" and Joe.alias_2 = "joe")

if you create/add anything with the same name (in the same location/scope) as something that already exists, that's how you 'over-ride/over-write' it.


I personally don't know the built-in stuff that well, and so i create a lot of custom stuff, and so I have to be careful in my own naming/labeling scheme/convention/system, not to accidentally use a name/label that is already in use, as I don't want to over-ride/over-write something that involves the "under the hood coding" which gives that built-in functionality to me, as I'm not good enough to recreate/re-code in that same "under the hood coding", as it can be really complex/advanced stuff (and/or requires lots of coding knowledge to know how quest works, which unfortunately few people have, and so that's why quest v6.0/QuestKit won't be happening any time soon, as unfortunately, Alex (and possibly co) created quest using a bunch of different and very wide-ranging programming languages, which he had the knowledge and skill of/with, but so far no one else has come along knowing all the stuff that went into creating quest. Some of the "under the hood / built-in stuff" isn't that messy/deep (which can be easily adjusted/changed), but then there's the messy/deep stuff that I was just talking about, which isn't so easy to change/alter.

  1. the 'Templates' allows you to be able to change the messaging/prompts to whatever you want (the big purpose is for human language conversions of quest: european english~american english~chinese~german~french~japanese~russian~indian~etc etc etc, but can be used for individual game makers and their games too, for what the want the default repsonses or whatever to be as the responses you want them as being), but I do believe they're global changes.

However, I know you can somehow do it locally (maybe... you just got to over-ride/over-write them: create/add into/for a specific Object), but I've just not gotten into learning how Templates work yet, sighs. Pixie can help you with them (and has guides already done too, which maybe you can follow, as Pixie is great at explaining/guiding, whereas I'm not, as can be seen, laughs)

  1. definately, go ahead and pm Pixie and/or Richard (not sure if Richard knows how Templates work yet, but he can probably research them and be an expert on them in no time: he's learning to code so quickly), but Pixie can certainly help, he knows quest quite well, as he's continuing to develop quest (just not the all the stuff that's needed for converting it into fully using JS:v6.0/QuestKit so that it can run on any platform, as Pixie just doesn't know all of that stuff/programming languages and etc stuff involved in quest's creation, not yet anyways, but it'll take him time... as he's probably already super busy between real life and just developing quest further. He just posted that it'd likely take at least 5 years to learn how to convert quest into fully using JS, that's how messy quest's creation is, lots of programming languages to learn and how to use them together, not easy to learn)

  2. "order of operations" matter as much in programming as it does in mathematics: vitally so!

now, placement in code vertically doesn't matter, so long as you're keeping the nesting/indenting/containment/parent-child heirarchy (think of literally like the folders on your computer, quest's code structure is exactly the same as that) intact/correct, with the exception of the 'include ref' library file references, Delegates, and maybe also the special 'game' Game Settings Object.

let me try to explain this stuff... (I'll probably just continue to confuse you, laughs, but I've already done that, so no harm in confusing you more, laughs, right?)


in quest, the GAME OBJECT is the 'asl' tag

these 'tag' lines/blocks are the "actual physical things that exist" within your game/game-file and/or library-file.

these tags, these "actual physical things that exist" are known as 'Elements'. The (normal) Elements are: Objects, Exits, Verbs, Commands, Functions, Turnscripts, Timers, and Object Types / Types

Attributes are a bit weird, as they're kind of a hybrid between an Element and scripting. Attributes are/have tags, but they HAVE TO BE CONTAINED WITHIN an (NON-Attribute) Element: Objects, Exits, Verbs, Commands, Functions, Turnscripts, Timers, and Object Types / Types, yet they (Script Attributes) can hold scripting too, like some Elements can. So, they kinda are Elements but also are kinda not Elements. Attributes are hard for me to explain.

anything without the 'tag' lines/blocks is either: scripting (actions) or comments (for us humans to read, to know what's going on or whatever, documentation for us humans: comments are NOT code used by quest)

to do comments:

(these can't be wrongly put inside of stuff/tags, as that'll cause a syntax error)

// THIS IS MY COMMENT LINE: kljdqslkjdlqsjdlqksjdlkqsjd fjkljflksdjfkldsjflkjsdlfkdslkfjdsklfjdlskjfldskjflkdsjflkdsjflkdsjflkdsjfldkjflkdwjfldkwjflwdkjfldwkjfldkwjfdlwkjfldkwjflkdwjflkdwjflkdwjflkdwjflkwdjflkdwjflkwdjflkdwjflkdwjflkdwjflkwdjflkwjfl
// THIS IS ANOTHER COMMENT LINE:  kljlskjlksjdlkqsj jkasldkjaslkdjalkjdlkasjdlkasjdlksajdlkslkdsqlkdhlskqhdlksqhdlskqjdlksqjdlkjsqlkdjsqlkjdlqskjdlksqjdlkqsjdlkqsjdlkqsjdlkqsjdlkqsjdlkqsjd

or:

<!--
THIS IS A COMMENT BLOCK:

sdkjwlfjdlwkfjlwdkjfkljflksjlksqjdlksqjdlksqjdlksqjdlkjqslkdjqslkjdfklwhjlkshfjvbjkwbdklsndlksqjdlkqsjdlkqsjdlkqsjdlkjqslkdjsqlkdjslkqjdlksq

slkjlkfjlkjdlsqk
-->

for the 'xxx.aslx' game file:

this is the GAME OBJECT:

<asl> // beginning 'asl' tag (like the start of a sentence:code-line or the start of a paragraph:code-block)
  // mass of game code/content: EVERYTHING MUST GO BETWEEN/WITHIN these 'asl' tags (except for comments)
</asl> // ending 'asl' tag

// comments: blah blah blah

<!--
comments: blah blah blah
-->

and, if you want to made a 'xxx.aslx' library file:

this is the LIBRARY OBJECT:

<library>
  // mass of code/content: EVERYTHING MUST GO BETWEEN/WITHIN these 'library' tags (except for comments) 
</library>

(back to the game file)

now, you HAVE TO put in the version number into the beginning 'asl' tag (this is known as its 'signature/header': holds special types of Attributes):

<asl version="570"> // v570 is the most recent version (or is it v580, meh) Pixie just released publically
</asl>

I'm still using an older version: quest (quest.exe) v550, so I have to tell quest so:

<asl version="550">
</asl>

to know your quest version:

open up into the GUI/Editor, and in the menu bar at the top, under the 'help' (or is there directly an 'about' menu option? I don't have quest open at the moment and can't remember, lol), click on 'about', and you'll see its version, for a pretend example:

quest version: 5.7.6.398234802380832

you completely ignore the decimal number (after the 3rd digit: for the example above: x.x.x.398234802380832)

you also completely ignore the '1s column/digit', AS IT IS ALWAYS TO BE: 0 (zero), so in the example it would be the: x.x.6, that is ignored, and instead it is this: X.X.0)

and that's your 3 digit version (570) for putting into the beginning 'asl' tag:

<asl version="570">
</asl>

now, next MUST BE the default (or custom) ENGINE library files (quest is really powerful, as literally its engine comes from its library files, which if you're a good programmer and you know quest well, you can create your own totally different engine library files, making whatever engine you want for quest, though probably there's some limits on the engine... lol. I don't think you could make a 3D world engine... but maybe... though I don't think that'd be possible.... I don't think... lol):

the language library file goes FIRST:ABOVE, and then goes next (BELOW) the ENGINE library file(s)

<asl version="570">

  <include ref="English.aslx" /> // for english speakers quest.exe download // also note that this is a tag line (horizonal) (and not the usual tag block: vertical), and for this type of tag line, it's correct syntax is this: <include ref="NAME_OF_LIBRARY_FILE.aslx" /> // not sure if the language library files are also 'hubs' to individual language library files like the 'core.aslx' library file is below.

  <include ref="Core.aslx" /> // this is actually a 'hub' library file (though it may also have/hold some coding too), with lots of its own 'include ref' to all of the individual 'core' engine library files (can be seen within the quest folder itself, but do NOT mess with them: you can open them up and look at them BUT do NOT: change them and then save it, unless you want to have to delete quest and re-download and re-install it, lol)
  
</asl>

next, if you're using Delegates (don't worry about these, as they're a bit more advanced stuff), here's a good place to put them (to be safe), an example of one of mine (for an Object's Script Attribute that will have the scripting for it, I'll show it when I get past this required vertical ordering of stuff):

<asl version="570">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <delegate name="critical_hit_delegate" parameters="name_of_object_dot_name_of_attribute" type="int" />

</asl>

lastly, just to be safe, next should be the special (and required) 'game' Game Settings Object:

<asl version="570">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <delegate name="critical_hit_delegate" parameters="name_of_object_dot_name_of_attribute" type="int" />

  <game name="example_game">

    // these three tags (gameid, version, firstpublished) are Attributes (I'm not sure if they're all String Attributes or not, so I'm just writing/coding them as they appear by default format/syntax by quest):

    <gameid>SOME RANDOMLY GENERATED HASH STRING MAINLY AS ID FOR THE ONLINE SERVERS BUT IT MIGHT STILL BE REQUIRED FOR OFFLINE USAGE TOO</gameid> // default new game code
    <version>1.0</version> // default new game code
    <firstpublished>2017</firstpublished>  // default new game code

  </game>

</asl>

do note (EXTREMELY IMPORTANT) the indenting/nesting:

  1. there's NO indenting (NO/ZERO indenting units) in front of the 'asl' tags
  2. there's only 1 indenting unit (an indenting "uni"t is conventionally: 2 individual white-spaces:SPACEBAR-key or 1 tab-space:TAB-key) in front of the Element (non-Attribute) Tags: 'include ref', 'delegate', and 'game' tags
  3. the Attribute tags MUST be within an Element, and thus they must be indenting another unit BEYOND (to the right) of its parent Element tag

and now (after:below the special 'game' Game Settings Object) , the vertical ordering does not matter at all (aside from the ending 'asl' tag, as all of this stuff has to be contained within the 'asl' tag block, aka, the GAME OBJECT), though you do got to have the proper/correct indenting/nesting and placement, as that always matters:

<asl version="570">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <delegate name="critical_hit_delegate" parameters="name_of_object_dot_name_of_attribute" type="int" />

  <game name="example_game">

    <gameid>SOME RANDOMLY GENERATED HASH STRING MAINLY AS ID FOR THE ONLINE SERVERS BUT IT MIGHT STILL BE REQUIRED FOR OFFLINE USAGE TOO</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>

  </game>

  <object name="room">

    <inherit name="editor_room" />

    <object name="player">

      <inherit name="editor_object" />
      <inherit name="editor_player" />

      <attr name="damage" type="int">100</attr>
      <attr name="current_life" type="int">999</attr>
      <attr name="maximum_life" type="int">999</attr>
      <attr name="life" type="string">999/999</attr>
      <attr name="speed" type="int">100</attr>
      <attr name="luck" type="int">75</attr>

      <attr name="changedcurrent_life" type="script">
        <![ CDATA[
          if (this.current_life > this.maximum_life) {
            this.current_life = this.maximum_life
          } else if (this.current_life < 1) {
            msg ("You died or were killed")
            msg ("GAME OVER")
            finish
          }
          this.life = this.current_life + "/" + this.maximum_life
        ]]>
      </attr>

      <attr name="changedmaximum_life" type="script">
        <![ CDATA[
          if (this.current_life > this.maximum_life) {
            this.current_life = this.maximum_life
          }
          this.life = this.current_life + "/" + this.maximum_life
        ]]>
      </attr>

      <attr name="statusattributes" type="simplestringdictionary">life = Life: !; damage = Damage: !; speed = Speed: !; Luck: !</attr>

    </object>

  </object>

  <object name="orc_1">

    <inherit name="editor_object" /> // this is a built-in Inherited Attribute (see Object Types / Types: this is more advanced stuff) // these specific 'editor_XXX' Inherited Attributes are destroyed at game start (so don't have any code that uses them for your during game play stuff), as they're just for giving the GUI/Editor its controls/options/Tabs/drop-down-boxes/text-boxes/check-in-boxes/etc for you to use in/with/for your using of the GUI/Editor
    
    //  these are some built-in Attributes (I'm using a different syntax/format/form of writing/typing/coding them in: long/full form/syntax/format):

    <attr name="parent" type="object">room</attr> // this 'parent' Object (reference/pointer) Attribute, is what actually controls/determines containment/parent-child heirarcy (though for some situations, it's defaulted to not be shown by quest)
    <attr name="alias" type="string">orc</attr>

    // these are custom (my own) (some of the normal Attribute Types) Attributes (I'm using a different syntax/format/form of writing/typing/coding them in: long/full form/syntax/format):

    <attr name="dead" type="boolean">false</attr>
    <attr name="damage" type="int">50</attr>
    <attr name="current_life" type="int">999</attr>
    <attr name="maximum_life" type="int">999</attr>
    <attr name="life" type="string">Life: 999/999</attr>
    <attr name="currency" type="int">200</attr>
    <attr name="experience" type="int">300</attr>
    <attr name="speed" type="int">0</attr>
    <attr name="luck" type="int">25</attr>

    // the special 'changedNAME_OF_ATTRIBUTE' Script Attribute (this is a bit advanced though):

    <attr name="changedcurrent_life" type="script">
      <![CDATA [
        if (this.current_life > this.maximum_life) {
          this.current_life = this.maximum_life
        } else if (this.current_life < 1) {
          this.current_life = 0
          this.dead = true
        }
        this.life = this.current_life + "/" + this.maximum_life
      ]]>
    </attr>

    <attr name="changedmaximum_life" type="script">
      <![CDATA [
        if (this.current_life > this.maximum_life) {
          this.current_life = this.maximum_life
        }
        this.life = this.current_life + "/" + this.maximum_life
      ]]>
    </attr>

    // a normal Script Attribute (and also is a Verb due to its extra coding I'll give to it: find/see the 'attack' Verb tag block):

    <attr name="attack" type="script">
      <![CDATA[
        if (this.dead) { // if orc is dead
          firsttime {
            player.current_currency = player.current_currency + this.currency
            player.current_experience = player.current_experience + this.experience
            msg ("You loot the dead " + this.alias + "'s corpse")
          } otherwise {
            msg ("The " + this.alias + " is already dead, and its corpse already looted, silly.")
          }
        } else { // if orc is alive
          you_go_first_boolean_variable = false // initially set for the orc going first (unless this is changed to 'true', the orc WILL go first. But if it's changed to 'true', then you WILL go first)
          if (player.speed > this.speed) { // you go first
            you_go_first_boolean_variable = true
          } else if (player.speed = this.speed and RandomChance (50)) { // if tied in speed (player.speed = this.speed), "flip a coin" (50% chance of you going first)
            you_go_first_boolean_variable = true
          } // end of speed/who-goes-first 'if check'

          if (you_go_first_boolean_variable) { // you go first
            msg (UCase (this.alias) + "'s Life: " + this.life)
            this.current_life = this.current_life - (player.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", player.luck))
            msg ("You damage the " + this.alias + " for " + player.damage + " damage")
            if (this.current_life < 1) { // if you killed the orc
              this.dead = true // setting the orc to actually being dead, lol
              msg ("You killed the " + this.alias +"!")
            } else { // the orc is still alive, and now it's the orc's turn to attack/damage you
              msg ("The " + this.alias + " has " + this.life + " life remaining")
              msg ("Your (Player's) Life: " + player.life)
              player.current_life = player.current_life - (this.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", this.luck))
              msg ("The " + this.alias + " damages you for " + this.damage + " damage)
              // if your current life is less than 1, you're dead and the game is over (this is handled by the 'player' Player Object's special 'changedcurrent_life" Script Attribute)
              // otherwise, you're still alive (and so is the orc), so the combat round is over, and we keep doing combat rounds (looping) until one of you is dead:
              do (this, "attack") // looping (doing another combat round) until one of you is dead
            }
          } else { // the orc goes first
            msg ("Your (Player's) Life: " + player.life)
            player.current_life = player.current life - (this.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", this.luck))
            msg ("The " + this.alias + " damages you for " + this.damage + " damage")
            // if your current life is less than 1, you're dead and the game is over (this is handled by the 'player' Player Object's special 'changedcurrent_life" Script Attribute)
            // otherwise, you're still alive (and so is the orc), and so now it's your turn:
            msg ("Your (Player's) Life: " + player.life)
            msg (UCase (this.alias) + "'s Life: " + this.life)
            this.current_life = this.current_life - (player.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", player.luck))
            msg ("You damage the " + this.alias + " for " + player.damage + " damage")
            if (this.current_life < 1) { // if you killed the orc
              this.dead = true // setting the orc to actually being dead, lol
              msg ("You killed the " + this.alias +"!")
            } else { // the orc is still alive (and so are you), so another combat round (looping), until one of you is dead
              do (this, "attack") // looping (doing another combat round) until one of you is dead
            }
          }
        }
      ]]>
    </attr>
    
  </object>

  <object name="global_data_object">

    <inherit name="editor_object" />

    <attr name="critical_hit_script_attribute" type="critical_hit_delegate">
      if (RandomChance (name_of_object_dot_name_of_attribute)) {
        return (2)
      } else {
        return (1)
      }
    </attr>

  </object>

  <verb>
    <property>attack</property>
    <pattern>attack</pattern>
    <defaultexpression>You can't attack that!</defaultexpression>
  </verb>

</asl>

vs (different vertical ordering, but still correct/proper indenting/nesting and placement: NO errors)

<asl version="570">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <delegate name="critical_hit_delegate" parameters="name_of_object_dot_name_of_attribute" type="int" />

  <game name="example_game">

    <gameid>SOME RANDOMLY GENERATED HASH STRING MAINLY AS ID FOR THE ONLINE SERVERS BUT IT MIGHT STILL BE REQUIRED FOR OFFLINE USAGE TOO</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>

  </game>

  <verb>
    <property>attack</property>
    <pattern>attack</pattern>
    <defaultexpression>You can't attack that!</defaultexpression>
  </verb>

  <object name="global_data_object">

    <inherit name="editor_object" />

    <attr name="critical_hit_script_attribute" type="critical_hit_delegate">
      if (RandomChance (name_of_object_dot_name_of_attribute)) {
        return (2)
      } else {
        return (1)
      }
    </attr>

  </object>

  <object name="player">

    <inherit name="editor_object" />
    <inherit name="editor_player" />

    <attr name="parent" type="object">room</attr>

    <attr name="statusattributes" type="simplestringdictionary">life = Life: !; damage = Damage: !; speed = Speed: !; Luck: !</attr>

    <attr name="changedcurrent_life" type="script">
      <![ CDATA[
        if (this.current_life > this.maximum_life) {
          this.current_life = this.maximum_life
        } else if (this.current_life < 1) {
          msg ("You died or were killed")
          msg ("GAME OVER")
          finish
        }
        this.life = this.current_life + "/" + this.maximum_life
      ]]>
    </attr>

    <attr name="changedmaximum_life" type="script">
      <![ CDATA[
        if (this.current_life > this.maximum_life) {
          this.current_life = this.maximum_life
        }
        this.life = this.current_life + "/" + this.maximum_life
      ]]>
    </attr>

    <attr name="damage" type="int">100</attr>
    <attr name="current_life" type="int">999</attr>
    <attr name="maximum_life" type="int">999</attr>
    <attr name="life" type="string">999/999</attr>
    <attr name="speed" type="int">100</attr>
    <attr name="luck" type="int">75</attr>

  </object>

  <object name="orc_1">

    <inherit name="editor_object" />

    <attr name="changedcurrent_life" type="script">
      <![CDATA [
        if (this.current_life > this.maximum_life) {
          this.current_life = this.maximum_life
        } else if (this.current_life < 1) {
          this.current_life = 0
          this.dead = true
        }
        this.life = this.current_life + "/" + this.maximum_life
      ]]>
    </attr>

    <attr name="changedmaximum_life" type="script">
      <![CDATA [
        if (this.current_life > this.maximum_life) {
          this.current_life = this.maximum_life
        }
        this.life = this.current_life + "/" + this.maximum_life
      ]]>
    </attr>

    <attr name="attack" type="script">
      <![CDATA[
        if (this.dead) { // if orc is dead
          firsttime {
            player.current_currency = player.current_currency + this.currency
            player.current_experience = player.current_experience + this.experience
            msg ("You loot the dead " + this.alias + "'s corpse")
          } otherwise {
            msg ("The " + this.alias + " is already dead, and its corpse already looted, silly.")
          }
        } else { // if orc is alive
          you_go_first_boolean_variable = false // initially set for the orc going first (unless this is changed to 'true', the orc WILL go first. But if it's changed to 'true', then you WILL go first)
          if (player.speed > this.speed) { // you go first
            you_go_first_boolean_variable = true
          } else if (player.speed = this.speed and RandomChance (50)) { // if tied in speed (player.speed = this.speed), "flip a coin" (50% chance of you going first)
            you_go_first_boolean_variable = true
          } // end of speed/who-goes-first 'if check'

          if (you_go_first_boolean_variable) { // you go first
            msg (UCase (this.alias) + "'s Life: " + this.life)
            this.current_life = this.current_life - (player.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", player.luck))
            msg ("You damage the " + this.alias + " for " + player.damage + " damage")
            if (this.current_life < 1) { // if you killed the orc
              this.dead = true // setting the orc to actually being dead, lol
              msg ("You killed the " + this.alias +"!")
            } else { // the orc is still alive, and now it's the orc's turn to attack/damage you
              msg ("The " + this.alias + " has " + this.life + " life remaining")
              msg ("Your (Player's) Life: " + player.life)
              player.current_life = player.current_life - (this.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", this.luck))
              msg ("The " + this.alias + " damages you for " + this.damage + " damage)
              // if your current life is less than 1, you're dead and the game is over (this is handled by the 'player' Player Object's special 'changedcurrent_life" Script Attribute)
              // otherwise, you're still alive (and so is the orc), so the combat round is over, and we keep doing combat rounds (looping) until one of you is dead:
              do (this, "attack") // looping (doing another combat round) until one of you is dead
            }
          } else { // the orc goes first
            msg ("Your (Player's) Life: " + player.life)
            player.current_life = player.current life - (this.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", this.luck))
            msg ("The " + this.alias + " damages you for " + this.damage + " damage")
            // if your current life is less than 1, you're dead and the game is over (this is handled by the 'player' Player Object's special 'changedcurrent_life" Script Attribute)
            // otherwise, you're still alive (and so is the orc), and so now it's your turn:
            msg ("Your (Player's) Life: " + player.life)
            msg (UCase (this.alias) + "'s Life: " + this.life)
            this.current_life = this.current_life - (player.damage * RunDelegateFunction (global_data_object, "critical_hit_script_attribute", player.luck))
            msg ("You damage the " + this.alias + " for " + player.damage + " damage")
            if (this.current_life < 1) { // if you killed the orc
              this.dead = true // setting the orc to actually being dead, lol
              msg ("You killed the " + this.alias +"!")
            } else { // the orc is still alive (and so are you), so another combat round (looping), until one of you is dead
              do (this, "attack") // looping (doing another combat round) until one of you is dead
            }
          }
        }
      ]]>
    </attr>

    <attr name="parent" type="object">room</attr>
    <attr name="alias" type="string">orc</attr>

    <attr name="dead" type="boolean">false</attr>
    <attr name="damage" type="int">50</attr>
    <attr name="current_life" type="int">999</attr>
    <attr name="maximum_life" type="int">999</attr>
    <attr name="life" type="string">Life: 999/999</attr>
    <attr name="currency" type="int">200</attr>
    <attr name="experience" type="int">300</attr>
    <attr name="speed" type="int">0</attr>
    <attr name="luck" type="int">25</attr>
    
  </object>

  <object name="room">

    <inherit name="editor_room" />

  </object>

</asl>

That would help loads thank you so much! I've actually learned a lot just looking at the code you've provided and the code view as well, so no worries with throwing this code right at me. It's confusing but really interesting.

How do you remember how many spaces to put and what pattern to use?


just edited my previous post (sorry about that, so if you don't mind, refresh and take a look at it), lots of code for you to look at (laughs... I try to explain it for you... regardless of whether you actually want to learn to code or not, laughs), so take a look and see if it makes some sense, or let me know if I just confused you even more, and I'll just get around to getting that code model working for you to try out. (I still haven't slept yet... need to get my sleep first... then I'll get that code working for you to try out)


if you want to learn to code:

looking at other people's code is the best way to learn! (once you know/learn how to read/understand code, of course. You got to first learn/know code, before you can study other people's code, as otherwise, it's just a bunch of very very scary gibberish).

it's like in math: imagine NEVER seeing each of the steps (and with explanations of those steps: I hate that they just assume you understand what's going on in the step, lol --- I HATE math, by the way, lol) to the final solution/answer of how to do some math problem you're stuck on/with, and/or even worse, imagine NEVER seeing how to do an entire field of math, you have to discover that field all by yourself! That's what it's like with programming when you don't get to see example code, and the professor just gives you a program to write, and you got to figure out how to do it, with never seeing how to do the program... you got to completely all on your own figure out how to do the program... it's really awesome (huge rush) when you do, and regardless of whether you do or not, you also usually learn a lot, but it also really sucks if you spend an entire week up nearly 24/7 trying to get the program done, and you fail to do so, getting an F grade on that project/program... sighs... Some programming professors are like this, and some are more helpful, letting you see some example code, and then some give you the code/program, and you practice and learn/memorize it, and then you're tested on it: you got to create/write/code the program in class as an exam/test.


that said, code is IP (intellectual property), so stealing/vandalizing/etc it outside of educational legally-protected uses and/or getting the owner's recorded permission, is a crime of course. But, if no one ever saw any code, there'd be very few people who can program/code in the world.

Imagine if calculus, trigonometry, geometry, algebra, etc was copyrighted/patented/trademarked... BAD BAD BAD BAD BAD, lol


containment/parent-child heirarchies:

C:/ // drive
-> Programs // folder
->-> Quest 5 // folder
->->-> (various more folders and/or quest library files)

grandfather
-> father
->-> son
->->> grandson

HK
-> pants
->-> wallet
->->-> $1
->->-> $5
-> shirt
->-> pen
JOE
-> jeans
->-> pennies
-> t-shirt

multiverse (ours)
-> universe (ours)
->-> galaxy cluster (ours)
->->-> galaxy (ours, which we call the "milky way", a spiral galaxy, we're on one of its two "tendrils/arms", maybe 3/5 to the tip of it --- but not certain of our exact location/distance on the tendril/arm to the tip of it)
->->->-> star (ours, which we call "the sun", most stars are binary: two stars next to each other, we've obiously got a single/unary star)
->->->->-> planet (ours, which we call "earth")

<asl version="570">
  <object name="A1">
    <attr name="BB1" type="string">BB1</attr>
    <object name="B1">
      <attr name="CC1" type="string">CC1</attr>
      <object name="C1">
        <attr name="DD1" type="string">DD1</attr>
      </object>
    </object>
    <object name="B2">
    </object>
  </object>
  <object name="A2">
    <attr name="BB2" type="string">BB2</attr>
  </object>
</asl>

grandfather
-> father
->-> son
->->-> grandson

'grandfather' is the main ("root") parent of 'father', 'son', and 'grandson'
'grandfather' is the direct parent of 'father'
'grandfather' is the indirect parent of 'son' and 'grandson'

'father' is the direct child of 'grandfather'
'father' is the direct parent of 'son'
'father' is the indirect parent of 'grandson'

'son' is the indirect child of 'grandfather'
'son' is the direct child of 'father'
'son' is the direct parent of 'grandson'

'grandson' is the indirect child of 'grandfather' and 'father'
'grandson' is the direct child of 'son'

as scripting code:

grandfather.parent = null // 'null' (at least in this specific usage of it: as the value for a 'parent' Object reference/pointer Attribute) means that the 'asl' GAME OBJECT is it's direct parent: it's NOT contained within anything else, it's ONLY contained within the 'asl' GAME OBJECT
father.parent = grandfather
son.parent = father
grandson.parent = son

as tag code:

// nested:

// (when nested, quest defaults to hide (not show) its 'parent' Object (reference/pointer) Attribute
// (quest also defaults to hide (not show) its 'parent' Object Attribute (reference/pointer) Attribute when its 'null' (when ONLY the 'asl' GAME OBJECT is it's parent)

<asl version="570">
  <object name="grandfather">
    <object name="father">
      <object name="son">
        <object name="grandson">
        </object>
      </object>
    </object>
  </object>
</asl>

// not using nesting:

<asl version="570">

  <object name="grandfather">
    // again, quest defaults to hide its 'parent' Object (reference/pointer) Attribute, when it's 'null' (when the 'asl' GAME OBJECT is it's only parent)
  </object>

  <object name="father">
    <attr name="parent" type="object">grandfather</attr>
  </object>

  <object name="son">
    <attr name="parent" type="object">father</attr>
  </object>

  <object name="grandson">
    <attr name="parent" type="object">son</attr>
  </object>

</asl>

and what if we manipulate/change/alter the values of the 'parent' Object (reference/pointer) Attribute ??? (see below)

grandson.parent = null
son.parent = grandson
father.parent = son
grandfather.parent = father

grandson
-> son
->-> father
->->-> grandfather


grandson.parent = son
son.parent = null
father.parent = son
grandfather.parent = son

son
-> grandfather
-> father
-> grandson


Thank you so much for the helpful code! I'm actually signed up for a class on coding in C++, so this is actually very helpful (hopefully) for it.

I'll send Pixie and Richard a PM whenever I can and hopefully they can help me as well. You've been an amazing help and your code is very long and almost a bit intimidating. Do I need to remove the // from the code or can they just stay in there?

Does it really matter what version of Quest I have for most people? Or is it usually just little updates that Pixie does? Is it easy to update if I need to?


if you need any help in C++, let me know, I'd be glad to help you with it.


you can leave the comment lines/blocks in or remove them, it doesn't make any difference. The comment lines/blocks are for humans (you and/or others) looking at your code.


I think... (Pixie can correct me) that actually there was no change to the engine from v550 to v570: meaning that v550 will work with v570, but that hasn't always been the case. It just depends whether a new version alters the engine, or if it's just some additional content/features/coding being added.

you can see quest's version history here: http://docs.textadventures.co.uk/quest/upgrade_notes.html

and also Pixie's github page has the version history for his quest development (taking over as the new quest team member, as Alex needed to move on with his life: he's been developing quest for 20 years! https://blog.textadventures.co.uk/ --- read quite a good bit of the entries down until you get to the 'squiffy 5' section)


I'm having a hard time with figuring out all of the built-in stuff... for me, it's very confusing...

if you wanto take a look at it:

Objects:

http://docs.textadventures.co.uk/quest/elements/object.html (see the 'top:attributes' section and the bottom 'core Object Types' section)

Exits:

http://docs.textadventures.co.uk/quest/elements/exit.html


I was suppose to give you workable code back this last saturday (or whatever the day I said), so I totally failed at that. All I can do is say I'm sorry if that means anything, as I've got no excuses: I said I would and I didn't.

I can probably provide my own custom code stuff (ignoring how all the built-in stuff works and by not using Exits) to give you a workable game/code, but I think it'd be better for you to just get some help with how to do this stuff with the built-in stuff and using Exits instead, and thus that means get some help from someone else, as I'm still confused over all of the built-in stuff (I have just now been trying to get it figured out for 2 hrs but am still just as confused, if not more so, lol).

So, maybe try to see if you can get Pixie's or who-evers help (XanMag can probably help too with the built-in stuff), as, especially Pixie, can help really well and explain how all of it is working really well.


I tried using your code, and it works !!!! (just had a single small stupid typo: an extra '}' character/symbol)

(you got it figured out, while I was totally baffled at using the built-in stuff, laughs). You already figured out the working code! just had one single stupid typo (an extra '}' character/symbol) !!! (90% of the time, it's some stupid small typo or whatever mistake!). You did my job for me, you already got the code right, hehe.

you have one typo to remove: an extra '}' character/symbol (shown by comments in the code below) and you can remove my 'myopen' Verb's 'script' and 'verb' tag lines/blocks:

also, I added in the Attributes for the other door to the other room, and I also added in a missing code line (from my own code, and thus you don't have it in your code: my fault!) to open both doors and close both doors.

Also, added in the 'closescript' Script Attributes too and their Attributes and handling

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="From the Forum">

    <gameid>2a541114-7ed5-4161-a061-707e8670825e</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>

  </game>

  <object name="room1A">

    <inherit name="editor_room" />

    <alias>room</alias>

    <object name="player">

      <inherit name="editor_object" />
      <inherit name="editor_player" />

    </object>

    <exit name="room1Alock" alias="east" to="room1B">

      <inherit name="eastdirection" />

      <locked />

    </exit>

    <object name="door1A">

      <inherit name="editor_object" />

      <inherit name="openable" />

      <alias>door</alias>
      <feature_container />

      // --------------------------------------------------------------

      // remove this entire tag block:

      <myopen type="script">
        if (door1A.isopen) {
          msg ("The door is already open (and the exit is already unlocked) silly!")
        }
        else {
        }
      </myopen>

      // --------------------------------------------------------------------------

      <openscript type="script">
        if (door1A.isopen) {
          msg ("The door is already open and unlocked silly. ")
        }
        else {
          if (Got (key_1)) {
            UnlockExit (room1Alock)
            UnlockExit (room1Block)
            HelperOpenObject (door1A)
            HelperOpenObject (door1B) // <---------------------------- I forgot to include this line in my code, so I added it into your code
            msg ("You unlock and open the door. ")
          }
          else {
            msg ("sorry but you need the right key to open up the locked door.")
          }
        }
      } // <----------------------------------------------- delete this extra ending/right curly brace/bracket
      </openscript>

     // -------------------------------------------------------------------

    // adding in the 'closescript' Script Attribute:

   <closescript type="script">
        if (door1A.isopen) {
          if (Got (key_1)) {
            LockExit (room1Alock)
            LockExit (room1Block)
            HelperCloseObject (door1A)
            HelperCloseObject (door1B)
            msg ("You close and lock the door. ")
          }
          else {
            msg ("sorry but you need the right key to close and lock the door.")
          }
        }
        else {
          msg ("The door is already locked and closed, silly.")
        }
      </closescript>

     // ------------------------------------------------------------

    </object>

    <object name="key_1">

      <inherit name="editor_object" />

      <take />
      <takemsg>You pick up the key</takemsg>

    </object>

  </object>

  <object name="room1B">

    <inherit name="editor_room" />

    <exit name="room1Block" alias="west" to="room1A">

      <inherit name="westdirection" />

      <locked />

    </exit>

    <object name="door1B">

      <inherit name="editor_object" />

      <inherit name="openable" />

      <alias>door</alias>

      <feature_container />

      // -------------------------------------------------------------

      // add in these Attrbiutes for this door for this room:

      <openscript type="script">
        if (door1B.isopen) {
          msg ("The door is already open and unlocked silly. ")
        }
        else {
          if (Got (key_1)) {
            UnlockExit (room1Alock)
            UnlockExit (room1Block)
            HelperOpenObject (door1A)
            HelperOpenObject (door1B)
            msg ("You unlock and open the door. ")
          }
          else {
            msg ("sorry but you need the right key to open up the locked door.")
          }
        }
      </openscript>

     // --------------------------------------------------------------

    // adding in the 'closescript' Script Attribute:

   <closescript type="script">
        if (door1B.isopen) {
          if (Got (key_1)) {
            LockExit (room1Alock)
            LockExit (room1Block)
            HelperCloseObject (door1A)
            HelperCloseObject (door1B)
            msg ("You close and lock the door. ")
          }
          else {
            msg ("sorry but you need the right key to close and lock the door.")
          }
        }
        else {
          msg ("The door is already locked and closed, silly.")
        }
      </closescript>

     // ------------------------------------------------------------

    </object>

  </object>

  // ----------------------------------------------------------------------

  // remove this entire tag block:

  <verb name="myopen">
    <pattern>myopen</pattern>
    <property>myopen</property>
    <defaulttext>You open the door</defaulttext>
  </verb>

  // -------------------------------------------------------------------------------------

</asl>

here's the fixed up code (doing everything in the above, without all the comments/clutter/etc):

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="From the Forum">

    <gameid>2a541114-7ed5-4161-a061-707e8670825e</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>

  </game>

  <object name="room1A">

    <inherit name="editor_room" />

    <alias>room</alias>

    <object name="player">

      <inherit name="editor_object" />
      <inherit name="editor_player" />

    </object>

    <exit name="room1Alock" alias="east" to="room1B">

      <inherit name="eastdirection" />

      <locked />

    </exit>

    <object name="door1A">

      <inherit name="editor_object" />

      <inherit name="openable" />

      <alias>door</alias>

      <feature_container />

      <openscript type="script">
        if (door1A.isopen) {
          msg ("The door is already open and unlocked, silly. ")
        }
        else {
          if (Got (key_1)) {
            UnlockExit (room1Alock)
            UnlockExit (room1Block)
            HelperOpenObject (door1A)
            HelperOpenObject (door1B)
            msg ("You unlock and open the door. ")
          }
          else {
            msg ("sorry but you need the right key to open up the locked door.")
          }
        }
      </openscript>

      <closescript type="script">
        if (door1A.isopen) {
          if (Got (key_1)) {
            LockExit (room1Alock)
            LockExit (room1Block)
            HelperCloseObject (door1A)
            HelperCloseObject (door1B)
            msg ("You close and lock the door. ")
          }
          else {
            msg ("sorry but you need the right key to close and lock the door.")
          }
        }
        else {
          msg ("The door is already locked and closed, silly.")
        }
      </closescript>

    </object>

    <object name="key_1">

      <inherit name="editor_object" />

      <take />
      <takemsg>You pick up the key</takemsg>

    </object>

  </object>

  <object name="room1B">

    <inherit name="editor_room" />

    <exit name="room1Block" alias="west" to="room1A">

      <inherit name="westdirection" />

      <locked />

    </exit>

    <object name="door1B">

      <inherit name="editor_object" />

      <inherit name="openable" />

      <alias>door</alias>

      <feature_container />

      <openscript type="script">
        if (door1B.isopen) {
          msg ("The door is already open and unlocked silly. ")
        }
        else {
          if (Got (key_1)) {
            UnlockExit (room1Alock)
            UnlockExit (room1Block)
            HelperOpenObject (door1A)
            HelperOpenObject (door1B)
            msg ("You unlock and open the door. ")
          }
          else {
            msg ("sorry but you need the right key to open up the locked door.")
          }
        }
      </openscript>

      <closescript type="script">
        if (door1B.isopen) {
          if (Got (key_1)) {
            LockExit (room1Alock)
            LockExit (room1Block)
            HelperCloseObject (door1A)
            HelperCloseObject (door1B)
            msg ("You close and lock the door. ")
          }
          else {
            msg ("sorry but you need the right key to close and lock the door.")
          }
        }
        else {
          msg ("The door is already locked and closed, silly.")
        }
      </closescript>

    </object>

  </object>

</asl>

Hi HK, just put your code above into quest to check it out. Try as I can, I cannot get the message 'The door is unlocked and open Silly!' message to appear. It only prints the default message 'It is already open'.


Hi, I've had another look at the 'open #object#' script, and I think I know why a custom message is not being printed when you open the door.

Verb: open/close #object#
[call function:TryOpenClose]
//If object can be opened/can be closed ---> continue else print message 'object cannot be opened closed'
//If object is not open/closed ---> continue else print message 'object is already open/closed'
[call function:OpenObject]
[call function:CloseObject]
//Basically these two do the same thing. They print the successful message. 'It is open/closed' And Show/Hide the contents of the opened/closed object in question
Then [#object# script]// This is the object in question that you are trying to open/close. And it will now perform the scripting following a successful open/close.eg. unlocking exits, printing a message, etc

As you can see, if the object is already open/closed, the path will stop at the first function [TryOpenClose]
There might be a few things I've missed, such as [doopen][doclose][openmsg], but I think this is the general gist of the open/close verb.


Ah, thanks for pointing that out, I wasn't even paying attention to the messages, ya, my custom messages aren't being used, only the default messages.


ah cool for finding out how the built-in stuff is working! great job! I have trouble with built-in stuff, laughs.

I'm pretty sure there's a template for the default messages too and a way to customize it locally (for a specific Object), instead of changing it for global effect, but not sure how this is done, as I don't know how Templates work that well. Maybe you just over-ride/over-write it for an Object to make it local to/for only that Object, instead of it being a global change, but I'm not sure.


There is a template for the default message for 'open object' and closed object. I mentioned it earlier in a previous post.
AlreadyOpen
AlreadyClosed
To use these dynamic templates in your game, you would first have to copy them. They are then able to be changed with whatever message you desire. BUT, it will affect all openable/closable objects.


Hi. Apologies. NinjaNin, there is a way to do your custom open message, without altering the dynamic template. It involves setting up a room specific command for that object. The following code is for 2 doors, across 3 rooms. Rooms A&B use Quests built in open/close/unlock/lock features together with the built in lock-key feature. Rooms B&C use the customised room command 'open'. I've only put the open room command on for now for room B to C, so you can see what it does. If you need me to finish it off, let me know.

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Test - Open-Close-Unlock-Lock">
    <gameid>4eff0bb7-9dfc-4d39-ad67-1c48c12e34f2</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
  </game>
  <object name="roomB">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <exit name="Exit1AB" alias="north" to="roomA">
      <inherit name="northdirection" />
      <locked />
    </exit>
    <exit name="Exit1AC" alias="east" to="roomC">
      <inherit name="eastdirection" />
      <locked />
    </exit>
    <object name="door1AB">
      <inherit name="editor_object" />
      <inherit name="openable" />
      <inherit name="container_lockable" />
      <feature_container />
      <openscript type="script">
        if (this.locked) {
          if (this.autounlock and AllKeysAvailable(this)) {
            do (this, "unlock")
            if (not this.isopen) {
              OpenObject (this)
            }
          }
          else {
            msg (DynamicTemplate("LockedObject", this))
          }
        }
        else {
          OpenObject (this)
          UnlockExit (Exit1AB)
          HelperOpenObject (door2AB)
          door2AB.locked = false
          UnlockExit (Exit2AB)
        }
      </openscript>
      <closescript type="script">
        if (this.locked) {
          msg (DynamicTemplate("LockedObject", this))
        }
        else {
          CloseObject (this)
          LockExit (Exit1AB)
          HelperCloseObject (door2AB)
          door2AB.locked = true
          LockExit (Exit2AB)
        }
      </closescript>
      <keycount type="int">1</keycount>
      <key type="object">key1</key>
      <autounlock type="boolean">false</autounlock>
      <autoopen type="boolean">false</autoopen>
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Take</value>
        <value>Open</value>
        <value>Close</value>
        <value>Unlock</value>
        <value>Lock</value>
      </displayverbs>
    </object>
    <object name="door1AC">
      <inherit name="editor_object" />
    </object>
    <object name="key1">
      <inherit name="editor_object" />
      <take />
    </object>
    <command>
      <pattern>open door1AC</pattern>
      <script>
        if (not Got(key1)) {
          msg ("You need a key. DOH!!!")
        }
        else if (Got(key1)) {
          if (door1AC.isopen) {
            msg ("The door is already open. What is wrong with you today! You just opened it!!!")
          }
          else {
            msg ("You unlock and open door1AC")
            HelperOpenObject (door1AC)
            HelperOpenObject (door2AC)
            UnlockExit (Exit1AC)
            UnlockExit (Exit2AC)
          }
        }
      </script>
    </command>
  </object>
  <object name="roomC">
    <inherit name="editor_room" />
    <exit name="Exit2AC" alias="west" to="roomB">
      <inherit name="westdirection" />
      <locked />
    </exit>
    <object name="door2AC">
      <inherit name="editor_object" />
    </object>
  </object>
  <object name="roomA">
    <inherit name="editor_room" />
    <exit name="Exit2AB" alias="south" to="roomB">
      <inherit name="southdirection" />
      <locked />
    </exit>
    <object name="door2AB">
      <inherit name="editor_object" />
      <inherit name="openable" />
      <inherit name="container_lockable" />
      <feature_container />
      <openscript type="script"><![CDATA[
        if (this.locked) {
          if (this.autounlock and AllKeysAvailable(this)) {
            do (this, "unlock")
            if (not this.isopen) {
              OpenObject (this)
            }
          }
          else {
            msg (DynamicTemplate("LockedObject", this))
          }
        }
        else {
          OpenObject (this)
          UnlockExit (Exit2AB)
          HelperOpenObject (door1AB)
          door1AB.locked = false
          UnlockExit (Exit1AB)
          // The above 4 lines open the door connecting rooms A&B. doors 1AB & 2AB, are essentially the same door but in two rooms.
        }
      ]]></openscript>
      <closescript type="script">
        if (this.locked) {
          msg (DynamicTemplate("LockedObject", this))
        }
        else {
          CloseObject (this)
          LockExit (Exit2AB)
          HelperCloseObject (door1AB)
          door1AB.locked = true
          LockExit (Exit1AB)
        }
      </closescript>
      <keycount type="int">1</keycount>
      <key type="object">key1</key>
      <autounlock type="boolean">false</autounlock>
      <autoopen type="boolean">false</autoopen>
      <displayverbs type="stringlist">
        <value>Look at</value>
        <value>Take</value>
        <value>Open</value>
        <value>Close</value>
        <value>Unlock</value>
        <value>Lock</value>
      </displayverbs>
    </object>
  </object>
</asl>

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums