The Code

A C Implementation
struct stNode { uint8_t key; stNode *left, *right, *parent; void* data; }; stNode* root; // variation on a theme - a non recursive insert that uses // a while loop to navigate to the right empty location bool stInsert(uint16_t key, cBoard* dta, stNode** root) { stNode* leaf = *root; stNode* parent = NULL; while (leaf) { parent = leaf; if (key < leaf->key) { leaf = leaf->left; } else { leaf = leaf->right; } } // leaf is NULL so empty location found leaf = (stNode*)malloc(sizeof(stNode)); leaf->left = leaf->right = NULL; leaf->key = key; leaf->parent = parent; leaf->data = malloc(sizeof(cBoard)); if (leaf->data) { memcpy(leaf->data, dta, sizeof(cBoard)); } if (parent == NULL) { *root = leaf; } else { if (key < parent->key) { parent->left = leaf; } else { parent->right = leaf; } } splay(leaf); return true; } void splay(stNode* leaf) { while (leaf->parent) { if (leaf->parent->parent == NULL) { if (leaf == leaf->parent->left) { stRightRotate(leaf->parent); } else { stLeftRotate(leaf->parent); } } else if (leaf == leaf->parent->left && leaf->parent == leaf->parent->parent->left) { stRightRotate(leaf->parent->parent); stRightRotate(leaf->parent); } else if (leaf == leaf->parent->right && leaf->parent == leaf->parent->parent->right) { stLeftRotate(leaf->parent->parent); stLeftRotate(leaf->parent); } else if (leaf == leaf->parent->left && leaf->parent == leaf->parent->parent->right) { stRightRotate(leaf->parent); stLeftRotate(leaf->parent); } else { stLeftRotate(leaf->parent); stRightRotate(leaf->parent); } } } cBoard* stFind(uint8_t key, bool doSplay) { stNode* found = stFindNode(key, root); if (found) { if (doSplay) { splay(found); } return (cBoard*)found->data; } return NULL; } stNode* stFindNode(uint8_t key, stNode* leaf) { if (leaf) { if (key == leaf->key) { return leaf; } if (key < leaf->key) { return stFindNode(key, leaf->left); } return stFindNode(key, leaf->right); } return NULL; } bool stDeleteNode(uint8_t key) { stNode* found = stFindNode(key, root); if (found == NULL) { return false; } splay(found); // does this node have children to take it's place? if (found->left == NULL) { stSwap(found, found->right); } else if (found->right == NULL) { stSwap(found, found->left); } else { // two children stNode* next = stMinimum(found->right); if (next->parent != found) { stSwap(next, next->right); next->right = found->right; next->right->parent = next; } stSwap(found, next); next->left = found->left; next->left->parent = next; } free(found->data); free(found); return true; } void stSwap(stNode* a, stNode* b) { if (a->parent == NULL) { root = b; } else if (a == a->parent->left) { a->parent->left = b; } else { a->parent->right = b; } if (b) { b->parent = a->parent; } } stNode* stMinimum(stNode* leaf) { while (leaf->left) { leaf = leaf->left; } return leaf; } void stLeftRotate(stNode *node) { stNode *child = node->right; if (child) { node->right = child->left; if (child->left) { child->left->parent = node; } child->parent = node->parent; } if (!node->parent) { root = child; } else if (node == node->parent->left) { node->parent->left = child; } else { node->parent->right = child; } if (child) { child->left = node; } node->parent = child; } void stRightRotate(stNode *node) { stNode *child = node->left; if (child) { node->left = child->right; if (child->right) { child->right->parent = node; } child->parent = node->parent; } if (!node->parent) { root = child; } else if (node == node->parent->left) { node->parent->left = child; } else { node->parent->right = child; } if (child) { child->right = node; } node->parent = child; } void stDeleteTree(stNode* leaf) { if (leaf) { stDeleteTree(leaf->left); stDeleteTree(leaf->right); free(leaf->data); free(leaf); } } int stMax(int a, int b) { return (a <= b) ? b : a; } int stHeight(stNode* leaf) { if (leaf) { return 1 + stMax(stHeight(leaf->left), stHeight(leaf->right)); } return 0; }


main() demo code
#include "stdafx.h" #include "stdafx.h" #include <stdint.h> #include <stdlib.h> #include <iostream> enum Players { WHT, BLK }; uint8_t nextMove = WHT; enum Pieces { PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING }; char pNames[][7] = { "Pawn", "Rook", "Knight", "Bishop", "Queen", "King" }; char pSymbol[] = { 'P', 'R', 'N', 'B', 'Q', 'K' }; struct cBoard { uint8_t player; uint8_t piece; }; void playGame(); void makeMove(uint8_t from, uint8_t to); void castleMove(uint8_t f1, uint8_t f2, uint8_t t1, uint8_t t2); void setupBoard(); void displayBoard(); bool stInsert(uint16_t key, cBoard * dta, stNode ** root); void splay(stNode * leaf); cBoard * stFind(uint8_t key, bool doSplay); stNode * stFindNode(uint8_t key, stNode * leaf); bool stDeleteNode(uint8_t key); void stSwap(stNode * a, stNode * b); stNode * stMinimum(stNode * leaf); void stLeftRotate(stNode * node); void stRightRotate(stNode * node); void stDeleteTree(stNode * leaf); int stMax(int a, int b); int stHeight(stNode * leaf); int main() { setupBoard(); displayBoard(); playGame(); std::cin.get(); return 0; } void playGame() { uint8_t cOpt = 0; uint8_t moves[][2] = { { 13,29 },{ 53,37 },{ 7,13 },{ 58,43 },{ 2,19 },{ 62,35 }, { 13,23 },{ 52,44 },{ 12,20 },{ 63,46 },{ 3,39 },{ 59,45 },{ 23,40 },{ 0,0 }, { 19,36 },{ 46,29 },{ 39,60 },{ 35,14 },{ 5,13 },{ 45,31 } }; uint8_t cstlmoves[][4] = { { 61,64,63,62 } }; for (int i = 0; i < sizeof(moves) / 2; i++) { if (moves[i][0] == 0) { castleMove(cstlmoves[cOpt][0], cstlmoves[cOpt][1], cstlmoves[cOpt][2], cstlmoves[cOpt][3]); cOpt++; // max is 2 per game } else { makeMove(moves[i][0], moves[i][1]); } } std::cout << "Checkmate!\n"; } void makeMove(uint8_t from, uint8_t to) { cBoard* fSquare = stFind(from, false); cBoard* tSquare = stFind(to, false); if (fSquare) { if (fSquare->player == nextMove) { if (tSquare == NULL || tSquare->player != nextMove) { if (tSquare) { stDeleteNode(to); } stInsert(to, fSquare, &root); stDeleteNode(from); } else { std::cout << "Target square invalid\n"; } } else { std::cout << "Not your move\n"; } } nextMove = (nextMove == WHT) ? BLK : WHT; //whose move next displayBoard(); } // OK the castle move needs different validation so // as this is not intended as a chess playing game demo // this function is a bodge to allow the move void castleMove(uint8_t f1, uint8_t f2, uint8_t t1, uint8_t t2) { cBoard* f1Square = stFind(f1, false); cBoard* f2Square = stFind(f2, false); stInsert(t1, f1Square, &root); stDeleteNode(f1); stInsert(t2, f2Square, &root); stDeleteNode(f2); nextMove = (nextMove == WHT) ? BLK : WHT; //whose move next displayBoard(); } void setupBoard() { cBoard wSquare = { WHT, PAWN }, bSquare = { BLK, PAWN }; for (int i = 1; i < 9; i++) { wSquare.piece = bSquare.piece = PAWN; stInsert(i + 8, &wSquare, &root); stInsert(i + 48, &bSquare, &root); switch (i) { case 1: case 8: wSquare.piece = bSquare.piece = ROOK; break; case 2: case 7: wSquare.piece = bSquare.piece = KNIGHT; break; case 3: case 6: wSquare.piece = bSquare.piece = BISHOP; break; case 4: wSquare.piece = bSquare.piece = QUEEN; break; case 5: wSquare.piece = bSquare.piece = KING; break; } stInsert(i, &wSquare, &root); stInsert(i + 56, &bSquare, &root); } } void displayBoard() { cBoard* square; std::cout << "Board Positions\n"; for (int i = 0; i < 8; i++) { for (int j = 1; j < 9; j++) { square = stFind(j + i * 8, false); if (square) { std::cout << (square->player == WHT ? pSymbol[square->piece] : (char)(pSymbol[square->piece] + 32)); } else { std::cout << ' '; } } std::cout << '\n'; } std::cout << "________\n"; }


setup() demo code
enum Players {WHT, BLK}; uint8_t nextMove = WHT; enum Pieces {PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING}; char pNames[][7] = {"Pawn", "Rook", "Knight", "Bishop", "Queen", "King"}; char pSymbol[] = {'P', 'R', 'N', 'B', 'Q', 'K'}; struct cBoard{ uint8_t player; uint8_t piece; }; template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; } void setup() { Serial.begin(115200); setupBoard(); displayBoard(); Serial << "Height: " << stHeight(root) << '\n'; playGame(); Serial << "Height: " << stHeight(root) << '\n'; } void playGame() { uint8_t cOpt = 0; uint8_t moves[][2] = {{13,29},{53,37},{7,13},{58,43},{2,19},{62,35},          {13,23},{52,44},{12,20},{63,46},{3,39},{59,45},{23,40},{0,0},          {19,36},{46,29},{39,60},{35,14},{5,13},{45,31}}; uint8_t cstlmoves[][4] = {{61,64,63,62}}; for (int i = 0; i < sizeof(moves) / 2; i++) {     if(moves[i][0] == 0) {      castleMove(cstlmoves[cOpt][0], cstlmoves[cOpt][1], cstlmoves[cOpt][2], cstlmoves[cOpt][3]);      cOpt++; // max is 2 per game     } else {      makeMove(moves[i][0], moves[i][1]);     } } Serial << "Checkmate!\n"; } void makeMove(uint8_t from, uint8_t to) { cBoard* fSquare = stFind(from, false); cBoard* tSquare = stFind(to, false); if(fSquare) {     if(fSquare->player == nextMove) {      if(tSquare == NULL || tSquare->player != nextMove) {         // probably a valid move but you could write a lot more         // validation to check route is clear if not knight and         // distance allowed and from and to not the same etc.         if(tSquare) {          stDeleteNode(to);         }         stInsert(to, fSquare, &root);         stDeleteNode(from);      } else {         Serial << "Target square invalid\n";      }     } else {      Serial << "Not your move\n";     } } nextMove = (nextMove == WHT)? BLK : WHT; //whose move next displayBoard(); } // OK the castle move needs different validation so // as this is not intended as a chess playing game demo // this function is a bodge to allow the move void castleMove(uint8_t f1, uint8_t f2, uint8_t t1, uint8_t t2) { cBoard* f1Square = stFind(f1, false); cBoard* f2Square = stFind(f2, false); stInsert(t1, f1Square, &root); stDeleteNode(f1); stInsert(t2, f2Square, &root); stDeleteNode(f2); nextMove = (nextMove == WHT)? BLK : WHT; //whose move next displayBoard(); } void setupBoard() { cBoard wSquare = {WHT, PAWN}, bSquare = {BLK, PAWN}; for(int i = 1; i < 9; i++) {     wSquare.piece = bSquare.piece = PAWN;     stInsert(i + 8, &wSquare, &root);     stInsert(i + 48, &bSquare, &root);     switch(i) {      case 1:      case 8:         wSquare.piece = bSquare.piece = ROOK;         break;      case 2:      case 7:         wSquare.piece = bSquare.piece = KNIGHT;         break;      case 3:      case 6:         wSquare.piece = bSquare.piece = BISHOP;         break;      case 4:         wSquare.piece = bSquare.piece = QUEEN;         break;      case 5:         wSquare.piece = bSquare.piece = KING;         break;     }     stInsert(i, &wSquare, &root);     stInsert(i + 56, &bSquare, &root); } } void displayBoard() { cBoard* square; Serial << "Board Positions\n"; for(int i = 0; i < 8; i++) {     for(int j = 1; j < 9; j++) {      square = stFind(j + i * 8, false);      if(square) {         Serial << (square->player == WHT ? pSymbol[square->piece] : (char)(pSymbol[square->piece]+32));      }else {         Serial << ' ';      }     }     Serial << '\n'; } Serial << "________\n"; }


SplayTree.h
#pragma once #ifndef SplayTree_h #define SplayTree_h template<typename T, typename K> class SplayTree { public: using stIter = void(*)(K, T*); using stIterP = void(*)(K, int); SplayTree(); ~SplayTree(); bool insert(K, T*); T* find(K, bool); bool deleteNode(K); int height(); void iterateLevel(int, stIter); void iterateLevel(int, stIterP, int); private: size_t nodeSize, tSize; struct stNode { K key; stNode *left, *right, *parent; void* data; }; stNode* root; bool stInsert(K, T*, stNode**); void splay(stNode*); T* stFind(K, bool); stNode* stFindNode(K, stNode*); bool stDeleteNode(K); void stSwap(stNode*, stNode*); stNode* stMinimum(stNode*); void stLeftRotate(stNode*); void stRightRotate(stNode*); void stDeleteTree(stNode*); int stMax(int, int); int stHeight(stNode*); void stIterateLevel(int, stIter, stNode*); void stIterateLevel(int, stIterP, stNode*, int, int); }; //Constructor / Destructor template<typename T, typename K> SplayTree<T, K>::SplayTree() { tSize = sizeof(T); nodeSize = sizeof(stNode); } template<typename T, typename K> SplayTree<T, K>::~SplayTree() { stDeleteTree(root); } //public Methods template<typename T, typename K> bool SplayTree<T, K>::insert(K key, T* data) { return stInsert(key, data, &root); } template<typename T, typename K> T* SplayTree<T, K>::find(K key, bool doSplay) { return stFind(key, doSplay); } template<typename T, typename K> bool SplayTree<T, K>::deleteNode(K key) { return stDeleteNode(key); } template<typename T, typename K> int SplayTree<T, K>::height() { return stHeight(root); } template<typename T, typename K> void SplayTree<T, K>::iterateLevel(int level, stIter callBack) { stIterateLevel(level, callBack, root); } template<typename T, typename K> void SplayTree<T, K>::iterateLevel(int level, stIterP callBack, int m) { stIterateLevel(level, callBack, root, m, m); } //private Methods template<typename T, typename K> bool SplayTree<T, K>::stInsert(K key, T* data, stNode** root) { // variation on a theme - a non recursive insert that uses // a while loop to navigate to the right empty location stNode* leaf = *root; stNode* parent = NULL; bool retVal = true; while (leaf) { parent = leaf; if (key < leaf->key) { leaf = leaf->left; } else { leaf = leaf->right; } } // leaf is NULL so empty location found leaf = (stNode*)malloc(nodeSize); if (leaf) { leaf->left = leaf->right = NULL; leaf->key = key; leaf->parent = parent; leaf->data = malloc(tSize); if (leaf->data) { memcpy(leaf->data, data, tSize); if (parent == NULL) { *root = leaf; //first node to be inserted } else { if (key < parent->key) { parent->left = leaf; } else { parent->right = leaf; } splay(leaf); return true; } } else { free(leaf); } } return false; } template<typename T, typename K> void SplayTree<T, K>::splay(stNode* leaf) { while (leaf->parent) { if (leaf->parent->parent == NULL) { if (leaf == leaf->parent->left) { stRightRotate(leaf->parent); } else { stLeftRotate(leaf->parent); } } else if (leaf == leaf->parent->left && leaf->parent == leaf->parent->parent->left) { stRightRotate(leaf->parent->parent); stRightRotate(leaf->parent); } else if (leaf == leaf->parent->right && leaf->parent == leaf->parent->parent->right) { stLeftRotate(leaf->parent->parent); stLeftRotate(leaf->parent); } else if (leaf == leaf->parent->left && leaf->parent == leaf->parent->parent->right) { stRightRotate(leaf->parent); stLeftRotate(leaf->parent); } else { stLeftRotate(leaf->parent); stRightRotate(leaf->parent); } } } template<typename T, typename K> T* SplayTree<T, K>::stFind(K key, bool doSplay) { stNode* found = stFindNode(key, root); if (found) { if (doSplay) { splay(found); } return (T*)found->data; } return NULL; } template<typename T, typename K> typename SplayTree<T, K>::stNode* SplayTree<T, K>::stFindNode(K key, stNode* leaf) { if (leaf) { if (key == leaf->key) { return leaf; } if (key < leaf->key) { return stFindNode(key, leaf->left); } return stFindNode(key, leaf->right); } return NULL; } template<typename T, typename K> bool SplayTree<T, K>::stDeleteNode(K key) { stNode* found = stFindNode(key, root); if (found == NULL) { return false; } splay(found); // does this node have children to take it's place? if (found->left == NULL) { stSwap(found, found->right); } else if (found->right == NULL) { stSwap(found, found->left); } else { // two children stNode* next = stMinimum(found->right); if (next->parent != found) { stSwap(next, next->right); next->right = found->right; next->right->parent = next; } stSwap(found, next); next->left = found->left; next->left->parent = next; } free(found->data); free(found); return true; } template<typename T, typename K> void SplayTree<T, K>::stSwap(stNode* a, stNode* b) { if (a->parent == NULL) { root = b; } else if (a == a->parent->left) { a->parent->left = b; } else { a->parent->right = b; } if (b) { b->parent = a->parent; } } template<typename T, typename K> typename SplayTree<T, K>::stNode* SplayTree<T, K>::stMinimum(stNode* leaf) { while (leaf->left) { leaf = leaf->left; } return leaf; } template<typename T, typename K> void SplayTree<T, K>::stLeftRotate(stNode* node) { stNode *child = node->right; if (child) { node->right = child->left; if (child->left) { child->left->parent = node; } child->parent = node->parent; } if (!node->parent) { root = child; } else if (node == node->parent->left) { node->parent->left = child; } else { node->parent->right = child; } if (child) { child->left = node; } node->parent = child; } template<typename T, typename K> void SplayTree<T, K>::stRightRotate(stNode* node) { stNode *child = node->left; if (child) { node->left = child->right; if (child->right) { child->right->parent = node; } child->parent = node->parent; } if (!node->parent) { root = child; } else if (node == node->parent->left) { node->parent->left = child; } else { node->parent->right = child; } if (child) { child->right = node; } node->parent = child; } template<typename T, typename K> void SplayTree<T, K>::stDeleteTree(stNode* leaf) { if (leaf) { stDeleteTree(leaf->left); stDeleteTree(leaf->right); free(leaf->data); free(leaf); } } template<typename T, typename K> int SplayTree<T, K>::stMax(int a, int b) { return (a <= b) ? b : a; } template<typename T, typename K> int SplayTree<T, K>::stHeight(stNode* leaf) { if (leaf) { return 1 + stMax(stHeight(leaf->left), stHeight(leaf->right)); } return 0; } template<typename T, typename K> void SplayTree<T, K>::stIterateLevel(int level, stIter callBack, stNode* leaf) { if (leaf == NULL) { return; } if (level == 1) { callBack(leaf->key, (T*)leaf->data); } if (level > 1) { stIterateLevel(--level, callBack, leaf->left); stIterateLevel(--level, callBack, leaf->right); } } template<typename T, typename K> void SplayTree<T, K>::stIterateLevel(int level, stIterP callBack, stNode* leaf, int pos, int offSet) { if (leaf == NULL) { return; } if (level == 1) { callBack(leaf->key, pos); } if (level > 1) { offSet /= 2; stIterateLevel(--level, callBack, leaf->left, pos - offSet, offSet); stIterateLevel(--level, callBack, leaf->right, pos + offSet, offSet); } } #endif


SplayTree.cpp
#include "stdafx.h" #include "stdafx.h" #include <stdint.h> #include <stdlib.h> #include <iostream> #include "SplayTree.h" void setupBoard(); void displayBoard(); void playGame(); void makeMove(uint8_t, uint8_t); void castleMove(uint8_t, uint8_t, uint8_t, uint8_t); enum Players { WHT, BLK }; uint8_t nextMove = WHT; enum Pieces { PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING }; char pNames[][7] = { "Pawn", "Rook", "Knight", "Bishop", "Queen", "King" }; char pSymbol[] = { 'P', 'R', 'N', 'B', 'Q', 'K' }; struct cBoard { uint8_t player; uint8_t piece; }; SplayTree<cBoard, uint8_t> myTree; char* pLine; int main() { setupBoard(); displayBoard(); playGame(); std::cin.get(); return 0; } void playGame() { uint8_t cOpt = 0; uint8_t moves[][2] = { { 13,29 },{ 53,37 },{ 7,13 },{ 58,43 },{ 2,19 },{ 62,35 }, { 13,23 },{ 52,44 },{ 12,20 },{ 63,46 },{ 3,39 },{ 59,45 },{ 23,40 },{ 0,0 }, { 19,36 },{ 46,29 },{ 39,60 },{ 35,14 },{ 5,13 },{ 45,31 } }; uint8_t cstlmoves[][4] = { { 61,64,63,62 } }; for (int i = 0; i < sizeof(moves) / 2; i++) { if (moves[i][0] == 0) { castleMove(cstlmoves[cOpt][0], cstlmoves[cOpt][1], cstlmoves[cOpt][2], cstlmoves[cOpt][3]); cOpt++; // max is 2 per game } else { makeMove(moves[i][0], moves[i][1]); } } std::cout << "Checkmate!\n"; } void makeMove(uint8_t from, uint8_t to) { cBoard* fSquare = myTree.find(from, false); cBoard* tSquare = myTree.find(to, false); if (fSquare) { if (fSquare->player == nextMove) { if (tSquare == NULL || tSquare->player != nextMove) { if (tSquare) { myTree.deleteNode(to); } myTree.insert(to, fSquare); myTree.deleteNode(from); } else { std::cout << "Target square invalid\n"; } } else { std::cout << "Not your move\n"; } } nextMove = (nextMove == WHT) ? BLK : WHT; //whose move next displayBoard(); } // OK the castle move needs different validation so // as this is not intended as a chess playing game demo // this function is a bodge to allow the move void castleMove(uint8_t f1, uint8_t f2, uint8_t t1, uint8_t t2) { cBoard* f1Square = myTree.find(f1, false); cBoard* f2Square = myTree.find(f2, false); myTree.insert(t1, f1Square); myTree.deleteNode(f1); myTree.insert(t2, f2Square); myTree.deleteNode(f2); nextMove = (nextMove == WHT) ? BLK : WHT; //whose move next displayBoard(); } void setupBoard() { cBoard wSquare = { WHT, PAWN }, bSquare = { BLK, PAWN }; for (int i = 1; i < 9; i++) { wSquare.piece = bSquare.piece = PAWN; myTree.insert(i + 8, &wSquare); myTree.insert(i + 48, &bSquare); switch (i) { case 1: case 8: wSquare.piece = bSquare.piece = ROOK; break; case 2: case 7: wSquare.piece = bSquare.piece = KNIGHT; break; case 3: case 6: wSquare.piece = bSquare.piece = BISHOP; break; case 4: wSquare.piece = bSquare.piece = QUEEN; break; case 5: wSquare.piece = bSquare.piece = KING; break; } myTree.insert(i, &wSquare); myTree.insert(i + 56, &bSquare); } } void displayBoard() { cBoard* square; std::cout << "Board Positions\n"; for (int i = 0; i < 8; i++) { for (int j = 1; j < 9; j++) { square = myTree.find(j + i * 8, false); if (square) { std::cout << (square->player == WHT ? pSymbol[square->piece] : (char)(pSymbol[square->piece] + 32)); } else { std::cout << ' '; } } std::cout << '\n'; } std::cout << "________\n"; }


SplayTree.ino
#include "SplayTree.h" enum Players {WHT, BLK}; uint8_t nextMove = WHT; enum Pieces {PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING}; char pNames[][7] = {"Pawn", "Rook", "Knight", "Bishop", "Queen", "King"}; char pSymbol[] = {'P', 'R', 'N', 'B', 'Q', 'K'}; struct cBoard{ uint8_t player; uint8_t piece; }; SplayTree<cBoard, uint8_t> myTree; char* pLine; template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; } void setup() { Serial.begin(115200); setupBoard(); displayBoard(); printLevels2(5); Serial << "Height: " << myTree.height() << '\n'; playGame(); Serial << "Height: " << myTree.height() << '\n'; for(int i = 1, j= myTree.height(); i<=j; i++) {     myTree.iterateLevel(i, printLevel);     Serial << '\n'; } printLevels2(5); } void printLevel(uint8_t key, cBoard* square) { Serial << key << " "; } void printLevels2(int toLevel) { size_t pLineSize = pow(3, toLevel-1) + 1; pLine = (char*)malloc(pLineSize--); pLine[pLineSize-1] = 0; int m = (pLineSize - 1) / 2; for(int i = 1; i<= toLevel; i++){     memset(pLine, ' ', pLineSize-1);     myTree.iterateLevel(i, setKey, m);     Serial << pLine << '\n'; } free(pLine); } void setKey(uint8_t key, int pos){ intToString(key, pLine, pos); } // converts +ve int to string inserted into buffer void intToString(int iVal, char* buff, int pos){ int i = pos; do {     buff[i++] = iVal % 10 + '0'; } while ((iVal /= 10) > 0); char h; // now reverse the string for(int j= pos; j < i; j++, i--) {     h = buff[j];     buff[j] = buff[i];     buff[i] = h; } } void playGame() { uint8_t cOpt = 0; uint8_t moves[][2] = {{13,29},{53,37},{7,13},{58,43},{2,19},{62,35},          {13,23},{52,44},{12,20},{63,46},{3,39},{59,45},{23,40},{0,0},          {19,36},{46,29},{39,60},{35,14},{5,13},{45,31}}; uint8_t cstlmoves[][4] = {{61,64,63,62}}; for (int i = 0; i < sizeof(moves) / 2; i++) {     if(moves[i][0] == 0) {      castleMove(cstlmoves[cOpt][0], cstlmoves[cOpt][1], cstlmoves[cOpt][2], cstlmoves[cOpt][3]);      cOpt++; // max is 2 per game     } else {      makeMove(moves[i][0], moves[i][1]);     } } Serial << "Checkmate!\n"; } void makeMove(uint8_t from, uint8_t to) { cBoard* fSquare = myTree.find(from, false); cBoard* tSquare = myTree.find(to, false); if(fSquare) {     if(fSquare->player == nextMove) {      if(tSquare == NULL || tSquare->player != nextMove) {         // probably a valid move but you could write a lot more         // validation to check route is clear if not knight and         // distance allowed and from and to not the same etc.         if(tSquare) {          myTree.deleteNode(to);         }         myTree.insert(to, fSquare);         myTree.deleteNode(from);      } else {         Serial << "Target square invalid\n";      }     } else {      Serial << "Not your move\n";     } } nextMove = (nextMove == WHT)? BLK : WHT; //whose move next displayBoard(); } // OK the castle move needs different validation so // as this is not intended as a chess playing game demo // this function is a bodge to allow the move void castleMove(uint8_t f1, uint8_t f2, uint8_t t1, uint8_t t2) { cBoard* f1Square = myTree.find(f1, false); cBoard* f2Square = myTree.find(f2, false); myTree.insert(t1, f1Square); myTree.deleteNode(f1); myTree.insert(t2, f2Square); myTree.deleteNode(f2); nextMove = (nextMove == WHT)? BLK : WHT; //whose move next displayBoard(); } void setupBoard() { cBoard wSquare = {WHT, PAWN}, bSquare = {BLK, PAWN}; for(int i = 1; i < 9; i++) {     wSquare.piece = bSquare.piece = PAWN;     myTree.insert(i + 8, &wSquare);     myTree.insert(i + 48, &bSquare);     switch(i) {      case 1:      case 8:         wSquare.piece = bSquare.piece = ROOK;         break;      case 2:      case 7:         wSquare.piece = bSquare.piece = KNIGHT;         break;      case 3:      case 6:         wSquare.piece = bSquare.piece = BISHOP;         break;      case 4:         wSquare.piece = bSquare.piece = QUEEN;         break;      case 5:         wSquare.piece = bSquare.piece = KING;         break;     }     myTree.insert(i, &wSquare);     myTree.insert(i + 56, &bSquare); } } void displayBoard() { cBoard* square; Serial << "Board Positions\n"; for(int i = 0; i < 8; i++) {     for(int j = 1; j < 9; j++) {      square = myTree.find(j + i * 8, false);      if(square) {         Serial << (square->player == WHT ? pSymbol[square->piece] : (char)(pSymbol[square->piece]+32));      }else {         Serial << ' ';      }     }     Serial << '\n'; } Serial << "________\n"; }


Read the chapter in my book C++ Data Structures with immediate download from Amazon