# TSCP - DM1 et DM2
> [name= Adriana PANGRACOVA, Alexandre PRIMAULT, Fatoumata SYLLA]
[TOC]
## Optimisation 1 du DM1
### Création des nouveaux tableaux
Pour réaliser la première optimisation nous avons commencé par créer un tableau `board[]` et `posPieces[]`. Le lien entre les 2 tableaux est : `board[a] = b` & `posPiece[b] = a`. Ses tableaux nous serviront à indexer le plateau de jeu.
### Remplissage des nouveaux tableau
Pour remplir les nouveaux tableaux, nous avons ajouté une fonction `syncBoard()` qui va synchroniser `color[]` et `piece[]` avec `board[]` (et `posPieces[]`).
Les rois auront une position fixe tandis que les autres pièces n'auront pas d'ordre fixe mais seront placées les unes à la suite des autres dans `posPieces[]`.
La synchronisation est effectuée avant de jouer dans `init_board()` et `bench()`.
### Création des fonctions de test
Pour faciliter le debug, nous avons créé une fonction `displayBoard()` qui affiche le contenu du `board[]` et `checkBoard()` qui permet de vérifier si le contenu du `board[]` est cohérent.
### (Modification des fonctions de jeu)
## Optimisation 2 du DM1
### Création du tableau de stockage des tables
Pour réaliser la deuxième optimisation nous avons commencer par créer un tableau à trois dimensions `canAttack[6][64][64]`. C'est dans ce tableau que nous allons stocker toutes les tables prégénérées des mouvements possibles pour une pièce en particulier (sauf les pions) en fonction de sa position.
### Génération des tables
Les tables mentionnées précédemment sont créées dans la fonction `initAttackTables()`. Pour faire cela, on a utilisé "l'idée général" du code de la fonction `gen()` (fonction qui regarde où peut aller une pièce). Tout d'abord, on a rempli toutes les tables avec des 0 et ce n'est que dans un second temps que nous avons rempli les tables avec des 1. On rapelle que les 1 correspondent à des cases atteignables et les 0 à des cases non atteignables.
### Modification de fonction
Par la suite il fallait modifier la fonction `attack(int sq, int s)`. Plus précisement, ajouter la condition `else if (canAttack[piece[i]][i][sq] == 1)` à la place du ***else*** (corespondant au if du test de la pièce pion).
### Ajout d'un affichage
Enfin nous avons ajouter un printf dans une boucle
pour afficher la table d'une pièce en une position choisie pour vérifier que initialisation fait bien le travail attendu.
## Optimisation 1 du DM2 : Hashing
<span style="text-decoration: underline;">Objectif:</span> L'objectf de optimisation est de remplacer la fonction `set_hash()` se trouvant à la fin de la fonction `moveback()` par des opérations XOR nécessaire sur le hash.
<span style="text-decoration: underline;">Mise en place:</span>
Tout d'abord, nous avons créé la fonction get_hash() qui est une copie intégrale de la fonction set_hash().

Ensuite, nous avons fait des opérations sur le hash dans `moveback()` partout où il y a des modifications sur la position d'une pièce. Pour des raisons de répétitions, nous avons créé une fonction `xor_hash(int i)` qui prend en argument la position (to,from...) et le remplace dans l'opération `hash ^= hash_piece[color[i]][piece[i]][i]`.

En plus, il fallait faire des opération du style `hash ^= hash_ep[ep]` et `hash ^= hash_side`.
On a utilisé plusieurs moyens pour debugger, principalement le `ASSERT(hash == get_hash())` et ensuite des printf en début et fin de bout de code où une modification de position a eu lieu.
<span style="text-decoration: underline;">exemple:</span>

## Optimisation 2 du DM2 : Apprentissage
### Ajout de la création des nombres aléatoires 64 bits
Pour ce faire, à l'aide du code fourni par mail nous avons créé la fonction suivante :
```C=
unsigned long long Aleatoire64() {
return ((unsigned long long) Aleatoire()) |
((unsigned long long) Aleatoire() << 32);
}
```
Cette fonction nous retourne un entier non signé sur 64 bits.
### Création de la hash table de learning
A partir de variables globales, on créé la table de learning en allouant la mémoire nécessaire.
```C
int learnPos = 0; // Position dans la table de learning
size_t learnSize = 100000; // Taille de la table de learning
HtLearning** learnTable;
typedef struct
{
HTTyp hash;
short score;
unsigned char depth; // Profondeur de la recherche.
} HtLearning;
void init_learn() {
learnTable = malloc(sizeof(HtLearning*)*learnSize);
for(int i=0; i<learnSize; i++) {
learnTable[i] = malloc(sizeof(HtLearning));
}
}
```
### Récupérer un index de la hash table
Soit le code ci-dessus. On récupère l'index learnPos-1 (si celui ci est different de -1, sinon le tableau dépasse).
```C
HtLearning* getLearn() {
return learnPos > 0 ? learnTable[learnPos-1] : NULL;
}
```
### Stockage dans un fichier
Soit le code ci-dessus. On vérifie si le fichier existe. S'il n'existe pas on le créé et on le rempli de structures vides après avoir appelé `init_learn()`. S'il existe, on copie son contenu dans la structure.
```C
void init_file() {
FILE *file;
init_learn();
if((file = fopen("learn.bin","r"))!=NULL) { // Si le fichier existe
for(int i=0; i<learnSize; i++) { // Lecture du fichier dans la table
fread(learnTable[i], sizeof(HtLearning), 1, file);
}
}
else {
file = fopen("learn.bin", "w");
for(int i=0; i<learnSize; i++) {
fwrite(learnTable[i], sizeof(HtLearning), 1, file);
}
}
fclose(file);
}
```
### Ajouter une donnée dans la table de learning
On ajoute une entrée dans la table et on augmente la position de 1. La donnée est ensuite synchronisée avec le fichier.
```C
void learn(int depth, int eval) {
learnPos = learnPos%(learnSize-1);
learnTable[learnPos]->hash = hash;
learnTable[learnPos]->depth = depth;
learnTable[learnPos]->score = score;
FILE *file = fopen("learn.bin","w");
fseek(file, learnPos*sizeof(HtLearning), 1);
fwrite(learnTable[learnPos], sizeof(HtLearning), 1, file);
fclose(file);
learnPos++;
}
```