clear
clf

load('MyColormaps','mycmap') % load custom colormap
A = ones(15);
T = ones(15);
T = 10*T; % temperature 10 everywhere in map

% make the map
A(1,1:7.5) = 0;
A(1,8.5:15) = 0;
A(:,1) = 0;
A(15,1:7.5) = 0;
A(15,8.5:15) = 0;
A(:,15) = 0;
A(3,13) = 0;
A(5:6,13) = 0;
A(13,13) = 0;
A(10:11,13) = 0;
A(8,13:15) = 0;
A(3,11) = 0;
A(13,11) = 0;
A(5,9:11) = 0;
A(7:9,11) = 0;
A(11,9:11) = 0;
A(1:3,9) = 0;
A(13:15,9) = 0;
A(1:3,7) = 0;
A(13:15,7) = 0;
A(5,6:7) = 0;
A(11,6:7) = 0;
A(7:9,6) = 0;
A(8,5) = 0;
A(5:6,3:4) = 0;
A(10:11,3:4) = 0;
A(3,3:5) = 0;
A(13,3:5) = 0;
A(8,3) = 0;
A(7,8:9) = 0;
A(9,8:9) = 0;
A(8,8) = 0;

time = 0;

for iter = 1
    % start pacman at 8,4
	xP = 8; 
	yP = 4; 
    % start blinky at 8,12
    xB = 8;
    yB = 12;
    % start pinky at 6,10
    xK = 6;
    yK = 10;
    % start inky at 10,10
    xI = 10;
    yI = 10;
    % start clyde at 8,9
    xC = 8;
    yC = 10;

    while 1
        
        xOldP = xP; %store current x and y values
        yOldP = yP;
        
        xOldB = xB;
        yOldB = yB;
        
        xOldK = xK;
        yOldK = yK;
        
        xOldI = xI;
        yOldI = yI;
        
        xOldC = xC;
        yOldC = yC;
        
        time = time+1;
        
        % initial temperature conditions, pacman is hot, ghosts are cold
        T(xOldP,yOldP) = 30; 
        T(xOldB,yOldB) = 0;
        T(xOldK,yOldK) = 0;
        T(xOldI,yOldI) = 0;
        T(xOldC,yOldC) = 0;
        
%         ghosts travel with random motion, determine which direction to turn to
        
        s = rand();
        if (s <= .25)
            xB = xOldB+1;
        elseif (s > .25 && s <= .50)
            xB = xOldB-1;
        elseif (s > .50 && s <= .75)
            yB = yOldB+1;
        elseif (s > .75 && s <= 1)
            yB = yOldB-1;
        end
        
        t = rand();
        if (t <= .25)
            xK = xOldK+1;
        elseif (t > .25 && t <= .50)
            xK = xOldK-1;
        elseif (t > .50 && t <= .75)
            yK = yOldK+1;
        elseif (t > .75 && t <= 1)
            yK = yOldK-1;
        end
        
        u = rand();
        if (u <= .25)
            xI = xOldI+1;
        elseif (u > .25 && u <= .50)
            xI = xOldI-1;
        elseif (u > .50 && u <= .75)
            yI = yOldI+1;
        elseif (u > .75 && u <= 1)
            yI = yOldI-1;
        end
        
        v = rand();
        if (v <= .25)
            xC = xOldC+1;
        elseif (v > .25 && v <= .50)
            xC = xOldC-1;
        elseif (v > .50 && v <= .75)
            yC = yOldC+1;
        elseif (v > .75 && v <= 1)
            yC = yOldC-1;
        end
        
        % boundary conditions: if pacman/ghost moves in the "pipe" at y = 8, he
        % re-appears at the other end
        
        if xB < 1
            xB = 15;
        elseif xB > 15
            xB = 1;
        end
        
        if xK < 1
            xK = 15;
        elseif xK > 15
            xK = 1;
        end
        
        if xI < 1
            xI = 15;
        elseif xI > 15
            xI = 1;
        end
        
        if xC < 1
            xC = 15;
        elseif xC > 15
            xC = 1;
        end
        
        if (A(xP,yP)==0)
            xP=xOldP;
            yP=yOldP;
            A(xP,yP) = .17; % if he goes into a wall, start over
        end
               
        % spaces where pacman is surrounded by 2 or more walls are
        % problematic, fix this by altering his motion if he's in one of
        % the spaces
        
        if ((xOldP+1)==0) && ((xOldP-1)==0) % if walls to the right and left, move up or down
            f = rand();
            if (f <= .5)
                yP = yOldP+1;
            elseif (f > .5)
                yP = yOldP-1;
            end
        elseif ((xOldP+1)==0) && ((yOldP+1==0)) % if walls to right and above, move left or down
            f = rand();
            if (f <= .5)
                xP = xOldP-1;
            elseif (f > .5)
                yP = yOldP-1;
            end
        elseif ((xOldP+1)==0) && ((yOldP-1)==0) % if walls to right and below, move left or up
            f = rand();
            if (f <= .5)
                xP = xOldP-1;
            elseif (f > .5)
                yP = yOldP+1;
            end
        elseif ((xOldP-1)==0) && ((yOldP+1)==0) % if walls to left and above, move right or down
            f = rand();
            if (f <= .5)
                xP = xOldP+1;
            elseif (f > .5)
                yP = yOldP-1;
            end
        elseif ((xOldP-1)==0) && ((yOldP-1)==0) % if walls to left and below, move right or up
            f = rand();
            if (f <= .5)
                xP = xOldP+1;
            elseif (f > .5)
                yP = yOldP+1;
            end
        elseif ((yOldP+1)==0) && ((yOldP-1)==0) % if walls above and below, move right or left
            f = rand();
            if (f <= .5)
                xP = xOldP+1;
            elseif (f > .5)
                xP = xOldP-1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
        elseif ((xOldP+1)==0) && ((xOldP-1)==0) && ((yOldP-1)==0) % if walls to right, left and below, move up (only one spot on map)
            yP = yOldP+1;
        end
        
        % when a ghost is close to pacman, he avoids the ghost. motion is
        % adjusted such that pacman avoids going directly towards a ghost
        
        if (((xB-xOldP)<=2) && ((yB-yOldP)==0)) || (((xK-xOldP)<=2) && ((yK-yOldP)==0)) || (((xI-xOldP)<=2) && ((yI-yOldP)==0)) || (((xC-xOldP)==2) && ((yC-yOldP)==0)) % if a ghost is close to pacman from right, move left, down or up
            g = rand();
            if (g <= .5)
                xP = xOldP-1;
            elseif ((g > .5) && (g <= .75))
                yP = yOldP-1;
            elseif ((g > .75) && (g <= 1))
                yP = yOldP+1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end                 
        elseif (((xB-xOldP)==0) && ((yOldP-yB)<=2)) || (((xK-xOldP)==0) && ((yOldP-yK)<=2)) || (((xI-xOldP)==0) && ((yOldP-yI)<=2)) || (((xC-xOldP)==0) && ((yOldP-yC)<=2)) % if a ghost is close to pacman from below, move up, right or left
            g = rand();
            if (g <= .5)
                yP = yOldP+1;
            elseif ((g > .5) && (g <= .75))
                xP = xOldP-1;
            elseif ((g > .75) && (g <= 1))
                xP = xOldP+1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end            
        elseif (((xOldP-xB)==0) && ((yB-yOldP)<=2)) || (((xOldP-xK)==0) && ((yK-yOldP)<=2)) || (((xOldP-xI)==0) && ((yI-yOldP)<=2)) || (((xOldP-xC)==0) && ((yC-yOldP)<=2)) % if a ghost is close to pacman from above, move down, right or left
            g = rand();
            if (g <= .5)
                yP = yOldP-1;
            elseif ((g > .5) && (g <= .75))
                xP = xOldP-1;
            elseif ((g > .75) && (g <= 1))
                xP = xOldP+1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end            
        elseif (((xOldP-xB)<=2) && ((yOldP-yB)==0)) || (((xOldP-xK)<=2) && ((yOldP-yK)==0)) || (((xOldP-xI)<=2) && ((yOldP-yI)==0)) || (((xOldP-xC)<=2) && ((yOldP-yC)==0)) % if a ghost is close to pacman from left, move right, up or down
            g = rand();
            if (g <= .5)
                xP = xOldP+1;
            elseif ((g > .5) && (g <= .75))
                yP = yOldP-1;
            elseif ((g > .75) && (g <= 1))
                yP = yOldP+1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end    
        elseif (((xB-xOldP)<=2) && ((yB-yOldP)<=2)) || (((xK-xOldP)<=2) && ((yK-yOldP)<=2)) || (((xI-xOldP)<=2) && ((yI-yOldP)<=2)) || (((xC-xOldP)<=2) && ((yC-yOldP)<=2)) % if a ghost is close to pacman towards quadrant 1, move left or down
            g = rand();
            if (g <= .5)
                xP = xOldP-1;
            else
                yP = yOldP-1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end 
        elseif (((xB-xOldP)<=2) && ((yOldP-yB)<=2)) || (((xK-xOldP)<=2) && ((yOldP-yK)<=2)) || (((xI-xOldP)<=2) && ((yOldP-yI)<=2)) || (((xC-xOldP)<=2) && ((yOldP-yC)<=2)) % if a ghost is close to pacman towards quadrant 4, move left or up
            g = rand();
            if (g <= .5)
                xP = xOldP-1;
            else
                yP = yOldP+1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end
        elseif (((xOldP-xB)<=2) && ((yB-yOldP)<=2)) || (((xOldP-xK)<=2) && ((yK-yOldP)<=2)) || (((xOldP-xI)<=2) && ((yI-yOldP)<=2)) || (((xOldP-xC)<=2) && ((yC-yOldP)<=2)) % if a ghost is close to pacman towards quadrant 2, move right or down
            g = rand();
            if (g <= .5)
                xP = xOldP+1;
            else
                yP = yOldP-1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end
        elseif (((xOldP-xB)<=2) && ((yOldP-yB)<=2)) || (((xOldP-xK)<=2) && ((yOldP-yK)<=2)) || (((xOldP-xI)<=2) && ((yOldP-yI)<=2)) || (((xOldP-xC)<=2) && ((yOldP-yC)<=2)) % if a ghost is close to pacman towards quadrant 3, move right or up
            g = rand();
            if (g <= .5)
                xP = xOldP+1;
            else
                yP = yOldP+1;
            end
            if xP == 0
                xP = 15;
            elseif xP == 16
                xP = 1;
            end
            if (A(xP,yP)==0)
                xP=xOldP;
                yP=yOldP;
                A(xP,yP) = .17; % if he goes into a wall, start over
            end

        end
        
        % set old position to white, set new position to yellow to show
        % that pacman has moved
        
        A(xOldP,yOldP) = 1;
        A(xP,yP) = .17;
        
        % random motion of ghosts
        
        if (A(xB,yB)==0) || (A(xB,yB)==.33) || (A(xB,yB)==.67) || (A(xB,yB)==.83)
            xB=xOldB;
            yB=yOldB;
            A(xOldB,yOldB) = .5; % if he goes into a wall or collides w/another ghost, start over
        else
            A(xOldB,yOldB) = 1; % reset original position back to white
            A(xB,yB) = .5; 
        end
        
        if (A(xK,yK)==0) || (A(xK,yK)==.33) || (A(xK,yK)==.5) || (A(xK,yK)==.83)
            xK=xOldK;
            yK=yOldK;
            A(xOldK,yOldK) = .67; % if he goes into a wall or collides w/another ghost, start over
        else
            A(xOldK,yOldK) = 1; % reset original position back to white
            A(xK,yK) = .67; 
        end
        
        if (A(xI,yI)==0) || (A(xI,yI)==.33) || (A(xI,yI)==.5) || (A(xI,yI)==.67)
            xI=xOldI;
            yI=yOldI;
            A(xOldI,yOldI) = .83; % if he goes into a wall or collides w/another ghost, start over
        else
            A(xOldI,yOldI) = 1; % reset original position back to white
            A(xI,yI) = .83; 
        end
        
        if (A(xC,yC)==0) || (A(xC,yC)==.5) || (A(xC,yC)==.67) || (A(xC,yC)==.83)
            xC=xOldC;
            yC=yOldC;
            A(xOldC,yOldC) = .33; % if he goes into a wall, start over
        else
            A(xOldC,yOldC) = 1; % reset original position back to 0
            A(xC,yC) = .33; 
        end
        
        % tests to see if pacman collides with ghost, ends simulation if he
        % does
        
        if xP == xB && yP == yB 
            break;
        end
        
        if xP == xK && yP == yK
            break;
        end
        
        if xP == xI && yP == yI
            break;
        end
        
        if xP == xC && yP == yC
            break;
        end
        
        
        if mod((time/3),1) == 0
            subplot(1,2,1)
            imagesc(A');
            set(gca,'YDir','normal');
            colormap(mycmap);
            axis equal;
            axis tight;
            drawnow 
            freezeColors % function that allows me to use 2 different colormaps in a subplot, credit to John Iversen: http://www.mathworks.com/matlabcentral/fileexchange/7943
        end

        for i = 2:14
            for j = 2:14
                T(i,j) = (.25*(T(i+1,j)+T(i-1,j)+T(i,j+1)+T(i,j-1)-4*T(i,j)))-(.05*(T(i+1,j)+T(i,j+1)-2*T(i,j)))+T(i,j); % update T immediately, diffusion-convection equation
                T(:,1) = 10; % temperature always 10 at boundaries, even if pac-man/ghosts are there
                T(:,15) = 10;
                T(1,:) = 10;
                T(15,:) = 10;
            end
        end
        
        if mod((time/2),1)==0
            subplot(1,2,2)
            colormap jet
            xx = 1:15;
            yy = 1:15;
            [X,Y] = meshgrid(yy,xx);
            surf(X,Y,T);
            axis([1 15 1 15 0 20])
            view([-100 50]);
            axis square
            freezeColors
            saveas(gcf,['pacman',sprintf('%03d',time/3),'.png'])
            pause(.02)
        end
 
    end
end
