frenchy22
Published © GPL3+

Try to win against this Othello game

Several game levels will allow you to discover the Othello game or to become a champion

IntermediateFull instructions provided2 hours99
Try to win against this Othello game

Things used in this project

Hardware components

Arduino Nano Every
Arduino Nano Every
×1
Voltage translator
×1
1.3 inch 128x64 OLED display I2C white
This OLED display is driven by a SH1106 module. If your own display is driven by a SSD1306 module, please edit line#19 of the program
×1
Omron Electronic Components LLC 6 mm push-button
×4
Omron Electronic Components LLC 12 mm push-button
×2
Solderless Breadboard Full Size
Solderless Breadboard Full Size
×1

Story

Read more

Schematics

Athalie schematics

Code

Athalie 4.0

C/C++
Adapt line #19 to your own OLED display
/***** ATHALIE *****/

String version="4.0";

/* If you want a reduced version of this
   program with the following characteristics:
    - user interface limited to the serial
      monitor of the IDE, no OLED display,
      no push buttons,
    - all the functions of the programm
      available except the timers,
    - no library needed for compilation,
    - fast compilation and uploading,
   you can comment or suppress the next line */
#define OLEDDisplay

#ifdef OLEDDisplay
  #include <U8g2lib.h>
  U8G2_SH1106_128X64_NONAME_2_HW_I2C
  u8g2(U8G2_R0);
  #include <ISR_Timer_Generic.h>
  ISR_Timer myTimer;
#endif

#define COMPUTER 0
#define PLAYER 1
#define EMPTY 0
#define BLACK 1
#define WHITE 2
#define FAR 4
#define NOTFAR 0xFB
#define EDGE 8

const int enterPin=5;
const int menuPin=4;
const int downPin=3;
const int upPin=2;
const int leftPin=A6;
const int rightPin=A7;
int displayWidth, displayHeight;

typedef byte tBoard[10][10];

tBoard currentBoard;
byte who, whoPlays=PLAYER;
bool gameOver=false;
bool exitGame=false;
byte level=1;
bool showCursor=false;
byte xCursor, yCursor;
byte xPlay, yPlay;
byte nbBlack, nbWhite;

bool openingBookActive=true;

byte memoGame[61][3];
byte memoGameNum=0;

enum {enter, menu, down, up, left, right};
bool buttonPressed[6]=
  {false, false, false, false, false, false};
bool twoPlayersGame=false;

volatile unsigned int blackTime=0, whiteTime=0;
bool blackTimeActive,
     whiteTimeActive;
volatile bool oneSecond=false;
char message1[14];
char message2[14];
const int newGameOption=0, twoPlayersOption=1,
          replayOption=2, resumeOption=3;
int option;

/*
   Objects of the class stopWatch are used to
   perform time dependant actions without
   blocking the program by delay functions.
*/
class stopWatch
{
  unsigned long previousTime, currentTime;
  public :
  unsigned long elapsed;
  void init();
  void now();
  stopWatch();  
};

void stopWatch::init()
{
  currentTime=millis();
  previousTime=currentTime;
}

void stopWatch::now()
{
   currentTime=millis();
  if (currentTime<previousTime)
    elapsed=0xFFFFFFFFul-previousTime+
              currentTime;
  else 
    elapsed=currentTime-previousTime;
}

stopWatch::stopWatch()
{
  currentTime=millis();
  previousTime=currentTime;
}

void displayBoard(tBoard board) // On the OLED
                                // display
{
#ifdef OLEDDisplay

  int squareSize=7;
  int xBoard=displayWidth-8*squareSize-1;
  int yBoard=displayHeight-8*squareSize-1;
  for(int i=0; i<9; i++)
  {
    u8g2.drawLine(xBoard+squareSize*i,
                  yBoard,
                  xBoard+squareSize*i, 
                  yBoard+squareSize*8);
    u8g2.drawLine(xBoard,
                  yBoard+squareSize*i,
                  xBoard+squareSize*8, 
                  yBoard+squareSize*i);
  }

  u8g2.setFont(u8g2_font_4x6_mf);
  for(int i=0; i<8; i++)
  {
    u8g2.setCursor(xBoard+2+squareSize*i,
                   yBoard-2);
    u8g2.print(char('A'+i));
    u8g2.setCursor(xBoard-5,
                   yBoard+squareSize-1+
                   squareSize*i);
    u8g2.print(char('1'+i));
  }

  for(byte i=1; i<=8; i++)
    for(byte j=1; j<=8; j++)
    {
      if(board[i][j]==BLACK)
        u8g2.drawRFrame(
          xBoard+2+squareSize*(i-1),
          yBoard+2+squareSize*(j-1),
          squareSize-3,
          squareSize-3, 1);
            
      else if(board[i][j]==WHITE)
        u8g2.drawRBox(
          xBoard+2+squareSize*(i-1),
          yBoard+2+squareSize*(j-1),
          squareSize-3,
          squareSize-3, 1);

      else if(showCursor && canPlay(i, j,
              board, who))
        u8g2.drawPixel(xBoard+3+
                       squareSize*(i-1),
                       yBoard+3+
                       squareSize*(j-1));
    }
  if(showCursor)
  {
    u8g2.drawPixel(
      xBoard+1+squareSize*(xCursor-1),
      yBoard+1+squareSize*(yCursor-1));
    u8g2.drawPixel(
      xBoard-1+squareSize*xCursor,
      yBoard+1+squareSize*(yCursor-1));
    u8g2.drawPixel(
      xBoard+1+squareSize*(xCursor-1),
      yBoard-1+squareSize*yCursor);
    u8g2.drawPixel(
      xBoard-1+squareSize*xCursor,
      yBoard-1+squareSize*yCursor);
  
    u8g2.setDrawColor(0);
    u8g2.drawLine(
      xBoard+3+squareSize*(xCursor-1),
      yBoard+squareSize*(yCursor-1),
      xBoard-3+squareSize*xCursor,
      yBoard+squareSize*(yCursor-1));
    u8g2.drawLine(
      xBoard+squareSize*(xCursor-1),
      yBoard+3+squareSize*(yCursor-1),
      xBoard+squareSize*(xCursor-1),
      yBoard-3+squareSize*yCursor);
    u8g2.drawLine(
      xBoard-3+squareSize*xCursor,
      yBoard+squareSize*yCursor,
      xBoard+3+squareSize*(xCursor-1),
      yBoard+squareSize*yCursor);
    u8g2.drawLine(
      xBoard+squareSize*xCursor,
      yBoard-3+squareSize*yCursor,
      xBoard+squareSize*xCursor,
      yBoard+3+squareSize*(yCursor-1));
    u8g2.setDrawColor(1);
  }

#endif
}

void sendBoard(tBoard board) // To the serial
                             // monitor
{
  String line=
    "   +---+---+---+---+---+---+---+---+";
  Serial.println();
  Serial.println
    ("     A   B   C   D   E   F   G   H");
  for(byte i=1; i<=8; i++)
  {
    Serial.println(line);
    Serial.print(" ");
    Serial.print(i);
    Serial.print(" |");
    for(byte j=1; j<=8; j++)
    {
      if(board[j][i]==BLACK)
        Serial.print(" @ |");
      else if(board[j][i]==WHITE)
        Serial.print(" 0 |");
      else if(showCursor && canPlay(j, i,
              board, who))
        Serial.print(" . |");
      else Serial.print("   |");
    }
    Serial.println();
  }
  Serial.println(line);
}

void displayInfos() // On the OLED display
{
#ifdef OLEDDisplay

  int xDisplayInfos=0;
  char str[16];
  
  u8g2.setFont(u8g2_font_5x8_mf);
  countDisks(currentBoard);
  u8g2.setCursor(xDisplayInfos, 8);
  u8g2.print(message1);
  u8g2.setCursor(xDisplayInfos, 16);
  u8g2.print(message2);
  u8g2.drawCircle(xDisplayInfos+17, 26, 3);
  u8g2.setCursor(xDisplayInfos+28, 30);
  u8g2.print(nbBlack);
  u8g2.setCursor(xDisplayInfos+5, 39);
  sprintf(str, "%02d:%02d:%02d",
           blackTime/3600, (blackTime%3600)/60,
           blackTime%60);
  u8g2.print(str);
  u8g2.drawDisc(xDisplayInfos+17, 48, 3);
  u8g2.setCursor(xDisplayInfos+28, 52);
  u8g2.print(nbWhite);
  u8g2.setCursor(xDisplayInfos+5, 61);
  sprintf(str, "%02d:%02d:%02d",
           whiteTime/3600, (whiteTime%3600)/60,
           whiteTime%60);
  u8g2.print(str);
  if(!gameOver)
    if(who==BLACK)
      u8g2.drawFrame(xDisplayInfos,
                     20, 50, 22);
    else
      u8g2.drawFrame(xDisplayInfos,
                     42, 50, 22);

#endif
}

void sendInfos() // To the serial monitor
{
  countDisks(currentBoard);
  Serial.print("@ : ");
  Serial.print(nbBlack);
  Serial.print("  0 : ");
  Serial.println(nbWhite);
  Serial.println(message1);
  if(!gameOver)
    if(who==BLACK)
      Serial.println("@ plays");
    else
      Serial.println("0 plays");
  Serial.println(message2);
}

void displayGame() // On the OLED dipslay
{
#ifdef OLEDDisplay

  u8g2.firstPage();
  do
  {
    displayBoard(currentBoard);
    displayInfos();
  }
  while(u8g2.nextPage());

#endif
}

void sendGame() // To the serial monitor
{
  sendBoard(currentBoard);
  sendInfos();
}


/* The two next functions are the move
   generator. Their programming is neither
   elegant nor easy to understand, but it
   aims for a maximum speed because it is
   called very often when looking for the
   best move.
*/

bool canMove;

void playOneDirection(byte * square, int dir,
                      byte who)
{
  byte other=who^(BLACK | WHITE);
  square+=dir;
  if((*square)!=other) return;
  do
    square+=dir;
  while((*square)==other);
  if((*square)==who)
  {
    canMove=true;
    while((*square)!=EMPTY)
    {
      *square=who;
      square-=dir;      
    }
  }  
}

bool play(byte x, byte y, tBoard board,
          byte who)
{
  byte other=who^(BLACK|WHITE);
  byte *square;
  byte k;

  canMove=false;
  if(board[x][y]==EMPTY)
  {
    square=(&board[0][0])+10+y+10*(x-1);

    playOneDirection(square, 1, who);
    playOneDirection(square, 9, who);
    playOneDirection(square, 10, who);
    playOneDirection(square, 11, who);
    playOneDirection(square,-9, who);
    playOneDirection(square, -10, who);
    playOneDirection(square, -11, who);
    playOneDirection(square, -1, who);

    if(canMove)
    {
      *square=who;
      *(square+1)&=NOTFAR;
      *(square+9)&=NOTFAR;
      *(square+10)&=NOTFAR;
      *(square+11)&=NOTFAR;
      *(square-9)&=NOTFAR;
      *(square-10)&=NOTFAR;
      *(square-11)&=NOTFAR;
      *(square-1)&=NOTFAR;
    }
  }
  return(canMove);
}

/* Identify the squares where it is
   impossible to play because they have
   no neighbour.
*/

void calculateFar(tBoard board)
{
  for(byte i=1; i<=8; i++)
    for(byte j=1; j<=8; j++)
      if(board[i][j]==EMPTY ||
         board[i][j]==FAR)
      {
        board[i][j]=FAR;
        for(int k=-1; k<=1; k++)
          for(int l=-1; l<=1; l++)
            if(board[i+k][j+l]==BLACK ||
               board[i+k][j+l]==WHITE)
            {
              board[i][j]=EMPTY;
              break;
            }
      }
}

bool canPlay(byte x, byte y, tBoard board,
             byte who)
{
  byte other=who^(BLACK|WHITE);
  int k;

  if(board[x][y]!=EMPTY) return(false);
  else
  {
    // East
    if(board[x+1][y]==other)
    {
      for(k=2; k<8-x && 
          board[x+k][y]==other; k++);
      if(board[x+k][y]==who)
        return(true);
    }

    // South-East
    if(board[x+1][y+1]==other)
    {
      for(k=2; k<8-x && k<8-y &&
          board[x+k][y+k]==other; k++);
      if(board[x+k][y+k]==who)
        return(true);
    }

    // South
    if(board[x][y+1]==other)
    {
      for(k=2; k<8-y && 
          board[x][y+k]==other; k++);
      if(board[x][y+k]==who)
        return(true);
    }

    // South-West
    if(board[x-1][y+1]==other)
    {
      for(k=2; k<x && k<8-y &&
          board[x-k][y+k]==other; k++);
      if(board[x-k][y+k]==who)
        return(true);
    }

    // West
    if(board[x-1][y]==other)
    {
      for(k=2; k<x && 
          board[x-k][y]==other; k++);
      if(board[x-k][y]==who)
        return(true);
    }

    // North-West
    if(board[x-1][y-1]==other)
    {
      for(k=2; k<x && k<y &&
          board[x-k][y-k]==other; k++);
      if(board[x-k][y-k]==who)
        return(true);
    }

    // North
    if(board[x][y-1]==other)
    {
      for(k=2; k<y && 
          board[x][y-k]==other; k++);
      if(board[x][y-k]==who)
        return(true);
    }

    // North-East
    if(board[x+1][y-1]==other)
    {
      for(k=2; k<8-x && k<y &&
        board[x+k][y-k]==other; k++);
      if(board[x+k][y-k]==who)
        return(true);
    }
    return(false);
  }
}

int nbMoves(byte who, tBoard board)
{
  byte moves=0;
  for(int i=1; i<=8; i++)
    for(int j=1; j<=8; j++)
      if(canPlay(i, j, board, who)) moves++;
  return moves;
}

void countDisks(tBoard board)
{
  nbBlack=0;
  nbWhite=0;
  for(byte i=1; i<=8; i++)
    for(byte j=1; j<=8; j++)
    {
      if(board[i][j]==BLACK)
        nbBlack++;
      else if (board[i][j]==WHITE)
        nbWhite++;
    }
}

void initBoard()
{
  for(byte i=0; i<10; i++)
  {
    currentBoard[0][i]=EDGE;
    currentBoard[9][i]=EDGE;
    currentBoard[i][0]=EDGE;
    currentBoard[i][9]=EDGE;
  }
  for(byte i=1; i<=8; i++)
    for(byte j=1; j<=8; j++)
      currentBoard[i][j]=EMPTY;
  currentBoard[4][4]=WHITE;
  currentBoard[5][5]=WHITE;
  currentBoard[4][5]=BLACK;
  currentBoard[5][4]=BLACK;

  calculateFar(currentBoard);
}

void buttonsManagement(void)
{  
  const int debounce=20;
  const int repeatPeriod=300;
  const int beginRepeatTime=1000;
  static stopWatch buttonStopWatch[6];
  static stopWatch repeatStopWatch[6];
  int buttonState[6];
  static int nbButton[6]={0, 0, 0, 0,0 ,0};

  buttonState[enter]=
    digitalRead(enterPin);
  buttonState[menu]=
    digitalRead(menuPin);
  buttonState[down]=
    digitalRead(downPin);
  buttonState[up]=
    digitalRead(upPin);
  buttonState[left]=
    digitalRead(leftPin);
  buttonState[right]=
    digitalRead(rightPin);
  for(int i=0; i<6; i++)
  {
    if(buttonState[i]==HIGH)
    {
      buttonStopWatch[i].init();
      nbButton[i]=0;
      buttonPressed[i]=false;
    }
    else
    {
      buttonStopWatch[i].now();
      switch(nbButton[i])
      {
        case 0 :
          if(buttonStopWatch[i].elapsed>
               debounce)
          {
            buttonPressed[i]=true;
            nbButton[i]=1;
          }
          break;
        case 1 :
          if(buttonStopWatch[i].elapsed>
               beginRepeatTime)
          {
            buttonPressed[i]=true;
            nbButton[i]=2;
            repeatStopWatch[i].init();
          }
          break;
        default :
          repeatStopWatch[i].now();
          if(repeatStopWatch[i].elapsed>
               repeatPeriod)
          {
            buttonPressed[i]=true;
            repeatStopWatch[i].init();
          }
          break;
      }    
    }
  }
}

void playerManagement()
{
  bool playerAction=false;
  byte xReceived=0, yReceived=0;
  byte receivedByte;

  while(Serial.available()) Serial.read();

  while(!playerAction && !exitGame)
  {
    buttonsManagement();
    if(buttonPressed[down])
    {
      if(yCursor<8) yCursor++;
      buttonPressed[down]=false;
      displayGame();
    }
  
    if(buttonPressed[up])
    {
      if(yCursor>1) yCursor--;
      buttonPressed[up]=false;
      displayGame();
    }
  
    if(buttonPressed[left])
    {
      if(xCursor>1) xCursor--;
      buttonPressed[left]=false;
      displayGame();
    }
  
    if(buttonPressed[right])
    {
      if(xCursor<8) xCursor++;
      buttonPressed[right]=false;
      displayGame();
    }

    if(buttonPressed[enter]&&
       canPlay(xCursor, yCursor,
               currentBoard, who))
    {
      xPlay=xCursor;
      yPlay=yCursor;
      buttonPressed[enter]=false;
      playerAction=true;
    }

    if(buttonPressed[menu])
    {
      buttonPressed[menu]=false;
      exitGame=true;
    }

    if(Serial.available())
    {
      receivedByte=Serial.read();
      if(receivedByte>='a' &&
         receivedByte<='h')
        xReceived=receivedByte-'a'+1;
      if(receivedByte>='A' &&
         receivedByte<='H')
        xReceived=receivedByte-'A'+1;
      if(receivedByte>='1' &&
         receivedByte<='8')
        yReceived=receivedByte-'1'+1;
      if(receivedByte==10 ||
         receivedByte==13)
        if(canPlay(xReceived, yReceived,
           currentBoard, who))
          {
            xPlay=xReceived;
            yPlay=yReceived;
            playerAction=true;
          }
      if(receivedByte=='m' ||
         receivedByte=='M')
        exitGame=true;
    }

#ifdef OLEDDisplay
  if(oneSecond)
    {
      displayGame();
      oneSecond=false;
    }
    myTimer.run();
#endif

  }
}

char * opBook[150];
int numLines;

void installOpeningBook(void)
{
  numLines=0;
  opBook[numLines++]="C4C3D3C5D6F4F5D2G4D7C7E7"
                     "C6B5B4E3A6E6F3B3E2";
  opBook[numLines++]="C4E3F6E6F5C5C3B4D6C6B3D7"
                     "A4F4B5B6C7";
  opBook[numLines++]="C4E3F6E6F5C5C3C6D3D2C2F4"
                     "G3B4";
  opBook[numLines++]="C4E3F6E6F5C5F4G5G6D3F3G4"
                     "D6C7H3H4E2";
  opBook[numLines++]="C4E3F6E6F5C5C3C6D6G5G4D3"
                     "D2B4F4";
  opBook[numLines++]="C4C3D3C5B4D2C2A4E6F3E2F5"
                     "B5A5D6";
  opBook[numLines++]="C4E3F4C5D6F3E6C3D3E2D2F2"
                     "F5C6E1F1G1D1C1C2B1D7G4F7"
                     "B4";
  opBook[numLines++]="C4C3D3C5B3E3D6C6B5B4E6D7"
                     "F4";
  opBook[numLines++]="C4C3D3C5F6E2C6E3B4B5D6B3"
                     "D2B6C2C1D1F5";
  opBook[numLines++]="C4E3F5E6F4G5F6E7G3F3G4D3"
                     "H6H4";
  opBook[numLines++]="C4E3F4C5E6F5D6D3C3B4F6D2";
  opBook[numLines++]="C4E3F6E6F5C5D3C3D6F4F3G3"
                     "F2G4E2D2C2";
  opBook[numLines++]="C4C5D6C3E6D7C6C7D3E7B4A3"
                     "B5";
  opBook[numLines++]="C4E3F3";
  opBook[numLines++]="C4E3F5E6F4C5D6C6F7F3D3E7"
                     "B5G3G4F6G5F8C7H6D7H4";
  opBook[numLines++]="C4C3D3C5D6F4F5D2B5B6";
  opBook[numLines++]="C4C3D3C5D6F4F5E6C6D7";
  opBook[numLines++]="C4C3D3C5D6F4F3E6C6D2";
  opBook[numLines++]="C4C3D3C5D6E3F5C6";
  opBook[numLines++]="C4C3D3C5D6E3F3F4";
  opBook[numLines++]="C4C3D3C5D6E3D2E2";
  opBook[numLines++]="C4C3D3C5D6E6C6";
  opBook[numLines++]="C4C3D3C5D6E2B3";
  opBook[numLines++]="C4C3D3C5D6C7F6";
  opBook[numLines++]="C4C3D3C5F6E2C6E6B5D6";
  opBook[numLines++]="C4C3D3E3F4D6E6B4E2F2";
  opBook[numLines++]="C4C3D3E3F4D6E6F5F3G4";
  opBook[numLines++]="C4C3D3E3F4D6C6F5F3B4";
  opBook[numLines++]="C4C3D3E3F4C5E6F3";
  opBook[numLines++]="C4C3D3E3F4C5C6D6";
  opBook[numLines++]="C4C3D3E3F4C5B4B5";
  opBook[numLines++]="C4C3D3E3F4F5F3";
  opBook[numLines++]="C4C3D3E3F4B5C2";
  opBook[numLines++]="C4C3D3E3F4G3F6";
  opBook[numLines++]="C4C3D3E3F6B5F3F5E2F4";
  opBook[numLines++]="C4C3F5B4D3";
  opBook[numLines++]="C4C3E6B4D3";
  opBook[numLines++]="C4C3C2C5E6";
  opBook[numLines++]="C4E3F4C5D6F3E6B4C3G4";
  opBook[numLines++]="C4E3F4C5D6F3E6D7C6";
  opBook[numLines++]="C4E3F4C5D6F5D3";
  opBook[numLines++]="C4E3F4C5D6E6C6C7";
  opBook[numLines++]="C4E3F4C5D6E6D3B4F3C6";
  opBook[numLines++]="C4E3F4C5D2C3";
  opBook[numLines++]="C4E3F4C5E2C3";
  opBook[numLines++]="C4E3F4C5C6B5";
  opBook[numLines++]="C4E3F4C5E6C3";
  opBook[numLines++]="C4E3F4G5G4C5";
  opBook[numLines++]="C4E3F4G3G4C5";
  opBook[numLines++]="C4E3F4C3D3C5";
  opBook[numLines++]="C4E3F5B4F3F4";
  opBook[numLines++]="C4E3F5E6F3C5";
  opBook[numLines++]="C4E3F6E6F5C5";
  opBook[numLines++]="C4E3F3C5E2C3";
  opBook[numLines++]="C4E3F3G3E2C6";
  opBook[numLines++]="C4E3F2C6F6F5";
  opBook[numLines++]="C4E3F2C3C5C6";
  opBook[numLines++]="C4C5D6E3C6B5E6";
  opBook[numLines++]="C4C5D6E3C6B4C3";
  opBook[numLines++]="C4C5D6E3C6B6B5";
  opBook[numLines++]="C4C5D6E3C6C7D7";
  opBook[numLines++]="C4C5D6E3D3C3";
  opBook[numLines++]="C4C5D6C3E6F6F5";
  opBook[numLines++]="C4C5D6C3E6F7E7";
  opBook[numLines++]="C4C5D6C3E6E7D7";
  opBook[numLines++]="C4C5D6C3E6F5C6";
  opBook[numLines++]="C4C5D6C3E6D7C6";
  opBook[numLines++]="C4C5D6C3E6F4E3";
  opBook[numLines++]="C4C5D6C7D7C3E6";
  opBook[numLines++]="C4C5D6C7D7E7C6";
  opBook[numLines++]="C4C5D6C7D7E3C6";
  opBook[numLines++]="C4C5D6E7D7C3E6";
  opBook[numLines++]="C4C5D6E7D7C7C6";
  opBook[numLines++]="C4C5D6E7D7E3C6";
  opBook[numLines++]="C4C5B6C3";
  opBook[numLines++]="C4C5C6B5";
  opBook[numLines++]="C4C5E6C3";
  opBook[numLines++]="C4C5F6C3";
}

/* Play according to the opening book */
void opBookPlay(void)
{
  char playFirstQuarter[3];
  char memoLine[100];
  char nextMove[]="C4";
  
  if(memoGameNum==0)
  {
    xPlay=3;
    yPlay=4;   
  }
  else
  {
    strcpy(playFirstQuarter, "C4");
    strcpy(memoLine, "");
    for(int moveNum=0; moveNum<memoGameNum;
        moveNum++)
    {
      switch(memoGame[0][0])
      {
        case 3 :
          playFirstQuarter[0]= 
                 'A'-1+memoGame[moveNum][0];
          playFirstQuarter[1]=
                 '1'-1+memoGame[moveNum][1];
          break;
  
        case 4 :
          playFirstQuarter[0]=
           'A'-1+memoGame[moveNum][1];
          playFirstQuarter[1]=
            '1'-1+memoGame[moveNum][0];
          break;
  
        case 5 :
          playFirstQuarter[0]=
            'A'+8-memoGame[moveNum][1];
          playFirstQuarter[1]=
            '1'+8-memoGame[moveNum][0];
          break;
  
        case 6 :
          playFirstQuarter[0]=
            'A'+8-memoGame[moveNum][0];
          playFirstQuarter[1]=
            '1'+8-memoGame[moveNum][1];
          break;       
      }
      strcat(memoLine, playFirstQuarter);
    }

    for(int i=0; i<numLines; i++)
      if(!(strncmp(opBook[i], memoLine,
                  strlen(memoLine))) &&
          strlen(opBook[i])>strlen(memoLine))
      {
        playFirstQuarter[0]=
          opBook[i][strlen(memoLine)];
        playFirstQuarter[1]=
          opBook[i][strlen(memoLine)+1];

        switch(memoGame[0][0])
        {
          case 3 :
            xPlay=playFirstQuarter[0]+1-'A';
            yPlay=playFirstQuarter[1]+1-'1';
            break;
  
          case 4 :
            xPlay=playFirstQuarter[1]+1-'1';
            yPlay=playFirstQuarter[0]+1-'A';
            break;
  
          case 5 :
            xPlay='1'+8-playFirstQuarter[1];
            yPlay='A'+8-playFirstQuarter[0];
            break;
  
          case 6 :
            xPlay='A'+8-playFirstQuarter[0];
            yPlay='1'+8-playFirstQuarter[1];
        }
        return;
      }
      openingBookActive=false;
  }
}

/* The next five functions evaluate a position
   using a cooking that mixes different
   criteria such as the mobility, the number
   of disks of each color, the owning of the
   corners... The higher the resulting score
   is, the more the position is favorable to
   the white player.
*/
int mobility(tBoard board)
{
  int mob=0;
  byte*square;
  byte*firstSquare;

  firstSquare=&board[1][1];
  for(byte i=0; i<78; i++)
  {
    square=firstSquare+i;
    if(*square==EMPTY)
    {
      if(*(square+1)==BLACK) mob++;
      if(*(square+1)==WHITE) mob--;
      if(*(square+9)==BLACK) mob++;
      if(*(square+9)==WHITE) mob--;
      if(*(square+10)==BLACK) mob++;
      if(*(square+10)==WHITE) mob--;
      if(*(square+11)==BLACK) mob++;
      if(*(square+11)==WHITE) mob--;
      if(*(square-9)==BLACK) mob++;
      if(*(square-9)==WHITE) mob--;
      if(*(square-10)==BLACK) mob++;
      if(*(square-10)==WHITE) mob--;
      if(*(square-11)==BLACK) mob++;
      if(*(square-11)==WHITE) mob--;
      if(*(square-1)==BLACK) mob++;
      if(*(square-1)==WHITE) mob--;
    }
  }
  return (mob);
}

int fiveDiskEdges(tBoard board)
{
  int score=0;
  
  if((board[1][1]&NOTFAR)==EMPTY)
  {
    if((board[1][8]&NOTFAR)==EMPTY)
    {
      if(board[1][2]==EMPTY)
      {
        if(board[1][3]==board[1][7])
        {
          if(board[1][3]==BLACK) score++;
          else if(board[1][3]==WHITE) score--;
        }
      }
      else if(board[1][7]==EMPTY)
      {
        if(board[1][2]==board[1][6])
        {
          if(board[1][2]==BLACK) score++;
          else if(board[1][2]==WHITE) score--;
        }
      }
    }
    if((board[8][1]&NOTFAR)==EMPTY)
    {
      if(board[2][1]==EMPTY)
      {
        if(board[3][1]==board[7][1])
        {
          if(board[3][1]==BLACK) score++;
          else if(board[3][1]==WHITE) score--;
        }
      }
      else if(board[7][1]==EMPTY)
      {
        if(board[2][1]==board[6][1])
        {
          if(board[2][1]==BLACK) score++;
          else if(board[2][1]==WHITE) score--;
        }
      }
    }
  }

  if((board[8][8]&NOTFAR)==EMPTY)
  {
    if((board[8][1]&NOTFAR)==EMPTY)
    {
      if(board[8][2]==EMPTY)
      {
        if(board[8][3]==board[8][7])
        {
          if(board[8][3]==BLACK) score++;
          else if(board[8][3]==WHITE) score--;
        }
      }
      else if(board[8][7]==EMPTY)
      {
        if(board[8][2]==board[8][6])
        {
          if(board[8][2]==BLACK) score++;
          else if(board[8][2]==WHITE) score--;
        }
      }
    }
    if((board[1][8]&NOTFAR)==EMPTY)
    {
      if(board[2][8]==EMPTY)
      {
        if(board[3][8]==board[7][8])
        {
          if(board[3][8]==BLACK) score++;
          else if(board[3][8]==WHITE) score--;
        }
      }
...

This file has been truncated, please download it to see its full contents.

Credits

frenchy22
6 projects • 3 followers
Contact

Comments

Please log in or sign up to comment.