Salut,
La fonction neighbours permet, comme son nom l'indique, de récupérer un vecteur comportement tous les voisins du point de coordonnée (x,y) (dans un vecteur).
Avec ça, on fait une boucle. Le premier vecteur passé à la macro for est la forme liante ; on assigne à l'élément local "dx" le vecteur [-1 0 1] et le même à l'élément local "dy". Ils représentent les directions à explorer (-1 et 1 sur un axe x, -1 et 1 sur un axe y, ça revient à dire une fois à gauche, une à droite, une en haut et une en bas).
La macro for permet de recevoir des conditions ; c'est le :when. Ici, on saute l'itération lorsque dx ET dy valent 0 en même temps (ça évite de se compter soi-même ; si on ne le faisait pas, on comptabiliserai la position d'origine du point, puisqu'on appliquerait une translation de (0,0) sur le point).
Enfin, le coeur de la boucle dit de renvoyer, à chaque itération, un vecteur. Tous les vecteurs seront `cons`ed à une liste vide pour être renvoyées à la fin. Pour chaque itération, on renvoie donc un vecteur à deux membres, chaque membre étant une position (x,y).
Au final, on se retrouve donc bien avec une liste de vecteurs de coordonnées de tous les voisins du point d'origine.
Pour la fonction count-neighbours, celle-ci compte le nombre de voisins réels sur le tableau de jeu.
Concrètement, la fonction précédente te renvoie un ensemble de points potentiellement voisins, elle se fiche de savoir s'ils existent. Si par exemple tu lui fournis en argument le point [0, 0], elle va te renvoyer 5 coordonnées qui ne sont pas sur le plateau (en considérant un plateau d'indices uniquement positifs).
Du coup, count-neighbors va vérifier s'ils existent. Elle prend en argument le tableau ("board") et la localisation du point intéressé. Examinons-là :
-> (filter #(get-in board %) (neighbours loc))
Décomposons cette première partie :
-> neighbours loc
Fonction précédente, on a une liste des voisins potentiels du point
Du coup, `filter` va appliquer à chaque élément de la liste retournée par `neighbours loc` la fonction `#(get-in board %)`. Si cette dernière renvoie vraie, on garde l'élément ; sinon on le jette.
-> #(get-in board %)
Du coup, cette fonction prend en argument (%) un vecteur contenant les coordonnées d'un point, et cherche si ce vecteur est contenu dans le plateau. Get-in est l'équivalent d'un 'get' pour les structures imbriquées, comme le tableau.
Au final, cette partie avec filter élimine donc tous les éléments retournés par la fonction neighbours qui ne sont pas réellement dans le tableau.
On enveloppe le tout dans un count, et on a donc bien le nombre total de voisins réels d'un point donné.
Voilà voilà 