% 1st generation pokémon catch rate analysis
% quelle: https://bulbapedia.bulbagarden.net/wiki/Catch_rate

% some pokemon data:
% pikachu:
% Max HP range: 95 - 142 @ lv50,
% catch rate: 190

% pantimos:
% Max HP range: 100 - 147 @ lv50,
% catch rate: 45

clear; clc; clf
hold on

% compare catch rates with different ball types
% consider a pokemon with 132 max hp, catch rate 45:
[hp_percents, catch_rates] = simulate_catch_rates(10000, 1, 132, 45, 0);
plot(hp_percents, catch_rates)

[hp_percents, catch_rates] = simulate_catch_rates(10000, 2, 132, 45, 0);
plot(hp_percents, catch_rates)

[hp_percents, catch_rates] = simulate_catch_rates(10000, 3, 132, 45, 0);
plot(hp_percents, catch_rates)

[hp_percents, catch_rates] = simulate_catch_rates(10000, 4, 132, 45, 0);
plot(hp_percents, catch_rates)

xlabel("HP Pokemon in %")
ylabel("Ratio of caught pokemon (approx. for catch rate)")
legend("poke ball", "great ball", "ultra ball", "master ball")


function [hp_percents, catch_rates] = simulate_catch_rates(num_simulations, ball_type, hp_max, catch_rate, status_code)
   hp_vec = 1:hp_max;
   catch_rates = zeros(1, hp_max);
   
   for hp_current=hp_vec
       num_caught = 0;
       for round=1:num_simulations
           num_caught = num_caught + simulate_throw(ball_type, hp_max, hp_current, catch_rate, status_code);
       end
       catch_rates(hp_current) = num_caught / num_simulations;
   end
   hp_percents = hp_vec / hp_max * 100;
end

% ball types: 
% 1 -> poke ball 
% 2 -> great ball 
% 3 -> ultra ball 
% 4 -> master ball

% status codes
% 0 -> normal
% 12 -> paralyzed or burned or poisoned
% 25 -> asleep or frozen

function result = simulate_throw(ball_type, hp_max, hp_current, catch_rate, status_code)
    if ball_type == 4
        result = 1;
        return
    elseif ball_type == 3
        N_max = 150;
    elseif ball_type == 2
        N_max = 200;
    else
        N_max = 255;
    end
    N = randi([0 N_max]);
    
    if N < status_code
        result = 1;
        return
    end
    
    if N - status_code > catch_rate
        result = 0;
        return
    end
    
    M = randi([0 255]);
    if ball_type == 2
        ball = 8;
    else
        ball = 12;
    end
    f = floor((hp_max * 255 * 4) / (hp_current * ball));
    if f >= M
        result = 1;
    else
        result = 0;
    end
end