Skip to content

Commit

Permalink
reduce binary size by reducing Card flag pointers to 1 byte
Browse files Browse the repository at this point in the history
  • Loading branch information
serprex committed Aug 4, 2024
1 parent d3f21d7 commit 0c9ce79
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 29 deletions.
39 changes: 28 additions & 11 deletions src/rs/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct Card {
cast: i8,
castele: u8,
status: String,
flag: String,
flag: u8,
skill: String,
}

Expand All @@ -59,7 +59,13 @@ fn parse<F: FromStr + Default>(s: &str) -> F {
}
}

fn process_cards(set: &'static str, path: &'static str, source: &mut String, enums: &mut Enums) {
fn process_cards(
set: &'static str,
path: &'static str,
source: &mut String,
enums: &mut Enums,
flagmap: &mut BTreeMap<String, u8>,
) {
let mut cards: Vec<Card> = Vec::new();
let cards_json = fs::read_to_string(path).expect("failed to read cards.csv");
for row in cards_json.split('\n') {
Expand All @@ -82,7 +88,8 @@ fn process_cards(set: &'static str, path: &'static str, source: &mut String, enu
let mut cast = 0;
let mut castele = 0;
let mut statstr = String::from("&[");
let mut flagstr = String::from("&0");
let mut flagstr = String::from("0");
let flagidx;
let mut stat = Vec::new();
let mut flag = Vec::new();
let status = values[9];
Expand All @@ -103,14 +110,15 @@ fn process_cards(set: &'static str, path: &'static str, source: &mut String, enu
}
}
if !flag.is_empty() {
let lastch = flagstr.len() - 1;
unsafe { flagstr.as_mut_vec()[lastch] = b'(' };
flag.sort_unstable();
flagstr.clear();
for fl in flag {
write!(flagstr, "Flag::{}|", fl).ok();
}
let lastch = flagstr.len() - 1;
unsafe { flagstr.as_mut_vec()[lastch] = b')' };
flagstr.truncate(flagstr.len() - 1);
}
let newflagidx = flagmap.len() as u8;
flagidx = *flagmap.entry(flagstr).or_insert(newflagidx);
statstr.push(']');

let mut skillstr = String::from("&[");
Expand Down Expand Up @@ -189,7 +197,7 @@ fn process_cards(set: &'static str, path: &'static str, source: &mut String, enu
cast,
castele,
status: statstr,
flag: flagstr,
flag: flagidx,
skill: skillstr,
};
cards.push(card);
Expand Down Expand Up @@ -218,7 +226,7 @@ fn process_cards(set: &'static str, path: &'static str, source: &mut String, enu
)
.ok();
for card in cards.iter() {
write!(source, "Card{{code:{},name:r#\"{}\"#,kind:Kind::{},element:{},rarity:{},attack:{},health:{},cost:{},costele:{},cast:{},castele:{},flag:{},status:{},skill:{}}},\n",
write!(source, "Card{{code:{},name:r#\"{}\"#,kind:Kind::{},element:{},rarity:{},attack:{},health:{},cost:{},costele:{},cast:{},castele:{},flagidx:{},status:{},skill:{}}},\n",
card.code, card.name, ["Weapon","Shield","Permanent","Spell","Creature"][card.kind as usize],
card.ele, card.rarity, card.attack, card.health, card.cost, card.costele, card.cast, card.castele,
card.flag, card.status, card.skill
Expand Down Expand Up @@ -297,8 +305,17 @@ fn main() {
}
source.push_str("}}\n");

process_cards("Open", "../cards.csv", &mut source, &mut enums);
process_cards("Orig", "../vanilla/cards.csv", &mut source, &mut enums);
let mut flagmap = BTreeMap::new();
flagmap.insert(String::from("0"), 0);
process_cards("Open", "../cards.csv", &mut source, &mut enums, &mut flagmap);
process_cards("Orig", "../vanilla/cards.csv", &mut source, &mut enums, &mut flagmap);
write!(source, "pub const FlagTable: [u64; {}] = [", flagmap.len()).ok();
let mut flagkeys: Vec<_> = flagmap.keys().collect();
flagkeys.sort_unstable_by_key(|k| flagmap.get(k.as_str()).cloned().unwrap_or(0));
for k in flagkeys.iter() {
write!(source, "{},", k).ok();
}
write!(source, "];\n").ok();

fs::write("../enum.json", &serde_json::to_string(&enums).expect("failed to serialize enums"))
.expect("Failed to write enum.json");
Expand Down
20 changes: 12 additions & 8 deletions src/rs/src/card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct Card {
pub costele: i8,
pub cast: i8,
pub castele: i8,
pub flag: &'static u64,
pub flagidx: u8,
pub status: &'static [(Stat, i16)],
pub skill: &'static [(Event, &'static [Skill])],
}
Expand Down Expand Up @@ -71,7 +71,7 @@ impl Cards {
where
Ffilt: Fn(&'static Card) -> bool,
{
rng.choose_iter(self.filter(upped).iter().filter(|c| (c.flag & Flag::token) == 0 && ffilt(c)))
rng.choose_iter(self.filter(upped).iter().filter(|c| (c.flag() & Flag::token) == 0 && ffilt(c)))
}
}

Expand All @@ -88,8 +88,12 @@ impl Card {
IsOf(self.code, code)
}

pub fn free(&self) -> bool {
self.rarity == 0 && (self.flag & Flag::pillar) != 0 && !self.upped()
pub const fn free(&self) -> bool {
self.rarity == 0 && (self.flag() & Flag::pillar) != 0 && !self.upped()
}

pub const fn flag(&self) -> u64 {
FlagTable[self.flagidx as usize]
}
}

Expand Down Expand Up @@ -186,13 +190,13 @@ pub fn card_costele(set: CardSet, index: usize) -> Option<i8> {
#[cfg(target_arch = "wasm32")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
pub fn card_pillar(set: CardSet, index: usize) -> bool {
cardSetCards(set).try_get_index(index).map(|&card| (card.flag & Flag::pillar) != 0).unwrap_or(false)
cardSetCards(set).try_get_index(index).map(|&card| (card.flag() & Flag::pillar) != 0).unwrap_or(false)
}

#[cfg(target_arch = "wasm32")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
pub fn card_token(set: CardSet, index: usize) -> bool {
cardSetCards(set).try_get_index(index).map(|&card| (card.flag & Flag::token) != 0).unwrap_or(false)
cardSetCards(set).try_get_index(index).map(|&card| (card.flag() & Flag::token) != 0).unwrap_or(false)
}

#[cfg(target_arch = "wasm32")]
Expand All @@ -211,7 +215,7 @@ pub fn code_cmp_core(cards: &'static Cards, x: i16, y: i16) -> Ordering {
cx.upped()
.cmp(&cy.upped())
.then(cx.element.cmp(&cy.element))
.then((cy.flag & Flag::pillar).cmp(&(cx.flag & Flag::pillar)))
.then((cy.flag() & Flag::pillar).cmp(&(cx.flag() & Flag::pillar)))
.then(cx.cost.cmp(&cy.cost))
.then(cx.kind.cmp(&cy.kind))
.then(x.cmp(&y))
Expand Down Expand Up @@ -241,7 +245,7 @@ pub fn selector_filter(set: CardSet, col: u32, element: i8, rarity: i8) -> Vec<i
let cards = cardSetCards(set);
let mut result = Vec::with_capacity(15);
for card in cards.filter(col > 2) {
if (card.flag & Flag::token) == 0
if (card.flag() & Flag::token) == 0
&& (rarity == 4 || card.element == element)
&& (rarity == 0 || card.rarity == rarity)
&& match col % 3 {
Expand Down
6 changes: 3 additions & 3 deletions src/rs/src/deckgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn deckgen_duo(e1: i8, e2: i8, uprate: u8, markpower: i16, maxrarity: i32, s
let upped = rng.upto(100) < uprate as u32;
if let Some(card) = card::OpenSet.random_card(&rng, upped, |card| {
card.element == ele
&& (card.flag & Flag::pillar) == 0
&& (card.flag() & Flag::pillar) == 0
&& card.rarity as i32 <= maxrarity
&& build.card_count(card.code) != 6
&& !(card.kind == Kind::Shield && build.anyshield >= 3)
Expand Down Expand Up @@ -68,7 +68,7 @@ pub fn deckgen_bow(uprate: u8, markpower: i16, maxrarity: i32, seed: u32) -> Vec
let upped = (rng.upto(100) as u8) < uprate;
if let Some(card) = card::OpenSet.random_card(&rng, upped, |card| {
card.element == ele
&& (card.flag & Flag::pillar) == 0
&& (card.flag() & Flag::pillar) == 0
&& card.cost < 7 && card.rarity as i32 <= maxrarity
&& build.card_count(card.code) != 6
&& !(card.kind == Kind::Shield && build.anyshield >= 3)
Expand Down Expand Up @@ -246,7 +246,7 @@ fn filters(code: i16, deck: &[i16], ecost: &[i16; 13]) -> bool {
card::TidalHealing => {
let mut aquatics: i32 = 0;
for &dcode in deck.iter() {
if card::OpenSet.get(dcode).flag & Flag::aquatic != 0 {
if card::OpenSet.get(dcode).flag() & Flag::aquatic != 0 {
if aquatics > 3 {
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions src/rs/src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1946,7 +1946,7 @@ impl Game {
thing.status.insert(Stat::hp, card.health as i16);
thing.status.insert(Stat::maxhp, card.health as i16);
thing.status.insert(Stat::atk, card.attack as i16);
thing.flag.0 |= card.flag;
thing.flag.0 |= card.flag();
for &(k, v) in card.status.iter() {
thing.status.insert(k, v);
}
Expand All @@ -1973,7 +1973,7 @@ impl Game {
| Flag::ranged | Flag::stackable
| Flag::token | Flag::tunnel
| Flag::voodoo | Flag::whetstone);
thing.flag.0 |= card.flag;
thing.flag.0 |= card.flag();
for &(k, v) in card.status {
thing.status.insert(k, v);
}
Expand Down
6 changes: 3 additions & 3 deletions src/rs/src/skill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3617,7 +3617,7 @@ impl Skill {
let roll = ctx.upto(3) < 2;
let e = ctx.get_player(if roll { owner } else { ctx.get_foe(owner) }).mark;
if let Some(newcard) = ctx.random_card(false, |ctx, card| {
card.element == e && card.rarity != -1 && (card.flag & Flag::pillar) != 0
card.element == e && card.rarity != -1 && (card.flag() & Flag::pillar) != 0
}) {
let inst = ctx.new_thing(card::As(ctx.get(c, Stat::card), newcard.code), owner);
ctx.fx(inst, Fx::StartPos(c));
Expand Down Expand Up @@ -4136,7 +4136,7 @@ impl Skill {
let ccard = ctx.get(c, Stat::card);
for i in (0..num).rev() {
if let Some(card) = ctx.random_card(card::Upped(ccard), |ctx, card| {
(card.flag & Flag::pillar) == 0
(card.flag() & Flag::pillar) == 0
&& (i > 0 || anyentro || card.element as i16 == etg::Entropy)
}) {
if card.element as i16 == etg::Entropy {
Expand Down Expand Up @@ -5393,7 +5393,7 @@ impl Skill {
.filter(|&&pr| {
pr != 0 && {
let card = ctx.get_card(ctx.get(pr, Stat::card));
(card.flag & Flag::pillar) == 0
(card.flag() & Flag::pillar) == 0
&& matches!(card.element as i16, etg::Darkness | etg::Death)
}
})
Expand Down
4 changes: 2 additions & 2 deletions src/rs/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl<'a> SkillThing<'a> {
fn get_flag(&self, flag: u64) -> bool {
match *self {
Self::Thing(game, id) => game.get(id, flag),
Self::Card(cards, c) => (c.flag & flag) != 0,
Self::Card(cards, c) => (c.flag() & flag) != 0,
}
}

Expand All @@ -119,7 +119,7 @@ impl<'a> SkillThing<'a> {
fn flags(&self) -> Flag {
match *self {
Self::Thing(game, id) => game.get_thing(id).flag,
Self::Card(cards, c) => Flag(*c.flag),
Self::Card(cards, c) => Flag(c.flag()),
}
}

Expand Down

0 comments on commit 0c9ce79

Please sign in to comment.