%======================================================================
% This is
%		knight.mf
%
% Copyright (C) 1989-93  by Elmar Bartel.
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 1, or (at your option)
% any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%======================================================================
%
def sympoint (expr p,d,a) = 
	% Come to point p in direction d + angel a, and leave symmetrical
	% to d - a This gives us a peak in p pointing in direction d.
	% sharpnes is specified by a. a= 0 no peak, a=90 real peak;

	{dir (angle(d)+a)} p {dir(angle(d)+180-a)}
enddef;

def Ear(expr p,pd,q,qd,a,r,rd) =
	p{pd} .. sympoint(q,qd,a) .. {rd}r
enddef;

def DefineKnightPath =
	% we construct the path from right to left.
	% Ie we begin with the nack and come then to the ears,
	% the nose etc
	z0 = (.33qs,BottomSpace);	% The leftmost bottompoint
	z1 = (qs-SideSpace,BottomSpace); % The right bottom edge
	path Foot;
	Foot = z0 -- z1;
					% z2 will be later defined, it
					% is the connection to the right
					% ear
	z4 = (.465qs,qs-TopSpace+.035qs);	% The peak of the right ear
	z3 = z4 + (.042qs,-0.12qs);	% The right lower point of the
					% right ear
	z5 = z3 + (-.09qs,.015qs );	% The left lower point of the
					% right ear

	% Now comes the definition of the right ear
	% There are two paths:
	%	RightEar:  The complete path for the ear
	%	sRightEar: The subpath for the whole shape
	path RightEar, sRightEar;
	RightEar = Ear(z3,(1,10),z4,(0,1),35,z5,(1,-10));
	sRightEar = subpath (.25,1.85) of RightEar;
	z2 = point 0 of sRightEar;	% The right 
	z6 = point 2 of sRightEar;	% The left connection point of
					% the right ear 

	% Now we can also define the nack
	path Nack;
	Nack = z1{up} .. tension 1 and 1 ..  {left}z2;

	z7 = z6 + (-.08qs,-0.05qs);	% This is the point under the
					% left ear

	% Now the two pathes from the right to the left ear.
	% EarUnderEar, goes from the right ear under the left ear
	% EarToEar connects only the two ears

	path EarUnderEar,EarToEar;
	EarUnderEar= z6{left} .. {-5,-4}z7;
	EarToEar = subpath (0,.4) of EarUnderEar;	

	z8 = point 1 of EarToEar;	% The connection point and the
					% start of the left ear

	% to get easier definition of the following points 
	% we define a line bx from z7 (point under left ear) down to z13
	% (leftmost point of shape) ie the begining of nose and mount

	z13 = (SideSpace,0.41qs);	% The leftmost point of the
					% shape
	pair bx,by;
	bx = z13 - z7;
	by = z13 rotatedabout (z7,-90);

	z9 = z7 + .21bx + .21by;	% the peak of the left ear
	z10= z7 + .15bx + .08by;	% the left point of the left ear

	% Now the path for the leaft ear
	path LeftEar;
	LeftEar= Ear(z8,(-1,3),z9,(-1,2),20,z10,(2,-3));

	z11 = z7 + .45bx + .10by;
	z12 = z7 + .50bx + .06by;
	z26 = z7 + .16bx - .02by;	% the eye point

	path Bless;
	Bless = z10{dir(angle(bx)-15)} .. z11 .. z12 .. {down} z13;

	% the points from z14 to z17 are defined via a line nx
	% from z13 to z18
	pair nx,ny;

	z19 = (.255qs,.315qs);
	nx = z19 - z13;
	ny = nx rotatedabout ((0,0),90);

	z14 = z13 + .30nx - .22ny;	% the point between mouth
					% and nose
	z15 = z13 + .60nx - .15ny;	% the upper point of mouth
	z16 = z13 + .70nx + .31ny;	% the inner point of mouth
	z17 = z13 + .76nx - .02ny;	% 
	z18 = z13 + .82nx - .07ny;	%
	z25 = z13 + .22nx + .28ny;	% the location of the nose

	path MouthNose;
	MouthNose = z13 .. z14{nx} .. z15 ... sympoint(z16,(z16-z17),0)
		       ... z17 .. z18 .. z19;

	% the points from z20 to z23 are defined via a line nx
	% from z19 to z23
	pair ux,uy;

	z23 = (.546qs,.64qs);
	ux = z23 - z19;
	uy = z23 rotatedabout (z19,90);

	z20 = z19 + .15ux + .01uy;
	z21 = z19 + .45ux - .02uy;
	z22 = z19 + .90ux - .11uy;
	path UnderMouth, sUnderMouth;
	UnderMouth = z19..z20..z21..z22..{up}z23;
	sUnderMouth = subpath (0,3) of UnderMouth;

	z24 = z22 + (.008qs,-.05qs);
	path ToFoot;
	%ToFoot = z22..{down}z24 .. {down}z0;
	ToFoot = z22..z24..{down}z0;


	path KnightShape;
	KnightShape = Foot & Nack & sRightEar & EarToEar
			   & LeftEar & Bless & MouthNose
			   & sUnderMouth & ToFoot & cycle;

enddef;

def DefineNosePath(expr p,s) = 
	begingroup
	if proofing >0:
		show p,s;
	fi;
	save z; pair z[];

	z0 + (0,s) = p;
	pair px,py;
	py= p - z0;
	px= py rotated -90;
	z1= z0 + 0.10px + 0.50py;
	z2= z0 + 0.70px + 1.00py;
	z3= z0 + 0.70px + 1.60py;
	z4= z0 + 0.10px + 2.10py;
	z5= z0 - 0.20px + 1.90py;
	z6= z0 - 0.60px + 0.50py;
	z7= z0 - 0.60px + 0.10py;
	z8= z0 - 0.50px + 0.00py;
	forsuffixes i=0,1,2,3,4,5,6,7,8:
		z[i]..
	endfor cycle
	endgroup
enddef;

def EyePath (expr p,s) =
	begingroup
	save z; pair z[];

	z0 + (0,s) = p;
	pair px,py;
	py= p - z0;
	px= py rotated -90;

	z1= z0 + 1.00px + 1.00py;

	z0{0,1} .. {1,0} z1 & z1 {0,-1} .. {-1,0}z0 & cycle
	endgroup
enddef;

def EyeBrowPath (expr p,s) =
	begingroup
	save z; pair z[];

	z0 + (0,s) = p;
	pair px,py;
	py= p - z0;
	px= py rotated -90;

	z1= z0 - 0.74px - 0.74py;
	z2= z0 + 1.74px + 1.74py;

	z1{0,1} .. {1,0}z2
	endgroup
enddef;

def MakeWhiteKnight = 
	clearit;
	pickup chess_pen;
	draw Foot;
	draw RightEar;
	draw EarUnderEar;
	draw LeftEar & Bless & MouthNose & UnderMouth;
	draw ToFoot;
	draw EyePath(z26,.025qs);
	filldraw DefineNosePath(z25,.015qs);
	pickup chess_pen xscaled 2 rotated -10; 
	draw ShortenEnd(Nack,thin);
	pickup chess_pen scaled 0.6;
	draw EyeBrowPath(z26,.030qs);
	WhiteMan:= currentpicture;
enddef;

def MakeBlackKnight = 
	clearit;
	pickup chess_pen;

	filldraw KnightShape;
	cullit;
	unfilldraw DefineNosePath(z25,.015qs);
	undraw EyePath(z26,.025qs);
	undraw ParallelPath(EarUnderEar,1.2thin) rotatedaround(z6,-20);
	pickup chess_pen xscaled 2 rotated -20;
	undraw ShortenPath(xyParallelPath(Nack,1.5thin,thin),thin);
	pickup chess_pen scaled .6;
	undraw subpath (3,3.5) of UnderMouth;
	undraw EyeBrowPath(z26,.030qs);
	undraw subpath (2.5,3) of MouthNose;
	BlackMan:= currentpicture;
enddef;

def MakeKnightSpace =
	clearit;
	pickup frame_pen;
	filldraw KnightShape;
	cullit;
	OuterShape:= currentpicture;
enddef;

DefineKnightPath;
%DefineNosePath(z25,.2qs);

MakeWhiteKnight;
MakeBlackKnight;
MakeNeutral(WhiteMan,BlackMan);
MakeKnightSpace;

%===========================================================
% this one for testing
%beginchar(Knight+Black+OnBlack, qs#, qs#, 0);
%	"White knight on black field";
%	MakeBlackField;
%	cullit;
%	currentpicture:= currentpicture - OuterShape;
%	cullit;
%	currentpicture:= currentpicture + BlackMan;
%endchar;
%endinput
%===========================================================

beginchar(Knight+White+OnWhite, qs#, qs#, 0);
	"White knight on white field";
	currentpicture:= WhiteMan;
%	labels(z0,z1l,z1,z1r,z2l,z2,z2r);
%	labels(z3l,z3,z3l,z4,z5,z6l,z6r);
%	labels(z7l,z7,z7r,z8);
endchar;

beginchar(Knight+White+OnWhite+LeftTurned, qs#, qs#, 0);
	"White knight turned to the left on white field";
	currentpicture:= TurnLeft(WhiteMan);
endchar;

beginchar(Knight+White+OnWhite+RightTurned, qs#, qs#, 0);
	"White knight turned to the right on white field";
	currentpicture:= TurnRight(WhiteMan);
endchar;

beginchar(Knight+White+OnWhite+UpSideDown, qs#, qs#, 0);
	"White knight turned upsidedown on white field";
	currentpicture:= TurnUpSideDown(WhiteMan);
endchar;

%===========================================================

beginchar(Knight+White+OnBlack, qs#, qs#, 0);
	"White knight on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - OuterShape;
	cullit;
	currentpicture:= currentpicture + WhiteMan;
endchar;

beginchar(Knight+White+OnBlack+LeftTurned, qs#, qs#, 0);
	"White knight turned to the left on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - TurnLeft(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnLeft(WhiteMan);
endchar;

beginchar(Knight+White+OnBlack+RightTurned, qs#, qs#, 0);
	"White knight turned to the right on black field";
	MakeBlackField;
	currentpicture:= currentpicture - TurnRight(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnRight(WhiteMan);
endchar;

beginchar(Knight+White+OnBlack+UpSideDown, qs#, qs#, 0);
	"White knight turned upsidedown on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - TurnUpSideDown(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnUpSideDown(WhiteMan);
endchar;

%===========================================================

beginchar(Knight+Neutral+OnWhite, qs#, qs#, 0);
	"Neutral knight on white field";
	currentpicture:= NeutralMan;
endchar;

beginchar(Knight+Neutral+OnWhite+LeftTurned, qs#, qs#, 0);
	"Neutral knight turned to the left on white field";
	currentpicture:= TurnLeft(NeutralMan);
endchar;

beginchar(Knight+Neutral+OnWhite+RightTurned, qs#, qs#, 0);
	"Neutral knight turned to the right on white field";
	currentpicture:= TurnRight(NeutralMan);
endchar;

beginchar(Knight+Neutral+OnWhite+UpSideDown, qs#, qs#, 0);
	"Neutral knight turned upsidedown on white field";
	currentpicture:= TurnUpSideDown(NeutralMan);
endchar;

%===========================================================

beginchar(Knight+Neutral+OnBlack, qs#, qs#, 0);
	"Neutral knight on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - OuterShape;
	cullit;
	currentpicture:= currentpicture + NeutralMan;
endchar;

beginchar(Knight+Neutral+OnBlack+LeftTurned, qs#, qs#, 0);
	"Neutral knight turned to the left on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - TurnLeft(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnLeft(NeutralMan);
endchar;

beginchar(Knight+Neutral+OnBlack+RightTurned, qs#, qs#, 0);
	"Neutral knight turned to the right on black field";
	MakeBlackField;
	currentpicture:= currentpicture - TurnRight(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnRight(NeutralMan);
endchar;

beginchar(Knight+Neutral+OnBlack+UpSideDown, qs#, qs#, 0);
	"Neutral knight turned upsidedown on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - TurnUpSideDown(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnUpSideDown(NeutralMan);
endchar;

%===========================================================

beginchar(Knight+Black+OnWhite, qs#, qs#, 0);
	"Black knight on white field";
	currentpicture:= BlackMan;
endchar;

beginchar(Knight+Black+OnWhite+LeftTurned, qs#, qs#, 0);
	"Black knight turned to the left on white field";
	currentpicture:= TurnLeft(BlackMan);
endchar;

beginchar(Knight+Black+OnWhite+RightTurned, qs#, qs#, 0);
	"Black knight turned to the right on white field";
	currentpicture:= TurnRight(BlackMan);
endchar;

beginchar(Knight+Black+OnWhite+UpSideDown, qs#, qs#, 0);
	"Black knight turned upsidedown on white field";
	currentpicture:= TurnUpSideDown(BlackMan);
endchar;

%===========================================================

beginchar(Knight+Black+OnBlack, qs#, qs#, 0);
	"Black knight on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - OuterShape;
	cullit;
	currentpicture:= currentpicture + BlackMan;
endchar;

beginchar(Knight+Black+OnBlack+LeftTurned, qs#, qs#, 0);
	"Black knight turned to the left on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - TurnLeft(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnLeft(BlackMan);
endchar;

beginchar(Knight+Black+OnBlack+RightTurned, qs#, qs#, 0);
	"Black knight turned to the right on black field";
	MakeBlackField;
	currentpicture:= currentpicture - TurnRight(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnRight(BlackMan);
endchar;

beginchar(Knight+Black+OnBlack+UpSideDown, qs#, qs#, 0);
	"Black knight turned upsidedown on black field";
	MakeBlackField;
	cullit;
	currentpicture:= currentpicture - TurnUpSideDown(OuterShape);
	cullit;
	currentpicture:= currentpicture + TurnUpSideDown(BlackMan);
endchar;

endinput
