📄 pawn.m
字号:
function varargout = Pawn(method, varargin)
% Pawn The pawn objects.
% This m-function contains the variables and methods for all knights.
%
% Inputs:
% * method ... What the pawn instance wants (i.e move, best_move,init,...).
% * varargin ... parameters required for the method(i.e from, to, ...)
% * global board ... chess board and related information
%
% Outputs:
% * varargout ... outputs generated by the method (i.e. best move, legal move,...)
% * global board ... updated chess board and related information
%
% Example
% Add a white pawn on field c4 [5,3].
% |Pawn('init',[5 3],1,'Bc4')|
%
% Move the pawn from c4 [5,3] to c5 [3 3].
% |Pawn('move',[5 3],[3 3])|
%
% Determine the pawns best move from c4
% |Pawn('best_move',[5 3])|
%
% See also: Chess, legal_move, show, remove_figure, Value_of_Figure
%
%% Signature
% Author: W.Garn
% E-Mail: wgarn@yahoo.com
% Date: 2006/03/23 12:00:00
%
% Copyright 2006 W.Garn
%
%% Last modifications
% * 30/3/2006 corrected removal of pawn
%
if nargin<1
Chess;
return;
end
persistent pos; % nx2 matrix of all knights
persistent instances; % cell array - names of all the knights
persistent color; % array of colors (0=black,1=white)
persistent handle; % array of handles to knights
% classic example that there is a big difference beween object orientated
% languages and procedural languages. I have to take care of all the
% instances, hence instance variables myself.
% the escape route is to copy all the variables, which by the way is
% Matlabs object approach, but it's a lot of copying, persistent variables
% offer the reference approach, that is why I stick to it.
global board;
global EDIs;
%logFlag=1; logFile=1;
switch method
case 'clear'
pos = []; instances = []; color = [];
for k = 1:length(handle)
try delete(handle);
catch end
end
handle = [];
case 'init'
% varargin: 1: pos, 2: color, 3: instance
n = length(instances)+1; % which instance number
instances{n} = varargin{3};
pos = [pos; varargin{1}]; %matrix position (i.e. [2 3]=c7)
color = [color; varargin{2}]; %color
if color(n), fig='P'; else fig='p'; end
if color(n), board.white(pos(n,1),pos(n,2))=1;
else board.black(pos(n,1),pos(n,2))=1; end
board.figures(pos(n,1),pos(n,2)) = fig;
handle = [handle, show('Pawn',varargin{1},color(n))];
set(handle,'ButtonDownFcn','cursorListener(gcbo,[],guidata(gcbo))');
case 'legal_move'
varargout{1} = legal_move(varargin{1},varargin{2});
case 'move'
%if logFlag, fprintf(logFile,'Pawn will move from %s to %s.\n',matrix2chess(varargin{1}),matrix2chess(varargin{2})); end
% en passante
from = varargin{1}; to = varargin{2};
if abs(from(2)-to(2))==1 % pawn beats
if board.figures(to(1),to(2))==' ' % there is no figure
% then it is en passant
remove_figure( [from(1), to(2)] );
else
remove_figure( varargin{2} );
end
end
pos = move_figure(from, to , pos, handle);
% possible transformation into other figure
if to(1)==1 || to(1)==8
% ask which figure
cur_color = getColor(to);
if EDIs.color == cur_color,
fig='q';
else
fig = ask_which_figure;
end
if cur_color, fig = upper(fig); else fig = lower(fig); end
% remove old pawn
remove_figure( to );
% create Figure
[name, handle_chess_figure] = getFigureName(fig);
handle_chess_figure('init',[to(1) to(2)],cur_color,[fig matrix2chess(to)]); % matrix position, color, instance name
end
%if logFlag, fprintf(logFile,'Pawn moved from %s to %s.\n',matrix2chess(varargin{1}),matrix2chess(varargin{2})); end
case 'best_move'
%if logFlag, fprintf(logFile,'Try to detect best pawn move from %s.\n',matrix2chess(varargin{1})); end
from = varargin{1};
%if logFlag, fprintf(logFile,'to fields...\n'); end
T = toFields(from); % all possible moves within board
cur_color = getColor(from);
if cur_color %white
%if logFlag, fprintf(logFile,'white possible fields...\n'); end
P = possible(from, T); % only moves, where there is no own figure
[b,gain] = best(P,board.black,from);
else %black
%if logFlag, fprintf(logFile,'black possible fields...\n'); end
P = possible(from, T); % only moves, where there is no own figure
[b,gain] = best(P,board.white,from);
end
varargout{1}=b;
varargout{2}=gain;
case 'remove'
k = findPos(pos,varargin{1});
if ~isempty(k)
pos(k,:)=[];
instances(k)=[];
color(k)=[];
delete(handle(k));
handle(k)=[];
end
otherwise
disp('Method is not defined.');
end
%--------------------------------------
function pos = move_figure(from, to, pos, handle)
% from, to ... matrix notation
% moves the figure from a field to a other field
% it is assumed that the legality of the move was checked
% if a opponent figure is on the field it will be first removed.
global board
p = findPos(pos, from);
pos(p,:) = to;
setFiguresPosition(handle(p),to);
% set board
color = getColor(from);
% to
board.figures(to(1),to(2)) = board.figures(from(1),from(2));
if color %white
board.white(to(1),to(2)) = board.white(from(1),from(2));
else
board.black(to(1),to(2)) = board.black(from(1),from(2));
end
% from
board.figures(from(1),from(2)) = ' ';
if color %white
board.white(from(1),from(2)) = 0;
else
board.black(from(1),from(2)) = 0;
end
%--------------------------------------
function T = toFields(position)
% determines all possibles fields within the board (without regarding
% opponent figures)
% position ... current position of pawn
color = getColor(position);
if color %white
M = [[-1 -1 -1]', [0 -1 +1]']; %one up, beat left, beat right
if position(1)==7 % is allowed to move two fields up
M = [M; [-2 0]];
end
else %black
M = [[1 1 1]', [0 -1 +1]']; %one down, beat left, beat right
if position(1)==7 % is allowed to move two fields up
M = [M; [-2 0]];
end
end
e = ones(size(M,1),1);
D = e*position + M;
I = find ( sum((D > 0 & D < 9),2)==2 ); % only fields within the board
T = D(I,:);
function P = possible(from, T)
% checks whether there is no own figure on field
% or between
% T ... fields a pawn can reach
% from ... original field of pawn
global board
global history
P =[];
color = getColor(from);
f1 = from(1); f2 = from(2);
for k = 1:size(T,1)
i=T(k,1); j=T(k,2);
if f2-j==0 % straight forward
% forward one field
if ( abs(f1-i)==1 )
if board.white(i,j)+board.black(i,j)==0 % no own or opponenet figure
P = [P; T(k,:)];
end
elseif abs(f1-i)==2 % forward two fields
if color %white
% no figure in between
if board.white(i+1,j)+board.black(i+1,j)==0
if board.white(i,j)+board.black(i,j)==0 % no own or opponenet figure
P = [P; T(k,:)];
end
end
else % black
if board.white(i-1,j)+board.black(i-1,j)==0
if board.white(i,j)+board.black(i,j)==0 % no own figure
P = [P; T(k,:)];
end
end
end
end
else % beating left, right or enpassant
if color %white
if board.black(i,j)>0 % there is an opponents figure
P = [P; T(k,:)];
else % en passant
if i==3 % only possible when white is in 4th[matrix notation] row
lm_nb = size(history.black_pos,1); % blacks last move number
bf = history.black_pos{lm_nb,1};
bt = history.black_pos{lm_nb,2};
bfig = history.black_fig{k};
% black pawn tried to pass by with his last move
if bfig=='P' && j==bt(2) && i==bt(1)-1 && i==bf(1)+1 % same column, passed by, two fields
P = [P; T(k,:)];
end
end
end
else %black
if board.white(i,j)>0 % there is an opponents figure
P = [P; T(k,:)];
else % en passant
if i==6 % only possible when white is in 4th[matrix notation] row
lm_nb = size(history.white_pos,1); % blacks last move number
wf = history.white_pos{lm_nb,1};
wt = history.white_pos{lm_nb,2};
wfig = history.white_fig{k};
% white pawn tried to pass by with his last move
if wfig=='P' && j==wt(2) && i==wt(1)+1 && i==wf(1)-1 % same column, passed by, two fields
P = [P; T(k,:)];
end
end
end
end
end
end
%------------------------------------------------------------------
% Edis intelligence (ok. I admit, quite simple)
function [b,gain] = best(P, board,from)
% one move best
% Inputs:
% * board ... values of opponent
%
% Outputs:
% * b ... best field to go to
% * gain ... what the gain would be
b=[]; gain=-inf;
%disp('started best...');
if ~isempty(P)
values = zeros(1, size(P,1));
for k = 1:size(P,1)
values(k) = board(P(k,1),P(k,2));
if abs(from(2)-P(k,2))==1 % beats
if board(P(k,1),P(k,2))==0 % but no figure
%hence it is en passant
values(k) = 1;
end
end
% maybe a queen
if P(k,1)== 8 || P(k,1)== 1
values(k) = values(k) + 9; % choose queen
end
end
[M I] = max(values);
% take randomly one of the best
j = ceil(length(I)*rand); %(0,1]
b = P(I(j),:);
gain = values(I(j));
end
%disp('finished best!');
%------------------------------------------------------------------
function answer = legal_move(from, to)
T = toFields(from); % all possible moves within board
color = getColor(from);
if color %white
P = possible(from, T); % only moves, where there is no own figure
else %black
P = possible(from, T); % only moves, where there is no own figure
end
if ~isempty(P)
I = find( sum((P == ones(size(P,1),1)*to),2) == 2 );
else
I = [];
end
if isempty(I), answer=0; % not legal
else answer = 1; % legal move
end
%------------------------------------------------------------------
function fig = ask_which_figure
s = [];
while isempty(s) % there is no cancle possible!
s = listdlg('PromptString','Please choose your figure','SelectionMode','single','ListString',{'Queen','Rook','Bishop','Knight'},'Name','Pawn transformation','ListSize',[150,80]);
end
switch s
case 1
fig='q';
case 2
fig='r';
case 3
fig='b';
case 4
fig='n';
otherwise
fig='q';
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -