Fix bugs with powders and migrate constants to c++

This commit is contained in:
hppeng 2023-04-05 10:08:52 -07:00
parent 3a5876ceba
commit 1c07cd0911
11 changed files with 103 additions and 86 deletions

View file

@ -1,5 +1,6 @@
CXX=emcc CXX=emcc
CXXFLAGS=-sENVIRONMENT=web -sSINGLE_FILE -sMODULARIZE -sWASM_ASYNC_COMPILATION=0 -sALLOW_MEMORY_GROWTH -lembind --closure 1 #CXXFLAGS=-sENVIRONMENT=web -sSINGLE_FILE -sMODULARIZE -sWASM_ASYNC_COMPILATION=0 -sALLOW_MEMORY_GROWTH -lembind --closure 1
CXXFLAGS=-sENVIRONMENT=web -sSINGLE_FILE -sMODULARIZE -sWASM_ASYNC_COMPILATION=0 -sALLOW_MEMORY_GROWTH -lembind -g
all: utils.js powders.js all: utils.js powders.js

36
js/c++/js_helpers.h Normal file
View file

@ -0,0 +1,36 @@
#pragma once
#ifdef __EMSCRIPTEN__
#include <emscripten/bind.h>
using namespace emscripten;
#define MAP_TO_JS_FUNC(map_name) \
auto make_ ## map_name () { \
return map_to_js(map_name); \
}
#define VEC_TO_JS_FUNC(vec_name) \
auto make_ ## vec_name () { \
return vector_to_js(vec_name); \
}
// NOTE!!! For some stupid reason you can'd declare constants with these...
template<class Container>
val map_to_js(const Container& input_map) {
static val Map = val::global("Map");
val retval = Map.new_();
for (const auto& [k, v] : input_map) {
retval.call<val>("set", k, v);
}
return retval;
}
template<class Container>
val vector_to_js(const Container& input_vec) {
val retval = val::array();
for (const auto& x : input_vec) {
retval.call<void>("push", x);
}
return retval;
}
#endif

View file

@ -8,31 +8,32 @@ using namespace emscripten;
#include <cstring> #include <cstring>
const std::map<std::string, int> powderIDs = []{ const std::map<std::string, int> powder_IDs = []{
std::map<std::string, int> m; std::map<std::string, int> m;
int powder_id = 0; int powder_id = 0;
for (const auto& x : skp_elements) { for (const auto& x : skp_elements) {
for (int i = 0; i < 6; ++i) { for (int i = 1; i <= 6; ++i) {
m[x + std::to_string(i)] = i; m[x + std::to_string(i)] = powder_id;
m[(char)toupper(x[0]) + std::to_string(i)] = i; m[(char)toupper(x[0]) + std::to_string(i)] = powder_id;
powder_id++; powder_id++;
} }
} }
return m; return m;
}(); }();
const std::map<int, std::string> powderNames = []{ const std::map<int, std::string> powder_names = []{
std::map<int, std::string> m; std::map<int, std::string> m;
for (const auto& kv : powderIDs) { for (const auto& kv : powder_IDs) {
m[kv.second] = kv.first; m[kv.second] = kv.first;
} }
return m; return m;
}(); }();
Powder::Powder() {}
Powder::Powder(int min, int max, int conv, int defPlus, int defMinus) : Powder::Powder(int min, int max, int conv, int defPlus, int defMinus) :
min(min), max(max), convert(conv), defPlus(defPlus), defMinus(defMinus) {} min(min), max(max), convert(conv), defPlus(defPlus), defMinus(defMinus) {}
const std::vector<Powder> powderStats = []{ const std::vector<Powder> powder_stats = []{
auto p = [](int a, int b, int c, int d, int e){ return Powder(a,b,c,d,e); }; auto p = [](int a, int b, int c, int d, int e){ return Powder(a,b,c,d,e); };
return std::vector<Powder> { return std::vector<Powder> {
p(3,6,17,2,1), p(5,8,21,4,2), p(6,10,25,8,3), p(7,10,31,14,5), p(9,11,38,22,9), p(11,13,46,30,13), p(3,6,17,2,1), p(5,8,21,4,2), p(6,10,25,8,3), p(7,10,31,14,5), p(9,11,38,22,9), p(11,13,46,30,13),
@ -44,6 +45,24 @@ const std::vector<Powder> powderStats = []{
}(); }();
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
#include "js_helpers.h"
#include <iostream>
MAP_TO_JS_FUNC(powder_IDs);
MAP_TO_JS_FUNC(powder_names);
VEC_TO_JS_FUNC(powder_stats);
EMSCRIPTEN_BINDINGS(powders) { EMSCRIPTEN_BINDINGS(powders) {
function("powderIDs", &make_powder_IDs);
function("powderNames", &make_powder_names);
value_object<Powder>("Powder")
.field("min", &Powder::min)
.field("max", &Powder::max)
.field("convert", &Powder::convert)
.field("defPlus", &Powder::defPlus)
.field("defMinus", &Powder::defMinus)
;
function("powderStats", make_powder_stats);
} }
#endif #endif

View file

@ -3,8 +3,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
extern const std::map<std::string, int> powderIDs; extern const std::map<std::string, int> powder_IDs;
extern const std::map<int, std::string> powderNames; extern const std::map<int, std::string> powder_names;
struct Powder { struct Powder {
int min; int min;
@ -13,7 +13,8 @@ struct Powder {
int defPlus; int defPlus;
int defMinus; int defMinus;
Powder();
Powder(int min, int max, int conv, int defPlus, int defMinus); Powder(int min, int max, int conv, int defPlus, int defMinus);
}; };
extern const std::vector<Powder> powderStats; extern const std::vector<Powder> powder_stats;

View file

@ -1,38 +1,9 @@
const _module_powders = create_powders(); const _module_powders = create_powders();
let powderIDs = new Map(); const powderIDs = _module_powders.powderIDs();
let powderNames = new Map(); const powderNames = _module_powders.powderNames();
let _powderID = 0; const powderStats = _module_powders.powderStats();
for (const x of skp_elements) {
for (let i = 1; i <= 6; ++i) {
// Support both upper and lowercase, I guess.
powderIDs.set(x.toUpperCase()+i, _powderID);
powderIDs.set(x+i, _powderID);
powderNames.set(_powderID, x+i);
_powderID++;
}
}
// Ordering: [dmgMin, dmgMax, convert, defPlus, defMinus (+6 mod 5)]
class Powder {
constructor(min, max, convert, defPlus, defMinus) {
this.min = min;
this.max = max;
this.convert = convert;
this.defPlus = defPlus;
this.defMinus = defMinus;
}
}
function _p(a,b,c,d,e) { return new Powder(a,b,c,d,e); } //bruh moment
let powderStats = [
_p(3,6,17,2,1), _p(5,8,21,4,2), _p(6,10,25,8,3), _p(7,10,31,14,5), _p(9,11,38,22,9), _p(11,13,46,30,13),
_p(1,8,9,3,1), _p(1,12,11,5,1), _p(2,15,13,9,2), _p(3,15,17,14,4), _p(4,17,22,20,7), _p(5,20,28,28,10),
_p(3,4,13,3,1), _p(4,6,15,6,1), _p(5,8,17,11,2), _p(6,8,21,18,4), _p(7,10,26,28,7), _p(9,11,32,40,10),
_p(2,5,14,3,1), _p(4,8,16,5,2), _p(5,9,19,9,3), _p(6,9,24,16,5), _p(8,10,30,25,9), _p(10,12,37,36,13),
_p(2,6,11,3,1), _p(3,10,14,6,2), _p(4,11,17,10,3), _p(5,11,22,16,5), _p(7,12,28,24,9), _p(8,14,35,34,13)
];
//Ordering: [weapon special name, weapon special effects, armor special name, armor special effects] //Ordering: [weapon special name, weapon special effects, armor special name, armor special effects]
class PowderSpecial{ class PowderSpecial{

View file

@ -1,6 +1,5 @@
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
#include <emscripten/bind.h> #include <emscripten/bind.h>
using namespace emscripten;
#endif #endif
#include "utils.h" #include "utils.h"
@ -45,7 +44,9 @@ std::vector<std::vector<T>> perm(std::vector<T> a) {
} }
return result; return result;
} }
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
using namespace emscripten;
val __perm_wrap(val a) { val __perm_wrap(val a) {
const size_t l = a["length"].as<size_t>(); const size_t l = a["length"].as<size_t>();
std::vector<val> things; std::vector<val> things;
@ -65,26 +66,6 @@ val __perm_wrap(val a) {
return return_array; return return_array;
} }
/** Appends data to the BitVector.
*
* @param {Number | String} data - The data to append.
* @param {Number} length - The length, in bits, of the new data. This is ignored if data is a string.
*/
void __BitVector_append(BitVector& self, val data, val length) {
if (data.typeOf().as<std::string>() == "string") {
self.append(data.as<std::string>());
return;
}
if (data.typeOf().as<std::string>() == "number") {
size_t num = data.as<size_t>();
//if (num >= 1<<bitvec_data_s) {
// throw std::range_error("Numerical data has to fit within a 32-bit integer range to append to a BitVector.");
//}
self.append(num, length.as<size_t>());
return;
}
throw std::invalid_argument("BitVector must be appended with a Number or a B64 String");
}
EMSCRIPTEN_BINDINGS(utils) { EMSCRIPTEN_BINDINGS(utils) {
function("clamp", &clamp); function("clamp", &clamp);
@ -97,6 +78,7 @@ EMSCRIPTEN_BINDINGS(utils) {
class_<BitVector>("BitVector") class_<BitVector>("BitVector")
.constructor<std::string>() .constructor<std::string>()
.constructor<size_t, size_t>() .constructor<size_t, size_t>()
.property("length", &BitVector::length)
.function("read_bit", &BitVector::read_bit) .function("read_bit", &BitVector::read_bit)
.function("slice", &BitVector::slice) .function("slice", &BitVector::slice)
.function("set_bit", &BitVector::set_bit) .function("set_bit", &BitVector::set_bit)

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <vector>
/** /**
* Generate all permutations of a vector. * Generate all permutations of a vector.
* *

View file

@ -12,7 +12,7 @@ namespace Base64 {
return result; return result;
} }
std::string fromIntN(unsigned int int32, int n) { std::string fromIntN(int int32, int n) {
std::string result; std::string result;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
result = digits[int32 & 0x3f] + result; result = digits[int32 & 0x3f] + result;

View file

@ -24,7 +24,7 @@ namespace Base64 {
std::string fromIntV(unsigned int i); std::string fromIntV(unsigned int i);
std::string fromIntN(unsigned int i, int n); std::string fromIntN(int i, int n);
unsigned int toInt(std::string digitsStr); unsigned int toInt(std::string digitsStr);

View file

@ -5,11 +5,11 @@
#include <sstream> #include <sstream>
BitVector::BitVector() {}; BitVector::BitVector() {};
BitVector::BitVector(const BitVector& other) : data(other.data), length(other.length) {}; BitVector::BitVector(const BitVector& other) : data(other.data), _length(other.length()) {};
BitVector::BitVector(const std::string b64_data) { BitVector::BitVector(const std::string b64_data) {
length = b64_data.length() * 6; _length = b64_data.length() * 6;
data.reserve(length/bitvec_data_s + 1); data.reserve(_length/bitvec_data_s + 1);
bitvec_data_t scratch = 0; bitvec_data_t scratch = 0;
size_t bitvec_index = 0; size_t bitvec_index = 0;
@ -34,7 +34,7 @@ BitVector::BitVector(bitvec_data_t num, size_t length) {
throw std::range_error("BitVector must have nonnegative length."); throw std::range_error("BitVector must have nonnegative length.");
} }
data.push_back(num); data.push_back(num);
this->length = length; this->_length = length;
} }
/** Return value of bit at index idx. /** Return value of bit at index idx.
@ -44,9 +44,9 @@ BitVector::BitVector(bitvec_data_t num, size_t length) {
* @returns The bit value at position idx * @returns The bit value at position idx
*/ */
bool BitVector::read_bit(size_t idx) const { bool BitVector::read_bit(size_t idx) const {
if (idx < 0 || idx >= length) { if (idx < 0 || idx >= length()) {
std::stringstream ss; std::stringstream ss;
ss << "Cannot read bit outside the range of the BitVector. (" << idx << " > " << length << ")"; ss << "Cannot read bit outside the range of the BitVector. (" << idx << " > " << length() << ")";
throw std::range_error(ss.str()); throw std::range_error(ss.str());
} }
return (data[idx / bitvec_data_s] & (1 << (idx % bitvec_data_s))) == 0 ? 0 : 1; return (data[idx / bitvec_data_s] & (1 << (idx % bitvec_data_s))) == 0 ? 0 : 1;
@ -104,7 +104,7 @@ bitvec_data_t BitVector::slice(size_t start, size_t end) const {
* @param {Number} idx - The index to set. * @param {Number} idx - The index to set.
*/ */
void BitVector::set_bit(size_t idx) { void BitVector::set_bit(size_t idx) {
if (idx < 0 || idx >= length) { if (idx < 0 || idx >= length()) {
throw std::range_error("Cannot set bit outside the range of the BitVector."); throw std::range_error("Cannot set bit outside the range of the BitVector.");
} }
data[idx / bitvec_data_s] |= (1 << (idx % bitvec_data_s)); data[idx / bitvec_data_s] |= (1 << (idx % bitvec_data_s));
@ -115,7 +115,7 @@ void BitVector::set_bit(size_t idx) {
* @param {Number} idx - The index to clear. * @param {Number} idx - The index to clear.
*/ */
void BitVector::clear_bit(size_t idx) { void BitVector::clear_bit(size_t idx) {
if (idx < 0 || idx >= length) { if (idx < 0 || idx >= length()) {
throw std::range_error("Cannot clear bit outside the range of the BitVector."); throw std::range_error("Cannot clear bit outside the range of the BitVector.");
} }
data[idx / bitvec_data_s] &= ~(1 << (idx % bitvec_data_s)); data[idx / bitvec_data_s] &= ~(1 << (idx % bitvec_data_s));
@ -126,12 +126,12 @@ void BitVector::clear_bit(size_t idx) {
* @returns A b64 string representation of the BitVector. * @returns A b64 string representation of the BitVector.
*/ */
std::string BitVector::toB64() const { std::string BitVector::toB64() const {
if (length == 0) { if (length() == 0) {
return ""; return "";
} }
std::stringstream b64_str; std::stringstream b64_str;
size_t i = 0; size_t i = 0;
while (i < length) { while (i < length()) {
b64_str << Base64::fromIntN(this->slice(i, i + 6), 1); b64_str << Base64::fromIntN(this->slice(i, i + 6), 1);
i += 6; i += 6;
} }
@ -145,7 +145,7 @@ std::string BitVector::toB64() const {
*/ */
std::string BitVector::toString() const { std::string BitVector::toString() const {
std::stringstream ret_str; std::stringstream ret_str;
for (size_t i = length; i != 0; --i) { for (size_t i = length(); i != 0; --i) {
ret_str << (this->read_bit(i-1) ? "1": "0"); ret_str << (this->read_bit(i-1) ? "1": "0");
} }
return ret_str.str(); return ret_str.str();
@ -157,7 +157,7 @@ std::string BitVector::toString() const {
*/ */
std::string BitVector::toStringR() const { std::string BitVector::toStringR() const {
std::stringstream ret_str; std::stringstream ret_str;
for (size_t i = 0; i < length; ++i) { for (size_t i = 0; i < length(); ++i) {
ret_str << (this->read_bit(i) ? "1": "0"); ret_str << (this->read_bit(i) ? "1": "0");
} }
return ret_str.str(); return ret_str.str();
@ -167,22 +167,22 @@ void BitVector::append(const BitVector& other) {
data.reserve(data.size() + other.data.size()); data.reserve(data.size() + other.data.size());
size_t other_index = 0; size_t other_index = 0;
if (this->length % bitvec_data_s != 0) { if (this->length() % bitvec_data_s != 0) {
// fill in the last block. // fill in the last block.
bitvec_data_t scratch = data[data.size() - 1]; bitvec_data_t scratch = data[data.size() - 1];
size_t bits_remaining = bitvec_data_s - (this->length % bitvec_data_s); size_t bits_remaining = bitvec_data_s - (this->length() % bitvec_data_s);
size_t n = std::min(other.length, bits_remaining); size_t n = std::min(other.length(), bits_remaining);
scratch |= (other.slice(0, n) << (this->length % bitvec_data_s)); scratch |= (other.slice(0, n) << (this->length() % bitvec_data_s));
data[data.size() - 1] = scratch; data[data.size() - 1] = scratch;
other_index += n; other_index += n;
} }
while (other_index != other.length) { while (other_index != other.length()) {
size_t n = std::min(other.length - other_index, (size_t)bitvec_data_s); size_t n = std::min(other.length() - other_index, (size_t)bitvec_data_s);
data.push_back(other.slice(other_index, other_index + n)); data.push_back(other.slice(other_index, other_index + n));
other_index += n; other_index += n;
} }
this->length += other.length; this->_length += other.length();
} }
void BitVector::append(const std::string b64_data) { void BitVector::append(const std::string b64_data) {
@ -194,3 +194,5 @@ void BitVector::append(bitvec_data_t num, size_t length) {
BitVector tmp(num, length); BitVector tmp(num, length);
this->append(tmp); this->append(tmp);
} }
size_t BitVector::length() const { return this->_length; }

View file

@ -84,7 +84,10 @@ public:
void append(const std::string b64_data); void append(const std::string b64_data);
void append(bitvec_data_t num, size_t length); void append(bitvec_data_t num, size_t length);
// length getter.
size_t length() const;
private: private:
std::vector<bitvec_data_t> data; std::vector<bitvec_data_t> data;
size_t length; size_t _length;
}; };