Planned Feature: Formula Parser

Discussion in 'Site Feedback' started by gene.sis, Nov 5, 2016.

  1. gene.sis

    gene.sis CHYOA Guru

    I'm currently working on a "Formula Parser" for Conditional Branch Stories.
    It is an addition to the current possibilities to change Conditional Branch Variables.

    Now I want to introduce you the currently planned syntax and would like to get some feedback about it and suggestions about missing functions.

    There is a summary of functions at the end of this post (tldr).

    (Please note, that everything described below isn't available yet and can be different when this feature will be finally published.)

    The syntax for the formulas is inspired by the syntax of spreadsheet formulas, so if you have experience with spreadsheets you may be already familiar with it.



    Why using formulas?
    - Use of more complex mathematical operations. (e.g. add 20% of the current value)
    - Use of conditional calculations. (e.g. if {charisma} is below 50, add 10 points, else add 5 points)
    - Use of calculations with other Score Variables. (e.g. if {charisma}+{negotiating skill} is below 15 )
    - Use of randomize functions.



    Note: The most examples used below are using numbers to illustrate the functions while keeping it simple. Usually, most of the numbers would be functions or variables. (there are some more complex examples under 12.)



    General usage:
    Create a Score Change of the desired type, choose "formula" as operator and type your formula into the value field.
    The Variable named in the left is the receiver of the calculated value of the formula.
    If the previous value of the variable should be modified by the formula, you have to include the variable into the formula.



    1. Result
    Boolean variables: If the result of the formula is equal 0, the variable will be set to "false". Else the variable will be set to "true".
    Numerical and Progress variables: The result will be converted into an integer (round down).

    Within a formula, all calculations will be done with floating point numbers.



    2. Syntax Errors
    The syntax of the formula will be checked while saving the chapter. If the syntax isn't valid, the formula won't be saved.



    3. Calculation Errors
    Some errors may occur while evaluating a formula with actual values from variables (e.g. division by zero) or with nonexistent variables.
    These uncaught "errors" will be evaluated as 0 to be able to calculate the rest of the formula.
    There are functions to cover those situations and provide a default value.



    4. Numbers
    You can use any integer or floating point number.
    You can use a decimal separator of your choice (decimal point or decimal comma).
    You can omit leading zeros.
    You mustn't use thousand separators.
    Code:
    2.03
    .75
    500,63


    5. Variables
    You can use Score Variables within your formula.
    Code:
    {Variable A} + 26


    6. Comments
    You can use comments to remind yourself or an editor what the formula is about.
    Write "//" followed by your comment at the end of your formula.
    Code:
    {Variable A} + 26 // this is a comment


    7. Mathematical calculations
    You can use mathematical calculations with following operators (normal precedence)
    Code:
    +
    -
    *
    /
    unary +
    unary -
    parentheses ( )
    Code:
    -22.4*3-2/(6-2)*(-2) // results in -66.2 


    8. functions
    Functions usually looks like this:
    Code:
    FUNCTIONNAME( parameter1 ; parameter2 ; parameter3 ; ... )
    Each function can have a definite or an indefinite number of parameters (depends on the function).
    The semicolons are used as separators for the parameters.
    A parameter can be a number, a variable, a function or a condition (depends on the function).



    9. general functions
    IF( condition ; value ; value )
    This function checks if the "condition" is true. If so, the result will be the first "value" (parameter 2), else the second "value" (parameter 3).
    Code:
    IF( 25 > 17 ; 5 ; 10 ) // results in 5
    IF( 17 > 25 ; 5 ; 10 ) // results in 10

    ROUND( value [; number of decimal places] )
    ROUNDUP( value [; number of decimal places] )
    ROUNDDOWN( value [; number of decimal places] )
    This functions can be used to round a value to a number of decimal places.
    Code:
    ROUND( 21.345 ; 2 ) // results in 21.35
    ROUNDUP( 21.345 ; 1 ) // results in 21.4
    ROUNDDOWN( 21.345 ; 2 ) // results in 21.34
    The parameter "number of decimal places" is optional. If omitted, the value will be rounded to no decimal places.
    Code:
    ROUND( 21.345 ) // results in 21
    If the parameter is negative, the value will be rounded to a number of places before the decimal point.
    Code:
    ROUND( 21.345 ; -1 ) // results in 20

    POW( base ; exponent )
    This function can be used to calculate the power of a number.
    Code:
    POW( 3 ; 3 ) // results in 27

    MOD( dividend ; divisor )
    This function can be used to perform modulo operation on numbers.
    Code:
    MOD( 15 ; 4 ) // results in 3
    Code:
    MOD( 15 ; 0 ) // results in 0 and sets an error flag

    IFNOTSET( variable ; alternative value )
    This function can be used to provide a default value if a variable doesn't exists in the readers score. This function removes the error flag from the variable value.
    Code:
    IFNOTSET( {existant variable} ; 25 ) // results in the value of the variable
    IFNOTSET( {non-existant variable} ; 25 ) // results in 25

    IFERROR( value ; alternative value )
    This function can be used to provide a default value if a value has an error flag. This removes an error flag from the value.
    Code:
    IFERROR( 25/0 ; 1 ) // results in 1
    IFERROR( 25/1 ; 1 ) // results in 25

    DICE( [number of sides] )
    This function can be used to do a dice roll. The result will be a random integer between 1 and "number of sides".
    Code:
    DICE( 15 ) // results in a random integer between 1 and 15
    The parameter "number of sides" is optional. If omitted, "number of sides" is supposed to be 6
    Code:
    DICE() // results in a random integer between 1 and 6

    RANDOM()
    This function can be used to create a random floating point number between 0 and 1.
    Code:
    RANDOM() // results in a random floating point number between 0 and 1

    MIN( value ; value [; value [; ...]] )
    MAX( value ; value [; value [; ...]] )
    These functions can be used to determinate the minimum/maximum of two or more values.
    Code:
    MIN( 25 ; 10 ) // results in 10
    MAX( 25 ; 10 ) // results in 25
    You can use the as many additional values to compare.
    Code:
    MIN( 25 ; 10 ; 13 ; 17 ; 34 ; 64 ; 23 ) // results in 10
    MAX( 25 ; 10 ; 13 ; 17 ; 34 ; 64 ; 23 ) // results in 64

    SAVEnumber( value )
    RETURNnumber()
    These functions are used to save a value as a formula-internal interim result and return it at another position. This is necessary, if you work with random numbers or dice rolls. It can also be useful to shorten complex formulas.
    "number" is the number to identify a particular interim result.
    Code:
    IF( SAVE1( DICE() ) <= 3 ; RETURN1()-1 ; RETURN1()+1 ) // result can have a value of 0, 1, 2, 5, 6 or 7
    10. conditions
    Code:
    value operator value
    Conditions consist of two values connected by a comparison operator or a single value.
    They can only be used within the IF-function and the logical functions (see 11.).
    Available operators:
    Code:
    == or = equal
    != not equal
    < lower than
    <= lower than or equal to
    > greater than
    >= greater than or equal to

    Code:
    value
    You can also use a single value as condition.
    If the value is 0, the result will be "false", else the result will be "true".



    11. logical functions
    You can use logical functions wherever you can use a condition.
    AND( condition ; condition [; condition [; ...]] )
    OR( condition ; condition [; condition [; ...]] )
    You can use these functions to evaluate multiple conditions
    NOT( condition )
    You can use this function to reverse the result of a condition.
    Code:
    IF( AND( 15 > 10 ; 23 <= 50 ) ; 1 ; 0 ) // results in 1
    IF( OR( 15 < 10 ; 23 <= 50 ) ; 1 ; 0 ) // results in 1
    IF( NOT( 5 = 5 ) ; 1 ; 0 ) // results in 0


    12. concrete examples
    Someone steals 20 backs from your purse. To ensure, that your purse won't contain a "negative amount of money, the thief will take only the rest, if you don't have that much.
    Code:
    IF( {Money} < 20 ; 0 ; {Money} - 20 )

    Haggling. If haggling is successful, the price will be reduced by 3% per point of haggling skill. If haggling fails badly, the price will be 20% higher than normal.
    Code:
    IF( ( {haggling} + ROUNDDOWN( {charisma} / 5 ) - {difficulty} + SAVE1(DICE( 20 ) ) ) > 20 ; {price} - {price}*{haggling}*0.03 ; IF( RETURN1() == 1 ; {price} * 1,2 ; {price} ) )

    Perform an attack and calculate the damage you do to your enemy. In most cases you would want to split this formula into smaller pieces, because you probably also want to tell the reader, if you hit, if the enemy parried and if the enemies armor absorbed the damage.
    Code:
    IF( AND( DICE( 20 ) > {weapon_skill} ; DICE( 20 ) < {enemy_defense} ) ; IF( SAVE1( DICE( {weapon_damage_dice_sides} ) + {weapon_damage_modifier} + ROUNDDOWN({strengh} / 10) ) > {enemies_armor} ; RETURN1() - {enemies_armor} ; 0 ) ; 0 )

    Calculate the attractiveness of a woman to the protagonist. (In this example we assume a 37 year old redhead with medium bust size. Haircolor and bust size are determinated by numbers in this example)
    The attributes are weighted (hair color 3, bust size 2, age 3). if one of the attributes is important, the weighting gets doubled.
    Code:
    IF( {favorite haircolor} = 1 ; 3 * IF( {haircolor important} ; 2 ; 1 ) ; 0 ) + IF( {favorite bust size} = 3 ; 2 * IF( {bust size important} ; 2 ; 1 ) ; 0 ) + IF( AND( {favorite age minimum} <= 37 ; {favorite age maximum} >= 37) ; 3 * IF( {age important} ; 2 ; 1 )  ; 0 )


    Summary of functions:
    - use of numbers (allows decimal point and decimal comma and omitting of leading zeros)
    - use of Score variables: {variable}
    - mathematical operators: +, -, *, /, (, ), unary -, unary +
    - comments //
    - error handling IFNOTSET for missing variables and IFERROR for general errors like division by zero
    - IF function
    - rounding functions ROUND, ROUNDUP, ROUNDDOWN
    - modulo function MOD
    - power of function POW
    - randomize functions DICE and RANDOM
    - functions MIN and MAX
    - comparison operators ==, =, !=, <, <=, >, >=
    - logical functions AND, OR and NOT

    I appreciate any feedback and suggestions (e.g. missing functions).
    Feel free to ask questions.
     
    Last edited: Nov 27, 2016
  2. 229

    229 Experienced

    This is such a great idea! Just reading about it makes me want to do something with this sort of thing.
     
    gene.sis likes this.
  3. gene.sis

    gene.sis CHYOA Guru

    It is still possible to change or adjust the syntax now, so I'm still looking for feedback about it. :)
    At the moment it isn't a big deal to do changes but it will be all but impossible to change the syntax if this feature is released.
     
  4. Toadsith

    Toadsith Virgin

    This looks fantastic! My programming is a bit rusty though, so I'm finding the If/Then syntax somewhat confusing, namely all of the semicolons.

    I mostly follow with the basic If/Then as in IF( A > B ; C ; D ) is the same as If A is greater than B then C, else D.

    However, I start getting a bit lost when the AND / OR / NOT come into play... so the parenthetical statement following the Boolean function sets the conditions for the which side of the If/Then the computer goes with... I think...

    The more I look at it, the more it makes sense, but I can't help but wonder if a bit more wording would make the equations more readable. The semicolons are just hard for me, I have to carefully walk through the statement and translate the ; into a Then or an Else.

    Outside of the semicolons, everything makes easy sense to me and, honestly, I think I could probably get used to the semicolons.
     
    gene.sis likes this.
  5. Nemo of Utopia

    Nemo of Utopia CHYOA Guru

    (o_O);*

    Are you trying to turn CHYOA into Kingdom of Loathing? Because that's where this ends up...
     
    gene.sis likes this.
  6. gene.sis

    gene.sis CHYOA Guru

    yes

    yes
    This is the way it gets evaluated ("true" is just to show what happens):
    Code:
    IF( AND( 15 > 10 ; 23 <= 50 ) ; 1 ; 0 )
    IF( AND( true ; 23 <= 50 ) ; 1 ; 0 )
    IF( AND( true ; true ) ; 1 ; 0 )
    IF( true ; 1 ; 0 )
    1
    Currently, it is only possible to use conditions within IF-statements, so the IF-statement is necessary to evaluate conditions.
    Maybe it would be easier to allow conditions everywhere (resulting in 0 or 1) and also allow other values and function as conditions (resulting in false if the value is 0 and resulting in true if the value isn't 0)

    The semicolon is inspired by the spreadsheet functions. You can see this here or here.
    But I'm open for suggestions for different approaches.


    Had to use google about KoL first ^^
    The main thing is the ability to change variables depending on other variables and to use randomize functions as extension to the current Conditional Branches Score Changes.
    In general, you probably could do something like Kingdom of Loathing, though this can be pretty complex.
     
    Toadsith likes this.
  7. Toadsith

    Toadsith Virgin

    That shows exactly how it works, thanks!

    Since it's a commonly used method, I'm all for it — it is simply a method I didn't know. I'll just add it to my repertoire.

    There's always been that struggle between making code easily readable and keeping it clean and short. For the most part CHOYOA seems to err on the side of being easily readable and, for me, this is leaning the other way a bit. That said: One can't exactly point at it and say, "THAT'S TOO FAR! WE'RE TALKING LIKE THE MACHINES!" but it will make some of the programming a bit more obtuse to many. However, what this code does is clearly on the advanced side of interactive fiction, so I feel like only more experienced writers (or excessively ambitious ones, like myself) are going to bother attempting to use it. One can certainly write a great story without dipping a single toe into these programming waters.

    Since this is already a heavily used and well established format, I think it's probably not wise to customize it too much lest we risk creating problems down the road that the original format probably was designed to avoid. I just needed to take a moment to wrap my brain around it (as you can probably see happening during my earlier post).
     
    gene.sis likes this.
  8. gene.sis

    gene.sis CHYOA Guru

    CHYOA should stay easy to use, so this should be an addition to the current ways of manipulating score variables (plus, minus, set).
    I agree that this feature is more for experienced writers, though I think, that an easy basic usage could lead writers to grow into it.
     
    Toadsith likes this.
  9. Nemo of Utopia

    Nemo of Utopia CHYOA Guru

    I also am of the opinion that if this feature is going to be implemented we should continue the trend of having controls which are as noob friendly as possible, therefore instead of colons and semicolons we should use actual if/then/or/and statements.
     
  10. gene.sis

    gene.sis CHYOA Guru

    Could you provide some example syntax?
     
  11. Nemo of Utopia

    Nemo of Utopia CHYOA Guru

    If I were a programming professional I probably wouldn't be asking for simpler, (easily read and debugged by non programmers,) language, now would I?
     
  12. gene.sis

    gene.sis CHYOA Guru

    Well, the syntax above is meant to be simple.

    It always follows the same structure (1 exception):
    Code:
    FunctionName( ParameterList )
    (FunctionNames are case insensitive, so it doesn't matter if you write "if", "IF" or even "iF".)
    The ParameterList consists of 0 to infinite elements (depending on the Function), separated by semicolons.

    Besides the functions, you can use mathematical operations with normal precedence (BODMAS or PEMDAS). To make it easier, I decided to omit the operators % (modulo) and ^ (power of) and implemented them as functions which show the precedence very clearly.
    Same applies to AND and OR. In a programming language, you would use ||, &&, AND or OR with precedence.
    Logical operators (conditions) also have precedence. By using them like "expression LogicalOperator expression" separated within AND, OR and NOT functions, you don't have to care about precedence.

    The functions must be "learned", though I think, that this shouldn't be that hard.
    e.g. you need a function to do something.
    First, you will look at the manual to see, what function you could use (the name of the function should say something about the intended use).
    You don't know, what the parameters are, so you look at the description of the function.
    You use the function in your formula.
    After that, you maybe forget the parameters, so you have to look at the description again when you want to use the function in another formula. After using a function a couple of times, you may memorize the function and their parameters.
    (Programming languages can use a lot of functions. To use that language, you don't have to know the most of them by heart.)


    For building a formula I would suggest building it step by step with replacing the parts. (I do the same for a complex formula, though I would use fewer steps.)
    e.g. the haggling formula
    "Haggling. If haggling is successful, the price will be reduced by 3% per point of haggling skill. If haggling fails, the price is normal. If haggling fails badly, the price will be 20% higher than normal."
    IF( "haggling is successful"; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( "haggling result" ) > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( "haggling skill" + "+1 for each 5 charisma points" - "difficulty" + "a D20 dice roll" ) > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + "+1 for each 5 charisma points" - "difficulty" + "a D20 dice roll" ) > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ; "number of decimal places") - "difficulty" + "a D20 dice roll") > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ; "we can omit this optional parameter because we want a full number") - "difficulty" + "a D20 dice roll") > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - "difficulty" + "a D20 dice roll") > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + "a D20 dice roll") > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > "minimum for haggling success" ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; "price reduced by 3% per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; {price} - "3% of price per point of haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; {price} - "3 percent" * "price" * "haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; {price} - 0.03 * "price" * "haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; {price} - 0.03 * {price} * "haggling skill"; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; {price} - 0.03 * {price} * {haggling}; "normal price or 20% higher when failing badly")
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; {price} - 0.03 * {price} * {haggling}; IF( "haggling fails badly" ; "price is 20% higher" ; "normal price" ) )
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + DICE(20) ) > 20 ; {price} - 0.03 * {price} * {haggling}; IF( "dice roll" == 1 ; "price is 20% higher" ; "normal price" ) )
    now we need the original dice roll, so we insert the SAVE-function to save the dice roll and the RETURN-function to return the value
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + SAVE1( DICE(20) ) ) > 20 ; {price} - 0.03 * {price} * {haggling}; IF( RETURN1() == 1 ; "price is 20% higher" ; "normal price" ) )
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + SAVE1( DICE(20) ) ) > 20 ; {price} - 0.03 * {price} * {haggling}; IF( RETURN1() == 1 ; {price} * 1.2 ; "normal price" ) )
    IF( ( {haggling} + ROUNDDOWN( {charisma} /5 ) - {difficulty} + SAVE1( DICE(20) ) ) > 20 ; {price} - 0.03 * {price} * {haggling}; IF( RETURN1() == 1 ; {price} * 1.2 ; {price} ) )
     
    Toadsith likes this.
  13. Toadsith

    Toadsith Virgin

    The above is a great way of explaining how to convert the description into the code. (Too bad the computer can't read our mind and just write this code on its own, lol)

    Reading through the conversion made me think that it would be helpful if, as authors, we could test our code on the fly by temporarily specifying the values of variables used in the code. Sort of a debugging mode, if you will. I know while I've been slowly writing my story, I've had to go and start game mode and do the appropriate actions just to make sure my rather simple IF/THEN text descriptions were behaving correctly. As the story gets longer, this is going to become more and more time consuming and I'll probably be releasing untested code just because I didn't feel like doing the 50 clicks necessary to make a 100% sure that I wrote it correctly.
     
    gene.sis likes this.
  14. Nemo of Utopia

    Nemo of Utopia CHYOA Guru

    Clear as MUD. I don't think I will EVER be able to use this feature.
     
  15. gene.sis

    gene.sis CHYOA Guru

    Do you think, that following would be easier to understand?
    Code:
    IF {haggling} + ROUND {charisma} / 5 DOWN TO 0 PLACES - {difficulty} + SAVE ROLL DICE20 AS1 > 20 THEN {price} - 0.03 * {price} * {haggling} ELSE IF RETURN FROM 1 == 1 THEN {price} * 1.2 ELSE {price} ENDIF ENDIF
    To my mind, it is a lot harder to group the logical elements in this example.


    You should also bear in mind, that the haggling formula isn't meant to be a simple formula.
    Following examples are more basic:
    "Add 20% to charisma"
    Code:
    {charisma} * 1.2
    or
    "If charisma is below 50, add 5 points to charisma, else add 3 points to charisma"
    Code:
    IF( {charisma} < 50 ; {charisma} + 5 ; {charisma} + 3 )
     
  16. gene.sis

    gene.sis CHYOA Guru

    I had the same thought while creating the Conditional Branches - If Statements guide. Additionally, it would be nice if it would be also possible to test the story "as a reader". (The link in a linked chapter always opens in a new browser tab.)


    The same would be useful for formulas. In my testing environment, the formula score changes have the same behavior as the current CHYOA score changes. If the syntax check fails, the score change will be dropped.
     
    Toadsith likes this.
  17. Nemo of Utopia

    Nemo of Utopia CHYOA Guru

    Actually I found the new examples easier to follow by far: to whit, I could actually follow them.
     
  18. Nemo of Utopia

    Nemo of Utopia CHYOA Guru

    Let me give you an example of why using colons instead of words is a bad idea:

    ---

    IF {Sorceress} = [TRUE] : THEN +3 to {Charisma} : AND [GO TO NEXT LINE ]

    IF {Charisma} > 99 : THEN + {LEVEL} * 10 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 89 : THEN + {LEVEL} * 9 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 79 : THEN + {LEVEL} * 8 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 69 : THEN + {LEVEL} * 7 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 59 : THEN + {LEVEL} * 6 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 49 : THEN + {LEVEL} * 5 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 39 : THEN + {LEVEL} * 4 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 29 : THEN + {LEVEL} * 3 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 19 : THEN + {LEVEL} * 2 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} > 9 : THEN + {LEVEL} * 1 TO {Mana} : AND [GO TO NEXT LINE] : ELSE-IF {Charisma} < 10 : THEN [GO TO NEXT]

    ---

    Now imagine someone, who, unlike me, has never read a book on programming languages in their life, and only has whatever's in the CHYOA guide to go on, trying to write that using semicolons...

    I couldn't even figure out what you were doing with things dozens of times simpler than that, what chance do you think the AVERAGE person has of managing to navigate your originally published system...?
     
    gene.sis likes this.
  19. gene.sis

    gene.sis CHYOA Guru

    Well, you have to look at a formula as mathematical term and not as a programming language, so it would be
    Code:
    {Charisma} = "something"
    the thing is, that {Charisma} and = won't be part of the formula, as they are still part of the CHYOA Score Change input field.
    So you assign the result of "something" to the variable {Charisma}. (You wouldn't use curly brackets as you don't use them for a plus, minus or set operation.

    So with the suggested syntax it would be:
    Code:
    IF( {Sorceress} == 1 ; {Charisma} +3 ; {Charisma} )
    IF( {Sorceress} = 1 ; {Charisma} +3 ; {Charisma} ) // alternative with non-programming equal sign
    IF( {Sorceress} ; {Charisma} +3 ; {Charisma} ) // alternative if implementing evaluation of a value as condition
    You won't go the next line, but proceeding with the next score change.

    The second could be (depending if you want to recalculate the Mana or to add to the existing amount of Mana):
    Code:
    IF( {Sorceress} ; 1 ; 0 ) * {LEVEL} * ROUNDDOWN( {Charisma} / 10 )
    {Mana} + IF( {Sorceress} ; 1 ; 0 ) * {LEVEL} * ROUNDDOWN( {Charisma} / 10 )
    If this feature will be released, it should get its own section within the CHYOA guide. This thread should also help me to find ways to explain the issues.


    The initial thought was to use a system, that is still known by some people.
    It is a widespread syntax within spreadsheets meant to be used by end-user of that programs. It actually has nothing to do with programming itself.
    The following programs use the same or similar syntax (with flavours like using "," or ";" as parameter separator).
    Google Sheets
    Excel
    NeoOffice
    (LibreOffice)
    (OpenOffice)
    Lotus 1-2-3
    (In CHYOA there are no cell names, so you would refer to variable names instead. There are no string function, as CHYOA can't hold strings as variables)



    The thing is, for me, it feels pretty simple.
    Removing the function parentheses would make it harder to understand.
    Replacing the semicolons with words would change each function to a construct of its own.

    Could you suggest a syntax, you think is easier.
    Or could you explain, where exactly you see the problem?
     
    Last edited: Dec 3, 2016
  20. Nemo of Utopia

    Nemo of Utopia CHYOA Guru

    Actually, fairly easily.

    What you are doing, in essence is creating a small and very restricted programming language for CHYOA. You may not THINK that is what you are doing, but (and, keep in mind, I intend no malice or derogation here,) your wrong: you are.

    Now, here's WHY you're wrong. However you are INTENDING to make the system work, that is how the users will put it into practice. If this is implemented you WILL see a reconstruction of one or more of the old text only RPGs from the early 80s. You only have three choices here, the first of which I doubt will even be seriously considered and the last of which you seem resistant to and I am desperately trying to persuade you to adopt before it's too late...
    1: Abandon this notion of adding any sort of coding features to the site.
    As it stands now, the variables are too limited for people to start trying to use it to program full games: that ENDS the moment we have THEN and AND functionality, to say nothing of THEN-IF/AND-IF/OR-IF. You can walk away from this precipice now, and some people will be disappointed, but that's all, but once the leap is taken there's no turning back.
    IF, as I suspect, you are committed to this course the other two choices come into play.

    2A: You go with your current system, (And again, remember I am trying to save you and everyone else from a terrible mistake, not insult you,) and the whole user base curses your name in ten years time for saddling them with this horribly awkward, clunky, and restricted programming language. (Because, remember, like it or not, that's what this will be used for.)
    2B: You see the handwriting on the wall: go back to the drawing board, and come out with a system that can be used to program full games within the limits of the base CHYOA architecture right from the start. End result; basically identical, except instead of cursing you you are lauded as a hero and 'Latterday Founder of the Site'...

    The choice is yours: (Friedman's actually, but he'll most likely agree with your decision...) I implore you to choose something other than 2A...