No BSD License  

Highlights from
othello.m

from othello.m by Subroto Gunawan
A simple one-player othello board-game program.

othello()
function othello()

% othello.m
% A simple othello program
% Author: Subroto Gunawan
% Date: August 8, 2000

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%% VARIABLE DECLARATIONS %%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% drawing parameters
DrawResolution = 1/100;
N=2*pi;
Theta = 0:DrawResolution:N;

% define the board
BoardSize = 8;
FigSize = 400;
ButtonWidth = 100;
Board = zeros(BoardSize,BoardSize);
InitXLoc = [ BoardSize/2 BoardSize/2+1 BoardSize/2 BoardSize/2+1];
InitYLoc = [ BoardSize/2 BoardSize/2 BoardSize/2+1 BoardSize/2+1];

% default values
DefaultFirstTurn = 1; % 1 is white, 2 is black
finish=0;
whitePlayer = 'human';
blackPlayer = 'com';
XPos = [-1];
YPos = [-1];
XLegalPos = [];
YLegalPos = [];
BetweenCount = [];
NoMoveTurnCount = 0;
XDir = [-1 -1 0 +1 +1 +1 0 -1]; % counter clockwise directions starting from West
YDir = [0 +1 +1 +1 0 -1 -1 -1];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%% INITIALIZATION %%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% set up the main frame
fig1 = figure(1); 
clf;
set(fig1, 'Position', [120 120 FigSize+ButtonWidth FigSize],...
   'Name','Othello',...
   'NumberTitle','off',...
   'MenuBar','none');

% user control panel
left = 400;
bottom = 300;
width = 75;
height = 30;
ymod = 30;

statusText = uicontrol('Style','Text',...
   'Position',[(FigSize+ButtonWidth-300)/2 FigSize-30 300 25],...
   'BackgroundColor',[0.8 0.8 0.8],...
   'FontWeight','bold',...
   'String','');

infoText = uicontrol('Style','Text',...
   'Position',[(FigSize+ButtonWidth-300)/2 5 300 25],...
   'BackgroundColor',[0.8 0.8 0.8],...
   'String','Right Click to Quit');

whitePlayerText = uicontrol('Style','Text',...
   'Position',[left bottom width height],...
   'BackgroundColor',[0.8 0.8 0.8],...
   'HorizontalAlignment','left',...
   'String',[' White : ' whitePlayer]);
   
blackPlayerText = uicontrol('Style','Text',...
   'Position',[left bottom-ymod width height],...
   'BackgroundColor',[0.8 0.8 0.8],...
   'HorizontalAlignment','left',...
   'String',[' Black : ' blackPlayer]);

turnText = uicontrol('Style','Text',...
   'Position',[left bottom-4*ymod width height],...
   'BackgroundColor',[0.8 0.8 0.8],...
   'String',' White Turn ');
   
whiteText = uicontrol('Style','Text',...
   'Position',[left bottom-7*ymod width height],...
      'BackgroundColor',[0.8 0.8 0.8],...
      'String','White = 2');
   
blackText = uicontrol('Style','Text',...
   'Position',[left bottom-8*ymod width height],...
      'BackgroundColor',[0.8 0.8 0.8],...
      'String','Black = 2');

% creating the board grids
XLine = linspace(0,FigSize,BoardSize+1);
YLine = linspace(0,FigSize,BoardSize+1);

for i=1:(BoardSize+1)
   line([XLine(i) XLine(i)], [YLine(1) YLine(BoardSize+1)],'Color',[0 0 0]);
   line([XLine(1) XLine(BoardSize+1)], [YLine(i) YLine(i)],'Color',[0 0 0]);
end

axis([0,FigSize+ButtonWidth,0,FigSize]);
hold on; 
axis off;

% determine the radius of the piece
gap = (XLine(2)-XLine(1))/2;
radius = gap - (gap*0.25); % leave a 25% side margin

% save the center of the pieces for drawing purposes
XCenter = linspace((XLine(2)-XLine(1))/2, FigSize-(XLine(2)-XLine(1))/2, BoardSize);
YCenter = linspace((YLine(2)-YLine(1))/2, FigSize-(YLine(2)-YLine(1))/2, BoardSize);

BoardCenterX = repmat(XCenter,BoardSize,1);
BoardCenterY = repmat((FigSize - YCenter)',1,BoardSize);

% set up the transparent pieces and draw the first four pieces
Board(InitYLoc(1),InitXLoc(1)) = 1;
Board(InitYLoc(2),InitXLoc(2)) = 2;
Board(InitYLoc(3),InitXLoc(3)) = 2;
Board(InitYLoc(4),InitXLoc(4)) = 1;

for i=1:BoardSize
   for j=1:BoardSize
      X = BoardCenterX(j,i) + radius*cos(Theta);
      Y = BoardCenterY(j,i) + radius*sin(Theta);
      switch Board(j,i)
         case 1, BoardColor(j,i) = fill(X,Y,'w');
         case 2, BoardColor(j,i) = fill(X,Y,'k');
         otherwise
         	BoardColor(j,i) = fill(X,Y,[0.8 0.8 0.8]);
            set(BoardColor(j,i),'EdgeColor',[0.8 0.8 0.8]);
      end
   end
end

%%%%%%%%%%%%%%%%%%%%%%
%%%% MAIN PROGRAM %%%%
%%%%%%%%%%%%%%%%%%%%%%

turn = DefaultFirstTurn;

while ~finish
      
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % check and see if there is any move available
      
      canMove = 0;
      XPosLegal = [];
      YPosLegal = [];
      BetweenCount = [];

      for i=1:BoardSize
         for j=1:BoardSize
            
            if Board(j,i)==0
                              
               for dir=1:8
                  
                  done=0;
                  count=2;
                  between=[];
                                    
                  while(~done)
                     markerX = i + count*XDir(dir);
                     markerY = j + count*YDir(dir);
                     if (markerX<1) | (markerX>BoardSize) | (markerY<1) | (markerY>BoardSize)
                        done=1;
                     elseif (Board(markerY,markerX)==turn)
                        done=1;
                        between = [between Board(markerY-YDir(dir),markerX-XDir(dir))];
                        
                        if (Board(markerY,markerX)==turn) & (between==(mod(turn,2)+1))
                           canMove=1;
                           XPosLegal = [XPosLegal i];
                           YPosLegal = [YPosLegal j];
                           BetweenCount = [BetweenCount length(between)];
                        end
                     else
                        count = count+1;
                        between = [between Board(markerY-YDir(dir),markerX-XDir(dir))];
                     end
                     
                  end % end of while not done
                  
               end % end of for dir
               
            end % end of if board==0
            
         end
      end
      
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % A piece of code for debugging purposes
      
      %BoardLegal = zeros(BoardSize,BoardSize);
      %for i=1:length(XPosLegal)
      %   BoardLegal(YPosLegal(i),XPosLegal(i))=1;
      %end
      %BoardLegal
      
      
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % if there is a move available and white turns, get the input from player
      
if canMove
         
   if turn==1; % if it's the player's turn
   
      done=0;
      while (~done)
         
         [Xnew Ynew Button] = ginput(1);
         if Button==1
            
            if (XLine(1)<=Xnew) & (Xnew<=XLine(BoardSize+1)) & ...
                  (YLine(1)<=Ynew) & (Ynew<=YLine(BoardSize+1) ) 
               for i=1:BoardSize
                  if (XLine(i)<Xnew) & (Xnew<XLine(i+1))
                     XPos = i;
                  end
                  if (YLine(i)<Ynew) & (Ynew<YLine(i+1))
                     YPos = BoardSize+1-i;
                  end
               end
            end
         
         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
         % based on previous result, check and see if the move is legal
         % and if it's legal, draw the piece
         
         legal = 0;
         for i=1:length(XPosLegal)
            if (XPos == XPosLegal(i)) & (YPos == YPosLegal(i))
               legal = 1;
            end
         end
                  
         if legal
            NoMoveTurnCount = 0;
            Board(YPos,XPos) = turn;
            set(BoardColor(YPos,XPos),'FaceColor','w','EdgeColor',[0 0 0]);
            set(statusText,'String','');
            done=1;
            drawnow;
         else
            set(statusText,'String','***** Invalid Move *****');
            drawnow;
         end
               
         else                % if right click
            done=1;
            finish=1;
         end
      end % end of while not done
   
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % then check into 8 direction, reverse the pieces and draw
   
   if ~finish
      
   for dir=1:8
      done=0;
      count=2;
      between=[];
      
      while(~done)
         markerX = XPos + count*XDir(dir);
         markerY = YPos + count*YDir(dir);
         if (markerX<1) | (markerX>BoardSize) | (markerY<1) | (markerY>BoardSize)
            done=1;
         elseif (Board(markerY,markerX)==turn)
            done=1;
            between = [between Board(markerY-YDir(dir),markerX-XDir(dir))];
            if (Board(markerY,markerX)==turn) & (between==(mod(turn,2)+1))
               for i=1:(count-1)
                  Board(YPos+YDir(dir)*i,XPos+XDir(dir)*i) = turn;
                  set(BoardColor(YPos+YDir(dir)*i,XPos+XDir(dir)*i),...
                     'FaceColor','w','EdgeColor',[0 0 0]);
                  drawnow;
               end
            end
         else
            count = count+1;
            between = [between Board(markerY-YDir(dir),markerX-XDir(dir))];
         end
      end
   end
  
   end % end of if ~finish
   
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % if it is black turn, activate the AI
   
else
   % search the highest number of pieces reversed
   [dummy Pos] = max(BetweenCount);
   XPos = XPosLegal(Pos);
   YPos = YPosLegal(Pos);
   Board(YPos,XPos) = turn;
   
      
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % draw the new piece
   NoMoveTurnCount = 0;
   set(statusText,'String','');
   set(BoardColor(YPos,XPos),'FaceColor','k','EdgeColor',[0 0 0]);
   drawnow;
   
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % then check into 8 direction, reverse the pieces and draw
   
   for dir=1:8
      done=0;
      count=2;
      between=[];
      while(~done)
         markerX = XPos + count*XDir(dir);
         markerY = YPos + count*YDir(dir);
         if (markerX<1) | (markerX>BoardSize) | (markerY<1) | (markerY>BoardSize)
            done=1;
         elseif (Board(markerY,markerX)==turn)
            done=1;
            between = [between Board(markerY-YDir(dir),markerX-XDir(dir))];
            if (Board(markerY,markerX)==turn) & (between==(mod(turn,2)+1))
               for i=1:(count-1)
                  Board(YPos+YDir(dir)*i,XPos+XDir(dir)*i) = turn;
                  set(BoardColor(YPos+YDir(dir)*i,XPos+XDir(dir)*i),...
                     'FaceColor','k','EdgeColor',[0 0 0]);
                  drawnow;
               end
            end
         else
            count = count+1;
            between = [between Board(markerY-YDir(dir),markerX-XDir(dir))];
         end
      end
   end
   
end % end of separating human player and com player
   
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % if there is no legal move, display the status
   
else
   % this situation is only allowed twice, otherwise it will repeat forever
   if NoMoveTurnCount<3
      set(statusText,'String','***** No Legal Moves, Change Turns *****');
      drawnow;
      NoMoveTurnCount = NoMoveTurnCount + 1;
   else
      set(statusText,'String','***** No Legal Move For Both Players, End of Game *****');
      finish=1;
   end
end
   
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % once all is done, change turns
   
   turn = mod(turn,2)+1;
   if ~finish
   	if turn==1
      	set(turnText,'String','White Turn');
   	else
      	set(turnText,'String','Black Turn');
      end
   end
      
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % count the number of pieces and see if finished
   
   White = sum(sum(Board == ones(BoardSize,BoardSize)));
   Black = sum(sum(Board == repmat([2],BoardSize,BoardSize)));
   set(whiteText,'String',['White = ' num2str(White)]);
   set(blackText,'String',['Black = ' num2str(Black)]);
   
   if (White+Black) == BoardSize^2
      finish = 1;
      if (White > Black), winner = 'White';
      elseif (White < Black), winner = 'Black';
      else winner = 'Stalemate, no one';
      end
      
      set(statusText,'String',['***** ' winner ' wins! *****']);
   end
      
end % end of while - end of game

Contact us at files@mathworks.com