Skip to content

Instantly share code, notes, and snippets.

@tscmoo
Created March 14, 2020 09:15
Show Gist options
  • Save tscmoo/f10446517515828828b0a188ca3911a2 to your computer and use it in GitHub Desktop.
Save tscmoo/f10446517515828828b0a188ca3911a2 to your computer and use it in GitHub Desktop.
#include <cstdio>
#include <random>
#include "openbw/bwgame.h"
#include "openbw/actions.h"
int main() {
std::mt19937 rng(std::random_device{}());
try {
bwgame::game_player player(".");
auto& st = player.st();
//player.load_map_file();
bwgame::game_load_functions game_funcs(st);
game_funcs.load_map_file("maps/(4)Fighting Spirit.scx", [&]() {
game_funcs.setup_info.starting_units = true;
game_funcs.setup_info.create_no_units = true;
st.players[0].controller = bwgame::player_t::controller_occupied;
st.players[1].controller = bwgame::player_t::controller_occupied;
st.lcg_rand_state = rng();
});
bwgame::action_state action_st;
bwgame::action_functions funcs(st, action_st);
bwgame::xy pos = funcs.map_bounds().to / 2;
auto test = [&](bool aensnared, bool bensnared) {
int awins = 0;
int bwins = 0;
for (int i = 0; i != 100; ++i) {
auto* a = funcs.trigger_create_unit(funcs.get_unit_type(bwgame::UnitTypes::Zerg_Ultralisk), pos, 0);
auto* b = funcs.trigger_create_unit(funcs.get_unit_type(bwgame::UnitTypes::Zerg_Ultralisk), pos, 1);
if (!a || !b) {
throw std::runtime_error("Failed to spawn");
}
a->heading = funcs.xy_direction(b->position - a->position);
b->heading = funcs.xy_direction(a->position - b->position);
funcs.action_select(0, a);
funcs.action_order(0, funcs.get_order_type(bwgame::Orders::AttackDefault), {}, b, nullptr, false);
funcs.action_select(1, b);
funcs.action_order(1, funcs.get_order_type(bwgame::Orders::AttackDefault), {}, a, nullptr, false);
if (aensnared) funcs.ensnare_unit(a);
if (bensnared) funcs.ensnare_unit(b);
int t = 0;
while (!funcs.unit_dead(a) && !funcs.unit_dead(b) && t < 1000) {
funcs.next_frame();
++t;
}
if (funcs.unit_dead(a)) {
//printf("dead ");
}
else {
//printf("% 4d ", a->hp.integer_part());
++awins;
}
if (funcs.unit_dead(b)) {//printf("dead ");
}
else {
//printf("% 4d ", b->hp.integer_part());
++bwins;
}
//printf(" in %d frames\n", t);
if (!funcs.unit_dead(a)) {
funcs.hide_unit(a);
funcs.kill_unit(a);
}
if (!funcs.unit_dead(b)) {
funcs.hide_unit(b);
funcs.kill_unit(b);
}
}
return std::make_pair(awins, bwins);
};
auto measure = [&](std::string title, bool ae, bool be) {
std::vector<float> results;
float sum = 0.0f;
for (int i = 0; i != 1000; ++i) {
auto result = test(ae, be);
float winrate = result.first / float(result.first + result.second);
sum += winrate;
results.push_back(winrate);
}
std::sort(results.begin(), results.end());
float min = *std::min_element(results.begin(), results.end());
float max = *std::max_element(results.begin(), results.end());
float avg = sum / results.size();
float variance = 0.0f;
for (float v : results) {
variance += (v - avg) * (v - avg) / results.size();
}
printf("\n\n -- %s -- \n\n", title.c_str());
printf("min: %g\n", min);
printf("max: %g\n", max);
printf("avg: %g\n", avg);
printf("med: %g [%g %g %g %g %g]\n", results.at(results.size() / 2), results.at(results.size() / 6), results.at(results.size() / 3), results.at(results.size() / 3 + results.size() / 6), results.at(results.size() / 3 + results.size() / 3), results.at(results.size() - results.size() / 6));
printf("stddev: %g variance: %g\n", std::sqrt(variance), variance);
};
measure("plain", false, false);
measure("a ensnared", true, false);
measure("b ensnared", false, true);
measure("both ensnared", true, true);
} catch (const std::exception& e) {
printf("exception %s\n", e.what());
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment