# RPSSL resolution logic

:::{card} 🤔 Question to ponder
How do we determine which player has won?
:::

In other words, how do we resolve different situations into win, lose, and tie?

## Analyzing an easier game: Rock paper scissors
If we have only rock 🪨 paper 🗒️ and scissors ✂️, then we have 9 combinations for player 1 and player 2 named as `p1` and `p2`, respectively.

:::{list-table}
:width: 25%
:header-rows: 1
* - p1
  - p2
  - p1 ...
* - 🪨
  - 🪨
  - tie
* - 🪨
  - 🗒️
  - loses
* - 🪨
  - ✂️
  - wins
* - 🗒️
  - 🪨
  - wins
* - 🗒️
  - 🗒️
  - tie
* - 🗒️
  - ✂️
  - loses
* - ✂️
  - 🪨
  - loses
* - ✂️
  - 🗒️
  - wins
* - ✂️
  - ✂️
  - tie
:::

:::{card} 🤔 Question to ponder
1. How would you implement this in C?
2. Do you see any simplifications on the table that leads to less rows?
:::
<!--
1. This table could be implemented as a `if-else if-else` statement. 
2. *Tie* cases could be easily checked with a equality operation or we can just use `else`.
-->

After simplification we end up with:

:::{list-table}
:name: rps-long-table
:width: 25%
:header-rows: 1
* - p1
  - p2
  - p1 ...
* - 🪨
  - 🗒️
  - loses
* - 🪨
  - ✂️
  - wins
* - 🗒️
  - 🪨
  - wins
* - 🗒️
  - ✂️
  - loses
* - ✂️
  - 🪨
  - loses
* - ✂️
  - 🗒️
  - wins
* - else
  - 
  - tie
:::

As a result, we have 3 * 3 - 3 = 6 `if-else if` lines with Boolean expressions and one else line.

:::{activity} RPS resolution logic
:label: rps-resolution-logic
1. 3 min. Draw a flowchart for the resolution table above.
2. Implement it using the template below:
   - 3 min. using `if-else`
   - 3 min. using `switch`
3. Which solution do you prefer?
   - `if-else`
   - `switch`

```{literalinclude} ../code/masked/rps_resolution_logic_if_else.c
:language: c
```
The output should be:
```{literalinclude} ../code/rps_resolution_logic_if_else.txt
:language: text
```
:::

:::{important}
`switch` only works with integers. You cannot use it with arrays like:

```c
switch (player_tuple) {
  case {ROCK, SCISSORS}:
    ... 
}
```
:::

## Moving on to 🪨✂️🗒️🦎🖖 

In our problem we have five different items. This corresponds to 5 * 5 - 5 + 1 = 21 `if-else if-else` lines. This is too long. A better idea is to analytically describe the win-lose table:

:::{commons-figure} https://commons.wikimedia.org/wiki/File:Pierre_ciseaux_feuille_l%C3%A9zard_spock_aligned.svg
:name: rpsls-resolution-diagram 
:figwidth: 35%
:align: right
rock paper scissors lizard Spock resolution diagram
:::

Let us try to extract a pattern from the resolution diagram in {numref}`rpsls-resolution-diagram`. Assume that clock-wise rotation is a forwards direction.

In the diagram we see that Spock wins against scissors and stone, which are +1 and +3 forward in the circle. Spock loses against lizard and paper, which are +2 and +4 forward in the circle. In other words, if the second shape is +1 and +3 away, Spock wins, and if the second shape is +2 and +4 shapes away, then Spock loses.

:::{card} 🤔 Question to ponder
Does the rule described above apply to all shapes? Why?
<!--
Indeed there is a symmetry in the diagram and this rule applies to all items.
-->
:::

## Describing the resolution using the distance between shapes

If we generalize our rule for all items, we get:

> If the second item is +1 or +3 away, then the first item wins.  If the second item is +2 or +4 away, then the first item loses.

How can we determine if the second item is +1 or +3 away, i.e the distance? An idea is to attach numbers to all items, for example:

0. Spock
1. scissors
2. paper
3. rock
4. lizard

The numbers 0 to 4 become their ids. Now we can determine the distance by subtracting their ids.

Example: rock vs lizard. lizard's id is 4, and rock's id is 3, so we get 4-3=1, which means that rock wins against the lizard. The resolution diagram confirms this.

This approach can be summarized as a table, where `id1` and `id2` stand for the ids of the items.

:::{list-table}
:width: 20%
:header-rows: 1
* - p2-p1
  - p1 ...
* - 0
  - tie
* - 1 or 3
  - wins
* - 2 or 4
  - loses
:::

:::{card} 🤔 Question to ponder
This was too fast. Do you see any problems with this table?
:::

## Expanding the resolution table

What happens if p1's id is greater than p2's id? Then we get negative numbers. For example for `p1 = 4` and `p2 = 0`, we get `p2 - p1 = -4`. 4 means lizard and 0 Spock; and lizard wins against Spock. 

We can look at the negative numbers from another perspective. -4 means a counter-clockwise turn, which is the same as if we moved 1 clockwise. So we can extend the table as follows:

:::{list-table}
:width: 30%
:header-rows: 1
* - p2-p1
  - p1 ...
* - 0
  - tie
* - -4 or -2 or 1 or 3
  - wins
* - -3 or -1 or 2 or 4
  - loses
:::

:::{activity} RPSSL resolution logic using difference between shapes
:label: rpssl-resolution-logic-using-difference-switch
Implement the resolution logic above either with
1. `if-else ...` or
1. `switch` 
statement.

Two students with different approaches will demonstrate and we will compare.

Use the following template. Your output should be the same as the output below.
```{literalinclude} ../code/masked/rpssl_resolution_logic_switch.c
:language: c
```
```{literalinclude} ../code/rpssl_resolution_logic_switch.txt
:language: text
```
:::

## Appendix

- {ref}`further-minimization-ideas-on-rpsls-resolution-logic`