inkle / inky

An editor for ink: inkle's narrative scripting language
http://www.inklestudios.com/ink
2.41k stars 295 forks source link

[Beginner's Question] How do I compare variables and divert from the highest/lowest? #363

Open Galactikill opened 3 years ago

Galactikill commented 3 years ago

Please forgive me if this is obvious but I am a novice to programming and I am not smart enough to figure out an answer to this from github thus far.

In my game I have various "personality" stats that I am tracking as integer variables. For example:

VAR Diplomacy = 0 VAR Investigation = 0 VAR Deception = 0 VAR Intimidation = 0

Different choices boost the values of these variables. For example:

[Talk it out] ~ Diplomacy = Diplomacy +1 [Dig through his trash] ~ Investigation = Investigation +1

Now my question: At different points, I would like the character diverted into particular knots/stitches based on whichever of these variables is higher. So for example, if after making choices the character has these stats:

VAR Diplomacy = 2 VAR Investigation = 1 VAR Deception = 0 VAR Intimidation = 4

Than in this case, the player should be diverted to the "Intimidation" path.

The problem is, this doesn't seem to work the way I set it up. If I use && for this logic, I cannot move past this checker. { -Diplomacy > Investigation && Deception && Intimidation:-> PathA -Investigation > Diplomacy && Deception && Intimidation:-> PathB -Deception > Diplomacy && Investigation && Intimidation:-> PathC -Intimidation > Investigation && Deception && Diplomacy:-> PathD } I thought this would work but I get a "ran out of content" error. If I use ||, than Diplomacy will be selected since it is higher than Investigation or Deception, which I don't want.

I know for sure that I have successfully implemented the variables and modifiers as I have tested for them. What I want is for all these four variables to be compared and the highest one selected.

Thanks so much for any help you are willing to offer!

Selsynn commented 3 years ago

First, what do you want to do if you have two or more variable that are the highest?

Second, I spotted where the error was: -Diplomacy > Investigation && Deception && Intimidation:-> PathA means if (Diplomacy is over investigation) and (Deception) and (Intimidation) as you may guess, the and is NOT in the first condition but rather along the first condition. Moreover a condition with only a variable test the value of that variable. If it is >0 it's true.

So I figured you wanted to do

{
-Diplomacy > Investigation && Diplomacy > Deception && Diplomacy > Intimidation:-> PathA
-Investigation > Diplomacy && Investigation > Deception && Investigation > Intimidation:-> PathB
-Deception > Diplomacy && Deception > Investigation && Deception > Intimidation:-> PathC
-Intimidation > Investigation && Intimidation > Deception && Intimidation > Diplomacy:-> PathD
-else: ->PathMultiple
}

You could of course explicit the else with each possibility (so 2 var wiht the highest, all combination so Diplomacy and Intimidation in my example line) - Diplomacy > Investigation && Diplomacy > Deception && Diplomacy == Intimidation: ->PathAD Don't forget you can also have 3 of the same, and of course the four (or whatever number you have at the end)

Just to be extra clear the condition in my version is -Intimidation > Investigation && Intimidation > Deception && Intimidation > Diplomacy:-> PathD If (Intimidation > Investigation) and (Intimidation > Deception ) and (Intimidiation > Diplomacy) then go to pathD

Note: if you are not familiar with && you can use good old and in place. You can also have bracket () to separate each condition and see for yourself that's all good So a line of the test is also good as -(Diplomacy > Investigation) and (Diplomacy > Deception) and (Diplomacy > Intimidation):-> PathA (You may find that better to read/write and understand ^^)

Note 2: I'm quasi sure there is a better way to do the same, let me some time to think of it.

Galactikill commented 3 years ago

This worked perfectly! I did not at all think about the logic working that way but it makes perfect sense. Thank you so much!

I think for multiple variables being equal, I would just put in an -else:-> to force the player to a default path. Unless you can recommend some way of selecting the two highest and randomly choosing between them?

Selsynn commented 3 years ago

There could be a solution, but that's a lot more complex. I'm searching for something less complex, without very much success.

Here is a solution that will record first (in the MaxList list) all the maximum values. (the MaxValue). You can either take all the elements, search for a specific in them, or just randomly take one to do something. The list CANNOT be empty, it will have either one or more, can have all the member of the stats.

You need to have the stats and the member of the MaxList different in name. (hence the stats as Diplomacy, and the MaxList value as MaxDiplomacy) If the MaxDiplomacy is in the values of the MaxList at the end of the calculation, it means that the Diplomacy is (one of) the highest stats of the player. (the link is done when calling the function)

Feel free to play around and change the value directly, and try to add a new variable to understand how it's working

VAR Diplomacy = 0
VAR Investigation = 5
VAR Deception = 5
VAR Intimidation = 0

VAR MaxValue = 0
LIST MaxList = MaxDiplomacy, MaxInvestigation, MaxDeception, MaxIntimidation
-(loop)
+ Calculate the Max
~ MaxList = () //Emptying the list before the calculation
~ MaxValue = 0 //Needed to always make sure we have at least one value over. You could also affect value of the stat directly
~ CalculateMax(Diplomacy, MaxDiplomacy)
~ CalculateMax(Investigation, MaxInvestigation)
~ CalculateMax(Deception, MaxDeception)
~ CalculateMax(Intimidation, MaxIntimidation)
//You add every one of your stats. 
//Now, in MaxList, you have the list of your highest values
DEBUG: MaxList: {MaxList} 
Choose one randomly: {LIST_RANDOM(MaxList)}
->loop

=== function CalculateMax (Carac, MaxChar)
{
- MaxValue < Carac:
    //We affect the new value for the max
    ~ MaxValue=Carac
    //We empty the value of the list if it was currently + affect only the current stat
    ~ MaxList = MaxChar
- MaxValue == Carac:
    //We add the current stat
    ~ MaxList += MaxChar
- MaxValue > Carac:
    //Nothing to do
}

I tried to give comments at the same time. In summary, we want to make a list (list are a tricky business in Ink, I encourage you to read about it if you are unfamiliar) of all the max stats of the list. Once we have the list, you can either take one randomly or test the existence of some particular... or do whatever you want.

Let me know if you have any new questions! Or if you don't understand some parts

lunarcloud commented 2 years ago

Love the CalculateMax function suggested here!

In future, I don't know if bug reports are really the place for how-to questions. Please check out the discord, there a whole section of channels for ink users. https://discord.com/invite/inkle

In any case, @Galactikill , please close this issue now you've got your answers 😄 .