Code covered by the BSD License  

Highlights from
Chebfun

image thumbnail

Chebfun

by

 

30 Apr 2009 (Updated )

Numerical computation with functions instead of numbers.

Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

chebsnake(nodes,alpha)
function chebsnake(nodes,alpha)
%CHEBSNAKE   Chebfun snake game.
%   CHEBSNAKE() Feed the snake with more and more interpolation nodes, but
%   avoid that it hits the boundary or itself! Use the arrow keys to
%   control the snake. Any other key will quit the game.
%
%   CHEBSNAKE(NODES) allows one to change the interpolation type. The
%   default type 'cheby' is polynomial interpolation in Chebyshev points.
%   Other types are polynomial interpolation in equispaced points ('equi')
%   and Floater-Hormann rational interpolation in equispaced points ('fh').
%   The blue dots on the snake indicate the interpolated function values.
%
%   CHEBSNAKE(NODES,ALPHA) allows to change the initial game speed by a
%   factor ALPHA > 0, ALPHA > 1 increases the game speed, ALPHA < 1
%   decreases it (default = 1).
%
%   To prevent you from neglecting your actual work, the game speed
%   increases with the total number of achieved points...

% Copyright 2011 by The University of Oxford and The Chebfun Developers. 
% See http://www.maths.ox.ac.uk/chebfun/ for Chebfun information.

    % get some constants right
    if nargin < 2, alpha = 1; end
    if nargin > 0 && strcmp(nodes,'equi'), nodes = 0; 
    elseif nargin > 0 && strcmp(nodes,'fh'), nodes = 2;  else nodes = 1; end
    LW = 'LineWidth'; lw = 2;
    res = 0.15; len = 5; dom = domain(-1,1); d = 1;
    food = @() res*(round((1.8*rand-.9)/res)+1i*round((1.8*rand-.9)/res));
    pause on
    
    % keyboard interaction
    figure('KeyPressFcn',@keypress);
    function keypress(~,evnt)
        dold = d;
        switch evnt.Key
            case 'leftarrow', d = -1;
            case 'rightarrow', d = 1;
            case 'downarrow', d = -1i;
            case 'uparrow', d = 1i;
            otherwise, d = 0; % quit
        end;
        if d == -dold; d = dold; end
    end

    alpha0 = alpha;                     % set base level for alpha
    fails = 0;                          % fail counter (no food eaten)
    failmax = 5;                        % number of consecutive fails before quit
    while ~(d==0), % until quit
        d = 1;
        clf; 
        s = linspace(res*(1-len),0,len) + 1i*eps;
        hs1 = plot(s(1:end-1),'b-',LW,lw); hold on
        hs2 = plot(s(1:end-1),'bo',LW,lw);
        f = food();
        hf = plot(real(f),imag(f),'md','MarkerSize',10,'MarkerFaceColor','m');
        ht = plot(8,0);                     % dummy handle
        title('Control the snake with arrow keys. Quit with any other key.');
        axis([-1,1,-1,1]); shg; pause(0.3);
        pts = 0;                            % points counter
        alpha = alpha0;                     % reset alpha (speed)
        t = 1;                              % convex factor for nodes
        tic;
        while ~(d==0),                      % until game over or quit
            t = t + .2*alpha;
            if t > 1,
                t = 0; dr = res*d;
                s = [ s(2:end),s(end)+dr ];
                if length(s) < len+pts, s = [ s(2),s ]; end
            end
            y = (1-t)*s(1:end-1)+t*s(2:end);
            if nodes==1,
                c = chebfun(y);
            elseif nodes==2,
                fhd = min(ceil(0.4*sqrt(length(y))),4);
                c = bary(linspace(-1,1,5*length(y)),y,linspace(-1,1,...
                    length(y)),weights(length(y)-1,fhd));
            elseif nodes==0
                c = polyfit(linspace(-1,1,length(y)),y,length(y)-1,dom);
            end
            for k = 1:numel(hs1)
                if isnan(hs1(k)), continue, end
                delete(hs1(k));
            end
            hs1 = plot(c,'b-',LW,lw);
            delete(hs2);
            hs2 = plot(y,'bo',LW,lw);
            shg; pause(max(0.01,0.03-toc)/alpha); tic;

            % check if the snake hits itself or the boundary
            if max(abs([real(y(end)),imag(y(end))])) > 1 || ...
                   min(abs(y(end)-y(1:end-1))) < res/2,
                ht = plot(.8*scribble('game over'),'r',LW,lw); 
                shg; pause(1); 
                if pts == 0, fails = fails + 1; end
                if fails > failmax, d = 0; end
                break
            end
            if abs(y(end)-f) < res/2, % snake eats food ?
                pts = pts + 1; alpha = alpha * 1.003; fails = 0;
                title(['Points : ' num2str(pts)]);
                f = food();
                set(hf,'XData',real(f),'YData',imag(f));
            end
        end
        for k = 1:numel(ht)
            if isnan(ht(k)), continue, end
            delete(ht(k));
        end
    end;
    plot(.8*scribble('goodbye'),'r',LW,lw);
    shg; pause(1); close(gcf);

    function w = weights(n,fhd) % weights for Floater-Hormann interpolation
        w = zeros(1,n+1);
        for l = 0:n
            ji = max(l-fhd,0);
            jf = min(l,n-fhd);
            sumcoeff = zeros(jf-ji+1,1);
            for i=ji:jf
                sumcoeff(i-ji+1) = nchoosek(fhd,l-i);
            end
            w(l+1) = (-1)^(l-fhd)*sum(sumcoeff);
        end
    end

end % chebsnake()

Contact us