Skip to content

Instantly share code, notes, and snippets.

@iglesias
Last active June 16, 2024 20:30
Show Gist options
  • Select an option

  • Save iglesias/b5ac2e97f68a773fb8da1f81f675023d to your computer and use it in GitHub Desktop.

Select an option

Save iglesias/b5ac2e97f68a773fb8da1f81f675023d to your computer and use it in GitHub Desktop.
codeweekend.dev
def Settings( **kwargs ):
return {
'flags': [ '-x', 'c++', '-Wall', '-Wextra', '-Werror', '-std=c++23'],
}
#include <cmath>
#include <exception>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
constexpr auto squared(auto x) {
return x * x;
}
struct unimplemented : public std::exception {
private:
std::string message_;
public:
explicit unimplemented(std::string_view message) : message_(message) {}
const char* what() const noexcept override {
return message_.c_str();
}
};
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace {
struct hero {
int base_speed;
int base_power;
int base_range;
int level_speed_coeff;
int level_power_coeff;
int level_range_coeff;
};
[[maybe_unused]] void to_json(json& j, const hero& h) {
j = json{{"base_speed", h.base_speed}, {"base_power", h.base_power}, {"base_range", h.base_range},
{"level_speed_coeff", h.level_speed_coeff}, {"level_power_coeff", h.level_power_coeff},
{"level_range_coeff", h.level_range_coeff}};
}
[[maybe_unused]] void from_json(const json& j, hero& h) {
j.at("base_speed").get_to(h.base_speed);
j.at("base_power").get_to(h.base_power);
j.at("base_range").get_to(h.base_range);
j.at("level_speed_coeff").get_to(h.level_speed_coeff);
j.at("level_power_coeff").get_to(h.level_power_coeff);
j.at("level_range_coeff").get_to(h.level_range_coeff);
}
struct monster {
int x;
int y;
int hp;
int gold;
int exp;
};
[[maybe_unused]] void to_json(json& j, const monster& m) {
j = json{{"x", m.x}, {"y", m.y}, {"hp", m.hp}, {"gold", m.gold}, {"exp", m.exp}};
}
[[maybe_unused]] void from_json(const json& j, monster& m) {
j.at("x").get_to(m.x);
j.at("y").get_to(m.y);
j.at("hp").get_to(m.hp);
j.at("gold").get_to(m.gold);
j.at("exp").get_to(m.exp);
}
using monsters_t = std::vector<::monster>;
struct move {
std::string type;
int target_x, target_y;
};
[[maybe_unused]] void to_json(json& j, const move& m) {
j = json{{"type", m.type}, {"target_x", m.target_x}, {"target_y", m.target_y}};
}
[[maybe_unused]] void from_json(const json& j, move& m) {
j.at("type").get_to(m.type);
j.at("target_x").get_to(m.target_x);
j.at("target_y").get_to(m.target_y);
}
struct attack {
std::string type;
int target_id;
};
[[maybe_unused]] void to_json(json& j, const attack& a) {
j = json{{"type", a.type}, {"target_id", a.target_id}};
}
[[maybe_unused]] void from_json(const json& j, attack& a) {
j.at("type").get_to(a.type);
j.at("target_id").get_to(a.target_id);
}
[[maybe_unused]] void to_json(json& j, const std::variant<move, attack>& v) {
switch (v.index()) {
case 0:
j = {{"type", "move"},
{"target_x", std::get<move>(v).target_x},
{"target_y", std::get<move>(v).target_y}};
return;
case 1:
j = {{"type", "attack"}, {"target_id", std::get<attack>(v).target_id}};
return;
default:
throw std::runtime_error("Unexpected case in moves variant.");
}
}
struct moves_t {
using move_t = std::variant<move, attack>;
std::vector<move_t> moves;
void push_back(move_t&& move) { moves.push_back(move); };
};
[[maybe_unused]] void to_json(json& j, const moves_t& moves) {
j = {{"moves", moves.moves}};
}
} // anonymous
[[maybe_unused]] std::ostream& operator<<(std::ostream& os, const ::monster& m) {
os << "xxxxxxxxxxx\n"
<< "x (" << m.x << ", " << m.y << ")\n"
<< "x " << std::setw(4) << m.hp << " HP\n"
<< "x " << std::setw(4) << m.exp << " EXP\n"
<< "x " << std::setw(8) << m.gold << "g\n"
<< "xxxxxxxxxxx\n\n";
return os;
}
struct levelling_t {
int level;
int experience; // relative to each level
};
int find_closest_alive_monster_in_range(const int x, const int y, const ::hero& h,
const ::monsters_t& ms, const levelling_t& levelling) {
int closest_monster_id = -1, shortest_distance = 1000000000;
const int resulting_range = static_cast<int>(std::floor(
h.base_range * (1 + levelling.level * ((1. * h.level_range_coeff) / 100))));
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
const int d2 = squared(x - ms[i].x) + squared(y - ms[i].y);
if (d2 <= squared(resulting_range) and d2 < shortest_distance) {
closest_monster_id = i;
shortest_distance = d2;
}
}
return closest_monster_id;
}
[[maybe_unused]] int find_closest_alive_monster(const int x, const int y, const ::monsters_t ms) {
int closest_monster_id = -1, shortest_distance = 1000000000;
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
const int d2 = squared(x - ms[i].x) + squared(y - ms[i].y);
if (d2 < shortest_distance) {
closest_monster_id = i;
shortest_distance = d2;
}
}
return closest_monster_id;
}
[[maybe_unused]] int find_richest_alive_monster(const ::monsters_t ms) {
int richest_monster_id = -1, richest_value = 0;
for (int i = 1; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
if (ms[i].gold > richest_value) {
richest_monster_id = i;
richest_value = ms[i].gold;
}
}
if (richest_monster_id == -1) throw unimplemented("Hoped this wouldn't happen.");
return richest_monster_id;
}
[[maybe_unused]] int find_weakest_alive_monster(const ::monsters_t ms) {
int weakest_monster_id = -1, weakest_value = 1000000000;
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
if (ms[i].hp < weakest_value) {
weakest_monster_id = i;
weakest_value = ms[i].hp;
}
}
if (weakest_monster_id == -1) throw unimplemented("Hoped this wouldn't happen.");
return weakest_monster_id;
}
[[maybe_unused]] int find_expest_alive_monster(const ::monsters_t ms) {
int best_monster_id = -1, best_value = 0;
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
if (ms[i].exp > best_value) {
best_monster_id = i;
best_value = ms[i].exp;
}
}
if (best_monster_id == -1) throw unimplemented("Hoped this wouldn't happen.");
return best_monster_id;
}
int width;
int height;
bool within_bounds(int x, int y) {
return 0 <= x and x <= width and 0 <= y and y <= height;
}
void move_toward(int& x, int& y, const int x_g, const int y_g, const int resulting_speed) {
const double D = std::sqrt(squared(x_g - x) + squared(y_g - y));
if (resulting_speed >= D) {
x = x_g;
y = y_g;
return;
}
const double ux = resulting_speed * (x_g - x) / D, uy = resulting_speed * (y_g - y) / D;
///logging
///std::cout << " resulting_speed: " << resulting_speed << " D: " << D << '\n';
///
const int xf = static_cast<int>(std::round(x + ux)), yf = static_cast<int>(std::round(y + uy));
///logging
///std::cout << " (xf, yf): (" << xf << ", " << yf << ")\n";
///
if (squared(xf - x) + squared(yf - y) <= squared(resulting_speed) and within_bounds(xf, yf)) {
x = xf;
y = yf;
} else {
const std::vector<std::vector<int>> deltas{{-1, 0}, {+1, 0}, { 0, -1}, {0, +1},
{-1, -1}, {+1, -1}, {-1, +1}, {+1, +1}};;
const int init_x = x, init_y = y;
int scaling_x = 1, scaling_y = 1;
for(;;) {
bool found = false;
for (const std::vector<int>& delta : deltas) {
const int try_x = xf + scaling_x * delta[0], try_y = yf + scaling_y * delta[1];
if (squared(try_x - init_x) + squared(try_y - init_y) <= squared(resulting_speed) and
within_bounds(try_x, try_y)) {
if (found) {
if (squared(try_x - x_g) + squared(try_y - x_g) < squared(x - x_g) + squared(y - y_g)) {
x = try_x;
y = try_y;
}
} else {
found = true;
x = try_x;
y = try_y;
}
}
}
if (found) return;
if (scaling_x > scaling_y) scaling_y++;
else { assert(scaling_y == scaling_x); scaling_x++; }
}
}
}
std::variant<::move, ::attack> turn(int& x, int& y, const ::hero& h, ::monsters_t& ms, levelling_t& levelling) {
const int closest_monster_in_range_id = find_closest_alive_monster_in_range(x, y, h, ms, levelling);
static int turn_id = -1;
turn_id++;
if (closest_monster_in_range_id == -1) {
//FIXME efficiency this will iterate through monsters for a second time.
//const int monster_id = find_closest_alive_monster(x, y, ms);
//const int monster_id = find_weakest_alive_monster(ms);
const int monster_id = turn_id < 100 ? find_expest_alive_monster(ms) : find_richest_alive_monster(ms);
const ::monster& closest = ms.at(monster_id);
const int resulting_speed = static_cast<int>(std::floor(
h.base_speed * (1 + levelling.level * ((1. * h.level_speed_coeff) / 100))));
/// logging
std::cout << "Moving toward monster " << monster_id << " at " << closest.x << " " << closest.y
<< " from " << x << " " << y << "\n";
///
move_toward(x, y, closest.x, closest.y, resulting_speed);
return ::move("move", x, y);
} else {
/****** Attack the closest monster ******/
const int resulting_attack = static_cast<int>(std::floor(
h.base_power * (1 + levelling.level * ((1. * h.level_power_coeff) / 100))));
/// logging
std::cout << "Monster " << closest_monster_in_range_id << " with " << ms[closest_monster_in_range_id].hp
<< " HP takes " << resulting_attack << " damage from level " << levelling.level
<< " hero with " << levelling.experience << " EXP\n";
///
//FIXME remove death monsters, would probably need to store initial index of the monsters since
//when removing from the vector the initial order is lost.
ms.at(closest_monster_in_range_id).hp -= resulting_attack;
if (ms[closest_monster_in_range_id].hp <= 0) {
/// logging
std::cout << "Monster " << closest_monster_in_range_id << " died. It left "
<< ms[closest_monster_in_range_id].gold << " gold and "
<< ms[closest_monster_in_range_id].exp << " experience.\n";
///
levelling.experience += ms.at(closest_monster_in_range_id).exp;
int L = levelling.level + 1;
while (levelling.experience >= 1000 + L * (L - 1) * 50) {
levelling.experience -= 1000 + L * (L - 1) * 50;
levelling.level++;
L++;
}
}
return ::attack("attack", closest_monster_in_range_id);
}
}
int main(int argc, char** argv) {
using std::vector;
using std::cout;
json input;
{
std::string fname = "input.json";
if (argc > 1) fname = std::string(argv[1]);
std::ifstream ifstream(fname);
ifstream >> input;
}
height = input["height"];
width = input["width"];
const ::hero hero = input["hero"];
vector<::monster> monsters = input["monsters"];
//for (const ::monster& m : monsters) cout << m << '\n';
moves_t moves;
levelling_t levelling(0, 0); // experience and level, updated and used inside turn,
// here we are just maintaining of keeping track of its state.
// With better design it would be inside hero, together with its position
// Would it be good for something to separate the parts of the hero read
// from the input json (constant) and the dynamic stats and position?
int x = input["start_x"], y = input["start_y"];
for (int i = 0; i < input["num_turns"]; i++) {
///logging
std::cout << "======= TURN " << i << " =======\n";
moves.push_back(turn(x, y, hero, monsters, levelling));
}
{
json output(moves);
std::ofstream ofstream("output.json");
ofstream << output << std::endl;
}
}
#include <bitset>
#include <cmath>
#include <exception>
#include <iostream>
#include <fstream>
#include <optional>
#include <queue>
#include <set>
#include <stdexcept>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
#include <nlohmann/json.hpp>
/*
* SUMMARY
struct hero { int base_speed, base_power, ...; };
struct monster { int x, y, hp, gold, ...; };
using monsters_t = std::vector<::monster>;
struct levelling_t { int level, experience; };
using move_t = std::variant<::move, ::attack>;
move_t turn(int& x, int& y, const ::hero& h, ::monsters_t& ms, levelling_t& levelling) {
*/
constexpr auto squared(auto x) {
return x * x;
}
struct unimplemented : public std::exception {
private:
std::string message_;
public:
explicit unimplemented(std::string_view message) : message_(message) {}
const char* what() const noexcept override {
return message_.c_str();
}
};
using json = nlohmann::json;
// TODO name namespace.
namespace {
struct hero {
int base_speed;
int base_power;
int base_range;
int level_speed_coeff;
int level_power_coeff;
int level_range_coeff;
};
[[maybe_unused]] void from_json(const json& j, hero& h) {
j.at("base_speed").get_to(h.base_speed);
j.at("base_power").get_to(h.base_power);
j.at("base_range").get_to(h.base_range);
j.at("level_speed_coeff").get_to(h.level_speed_coeff);
j.at("level_power_coeff").get_to(h.level_power_coeff);
j.at("level_range_coeff").get_to(h.level_range_coeff);
}
struct monster {
int x;
int y;
int hp;
int gold;
int exp;
std::optional<int> attack = std::nullopt;
std::optional<int> range = std::nullopt;
};
[[maybe_unused]] void from_json(const json& j, monster& m) {
j.at("x").get_to(m.x);
j.at("y").get_to(m.y);
j.at("hp").get_to(m.hp);
j.at("gold").get_to(m.gold);
j.at("exp").get_to(m.exp);
if (j.count("attack")) m.attack = j.at("attack").get<int>();
if (j.count("range")) m.range = j.at("range").get<int>();
}
using monsters_t = std::vector<::monster>;
struct move {
int target_x, target_y;
};
struct attack {
int target_id;
};
using move_t = std::variant<move, attack>;
[[maybe_unused]] void to_json(json& j, const move_t& v) {
switch (v.index()) {
case 0:
j = {{"type", "move"},
{"target_x", std::get<move>(v).target_x},
{"target_y", std::get<move>(v).target_y}};
return;
case 1:
j = {{"type", "attack"}, {"target_id", std::get<attack>(v).target_id}};
return;
default:
throw std::runtime_error("Unexpected case in moves variant.");
}
}
// TODO can this be a using instead?
struct moves_t {
std::vector<move_t> moves;
void push_back(move_t&& move) { moves.push_back(move); };
};
[[maybe_unused]] void to_json(json& j, const moves_t& moves) {
j = {{"moves", moves.moves}};
}
} // anonymous
[[maybe_unused]] std::ostream& operator<<(std::ostream& os, const ::monster& m) {
os << "xxxxxxxxxxx\n"
<< "x (" << m.x << ", " << m.y << ")\n"
<< "x " << std::setw(4) << m.hp << " HP\n"
<< "x " << std::setw(4) << m.exp << " EXP\n"
<< "x " << std::setw(8) << m.gold << "g\n"
<< "xxxxxxxxxxx\n\n";
return os;
}
struct levelling_t {
int level;
int experience; // relative to each level
};
int find_closest_alive_monster_in_range(const int x, const int y, const ::hero& h,
const ::monsters_t& ms, const levelling_t& levelling) {
int closest_monster_id = -1, shortest_distance = 1000000000;
const int resulting_range = static_cast<int>(std::floor(
h.base_range * (1 + levelling.level * ((1. * h.level_range_coeff) / 100))));
//std::cout << ">>>> resulting_range: " << resulting_range << '\n';
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
if (ms[i].hp >= 1000) continue;
//if (ms[i].gold == 1) continue;
const int d2 = squared(x - ms[i].x) + squared(y - ms[i].y);
//std::cout << ">>>> d2 to " << i << ": " << d2 << '\n';
if (d2 <= squared(resulting_range) and d2 < shortest_distance) {
closest_monster_id = i;
shortest_distance = d2;
}
}
return closest_monster_id;
}
//TODO consider reducing code duplication in find_*est_alive_monster functions.
[[maybe_unused]] int find_closest_alive_monster(const int x, const int y, const ::monsters_t ms) {
int closest_monster_id = -1, shortest_distance = 1000000000;
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
const int d2 = squared(x - ms[i].x) + squared(y - ms[i].y);
if (d2 < shortest_distance) {
closest_monster_id = i;
shortest_distance = d2;
}
}
return closest_monster_id;
}
[[maybe_unused]] int find_richest_alive_monster(const ::monsters_t ms) {
int richest_monster_id = -1, richest_value = 0;
for (int i = 1; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
if (ms[i].gold > richest_value) {
richest_monster_id = i;
richest_value = ms[i].gold;
}
}
if (richest_monster_id == -1) throw unimplemented("Hoped this wouldn't happen.");
return richest_monster_id;
}
[[maybe_unused]] int find_weakest_alive_monster(const ::monsters_t ms) {
int weakest_monster_id = -1, weakest_value = 1000000000;
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
if (ms[i].hp < weakest_value) {
weakest_monster_id = i;
weakest_value = ms[i].hp;
}
}
if (weakest_monster_id == -1) throw unimplemented("Hoped this wouldn't happen.");
return weakest_monster_id;
}
[[maybe_unused]] int find_expest_alive_monster(const ::monsters_t ms) {
int best_monster_id = -1, best_value = 0;
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms[i].hp <= 0) continue;
if (ms[i].exp > best_value) {
best_monster_id = i;
best_value = ms[i].exp;
}
}
if (best_monster_id == -1) throw unimplemented("Hoped this wouldn't happen.");
return best_monster_id;
}
//TODO refactor globals in global namespace.
int width;
int height;
std::bitset<1001*1001> map;
bool within_bounds(int x, int y) {
return 0 <= x and x <= width and 0 <= y and y <= height;
}
void setup_map_against_strong(const ::monsters_t& ms) {
map.reset();
for (int i = 0; i < static_cast<int>(ms.size()); i++) {
if (ms.at(i).attack <= 1000) continue;
std::queue<std::pair<int, int>> Q;
std::set<std::pair<int, int>> Qed;
const std::vector<std::vector<int>> deltas = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
Q.emplace(ms.at(i).x, ms.at(i).y);
Qed.emplace(ms.at(i).x, ms.at(i).y);
while(!Q.empty()){
std::pair<int, int> cell = Q.front();
Q.pop();
map.set(1001*cell.first + cell.second);
for (const std::vector<int>& delta : deltas) {
std::pair new_cell = cell;
new_cell.first += delta[0];
new_cell.second += delta[1];
if (!within_bounds(new_cell.first, new_cell.second)) continue;
if (Qed.contains(new_cell)) continue;
constexpr auto error = "No input range for monster.";
if (squared(new_cell.first - ms.at(i).x) +
squared(new_cell.second - ms.at(i).y) <=
squared(ms.at(i).range.or_else(
[]() -> std::optional<int> {
throw std::runtime_error(error);
}).value())) {
Q.push(new_cell);
Qed.insert(new_cell);
}
}
}
}
/*
for (int y = 0; y <= 1000; y++) {
for (int x = 0; x <= 1000; x++) {
std::cout << (map.test(x*1001 + y) ? 'x' : ' ');
}
std::cout << '\n';
}
*/
}
void move_toward(int& x, int& y, const int x_g, const int y_g, const int resulting_speed) {
const double D = std::sqrt(squared(x_g - x) + squared(y_g - y));
if (resulting_speed >= D) {
x = x_g;
y = y_g;
return;
}
const double ux = resulting_speed * (x_g - x) / D, uy = resulting_speed * (y_g - y) / D;
///logging
///std::cout << " resulting_speed: " << resulting_speed << " D: " << D << '\n';
///
const int xf = static_cast<int>(std::round(x + ux)), yf = static_cast<int>(std::round(y + uy));
///logging
///std::cout << " (xf, yf): (" << xf << ", " << yf << ")\n";
///
if (squared(xf - x) + squared(yf - y) <= squared(resulting_speed) and within_bounds(xf, yf) and !map.test(xf*1001 + yf)) {
x = xf;
y = yf;
} else {
const std::vector<std::vector<int>> deltas{{-1, 0}, {+1, 0}, { 0, -1}, {0, +1},
{-1, -1}, {+1, -1}, {-1, +1}, {+1, +1}};;
const int init_x = x, init_y = y;
int scaling_x = 1, scaling_y = 1;
for(;;) {
bool found = false;
for (const std::vector<int>& delta : deltas) {
const int try_x = xf + scaling_x * delta[0], try_y = yf + scaling_y * delta[1];
//std::cout << "trying coordinates: " << try_x << ' ' << try_y << std::endl;
if (squared(try_x - init_x) + squared(try_y - init_y) <= squared(resulting_speed) and
within_bounds(try_x, try_y) and !map.test(try_x*1001 + try_y)) {
if (found) {
if (squared(try_x - x_g) + squared(try_y - x_g) < squared(x - x_g) + squared(y - y_g)) {
x = try_x;
y = try_y;
}
} else {
found = true;
x = try_x;
y = try_y;
}
}
}
if (found) return;
if (scaling_x > scaling_y) scaling_y++;
else { assert(scaling_y == scaling_x); scaling_x++; }
//std::cout << "scalings: " << scaling_x << ' ' << scaling_y << std::endl;
}
}
}
move_t turn(int& x, int& y, const ::hero& h, ::monsters_t& ms, levelling_t& levelling) {
const int closest_monster_in_range_id = find_closest_alive_monster_in_range(x, y, h, ms, levelling);
[[maybe_unused]] static int turn_id = -1;
turn_id++;
if (closest_monster_in_range_id == -1) {
//const int monster_id = find_closest_alive_monster(x, y, ms);
const int monster_id = find_weakest_alive_monster(ms);
//const int monster_id = turn_id < 100 ? find_expest_alive_monster(ms) : find_richest_alive_monster(ms);
const ::monster& closest = ms.at(monster_id);
const int resulting_speed = static_cast<int>(std::floor(
h.base_speed * (1 + levelling.level * ((1. * h.level_speed_coeff) / 100))));
/// logging
///std::cout << "Moving toward monster " << monster_id << " at " << closest.x << " " << closest.y
/// << " from " << x << " " << y << "\n";
///
move_toward(x, y, closest.x, closest.y, resulting_speed);
return ::move(x, y);
} else {
const int resulting_attack = static_cast<int>(std::floor(
h.base_power * (1 + levelling.level * ((1. * h.level_power_coeff) / 100))));
/// logging
///std::cout << "Monster " << closest_monster_in_range_id << " with " << ms[closest_monster_in_range_id].hp
/// << " HP takes " << resulting_attack << " damage from level " << levelling.level
/// << " hero with " << levelling.experience << " EXP\n";
///
ms.at(closest_monster_in_range_id).hp -= resulting_attack;
if (ms[closest_monster_in_range_id].hp <= 0) {
/// logging
///std::cout << "Monster " << closest_monster_in_range_id << " died. It left "
/// << ms[closest_monster_in_range_id].gold << " gold and "
/// << ms[closest_monster_in_range_id].exp << " experience.\n";
///
levelling.experience += ms.at(closest_monster_in_range_id).exp;
int L = levelling.level + 1;
while (levelling.experience >= 1000 + L * (L - 1) * 50) {
levelling.experience -= 1000 + L * (L - 1) * 50;
levelling.level++;
L++;
}
}
return ::attack(closest_monster_in_range_id);
}
}
int main(int argc, char** argv) {
json input;
{
std::string fname = "input.json";
if (argc > 1) fname = std::string(argv[1]);
std::ifstream ifstream(fname);
ifstream >> input;
}
height = input["height"];
width = input["width"];
const ::hero hero = input["hero"];
std::vector<::monster> monsters = input["monsters"];
//for (const ::monster& m : monsters) std::cout << m << '\n';
setup_map_against_strong(monsters);
moves_t moves;
levelling_t levelling(0, 0); // experience and level, in/out param for turn,
int x = input["start_x"], y = input["start_y"];
for (int i = 0; i < input["num_turns"]; i++) {
///logging
///std::cout << "======= TURN " << i << " =======\n";
///
moves.push_back(turn(x, y, hero, monsters, levelling));
}
{
json output(moves);
std::ofstream ofstream("output.json");
ofstream << output << std::endl;
}
}
api_token = 'ihrpngqrxqepzpnajzvhzwmbqccoqocw'
api_url = 'https://codeweekend.dev:3721/api/'
files_url = 'https://codeweekend.dev:81/'
print('API TOKEN:', api_token)
print('API URL:', api_url)
import requests
import json
import time
import os
headers = {
'authorization': f'Bearer {api_token}'
}
def show(inner_json):
print(json.dumps(inner_json, indent=2))
def get_scoreboard():
return requests.get(api_url + 'scoreboard', headers=headers).json()
def get_team_dashboard():
return requests.get(api_url + 'team_dashboard', headers=headers).json()
def get_test(task_id):
task_id_padded = '{:03d}'.format(task_id)
url = f'{files_url}{task_id_padded}.json'
return requests.get(url, headers=headers).content
# Returns at most 50 submissions
def get_team_submissions(offset=0, task_id=None):
url = f'{api_url}team_submissions?offset={offset}'
if task_id is not None:
url += f'&task_id={task_id}'
return requests.get(url, headers=headers).json()
def get_submission_info(submission_id, wait=False):
url = f'{api_url}submission_info/{submission_id}'
res = requests.get(url, headers=headers).json()
if 'Pending' in res and wait:
print('Submission is in Pending state, waiting...')
time.sleep(1)
return get_submission_info(submission_id)
return res
# Returns submission_id
def submit(task_id, solution):
res = requests.post(url = f'{api_url}submit/{task_id}',
headers=headers, files={'file': solution})
if res.status_code == 200:
return res.text
print(f'Error: {res.text}')
return None
def download_submission(submission_id):
import urllib.request
url = f'{api_url}download_submission/{submission_id}'
opener = urllib.request.build_opener()
opener.addheaders = headers.items()
urllib.request.install_opener(opener)
try:
file, _ = urllib.request.urlretrieve(url, "downloaded.txt")
except Exception as e:
print('Failed to download submission: ', e)
return None
content = open(file, "r").read()
os.remove(file)
return content
def update_display_name(new_name):
url = api_url + 'update_user'
data = {
'display_name': new_name,
'email': "",
'team_members': ""
}
return requests.post(url, json=data, headers=headers).content
# show(get_scoreboard())
# show(get_submission_info(427))
# show(get_team_dashboard())
# show(get_team_submissions())
# download_submission(476)
# update_display_name('Test 123')
for task_id in range(26, 51):
print(f'Task_id: {task_id}')
f = open('input.json', 'w')
f.write(get_test(task_id).decode())
f.close()
import os
os.system('./hero')
with open('output.json') as f:
d = json.load(f)
submission_id = submit(task_id, json.dumps(d))
print(f' Submission_id: {submission_id}')
info = get_submission_info(submission_id, wait=True)
print(f' Result: {info}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment