Decreasing or adding attributes

I've been trying to implement a code where there is a certain amount of food and when you eat it the number decreases(ex. there are 10 cans. Eat 1. 9 cans left.).


Something like...
cans=10
(eat one)
cans=cans-1
cans (now)=9
But, Quest also has the Add script: Decrease counter... which looks like this:
DecreaseObjectCounter (player, "cans")
Does the same thing...
The first option allows you to change cans by any amount...
but DecreaseObjectCounter (player, "cans") only decreases the amount by 1 at a time.
AND there is also the IncreaseObjectCounter (player, "cans") that add 1 to cans...


<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>

  <attr name="life" type="string">999/999</attr>

  <attr name="current_life" type="int">999</attr>

  <attr name="maximum_life" type="int">999</attr>

  <attr name="minimum_life" type="int">0</attr>

  <attr name="condition" type="string">normal</attr>

  <attr name="changedcondition" type="script">

    if (player.condition = "poisoned") {
      poisoned_turnscript.enabled = true
    } else if (poisoned_turnscript.enabled) {
      poisoned_turnscript.enabled = false
    }

  </attr>

  <attr name="changedcurrent_life" type="script">

    <![CDATA[

      if (player.current_life < player.minimum_life) {
        player.current_life = player.minimum_life
      } else if (player.current_life > player.maximum_life) {
        player.current_life = player.maximum_life
      }

      player.life = player.current_life + "/" + player.maximum_life

      if (player.current_life = player.minimum_life) {
        player.condition = "dead"
      }

    ]]>

  </attr>

  <attr name="changedmaximum_life" type="script">

    <![CDATA[

      if (player.current_life > player.maximum_life) {
        player.current_life = player.maximum_life
      }

      player.life = player.current_life + "/" + player.maximum_life

    ]]>

  </attr>

  <statusattributes type="stringdictionary">

    <item>
      <key>life</key>
      <value>Life: !</value>
    </item>

    <item>
      <key>condition</key>
      <value>Condition: !</value>
    </item>

  </statusattributes>

</object>

<object name="poisoned_apple">

  <inherit name="editor_object" />

  <inherit name="consumable_type" />

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

  <attr name="alias" type="string">apple</attr>

  <attr name="quantity" type="int">5</attr>

  <attr name="effect" type="script">

    player.condition = "poisoned"

    msg ("You're poisoned from eating the " + this.alias + ".")

  </attr>

</object>

<object name="poison_antedote">

  <inherit name="editor_object" />

  <inherit name="consumable_type" />

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

  <attr name="alias" type="string">poison antedote</attr>

  <attr name="quantity" type="int">5</attr>

  <attr name="effect" type="script">

    if (player.condition = "poisoned")
      this.quantity = this.quantity - 1
      player.condition = "normal"
      msg ("You cured yourself of being poisoned")
   } else {
     msg ("You realize you're not poisoned, just in time before you eat the antedote plant, you don't want to foolishly waste it, silly!")
   }

  </attr>

</object>

<type name="consumable_type">

  <attr name="take" type="boolean">true</attr>
  <attr name="drop" type="boolean">true</attr>

  <attr name="quantity" type="int">0</attr>

  <attr name="quantity_maximum" type="int">99</attr>

  <attr name="quantity_minimum" type="int">0</attr>

  <displayverbs type="stringlist">

    <value>eat</value>

  </displayverbs>

  <inventoryverbs type="stringlist">

    <value>eat</value>

  </inventoryverbs>

  <attr name="eat" type="script">

    <![CDATA[

      if (this.quantity > 0) {
        this.quantity = this.quantity - 1
        msg ("You eat the " + this.alias + ".")
        if (HasAttribute (this, "effect")) {
          if (TypeOf (this.effect) = "script") {
            invoke (this.effect)
          } else if (TypeOf (this.effect) = "string") {
            msg (this.effect)
          } else {
            msg ("ERROR: the '" + this.name + "' Object's 'effect' Attribute is not a String nor a Script, which it must be one of them")
          }
        } else {
          msg ("ERROR: the '" + this.name + "' Object has no 'effect' String/Script, which is required")
        }
      }

    ]]>

  </attr>

  <attr name="changedquantity" type="script">

    <![CDATA[

      if (this.quantity < this.quantity_minimum) {
        this.quantity = this.quantity_minimum
      } else if (this.quantity > this.quantity_maximum) {
        this.quantity = this.quantity_maximum
      }

      if (this.quantity = 0) {
        list remove (this.displayverbs, "eat")
        list remove (this.inventoryverbs, "eat")
      } else {
        if (not ListContains (this.displayverbs, "eat")) {
          list add (this.displayverbs, "eat")
        }
        if (not ListContains (this.inventoryverbs, "eat")) {
          list add (this.inventoryverbs, "eat")
        }
      }

    ]]>

  </attr>
  
</type>

<verb>

  <property>eat</property>

  <pattern>eat</pattern>

  <defaultexpression> You can't eat that!</defaultexpression>

</verb>

<turnscript name="poisoned_turnscript">

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

  <script>

    player.current_life = player.current_life - player.maximum_life / 10

  </script>

</turnscript>

via using the GUI/Editor:

// creating/setting the Integer Attribute:

'WHATEVER' Object -> 'Attributes' Tab -> Attributes (I think it's the box on the bottom) -> Add -> (see below)

(Object Name: WHATEVER)
Attribute Name: WHATEVER
Attribute Type: int // (int: integer)
Attribute Value: WHATEVER AMOUNT/NUMBER

// how to do arithmetic operations via the GUI/Editor's script options:

run as script -> add new script -> 'variables' section/category -> 'set a variable or attribute' Script -> (see below)

// Arithmetic Operators:

// Addition: +
// Subtraction: -
// Multiplication: *
// Division: /
// Modulus (division, but it gets/finds/returns the REMAINDER): %

set variable NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = [EXPRESSION] NAME_OF_OBJECT.NAME_OF_ATTRIBUTE ARITHMETIC_OPERATOR VALUE_OR_ATTRIBUTE

for examples:

set variable player.strength = [EXPRESSION] player.strength + 5

set variable player.strength = [EXPRESSION] player.strength - 9

set variable player.strength = [EXPRESSION] player.strength * 3

set variable player.strength = [EXPRESSION] player.strength / 2

a more complex expression using Attributes:

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

// these just creates/sets the Integer Attributes' Values to be randomly selecting from 0 to 100 (it's the same as using create/setting the Attribute via the GUI/Editor's Tabs as shown above, except you have to choose a Value yourself, you can't do the 'GetRandomInt' randomization Script/Function, by using the GUI/Editor's Tabs, unless you set an Attribute to be a Script Attribute):

set variable player.strength = [EXPRESSION] GetRandomInt (0,100)
set variable player.endurance = [EXPRESSION] GetRandomInt (0,100)

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

set variable player.damage = [EXPRESSION] (player.strength + player.endurance) / 2

the expression can be as complex as you want it, using direct/literal Values and/or Attributes, and follows all of the same rules as with any mathematical expression

for examples of more complex expressions:

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

// as in code scripting (too lazy to do as using the GUI/Editor's options/controls):

create ("katana")
katana.damage = 50
katana.alias = "katana"

create ("short_sword")
short_sword.damage = 25
short_sword.alias = "short sword"

objectlist_variable = NewObjectList ()
list add (objectlist_variable, katana)
list add (objectlist_variable, short_sword)

player.weapon = ObjectListItem (objectlist_variable, GetRandomInt (0,1))

player.strength = GetRandomInt (0,100)

// ---------

set variable player.damage = [EXPRESSION] player.weapon.damage + player.weapon.damage * player.strength / 100

// as in-code scripting (just so you can see the small differences in syntaxes between the in-code scripting and via using the GUI/Editor's script options):

player.damage = player.weapon.damage + player.weapon.damage * player.strength / 100


conceptually how the arithmetic operations work (using an Addition simple expression as an example):

// initial Value: player.strength = 0

// old value: player.strength = 0

player.strength = player.strength + 5
// player.strength (NEW) = player.strength (OLD) + 5
// player.strength (NEW) = player.strength (OLD: 0) + 5
// player.strength (NEW) = (0) + 5
// player.strength (NEW) = 5

// new Value: player.strength = 5

// old Value: player.strength = 5

player.strength = player.strength + 5
// player.strength (NEW) = player.strength (OLD) + 5
// player.strength (NEW) = player.strength (OLD: 5) + 5
// player.strength (NEW) = (5) + 5
// player.strength (NEW) = 10

// new Value: player.strength = 10

// old Value: player.strength = 10

player.strength = player.strength + 5
// player.strength (NEW) = player.strength (OLD) + 5
// player.strength (NEW) = player.strength (OLD: 10) + 5
// player.strength (NEW) = (10) + 5
// player.strength (NEW) = 15

// new Value: player.strength = 15

// old Value: player.strength = 15

player.strength = player.strength + 5
// player.strength (NEW) = player.strength (OLD) + 5
// player.strength (NEW) = player.strength (OLD: 15) + 5
// player.strength (NEW) = (15) + 5
// player.strength (NEW) = 20

// new value: player.strength = 20

// etc etc etc


unfortunately in math (algebra) class, they don't teach that the '=' is a COMPARISON operator (is 'A' equal-to/the-same-as 'B'), for example:

2N = 10
// 2N (/2) = 10 (/2)
// N = 5

(if N=5): is '2 * N' the same as '10' ??? ---> yes/true
does 'N' = '5' ??? ---> (see above) ---> YES/TRUE

and also in math:

N = 10 // NO error
10 = N // NO error

whereas in programming, there's ALSO the 'Assignment' operator:

N = 10 // NO error
10 = N // ERROR!

because....

N = 5

the '5' Value on the right side of the '=' ASSIGNMENT operator, is STORED into the 'N' Variable VARIABLE on the left side of the '=' ASSIGNMENT operator

you can ONLY STORE something into a VARIABLE, as '10' is not a VARIABLE: 10 = N ---> ERROR!


quickly (keeping this simple), in quest, there's 3 types of VARIABLES:

VARIABLES:

  1. Variable
  2. Attribute
  3. Parameters/Arguments

you generally want to use Attributes (Attribute VARIABLES), until you understand about scope better, and know how/when you can use Variables vs Attributes

and the 'parameters/arguments' is specifically for Functions and Commands usage... but that's a topic for another day/post/thread/later....

(basically parameters/arguments are: the parameter is a Variable VARIABLE and the argument is the value being stored into it, except they can also be transferred to another Function/Command for its use of them)


M = 5
N = M

the 'M' Variable VARIABLE (which is storing the Value of '5') is STORED into the 'N' Variable VARIABLE, so essentially we're doing this:

N = (M = 5)
N <=== (M <=== 5)

N = 5

the 'N' is storing the '5' Value


and that's why the arithmetic operations work as they do:

player.strength = 7
player.strength = player.strength + 9

// player.strength = 16

because of the use of the Assignment operator/operation, taking whatever is the ultimate (if there's a complex expression, it first gets solved/evaluated) final Value on the right side of the '=' ASSIGNMENT operator, and STORING it into the VARIABLE on the left side of the '=' ASSIGNMENT operator

quest is able to handle/parse/know whether the '=' is the normal comparison operator vs an assignment operator

and for friendliness for those new to coding, quest uses the same operator symbol for both of them:

assignment operator: =
comparison operator: =

and uses for the Logic operators:

'AND' logic operator: A and B
'OR' logic operator: A or B
'Negation' (opposite) ('NOT') logic operator: not A = B // or: A <> B

usually though programming languages uses different symbols/operators:

assignment operator: =
comparison operator: ==

and for the logic operators, usually in programming languages, its:

'AND' logic operator: &&
'OR' logic operator: ||
'NOT' logic operator: !

but this can be confusing for people new to coding, so quest opted to use the same operator (which can be confusing too, meh) for both operations, and have internal coding handle/parse/know which operation to do for the '=' symbols/operators used in the syntaxes

and people new to coding are scared by lots of symbols, so for the logic operators/operations in quest, you literally use 'and' for the 'AND' logic operator, 'or' for the 'OR' logic operator, and 'not' for the 'NOT' logic operator, instead of the symbols '&&', '||', and '!'


here's some links to help you with learning quest and its coding:

http://textadventures.co.uk/forum/general/topic/ljjm32av4e2t9ot49k478g/help#710be61e-eae1-4af1-8363-520cc718ba1c

I go into more detail in my 'HKs attributes and if script usage' link:

http://textadventures.co.uk/forum/samples/topic/5559/attributes-and-if-script-guide-by-hk (scroll down past the ~ top half section, to get into the Attribute usage and arithmetic operations, and further down, for the 'if' Script: using Attributes with the 'if' Script, which is how you do 90% of everything that you want to do within your game)

though, you might also want to read this too/first, as I try to explain how to work directly in quest's code (makes everything so much easier/faster than using the GUI/Editor to do/change stuff), trying to explain its code structure:

http://textadventures.co.uk/forum/quest/topic/mu7itzjqv0yxrkdwgsbmzg/how-to-make-npc-confront-you-with-chioces#46cdb25b-4767-40a6-8bf4-3cd84e805781


ask if you need help and/or explanation of/with whatever, as this is really complicated stuff, especially if you're new to coding and programming


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

Support

Forums