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
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

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>
const std::map<std::string, int> powderIDs = []{
const std::map<std::string, int> powder_IDs = []{
std::map<std::string, int> m;
int powder_id = 0;
for (const auto& x : skp_elements) {
for (int i = 0; i < 6; ++i) {
m[x + std::to_string(i)] = i;
m[(char)toupper(x[0]) + std::to_string(i)] = i;
for (int i = 1; i <= 6; ++i) {
m[x + std::to_string(i)] = powder_id;
m[(char)toupper(x[0]) + std::to_string(i)] = powder_id;
powder_id++;
}
}
return m;
}();
const std::map<int, std::string> powderNames = []{
const std::map<int, std::string> powder_names = []{
std::map<int, std::string> m;
for (const auto& kv : powderIDs) {
for (const auto& kv : powder_IDs) {
m[kv.second] = kv.first;
}
return m;
}();
Powder::Powder() {}
Powder::Powder(int min, int max, int conv, int defPlus, int 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); };
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),
@ -44,6 +45,24 @@ const std::vector<Powder> powderStats = []{
}();
#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) {
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

View file

@ -3,8 +3,8 @@
#include <string>
#include <vector>
extern const std::map<std::string, int> powderIDs;
extern const std::map<int, std::string> powderNames;
extern const std::map<std::string, int> powder_IDs;
extern const std::map<int, std::string> powder_names;
struct Powder {
int min;
@ -13,7 +13,8 @@ struct Powder {
int defPlus;
int defMinus;
Powder();
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();
let powderIDs = new Map();
let powderNames = new Map();
let _powderID = 0;
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)
];
const powderIDs = _module_powders.powderIDs();
const powderNames = _module_powders.powderNames();
const powderStats = _module_powders.powderStats();
//Ordering: [weapon special name, weapon special effects, armor special name, armor special effects]
class PowderSpecial{

View file

@ -1,6 +1,5 @@
#ifdef __EMSCRIPTEN__
#include <emscripten/bind.h>
using namespace emscripten;
#endif
#include "utils.h"
@ -45,7 +44,9 @@ std::vector<std::vector<T>> perm(std::vector<T> a) {
}
return result;
}
#ifdef __EMSCRIPTEN__
using namespace emscripten;
val __perm_wrap(val a) {
const size_t l = a["length"].as<size_t>();
std::vector<val> things;
@ -65,26 +66,6 @@ val __perm_wrap(val a) {
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) {
function("clamp", &clamp);
@ -97,6 +78,7 @@ EMSCRIPTEN_BINDINGS(utils) {
class_<BitVector>("BitVector")
.constructor<std::string>()
.constructor<size_t, size_t>()
.property("length", &BitVector::length)
.function("read_bit", &BitVector::read_bit)
.function("slice", &BitVector::slice)
.function("set_bit", &BitVector::set_bit)

View file

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

View file

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

View file

@ -24,7 +24,7 @@ namespace Base64 {
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);

View file

@ -5,11 +5,11 @@
#include <sstream>
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) {
length = b64_data.length() * 6;
data.reserve(length/bitvec_data_s + 1);
_length = b64_data.length() * 6;
data.reserve(_length/bitvec_data_s + 1);
bitvec_data_t scratch = 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.");
}
data.push_back(num);
this->length = length;
this->_length = length;
}
/** 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
*/
bool BitVector::read_bit(size_t idx) const {
if (idx < 0 || idx >= length) {
if (idx < 0 || idx >= length()) {
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());
}
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.
*/
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.");
}
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.
*/
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.");
}
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.
*/
std::string BitVector::toB64() const {
if (length == 0) {
if (length() == 0) {
return "";
}
std::stringstream b64_str;
size_t i = 0;
while (i < length) {
while (i < length()) {
b64_str << Base64::fromIntN(this->slice(i, i + 6), 1);
i += 6;
}
@ -145,7 +145,7 @@ std::string BitVector::toB64() const {
*/
std::string BitVector::toString() const {
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");
}
return ret_str.str();
@ -157,7 +157,7 @@ std::string BitVector::toString() const {
*/
std::string BitVector::toStringR() const {
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");
}
return ret_str.str();
@ -167,22 +167,22 @@ void BitVector::append(const BitVector& other) {
data.reserve(data.size() + other.data.size());
size_t other_index = 0;
if (this->length % bitvec_data_s != 0) {
if (this->length() % bitvec_data_s != 0) {
// fill in the last block.
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);
scratch |= (other.slice(0, n) << (this->length % bitvec_data_s));
size_t n = std::min(other.length(), bits_remaining);
scratch |= (other.slice(0, n) << (this->length() % bitvec_data_s));
data[data.size() - 1] = scratch;
other_index += n;
}
while (other_index != other.length) {
size_t n = std::min(other.length - other_index, (size_t)bitvec_data_s);
while (other_index != other.length()) {
size_t n = std::min(other.length() - other_index, (size_t)bitvec_data_s);
data.push_back(other.slice(other_index, other_index + n));
other_index += n;
}
this->length += other.length;
this->_length += other.length();
}
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);
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(bitvec_data_t num, size_t length);
// length getter.
size_t length() const;
private:
std::vector<bitvec_data_t> data;
size_t length;
size_t _length;
};