| 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
|