# Guide pratique du Redstone Language

Ce guide apprend a programmer les blocs `Redstone Computer` et `Redstone Controller`
du mod `redstone_computer`. L'objectif n'est pas de tout memoriser, mais de
comprendre le modele mental et de savoir construire des petits circuits utiles.

Pour la reference complete des instructions, voir `REDSTONE_LANGUAGE.md`.

## 1. Le modele mental

Un programme redstone tourne comme une petite puce logique.

Chaque tick serveur :

1. Le bloc lit la puissance redstone sur ses 6 faces.
2. Si toutes les entrees valent `0`, il dort.
3. Si au moins une entree vaut plus que `0`, il execute le programme depuis le
   debut.
4. Les sorties redstone et le comparateur sont remis a `0` au debut du tick.
5. Le programme peut lire les entrees, calculer, ecrire des sorties, lire des
   items, bouger des items et utiliser la RAM.

Important : les registres `A`, `B`, `C`, `D` sont temporaires et repartent a `0`
a chaque tick. La RAM, elle, reste sauvegardee dans le bloc.

## 2. Les faces du bloc

Tu peux lire ou ecrire sur les 6 directions Minecraft :

| Nom | Alias | Usage |
| --- | --- | --- |
| `NORTH` | `N` | face nord |
| `SOUTH` | `S` | face sud |
| `EAST` | `E` | face est |
| `WEST` | `W` | face ouest |
| `UP` | `TOP`, `U` | dessus |
| `DOWN` | `BOTTOM`, `D` | dessous |

Exemple :

```asm
LD A, WEST
OUT EAST, A
HALT
```

Ce programme lit le signal qui arrive a l'ouest et le renvoie a l'est.

## 3. Premier programme : un relais

Branchement :

- levier ou signal redstone a l'ouest du Computer ;
- lampe redstone a l'est du Computer.

Programme :

```asm
LD A, WEST
OUT EAST, A
COMPARE A
HALT
```

Ce que ca fait :

- `LD A, WEST` met la puissance de l'ouest dans le registre `A`.
- `OUT EAST, A` sort cette puissance a l'est.
- `COMPARE A` donne la meme valeur a un comparateur colle au bloc.
- `HALT` arrete le programme pour ce tick.

## 4. Les valeurs utiles

Le langage manipule des valeurs de `0` a `255`, mais les sorties redstone sont
limitees a `0..15`.

Tu peux ecrire :

```asm
LD A, 15
LD B, 0xFF
LD C, $0F
LD D, %1010
LD A, ON
LD B, OFF
```

Notes :

- `ON` et `TRUE` valent `15`.
- `OFF` et `FALSE` valent `0`.
- `0xFF` et `$FF` sont de l'hexadecimal.
- `%1010` est du binaire.

## 5. Faire une porte logique

### AND

La sortie s'allume seulement si l'ouest et le nord sont allumes.

```asm
LD A, WEST
BOOL A
LD B, NORTH
BOOL B
AND A, B
OUT EAST, A
HALT
```

### OR

La sortie s'allume si l'ouest ou le nord est allume.

```asm
LD A, WEST
BOOL A
LD B, NORTH
BOOL B
OR A, B
OUT EAST, A
HALT
```

### NOT

La sortie s'allume quand l'entree ouest est eteinte.

```asm
LD A, WEST
BOOL A
EQ A, 0
OUT EAST, A
HALT
```

Ici `EQ A, 0` transforme `A` en `15` si `A` vaut `0`, sinon en `0`.

## 6. Conditions et labels

Un label est un nom suivi de `:`. On saute vers un label avec `JMP`, `JZ`, `JNZ`,
`JC` ou `JNC`.

Exemple : si le signal ouest est eteint, on eteint la sortie. Sinon, on allume.

```asm
LD A, WEST
BOOL A
JZ off

OUT EAST, 15
HALT

off:
OUT EAST, 0
HALT
```

Apres `BOOL A`, si `A` vaut `0`, le flag `ZERO` est actif. Donc `JZ off` saute
vers `off`.

## 7. Comparer des signaux

Branchement :

- signal A a l'ouest ;
- signal B au nord ;
- lampe a l'est.

Programme :

```asm
LD A, WEST
GT A, NORTH
OUT EAST, A
COMPARE A
HALT
```

La sortie est a `15` si `WEST` est plus grand que `NORTH`, sinon `0`.

Comparaisons disponibles :

| Instruction | Sens |
| --- | --- |
| `EQ A, value` | egal |
| `NE A, value` | different |
| `GT A, value` | plus grand |
| `LT A, value` | plus petit |
| `GE A, value` | plus grand ou egal |
| `LE A, value` | plus petit ou egal |

## 8. Utiliser la RAM

La RAM sert a garder un etat entre les ticks.

Le `Redstone Computer` a `256` bytes. Le `Redstone Controller` a `1024` bytes.

Exemple : une memoire ON/OFF tres simple.

Branchement :

- bouton SET a l'ouest ;
- bouton RESET au nord ;
- lampe a l'est.

Programme :

```asm
LD A, WEST
BOOL A
JZ check_reset
LD [0], 15

check_reset:
LD A, NORTH
BOOL A
JZ output
LD [0], 0

output:
LD A, [0]
OUT EAST, A
COMPARE A
HALT
```

La cellule `[0]` garde l'etat de la memoire.

## 9. Faire une horloge interne

Ce programme alterne une sortie est en utilisant la RAM.

Branchement :

- une alimentation permanente a l'ouest ;
- lampe a l'est.

Programme :

```asm
LD A, [0]
INC A
LD [0], A

AND A, 8
BOOL A
OUT EAST, A
COMPARE A
HALT
```

La valeur `[0]` augmente a chaque tick alimente. `AND A, 8` isole un bit pour
faire une alternance lente.

## 10. Lire des items

Le bloc a deux slots :

- slot d'entree : les hoppers peuvent y mettre des items ;
- slot de sortie : les hoppers peuvent extraire par dessous.

Instructions utiles :

| Instruction | Effet |
| --- | --- |
| `MATCH A, minecraft:diamond` | met `A` a `15` si l'item d'entree est un diamant |
| `COUNT A` | compte les items dans l'entree |
| `COUNT A, minecraft:diamond` | compte seulement les diamants |
| `PUSH 1` | deplace 1 item de l'entree vers le slot de sortie |
| `ROUTE DOWN, 1` | deplace 1 item vers l'inventaire sous le bloc |
| `ROUTEIF A, EAST, 1` | route vers l'est seulement si `A > 0` |

Exemple : accepter seulement les diamants.

Branchement :

- hopper d'offrande vers le Computer ;
- coffre sous le Computer ;
- lampe a l'est.

Programme :

```asm
MATCH A, minecraft:diamond
JZ reject

ROUTE DOWN, 1
LD B, A
EQ B, 1
OUT EAST, B
COMPARE B
HALT

reject:
OUT EAST, 0
COMPARE 0
HALT
```

`ROUTE DOWN, 1` consomme vraiment le diamant en l'envoyant dans le coffre du
dessous. Apres `ROUTE`, le registre `A` contient le nombre d'items deplaces.

## 11. Rituel pluie + offrande

But : quand il pleut, deposer un diamant dans le hopper lance un signal vers un
command block `weather clear`.

Branchement recommande :

- `Rain Detector` au-dessus du Controller ;
- hopper d'offrande au sud, pointe vers le Controller ;
- coffre sous le Controller pour recevoir le diamant consomme ;
- command block a l'ouest, regle en `Impulse`, `Unconditional`, `Needs Redstone` ;
- lampe ou effet rituel a l'est.

Programme :

```asm
LD A, UP
BOOL A
JZ idle

MATCH B, minecraft:diamond
JZ idle

ROUTE DOWN, 1
LD B, A
EQ B, 1
JZ idle

OUT EAST, 15
OUT WEST, 15
COMPARE 15
HALT

idle:
OUT EAST, 0
OUT WEST, 0
COMPARE 0
HALT
```

Pourquoi c'est fiable :

- sans pluie, `UP` vaut `0`, donc rien ne part ;
- sans diamant, `MATCH` echoue ;
- si le diamant ne peut pas etre consomme, `ROUTE DOWN, 1` renvoie `0`, donc le
  command block ne se declenche pas ;
- la sortie ouest pulse seulement quand l'offrande a vraiment ete prise.

Attention : le signal du capteur de pluie ne doit pas alimenter directement le
command block ni bloquer le hopper. Seule la sortie `WEST` du Controller doit
aller vers le command block.

## 12. Convention bus du Controller

Le Controller a une convention pratique pour controler plusieurs Computers.

| Alias | Face physique | Idee |
| --- | --- | --- |
| `BUS_IN` | `WEST` en entree | donnees entrantes |
| `BUS_OUT` | `EAST` en sortie | donnees sortantes |
| `CLOCK` | `NORTH` | rythme |
| `READY` | `SOUTH` | accuse de reception / pret |
| `MODE` | `UP` | mode |
| `RESET` | `DOWN` | reset |

Exemple de relais bus :

```asm
LD A, BUS_IN
LD B, CLOCK
OUT BUS_OUT, A
OUT READY, B
COMPARE A
HALT
```

Note : `LD A, BUS` lit l'ouest, mais `OUT BUS, A` ecrit a l'est. Le sens depend
du contexte lecture/ecriture.

## 13. Petites recettes de code

### Repeater avec seuil

Sortie est seulement si l'ouest vaut au moins `8`.

```asm
LD A, WEST
GE A, 8
OUT EAST, A
HALT
```

### Multiplexeur simple

Si `UP` est allume, envoyer `NORTH`; sinon envoyer `WEST`.

```asm
LD A, UP
BOOL A
JZ use_west

LD B, NORTH
OUT EAST, B
HALT

use_west:
LD B, WEST
OUT EAST, B
HALT
```

### Deux sorties selon l'item

Diamant vers le bas, le reste vers l'est.

```asm
MATCH A, minecraft:diamond
JZ reject

ROUTE DOWN, 1
OUT SOUTH, 15
HALT

reject:
ROUTE EAST, 1
OUT SOUTH, 0
HALT
```

## 14. Redstone I/O Extender

Le `Redstone I/O Extender` sert a ajouter des ports redstone a un Controller.
Il peut fonctionner comme module de sortie adressable, ou comme module d'entree
compactee.

Clic droit sur le bloc :

- mode `OUTPUT` : `WEST` = data, `NORTH` = clock, `EAST/SOUTH/UP/DOWN` =
  sorties memorisees ;
- mode `INPUT` : `EAST/SOUTH/UP/DOWN` entrent, `WEST` sort une valeur `0..15`.

### Mode OUTPUT

En mode `OUTPUT`, l'Extender est adressable et stateful.

Branchement :

- Controller a l'ouest ;
- I/O Extender juste a l'est du Controller ;
- ligne `CLOCK_OUT` du Controller vers la face `NORTH` de l'Extender ;
- lampes sur les faces `EAST`, `SOUTH`, `UP`, `DOWN` de l'Extender.

Table des adresses :

| Adresse | Sortie physique |
| --- | --- |
| `0` | `EAST` |
| `1` | `SOUTH` |
| `2` | `UP` |
| `3` | `DOWN` |

Protocole :

1. Mettre l'adresse sur `WEST`.
2. Faire un pulse sur `NORTH`.
3. Mettre la valeur `0..15` sur `WEST`.
4. Faire un pulse sur `NORTH`.

Exemple manuel :

```txt
BUS = 3, CLOCK pulse
BUS = 15, CLOCK pulse
```

Resultat : la sortie `DOWN` reste a `15`, meme si le bus change ensuite.

Programme Controller pour ecrire une fois `DOWN = 15` :

```asm
LD A, [0]
EQ A, 0
JNZ addr_high

LD A, [0]
EQ A, 1
JNZ addr_low

LD A, [0]
EQ A, 2
JNZ value_high

LD A, [0]
EQ A, 3
JNZ value_low

OUT BUS_OUT, 0
OUT CLOCK_OUT, 0
HALT

addr_high:
OUT BUS_OUT, 3
OUT CLOCK_OUT, 15
LD [0], 1
HALT

addr_low:
OUT BUS_OUT, 3
OUT CLOCK_OUT, 0
LD [0], 2
HALT

value_high:
OUT BUS_OUT, 15
OUT CLOCK_OUT, 15
LD [0], 3
HALT

value_low:
OUT BUS_OUT, 15
OUT CLOCK_OUT, 0
LD [0], 4
HALT
```

La RAM `[0]` sert de machine d'etat pour envoyer les deux pulses proprement.

### Mode INPUT

Branchement :

- I/O Extender a l'est du Controller ;
- sortie `WEST` de l'Extender vers une entree du Controller ;
- boutons ou leviers sur `EAST`, `SOUTH`, `UP`, `DOWN` de l'Extender.

L'Extender recompresse les entrees en une valeur :

```txt
EAST  = +1
SOUTH = +2
UP    = +4
DOWN  = +8
```

Programme Controller :

```asm
LD A, EAST
COMPARE A
HALT
```

Si `EAST` et `UP` de l'Extender sont allumes, le Controller lit `5`.

## 15. Redstone Display Matrix

Le `Redstone Display Matrix` est un afficheur dynamique.

Il peut afficher un caractere Unicode et une couleur Minecraft. Comme le bus
redstone ne transporte que `0..15`, on ecrit le caractere par petits morceaux de
4 bits, appeles nibbles.

Branchement :

- Controller a l'ouest ;
- Display Matrix juste a l'est du Controller ;
- `BUS_OUT` du Controller vers `WEST` du Display Matrix ;
- `CLOCK_OUT` du Controller vers `NORTH` du Display Matrix.

Protocole :

1. Mettre le numero de registre sur `WEST`.
2. Faire un pulse sur `NORTH`.
3. Mettre la valeur `0..15` sur `WEST`.
4. Faire un pulse sur `NORTH`.

Registres :

| Registre | Role |
| --- | --- |
| `0` | codepoint bits `0..3` |
| `1` | codepoint bits `4..7` |
| `2` | codepoint bits `8..11` |
| `3` | codepoint bits `12..15` |
| `4` | codepoint bits `16..19` |
| `5` | codepoint bits `20..23` |
| `6` | couleur Minecraft `0..15` |
| `15` | reset vers espace blanc |

Exemple : `A` vaut `0x0041`.

```txt
registre 0 = 1
registre 1 = 4
registre 2 = 0
registre 3 = 0
registre 4 = 0
registre 5 = 0
registre 6 = 14
```

Couleurs :

| Id | Couleur |
| --- | --- |
| `0` | white |
| `1` | orange |
| `2` | magenta |
| `3` | light_blue |
| `4` | yellow |
| `5` | lime |
| `6` | pink |
| `7` | gray |
| `8` | light_gray |
| `9` | cyan |
| `10` | purple |
| `11` | blue |
| `12` | brown |
| `13` | green |
| `14` | red |
| `15` | black |

Programme Controller de demo : afficher `A` en rouge.

```asm
LD A, [0]
EQ A, 0
JNZ r0_high
LD A, [0]
EQ A, 1
JNZ r0_low
LD A, [0]
EQ A, 2
JNZ v0_high
LD A, [0]
EQ A, 3
JNZ v0_low
LD A, [0]
EQ A, 4
JNZ r1_high
LD A, [0]
EQ A, 5
JNZ r1_low
LD A, [0]
EQ A, 6
JNZ v1_high
LD A, [0]
EQ A, 7
JNZ v1_low
LD A, [0]
EQ A, 8
JNZ rc_high
LD A, [0]
EQ A, 9
JNZ rc_low
LD A, [0]
EQ A, 10
JNZ vc_high
LD A, [0]
EQ A, 11
JNZ vc_low
OUT BUS_OUT, 0
OUT CLOCK_OUT, 0
HALT

r0_high:
OUT BUS_OUT, 0
OUT CLOCK_OUT, 15
LD [0], 1
HALT
r0_low:
OUT BUS_OUT, 0
OUT CLOCK_OUT, 0
LD [0], 2
HALT
v0_high:
OUT BUS_OUT, 1
OUT CLOCK_OUT, 15
LD [0], 3
HALT
v0_low:
OUT BUS_OUT, 1
OUT CLOCK_OUT, 0
LD [0], 4
HALT

r1_high:
OUT BUS_OUT, 1
OUT CLOCK_OUT, 15
LD [0], 5
HALT
r1_low:
OUT BUS_OUT, 1
OUT CLOCK_OUT, 0
LD [0], 6
HALT
v1_high:
OUT BUS_OUT, 4
OUT CLOCK_OUT, 15
LD [0], 7
HALT
v1_low:
OUT BUS_OUT, 4
OUT CLOCK_OUT, 0
LD [0], 8
HALT

rc_high:
OUT BUS_OUT, 6
OUT CLOCK_OUT, 15
LD [0], 9
HALT
rc_low:
OUT BUS_OUT, 6
OUT CLOCK_OUT, 0
LD [0], 10
HALT
vc_high:
OUT BUS_OUT, 14
OUT CLOCK_OUT, 15
LD [0], 11
HALT
vc_low:
OUT BUS_OUT, 14
OUT CLOCK_OUT, 0
LD [0], 12
HALT
```

Le comparateur colle au Display Matrix donne la couleur courante.

## 16. Debug rapide

Quand un programme ne marche pas :

1. Mets `COMPARE A` pour voir la valeur d'un registre avec un comparateur.
2. Teste d'abord un relais simple `LD A, WEST / OUT EAST, A`.
3. Verifie que le bloc est alimente, sinon le programme ne tourne pas.
4. Verifie les directions : `OUT EAST` alimente le bloc a l'est du Computer.
5. Pour les hoppers, verifie qu'ils ne sont pas alimentes par redstone, sinon ils
   se bloquent.
6. Pour `ROUTE`, mets toujours un coffre ou un inventaire sur la face visee.

## 17. Mini pense-bete

```asm
; lire une entree
LD A, WEST

; transformer en signal propre 0 ou 15
BOOL A

; ecrire une sortie
OUT EAST, A

; ecrire le comparateur
COMPARE A

; lire/ecrire la RAM
LD A, [0]
LD [0], A

; tester un item
MATCH A, minecraft:diamond

; bouger un item
ROUTE DOWN, 1

; condition
JZ label
JNZ label

; finir
HALT
```
