Finish 2010-11-17 12:00:00 UTC

first try, tuned a little

by Michael Bindschadler

Status: Passed
Results: 48119 (cyc: 24, node: 1088)
CPU Time: 1.257
Score: 9638.9
Submitted at: 2010-11-11 07:16:14 UTC
Scored at: 2010-11-11 07:21:15 UTC

Current Rank: 2250th (Highest: 6th )

Comments
Michael Bindschadler
11 Nov 2010
does pretty well on most boards, fails horrifically on some :)
Please login or create a profile.
Code
function [thrustRow, thrustCol,loc,v] = solver(chart, aIndex, bIndex, maxThrottle)
% First try
rwind = chart(:,:,1);
cwind = chart(:,:,2);
[nr,nc] = size(rwind);
[ar,ac] = ind2sub([nr,nc],aIndex);
[br,bc] = ind2sub([nr,nc],bIndex);

thrustRow = [];
thrustCol = [];
loc = [ar,ac];
v = [0,0];
iter = 1;

cur_r = ar;
cur_c = ac;
cur_pos = [ar,ac];
cur_vr = 0; %rwind(aIndex);
cur_vc = 0; %cwind(aIndex);
curV = [cur_vr,cur_vc];
cur_goal = [br,bc];

% Target cruising speed
target_speed = maxThrottle*.5;

keepgoing = true;
reached_B = false;


while keepgoing
       
    % Find the direction to current goal
    d = cur_goal-cur_pos;
    
    % Update current velocity with local winds
    cur_vr = cur_vr+rwind(cur_r,cur_c);
    cur_vc = cur_vc+cwind(cur_r,cur_c);
    curV =[cur_vr,cur_vc];
    
    % Are we within striking distance?
    if sum(abs(d))<maxThrottle
        getting_close = true;
    else
        getting_close = false;
    end
    
    % Decide on thrust inputs
    % If current velocity is good enough, then don't do anything
    
    % Find angle between current velocity and desired direction
    thetad = acosd(dot(d,curV)/norm(d)/norm(curV));
    
    theta_thresh = 30; % within 30 degrees is good enough
    
    if sum(abs(curV))>maxThrottle
        too_fast = true;
    else
        too_fast = false;
    end
    
   if thetad<theta_thresh && ~getting_close && ~too_fast
       % don't do anything
       cur_tr = 0;
       cur_tc = 0;
   else
       % Adjust direction by thrusting more towards where we want to go
       d_u = d/norm(d); % unit vector in the direction we want to go
       
       if ~getting_close
           % Multiply by desired target speed
           perfect_v = round(d_u*target_speed);
       elseif getting_close
           % perfect speed gets us there exactly
           perfect_v = d;
       end
           
       % Can we get there?
       Vdiff = perfect_v-curV;
       
       if sum(abs(Vdiff))<maxThrottle
           % Just do it!
           cur_tr = Vdiff(1);
           cur_tc = Vdiff(2);
       else
           % Come as close as you can
           Vdiff_scaled = round(Vdiff/sum(abs(Vdiff))*maxThrottle);
           if sum(abs(Vdiff_scaled))>maxThrottle
               % this happens when two .5s both get rounded up
               % randomly reduce one of these by 1
               [dum,ind] = max(rand(1,2));
               Vdiff_scaled(ind) = sign(Vdiff_scaled(ind))*(abs(Vdiff_scaled(ind))-1);
           end
           cur_tr = Vdiff_scaled(1);
           cur_tc = Vdiff_scaled(2);
       end
       
   end
   
%    if abs(cur_tr)+abs(cur_tc)>maxThrottle
%        keyboard;
%    end
       %it's almost certainly worth it to look around the local area we'll
       %end up in to see if there's a 'best' landing spot. Future versions
     
    
    % update position
    next_r = cur_r + cur_vr + cur_tr; % local wind already included in cur_vr
    next_c = cur_c + cur_vc + cur_tc; % local wind already included in cur_vc
    %fprintf('  %4d %4d  %4d %4d  %4d %4d  %4d %4d\n',rwind(cur_r,cur_c),cwind(cur_r,cur_c),cur_tr,cur_tc,cur_vr+cur_tr,cur_vc+cur_tc,next_r,next_c);
    
    off_board_flags = [next_r<1, next_r>nr, next_c<1, next_c>nc];
    off_board_dirs = {'top','bot','left','right'};
    
    % Are we off the board?
    if any(off_board_flags)
        % Uh-oh, we're going off the board, can we save it?
        if sum(off_board_flags)==1
            % we're only off one border
            available_thrust = maxThrottle-sum(abs([cur_tr,cur_tc]));
            % how far off are we?
            switch off_board_dirs{off_board_flags}
                case 'top'
                    % need more positive row thrust to stay on
                    dist_off = 1-next_r;
                    cur_tr = cur_tr+dist_off;
                    % change column thrust if necessary
                    thrustCol_change = max(dist_off-available_thrust,0);
                    cur_tc = sign(cur_tc)*(abs(cur_tc)-thrustCol_change);
                case 'bot'
                    % need more negative row thrust to stay on
                    dist_off = next_r-nr;
                    cur_tr = cur_tr-dist_off;
                    thrustCol_change = max(dist_off-available_thrust,0);
                    cur_tc = sign(cur_tc)*(abs(cur_tc)-thrustCol_change);
                case 'left'
                    dist_off = 1-next_c;
                    cur_tc = cur_tc+dist_off;
                    thrustRow_change = max(dist_off-available_thrust,0);
                    cur_tr = sign(cur_tr)*(abs(cur_tr)-thrustRow_change);
                
                case 'right'
                    dist_off = next_c-nc;
                    cur_tc = cur_tc-dist_off;
                    thrustRow_change = max(dist_off-available_thrust,0);
                    cur_tr = sign(cur_tr)*(abs(cur_tr)-thrustRow_change);
            end
            if abs(cur_tr)+abs(cur_tc)>maxThrottle
                % This means we're NOT going to make it
%%%                disp('GIVING UP NOW');
                break
%                keyboard;
            end
            
        else
            % we've sailed off a corner
%%%            disp('OFF A CORNER');
            %keyboard
        end
        next_r = cur_r + cur_vr + cur_tr;
        next_c = cur_c + cur_vc + cur_tc; % local wind already included in cur_vc
        new_off_board_flags = [next_r<1, next_r>nr, next_c<1, next_c>nc];
        %keyboard
        if any(new_off_board_flags)
            % we're pretty screwed, just give up, we're probably pretty
            % close to the goal anyway :)
%%%            disp('GIVING UP NOW');
            break
        end
    end
    
    
    loc(iter,:) = [cur_r,cur_c];
    % update position
    cur_r = next_r;
    cur_c = next_c;
    cur_pos = [cur_r,cur_c];
        
    
    % Update velocity
    cur_vr = cur_vr + cur_tr; %local wind already included
    cur_vc = cur_vc + cur_tc;
    curV = [cur_vr,cur_vc];
    v(iter+1,:) = curV;
    
    thrustRow(iter) = cur_tr;
    thrustCol(iter) = cur_tc;
    
    % are we to the current goal?
    if isequal(cur_pos,cur_goal)
        % are we back to point A
        if isequal(cur_pos,[ar,ac])
            %then we're done
            keepgoing = false;
        else %we must be at B
            % change the current goal to point A
            cur_goal = [ar,ac];
            reached_B = true;
            reached_B_iter = iter;
        end
    end
    
    % Are we in a loop?
    if reached_B
        % only consider locations in iterations since then
        dup_inds = find(loc(reached_B_iter:end-1,1)==cur_r & loc(reached_B_iter:end-1,2)==cur_c);
        if length(dup_inds)>=2
            % identify the cycle of locations
            inds_to_consider = (dup_inds(1)+reached_B_iter-1):(size(loc,1)-1);
            locs_to_consider = loc(inds_to_consider,:);
            % find the one closest to point A
            dist2_to_A = (locs_to_consider(:,1)-ar).^2+(locs_to_consider(:,2)-bc).^2;
            [dum,min_ind] = min(dist2_to_A);
            closest_loc_ind = inds_to_consider(min_ind);
            % declare that as close as we'll ever get to A and quit moving
            % truncate everything back to that point
            %keyboard
            iter = closest_loc_ind;
            loc(iter+1:end,:) = [];
            thrustRow(iter:end) = [];
            thrustCol(iter:end) = [];
            v(iter+2:end,:) = [];
            break

            
        end
        
    else
        % consider all locations up to now
        dup_inds = find(loc(1:end-1,1)==cur_r & loc(1:end-1,2)==cur_c);
        % If we've been here twice before, this is probably a loop
        if length(dup_inds)>=2
            % identify the cycle of locations
            inds_to_consider = dup_inds(1):(size(loc,1)-1);
            locs_to_consider = loc(inds_to_consider,:);
            % find the one closest to point B
            dist2_to_B = (locs_to_consider(:,1)-br).^2+(locs_to_consider(:,2)-bc).^2;
            [dum,min_ind] = min(dist2_to_B);
            closest_loc_ind = inds_to_consider(min_ind);
            % declare that one as close as we'll ever get to B, and change
            % goals
            reached_B = true;
            reached_B_iter = closest_loc_ind;
            % truncate everything back to this point in time, adjust iter,
            % and continue from there
            %keyboard
            iter = closest_loc_ind;
            loc(iter+1:end,:) = [];
            thrustRow(iter+1:end) = [];
            thrustCol(iter+1:end) = [];
            v(iter+2:end,:) = [];
            cur_r = loc(end,1);
            cur_c = loc(end,2);
            cur_vr = v(end,1);
            cur_vc = v(end,2);
            

        end
            
       
    end
    
    iter = iter+1;
    %disp(cur_pos)
end
%disp('-------------------------------------')
end