📄 king.m
字号:
function varargout = King(method, varargin)
% King The King objects.
% This m-function contains the variables and methods for all kings.
%
% Inputs:
% * method ... What the king 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 king on field c4 [5,3].
% |King('init',[5 3],1,'Bc4')|
%
% Move the king from c4 [5,3] to d5 [4 4].
% |King('move',[5 3],[4 4])|
%
% Determine the kings best move from c4
% |King('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
%
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;
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='K'; else fig='k'; end
if color(n), board.white(pos(n,1),pos(n,2))=inf;
else board.black(pos(n,1),pos(n,2))=inf; end
board.figures(pos(n,1),pos(n,2)) = fig;
handle = [handle, show('King',varargin{1},color(n))];
set(handle,'ButtonDownFcn','cursorListener(gcbo,[],guidata(gcbo))');
case 'legal_move'
varargout{1} = legal_move(varargin{1},varargin{2});
case 'move'
remove_figure( varargin{2} );
pos = move_figure(varargin{1}, varargin{2}, pos, handle);
% casteling
if varargin{2}(2)-varargin{1}(2) > 1 %small
from = [varargin{1}(1) 8];
to = [varargin{1}(1) 6];
Rook('move',from,to);
elseif varargin{2}(2)-varargin{1}(2) < -1 %big
from = [varargin{1}(1) 1];
to = [varargin{1}(1) 4];
Rook('move',from,to);
end
case 'best_move'
from = varargin{1};
P = possible(from);
cur_color = getColor(from);
if cur_color %white
[b,gain] = best(P,board.black);
else %black
[b,gain] = best(P,board.white);
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
case 'possible_moves'
% returns all possible king moves without the king beeing checked.
from = varargin{1};
P = possible(from);
% now look whether they are really possible
R=[];
for k=1:size(P,1)
to = P(k,:);
if ~is_in_check(from, to)
R = [R; P(k,:)];
end
end
varargout{1}=R;
case 'getPosition'
in_color = varargin{1};
I = find(color == in_color);
varargout{1} = pos(I,:);
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(from)
% determines all possibles fields within the board
% without regard whether there are other figures
%up,down,left,right - matrix notation
M = [[-1 -1 -1 1 1 1 0 0]',[-1 0 1 -1 0 1 -1 1]'];
e = ones(8,1);
D = e*from + M;
I = find ( sum((D > 0 & D < 9),2)==2 ); % only fields within the board
T = D(I,:);
%--------------------------------------
function P = possible(from)
% checks whether there is no own figure on field
global board
T = toFields(from);
color = getColor(from);
if color, ownfig=board.white; else ownfig=board.black; end
P =[];
for k = 1:size(T,1)
if ownfig(T(k,1),T(k,2))==0
if ~is_in_check(from, [T(k,:)]) % attention recursion
P = [P; T(k,:)];
end
end
end
% casteling (careful close to recursion)
if color %white
if from(1)==8 && from(2)== 5 % King is on original field
if ~has_moved(from) % and has not moved yet
% small casteling
% fields are free
a1=8; a2=6; b1=8; b2=7;
if board.black(a1,a2)+board.white(a1,a2) == 0 && ...
board.black(b1,b2)+board.white(b1,b2) == 0
%then fields are free
% but perhaps they are checked
% whether King is in check, if it is moved
if ~is_in_check(from, [a1 a2]) && ~is_in_check(from, [b1 b2])
if board.figures(8,8)=='R' % castle is there
if ~has_moved([8,8]) % and has not moved
P = [P; [8 7]];
end
end
end
end
% big casteling
% fields are free
a1=8; a2=4; b1=8; b2=3;
if board.black(a1,a2)+board.white(a1,a2) == 0 && ...
board.black(b1,b2)+board.white(b1,b2) == 0
%then fields are free
% but perhaps they are checked
% whether King is in check, if it is moved
if ~is_in_check(from, [a1 a2]) && ~is_in_check(from, [b1 b2])
if board.figures(8,1)=='R' % castle is there
if ~has_moved([8,1]) % and has not moved
P = [P; [8 3]];
end
end
end
end
end
end
else
if from(1)==1 && from(2)== 5 % King is on original field
if ~has_moved(from) % and has not moved yet
% small casteling
% fields are free
a1=1; a2=6; b1=1; b2=7;
if board.black(a1,a2)+board.white(a1,a2) == 0 && ...
board.black(b1,b2)+board.white(b1,b2) == 0
%then fields are free
% but perhaps they are checked
% whether King is in check, if it is moved
if ~is_in_check(from, [a1 a2]) && ~is_in_check(from, [b1 b2])
if board.figures(1,8)=='R' % castle is there
if ~has_moved([1,8]) % and has not moved
P = [P; [1 7]];
end
end
end
end
% big casteling
% fields are free
a1=1; a2=4; b1=1; b2=3;
if board.black(a1,a2)+board.white(a1,a2) == 0 && ...
board.black(b1,b2)+board.white(b1,b2) == 0
%then fields are free
% but perhaps they are checked
% whether King is in check, if it is moved
if ~is_in_check(from, [a1 a2]) && ~is_in_check(from, [b1 b2])
if board.figures(1,1)=='R' % castle is there
if ~has_moved([1,1]) % and has not moved
P = [P; [1 3]];
end
end
end
end
end
end
end
%------------------------------------------------------------------
% Edis intelligence (ok. I admit, quite simple)
function [b,gain] = best(P, board)
% one move best
% Inputs:
% * board ... values of opponent
%
% Outputs:
% * b ... best field to go to
% * gain ... what the gain would be
b=[]; gain=-inf;
if ~isempty(P)
values = zeros(1, size(P,1));
for k = 1:size(P,1)
values(k) = board(P(k,1),P(k,2));
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
%------------------------------------------------------------------
function answer = legal_move(from, to)
answer = 0;
P = possible(from);
if ~isempty(P)
I = find( sum((P == ones(size(P,1),1)*to),2) == 2 );
if isempty(I), answer=0; % not legal
else answer = 1; % legal move
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -