Project showcase

Arduino Mega Chess © GPL3+

Chess processor with GUI dedicated for Arduino Mega.

  • 9,712 views
  • 26 comments
  • 56 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

Apps and online services

About this project

After some my Arduino project remains unclaimed touchscreen, so I decided to realize my chidhood dream to create a chess program. After a couple of months it wins me, but it is not big deal because i do not have any chess rating, just amateur.

This project uses Arduino Mega 2560 because of lack of operative memory on Uno, 2.8 inch touchscreen, passive buzzer, and about 2000 lines of code.

Program uses Negamax algorithm, iterative deepening, some kind of killer heuristic, time control. No any bitboards or hashes for obvious reasons. Evaluate function is rather complicated, but not too much, anyway in except of material it calculates figures activity, king safity, pawn structure. Solve speed about 100-200 nodes per second.

Play is according to chess rules, including en passant, castling, pawn promotion. Draw is determined too. Algorithm also may give up if did no see any vay to escape checkmate.

Board is rotatable, step by drag and drop, can take step back. It is possible to arrange the initial position, or load from Serial port in FEN format. Chess game can be saved in EEPROM and downloaded later, or replayed in fast mode.

There is a checkmate search regime to solve chess problem.

  • Level of algorithm is given by choosing mean thinking time 10sec - 30sec -1min - 3min 10min - 30min - no limit. On 10 seconds regime play is adequate for me, but may be some probles in endspiel or with horizon effect. On 1min i don't even try to win - may be it is just lack of assiduity.
Some debut steps (no library), rapid replay of pawn pass

Arduino plays Black and wins. Time control - about 1 min/step. Rapid replay.

If anybody like to repeat this project, and screen not be the same model, i see only difficulty to calibrate touchscreen, need to tune coordinate transformation coefficients. Later i will remake sketch on more common and big 3.5 inch touchscreen.

Sorry for poor decor - it is my first public project.

Thank you for attention.

Upd: 6 feb 2018:

As i promised, updated sketch to 3.5 inch MCUFRIEND touchscreen 320x480 pixels. Added new variant.

Code

ArduinoMega Chess 1.0Arduino
//ArduinoMega Chess 1.0
//Sergey Urusov, ususovsv@gmail.com

#include <Adafruit_TFTLCD.h> 
#include <stdint.h>
#include "TouchScreen.h"
#include <avr/pgmspace.h>
#include <EEPROM.h> 


uint16_t BLACK,BLUE,RED,GREEN,CYAN,MAGENTA,YELLOW,WHITE,GRAY,DARK,GRAY2,BLACKF,WHITEF;
Adafruit_TFTLCD tft;
#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 350);
int touchx,touchy,touchx0,touchy0,ntouch;         
unsigned long lasttouch;
#define MINPRESSURE 10
#define MAXPRESSURE 1000
const int PinBuzz = 44;
int cycle=0; // 
const char fp=1;
const char fn=2;
const char fb=3;
const char fr=4;
const char fq=5;
const char fk=6;
const int fig_weight[]={0,100,320,330,500,900,0};
const char fig_symb[]="  NBRQK";
unsigned long count;
boolean rotate=false;
const char polezero[8][8] PROGMEM={
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             };  
const char polestart[8][8] PROGMEM={
             {-fr,-fn,-fb,-fq,-fk,-fb,-fn,-fr},
             {-fp,-fp,-fp,-fp,-fp,-fp,-fp,-fp},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             { fp, fp, fp, fp, fp, fp, fp, fp},
             { fr, fn, fb, fq, fk, fb, fn, fr},
             };  
             
char pole[8][8]={ //  3 
             {-fr,-fn,-fb,-fq,-fk,-fb,-fn,-fr},
             {-fp,-fp,-fp,-fp,-fp,-fp,-fp,-fp},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             { fp, fp, fp, fp, fp, fp, fp, fp},
             { fr, fn, fb, fq, fk, fb, fn, fr},
             };  
             
char pole0[8][8];  //   
char poledisp[8][8]; // 
char polechoice[7]; // 
boolean w00,w000,b00,b000;             
char blinkstep;
typedef struct {
  char fig1, fig2; //    
  char x1,y1,x2,y2; //     
  char check; //  
  char type; //  1-  ,2- ,3- ,4-5-6-7-  ,,,
  int weight; // , 
} step_type;
const int MAXSTEPS=500; //.      
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int MINDEPTH; //.   
int MAXDEPTH; //.   
int LIMDEPTH; //.       
const char MAXCUTS=10; //.. -  - (10-  ,  20)
boolean TRACE=0;
boolean checkmatesearch=0; //   
boolean solving=false;
boolean choice=false;
boolean sound=0;
int cur_step=1; //  , 1....
int limit=0; //  , 0-6;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const long limits[7]={10,30,60,180,600,1800,100000};
//                     0  1  2   3   4    5      6 
step_type steps[MAXSTEPS]; //  
step_type cuts[MAXCUTS]; //  -
step_type lastbest;
int lastscore;
int minbeta,maxalpha;
int startweight;
int cur_level; //   ()
int start_var; //   , 1....
int cur_var; //  , 1....
int cur_choice; //   
boolean check_on_table; //  
boolean isstatus;
char WKJ=0,WKI=0,BKJ=0,BKI=0; // 
boolean endspiel=false; // 
char progress; //   0-100
boolean only_action=false; // -  
unsigned long starttime,limittime,quitime=0;             
boolean drag;
const uint8_t fig[6][32] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x3,  0xC0, 0x7,  0xE0, 0x7,  0xE0, 0x3,  0xC0, 0x3,  0xC0,
0x7,  0xE0, 0x3,  0xC0, 0x3,  0xC0, 0x7,  0xE0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0x0,  0x0}, //
{0x0, 0x0,  0x3,  0x40, 0x7,  0xE0, 0xF,  0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x39, 0xFC, 0x33, 0xFC,
0x7,  0xFC, 0xF,  0xF8, 0xF,  0xF0, 0x7,  0xE0, 0x3,  0xC0, 0x7,  0xE0, 0x1F, 0xF8, 0x0,  0x0},  //
{0x1, 0x80, 0x3,  0xC0, 0x1,  0x80, 0xF,  0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8,
0x1F, 0xF8, 0x1F, 0xF8, 0xF,  0xF0, 0x7,  0xE0, 0x3,  0xC0, 0x31, 0x8C, 0x7F, 0xFE, 0x0,  0x0}, // 
{0x0, 0x0,  0x19, 0x98, 0x1F, 0xF8, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0,
0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x0,  0x0}, //
{0x19, 0x98, 0xD9, 0x9B, 0xD9, 0x9B, 0xD9, 0x9B, 0x6D, 0xB6, 0x6D, 0xB6, 0x6D, 0xB6, 0x35, 0xAC,
0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x1F, 0xF8, 0xF,  0xF0, 0xF,  0xF0, 0x1F, 0xF8, 0x0,  0x0}, //
{0x1, 0x80, 0x1,  0x80, 0x79, 0x9E, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x7F, 0xFE, 0x3F, 0xFC, 0x3F, 0xFC, 0x1F, 0xF8, 0xF,  0xF0, 0xF,  0xF0, 0x1F, 0xF8, 0x0,  0x0}  //
};
const uint8_t fig_cont[6][32] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x3,  0xC0, 0x4,  0x20, 0x8,  0x10, 0x8,  0x10, 0x4,  0x20, 0x4,  0x20,
0x8,  0x10, 0x4,  0x20, 0x4,  0x20, 0x8,  0x10, 0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x1F, 0xF8}, //
{0x3, 0x40, 0x4,  0xA0, 0x8,  0x10, 0x12, 0x8,  0x20, 0x4,  0x40, 0x2,  0x46, 0x2,  0x4C, 0x2,
0x38, 0x2,  0x10, 0x4,  0x10, 0x8,  0x8,  0x10, 0x4,  0x20, 0x18, 0x18, 0x20, 0x4,  0x3F, 0xFC},  //
{0x2, 0x40, 0x4,  0x20, 0x6,  0x60, 0x10, 0x8,  0x21, 0x84, 0x21, 0x84, 0x21, 0x84, 0x27, 0xE4,
0x21, 0x84, 0x21, 0x84, 0x11, 0x88, 0x8,  0x10, 0x34, 0x2C, 0x4E, 0x72, 0x80, 0x1,  0xFF, 0xFF}, // 
{0x39, 0x9C, 0x26, 0x64, 0x20, 0x4,  0x1F, 0xF8, 0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x10, 0x8,
0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x1F, 0xF8, 0x20, 0x4,  0x20, 0x4,  0x3F, 0xFC}, //
{0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x26, 0x64, 0x92, 0x49, 0x92, 0x49, 0x92, 0x49, 0x4A, 0x52,
0x40, 0x2,  0x40, 0x2,  0x5F, 0xFA, 0x20, 0x4,  0x1F, 0xF8, 0x10, 0x8,  0x20, 0x4,  0x3F, 0xFC}, //
{0x2, 0x40, 0x7A, 0x5E, 0x86, 0x61, 0x82, 0x41, 0x2,  0x40, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80,
0x80, 0x81, 0x41, 0x82, 0x5F, 0xFA, 0x20, 0x4,  0x1F, 0xF8, 0x10, 0x8,  0x20, 0x4,  0x3F, 0xFC}  //
};

const uint8_t issound[2][32] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x0,  0x32, 0x0,  0x54, 0x0,  0x98, 0x1F, 0x10, 0x10, 0x30, 0x10, 0x50,
0x10, 0x90, 0x11, 0x10, 0x1F, 0x10, 0x4,  0x90, 0x8,  0x50, 0x10, 0x30, 0x0,  0x0,  0x0,  0x0},
{0x0, 0x0,  0x0,  0x0,  0x0,  0x30, 0x0,  0x50, 0x0,  0x90, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x0,  0x90, 0x0,  0x50, 0x0,  0x30, 0x0,  0x0,  0x0,  0x0}
};
const uint8_t iswb[2][32] PROGMEM={
{0x0,  0x0,  0x0,  0x0,  0x3,  0xC0, 0x4,  0x20, 0x8,  0x10, 0x8,  0x10, 0x4,  0x20, 0x4,  0x20,
0x8,  0x10, 0x4,  0x20, 0x4,  0x20, 0x8,  0x10, 0x10, 0x8,  0x10, 0x8,  0x1F, 0xF8, 0x0,  0x0},
{0x0,  0x0,  0x0,  0x0,  0x3,  0xC0, 0x7,  0xE0, 0xF,  0xF0, 0xF,  0xF0, 0x7,  0xE0, 0x7,  0xE0,
0xF,  0xF0, 0x7,  0xE0, 0x7,  0xE0, 0xF,  0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x0,  0x0}
};
const uint8_t iscm[2][32] PROGMEM={
{0x0, 0x0,  0x7,  0xE0, 0xC,  0x30, 0xC,  0x30, 0xC,  0x30, 0xC,  0x30, 0x0,  0x30, 0x0,  0x60,
0x0,  0xC0, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x0,  0x0,  0x1,  0x80, 0x1,  0x80, 0x0,  0x0},
{0x0,  0x0,  0x3F, 0x0,  0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x1,  0x80, 0x3,  0x0,
0x6,  0x24, 0xC,  0x24, 0xC,  0xFF, 0xC,  0x24, 0x0,  0xFF, 0xC,  0x24, 0xC,  0x24, 0x0,  0x0}
};
const uint8_t islimit[7][32] PROGMEM={
{0x0, 0x0,  0x4,  0x70, 0xC,  0x88, 0x4,  0x88, 0x4,  0x88, 0x4,  0x88, 0x4,  0x88, 0x4,  0x88,
0xE,  0x70, 0x0,  0x0,  0x1D, 0xDC, 0x11, 0x10, 0x1D, 0xD0, 0x5,  0x10, 0x1D, 0xDC, 0x0,  0x0},
{0x0, 0x0,  0xC,  0x70, 0x12, 0x88, 0x2,  0x88, 0xC,  0x88, 0x2,  0x88, 0x2,  0x88, 0x12, 0x88,
0xC,  0x70, 0x0,  0x0,  0x1D, 0xDC, 0x11, 0x10, 0x1D, 0xD0, 0x5,  0x10, 0x1D, 0xDC, 0x0,  0x0},
{0x0, 0x0,  0x1,  0x80, 0x3,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80,
0x3,  0xC0, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0x3,  0xC0, 0x6,  0x60, 0x0,  0x60, 0x1,  0xC0, 0x0,  0x60, 0x6,  0x60, 0x6,  0x60,
0x3,  0xC0, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0xC,  0x78, 0x1C, 0xCC, 0xC,  0xCC, 0xC,  0xCC, 0xC,  0xCC, 0xC,  0xCC, 0xC,  0xCC,
0x1E, 0x78, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0x1C, 0x78, 0x36, 0xCC, 0x6,  0xCC, 0x1C, 0xCC, 0x6,  0xCC, 0x36, 0xCC, 0x36, 0xCC,
0x1C, 0x78, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3C, 0x3C, 0x7E, 0x7E, 0x63, 0xC6, 0x61, 0x86,
0x63, 0xC6, 0x66, 0x66, 0x3C, 0x3C, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0}
};
const uint8_t isdesc[2][32] PROGMEM={
{0x0,  0x0,  0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0xE3, 0x8E,
0xE3, 0x8E, 0xE3, 0x8E, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E},
{0x0,  0x0,  0x0,  0x4,  0x0,  0xE,  0x0,  0xE,  0x0,  0x1C, 0x0,  0x1C, 0x0,  0x38, 0x0,  0x30,
0x30, 0x70, 0x78, 0xE0, 0x3C, 0xC0, 0x1F, 0xC0, 0xF,  0x80, 0x7,  0x0,  0x2,  0x0,  0x0,  0x0}

};
const uint8_t isback[32] PROGMEM={
0x0,  0x0,  0x0,  0x0,  0x20, 0xF0, 0x31, 0xF8, 0x3B, 0xFC, 0x3F, 0x8E, 0x3F, 0xE,  0x3F, 0xE,
0x3F, 0x8E, 0x3F, 0xCE, 0x0,  0xE,  0x0,  0xE,  0x0,  0x1C, 0x0,  0x38, 0x0,  0x70, 0x0,  0x0
};
const uint8_t issave[32] PROGMEM={
0x1,  0x80, 0x3,  0xC0, 0x7,  0xE0, 0x7,  0xE0, 0x3,  0xC0, 0x3F, 0xFC, 0x23, 0xC4, 0x23, 0xC4,
0x23, 0xC4, 0x23, 0xC4, 0x23, 0xC4, 0x23, 0xC4, 0x20, 0x4,  0x20, 0x4,  0x3F, 0xFC, 0x0,  0x0
};
const uint8_t isload[32] PROGMEM={
0x0,  0x0,  0x3,  0xC0, 0x3,  0xC0, 0x3,  0xC0, 0x3,  0xC0, 0x3F, 0xFC, 0x23, 0xC4, 0x23, 0xC4,
0x23, 0xC4, 0x27, 0xE4, 0x27, 0xE4, 0x23, 0xC4, 0x21, 0x84, 0x20, 0x4,  0x3F, 0xFC, 0x0,  0x0
};
const uint8_t isempty[32] PROGMEM={
0xFF,  0xFF, 0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,
0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0xFF, 0xFF
};
const uint8_t isinit[32] PROGMEM={
0xFF,  0xFF, 0x80, 0x1,  0x80, 0x1,  0xFF, 0xFF, 0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,
0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
const uint8_t isplay[32] PROGMEM={
0x0,  0x0,  0x3,  0xC0, 0x3,  0xC0, 0x3,  0xC0, 0x1,  0x80, 0x23, 0xF8, 0x17, 0xC8, 0xB,  0xC8,
0x3,  0xC0, 0x3,  0xC0, 0x2,  0x40, 0x4,  0x40, 0x4,  0x38, 0x4,  0x8,  0xC,  0x0,  0x0,  0x0
};
const uint8_t isrotate[2][32] PROGMEM={
{0x0,  0x0,  0x0,  0x0,  0x3F, 0xFC, 0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,
0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x0,  0x0,  0x0,  0x0},
{0x0, 0x0,  0x0,  0x0,  0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC,
0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x3F, 0xFC, 0x0,  0x0,  0x0,  0x0}
};

const int pos[7][8][8] PROGMEM={
 {{  0,  0,  0,  0,  0,  0,  0,  0}, // 
  {100,100,100,100,100,100,100,100},  //{ 50, 50, 50, 50, 50, 50, 50, 50},
  { 20, 30, 40, 50, 50, 40, 30, 20},  //{ 10, 10, 20, 30, 30, 20, 10, 10},
  {  5,  5, 10, 25, 25, 10,  5,  5},
  {  0,  0,  0, 20, 20,  0,  0,  0},
  {  5, -5,-10,  0,  0,-10, -5,  5},
  {  5, 10, 10,-20,-20, 10, 10,  5},  //{  5, 10, 10,-20,-20, 10, 10,  5},
  {  0,  0,  0,  0,  0,  0,  0,  0}},
  
 {{-50,-40,-30,-30,-30,-30,-40,-50}, //
  {-40,-20,  0,  0,  0,  0,-20,-40},
  {-30,  0, 10, 15, 15, 10,  0,-30},
  {-30,  5, 15, 20, 20, 15,  5,-30},
  {-30,  0, 15, 20, 20, 15,  0,-30},
  {-30,  5, 10, 15, 15, 10,  5,-30},
  {-40,-20,  0,  5,  5,  0,-20,-40},
  {-50,-40,-30,-30,-30,-30,-40,-50}}, 
  
 {{-20,-10,-10,-10,-10,-10,-10,-20}, //
  {-10,  0,  0,  0,  0,  0,  0,-10},
  {-10,  0,  5, 10, 10,  5,  0,-10},
  {-10,  5,  5, 10, 10,  5,  5,-10},
  {-10,  0, 10, 10, 10, 10,  0,-10},
  {-10, 10, 10, 10, 10, 10, 10,-10},
  {-10,  5,  0,  0,  0,  0,  5,-10},
  {-20,-10,-10,-10,-10,-10,-10,-20}},  

 {{  0,  0,  0,  0,  0,  0,  0,  0}, //
  {  5, 10, 10, 10, 10, 10, 10,  5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  {  0,  0,  0,  5,  5,  0,  0,  0}},
  
 {{-20,-10,-10, -5, -5,-10,-10,-20}, //
  {-10,  0,  0,  0,  0,  0,  0,-10},
  {-10,  0,  5,  5,  5,  5,  0,-10},
  { -5,  0,  5,  5,  5,  5,  0, -5},
  {  0,  0,  5,  5,  5,  5,  0, -5},
  {-10,  5,  5,  5,  5,  5,  0,-10},
  {-10,  0,  5,  0,  0,  0,  0,-10},
  {-20,-10,-10, -5, -5,-10,-10,-20}},  

 {{-30,-40,-40,-50,-50,-40,-40,-30}, //
  {-30,-40,-40,-50,-50,-40,-40,-30},
  {-30,-40,-40,-50,-50,-40,-40,-30},
  {-30,-40,-40,-50,-50,-40,-40,-30},
  {-20,-30,-30,-40,-40,-30,-30,-20},
  {-10,-20,-20,-20,-20,-20,-20,-10},
  { 10, 10,-10,-10,-10,-10, 10, 10},  //{ 20, 20,  0,  0,  0,  0, 20, 20},
  { 10, 40, 30,  0,  0,  0, 50, 10}}, //{ 20, 30, 10,  0,  0, 10, 30, 20}},

 {{-50,-40,-30,-20,-20,-30,-40,-50}, // 
  {-30,-20,-10,  0,  0,-10,-20,-30},
  {-30,-10, 20, 30, 30, 20,-10,-30},
  {-30,-10, 30, 40, 40, 30,-10,-30},
  {-30,-10, 30, 40, 40, 30,-10,-30},
  {-30,-10, 20, 30, 30, 20,-10,-30},
  {-30,-30,  0,  0,  0,  0,-30,-30},
  {-50,-30,-30,-30,-30,-30,-30,-50}}  
};

//******
class Button {
public:
int bx,by,bw,bh,bshift;
String bs;
const uint8_t* bp;
 Button(int x,int y,int w,int h,String s,const uint8_t* p, int shift);
 void Show(int shift); 
 void Show(String s); 
 void Hide();
 boolean IsPressed(int xc, int yc);
private:
boolean active;
 void ishow(uint16_t textcolor,uint16_t backcolor);
};
Button::Button(int x,int y,int w,int h,String s,const uint8_t* p=NULL, int shift=0) {
  bx=x; by=y; bw=w; bh=h; bs=s; bp=p; bshift=shift;
};
void Button::Show(int shift=0) {
 bshift=shift; 
 active=true;
 ishow(WHITE,DARK);  
};
void Button::Show(String s) {
 bs=s; 
 active=true;
 ishow(WHITE,DARK);  
};
void Button::Hide() { 
 active=false; 
 ishow(GRAY,DARK);  
};
boolean Button::IsPressed(int xc, int yc) {
  if (active&&abs(bx+bw/2-xc)<bw/2&&abs(by+bh/2-yc)<bh/2) {
    ishow(WHITE,GRAY); 
    touchx=0; touchy=0;        
    return true;
  } 
  return false;
};  
void Button::ishow(uint16_t textcolor,uint16_t backcolor) {  
  tft.fillRoundRect(bx+2,by+2,bw,bh,3,GRAY2);               
  tft.fillRoundRect(bx,by,bw,bh,3,backcolor);               
  tft.setTextColor(textcolor);
  tft.setTextSize(1);    
  tft.setCursor(bx+(bw-bs.length()*6)/2,by+(bh-8)/2);       
  if (bp!=NULL) { 
   tft.drawBitmap(1+bx+(bw-16)/2, by+(bh-16)/2, bp+bshift*32, 16, 16,textcolor);          
  } 
  else  tft.print(bs);    
}
Button BAction(65, 216, 55, 20, "START");
Button BBW(125, 216, 22, 20, "",&iswb[0][0]);
Button BBack(152, 216, 23, 20, "",&isback[0]);
Button BInit(152, 216, 23, 20, "",&isinit[0]);
Button BLimit(180, 216, 23, 20, "",&islimit[0][0]);
Button BEmpty(180, 216, 23, 20, "",&isempty[0]);
Button BRotate(208, 216, 23, 20, "",&isrotate[0][0]);
Button BPlay(208, 216, 23, 20, "",&isplay[0]);
Button BCM(236, 216, 23, 20, "",&iscm[0][0]);
Button BSave(236, 216, 23, 20, "",&issave[0]);
Button BDesc(264, 216, 23, 20, "",&isdesc[0][0]);
Button BSound(292, 216, 23, 20, "",&issound[0][0]);
Button BLoad(292, 216, 23, 20, "",&isload[0]);
//******
//********************************** 
void drawBitmap(int16_t x, int16_t y,
            const uint8_t *bitmap, int16_t w, int16_t h,
            uint16_t color) {
  int16_t i, j, byteWidth = (w + 7) / 8;  
  for(j=0; j<h; j++) {
    for(i=0; i<w; i++ ) {
      if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
        tft.drawPixel(x+i, y+j, color);
      }      
    }
  }
}
//****************************
void deletebuttons() {
  tft.fillRect(0,215,320,30,BLACK);               
}

//****************************
void clearstatus() {
  tft.fillRect(0,210,60,30,BLACK);             
  tft.drawFastHLine(5,210,200,BLACK);   
  tft.drawFastHLine(5,212,200,BLACK);  
}  
//****************************
void setup() {      
  Serial.begin(57600);  
  Serial.println(F("Start"));     
  pinMode(13, OUTPUT);
  tft.reset();  
  tft.begin(tft.readID()); 
  tft.setRotation(1);  
  definecolors();
  beep(100);      
  for (int i=0;i<MAXSTEPS;i++) {
    steps[i].x1=0; steps[i].y1=0;
    steps[i].x2=0; steps[i].y2=0;
    steps[i].fig1=0; steps[i].fig2=0;
    steps[i].check=0;
    steps[i].type=0;
    steps[i].weight=0;
  }     
  initboard();
}
//****************************
void initboard() {        
  for (int i=0;i<8;i++)
   for (int j=0;j<8;j++) poledisp[j][i]=-100; //          
  tft.fillScreen(BLACK);      
  tft.setTextColor(GRAY);
  tft.setTextSize(1);  
  for (int j=1;j<9;j++) {
   tft.setCursor(2,j*24-15);  
   if (rotate) tft.print(j); else tft.print(9-j);
  }
  for (byte i=1;i<9;i++) { 
   tft.setCursor(i*24-1,198);    
   if (rotate) tft.print(char(96+9-i)); else tft.print(char(96+i));  
  }         
  initscreen();          
}
//****************************
void initscreen() {        
 show_board();   
 show_steps();      
 BAction.Show("START");
 BBW.Show(cur_step%2);   
 if (cur_step>1) BBack.Show(); else BBack.Hide();
 BSave.Hide();
 BLoad.Hide();
 BInit.Hide();
 BBack.Show();  
 BLimit.Show();         
 BPlay.Hide();           
 BRotate.Show(rotate);           
 BEmpty.Hide();
 BLimit.Show(limit);  
 BCM.Show(checkmatesearch); 
 BDesc.Show(choice); 
 BSound.Show(sound);    
}
//****************************
void loop() {        
  gui();  
  if (solving) {        
    int len=70;
    if (!sound) len=2;  
    for (int i=1;i<4;i++) { tone(44,400+300*i,len); delay(70); }
    lastscore=solve_step();               
    float tim=float(millis()-starttime)/1000;
    for (int i=3;i>=1;i--) { tone(44,400+300*i,len); delay(70); }
    if (!checkmatesearch&&lastscore>-9000&&lastscore!=8999) {             
      movestep(cur_step);       
      cur_step++; steps[cur_step].fig1=0; 
    } 
    initscreen();        
    animate_step(cur_step-1,false);
    clearstatus();
    if (lastscore>9000) {       
      tft.setTextSize(1);    
      tft.setTextColor(GREEN); 
      tft.setCursor(0,210);    
      if (lastscore<9999) {
       tft.print("# in "); 
       tft.print((9999-lastscore)/2+1); tft.print(F(" st"));        
      } else tft.print("Checkmate"); 
    } else if (lastscore<-9000) {
      tft.setTextSize(1);    
      tft.setTextColor(RED); 
      tft.setCursor(0,210);    
      tft.print("GIVE UP!");       
      show_steps();
    } else if (lastscore==8999) { //Draw
      tft.setTextSize(1);    
      tft.setTextColor(YELLOW); 
      tft.setCursor(0,210);    
      tft.print("Draw");       
    }         
    tft.setTextSize(1);    
    tft.setTextColor(GRAY); 
    tft.setCursor(0,220);    
    tft.print(tim,0); 
    tft.print("s ");    
    if (abs(lastscore)<5000) {   
     tft.print(lastscore);     
    }
    tft.setCursor(0,230);        
    tft.print(count); 
    tft.print("pos");   
    Serial.print(F("Positions estimated=")); Serial.println(count);
    Serial.print(F("Time=")); Serial.print(tim,1); Serial.println("s");    
  }
  delay(10);  
  
  
}

//********************************** 
void load_choice() {
  for (int i=0;i<7;i++) 
   if (cur_step%2==1) polechoice[i]=i; else polechoice[i]=-i;
}
//********************************** 
void show_choice() {
uint16_t color,color_cont;    
  for (int i=0;i<7;i++) {
    color=BLACKF;
    if (i%2==0) color=WHITEF;              
    tft.fillRect(260,i*25+35,25,25,color);    
    color=DARK;
    if (i==cur_choice) color=WHITE;   
    tft.drawRect(260,i*25+35,25,25,color);
    color=BLACK; color_cont=GRAY;
    if (polechoice[i]>0) { color=WHITE; color_cont=BLACK; }
    if (polechoice[i]!=0) {
     drawBitmap(264, i*25+39,&fig[abs(polechoice[i])-1][0], 16, 16,color);          
     drawBitmap(264, i*25+39,&fig_cont[abs(polechoice[i])-1][0], 16, 16,color_cont);     
    }
  }  
}
//********************************** 
void animate_step(int nstep, boolean hide) {   
 if (!hide&&nstep-1>0&&steps[nstep-1].fig1!=0) animate_step(nstep-1,true); 
 if (nstep-1<1||steps[nstep].fig1==0) return;
 int j=steps[nstep].x1;
 int dj=steps[nstep].x2-steps[nstep].x1;
 int i=steps[nstep].y1;
 int di=steps[nstep].y2-steps[nstep].y1; 
 di=di/abs(di); dj=dj/abs(dj);  
 if (hide) show_fig(i,j);
 while (j!=steps[nstep].x2||i!=steps[nstep].y2) {  
  show_fig(i,j); 
  if (!hide) 
   if (!rotate) tft.drawRect(i*24+13,j*24+1,23,23,WHITE);    
    else tft.drawRect((7-i)*24+13,(7-j)*24+1,23,23,WHITE);    
  int mj=0;  
  if (j!=steps[nstep].x2) { j+=dj; mj=1; }   
  if (abs(steps[nstep].fig1)==fn&&mj==1) continue;
  if (i!=steps[nstep].y2) i+=di;  
 } 
 show_fig(i,j); 
 if (!hide) 
  if (!rotate) tft.drawRect(i*24+13,j*24+1,23,23,WHITE);    
   else tft.drawRect((7-i)*24+13,(7-j)*24+1,23,23,WHITE);     
}
//********************************** 
boolean load_usb() {
char s='x',i=0,j=0;  boolean load=false; 
  Serial.println(F("Wait for FEN position"));
  for (int i=0;i<8;i++)
      for (int j=0;j<8;j++) {
        pole0[j][i]=pole[j][i];
        pole[j][i]=(char)pgm_read_byte(&polezero[j][i]);                 
      }       
  while (s!=' ') {
    s=Serial.read();       
    if (i>7) { i=0; j++; }
    if (!getpole(j,i)) break;
    switch (s) {      
    case '/': i=0; break;  
    case 'p': pole[j][i]=-fp; i++; break;
    case 'P': pole[j][i]=fp; i++; break;
    case 'n': pole[j][i]=-fn; i++; break;
    case 'N': pole[j][i]=fn; i++; break;
    case 'b': pole[j][i]=-fb; i++; break;
    case 'B': pole[j][i]=fb; i++; break;
    case 'r': pole[j][i]=-fr; i++; break;
    case 'R': pole[j][i]=fr; i++; break;
    case 'q': pole[j][i]=-fq; i++; break;
    case 'Q': pole[j][i]=fq; i++; break;
    case 'k': pole[j][i]=-fk; i++; break;
    case 'K': pole[j][i]=fk; i++; break;
    case '1': i++; break;
    case '2': i+=2; break;
    case '3': i+=3; break;
    case '4': i+=4; break;
    case '5': i+=5; break;
    case '6': i+=6; break;
    case '7': i+=7; break;
    case '8': i=0; j++; break;    
    case ' ': break;    
    }    
    delay(20);
    if (i+j>0&&Serial.available()==0) break;
  }  
  s=0;
  if (Serial.available()>0) s=Serial.read();
  while (Serial.available()>0) Serial.read();
  if (s=='w'||s==0) { cur_step=1; load=true; }
   else if (s=='b') { cur_step=2; load=true; }
     else load=false;  
  if (load) {
     steps[1].fig1=0; steps[2].fig1=0;
     Serial.println(F("Position loaded"));
  } else {  
    for (int i=0;i<8;i++)
      for (int j=0;j<8;j++) 
        pole[j][i]=pole0[j][i];     
  }   
  return load;  
}
//********************************** 
void play() {
 BAction.Show("STOP"); 
 BSave.Hide();
 BBW.Hide();
 BLoad.Hide();
 BInit.Hide();   
 BPlay.Hide();   
 BEmpty.Hide();
 BDesc.Hide(); 
 clearstatus();       
 for (int i=cur_step-1;i>0;i--) {
  if (steps[i].fig1!=0) backstep(i);
 }
 show_board();
 show_steps();
 boolean st=false;
 unsigned long tim=millis();
 int i=1;
 while (i<cur_step) {
  if (steps[i].fig1!=0) movestep(i); 
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);  
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);    
  int x=388-p.y/2.4; 
  int y=p.x/3.2-50;       
  if (p.z>MINPRESSURE&&p.z<MAXPRESSURE)     
    if (BAction.IsPressed(x,y)) { st=true; BAction.Show(); } 
  if (millis()-tim>2000||st) {
    tim=millis();
    i++;
    show_board();
    beep(20);              
  }  
 }       
 choice=0; 
 beep(200);                
 kingpositions();        
 clearstatus();
 initscreen();                               
}
//********************************** 
void gui() {   
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);  
  // if sharing pins, you'll need to fix the directions of the touchscreen pins  
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);    
  int x=388-p.y/2.4; 
  int y=p.x/3.2-50;       
  if (((abs(x-touchx)>5||abs(y-touchy)>5)||drag)&&p.z>MINPRESSURE&&p.z<MAXPRESSURE) {    
    touchx=x;
    touchy=y;             
    if (solving) {
      if (BAction.IsPressed(x,y)) { //        
        beep(100); 
        solving=false;  
        BAction.Show("stopping");        
        BAction.Hide();        
        return;    
      }   
    } else { //not solve
      if (BAction.IsPressed(x,y)) { // 
       if (!choice) {
        delay(100);        
        solving=true;   
        BAction.Show();         
        animate_step(cur_step-1,true);
        return;
       } else { //   USB
        delay(100);
        BAction.Hide(); 
        BSave.Hide();
        BBW.Hide();
        BLoad.Hide();
        BInit.Hide();   
        BPlay.Hide();   
        BEmpty.Hide();
        BDesc.Hide();        
        show_steps();
        choice=0;         
        if (!load_usb()) return;
        beep(200);                
        kingpositions();        
        clearstatus();
        initscreen();                              
       }
      } else if (BBW.IsPressed(x,y)) {   //-    
       beep(100);         
       if (cur_step==1) cur_step=2;
        else if (cur_step==2) cur_step=1;
         else if (cur_step%2==0) cur_step--; else cur_step++;       
       BBW.Show(cur_step%2);        
       if (choice) { load_choice(); show_choice(); }
       return;
      } else if (cur_step>1&&BBack.IsPressed(x,y)) {  //      
       beep(100);                
       cur_step--;       
       animate_step(cur_step,true);
       lastscore=0;              
       backstep(cur_step);               
       steps[cur_step].fig1=0;
       show_board();       
       show_steps();       
       if (cur_step>1) BBack.Show(); else BBack.Hide();      
       BBW.Show(cur_step%2);        
       clearstatus();       
       return;        
      } else if (BLimit.IsPressed(x,y)) {    //   
       beep(100);  
       limit++; if (limit>6) limit=0;       
       BLimit.Show(limit);        
       return; 
      } else if (BCM.IsPressed(x,y)) {   //                   
       beep(100); 
       checkmatesearch=!checkmatesearch; 
       BCM.Show(checkmatesearch);        
       if (!checkmatesearch) steps[cur_step].fig1=0;
       lastscore=0;
       show_steps();
       return; 
      } else if (BRotate.IsPressed(x,y)) {   //                   
       beep(100); 
       rotate=!rotate; 
       BRotate.Show(rotate);              
       initboard();       
       return;  
      } else if (BSound.IsPressed(x,y)) {   //                  
       if (sound==1) { beep(100); sound=0; } else { sound=1; beep(200); }       
       BSound.Show(sound);        
       return;
      } else if (BDesc.IsPressed(x,y)) {  //
       beep(100); 
       if (!choice) {
        choice=1;
        cur_choice=1;
        load_choice();
        show_choice();        
        BAction.Show("USB(FEN)");         
        BBack.Hide();  
        BInit.Show();  
        BSave.Show();  
        BLimit.Hide(); 
        BEmpty.Show();  
        BRotate.Hide();    
        BPlay.Show();    
        BCM.Hide();          
        BSound.Hide(); 
        BSave.Show();  
        BLoad.Show();    
       } else {
        choice=0;  
        lastscore=0;
        clearstatus();
        kingpositions();        
        initscreen();        
       }       
       BDesc.Show(choice);                                    
       return;
      } else if (BInit.IsPressed(x,y)) {  //        
        beep(200);        
        cur_step=1;
        steps[1].fig1=0;
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) pole[j][i]=(char)pgm_read_byte(&polestart[j][i]);         
        choice=0;         
        kingpositions();        
        clearstatus();
        initscreen();                     
      } else if (BEmpty.IsPressed(x,y)) {  //        
        beep(200);        
        cur_step=1;        
        clearstatus();        
        steps[1].fig1=0; steps[2].fig1=0;
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) pole[j][i]=(char)pgm_read_byte(&polezero[j][i]);                 
        BEmpty.Show();   
        show_board();          
      } else if (BSave.IsPressed(x,y)) { 
        beep(100); 
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) EEPROM.write(i*8+j,pole[j][i]);         
        EEPROM.put(64,cur_step);
        EEPROM.put(66,limit);
        for (int i=1;i<cur_step;i++) {
          EEPROM.put(66+i*10,steps[i]);
        }
        BSave.Show(); 
      } else if (BLoad.IsPressed(x,y)) { 
        beep(200); 
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) pole[j][i]=EEPROM.read(i*8+j);
        EEPROM.get(64,cur_step);                 
        if (cur_step<0||cur_step>400) cur_step=1;        
        EEPROM.get(66,limit);                 
        if (limit<0||limit>6) limit=2;        
        for (int i=1;i<cur_step;i++) {
          EEPROM.get(66+i*10,steps[i]);
        }        
        steps[0].fig1=0;         
        steps[cur_step].fig1=0;         
        choice=0;                 
        kingpositions();
        clearstatus();
        initscreen();                                   
      } else if (BPlay.IsPressed(x,y)) {    //   
       beep(100);  
       BPlay.Show();        
       play();       
       return; 
      }
      if (!choice&&ntouch==0) {
       touchx0=touchx;
       touchy0=touchy;
       char x1=touchy0/24; 
       char y1=(touchx0-10)/24;       
       if (rotate) { x1=7-x1; y1=7-y1; }
       if (getpole(y1,x1)&&(cur_step%2==1&&pole[x1][y1]>0||cur_step%2==0&&pole[x1][y1]<0)) {        
        char p=pole[x1][y1];        
        drag=true;        
        pole[x1][y1]=0;
        show_fig(y1,x1);
        pole[x1][y1]=p;                
       } else drag=false; 
      }       
      ntouch++;
      if (drag&&ntouch>1) {
          uint16_t buf[256];          
          int x1=touchy0/24; 
          int y1=(touchx0-10)/24;       
          if (rotate) { x1=7-x1; y1=7-y1; }       
          if (abs(pole[x1][y1])>0&&(cur_step%2==1&&pole[x1][y1]>0||cur_step%2==0&&pole[x1][y1]<0)) {
          for (int i=0;i<16;i++)
            for (int j=0;j<16;j++) buf[i*16+j]=tft.readPixel(touchx-8+i,touchy-8+j);
          buf[0]=tft.readPixel(touchx-8,touchy-8);  
          uint16_t color,color_cont;    
          color=BLACK; color_cont=GRAY;
          if (pole[x1][y1]>0) { color=WHITE; color_cont=BLACK; }             
          drawBitmap(touchx-8, touchy-8,&fig[abs(pole[x1][y1])-1][0], 16, 16,color);          
          drawBitmap(touchx-8, touchy-8,&fig_cont[abs(pole[x1][y1])-1][0], 16, 16,color_cont);       
          delay(30);
          for (int i=0;i<16;i++)
            for (int j=0;j<16;j++) tft.drawPixel(touchx-8+i,touchy-8+j,buf[i*16+j]);            
          }  
      } else if (choice) {
        int x1=touchy/24; 
        int y1=(touchx-10)/24;             
        if (rotate) { x1=7-x1; y1=7-y1; } 
        if (touchy+touchx!=0&&choice&&getpole(y1,x1)) {        
         pole[x1][y1]=polechoice[cur_choice];
         show_board(); 
        }       
        if (touchx>=260&&touchx<=285&&touchy>=35&&touchy<=210) {
         cur_choice=(touchy-35)/25;
         show_choice();                       
        }
      }
      lasttouch=millis();
    } //not solve      
    if (!drag) { beep(10); ntouch=0; animate_step(cur_step-1,true); }     
  } else { //touching
    if (!solving&&!choice&&drag!=0&&ntouch>0&&p.z<MINPRESSURE&&millis()-lasttouch>300) { //drag 
     char x1=touchy0/24; 
     char y1=(touchx0-10)/24;     
     char x2=touchy/24; 
     char y2=(touchx-10)/24; 
     if (rotate) { x1=7-x1; y1=7-y1; x2=7-x2; y2=7-y2; }    
     if (getpole(y1,x1)) show_fig(y1,x1);
     if (getpole(y1,x1)&&getpole(y2,x2)) {      
       start_var=cur_step+1;
       only_action=false;   
       load_variants(cur_step);     
       for (int i=cur_step+1;i<cur_step+cur_var+1;i++)  
        if (steps[i].x1==x1&&steps[i].y1==y1&&steps[i].x2==x2&&steps[i].y2==y2) {
         steps[cur_step]=steps[i];          
         movestep(cur_step); cur_step++; steps[cur_step].fig1=0;
         int len=100;
         if (!sound) len=2;  
         for (int i=2;i>=1;i--) { tone(44,400+300*i,len); delay(100); }
         initscreen();
         animate_step(cur_step-1,false);
         break;                                 
        }            
     } else { 
      beep(10);       
     }
     ntouch=0;       
     drag=false;
    } 
  }
  if (millis()-quitime>1000) {
    if (isstatus) show_status(); 
    quitime=millis();
  }
  
  
}
//********************************** 
void show_status() {      
   int tim=(millis()-starttime)/1000; 
   int cur=200000*tim/(limittime-starttime);
   if (cur>200) { cur=200; solving=false; }   
   tft.drawFastHLine(5,210,cur,GRAY);                  
   tft.drawFastHLine(5,212,progress*2,GRAY);  
   int m=tim/60;
   int s=tim%60;
   tft.setTextWrap(1);
   tft.setTextColor(GRAY);
   tft.setTextSize(1);
   tft.fillRect(0,220,60,10,BLACK);             
   tft.setCursor(2,220);     
   if (m>0) { tft.print(m); tft.print(":"); }
   if (s>0) {
    if (s<10&&m>0) tft.print("0"); 
    tft.print(s);
   } else if (m>0) tft.print("00"); else tft.print("0");
   tft.setCursor(36,220);   
   tft.print(cur_level);
   
   tft.setCursor(2,230);   
   if (cur_step%2==1) tft.setTextColor(WHITE); else tft.setTextColor(GRAY);   
   if (lastbest.fig1!=steps[0].fig1||lastbest.x1!=steps[0].x1||lastbest.y1!=steps[0].y1||
       lastbest.x2!=steps[0].x2||lastbest.y2!=steps[0].y2) {
     beep(10); 
     lastbest=steps[0];    
     tft.fillRect(0,230,50,10,BLACK);             
     tft.setCursor(2,230);     
     tft.print(str_step(0));    
     blinkstep=0;
   }  
   if (steps[0].fig1!=0&&blinkstep==0&&tim>5) {
    char poleb[8][8];     
    for (int i=0;i<8;i++)
     for (int j=0;j<8;j++) { poleb[j][i]=pole[j][i]; pole[j][i]=pole0[j][i]; }         
    movestep(0);    
    show_board(); 
    delay(100);  
    backstep(0);   
    show_board();      
    for (int i=0;i<8;i++)
     for (int j=0;j<8;j++) pole[j][i]=poleb[j][i];           
    kingpositions();  
   }
   blinkstep++;      
   if (blinkstep>2) blinkstep=0;              
}
//****************************
void beep(int leng) {
  analogWrite(PinBuzz, 20);
  delay(2); 
  if (!sound) analogWrite(PinBuzz, 0);  
  delay(leng); 
  analogWrite(PinBuzz, 0);   
}  
//****************************
void definecolors() {
 BLACK  =0x0000;
 BLUE   =0x07FF;  //0x001F;
 RED    =0xF800;
 GREEN  =0x07E0;
 CYAN   =0x07FF;
 MAGENTA=0xF81F;
 YELLOW =0xFFE0;
 WHITE  =0xFFFF;
 GRAY   =0x7BEF;
 DARK   =getColor(32,32,32); 
 GRAY2   =getColor(16,16,16); 
 BLACKF  =getColor(94,58,0); 
 WHITEF  =getColor(180,114,0); 
}
//****************************
uint16_t getColor(uint8_t red, uint8_t green, uint8_t blue)
{
  red   >>= 3;
  green >>= 2;
  blue  >>= 3;
  return (red << 11) | (green << 5) | blue;
}
//****************************
void show_fig(int i,int j) {
uint16_t color,color_cont;  
   color=BLACKF;   
   if ((i+j+2)%2==0) color=WHITEF;           
   int jj=j, ii=i;
   if (rotate) { jj=7-j; ii=7-i; }   
   tft.fillRect(ii*24+12,jj*24,25,25,color);    
   tft.drawRect(ii*24+12,jj*24,25,25,WHITE);  
   color=BLACK; color_cont=GRAY;
   if (pole[j][i]>0) { color=WHITE; color_cont=BLACK; }
   if (pole[j][i]!=0) {
    drawBitmap(ii*24+17, jj*24+5,&fig[abs(pole[j][i])-1][0], 16, 16,color);          
    drawBitmap(ii*24+17, jj*24+5,&fig_cont[abs(pole[j][i])-1][0], 16, 16,color_cont);     
   }
}
//****************************
void show_board() { 
 for (int i=0;i<8;i++)
  for (int j=0;j<8;j++) {
    if (poledisp[j][i]!=pole[j][i]) show_fig(i,j);      
    poledisp[j][i]=pole[j][i];
  }  
}
//****************************
String str_step(int i) {
  String s="";
   if (steps[i].fig1==0) return s;
   if (steps[i].type==2) s="0-0";
    else if (steps[i].type==3) s="0-0-0";
   else  {
    if (abs(steps[i].fig1)>1) s=fig_symb[abs(steps[i].fig1)];   
    if (abs(steps[i].fig1<5)) {
     s=s+char(97+steps[i].y1);  
     s=s+String(8-steps[i].x1);    
     if (steps[i].fig2==0) s=s+"-";    
    }
    if (steps[i].fig2!=0) {
      s=s+"x";    
      if (abs(steps[i].fig2)>1) s=s+fig_symb[abs(steps[i].fig2)];
    }    
    s=s+char(97+steps[i].y2);  
    s=s+String(8-steps[i].x2);
   } 
   if (steps[i].type>3) s=s+fig_symb[steps[i].type-2];
   if (steps[i].check==1) s=s+"+"; else 
    if (steps[i].check==2) s=s+"#";
   return s;
}
//****************************
void show_steps() {
  tft.fillRect(206,0,114,214,getColor(8,8,8));  
  tft.fillRect(206,0,114,12,DARK);  
  tft.setTextSize(1); 
  tft.setTextColor(WHITE,DARK);    
  tft.setCursor(206,2);    
  tft.print(" ArduinoMega Chess "); 
  int i=1; int y=14;
  tft.setTextColor(GRAY);    
  int cur=(cur_step+1)/2; //   
  int lim_step=cur_step;         
  if (checkmatesearch&&lastscore>9000) {     
    tft.setTextColor(GREEN);
    lim_step=cur_step+10000-lastscore;
    cur=lim_step/2;
  }
  if (cur>20) i=cur-20;
  while (i<=cur&&y<207) { // 
    tft.setCursor(210,y);    
    tft.print(i); 
    tft.print("."); 
    if (steps[i*2-1].fig1!=0) tft.print(str_step(i*2-1));
    if (steps[i*2].fig1==0||i*2>lim_step) break;        
    tft.print(","); 
    tft.print(str_step(i*2));    
    i++; y+=10; 
  }
    
}
//****************************
boolean getdiagrowcheckw(char dj,char di) { //    
char d,j1,i1;           
   j1=WKJ; i1=WKI;
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]==-fq||pole[j1][i1]==-fb) return true;      
      if (pole[j1][i1]!=0) break;      
    } else break;
   }
   return false;
}
//****************************
boolean getdiagrowcheckb(char dj,char di) { //    
char d,j1,i1;           
   j1=BKJ; i1=BKI;
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]==fq||pole[j1][i1]==fb) return true;      
      if (pole[j1][i1]!=0) break;      
    } else break;
   }
   return false;
}
//****************************
boolean getstreightrowcheckw(char dj,char di) { //   - 
char d,j1,i1;  
   j1=WKJ; i1=WKI;
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;    
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]==-fq||pole[j1][i1]==-fr) return true;      
      if (pole[j1][i1]!=0) break;      
    } else break;
   }
   return false;
}
//****************************
boolean getstreightrowcheckb(char dj,char di) { //   - 
char d,j1,i1;  
   j1=BKJ; i1=BKI;
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;    
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]==fq||pole[j1][i1]==fr) return true;      
      if (pole[j1][i1]!=0) break;      
    } else break;
   }
   return false;
}
//****************************
boolean get_check(char king) { //      
  if (king==fk) { //             
    if (getdiagrowcheckw(-1, 1)) return true;    
    if (getdiagrowcheckw(-1,-1)) return true;              
    if (getdiagrowcheckw( 1,-1)) return true;
    if (getdiagrowcheckw( 1, 1)) return true;    
    if (getstreightrowcheckw(-1, 0)) return true;                  
    if (getstreightrowcheckw( 0, 1)) return true;    
    if (getstreightrowcheckw( 0,-1)) return true;    
    if (getstreightrowcheckw( 1, 0)) return true;            
    if (getpole(WKJ-2,WKI-1)&&pole[WKJ-2][WKI-1]==-fn) return true;           
    if (getpole(WKJ-2,WKI+1)&&pole[WKJ-2][WKI+1]==-fn) return true;            
    if (getpole(WKJ-1,WKI-2)&&pole[WKJ-1][WKI-2]==-fn) return true;        
    if (getpole(WKJ-1,WKI+2)&&pole[WKJ-1][WKI+2]==-fn) return true;        
    if (getpole(WKJ+1,WKI-2)&&pole[WKJ+1][WKI-2]==-fn) return true;        
    if (getpole(WKJ+1,WKI+2)&&pole[WKJ+1][WKI+2]==-fn) return true;        
    if (getpole(WKJ+2,WKI-1)&&pole[WKJ+2][WKI-1]==-fn) return true;        
    if (getpole(WKJ+2,WKI+1)&&pole[WKJ+2][WKI+1]==-fn) return true;              
    if (getpole(WKJ-1,WKI-1)&&pole[WKJ-1][WKI-1]==-fp) return true;    
    if (getpole(WKJ-1,WKI+1)&&pole[WKJ-1][WKI+1]==-fp) return true;                
  } else { //                 
    if (getdiagrowcheckb( 1,-1)) return true;
    if (getdiagrowcheckb( 1, 1)) return true;
    if (getdiagrowcheckb(-1, 1)) return true;
    if (getdiagrowcheckb(-1,-1)) return true;      
    if (getstreightrowcheckb( 1, 0)) return true;    
    if (getstreightrowcheckb( 0, 1)) return true;
    if (getstreightrowcheckb( 0,-1)) return true;
    if (getstreightrowcheckb(-1, 0)) return true;              
    if (getpole(BKJ+2,BKI-1)&&pole[BKJ+2][BKI-1]==fn) return true;    
    if (getpole(BKJ+2,BKI+1)&&pole[BKJ+2][BKI+1]==fn) return true;            
    if (getpole(BKJ+1,BKI-2)&&pole[BKJ+1][BKI-2]==fn) return true;    
    if (getpole(BKJ+1,BKI+2)&&pole[BKJ+1][BKI+2]==fn) return true;                
    if (getpole(BKJ-1,BKI-2)&&pole[BKJ-1][BKI-2]==fn) return true;    
    if (getpole(BKJ-1,BKI+2)&&pole[BKJ-1][BKI+2]==fn) return true;    
    if (getpole(BKJ-2,BKI-1)&&pole[BKJ-2][BKI-1]==fn) return true;   
    if (getpole(BKJ-2,BKI+1)&&pole[BKJ-2][BKI+1]==fn) return true;           
    if (getpole(BKJ+1,BKI-1)&&pole[BKJ+1][BKI-1]==fp) return true;
    if (getpole(BKJ+1,BKI+1)&&pole[BKJ+1][BKI+1]==fp) return true;      
  }    
  if (abs(BKJ-WKJ)<=1&&abs(BKI-WKI)<=1) return true; //    
  return false;
}
//****************************
boolean getpole(char j,char i) { //         
  if (j>=0&&j<8&&i>=0&&i<8) return true; 
  return false; 
}
//****************************
void addstep(char j1,char i1,char j2,char i2,char type) {       
 int st=start_var+cur_var; 
 steps[st].x1=j1;
 steps[st].x2=j2;
 steps[st].y1=i1;
 steps[st].y2=i2;
 steps[st].fig1=pole[j1][i1];
 steps[st].fig2=pole[j2][i2];        
 if (type==1) { //  
  steps[st].fig2=-steps[st].fig1;        
 }
 steps[st].type=type;   
 char ko=-fk; //   
 if (steps[st].fig1>0) ko=fk;   
 movestep(st);  
 if (get_check(ko)) { backstep(st); return; } //     -    
 boolean che=get_check(-ko); //      
 backstep(st);
 steps[st].weight=abs(steps[st].fig2)-abs(steps[st].fig1);
 if (type>3) steps[st].weight+=fig_weight[type-2]; 
 if (endspiel&&steps[st].fig1==ko) steps[st].weight+=10; //   -   
 steps[st].check=che;
 if (che) steps[st].weight+=10;
 if (only_action) {
  if (steps[st].fig1==fp&&steps[st].x2==1||steps[st].fig1==-fp&&steps[st].x2==6) // 
   { cur_var++; return; }
  if (steps[st].fig2==0&&steps[st].type<4&&!che&&!check_on_table) return;    
 }
 
 cur_var++; 
}
//****************************
void getrowstepsw(char j,char i,char dj,char di) { //        
char d,j1,i1;     
   j1=j; i1=i; 
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]<=0) addstep(j,i,j1,i1,0);
      if (pole[j1][i1]!=0) break;
    } else break;
   }
}
//****************************
void getrowstepsb(char j,char i,char dj,char di) { //    
char d,j1,i1;     
   j1=j; i1=i; 
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]>=0) addstep(j,i,j1,i1,0);
      if (pole[j1][i1]!=0) break;
    } else break;
   }
}
//****************************
void getonestepw(char j,char i,char dj,char di) { //       
char j1,i1;  
  j1=j+dj; i1=i+di;
  if (getpole(j1,i1)) 
    if (pole[j1][i1]<=0) addstep(j,i,j1,i1,0);   
}
//****************************
void getonestepb(char j,char i,char dj,char di) { //   
char j1,i1;  
  j1=j+dj; i1=i+di;
  if (getpole(j1,i1)) 
    if (pole[j1][i1]>=0) addstep(j,i,j1,i1,0);   
}
//****************************
void sort_variants(int from, int to) { //     
   while (1) { 
    int mov=0;     
    for (int i=from;i<to;i++)  //      
     if (steps[i].weight<steps[i+1].weight) {    
       mov++; 
       step_type buf=steps[i];
       steps[i]=steps[i+1];
       steps[i+1]=buf;      
     }                   
    if (mov==0) break;
   }    
}
//****************************  
void load_variants(int nstep) { //       nstep
  cur_var=0;       
  if (pole[WKJ][WKI]!=fk||pole[BKJ][BKI]!=-fk) kingpositions(); 
  if (nstep%2==1) check_on_table=get_check(fk);   
   else check_on_table=get_check(-fk); //      
  for (char i=0;i<8;i++)
   for (char j=0;j<8;j++) 
    if (pole[j][i]>0&&nstep%2==1||pole[j][i]<0&&nstep%2==0) { 
     switch (pole[j][i]) { 
     case fp: //          
      if (getpole(j-1,i)&&pole[j-1][i]==0) 
        if (j!=1) addstep(j,i,j-1,i,0); else 
          for (char t=4;t<8;t++) addstep(1,i,0,i,t); //-...                        
      if (j==6&&pole[j-1][i]==0&&pole[j-2][i]==0) addstep(j,i,j-2,i,0);
      if (getpole(j-1,i-1)&&pole[j-1][i-1]<0) 
       if (j!=1) addstep(j,i,j-1,i-1,0); else 
          for (char t=4;t<8;t++) addstep(j,i,j-1,i-1,t); //-...                                      
      if (getpole(j-1,i+1)&&pole[j-1][i+1]<0) 
       if (j!=1) addstep(j,i,j-1,i+1,0); else 
         for (char t=4;t<8;t++) addstep(j,i,j-1,i+1,t); //-...                                      
      if (j==3&&steps[nstep-1].fig1==-fp&&steps[nstep-1].x2==3&&steps[nstep-1].x1==1) {          
          if (steps[nstep-1].y2-i==1) { //                
            addstep(j,i,j-1,i+1,1);
          } else if (steps[nstep-1].y2-i==-1) { //                 
            addstep(j,i,j-1,i-1,1);
          }
      }  
     break;
     case -fp: //                  
      if (getpole(j+1,i)&&pole[j+1][i]==0) 
        if (j!=6) addstep(j,i,j+1,i,0); else 
          for (char t=4;t<8;t++) addstep(j,i,j+1,i,t); //-...                                
      if (j==1&&pole[j+1][i]==0&&pole[j+2][i]==0) addstep(j,i,j+2,i,0);
      if (getpole(j+1,i-1)&&pole[j+1][i-1]>0) 
       if (j!=6) addstep(j,i,j+1,i-1,0); else
         for (char t=4;t<8;t++) addstep(j,i,j+1,i-1,t); //-...                                       
      if (getpole(j+1,i+1)&&pole[j+1][i+1]>0) 
       if (j!=6) addstep(j,i,j+1,i+1,0); else
        for (char t=4;t<8;t++) addstep(j,i,j+1,i+1,t); //-...                                       
      if (j==4&&steps[nstep-1].fig1==fp&&steps[nstep-1].x2==4&&steps[nstep-1].x1==6) {                                      
          if (steps[nstep-1].y2-i==1) { //                            
            addstep(j,i,j+1,i+1,1);
          } else if (steps[nstep-1].y2-i==-1) { //                 
            addstep(j,i,j+1,i-1,1);
          }
      }          
     break;   
     case fn: //   
      getonestepw(j,i,-2,-1);
      getonestepw(j,i,-2,1);
      getonestepw(j,i,-1,-2);
      getonestepw(j,i,-1,2);
      getonestepw(j,i,2,-1);
      getonestepw(j,i,2,1);
      getonestepw(j,i,1,-2);
      getonestepw(j,i,1,2);
      break;   
     case -fn: //          
      getonestepb(j,i,-2,-1);
      getonestepb(j,i,-2,1);
      getonestepb(j,i,-1,-2);
      getonestepb(j,i,-1,2);
      getonestepb(j,i,2,-1);
      getonestepb(j,i,2,1);
      getonestepb(j,i,1,-2);
      getonestepb(j,i,1,2);
      break;
     case fb: //   
      getrowstepsw(j,i,1,1);
      getrowstepsw(j,i,-1,-1);
      getrowstepsw(j,i,1,-1);
      getrowstepsw(j,i,-1,1);   
      break; 
     case -fb: //      
      getrowstepsb(j,i,1,1);
      getrowstepsb(j,i,-1,-1);
      getrowstepsb(j,i,1,-1);
      getrowstepsb(j,i,-1,1);   
      break;
     case fr: //      
      getrowstepsw(j,i,1,0);
      getrowstepsw(j,i,-1,0);
      getrowstepsw(j,i,0,1);
      getrowstepsw(j,i,0,-1);
      break;
     case -fr: //               
      getrowstepsb(j,i,1,0);
      getrowstepsb(j,i,-1,0);
      getrowstepsb(j,i,0,1);
      getrowstepsb(j,i,0,-1);
      break;
     case fq: // 
      getrowstepsw(j,i,1,1);
      getrowstepsw(j,i,-1,-1);
      getrowstepsw(j,i,1,-1);
      getrowstepsw(j,i,-1,1);   
      getrowstepsw(j,i,1,0);
      getrowstepsw(j,i,-1,0);
      getrowstepsw(j,i,0,1);
      getrowstepsw(j,i,0,-1);   
      break;
     case -fq: //    
      getrowstepsb(j,i,1,1);
      getrowstepsb(j,i,-1,-1);
      getrowstepsb(j,i,1,-1);
      getrowstepsb(j,i,-1,1);   
      getrowstepsb(j,i,1,0);
      getrowstepsb(j,i,-1,0);
      getrowstepsb(j,i,0,1);
      getrowstepsb(j,i,0,-1);   
      break;
     case fk: // 
      getonestepw(j,i, 1,-1); 
      getonestepw(j,i, 1, 0); 
      getonestepw(j,i, 1, 1);       
      getonestepw(j,i, 0,-1);                        
      getonestepw(j,i, 0, 1);  
      getonestepw(j,i,-1,-1); 
      getonestepw(j,i,-1, 0); 
      getonestepw(j,i,-1, 1);            
      if (!check_on_table) add_rok(j,i,nstep);
      break;       
     case -fk: //    
      getonestepb(j,i, 1,-1); 
      getonestepb(j,i, 1, 0); 
      getonestepb(j,i, 1, 1);       
      getonestepb(j,i, 0,-1);                        
      getonestepb(j,i, 0, 1);  
      getonestepb(j,i,-1,-1); 
      getonestepb(j,i,-1, 0); 
      getonestepb(j,i,-1, 1);            
      if (!check_on_table) add_rok(j,i,nstep);
      break;       
    } //switch
   } //if 

   if (nstep>cur_step) {
    for (int i=start_var;i<start_var+cur_var;i++) { //                
     for (char j=0;j<MAXCUTS;j++)    
      if (cuts[j].fig1==steps[i].fig1&&
       cuts[j].x1==steps[i].x1&&cuts[j].y1==steps[i].y1&&
       cuts[j].x2==steps[i].x2&&cuts[j].y2==steps[i].y2) {
        steps[i].weight+=100+cuts[j].weight;              
        break;
      }      
     if (nstep>1&&steps[nstep-1].fig2!=0)  //     -      
       if (steps[nstep-1].x2==steps[i].x2&&steps[nstep-1].y2==steps[i].y2) 
         steps[i].weight+=1000;              
    }    
   }   

   sort_variants(start_var,start_var+cur_var-1);   
        
 }
//****************************
void movestep(int nstep) {     
  pole[steps[nstep].x1][steps[nstep].y1]=0;
  pole[steps[nstep].x2][steps[nstep].y2]=steps[nstep].fig1;   
  if (steps[nstep].fig1==fk) {
   WKJ=steps[nstep].x2; WKI=steps[nstep].y2; 
  } else if (steps[nstep].fig1==-fk) {
   BKJ=steps[nstep].x2; BKI=steps[nstep].y2; 
  }
  if (steps[nstep].type==0) return; 
  if (steps[nstep].type==1)  //  
   if (steps[nstep].fig1>0)
    pole[steps[nstep].x2+1][steps[nstep].y2]=0;
   else 
    pole[steps[nstep].x2-1][steps[nstep].y2]=0; 
  else if (steps[nstep].type==2)  // 
   if (steps[nstep].fig1>0) { //     
    pole[7][4]=0; pole[7][5]=fr; pole[7][6]=fk; pole[7][7]=0; //show_board(); delay(3000);
   } else { //        
    pole[0][4]=0; pole[0][5]=-fr; pole[0][6]=-fk; pole[0][7]=0; //show_board(); delay(3000);
    }
  else if (steps[nstep].type==3)  // 
   if (steps[nstep].fig1>0) { //     
    pole[7][0]=0; pole[7][1]=0; pole[7][2]=fk; pole[7][3]=fr; pole[7][4]=0;
   } else { //
    pole[0][0]=0; pole[0][1]=0; pole[0][2]=-fk; pole[0][3]=-fr; pole[0][4]=0;    
   }  
   else if (steps[nstep].type>3)  //-....
   if (steps[nstep].fig1>0) pole[steps[nstep].x2][steps[nstep].y2]=steps[nstep].type-2;
    else pole[steps[nstep].x2][steps[nstep].y2]=2-steps[nstep].type;
}
//****************************  
void backstep(int nstep) {
  pole[steps[nstep].x1][steps[nstep].y1]=steps[nstep].fig1; 
  pole[steps[nstep].x2][steps[nstep].y2]=steps[nstep].fig2; 
  if (steps[nstep].fig1==fk) {
    WKJ=steps[nstep].x1; WKI=steps[nstep].y1; 
  } else if (steps[nstep].fig1==-fk) {
    BKJ=steps[nstep].x1; BKI=steps[nstep].y1; 
  }
  if (steps[nstep].type==0) return;
  if (steps[nstep].type==1) { //  
    pole[steps[nstep].x2][steps[nstep].y2]=0;
    if (steps[nstep].fig1>0)
     pole[steps[nstep].x2+1][steps[nstep].y2]=-fp; 
    else 
     pole[steps[nstep].x2-1][steps[nstep].y2]=fp; 
  } else if (steps[nstep].type==2)  // 
   if (steps[nstep].fig1>0) { // 
    pole[7][4]=fk; pole[7][5]=0; pole[7][6]=0; pole[7][7]=fr; 
   } else { //
    pole[0][4]=-fk; pole[0][5]=0; pole[0][6]=0; pole[0][7]=-fr; // show_board(); delay(3000);
   }
  else if (steps[nstep].type==3)  // 
   if (steps[nstep].fig1>0) { // 
    pole[7][0]=fr; pole[7][1]=0; pole[7][2]=0; pole[7][3]=0; pole[7][4]=fk;    
   } else { //
    pole[0][0]=-fr; pole[0][1]=0; pole[0][2]=0; pole[0][3]=0; pole[0][4]=-fk;
   }
     
}
//****************************
void get_wrocks(int nstep) {
  w00=true; w000=true; 
  for (int i=1;i<nstep;i++) {
   if (steps[i].fig1==fk) { w00=false; w000=false; return; }  
   if (steps[i].fig1==fr) 
    if (steps[i].x1==7&&steps[i].y1==7) w00=false;
     else if (steps[i].x1==7&&steps[i].y1==0) w000=false;
  } 
}
//****************************
void get_brocks(int nstep) {
  b00=true; b000=true; 
  for (int i=1;i<nstep;i++) {
   if (steps[i].fig1==-fk) { b00=false; b000=false; return; }  
   if (steps[i].fig1==-fr) 
    if (steps[i].x1==0&&steps[i].y1==7) b00=false;
     else if (steps[i].x1==0&&steps[i].y1==0) b000=false;
  } 
}
//****************************
void add_rok(char j,char i,int nstep) { //   
boolean che1,che2;   
 if (nstep%2==1) { //   
  if (j!=7||i!=4) return;  
  if (pole[7][5]==0&&pole[7][6]==0&&pole[7][7]==fr) { //  
    pole[7][4]=0; 
    WKI=5; che1=get_check(fk); 
    WKI=6; che2=get_check(fk); 
    WKI=4; pole[7][4]=fk; 
    get_wrocks(nstep);
    if (!che1&&!che2&&w00) addstep(7,4,7,6,2);
  }
  if (pole[7][0]==fr&&pole[7][1]==0&&pole[7][2]==0&&pole[7][3]==0) { //
    pole[7][4]=0; 
    WKI=2; che1=get_check(fk); 
    WKI=3; che2=get_check(fk); 
    WKI=4; pole[7][4]=fk; 
    get_wrocks(nstep);
    if (!che1&&!che2&&w000) addstep(7,4,7,2,3);
  }
 } else { //
  if (j!=0||i!=4) return;  
  if (pole[0][5]==0&&pole[0][6]==0&&pole[0][7]==-fr) { //    
    pole[0][4]=0;
    BKI=5; che1=get_check(-fk); 
    BKI=6; che2=get_check(-fk); 
    BKI=4; pole[0][4]=-fk; 
    get_brocks(nstep);
    if (!che1&&!che2&&b00) addstep(0,4,0,6,2);
  }
  if (pole[0][0]==-fr&&pole[0][1]==0&&pole[0][2]==0&&pole[0][3]==0) { //
    pole[0][4]=0;
    BKI=2; che1=get_check(-fk); 
    BKI=3; che2=get_check(-fk); 
    BKI=4; pole[0][4]=-fk; 
    get_brocks(nstep);
    if (!che1&&!che2&&b000) addstep(0,4,0,2,3);
  }
   
 }
}
//****************************
int addrowstepsw(char j,char i,char dj,char di,char dc) { //       
char d,j1,i1; int c=0;        
   j1=j; i1=i; 
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]==0) c+=dc; 
      else if (pole[j1][i1]>0) { //           
        c+=1; break;
      } else {        
        if (cur_step>6) c+=-pole[j1][i1]; //               
        break;
      }
    } else break;
   }
   return c;
}
//****************************
int addrowstepsb(char j,char i,char dj,char di,char dc) { //   
char d,j1,i1; int c=0;    
   j1=j; i1=i; 
   for (d=1;d<8;d++) {    
    j1+=dj; i1+=di;
    if (getpole(j1,i1)) {      
      if (pole[j1][i1]==0) c-=dc; 
      else if (pole[j1][i1]<0) { //           
        c-=1; break;
      } else {        
        if (cur_step>6) c-=pole[j1][i1]; //               
        break;
      }
    } else break;
   }
   return c;
}
//****************************
int addonestepw(char j,char i,char dj,char di) { //       
char j1,i1;  
  j1=j+dj; i1=i+di;
  if (getpole(j1,i1)) 
    if (pole[j1][i1]==0) return 2;   
     else if (pole[j1][i1]>0) return 1;
      else return -pole[j1][i1];   
  return 0;    
}
//****************************
int addonestepb(char j,char i,char dj,char di) { //   
char j1,i1; 
  j1=j+dj; i1=i+di;
  if (getpole(j1,i1)) 
    if (pole[j1][i1]==0) return 2;   
     else if (pole[j1][i1]<0) return 1;
      else return pole[j1][i1];   
  return 0;  
}
//****************************
int activity() { //      - +  
int c=0;
char pwj[8],pwi[8],pbj[8],pbi[8],ipw=0,ipb=0,nbw=0,nbb=0; 
  if (checkmatesearch) return 0; //  
  for (char i=0;i<8;i++)
   for (char j=0;j<8;j++) 
    if (pole[j][i]!=0) { 
     switch (pole[j][i]) { 
     case fp: //      
      if (getpole(j,i+1)&&pole[j][i+1]==fp) c+=2; //      
      if (getpole(j-1,i)&&pole[j-1][i]==fp) c-=20; // 
      pwj[ipw]=j; pwi[ipw]=i; ipw++;
     break;
     case -fp: //                  
      if (getpole(j,i-1)&&pole[j][i-1]==-fp) c-=2; //      
      if (getpole(j+1,i)&&pole[j+1][i]==-fp) c+=20; // 
      pbj[ipb]=j; pbi[ipb]=i; ipb++;
     break;   
     case fn: //   
      c+=addonestepw(j,i,-2,-1);
      c+=addonestepw(j,i,-2,1);
      c+=addonestepw(j,i,-1,-2);
      c+=addonestepw(j,i,-1,2);
      c+=addonestepw(j,i,2,-1);
      c+=addonestepw(j,i,2,1);
      c+=addonestepw(j,i,1,-2);
      c+=addonestepw(j,i,1,2);
      break;   
     case -fn: //          
      c+=addonestepb(j,i,-2,-1);
      c+=addonestepb(j,i,-2,1);
      c+=addonestepb(j,i,-1,-2);
      c+=addonestepb(j,i,-1,2);
      c+=addonestepb(j,i,2,-1);
      c+=addonestepb(j,i,2,1);
      c+=addonestepb(j,i,1,-2);
      c+=addonestepb(j,i,1,2);
      break;
     case fb: //   
      c+=addrowstepsw(j,i,1,1,1);
      c+=addrowstepsw(j,i,-1,-1,2);
      c+=addrowstepsw(j,i,1,-1,1);
      c+=addrowstepsw(j,i,-1,1,2);   
      nbw++;
      break; 
     case -fb: //      
      c+=addrowstepsb(j,i,1,1,2);
      c+=addrowstepsb(j,i,-1,-1,1);
      c+=addrowstepsb(j,i,1,-1,2);
      c+=addrowstepsb(j,i,-1,1,1);   
      nbb++;
      break;
     case fr: //      
      c+=addrowstepsw(j,i,1,0,2); // 
      c+=addrowstepsw(j,i,-1,0,2);
      c+=addrowstepsw(j,i,0,1,1);
      c+=addrowstepsw(j,i,0,-1,1);
      break;
     case -fr: //               
      c+=addrowstepsb(j,i,1,0,2); //
      c+=addrowstepsb(j,i,-1,0,2);
      c+=addrowstepsb(j,i,0,1,1);
      c+=addrowstepsb(j,i,0,-1,1);
      break;
     case fq: // 
      if (cur_step>10) {
       c+=addrowstepsw(j,i,1,1,1);
       c+=addrowstepsw(j,i,-1,-1,2);
       c+=addrowstepsw(j,i,1,-1,1);
       c+=addrowstepsw(j,i,-1,1,2);   
       c+=addrowstepsw(j,i,1,0,1);
       c+=addrowstepsw(j,i,-1,0,2);
       c+=addrowstepsw(j,i,0,1,1);
       c+=addrowstepsw(j,i,0,-1,1);   
      } 
      break;
     case -fq: //    
      if (cur_step>10) {
       c+=addrowstepsb(j,i,1,1,2);
       c+=addrowstepsb(j,i,-1,-1,1);
       c+=addrowstepsb(j,i,1,-1,2);
       c+=addrowstepsb(j,i,-1,1,1);   
       c+=addrowstepsb(j,i,1,0,2);
       c+=addrowstepsb(j,i,-1,0,1);
       c+=addrowstepsb(j,i,0,1,1);
       c+=addrowstepsb(j,i,0,-1,1);   
      } 
      break;    
    } //switch
    if (cur_step>6) {
     if (pole[j][i]>0) { //   
      if (abs(WKJ-j)<2&&abs(WKI-i)<2) c+=3;  
      if (abs(BKJ-j)<2&&abs(BKI-i)<2) c+=3;  
      if (abs(WKJ-j)<3&&abs(WKI-i)<3) c+=2;  
      if (abs(BKJ-j)<3&&abs(BKI-i)<3) c+=2;  
     } else { //   
      if (abs(WKJ-j)<2&&abs(WKI-i)<2) c-=3;  
      if (abs(BKJ-j)<2&&abs(BKI-i)<2) c-=3;  
      if (abs(WKJ-j)<3&&abs(WKI-i)<3) c-=2;  
      if (abs(BKJ-j)<3&&abs(BKI-i)<3) c-=2;  
     }    
    } 
   }    
   if (nbw>1) c+=30; // 
   if (nbb>1) c-=30;
   for (char w=0;w<ipw;w++) { //   
    boolean pass=1;
    for (char b=0;b<ipb;b++) {
      if (pwi[w]>0&&pbi[b]==pwi[w]-1&&pbj[b]<pwj[w]) pass=0; // 
      if (pbi[b]==pwi[w]&&pbj[b]<pwj[w]) pass=0;  // 
      if ( pwi[w]<7&&pbi[b]==pwi[w]+1&&pbj[b]<pwj[w])  pass=0; //       
      if (!pass) break;
    }    
    if (pass) {      
      c+=50; 
      if (!endspiel) break; //     
    }
   }
   for (char b=0;b<ipb;b++) { //   
    boolean pass=1;
    for (char w=0;w<ipw;w++) {
      if (pbi[b]>0&&pwi[w]==pbi[b]-1&&pwj[w]>pbj[b]) pass=0; // 
      if (pwi[w]==pbi[b]&&pwj[w]>pbj[b]) pass=0; // 
      if (pbi[b]<7&&pwi[w]==pbi[b]+1&&pwj[w]>pbj[b]) pass=0; //       
      if (!pass) break;
    }
    if (pass) {      
      c-=50; 
      if (!endspiel) break; //     
    }
   }      
   return c;      
}
//****************************
int evaluate(int nstep) { //   
  long ww=0, wb=0;      
  for (char i=0;i<8;i++)
   for (char j=0;j<8;j++)     
    if (pole[j][i]<0) {
     wb+=fig_weight[-pole[j][i]]+(int)pgm_read_word(&pos[-pole[j][i]-1][7-j][i]);                               
    }
    else if (pole[j][i]>0) {
     ww+=fig_weight[pole[j][i]]+(int)pgm_read_word(&pos[pole[j][i]-1][j][i]);                              
    }   
  count++; //                  
  long str=activity();   
  if (endspiel) { // 
   wb+=(int)pgm_read_word(&pos[6][7-BKJ][BKI])-(int)pgm_read_word(&pos[5][7-BKJ][BKI]);                               
   ww+=(int)pgm_read_word(&pos[6][WKJ][WKI])-(int)pgm_read_word(&pos[5][WKJ][WKI]);                                    
   if (wb<450&&ww>450) { //  -   -         
    str-=(abs(WKJ-BKJ)+abs(WKI-BKI))*30;
   } else if (ww<450&&wb>450) { // 
    str+=(abs(WKJ-BKJ)+abs(WKI-BKI))*30;
   }
  } 
  if (nstep>8) { //   
    if (steps[nstep-1].fig1==steps[nstep-5].fig1&&steps[nstep-2].fig1==steps[nstep-6].fig1&&
     steps[nstep-3].fig1==steps[nstep-7].fig1&&steps[nstep-4].fig1==steps[nstep-8].fig1)
      if (steps[nstep-1].x1==steps[nstep-5].x1&&steps[nstep-2].x1==steps[nstep-6].x1&&
       steps[nstep-3].x1==steps[nstep-7].x1&&steps[nstep-4].x1==steps[nstep-8].x1)
        if (steps[nstep-1].x2==steps[nstep-5].x2&&steps[nstep-2].x2==steps[nstep-6].x2&&
         steps[nstep-3].x2==steps[nstep-7].x2&&steps[nstep-4].x2==steps[nstep-8].x2)
          if (steps[nstep-1].y1==steps[nstep-5].y1&&steps[nstep-2].y1==steps[nstep-6].y1&&
           steps[nstep-3].y1==steps[nstep-7].y1&&steps[nstep-4].y1==steps[nstep-8].x1)
            if (steps[nstep-1].y2==steps[nstep-5].y2&&steps[nstep-2].y2==steps[nstep-6].y2&&
             steps[nstep-3].y2==steps[nstep-7].y2&&steps[nstep-4].y2==steps[nstep-8].y2)
               { Serial.println(F(" Draw - 3 repeat")); return 0;   }   
  }
  if (nstep%2==1) return 5000*(ww-wb)/(ww+wb+2000)+str; else return 5000*(wb-ww)/(ww+wb+2000)-str;    
}
//****************************  
void add_cut(int ind) {// ind       
  int minbeta=30000, minindex=MAXCUTS-1;   
  for (char i=0;i<MAXCUTS;i++) {   
   if (cuts[i].weight==0) { minindex=i; break; }//  
   if (cuts[i].fig1==steps[ind].fig1&&
       cuts[i].x1==steps[ind].x1&&cuts[i].y1==steps[ind].y1&&
       cuts[i].x2==steps[ind].x2&&cuts[i].y2==steps[ind].y2) {
       cuts[i].weight++; return; // -    1
   }     
   if (cuts[i].weight<minbeta) { //   
    minbeta=cuts[i].weight; 
    minindex=i;
   }      
  }
  cuts[minindex]=steps[ind];
  cuts[minindex].weight=1; //1 
}
//****************************  
int quiescence(int start, int nstep, int alpha, int beta ) {    
    if (nstep-cur_step>=LIMDEPTH||start>MAXSTEPS-70) return evaluate(nstep);                
    if (!solving&&progress==0) return -5000;                
    int score=-20000;           
    start_var=start; 
    only_action=true;   
    load_variants(nstep);    
    if (!check_on_table) {
     int stand_pat = evaluate(nstep);
     if (stand_pat >= score) score=stand_pat; 
     if (score>alpha) alpha=score;
     if (alpha>=beta) return alpha;       
    }                     
    if (cur_var==0) { 
      if (check_on_table) {      
       if (TRACE) Serial.println(F("checkmate?"));                        
       return -10000+nstep-cur_step;                     
     } else return evaluate(nstep);
    }
    int j=start+cur_var;      
    for (int i=start;i<j;i++) { //            
      if (TRACE) { //*****
       for (int u=0;u<nstep-cur_step;u++) Serial.print(F("   .   "));      
       Serial.println(str_step(i)); 
      }      
      movestep(i);            
      steps[nstep]=steps[i];              
      int tmp=-quiescence(j+1,nstep+1,-beta,-alpha);            
      backstep(i);              
      if (tmp>score) score=tmp;
      if (score>alpha) alpha=score;
      if (alpha>=beta )   {               
         add_cut(nstep);         
         return alpha;   
      }          
      if (checkmatesearch&&alpha>9000) break;     
      gui();                              
    }    
    return score;
}
//****************************  
int alphaBeta(int start, int nstep, int alpha, int beta, int depthleft) {
//start -            
//nstep -    
int score=-20000,best;
   if( depthleft==0) return quiescence(start,nstep,alpha,beta) ;      
   if (start>MAXSTEPS-70) return evaluate(nstep);              
   start_var=start; 
   only_action=false;         
   if (nstep!=cur_step) load_variants(nstep);     
   if (cur_var==0) { 
      if (check_on_table) {
       if (TRACE) Serial.println(F("checkmate!"));                 
       return -10000+nstep-cur_step;              
      } 
     return 0;
   }    
   int j=start+cur_var;     
   best=start;   
   for (int i=start;i<j;i++) { //                  
      if (nstep==cur_step) {              
        Serial.print(str_step(i)); Serial.print("  ");
        Serial.print(i-start+1); Serial.print("/"); Serial.print(j-start);                        
        if (steps[i].weight<-9000) { Serial.println(F(" checkmate")); continue; }
        if (steps[i].fig2!=0||steps[i].check||alpha<-100) 
        // , ,     -100    
         { LIMDEPTH=MAXDEPTH+2; Serial.print(F("+2")); } else LIMDEPTH=MAXDEPTH; 
      } else {
        if (TRACE) { //*****
         for (int u=0;u<nstep-cur_step;u++) Serial.print(F("       "));      
         Serial.println(str_step(i));
        } 
      }                  
      movestep(i);      
      steps[nstep]=steps[i];        
      int tmp=-alphaBeta(j+1,nstep+1,-beta,-alpha,depthleft-1);            
      backstep(i);
      steps[i].weight=tmp;
      if (tmp>score) score=tmp;
      if (score>alpha) {
        alpha=score;
        if (nstep>cur_step) add_cut(nstep); //           
        if (TRACE) { Serial.print(F("ALPHA+:")); Serial.println(score); }        
        best=i;         
        if (nstep==cur_step) {
         steps[0]=steps[best];           
         Serial.print(F(" BEST")); 
        }
      }
      if (alpha>=beta )   {        
       if (nstep>cur_step) add_cut(nstep); //                              
       if (TRACE) { Serial.print(F("BETA CUT:"));  Serial.println(score); }
       return alpha;            
      }   
      if (nstep==cur_step) {         
        Serial.print(F("        ")); Serial.println(tmp);        
        progress=100*(i-start+1)/(j-start);      
        if (alpha==9999||alpha==-5000) break;                     
        if (checkmatesearch&&alpha>9000&&limit<3) break;      
        if (!solving) {
         if (alpha>startweight&&cur_level>1) break;
          else { //      -      +50%
           if (BAction.bs==F("stopping")) break;                       
           if (cur_level>1&&100*(millis()-starttime)/(limittime-starttime)>240-limit*20) break;           
         }  
        }                   
      }       
      if (nstep==cur_step+1&&!solving&&progress==0) break;        
      gui();                                    
   }
   if (nstep==cur_step) { steps[nstep]=steps[best]; steps[0]=steps[best]; }                         
   return score;
}
//****************************  
void kingpositions() { 
 for (char i=0;i<8;i++) // 
  for (char j=0;j<8;j++)     
   if (pole[j][i]==fk) {
      WKJ=j; WKI=i; 
   } else if (pole[j][i]==-fk) {
      BKJ=j; BKI=i; 
   }    
}
//****************************  
int get_endspiel() { //   
  int weight=0;  
  for (char i=0;i<8;i++)
   for (char j=0;j<8;j++)     
    if (pole[j][i]<0) 
     weight+=fig_weight[-pole[j][i]];                               
    else if (pole[j][i]>0) 
     weight+=fig_weight[pole[j][i]]; //   8000
  if (weight<3500) endspiel=true; else endspiel=false;  
  return weight;
}
//****************************  
boolean is_drawn() { //   
  boolean drawn=false;
  int cn=0,cbw=0,cbb=0,co=0,cb=0,cw=0;
  for (char i=0;i<8;i++)
   for (char j=0;j<8;j++)   {  
    if (abs(pole[j][i])==1) co++;  
    if (abs(pole[j][i])>3&&abs(pole[j][i])<6) co++; // , ,   
    if (abs(pole[j][i])==6) continue;  // 
    if (abs(pole[j][i])==2) cn++; // 
    if (abs(pole[j][i])==3&&(i+j+2)%2==0) cbb++; //  
    if (abs(pole[j][i])==3&&(i+j+2)%2==1) cbw++; //   
    if (pole[j][i]==3) cw++; //     
    if (pole[j][i]==-3) cb++; //     
  }
  if (cn==1&&co+cbb+cbw==0) drawn=true;  // 
  if (cbb+cbw==1&&co+cn==0) drawn=true;  // 
  if (co+cn+cbb==0||co+cn+cbw==0) drawn=true; //    
  if (co+cn==0&&cb==1&&cw==1) drawn=true; //    
  if (drawn) return drawn;
  int rep=1;
  for (int s=cur_step-1; s>0; s--) {
    if (steps[s].fig1==0) continue;
    backstep(s); 
    boolean eq=true;    
    for (char i=0;i<8;i++)
     for (char j=0;j<8;j++) 
      if (pole[j][i]!=pole0[j][i]) 
       { eq=false; break; }
    if (eq) rep++;
    if (rep>2) break;    
  }  
  if (rep>1) { Serial.print(rep); Serial.println(" repetitions"); }
  for (char i=0;i<8;i++)
    for (char j=0;j<8;j++) pole[j][i]=pole0[j][i];   //          
  if (rep>2) drawn=true;
  return drawn;
}
//****************************  
int solve_step() { 
const int LMIN[6]={2,3,4,5,6,7};  
const int LMAX[6]={4,6,8,10,12,14};
const int LCMIN[6]={2,4,6,8,10,12};  
const int LCMAX[6]={4,6,8,10,12,14};
boolean check_on; 
 tft.fillRect(0,210,60,10,BLACK);             
 tft.drawFastHLine(5,210,200,DARK);   
 starttime=millis();    
 isstatus=1;
 deletebuttons();
 BAction.Show("STOP"); 
 BBW.Hide();   
 BBack.Hide();  
 BLimit.Hide();  
 BCM.Hide(); 
 BDesc.Hide(); 
 BSound.Hide(); 
 BRotate.Hide();  
 limittime=starttime+limits[limit]*1000; //       
 for (char i=0;i<8;i++)
    for (char j=0;j<8;j++) pole0[j][i]=pole[j][i];   //         
 lastbest.fig1=0;    
 kingpositions(); 
 int wei=get_endspiel();     
 count=0; 
 startweight=evaluate(cur_step);
 Serial.println("");
 Serial.println(F("---------------"));
 if (endspiel) { Serial.print(F("Endspiel: ")); Serial.println(wei); }   
 if (cur_step%2==1) Serial.print(F("WHITE, ")); else Serial.print(F("BLACK, "));
 Serial.print(F("start Score= ")); Serial.println(startweight);
 start_var=cur_step+21;
 only_action=false;     
 lastbest.fig1=0;
 steps[0].fig1=0;
 load_variants(cur_step);       
 check_on=check_on_table; 
 if (cur_var==0||is_drawn()) {  
  beep(500);
  tft.drawFastHLine(5,210,200,BLACK);   
  tft.drawFastHLine(5,212,200,BLACK);   
  BAction.Hide();
  isstatus=0;
  solving=false;  
  if (check_on_table) return -9999; else return 8999;
 }
 if (cur_var==1) { //  1
  tft.drawFastHLine(5,210,200,BLACK);   
  tft.drawFastHLine(5,212,200,BLACK);   
  BAction.Hide();
  isstatus=0;
  solving=false;  
  steps[cur_step]=steps[cur_step+21];
  return startweight; 
 }          
 int vars=cur_var;   
 int ALPHA=-20000; 
 int BETA=20000;
 int score; 
 solving=true; 
 if (checkmatesearch) { 
  Serial.println(F("Checkmate search"));
  steps[cur_step].fig1=0; lastscore=0; show_steps();
 }
 int l=0;
 for (char i=0;i<MAXCUTS;i++) { cuts[i].weight=0; cuts[i].fig1=0; } //   
 for (int i=cur_step+21;i<cur_step+21+vars;i++) {  //   
  movestep(i);
  steps[i].weight=evaluate(cur_step);
  if (steps[i].fig2!=0) steps[i].weight-=steps[i].fig1;
  backstep(i);
 } 
 while (l<6) {
  cur_level=l+1;  
  progress=0;
  tft.drawFastHLine(5,212,200,DARK);  
  MINDEPTH=LMIN[l];  
  MAXDEPTH=LMAX[l];        
  if (checkmatesearch) {   
    ALPHA=9000; BETA=10000; 
    MINDEPTH=LCMIN[l];
    MAXDEPTH=LCMAX[l];    
  }    
  if (l>0) Serial.println(""); Serial.print(F("******* LEVEL=")); Serial.print(l+1);   
  Serial.print(" "); Serial.print(MINDEPTH); Serial.print("-"); Serial.print(MAXDEPTH);     
  Serial.print("  "); Serial.print((millis()-starttime)/1000.,1); Serial.println("s");                                          
  if (checkmatesearch) {
    for (int i=cur_step+21;i<cur_step+21+vars;i++) { // -   
     movestep(i);   
     start_var=cur_step+22+vars;
     only_action=false;   
     load_variants(cur_step+1);     
     backstep(i);           
     steps[i].weight=-cur_var;     
    }
  }   
  sort_variants(cur_step+21,cur_step+20+vars);  //            
  cur_var=vars;
  check_on_table=check_on;
  score=alphaBeta(cur_step+21,cur_step,ALPHA,BETA,MINDEPTH);  
  if (score>9996) break;   
  if (score>9000&&limit<3) break;  
  if (100*(millis()-starttime)/(limittime-starttime)>70-l*8) break;          
  if (!solving) break;              
  l++;     
 } //while l    
 if (score<-9000) {   
   Serial.println(F("GIVE UP!")); 
 } else {
  Serial.print(F("STEP=")); Serial.println(str_step(cur_step));  
  if (score>9000) {   
   Serial.print(F("CHECKMATE ")); 
   if (score<9999) {
     Serial.print(F("in ")); Serial.print((9999-score)/2+1); Serial.print(F(" steps"));        
   } else steps[cur_step].check=2;
   Serial.println("");  
   if (checkmatesearch) {    
     steps[cur_step+9999-score].check=2;    
     steps[cur_step+10000-score].fig1=0;    
     for (int i=cur_step;i<cur_step+10000-score;i++) Serial.println(str_step(i));   
   }    
  } 
 }
 tft.drawFastHLine(5,210,200,BLACK);   
 tft.drawFastHLine(5,212,200,BLACK);  
 progress=0; 
 show_status();
 BAction.Hide(); 
 solving=0; 
 isstatus=0;
 return score;
 
 
}
//****************************  
ArduinoMega Chess 1.0 MCUFRIEND 320x480Arduino
Sketch updated to touchscreen MCUFRIEND 320x480 pixels.
//ArduinoMega Chess 1.0  (MCUFRIEND 320x480 version)
//Sergey Urusov, ususovsv@gmail.com

#include <UTFTGLUE.h>
#include <stdint.h>
#include "TouchScreen.h"
#include <avr/pgmspace.h>
#include <EEPROM.h> 

uint16_t BLACK,BLUE,RED,GREEN,CYAN,MAGENTA,YELLOW,WHITE,GRAY,DARK,GRAY2,BLACKF,WHITEF;
MCUFRIEND_kbv tft;

int XP = 6, YP = A1, XM = A2, YM = 7;  
TouchScreen ts(XP, YP, XM, YM, 300);   
TSPoint tp;                            

int touchx,touchy,touchx0,touchy0,ntouch;         
unsigned long lasttouch;
#define MINPRESSURE 10
#define MAXPRESSURE 1000
const int PinBuzz = 44;
int cycle=0; // 
const char fp=1;
const char fn=2;
const char fb=3;
const char fr=4;
const char fq=5;
const char fk=6;
const int fig_weight[]={0,100,320,330,500,900,0};
const char fig_symb[]="  NBRQK";
unsigned long count;
boolean rotate=false;
const char polezero[8][8] PROGMEM={
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             };  
const char polestart[8][8] PROGMEM={
             {-fr,-fn,-fb,-fq,-fk,-fb,-fn,-fr},
             {-fp,-fp,-fp,-fp,-fp,-fp,-fp,-fp},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             { fp, fp, fp, fp, fp, fp, fp, fp},
             { fr, fn, fb, fq, fk, fb, fn, fr},
             };  
             
char pole[8][8]={ //  3 
             {-fr,-fn,-fb,-fq,-fk,-fb,-fn,-fr},
             {-fp,-fp,-fp,-fp,-fp,-fp,-fp,-fp},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             {  0,  0,  0,  0,  0,  0,  0,  0},
             { fp, fp, fp, fp, fp, fp, fp, fp},
             { fr, fn, fb, fq, fk, fb, fn, fr},
             };  
             
char pole0[8][8];  //   
char poledisp[8][8]; // 
char polechoice[7]; // 
boolean w00,w000,b00,b000;             
char blinkstep;
typedef struct {
  char fig1, fig2; //    
  char x1,y1,x2,y2; //     
  char check; //  
  char type; //  1-  ,2- ,3- ,4-5-6-7-  ,,,
  int weight; // , 
} step_type;
const int MAXSTEPS=500; //.      
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int MINDEPTH; //.   
int MAXDEPTH; //.   
int LIMDEPTH; //.       
const char MAXCUTS=10; //.. -  - (10-  ,  20)
boolean TRACE=0;
boolean checkmatesearch=0; //   
boolean solving=false;
boolean choice=false;
boolean sound=0;
int cur_step=1; //  , 1....
int limit=0; //  , 0-6;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const long limits[7]={10,30,60,180,600,1800,100000};
//                     0  1  2   3   4    5      6 
step_type steps[MAXSTEPS]; //  
step_type cuts[MAXCUTS]; //  -
step_type lastbest;
int lastscore;
int minbeta,maxalpha;
int startweight;
int cur_level; //   ()
int start_var; //   , 1....
int cur_var; //  , 1....
int cur_choice; //   
boolean check_on_table; //  
boolean isstatus;
char WKJ=0,WKI=0,BKJ=0,BKI=0; // 
boolean endspiel=false; // 
char progress; //   0-100
boolean only_action=false; // -  
unsigned long starttime,limittime,quitime=0;             
boolean drag;
const uint8_t fig[6][32] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x3,  0xC0, 0x7,  0xE0, 0x7,  0xE0, 0x3,  0xC0, 0x3,  0xC0,
0x7,  0xE0, 0x3,  0xC0, 0x3,  0xC0, 0x7,  0xE0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0x0,  0x0}, //
{0x0, 0x0,  0x3,  0x40, 0x7,  0xE0, 0xF,  0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x39, 0xFC, 0x33, 0xFC,
0x7,  0xFC, 0xF,  0xF8, 0xF,  0xF0, 0x7,  0xE0, 0x3,  0xC0, 0x7,  0xE0, 0x1F, 0xF8, 0x0,  0x0},  //
{0x1, 0x80, 0x3,  0xC0, 0x1,  0x80, 0xF,  0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8,
0x1F, 0xF8, 0x1F, 0xF8, 0xF,  0xF0, 0x7,  0xE0, 0x3,  0xC0, 0x31, 0x8C, 0x7F, 0xFE, 0x0,  0x0}, // 
{0x0, 0x0,  0x19, 0x98, 0x1F, 0xF8, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0,
0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0xF,  0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x0,  0x0}, //
{0x19, 0x98, 0xD9, 0x9B, 0xD9, 0x9B, 0xD9, 0x9B, 0x6D, 0xB6, 0x6D, 0xB6, 0x6D, 0xB6, 0x35, 0xAC,
0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x1F, 0xF8, 0xF,  0xF0, 0xF,  0xF0, 0x1F, 0xF8, 0x0,  0x0}, //
{0x1, 0x80, 0x1,  0x80, 0x79, 0x9E, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x7F, 0xFE, 0x3F, 0xFC, 0x3F, 0xFC, 0x1F, 0xF8, 0xF,  0xF0, 0xF,  0xF0, 0x1F, 0xF8, 0x0,  0x0}  //
};
const uint8_t fig_cont[6][32] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x3,  0xC0, 0x4,  0x20, 0x8,  0x10, 0x8,  0x10, 0x4,  0x20, 0x4,  0x20,
0x8,  0x10, 0x4,  0x20, 0x4,  0x20, 0x8,  0x10, 0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x1F, 0xF8}, //
{0x3, 0x40, 0x4,  0xA0, 0x8,  0x10, 0x12, 0x8,  0x20, 0x4,  0x40, 0x2,  0x46, 0x2,  0x4C, 0x2,
0x38, 0x2,  0x10, 0x4,  0x10, 0x8,  0x8,  0x10, 0x4,  0x20, 0x18, 0x18, 0x20, 0x4,  0x3F, 0xFC},  //
{0x2, 0x40, 0x4,  0x20, 0x6,  0x60, 0x10, 0x8,  0x21, 0x84, 0x21, 0x84, 0x21, 0x84, 0x27, 0xE4,
0x21, 0x84, 0x21, 0x84, 0x11, 0x88, 0x8,  0x10, 0x34, 0x2C, 0x4E, 0x72, 0x80, 0x1,  0xFF, 0xFF}, // 
{0x39, 0x9C, 0x26, 0x64, 0x20, 0x4,  0x1F, 0xF8, 0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x10, 0x8,
0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x10, 0x8,  0x1F, 0xF8, 0x20, 0x4,  0x20, 0x4,  0x3F, 0xFC}, //
{0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x26, 0x64, 0x92, 0x49, 0x92, 0x49, 0x92, 0x49, 0x4A, 0x52,
0x40, 0x2,  0x40, 0x2,  0x5F, 0xFA, 0x20, 0x4,  0x1F, 0xF8, 0x10, 0x8,  0x20, 0x4,  0x3F, 0xFC}, //
{0x2, 0x40, 0x7A, 0x5E, 0x86, 0x61, 0x82, 0x41, 0x2,  0x40, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80,
0x80, 0x81, 0x41, 0x82, 0x5F, 0xFA, 0x20, 0x4,  0x1F, 0xF8, 0x10, 0x8,  0x20, 0x4,  0x3F, 0xFC}  //
};

const uint8_t fig24[6][72] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1E, 0x0,  0x0,  0x3F, 0x0,  0x80, 0x7F, 0x0,  0x80, 0x7F, 0x0,
0x80, 0x7F, 0x0,  0x0,  0x3F, 0x0,  0x0,  0x1C, 0x0,  0x0,  0x1C, 0x0,  0x80, 0xFF, 0x0,  0x80, 0xFF, 0x0,  0x0,  0x1C, 0x0,  0x0,  0x1C, 0x0,
0x0,  0x3E, 0x0,  0x0,  0x7F, 0x0,  0x80, 0xFF, 0x0,  0xC0, 0xFF, 0x1,  0xE0, 0xFF, 0x3,  0xE0, 0xFF, 0x3,  0xE0, 0xFF, 0x3,  0x0,  0x0,  0x0
}, //pawn
{0x0, 0x0,  0x0,  0x0,  0x6E, 0x0,  0x0,  0xFF, 0x0,  0x80, 0xFF, 0x1,  0x80, 0xFF, 0x3,  0xC0, 0xFF, 0x7,  0xE0, 0xFF, 0xF,  0xE0, 0xF9, 0xF,
0xF0, 0xF8, 0xF,  0xF0, 0xF8, 0xF,  0x60, 0xFC, 0xF,  0x0,  0xFE, 0xF,  0x0,  0xFF, 0xF,  0x0,  0xFF, 0x7,  0x0,  0xFF, 0x3,  0x0,  0xFF, 0x1,
0x0,  0xFE, 0x0,  0x0,  0x7C, 0x0,  0x0,  0x38, 0x0,  0x0,  0x38, 0x0,  0x0,  0x7C, 0x0,  0xF0, 0xFF, 0xF,  0xF0, 0xFF, 0xF,  0x0,  0x0,  0x0
}, //knight
{0x0, 0x0,  0x0,  0x0,  0x3C, 0x0,  0x0,  0x7E, 0x0,  0x0,  0x7E, 0x0,  0x0,  0x3C, 0x0,  0x0,  0x18, 0x0,  0x80, 0xFF, 0x1,  0xC0, 0xFF, 0x3,
0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,
0xE0, 0xFF, 0x7,  0xC0, 0xFF, 0x3,  0x80, 0xFF, 0x1,  0x0,  0xFF, 0x0,  0x8,  0x7E, 0x10, 0x1C, 0x3C, 0x38, 0xFE, 0xFF, 0x7F, 0x0,  0x0,  0x0
}, //bishop
{0x0, 0x0,  0x0,  0xF0, 0x3C, 0xF,  0xF0, 0x3C, 0xF,  0xF0, 0xFF, 0xF,  0xE0, 0xFF, 0x7,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,
0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,
0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xC0, 0xFF, 0x3,  0xE0, 0xFF, 0x7,  0xF0, 0xFF, 0xF,  0xF0, 0xFF, 0xF,  0x0,  0x0,  0x0
}, //rook
{0x0, 0x0,  0x0,  0xEE, 0xBD, 0x77, 0xEE, 0xBD, 0x77, 0xC6, 0x18, 0x63, 0xC6, 0x18, 0x63, 0xC6, 0x18, 0x63, 0xCC, 0x18, 0x33, 0xCC, 0x18, 0x33,
0xCC, 0x18, 0x33, 0xCC, 0x18, 0x33, 0xCC, 0x18, 0x33, 0x98, 0x99, 0x19, 0x98, 0x99, 0x19, 0x98, 0x99, 0x19, 0x98, 0x99, 0x19, 0x98, 0x99, 0x19,
0x30, 0xFF, 0xC,  0xB0, 0xFF, 0xD,  0xF0, 0xFF, 0xF,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xF0, 0xFF, 0xF,  0xF0, 0xFF, 0xF,  0x0,  0x0,  0x0
}, //queen
{0x0, 0x0,  0x0,  0x0,  0x18, 0x0,  0xF0, 0x18, 0xF,  0xF8, 0x99, 0x1F, 0xFC, 0xDB, 0x3F, 0xFE, 0xFF, 0x7F, 0xFE, 0xFF, 0x7F, 0xFE, 0xFF, 0x7F,
0xFE, 0xFF, 0x7F, 0xFE, 0xFF, 0x7F, 0xFE, 0xFF, 0x7F, 0xFE, 0xFF, 0x7F, 0xFE, 0xFF, 0x7F, 0xFE, 0xFF, 0x3F, 0xFC, 0xFF, 0x1F, 0xF8, 0xFF, 0x1F,
0xF0, 0xFF, 0xF,  0xE0, 0xFF, 0x7,  0xE0, 0xFF, 0x7,  0xC0, 0xFF, 0x3,  0xE0, 0xFF, 0x7,  0xF0, 0xFF, 0xF,  0xF0, 0xFF, 0xF,  0x0,  0x0,  0x0
} //king
};

const uint8_t fig24_cont[6][72] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1C, 0x0,  0x0,  0x22, 0x0,  0x0,  0x41, 0x0,  0x80, 0x80, 0x0,  0x80, 0x80, 0x0,
0x80, 0x80, 0x0,  0x0,  0x41, 0x0,  0x0,  0x22, 0x0,  0xC0, 0xE3, 0x1,  0x40, 0x0,  0x1,  0x40, 0x0,  0x1,  0xC0, 0xE3, 0x1,  0x0,  0x22, 0x0,
0x0,  0x41, 0x0,  0x80, 0x80, 0x0,  0x40, 0x0,  0x1,  0x20, 0x0,  0x2,  0x10, 0x0,  0x4,  0x10, 0x0,  0x4,  0x10, 0x0,  0x4,  0xF0, 0xFF, 0x7
}, //pawn
{0x0, 0x6E, 0x0,  0x0,  0x91, 0x0,  0x80, 0x0,  0x1,  0x40, 0x2,  0x2,  0x40, 0x0,  0x4,  0x20, 0x0,  0x8,  0x10, 0x0,  0x10, 0x10, 0x6,  0x10,
0x8,  0x5,  0x10, 0x8,  0x5,  0x10, 0x90, 0x2,  0x10, 0x60, 0x1,  0x10, 0x80, 0x0,  0x10, 0x80, 0x0,  0x8,  0x80, 0x0,  0x4,  0x80, 0x0,  0x2,
0x0,  0x1,  0x1,  0x0,  0x82, 0x0,  0x0,  0x44, 0x0,  0x0,  0x44, 0x0,  0xF8, 0x83, 0x1F, 0x8,  0x0,  0x10, 0x8,  0x0,  0x10, 0xF8, 0xFF, 0x1F
}, //knight
{0x0, 0x3C, 0x0,  0x0,  0x42, 0x0,  0x0,  0x81, 0x0,  0x0,  0x81, 0x0,  0x0,  0x42, 0x0,  0x80, 0xE7, 0x1,  0x40, 0x0,  0x2,  0x20, 0x18, 0x4,
0x10, 0x18, 0x8,  0x10, 0x18, 0x8,  0x10, 0x18, 0x8,  0x90, 0xFF, 0x9,  0x90, 0xFF, 0x9,  0x10, 0x18, 0x8,  0x10, 0x18, 0x8,  0x10, 0x18, 0x8,
0x10, 0x18, 0x8,  0x20, 0x18, 0x4,  0x40, 0x18, 0x2,  0x88, 0x0,  0x11, 0x14, 0x81, 0x28, 0xE2, 0xC3, 0x47, 0x1,  0x0,  0x80, 0xFF, 0xFF, 0xFF
}, //bishop
{0xF8, 0x7E, 0x1F, 0x8,  0xC3, 0x10, 0x8,  0xC3, 0x10, 0x8,  0x0,  0x10, 0x10, 0x0,  0x8,  0xE0, 0xFF, 0x7,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,
0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,
0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0x20, 0x0,  0x4,  0xE0, 0xFF, 0x7,  0x10, 0x0,  0x8,  0x8,  0x0,  0x10, 0x8,  0x0,  0x10, 0xF8, 0xFF, 0x1F
}, //rook
{0xEF, 0xBD, 0xF7, 0x11, 0x42, 0x88, 0x11, 0x42, 0x88, 0x29, 0xA5, 0x94, 0x29, 0xA5, 0x94, 0x29, 0xA5, 0x94, 0x32, 0xA5, 0x4C, 0x32, 0xA5, 0x4C,
0x32, 0xA5, 0x4C, 0x32, 0xA5, 0x4C, 0x32, 0xA5, 0x4C, 0x64, 0x66, 0x26, 0x64, 0x66, 0x26, 0x64, 0x66, 0x26, 0x64, 0x66, 0x26, 0x64, 0x66, 0x26,
0xC8, 0x0,  0x13, 0x48, 0x0,  0x12, 0x8,  0x0,  0x10, 0x10, 0x0,  0x8,  0xF0, 0xFF, 0xF,  0x8,  0x0,  0x10, 0x8,  0x0,  0x10, 0xF8, 0xFF, 0x1F
}, //queen
{0x0, 0x18, 0x0,  0xF0, 0x24, 0xF,  0x8,  0xA5, 0x10, 0x4,  0x66, 0x20, 0x2,  0x24, 0x40, 0x1,  0x24, 0x80, 0x1,  0x18, 0x80, 0x1,  0x18, 0x80,
0x1,  0x18, 0x80, 0x1,  0x18, 0x80, 0x1,  0x18, 0x80, 0x1,  0x18, 0x80, 0x1,  0x18, 0x80, 0x1,  0x18, 0x40, 0x2,  0x18, 0x20, 0x4,  0x18, 0x20,
0xE8, 0xFF, 0x17, 0x10, 0x0,  0x8,  0x10, 0x0,  0x8,  0x20, 0x0,  0x4,  0xF0, 0xFF, 0xF,  0x8,  0x0,  0x10, 0x8,  0x0,  0x10, 0xF8, 0xFF, 0x1F
} //king
};


const uint8_t issound[2][32] PROGMEM={
{0x0, 0x0,  0x0,  0x0,  0x0,  0x32, 0x0,  0x54, 0x0,  0x98, 0x1F, 0x10, 0x10, 0x30, 0x10, 0x50,
0x10, 0x90, 0x11, 0x10, 0x1F, 0x10, 0x4,  0x90, 0x8,  0x50, 0x10, 0x30, 0x0,  0x0,  0x0,  0x0},
{0x0, 0x0,  0x0,  0x0,  0x0,  0x30, 0x0,  0x50, 0x0,  0x90, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x0,  0x90, 0x0,  0x50, 0x0,  0x30, 0x0,  0x0,  0x0,  0x0}
};
const uint8_t iswb[2][32] PROGMEM={
{0x0,  0x0,  0x0,  0x0,  0x3,  0xC0, 0x4,  0x20, 0x8,  0x10, 0x8,  0x10, 0x4,  0x20, 0x4,  0x20,
0x8,  0x10, 0x4,  0x20, 0x4,  0x20, 0x8,  0x10, 0x10, 0x8,  0x10, 0x8,  0x1F, 0xF8, 0x0,  0x0},
{0x0,  0x0,  0x0,  0x0,  0x3,  0xC0, 0x7,  0xE0, 0xF,  0xF0, 0xF,  0xF0, 0x7,  0xE0, 0x7,  0xE0,
0xF,  0xF0, 0x7,  0xE0, 0x7,  0xE0, 0xF,  0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x0,  0x0}
};
const uint8_t iscm[2][32] PROGMEM={
{0x0, 0x0,  0x7,  0xE0, 0xC,  0x30, 0xC,  0x30, 0xC,  0x30, 0xC,  0x30, 0x0,  0x30, 0x0,  0x60,
0x0,  0xC0, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x0,  0x0,  0x1,  0x80, 0x1,  0x80, 0x0,  0x0},
{0x0,  0x0,  0x3F, 0x0,  0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x61, 0x80, 0x1,  0x80, 0x3,  0x0,
0x6,  0x24, 0xC,  0x24, 0xC,  0xFF, 0xC,  0x24, 0x0,  0xFF, 0xC,  0x24, 0xC,  0x24, 0x0,  0x0}
};
const uint8_t islimit[7][32] PROGMEM={
{0x0, 0x0,  0x4,  0x70, 0xC,  0x88, 0x4,  0x88, 0x4,  0x88, 0x4,  0x88, 0x4,  0x88, 0x4,  0x88,
0xE,  0x70, 0x0,  0x0,  0x1D, 0xDC, 0x11, 0x10, 0x1D, 0xD0, 0x5,  0x10, 0x1D, 0xDC, 0x0,  0x0},
{0x0, 0x0,  0xC,  0x70, 0x12, 0x88, 0x2,  0x88, 0xC,  0x88, 0x2,  0x88, 0x2,  0x88, 0x12, 0x88,
0xC,  0x70, 0x0,  0x0,  0x1D, 0xDC, 0x11, 0x10, 0x1D, 0xD0, 0x5,  0x10, 0x1D, 0xDC, 0x0,  0x0},
{0x0, 0x0,  0x1,  0x80, 0x3,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80,
0x3,  0xC0, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0x3,  0xC0, 0x6,  0x60, 0x0,  0x60, 0x1,  0xC0, 0x0,  0x60, 0x6,  0x60, 0x6,  0x60,
0x3,  0xC0, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0xC,  0x78, 0x1C, 0xCC, 0xC,  0xCC, 0xC,  0xCC, 0xC,  0xCC, 0xC,  0xCC, 0xC,  0xCC,
0x1E, 0x78, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0x1C, 0x78, 0x36, 0xCC, 0x6,  0xCC, 0x1C, 0xCC, 0x6,  0xCC, 0x36, 0xCC, 0x36, 0xCC,
0x1C, 0x78, 0x0,  0x0,  0x22, 0xA4, 0x36, 0xA4, 0x2A, 0xB4, 0x22, 0xAC, 0x22, 0xA4, 0x0,  0x0},
{0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3C, 0x3C, 0x7E, 0x7E, 0x63, 0xC6, 0x61, 0x86,
0x63, 0xC6, 0x66, 0x66, 0x3C, 0x3C, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0}
};
const uint8_t isdesc[2][32] PROGMEM={
{0x0,  0x0,  0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0xE3, 0x8E,
0xE3, 0x8E, 0xE3, 0x8E, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E},
{0x0,  0x0,  0x0,  0x4,  0x0,  0xE,  0x0,  0xE,  0x0,  0x1C, 0x0,  0x1C, 0x0,  0x38, 0x0,  0x30,
0x30, 0x70, 0x78, 0xE0, 0x3C, 0xC0, 0x1F, 0xC0, 0xF,  0x80, 0x7,  0x0,  0x2,  0x0,  0x0,  0x0}

};
const uint8_t isback[32] PROGMEM={
0x0,  0x0,  0x0,  0x0,  0x20, 0xF0, 0x31, 0xF8, 0x3B, 0xFC, 0x3F, 0x8E, 0x3F, 0xE,  0x3F, 0xE,
0x3F, 0x8E, 0x3F, 0xCE, 0x0,  0xE,  0x0,  0xE,  0x0,  0x1C, 0x0,  0x38, 0x0,  0x70, 0x0,  0x0
};
const uint8_t issave[32] PROGMEM={
0x1,  0x80, 0x3,  0xC0, 0x7,  0xE0, 0x7,  0xE0, 0x3,  0xC0, 0x3F, 0xFC, 0x23, 0xC4, 0x23, 0xC4,
0x23, 0xC4, 0x23, 0xC4, 0x23, 0xC4, 0x23, 0xC4, 0x20, 0x4,  0x20, 0x4,  0x3F, 0xFC, 0x0,  0x0
};
const uint8_t isload[32] PROGMEM={
0x0,  0x0,  0x3,  0xC0, 0x3,  0xC0, 0x3,  0xC0, 0x3,  0xC0, 0x3F, 0xFC, 0x23, 0xC4, 0x23, 0xC4,
0x23, 0xC4, 0x27, 0xE4, 0x27, 0xE4, 0x23, 0xC4, 0x21, 0x84, 0x20, 0x4,  0x3F, 0xFC, 0x0,  0x0
};
const uint8_t isempty[32] PROGMEM={
0xFF,  0xFF, 0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,
0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0xFF, 0xFF
};
const uint8_t isinit[32] PROGMEM={
0xFF,  0xFF, 0x80, 0x1,  0x80, 0x1,  0xFF, 0xFF, 0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,
0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0x80, 0x1,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
const uint8_t isplay[32] PROGMEM={
0x0,  0x0,  0x3,  0xC0, 0x3,  0xC0, 0x3,  0xC0, 0x1,  0x80, 0x23, 0xF8, 0x17, 0xC8, 0xB,  0xC8,
0x3,  0xC0, 0x3,  0xC0, 0x2,  0x40, 0x4,  0x40, 0x4,  0x38, 0x4,  0x8,  0xC,  0x0,  0x0,  0x0
};
const uint8_t isrotate[2][32] PROGMEM={
{0x0,  0x0,  0x0,  0x0,  0x3F, 0xFC, 0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,
0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x0,  0x0,  0x0,  0x0},
{0x0, 0x0,  0x0,  0x0,  0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC,
0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x20, 0x4,  0x3F, 0xFC, 0x0,  0x0,  0x0,  0x0}
};

const int pos[7][8][8] PROGMEM={
 {{  0,  0,  0,  0,  0,  0,  0,  0}, // 
  {100,100,100,100,100,100,100,100},  //{ 50, 50, 50, 50, 50, 50, 50, 50},
  { 20, 30, 40, 50, 50, 40, 30, 20},  //{ 10, 10, 20, 30, 30, 20, 10, 10},
  {  5,  5, 10, 25, 25, 10,  5,  5},
  {  0,  0,  0, 20, 20,  0,  0,  0},
  {  5, -5,-10,  0,  0,-10, -5,  5},
  {  5, 10, 10,-20,-20, 10, 10,  5},  //{  5, 10, 10,-20,-20, 10, 10,  5},
  {  0,  0,  0,  0,  0,  0,  0,  0}},
  
 {{-50,-40,-30,-30,-30,-30,-40,-50}, //
  {-40,-20,  0,  0,  0,  0,-20,-40},
  {-30,  0, 10, 15, 15, 10,  0,-30},
  {-30,  5, 15, 20, 20, 15,  5,-30},
  {-30,  0, 15, 20, 20, 15,  0,-30},
  {-30,  5, 10, 15, 15, 10,  5,-30},
  {-40,-20,  0,  5,  5,  0,-20,-40},
  {-50,-40,-30,-30,-30,-30,-40,-50}}, 
  
 {{-20,-10,-10,-10,-10,-10,-10,-20}, //
  {-10,  0,  0,  0,  0,  0,  0,-10},
  {-10,  0,  5, 10, 10,  5,  0,-10},
  {-10,  5,  5, 10, 10,  5,  5,-10},
  {-10,  0, 10, 10, 10, 10,  0,-10},
  {-10, 10, 10, 10, 10, 10, 10,-10},
  {-10,  5,  0,  0,  0,  0,  5,-10},
  {-20,-10,-10,-10,-10,-10,-10,-20}},  

 {{  0,  0,  0,  0,  0,  0,  0,  0}, //
  {  5, 10, 10, 10, 10, 10, 10,  5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  { -5,  0,  0,  0,  0,  0,  0, -5},
  {  0,  0,  0,  5,  5,  0,  0,  0}},
  
 {{-20,-10,-10, -5, -5,-10,-10,-20}, //
  {-10,  0,  0,  0,  0,  0,  0,-10},
  {-10,  0,  5,  5,  5,  5,  0,-10},
  { -5,  0,  5,  5,  5,  5,  0, -5},
  {  0,  0,  5,  5,  5,  5,  0, -5},
  {-10,  5,  5,  5,  5,  5,  0,-10},
  {-10,  0,  5,  0,  0,  0,  0,-10},
  {-20,-10,-10, -5, -5,-10,-10,-20}},  

 {{-30,-40,-40,-50,-50,-40,-40,-30}, //
  {-30,-40,-40,-50,-50,-40,-40,-30},
  {-30,-40,-40,-50,-50,-40,-40,-30},
  {-30,-40,-40,-50,-50,-40,-40,-30},
  {-20,-30,-30,-40,-40,-30,-30,-20},
  {-10,-20,-20,-20,-20,-20,-20,-10},
  { 10, 10,-10,-10,-10,-10, 10, 10},  //{ 20, 20,  0,  0,  0,  0, 20, 20},
  { 10, 40, 30,  0,  0,  0, 50, 10}}, //{ 20, 30, 10,  0,  0, 10, 30, 20}},

 {{-50,-40,-30,-20,-20,-30,-40,-50}, // 
  {-30,-20,-10,  0,  0,-10,-20,-30},
  {-30,-10, 20, 30, 30, 20,-10,-30},
  {-30,-10, 30, 40, 40, 30,-10,-30},
  {-30,-10, 30, 40, 40, 30,-10,-30},
  {-30,-10, 20, 30, 30, 20,-10,-30},
  {-30,-30,  0,  0,  0,  0,-30,-30},
  {-50,-30,-30,-30,-30,-30,-30,-50}}  
};

//******
class Button {
public:
int bx,by,bw,bh,bshift;
String bs;
const uint8_t* bp;
 Button(int x,int y,int w,int h,String s,const uint8_t* p, int shift);
 void Show(int shift); 
 void Show(String s); 
 void Hide();
 boolean IsPressed(int xc, int yc);
private:
boolean active;
 void ishow(uint16_t textcolor,uint16_t backcolor);
};
Button::Button(int x,int y,int w,int h,String s,const uint8_t* p=NULL, int shift=0) {
  bx=x; by=y; bw=w; bh=h; bs=s; bp=p; bshift=shift;
};
void Button::Show(int shift=0) {
 bshift=shift; 
 active=true;
 ishow(WHITE,DARK);  
};
void Button::Show(String s) {
 bs=s; 
 active=true;
 ishow(WHITE,DARK);  
};
void Button::Hide() { 
 active=false; 
 ishow(GRAY,DARK);  
};
boolean Button::IsPressed(int xc, int yc) {
  if (active&&abs(bx+bw/2-xc)<bw/2&&abs(by+bh/2-yc)<bh/2) {
    ishow(WHITE,GRAY); 
    touchx=0; touchy=0;        
    return true;
  } 
  return false;
};  
void Button::ishow(uint16_t textcolor,uint16_t backcolor) {  
  tft.fillRoundRect(bx+2,by+2,bw,bh,3,GRAY2);               
  tft.fillRoundRect(bx,by,bw,bh,3,backcolor);               
  tft.setTextColor(textcolor);
  tft.setTextSize(1);    
  tft.setCursor(bx+(bw-bs.length()*6)/2,by+(bh-8)/2);       
  if (bp!=NULL) { 
   tft.drawBitmap(1+bx+(bw-16)/2, by+(bh-16)/2, bp+bshift*32, 16, 16,textcolor);          
  } 
  else  tft.print(bs);    
}
Button BAction(320, 285, 70, 30, "START");
Button BBW(402, 285, 30, 30, "",&iswb[0][0]);
Button BBack(444, 285, 30, 30, "",&isback[0]);
Button BInit(444, 285, 30, 30, "",&isinit[0]);
Button BLimit(320, 245, 26, 30, "",&islimit[0][0]);
Button BEmpty(320, 245, 26, 30, "",&isempty[0]);
Button BRotate(352, 245, 26, 30, "",&isrotate[0][0]);
Button BPlay(352, 245, 26, 30, "",&isplay[0]);
Button BCM(384, 245, 26, 30, "",&iscm[0][0]);
Button BSave(384, 245, 26, 30, "",&issave[0]);
Button BDesc(416, 245, 26, 30, "",&isdesc[0][0]);
Button BSound(448, 245, 26, 30, "",&issound[0][0]);
Button BLoad(448, 245, 26, 30, "",&isload[0]);
//********************************** 
void drawBitmap(int16_t x, int16_t y,
            const uint8_t *bitmap, int16_t w, int16_t h,
            uint16_t color) {
  int16_t i, j, byteWidth = (w + 7) / 8;  
  for(j=0; j<h; j++) {
    for(i=0; i<w; i++ ) {      
        if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i % 8))) {        
        tft.drawPixel(x+i, y+j, color);
      }      
    }
  }
}
//****************************
void deletebuttons() {  
  tft.fillRect(320,245,160,75,BLACK);             
}

//****************************
void clearstatus() {
  tft.fillRect(320,225,160,20,BLACK);             
  tft.drawFastHLine(10,312,300,BLACK);   
  tft.drawFastHLine(10,315,300,BLACK);  
}  
//****************************
void setup() {      
  Serial.begin(57600);  
  Serial.println(F("Start"));     
  pinMode(13, OUTPUT);
  tft.reset();  
  tft.begin(tft.readID()); 
  tft.setRotation(1);  
  definecolors();
  beep(100);      
  for (int i=0;i<MAXSTEPS;i++) {
    steps[i].x1=0; steps[i].y1=0;
    steps[i].x2=0; steps[i].y2=0;
    steps[i].fig1=0; steps[i].fig2=0;
    steps[i].check=0;
    steps[i].type=0;
    steps[i].weight=0;
  }     
  initboard();
}
//****************************
void initboard() {        
  for (int i=0;i<8;i++)
   for (int j=0;j<8;j++) poledisp[j][i]=-100; //          
  tft.fillScreen(BLACK);      
  tft.setTextColor(GRAY);
  tft.setTextSize(1);  
  for (int j=1;j<9;j++) {
   tft.setCursor(2,j*37-20);  
   if (rotate) tft.print(j); else tft.print(9-j);
  }
  for (byte i=1;i<9;i++) { 
   tft.setCursor(i*37-8,300);    
   if (rotate) tft.print(char(96+9-i)); else tft.print(char(96+i));  
  }         
  initscreen();          
}
//****************************
void initscreen() {        
 show_board();   
 show_steps();      
 BAction.Show("START");
 BBW.Show(cur_step%2);   
 if (cur_step>1) BBack.Show(); else BBack.Hide();
 BSave.Hide();
 BLoad.Hide();
 BInit.Hide();
 BBack.Show();  
 BLimit.Show();         
 BPlay.Hide();           
 BRotate.Show(rotate);           
 BEmpty.Hide();
 BLimit.Show(limit);  
 BCM.Show(checkmatesearch); 
 BDesc.Show(choice); 
 BSound.Show(sound);    
}
//****************************
void loop() {        
  gui();  
  if (solving) {        
    int len=70;
    if (!sound) len=2;  
    for (int i=1;i<4;i++) { tone(44,400+300*i,len); delay(70); }
    lastscore=solve_step();               
    float tim=float(millis()-starttime)/1000;
    for (int i=3;i>=1;i--) { tone(44,400+300*i,len); delay(70); }
    if (!checkmatesearch&&lastscore>-9000&&lastscore!=8999) {             
      movestep(cur_step);       
      cur_step++; steps[cur_step].fig1=0; 
    } 
    initscreen();        
    animate_step(cur_step-1,false);
    clearstatus();
    if (lastscore>9000) {       
      tft.setTextSize(1);    
      tft.setTextColor(GREEN); 
      tft.setCursor(322,230);    
      if (lastscore<9999) {
       tft.print("# in "); 
       tft.print((9999-lastscore)/2+1); tft.print(F(" st"));        
      } else tft.print("Checkmate"); 
    } else if (lastscore<-9000) {
      tft.setTextSize(1);    
      tft.setTextColor(RED); 
      tft.setCursor(322,230);    
      tft.print("GIVE UP!");       
      show_steps();
    } else if (lastscore==8999) { //Draw
      tft.setTextSize(1);    
      tft.setTextColor(YELLOW); 
      tft.setCursor(322,230);    
      tft.print("Draw");       
    }         
    tft.setTextSize(1);    
    tft.setTextColor(GRAY); 
    tft.setCursor(322,230);    
    tft.print(tim,0); 
    tft.print("s ");    
    if (abs(lastscore)<5000) {   
     tft.print("=");
     tft.print(lastscore);     
    }
    tft.setCursor(390,230);        
    tft.print(count); 
    tft.print(" pos");   
    Serial.print(F("Positions estimated=")); Serial.println(count);
    Serial.print(F("Time=")); Serial.print(tim,1); Serial.println("s");    
  }
  delay(10);  
  
  
}

//********************************** 
void load_choice() {
  for (int i=0;i<7;i++) 
   if (cur_step%2==1) polechoice[i]=i; else polechoice[i]=-i;
}
//********************************** 
void show_choice() {
uint16_t color,color_cont;    
  for (int i=0;i<7;i++) {
    color=BLACKF;
    if (i%2==0) color=WHITEF;              
    tft.fillRect(416,i*25+35,25,25,color);    
    color=DARK;
    if (i==cur_choice) color=WHITE;   
    tft.drawRect(416,i*25+35,25,25,color);
    color=BLACK; color_cont=GRAY;
    if (polechoice[i]>0) { color=WHITE; color_cont=BLACK; }
    if (polechoice[i]!=0) {
     tft.drawBitmap(420, i*25+39,&fig[abs(polechoice[i])-1][0], 16, 16,color);          
     tft.drawBitmap(420, i*25+39,&fig_cont[abs(polechoice[i])-1][0], 16, 16,color_cont);     
    }
  }  
}
//********************************** 
void animate_step(int nstep, boolean hide) {   
 if (!hide&&nstep-1>0&&steps[nstep-1].fig1!=0) animate_step(nstep-1,true); 
 if (nstep-1<1||steps[nstep].fig1==0) return;
 int j=steps[nstep].x1;
 int dj=steps[nstep].x2-steps[nstep].x1;
 int i=steps[nstep].y1;
 int di=steps[nstep].y2-steps[nstep].y1; 
 di=di/abs(di); dj=dj/abs(dj);  
 if (hide) show_fig(i,j);
 while (j!=steps[nstep].x2||i!=steps[nstep].y2) {  
  show_fig(i,j); 
  if (!hide) 
   if (!rotate) tft.drawRect(i*37+13,j*37+1,36,36,WHITE);    
    else tft.drawRect((7-i)*37+13,(7-j)*37+1,36,36,WHITE);    
  int mj=0;  
  if (j!=steps[nstep].x2) { j+=dj; mj=1; }   
  if (abs(steps[nstep].fig1)==fn&&mj==1) continue;
  if (i!=steps[nstep].y2) i+=di;  
 } 
 show_fig(i,j); 
 if (!hide) 
  if (!rotate) tft.drawRect(i*37+13,j*37+1,36,36,WHITE);    
   else tft.drawRect((7-i)*37+13,(7-j)*37+1,36,36,WHITE);     
}
//********************************** 
boolean load_usb() {
char s='x',i=0,j=0;  boolean load=false; 
  Serial.println(F("Wait for FEN position"));
  for (int i=0;i<8;i++)
      for (int j=0;j<8;j++) {
        pole0[j][i]=pole[j][i];
        pole[j][i]=(char)pgm_read_byte(&polezero[j][i]);                 
      }       
  while (s!=' ') {
    s=Serial.read();       
    if (i>7) { i=0; j++; }
    if (!getpole(j,i)) break;
    switch (s) {      
    case '/': i=0; break;  
    case 'p': pole[j][i]=-fp; i++; break;
    case 'P': pole[j][i]=fp; i++; break;
    case 'n': pole[j][i]=-fn; i++; break;
    case 'N': pole[j][i]=fn; i++; break;
    case 'b': pole[j][i]=-fb; i++; break;
    case 'B': pole[j][i]=fb; i++; break;
    case 'r': pole[j][i]=-fr; i++; break;
    case 'R': pole[j][i]=fr; i++; break;
    case 'q': pole[j][i]=-fq; i++; break;
    case 'Q': pole[j][i]=fq; i++; break;
    case 'k': pole[j][i]=-fk; i++; break;
    case 'K': pole[j][i]=fk; i++; break;
    case '1': i++; break;
    case '2': i+=2; break;
    case '3': i+=3; break;
    case '4': i+=4; break;
    case '5': i+=5; break;
    case '6': i+=6; break;
    case '7': i+=7; break;
    case '8': i=0; j++; break;    
    case ' ': break;    
    }    
    delay(20);
    if (i+j>0&&Serial.available()==0) break;
  }  
  s=0;
  if (Serial.available()>0) s=Serial.read();
  while (Serial.available()>0) Serial.read();
  if (s=='w'||s==0) { cur_step=1; load=true; }
   else if (s=='b') { cur_step=2; load=true; }
     else load=false;  
  if (load) {
     steps[1].fig1=0; steps[2].fig1=0;
     Serial.println(F("Position loaded"));
  } else {  
    for (int i=0;i<8;i++)
      for (int j=0;j<8;j++) 
        pole[j][i]=pole0[j][i];     
  }   
  return load;  
}
//********************************** 
void play() {
 BAction.Show("STOP"); 
 BSave.Hide();
 BBW.Hide();
 BLoad.Hide();
 BInit.Hide();   
 BPlay.Hide();   
 BEmpty.Hide();
 BDesc.Hide(); 
 clearstatus();       
 for (int i=cur_step-1;i>0;i--) {
  if (steps[i].fig1!=0) backstep(i);
 }
 show_board();
 show_steps();
 boolean st=false;
 unsigned long tim=millis();
 int i=1;
 while (i<cur_step) {
  if (steps[i].fig1!=0) movestep(i); 
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);  
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);    
  int x=map(p.y,980,110,0,479);
  int y=map(p.x,145,902,0,319);  
  if (p.z>MINPRESSURE&&p.z<MAXPRESSURE)     
    if (BAction.IsPressed(x,y)) { st=true; BAction.Show(); } 
  if (millis()-tim>2000||st) {
    tim=millis();
    i++;
    show_board();
    beep(20);              
  }  
 }       
 choice=0; 
 beep(200);                
 kingpositions();        
 clearstatus();
 initscreen();                               
}
//********************************** 
void gui() {   
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);  
  // if sharing pins, you'll need to fix the directions of the touchscreen pins  
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);    
  int x=map(p.y,980,110,0,479);
  int y=map(p.x,145,902,0,319);
  
  if (((abs(x-touchx)>5||abs(y-touchy)>5)||drag)&&p.z>MINPRESSURE&&p.z<MAXPRESSURE) {    
  //  tft.drawPixel(x,y,CYAN);    
  //  Serial.println(x);
  //  Serial.println(y);  
    touchx=x;
    touchy=y;             
    if (solving) {
      if (BAction.IsPressed(x,y)) { //        
        beep(100); 
        solving=false;  
        BAction.Show("stopping");        
        BAction.Hide();        
        return;    
      }   
    } else { //not solve
      if (BAction.IsPressed(x,y)) { // 
       if (!choice) {
        delay(100);        
        solving=true;   
        BAction.Show();         
        animate_step(cur_step-1,true);
        return;
       } else { //   USB
        delay(100);
        BAction.Hide(); 
        BSave.Hide();
        BBW.Hide();
        BLoad.Hide();
        BInit.Hide();   
        BPlay.Hide();   
        BEmpty.Hide();
        BDesc.Hide();        
        show_steps();
        choice=0;         
        if (!load_usb()) return;
        beep(200);                
        kingpositions();        
        clearstatus();
        initscreen();                              
       }
      } else if (BBW.IsPressed(x,y)) {   //-    
       beep(100);         
       if (cur_step==1) cur_step=2;
        else if (cur_step==2) cur_step=1;
         else if (cur_step%2==0) cur_step--; else cur_step++;       
       BBW.Show(cur_step%2);        
       if (choice) { load_choice(); show_choice(); }
       return;
      } else if (cur_step>1&&BBack.IsPressed(x,y)) {  //      
       beep(100);                
       cur_step--;       
       animate_step(cur_step,true);
       lastscore=0;              
       backstep(cur_step);               
       steps[cur_step].fig1=0;
       show_board();       
       show_steps();       
       if (cur_step>1) BBack.Show(); else BBack.Hide();      
       BBW.Show(cur_step%2);        
       clearstatus();       
       return;        
      } else if (BLimit.IsPressed(x,y)) {    //   
       beep(100);  
       limit++; if (limit>6) limit=0;       
       BLimit.Show(limit);        
       return; 
      } else if (BCM.IsPressed(x,y)) {   //                   
       beep(100); 
       checkmatesearch=!checkmatesearch; 
       BCM.Show(checkmatesearch);        
       if (!checkmatesearch) steps[cur_step].fig1=0;
       lastscore=0;
       show_steps();
       return; 
      } else if (BRotate.IsPressed(x,y)) {   //                   
       beep(100); 
       rotate=!rotate; 
       BRotate.Show(rotate);              
       initboard();       
       return;  
      } else if (BSound.IsPressed(x,y)) {   //                  
       if (sound==1) { beep(100); sound=0; } else { sound=1; beep(200); }       
       BSound.Show(sound);        
       return;
      } else if (BDesc.IsPressed(x,y)) {  //
       beep(100); 
       if (!choice) {
        choice=1;
        cur_choice=1;
        load_choice();
        show_choice();        
        BAction.Show("USB(FEN)");         
        BBack.Hide();  
        BInit.Show();  
        BSave.Show();  
        BLimit.Hide(); 
        BEmpty.Show();  
        BRotate.Hide();    
        BPlay.Show();    
        BCM.Hide();          
        BSound.Hide(); 
        BSave.Show();  
        BLoad.Show();    
       } else {
        choice=0;  
        lastscore=0;
        clearstatus();
        kingpositions();        
        initscreen();        
       }       
       BDesc.Show(choice);                                    
       return;
      } else if (BInit.IsPressed(x,y)) {  //        
        beep(200);        
        cur_step=1;
        steps[1].fig1=0;
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) pole[j][i]=(char)pgm_read_byte(&polestart[j][i]);         
        choice=0;         
        kingpositions();        
        clearstatus();
        initscreen();                     
      } else if (BEmpty.IsPressed(x,y)) {  //        
        beep(200);        
        cur_step=1;        
        clearstatus();        
        steps[1].fig1=0; steps[2].fig1=0;
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) pole[j][i]=(char)pgm_read_byte(&polezero[j][i]);                 
        BEmpty.Show();   
        show_board();          
      } else if (BSave.IsPressed(x,y)) { 
        beep(100); 
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) EEPROM.write(i*8+j,pole[j][i]);         
        EEPROM.put(64,cur_step);
        EEPROM.put(66,limit);
        for (int i=1;i<cur_step;i++) {
          EEPROM.put(66+i*10,steps[i]);
        }
        BSave.Show(); 
      } else if (BLoad.IsPressed(x,y)) { 
        beep(200); 
        for (int i=0;i<8;i++)
         for (int j=0;j<8;j++) pole[j][i]=EEPROM.read(i*8+j);
        EEPROM.get(64,cur_step);                 
        if (cur_step<0||cur_step>400) cur_step=1;        
        EEPROM.get(66,limit);                 
        if (limit<0||limit>6) limit=2;        
        for (int i=1;i<cur_step;i++) {
          EEPROM.get(66+i*10,steps[i]);
        }        
        steps[0].fig1=0;         
        steps[cur_step].fig1=0;         
        choice=0;                 
        kingpositions();
        clearstatus();
        initscreen();                                   
      } else if (BPlay.IsPressed(x,y)) {    //   
       beep(100);  
       BPlay.Show();        
       play();       
       return; 
      }
      if (!choice&&ntouch==0) {
       touchx0=touchx;
       touchy0=touchy;
       char x1=touchy0/37; 
       char y1=(touchx0-10)/37;       
       if (rotate) { x1=7-x1; y1=7-y1; }
       if (getpole(y1,x1)&&(cur_step%2==1&&pole[x1][y1]>0||cur_step%2==0&&pole[x1][y1]<0)) {        
        char p=pole[x1][y1];        
        drag=true;        
        pole[x1][y1]=0;
        show_fig(y1,x1);
        pole[x1][y1]=p;                
       } else drag=false; 
      }       
      ntouch++;
      if (drag&&ntouch>1) {
          uint16_t buf[256];          
          int x1=touchy0/37; 
          int y1=(touchx0-10)/37;       
          if (rotate) { x1=7-x1; y1=7-y1; }       
          if (abs(pole[x1][y1])>0&&(cur_step%2==1&&pole[x1][y1]>0||cur_step%2==0&&pole[x1][y1]<0)) {
          for (int i=0;i<16;i++)
            for (int j=0;j<16;j++) buf[i*16+j]=tft.readPixel(touchx-8+i,touchy-8+j);
          buf[0]=tft.readPixel(touchx-8,touchy-8);  
          uint16_t color,color_cont;    
          color=BLACK; color_cont=GRAY;
          if (pole[x1][y1]>0) { color=WHITE; color_cont=BLACK; }             
          tft.drawBitmap(touchx-8, touchy-8,&fig[abs(pole[x1][y1])-1][0], 16, 16,color);          
          tft.drawBitmap(touchx-8, touchy-8,&fig_cont[abs(pole[x1][y1])-1][0], 16, 16,color_cont);       
          delay(30);
          for (int i=0;i<16;i++)
            for (int j=0;j<16;j++) tft.drawPixel(touchx-8+i,touchy-8+j,buf[i*16+j]);            
          }  
      } else if (choice) {
        int x1=touchy/37; 
        int y1=(touchx-10)/37;             
        if (rotate) { x1=7-x1; y1=7-y1; } 
        if (touchy+touchx!=0&&choice&&getpole(y1,x1)) {        
         pole[x1][y1]=polechoice[cur_choice];
         show_board(); 
        }       
        if (touchx>=416&&touchx<=441&&touchy>=35&&touchy<=210) {
         cur_choice=(touchy-35)/25;
         show_choice();                       
        }
      }
      lasttouch=millis();
    } //not solve      
    if (!drag) { beep(10); ntouch=0; animate_step(cur_step-1,true); }     
  } else { //touching
    if (!solving&&!choice&&drag!=0&&ntouch>0&&p.z<MINPRESSURE&&millis()-lasttouch>300) { //drag 
     char x1=touchy0/37; 
     char y1=(touchx0-10)/37;     
     char x2=touchy/37; 
     char y2=(touchx-10)/37; 
     if (rotate) { x1=7-x1; y1=7-y1; x2=7-x2; y2=7-y2; }    
     if (getpole(y1,x1)) show_fig(y1,x1);
     if (getpole(y1,x1)&&getpole(y2,x2)) {      
       start_var=cur_step+1;
       only_action=false;   
       load_variants(cur_step);     
       for (int i=cur_step+1;i<cur_step+cur_var+1;i++)  
        if (steps[i].x1==x1&&steps[i].y1==y1&&steps[i].x2==x2&&steps[i].y2==y2) {
         steps[cur_step]=steps[i];          
         movestep(cur_step); cur_step++; steps[cur_step].fig1=0;
         int len=100;
         if (!sound) len=2;  
         for (int i=2;i>=1;i--) { tone(44,400+300*i,len); delay(100); }
         initscreen();
         animate_step(cur_step-1,false);
         break;                                 
        }            
     } else { 
      beep(10);       
     }
     ntouch=0;       
     drag=false;
    } 
  }
  if (millis()-quitime>1000) {
    if (isstatus) show_status(); 
    quitime=millis();
  }
  
  
}
//********************************** 
void show_status() {      
   int tim=(millis()-starttime)/1000; 
   int cur=300000*tim/(limittime-starttime);
   if (cur>300) { cur=300; solving=false; }   
   tft.drawFastHLine(10,312,cur,GRAY);                  
   tft.drawFastHLine(10,315,progress*2,GRAY);  
   int m=tim/60;
   int s=tim%60;
   tft.setTextWrap(1);
   tft.setTextColor(GRAY);
   tft.setTextSize(1);
   tft.fillRect(320,225,50,20,BLACK);             
   tft.setCursor(322,230);     
   if (m>0) { tft.print(m); tft.print(":"); }
   if (s>0) {
    if (s<10&&m>0) tft.print("0"); 
    tft.print(s);
   } else if (m>0) tft.print("00"); else tft.print("0");
   tft.setCursor(350,230);   
   tft.print(cur_level);
   
   tft.setCursor(370,230);   
   if (cur_step%2==1) tft.setTextColor(WHITE); else tft.setTextColor(GRAY);   
   if (lastbest.fig1!=steps[0].fig1||lastbest.x1!=steps[0].x1||lastbest.y1!=steps[0].y1||
       lastbest.x2!=steps[0].x2||lastbest.y2!=steps[0].y2) {
     beep(10); 
     lastbest=steps[0];    
     tft.fillRect(370,230,50,10,BLACK);             
     tft.setCursor(370,230);     
     tft.print(str_step(0)); 
     blinkstep=0;
   }  
   if (steps[0].fig1!=0&&blinkstep==0&&tim>5) {
    char poleb[8][8];     
    for (int i=0;i<8;i++)
     for (int j=0;j<8;j++) { poleb[j][i]=pole[j][i]; pole[j][i]=pole0[j][i]; }         
    movestep(0);    
    show_board(); 
    delay(100);  
    backstep(0);   
    show_board();      
    for (int i=0;i<8;i++)
     for (int j=0;j<8;j++) pole[j][i]=poleb[j][i];           
    kingpositions();  
   }
   blinkstep++;      
   if (blinkstep>2) blinkstep=0;              
}
//****************************
void beep(int leng) {
  analogWrite(PinBuzz, 20);
  delay(2); 
  if (!sound) analogWrite(PinBuzz, 0);  
  delay(leng); 
  analogWrite(PinBuzz, 0);   
}  
//****************************
void definecolors() {
 BLACK  =0x0000;
 BLUE   =0x07FF;  //0x001F;
 RED    =0xF800;
 GREEN  =0x07E0;
 CYAN   =0x07FF;
 MAGENTA=0xF81F;
 YELLOW =0xFFE0;
 WHITE  =0xFFFF;
 GRAY   =0x7BEF;
 DARK   =getColor(32,32,32); 
 GRAY2   =getColor(16,16,16); 
 BLACKF  =getColor(94,58,0); 
 WHITEF  =getColor(180,114,0); 
}
//****************************
uint16_t getColor(uint8_t red, uint8_t green, uint8_t blue)
{
  red   >>= 3;
  green >>= 2;
  blue  >>= 3;
  return (red << 11) | (green << 5) | blue;
}
//****************************
void show_fig(int i,int j) {
uint16_t color,color_cont;  
   color=BLACKF;   
   if ((i+j+2)%2==0) color=WHITEF;           
   int jj=j, ii=i;
   if (rotate) { jj=7-j; ii=7-i; }   
   tft.fillRect(ii*37+12,jj*37,38,38,color);    
   tft.drawRect(ii*37+12,jj*37,38,38,WHITE);  
   color=BLACK; color_cont=GRAY;
   if (pole[j][i]>0) { color=WHITE; color_cont=BLACK; }
   if (pole[j][i]!=0) {
    drawBitmap(ii*37+19, jj*37+7,&fig24[abs(pole[j][i])-1][0], 24, 24,color);          
    drawBitmap(ii*37+19, jj*37+7,&fig24_cont[abs(pole[j][i])-1][0], 24, 24,color_cont);             
    //drawBitmap(ii*37+24, jj*37+12,&fig[abs(pole[j][i])-1][0], 16, 16,color);               
    //drawBitmap(ii*37+24, jj*37+12,&fig_cont[abs(pole[j][i])-1][0], 16, 16,color_cont);     
   }
}
//****************************
void show_board() { 
 for (int i=0;i<8;i++)
  for (int j=0;j<8;j++) {
    if (poledisp[j][i]!=pole[j][i]) show_fig(i,j);      
    poledisp[j][i]=pole[j][i];
  }  
}
//****************************
String str_step(int i) {
  String s="";
   if (steps[i].fig1==0) return s;
   if (steps[i].type==2) s="0-0";
    else if (steps[i].type==3) s="0-0-0";
   else  {
    if (abs(steps[i].fig1)>1) s=fig_symb[abs(steps[i].fig1)];   
    if (abs(steps[i].fig1<5)) {
     s=s+char(97+steps[i].y1);  
     s=s+String(8-steps[i].x1);    
     if (steps[i].fig2==0) s=s+"-";    
    }
    if (steps[i].fig2!=0) {
      s=s+"x";    
      if (abs(steps[i].fig2)>1) s=s+fig_symb[abs(steps[i].fig2)];
    }    
    s=s+char(97+steps[i].y2);  
    s=s+String(8-steps[i].x2);
   } 
   if (steps[i].type>3) s=s+fig_symb[steps[i].type-2