ID:50297
Title:the_wave2
Author:Kristian Lindqvist
Date:2008-11-07 12:56:51
Score:21410.5204
Result:20768.52 (cyc: 26, node: 1116)
CPU Time:131.1023
Status:Passed
Comments:
Based on:none
Code:
function [dRow,dCol,action,mark] = solver(mainMap,foodMap,myAntMap,opAntMap, ...
    myScentMap,opScentMap,myDeathMap,opDeathMap)

% constant with all possible moves
moves = [1,0; 1,1; 0,1; -1,1; -1,0; -1,-1; 0,-1;1,-1];
% matrix masks to mask out the moves


% use the scent map and add farms as sweet spots
myScentMap = myScentMap + (mainMap==1)*100;


% main mode decisions,
% is init?
init = ~any(any(myScentMap(2:4,2:4) > 0)) && ~any(any(mainMap==1));
% is missing or not (when missing, leave a small trace behind)
missing = ~any(any( myScentMap > 5 )) && any( any( myScentMap(2:4,2:4) > 0 ) );
% main movement decisions:
% * has food or not,
% * exist any food near
% use propabilites to avoid "mass psychosis"
has_food  = (mainMap(3,3)~= 1) && (rand < foodMap(3,3) / myAntMap(3,3));
food_near = rand < sum( sum( foodMap.*(mainMap~=1) ))/sum(sum(myAntMap));

% carry if you have it!
if has_food ,
    action = 1;
else
    action = -1;
end

% initialize movement to random with possible defence
moveIdx = randomMove(moves);
mark = calculateMark( myScentMap , myAntMap, mainMap, moves);

if init
    % use the random walk, mark up for next
    mark = 2;
    
elseif missing % missing strategy
    
    % simple strategy, leave a trace behind, continue in the same direction
    % get food if there is any
    mark = 1;
    if ~has_food && food_near
        % go get some food
        [rowIdx,colIdx] = find( foodMap > 0 );
        randIdx = ceil( length(rowIdx)*rand );
        moveIdx = goTo( rowIdx(randIdx) , colIdx(randIdx) , moves);
    else
        if has_food && any(any(mainMap==1))
            moveIdx = goHome( mainMap , myScentMap , moves);
        else
            % has food or no food anywhere, keep moving in same direction
            for idx = 1:length( moves )
                if myScentMap( 3+moves(idx,1),3+moves(idx,2) )
                    moveIdx =idx + 4; % hard-coded!!
                    if moveIdx >length(moves), moveIdx = moveIdx-length(moves); end
                    break;
                end
            end
        end
    end
    
else % not_missing strategy
    
    if has_food
        % go back
        moveIdx = goHome( mainMap , myScentMap , moves);
    elseif food_near
        % go get some food
        [rowIdx,colIdx] = find( foodMap > 0 );
        randIdx = ceil( length(rowIdx)*rand );
        moveIdx = goTo( rowIdx(randIdx) , colIdx(randIdx) , moves);
    else
        % no food near, go further away
        moveIdx = goAway( mainMap , myScentMap , moves);
    end
    
end

if myScentMap < 3
    mark = max(2,mark); % never have a single ant mark with less than 1
end
if mainMap(3,3) == 1
    mark = 0; % no need to mark up here
end
% take out the movement index to row,col
dRow = moves(moveIdx,1);
dCol = moves(moveIdx,2);

% check the validity, random move if move is in a wall
for idx = 1:10
    if ~isnan(mainMap(3+dRow,3+dCol))
        break;
    end
    
    dRow = round(rand*2) - 1;
    dCol = round(rand*2) - 1;
end

if ( ~has_food && any(any(mainMap==1))) || (rand < 0.2)
    dRow = round(rand*2) - 1;
    dCol = round(rand*2) - 1;
end    

% defence!!
% if any ant may come within your, stay and fight to 95 %
% allow some probability to move just to not lock up
if opAntMap(3,3) > 0 || ...
        ( any(any(opAntMap(2:4,2:4) > 0)) && ( rand() < 0.95 ) )
    dRow = 0;
    dCol = 0;
    action = -1;
end


end



function idx = randomMove( moves )
% select a random move along the valid
idx = ceil( length(moves)*rand() );
end

function idx = goTo(row,col,moves)
dRow = min(1,max(-1,row(1)-3));
dCol = min(1,max(-1,col(1)-3));
idx = find( moves(:,1) == dRow & moves(:,2) == dCol );
end

function mark = calculateMark(myScentMap, myAntMap, mainMap, moves)
cornerMask1 = zeros(5,5);
cornerMask1(2:3,2) = 1; cornerMask1(2,3) = 1;
cornerMask2 = fliplr( cornerMask1 );
cornerMask3 = flipud( cornerMask1 );
cornerMask4 = flipud( cornerMask2 );

innerMask = zeros(5,5);
innerMask(2:4,2:4) = 1;
innerMask(3,3) = 0;
% marking strategy:
% 1. avoid getting stuck between farms
if sum( sum( mainMap == 1 )) > 1
    mark = sum( sum( myScentMap ) );
    
    
% 2. general routine
else
    % get the proper mark value for this location
    % mark = 0;
    maxVal  = 0; 
    maxVal2 = 0; 
    for idx = 1:length( moves )
        tmpVal = myScentMap(3+moves(idx,1),3+moves(idx,2));
        maxVal = max( maxVal,tmpVal );
        if ~isnan( mainMap(3+moves(idx,1),3+moves(idx,2)) )
            tmpVal = myScentMap(3+2*moves(idx,1),3+2*moves(idx,2));
            maxVal2 = max( maxVal2,tmpVal );
        end            
    end
    if maxVal == 0 
        maxVal = maxVal2; 
    end
        
    mark = (maxVal-1); 
    %    for idx = 1:length( moves )
    %        mark = mark + myScentMap( 3+moves(idx,1), 3+moves(idx,2) );
    %    end
    %   mark = mark/length(moves);
end

% common routine for strategy
mark = mark - myScentMap(3,3); % subtract for scent already present
mark = mark/myAntMap(3,3); % divide between the ants at location
% if rand < ( mark-floor(mark) )
%     mark = ceil( mark );
% else
%     mark = floor( mark );
% end
mark = floor( mark );
end

function moveIdx = goAway( mainMap , myScentMap , moves)
% get the best movement index away from home
%randomIdx = ceil( length(moves)*rand(length(moves),1) );
randomIdx = 1:length(moves);
score = zeros( length(moves) , 1);
for k = 1:length(randomIdx)
    idx = randomIdx(k);
    score(idx) = myScentMap(3,3) - myScentMap(3+moves(idx,1),3+moves(idx,2));
    % useless score for moves into a wall or where there's no scent
    if isnan( mainMap(3+moves(idx,1),3+moves(idx,2)) )
        score(idx) = -10000;
    end
end
% get the maximum value
idx = find(score == max(score));
moveIdx = randomIdx(idx(1));
end

function moveIdx = goHome( mainMap , myScentMap , moves)
% if farm insight go to it
if any( any( mainMap == 1 ) )
    [rowIdx,colIdx] = find( mainMap == 1 );
    moveIdx = goTo( rowIdx(1), colIdx(1) ,moves);
    if isempty( moveIdx )
        moveIdx = goTo( rowIdx(1) , 0 , moves);
    end
else
    
    % get the best valid movement index uphill
    %randomIdx = ceil( length(moves)*rand(length(moves),1) );
    randomIdx = 1:length( moves );
    score = zeros( length( moves) ,1);
    for k = 1:length(randomIdx)
        idx = randomIdx(k);
        score(idx)   =  myScentMap(3+moves(idx,1),3+moves(idx,2));
        if ~isnan( mainMap(3+moves(idx,1),3+moves(idx,2)) )
            score(idx) = max( score(idx) , ...
                myScentMap(3+moves(idx,1),3+moves(idx,2)) );
        end
        % moves into a wall are easy lot negative...
        if isnan( mainMap(3+moves(idx,1),3+moves(idx,2)) )
            score(idx) = -10000;
        end        
    end
    % get the maximum value
    idx = find(score == max(score));
    moveIdx = randomIdx(idx(1));
end
end