# Overcomplicated Multireplace

**URL:** <https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380>\
**Category:** Game Development\
**Created:** [October 18, 2019, 2:41pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380 "2019-10-18T14:41:34Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![StorybookParagon](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/storybookparagon/32/61008_2.png) [@StorybookParagon](https://forum.choiceofgames.com/u/StorybookParagon)\
**Post date:** [October 18, 2019, 2:41pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/1 "2019-10-18T14:41:34Z")

</div>

I found a niche usage of the multireplace function using math:  
`@{(round((var1 - 50)/(x))+1) This is sample text the first.|I am the second sample text.|Behold, a third sample text.}`

It takes var1 as an integer and does funky stuff until it ends up being 1, 2, or 3. The variable x affects the threshold of when it will become one of the readable numbers.

If x = 50, var1 being below 25 triggers the first sample text and if var1 is at least 75, it triggers the third sample text. Anything in between triggers the second sample text.

The variable x changes the trigger numbers by at a rate of 1:0.5 from the base number 50. So if x = 30, the trigger numbers will be 35 and 65. (You still shouldn’t divide by 0.)

This is a very complicated version of using the different if’s and else’s:

```
*if var1 < (50-(x/2))
    This is a sample text the first.
*elseif var1 >= (50+(x/2))
     Behold, a third sample text.
*else
    I am the second sample text.

```

I would not recommend using this alternative. No, really. I just thought it was neat.

---

<div class="post-metadata">

**Author:** ![trevers17](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/trevers17/32/127415_2.png) [@trevers17](https://forum.choiceofgames.com/u/trevers17)\
**Post date:** [October 18, 2019, 9:09pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/2 "2019-10-18T21:09:26Z")

</div>

Definitely neat, but considering I scored a 17 in the Math section on my first ACT test a few years back, I think I’ll stick to the normal conventions here. 😂

---

<div class="post-metadata">

**Author:** ![cup\_half\_empty](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/cup_half_empty/32/273983_2.png) [@cup\_half\_empty](https://forum.choiceofgames.com/u/cup_half_empty)\
**Post date:** [April 15, 2020, 5:16am UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/3 "2020-04-15T05:16:51Z")

</div>

The idea is pretty neat, but I think the logic is a little funky.

> [@StorybookParagon](#):
>
> If x = 50, var1 being below 25 triggers the first sample text

This is not true, _(round((var1 - 50)/(x))+1)_ can still end up being 0, which will cause an error in the multireplace.

For example, if x = 50 and var1 = 24, then:

- var1 - 50 = 24 - 50 = - 26
- (- 26) / 50 = - 0.52
- round(- 0.52) = - 1
- (- 1) + 1 = 0

> [@StorybookParagon](#):
>
> if var1 is at least 75, it triggers the third sample text

- var1 - 50 = 75 - 50 = 25
- 25 / 50 = 0.5
- round( 0.5 ) = 1
- 1 + 1 = 2

This will trigger the second option.

You either didn’t notice that multireplace indices start at 1 and not 0, different than an array, or you forgot to check the _lower_ limits for each condition.

> [@StorybookParagon](#):
>
> ```choicescript
> @{(round((var1 - 50)/(x))+1) This is sample text the first.|I am the second sample text.|Behold, a third sample text.}
> 
> ```

For now, I think you can fix it (I could be wrong, it’s 3 a.m. here 😅😴) if you use **2** instead of _1_

> @{(round( (var - 50) / 50 ) + **2** ) One|Two|Three}

But I don’t think it’ll work for all _divisors_. This is an interesting challenge, though. I’ll try to work a solution as well 😜.

---

<div class="post-metadata">

**Author:** ![Chris\_Conley](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/chris_conley/32/199055_2.png) [@Chris\_Conley](https://forum.choiceofgames.com/u/Chris_Conley)\
**Post date:** [April 15, 2020, 8:36am UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/4 "2020-04-15T08:36:06Z")

</div>

Nice. This sort of construct should really get more explicit syntax, though. Coding all the logic inside a single parentheses pair is prone to error, as @cup_half_empty pointed out.

I’ve wished CS had some proper select case statements, as well; multireplace somewhat takes the place of them, but not entirely, and not across multiple lines.

---

<div class="post-metadata">

**Author:** ![cup\_half\_empty](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/cup_half_empty/32/273983_2.png) [@cup\_half\_empty](https://forum.choiceofgames.com/u/cup_half_empty)\
**Post date:** [April 15, 2020, 12:49pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/5 "2020-04-15T12:49:09Z")

</div>

I have a halfass solution for this, but it’s not so cool as @StorybookParagon and it’s still liable to break.

> @{ (round( ((x \* n) / 100) + 0.499 )) One | Two | … | Umpteen}

Where:

- **x** is the input variable (with a value between **0.1** and 100), and
- **n** is the number of elements in the multireplace ( **starting at 2** ).

Note that:

- if x \< 0.1 the result will be _zero_! This will break the code. So x should be _at least_ 0.1;
- if x \> 100, that is, 100.1, the return will be (n + 1), which will also break the code;
- all options get the same “bandwidth”, meaning that there is no ration like in @StorybookParagon’s solution. If you have 3 options inside the multireplace, the points of inflection will be at every (100 / 3), that is, at every 33.33…. In other words, from 0 to 33.33… multireplace will return the first option, from 33.4 to 66.66…, the second and from 66.7 to 100, the third.

This should work no matter how many elements you have inside the multireplace.

Edit:

> - if x \< 0.1 the result will be _zero_! This will break the code. So x should be _at least_ 0.1;
> - if x \> 100, that is, 100.1, the return will be (n + 1), which will also break the code;

As I wrote this I realized that you can circunvent this problem if you use this:

> @{ (round( ((x \* n) / 100) + 0.5 )) One | Two | … | Umpteen | Umpteen }

**Note** that the last option in the multireplace _must be_ duplicated!

> [@Chris\_Conley](#):
>
> Coding all the logic inside a single parentheses pair is prone to error

Try writing a program in _Java_! 😂

---

<div class="post-metadata">

**Author:** ![StorybookParagon](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/storybookparagon/32/61008_2.png) [@StorybookParagon](https://forum.choiceofgames.com/u/StorybookParagon)\
**Post date:** [April 15, 2020, 1:31pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/6 "2020-04-15T13:31:38Z")

</div>

It’s a loving homage to how complicated attempting to cram everything to take up the least space. 😂

Thanks for showing how you would do it.

---

<div class="post-metadata">

**Author:** ![Nahim\_Kerman](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/nahim_kerman/32/62734_2.png) [@Nahim\_Kerman](https://forum.choiceofgames.com/u/Nahim_Kerman)\
**Post date:** [November 12, 2022, 8:25am UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/7 "2022-11-12T08:25:04Z")

</div>

> [@Chris\_Conley](#):
>
> I’ve wished CS had some proper select case statements, as well; multireplace somewhat takes the place of them, but not entirely, and not across multiple lines.

Hmmm. Good point. Maybe it’s possible?

I mean, people woking in the cs\_libs invented workarounds for more complicated things before…

---

<div class="post-metadata">

**Author:** ![Chris\_Conley](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/chris_conley/32/199055_2.png) [@Chris\_Conley](https://forum.choiceofgames.com/u/Chris_Conley)\
**Post date:** [November 12, 2022, 3:35pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/8 "2022-11-12T15:35:16Z")

</div>

Sure, it’s possible if you’re going to edit the language. You can do anything at that point.

cs\_lib is explicitly working within the existing syntax of CS, though, which means a new language feature like select case would be outside their scope.

---

<div class="post-metadata">

**Author:** ![LiliArch](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/liliarch/32/120749_2.png) [@LiliArch](https://forum.choiceofgames.com/u/LiliArch)\
**Post date:** [November 12, 2022, 3:37pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/9 "2022-11-12T15:37:34Z")

</div>

I’m curious now, what’s so special about switch-case that you can’t just utilize if-elseifs-else?

---

<div class="post-metadata">

**Author:** ![Nahim\_Kerman](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/nahim_kerman/32/62734_2.png) [@Nahim\_Kerman](https://forum.choiceofgames.com/u/Nahim_Kerman)\
**Post date:** [November 12, 2022, 3:40pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/10 "2022-11-12T15:40:25Z")

</div>

> [@Chris\_Conley](#):
>
> cs\_lib is explicitly working within the existing syntax of CS, though, which means a new language feature like select case would be outside their scope.

It would? I mean, it isn’t using the very resources of a system to implement a work/solution within the very system the essence of a classic deterministic finite automata?

---

<div class="post-metadata">

**Author:** ![Nahim\_Kerman](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/nahim_kerman/32/62734_2.png) [@Nahim\_Kerman](https://forum.choiceofgames.com/u/Nahim_Kerman)\
**Post date:** [November 12, 2022, 4:21pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/11 "2022-11-12T16:21:55Z")

</div>

That is the magic of refined logic gates like switch, do whiles and for!

They give you the ability to implement game mechanics in a structured functional way. Making the code easyer to write, read and debug than using an assortment of ifs elses gotos and whatnot.

---

<div class="post-metadata">

**Author:** ![LiliArch](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/liliarch/32/120749_2.png) [@LiliArch](https://forum.choiceofgames.com/u/LiliArch)\
**Post date:** [November 12, 2022, 4:37pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/12 "2022-11-12T16:37:33Z")

</div>

Intersting. Apart from some performance calculations and edge cases where you might need to repeat some lines of code in one but not the other, I’ve never seen switch’s and if-else’s readability and debuggability as any different. 🤔

---

<div class="post-metadata">

**Author:** ![Chris\_Conley](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/chris_conley/32/199055_2.png) [@Chris\_Conley](https://forum.choiceofgames.com/u/Chris_Conley)\
**Post date:** [November 12, 2022, 4:50pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/13 "2022-11-12T16:50:23Z")

</div>

> [@LiliArch](#):
>
> I’m curious now, what’s so special about switch-case that you can’t just utilize if-elseifs-else?

Well, sure, the same way you can create various types of loops using `*if`s and `*goto`s. Just like multireplace didn’t add any new functionality, neither would this. They both merely let authors write much more compact and readable code in a very common use case: checking a single variable against several different conditions. It also avoids the need to fill a temporary value to simplify writing an if-then-else block.

But also, every block in an if-then-else set is mutually exclusive; you can’t write a set in which some but not others may fire, which is common in switch statements. Your only way to achieve that currently is to write every condition as a standalone `*if` statement. I’d imagine, to use existing CS syntax, authors not using ICF would need to end their case blocks with a flow-control command like `*goto`, while those using ICF would have fallthrough.

Or if they don’t want fallthrough, the language could instead implement a `*continue` command.

> **Proposed syntax and example:**
>
> ```choicescript
> *switch ((populace_hate_love %+ social_engineering) + charisma)
> *case 0
> You're a nobody.
> *case < 15
> You're relatively unknown.
> *case < 50
> You have some local renown.
> *set fame %+ 10
> *continue
> *case < 30
> But not much.
> *case < 70
> You are famous statewide.
> *set fame %+ 20
> *case >= 70
> You are recognized nationwide.
> *set fame %+ 30
> *continue
> *case >= 85
> Children write essays about wanting to be you when they grow up.
> *set fame %+ 25
> *continue
> *case > 100
> The national epic is composed in your honor.
> *achieve epic
> 
> ```

> **Implementing that in if-then-else requires a temp value, repeated use of the same variable name, and multiply nested ifs:**
>
> ```choicescript
> *temp scratch_value ((populace_hate_love %+ social_engineering) + charisma)
> *if scratch_value = 0
> You're a nobody.
> *elseif scratch_value < 15
> You're relatively unknown.
> *elseif scratch_value < 50
> You have some local renown.
> *set fame %+ 10
> *if scratch_value < 30
> But not much.
> *elseif scratch_value < 70
> You are famous statewide.
> *set fame %+ 20
> *else
> You are recognized nationwide.
> *set fame %+ 30
> *if scratch_value >= 85
> Children write essays about wanting to be you when they grow up.
> *set fame %+ 25
> *if scratch_value > 100
> The national epic is composed in your honor.
> *achieve epic
> 
> ```

> [@Nahim\_Kerman](#):
>
> It would? I mean, it isn’t using the very resources of a system to implement a work/solution within the very system the essence of a classic deterministic finite automata?

I’m not sure what you’re saying here.

The goal of cs\_lib is to create complex structures using existing Choicescript syntax, not to alter the language itself by adding new commands.

---

<div class="post-metadata">

**Author:** ![Nahim\_Kerman](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/nahim_kerman/32/62734_2.png) [@Nahim\_Kerman](https://forum.choiceofgames.com/u/Nahim_Kerman)\
**Post date:** [November 12, 2022, 9:47pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/14 "2022-11-12T21:47:37Z")

</div>

> [@Chris\_Conley](#):
>
> I’m not sure what you’re saying here.

I know, the notion of automata is more a math thing than a computer thing.

But back at the 50s they used Chomsky hierarchy of language types to build a arrangement of these mechanisms in order to code the first FORTRAN compilers.

In choicescript, I believe you can use a similar approach to create simple word parsers. In fact, IRRC, @Twiger_Fluff and @nocturno developed just that for their data structure emulation functions.

I believe the key word here is an set parse automata able to “build” logical gates based on a string of intructions. After all, parsers are the base of modern code interpreter.

Coding a parser in choicescript is not impossible. But is not simple either. I remember reading about something named “Vienna Method” in a math book from the 70s. I will try to find it. Maybe a future where choicescript have proper logical functionality is not just a dream…

**And yes, I just talked about coding a freaking parser subroutine that breaks a string with a switch case written in it as a abstract syntax tree (global var names, values, logical operators, etc), identify the references (everything with an “\*” symbol is a command), execute semantic validation, converts it all in an linear code with jumps and loops then generate a effective procedure based in the string with the case as if the coder had written it with normal choicescript.**

---

<div class="post-metadata">

**Author:** ![Chris\_Conley](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/chris_conley/32/199055_2.png) [@Chris\_Conley](https://forum.choiceofgames.com/u/Chris_Conley)\
**Post date:** [November 12, 2022, 11:12pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/15 "2022-11-12T23:12:38Z")

</div>

> [@Chris\_Conley](#):
>
> Proposed syntax and example:

As another possibility, CS could also implement PHP-style reversed value checking, with a value in the `*switch` command which various variable names or expressions on the `*case` lines will be compared against.

> **And a potentially more real-world example**
>
> ```choicescript
> *temp companions 0
> *switch true
> *case with_legoland
> "You have my bow," Legoland intones.
> *set companions 1
> 
> *continue
> *case with_gilgamesh
> "@{(companions = 0) You have|And} my axe," Gilgamesh burbles.
> *set companions + 1
> 
> *continue
> *case with_borogove
> "@{(companions = 0) You have|And} my sword," Borogove brilligs.
> *set companions + 1
> 
> *continue
> *case with_hobos
> "We're not sure why we're here," the hobos mutter.
> *set companions + 3
> 
> *continue
> *case (communed_with_spirits and (rebuilt_sword and (overthrown_king and ((fame + populace_love) > 100))))
> Green ectoplasm swirls around you swirlingly.
> *set have_spirits true
> *default
> But you are all alone.
> 
> ```

---

<div class="post-metadata">

**Author:** ![Nahim\_Kerman](https://sea3.discourse-cdn.com/choiceofgames/user_avatar/forum.choiceofgames.com/nahim_kerman/32/62734_2.png) [@Nahim\_Kerman](https://forum.choiceofgames.com/u/Nahim_Kerman)\
**Post date:** [November 13, 2022, 6:25pm UTC](https://forum.choiceofgames.com/t/overcomplicated-multireplace/67380/16 "2022-11-13T18:25:36Z")

</div>

I must say I in love with your snippets!  
The hobos companions!

Thank you for you examples. I really have no idea if I can make my silly idea of a switch case as a callabe subroutine (at least without abusing the use complex first class functions to simulate the behavior of a switch gate like in other languages, in a way that the code doesn’t end actually worse than you simply doing it with if and elsifs…).

> [@Nahim\_Kerman](#):
>
> And yes, I just talked about coding a freaking parser subroutine that breaks a string with a switch case written in it as a abstract syntax tree (global var names, values, logical operators, etc), identify the references (everything with an “\*” symbol is a command), execute semantic validation, converts it all in an linear code with jumps and loops then generate a effective procedure based in the string with the case as if the coder had written it with normal choicescript.

Man I feel like a idiot for suggesting it but… It is possible, I think? probably will take the amount of effort of _single handle coding Dwarf Fortress_ though…

An choicescript _built-in_ ‘high level code interpreter’ that simply reads a custom made command (in this case, \*case, no pun intended), breaks it in a lower level linear code using an assortment of reference loop trees, reassemble it in pure choicescript them execute the damn thing in front of your eyes!

Probably will work only with global variables though… (uh)
