diff --git a/contracts/adventurer/Scarb.lock b/contracts/adventurer/Scarb.lock new file mode 100644 index 000000000..57f6a649b --- /dev/null +++ b/contracts/adventurer/Scarb.lock @@ -0,0 +1,46 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "beasts" +version = "0.1.0" +dependencies = [ + "combat", +] + +[[package]] +name = "combat" +version = "0.1.0" + +[[package]] +name = "lootitems" +version = "0.1.0" +dependencies = [ + "combat", +] + +[[package]] +name = "market" +version = "0.1.0" +dependencies = [ + "combat", + "lootitems", +] + +[[package]] +name = "obstacles" +version = "0.1.0" +dependencies = [ + "combat", +] + +[[package]] +name = "survivor" +version = "0.1.0" +dependencies = [ + "beasts", + "combat", + "lootitems", + "market", + "obstacles", +] diff --git a/contracts/adventurer/src/adventurer.cairo b/contracts/adventurer/src/adventurer.cairo index d40051658..150a943e4 100644 --- a/contracts/adventurer/src/adventurer.cairo +++ b/contracts/adventurer/src/adventurer.cairo @@ -22,7 +22,7 @@ use super::{ MINIMUM_DAMAGE_FROM_BEASTS, OBSTACLE_CRITICAL_HIT_CHANCE, BEAST_CRITICAL_HIT_CHANCE, SILVER_RING_LUCK_BONUS_PER_GREATNESS, MINIMUM_DAMAGE_FROM_OBSTACLES, MINIMUM_DAMAGE_TO_BEASTS, MAX_ACTIONS_PER_BLOCK, MAX_PACKABLE_ITEM_XP, - MAX_PACKABLE_BEAST_HEALTH, MAX_LAST_ACTION_BLOCK + MAX_PACKABLE_BEAST_HEALTH, MAX_LAST_ACTION_BLOCK, MAX_STAT_VALUE_5_BITS }, discovery_constants::DiscoveryEnums::{ExploreResult, DiscoveryType} }, @@ -43,8 +43,8 @@ use beasts::{beast::{ImplBeast, Beast}, constants::BeastSettings}; struct Adventurer { last_action_block: u16, // 9 bits health: u16, // 9 bits - xp: u16, // 13 bits - stats: Stats, // 24 bits + xp: u16, // 14 bits + stats: Stats, // 26 bits gold: u16, // 9 bits weapon: ItemPrimitive, // 21 bits chest: ItemPrimitive, // 21 bits @@ -67,31 +67,32 @@ impl AdventurerPacking of StorePacking { (value.last_action_block.into() + value.health.into() * TWO_POW_9 + value.xp.into() * TWO_POW_18 - + StatsPacking::pack(value.stats).into() * TWO_POW_31 - + value.gold.into() * TWO_POW_55 - + ItemPrimitivePacking::pack(value.weapon).into() * TWO_POW_64 - + ItemPrimitivePacking::pack(value.chest).into() * TWO_POW_85 - + ItemPrimitivePacking::pack(value.head).into() * TWO_POW_106 - + ItemPrimitivePacking::pack(value.waist).into() * TWO_POW_127 - + ItemPrimitivePacking::pack(value.foot).into() * TWO_POW_148 - + ItemPrimitivePacking::pack(value.hand).into() * TWO_POW_169 - + ItemPrimitivePacking::pack(value.neck).into() * TWO_POW_190 - + ItemPrimitivePacking::pack(value.ring).into() * TWO_POW_211 - + value.beast_health.into() * TWO_POW_232 - + value.stat_points_available.into() * TWO_POW_241 - + value.actions_per_block.into() * TWO_POW_244) + + StatsPacking::pack(value.stats).into() * TWO_POW_32 + + value.gold.into() * TWO_POW_58 + + ItemPrimitivePacking::pack(value.weapon).into() * TWO_POW_67 + + ItemPrimitivePacking::pack(value.chest).into() * TWO_POW_88 + + ItemPrimitivePacking::pack(value.head).into() * TWO_POW_109 + + ItemPrimitivePacking::pack(value.waist).into() * TWO_POW_130 + + ItemPrimitivePacking::pack(value.foot).into() * TWO_POW_151 + + ItemPrimitivePacking::pack(value.hand).into() * TWO_POW_172 + + ItemPrimitivePacking::pack(value.neck).into() * TWO_POW_193 + + ItemPrimitivePacking::pack(value.ring).into() * TWO_POW_214 + + value.beast_health.into() * TWO_POW_235 + + value.stat_points_available.into() * TWO_POW_244 + + value.actions_per_block.into() * TWO_POW_247) .try_into() .unwrap() } + fn unpack(value: felt252) -> Adventurer { let packed = value.into(); let (packed, last_action_block) = integer::U256DivRem::div_rem( packed, TWO_POW_9.try_into().unwrap() ); let (packed, health) = integer::U256DivRem::div_rem(packed, TWO_POW_9.try_into().unwrap()); - let (packed, xp) = integer::U256DivRem::div_rem(packed, TWO_POW_13.try_into().unwrap()); - let (packed, stats) = integer::U256DivRem::div_rem(packed, TWO_POW_24.try_into().unwrap()); + let (packed, xp) = integer::U256DivRem::div_rem(packed, TWO_POW_14.try_into().unwrap()); + let (packed, stats) = integer::U256DivRem::div_rem(packed, TWO_POW_26.try_into().unwrap()); let (packed, gold) = integer::U256DivRem::div_rem(packed, TWO_POW_9.try_into().unwrap()); let (packed, weapon) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); let (packed, chest) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); @@ -128,7 +129,7 @@ impl AdventurerPacking of StorePacking { beast_health: beast_health.try_into().unwrap(), stat_points_available: stat_points_available.try_into().unwrap(), actions_per_block: actions_per_block.try_into().unwrap(), - mutated: false, + mutated: false, // This field is not packed/unpacked } } } @@ -1669,9 +1670,9 @@ impl ImplAdventurer of IAdventurer { assert(self.health <= MAX_ADVENTURER_HEALTH, 'health overflow'); assert(self.xp <= MAX_XP, 'xp overflow'); assert(self.gold <= MAX_GOLD, 'gold overflow'); - assert(self.stats.strength <= MAX_STAT_VALUE, 'strength overflow'); + assert(self.stats.strength <= MAX_STAT_VALUE_5_BITS, 'strength overflow'); assert(self.stats.dexterity <= MAX_STAT_VALUE, 'dexterity overflow'); - assert(self.stats.vitality <= MAX_STAT_VALUE, 'vitality overflow'); + assert(self.stats.vitality <= MAX_STAT_VALUE_5_BITS, 'vitality overflow'); assert(self.stats.charisma <= MAX_STAT_VALUE, 'charisma overflow'); assert(self.stats.intelligence <= MAX_STAT_VALUE, 'intelligence overflow'); assert(self.stats.wisdom <= MAX_STAT_VALUE, 'wisdom overflow'); @@ -1702,26 +1703,31 @@ impl ImplAdventurer of IAdventurer { } } -const TWO_POW_3: u256 = 0x8; -const TWO_POW_4: u256 = 0x10; -const TWO_POW_9: u256 = 0x200; -const TWO_POW_13: u256 = 0x2000; -const TWO_POW_18: u256 = 0x40000; -const TWO_POW_21: u256 = 0x200000; -const TWO_POW_24: u256 = 0x1000000; -const TWO_POW_31: u256 = 0x80000000; -const TWO_POW_55: u256 = 0x80000000000000; -const TWO_POW_64: u256 = 0x10000000000000000; -const TWO_POW_85: u256 = 0x2000000000000000000000; -const TWO_POW_106: u256 = 0x400000000000000000000000000; -const TWO_POW_127: u256 = 0x80000000000000000000000000000000; -const TWO_POW_148: u256 = 0x10000000000000000000000000000000000000; -const TWO_POW_169: u256 = 0x2000000000000000000000000000000000000000000; -const TWO_POW_190: u256 = 0x400000000000000000000000000000000000000000000000; -const TWO_POW_211: u256 = 0x80000000000000000000000000000000000000000000000000000; -const TWO_POW_232: u256 = 0x10000000000000000000000000000000000000000000000000000000000; -const TWO_POW_241: u256 = 0x2000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_244: u256 = 0x10000000000000000000000000000000000000000000000000000000000000; + +const TWO_POW_3: u256 = 0x8; // 2^3 +const TWO_POW_4: u256 = 0x10; // 2^4 +const TWO_POW_9: u256 = 0x200; // 2^9 +const TWO_POW_13: u256 = 0x2000; // 2^13 +const TWO_POW_14: u256 = 0x4000; // 2^14 +const TWO_POW_18: u256 = 0x40000; // 2^18 +const TWO_POW_21: u256 = 0x200000; // 2^21 +const TWO_POW_26: u256 = 0x4000000; // 2^26 +const TWO_POW_27: u256 = 0x8000000; // 2^27 +const TWO_POW_31: u256 = 0x80000000; // 2^31 +const TWO_POW_32: u256 = 0x100000000; // 2^32 +const TWO_POW_58: u256 = 0x400000000000000; // 2^58 +const TWO_POW_67: u256 = 0x80000000000000000; // 2^67 +const TWO_POW_88: u256 = 0x10000000000000000000000; // 2^88 +const TWO_POW_109: u256 = 0x2000000000000000000000000000; // 2^109 +const TWO_POW_130: u256 = 0x400000000000000000000000000000000; // 2^130 +const TWO_POW_151: u256 = 0x80000000000000000000000000000000000000; // 2^151 +const TWO_POW_172: u256 = 0x10000000000000000000000000000000000000000000; // 2^172 +const TWO_POW_193: u256 = 0x2000000000000000000000000000000000000000000000000; // 2^193 +const TWO_POW_214: u256 = 0x400000000000000000000000000000000000000000000000000000; // 2^214 +const TWO_POW_235: u256 = 0x80000000000000000000000000000000000000000000000000000000000; // 2^235 +const TWO_POW_244: u256 = 0x10000000000000000000000000000000000000000000000000000000000000; // 2^244 +const TWO_POW_247: u256 = 0x80000000000000000000000000000000000000000000000000000000000000; // 2^247 + // --------------------------- // ---------- Tests ---------- @@ -2759,11 +2765,11 @@ mod tests { let adventurer = Adventurer { last_action_block: 511, health: 511, - xp: 8191, + xp: 16383, stats: Stats { - strength: 15, + strength: 31, dexterity: 15, - vitality: 15, + vitality: 31, intelligence: 15, wisdom: 15, charisma: 15, @@ -2828,11 +2834,11 @@ mod tests { let adventurer = Adventurer { last_action_block: 511, health: 511, - xp: 8191, + xp: 16383, stats: Stats { - strength: 15, + strength: 31, dexterity: 15, - vitality: 15, + vitality: 31, intelligence: 15, wisdom: 15, charisma: 15, @@ -2927,10 +2933,19 @@ mod tests { #[available_gas(3000000)] fn test_pack_protection_overflow_strength() { let mut adventurer = ImplAdventurer::new(ItemId::Wand); - adventurer.stats.strength = MAX_STAT_VALUE + 1; + adventurer.stats.strength = 32; AdventurerPacking::pack(adventurer); } + #[test] + #[available_gas(3000000)] + fn test_pack_protection_strength() { + let mut adventurer = ImplAdventurer::new(ItemId::Wand); + adventurer.stats.strength = 31; + let unpacked: Adventurer = AdventurerPacking::unpack(AdventurerPacking::pack(adventurer)); + assert(unpacked.stats.strength == adventurer.stats.strength, 'strength should be same'); + } + #[test] #[should_panic(expected: ('dexterity overflow',))] #[available_gas(3000000)] @@ -2945,10 +2960,19 @@ mod tests { #[available_gas(3000000)] fn test_pack_protection_overflow_vitality() { let mut adventurer = ImplAdventurer::new(ItemId::Wand); - adventurer.stats.vitality = MAX_STAT_VALUE + 1; + adventurer.stats.vitality = 32; AdventurerPacking::pack(adventurer); } + #[test] + #[available_gas(3000000)] + fn test_pack_protection_vitality() { + let mut adventurer = ImplAdventurer::new(ItemId::Wand); + adventurer.stats.vitality = 31; + let unpacked: Adventurer = AdventurerPacking::unpack(AdventurerPacking::pack(adventurer)); + assert(unpacked.stats.vitality == adventurer.stats.vitality, 'vitality should be same'); + } + #[test] #[should_panic(expected: ('intelligence overflow',))] #[available_gas(3000000)] @@ -3192,7 +3216,7 @@ mod tests { let (previous_level, new_level) = adventurer.increase_adventurer_xp(MAX_XP + 10); assert(adventurer.xp == MAX_XP, 'xp should stop at max xp'); assert(previous_level == 2, 'prev level should be 2'); - assert(new_level == 90, 'new level should be 90'); + assert(new_level == 127, 'new level should be max 127'); // u16 overflow case adventurer.increase_adventurer_xp(65535); diff --git a/contracts/adventurer/src/adventurer_meta.cairo b/contracts/adventurer/src/adventurer_meta.cairo index b7c5b6f4a..5048709a4 100644 --- a/contracts/adventurer/src/adventurer_meta.cairo +++ b/contracts/adventurer/src/adventurer_meta.cairo @@ -20,8 +20,8 @@ impl PackingAdventurerMetadata of StorePacking { (value.start_block.into() + StatsPacking::pack(value.starting_stats).into() * TWO_POW_64 - + interface_camel_u256 * TWO_POW_88 - + value.name.into() * TWO_POW_89) + + interface_camel_u256 * TWO_POW_91 + + value.name.into() * TWO_POW_92) .try_into() .unwrap() } @@ -31,7 +31,7 @@ impl PackingAdventurerMetadata of StorePacking { packed, TWO_POW_64.try_into().unwrap() ); let (packed, starting_stats) = integer::U256DivRem::div_rem( - packed, TWO_POW_24.try_into().unwrap() + packed, TWO_POW_27.try_into().unwrap() ); let (packed, interface_camel_u256) = integer::U256DivRem::div_rem( packed, TWO_POW_1.try_into().unwrap() @@ -68,6 +68,9 @@ const TWO_POW_64: u256 = 0x10000000000000000; const TWO_POW_88: u256 = 0x10000000000000000000000; const TWO_POW_89: u256 = 0x20000000000000000000000; const TWO_POW_128: u256 = 0x100000000000000000000000000000000; +const TWO_POW_91: u256 = 0x80000000000000000000000; // 2^91 +const TWO_POW_92: u256 = 0x100000000000000000000000; // 2^92 +const TWO_POW_27: u256 = 0x8000000; // 2^27 #[cfg(test)] #[test] diff --git a/contracts/adventurer/src/constants/adventurer_constants.cairo b/contracts/adventurer/src/constants/adventurer_constants.cairo index 4687ec510..45ef7e75d 100644 --- a/contracts/adventurer/src/constants/adventurer_constants.cairo +++ b/contracts/adventurer/src/constants/adventurer_constants.cairo @@ -2,10 +2,12 @@ const STARTING_GOLD: u16 = 25; const STARTING_HEALTH: u16 = 100; + // Adventurer Max Values const MAX_ADVENTURER_HEALTH: u16 = 511; // 9 bits -const MAX_XP: u16 = 8191; // 13 bits +const MAX_XP: u16 = 16383; // 14 bits const MAX_STAT_VALUE: u8 = 15; // 4 bits +const MAX_STAT_VALUE_5_BITS: u8 = 31; // 5 bits const MAX_GOLD: u16 = 511; // 9 bits const MAX_PACKABLE_ITEM_XP: u16 = 511; // 9 bits const MAX_PACKABLE_BEAST_HEALTH: u16 = 511; // 9 bits diff --git a/contracts/adventurer/src/lib.cairo b/contracts/adventurer/src/lib.cairo index 8f7007090..962f46c8b 100644 --- a/contracts/adventurer/src/lib.cairo +++ b/contracts/adventurer/src/lib.cairo @@ -10,4 +10,4 @@ mod constants { mod discovery_constants; mod adventurer_constants; } -mod leaderboard; \ No newline at end of file +mod leaderboard; diff --git a/contracts/adventurer/src/stats.cairo b/contracts/adventurer/src/stats.cairo index f702cb5e6..e22ff3d96 100644 --- a/contracts/adventurer/src/stats.cairo +++ b/contracts/adventurer/src/stats.cairo @@ -1,10 +1,10 @@ use core::{option::OptionTrait, starknet::{StorePacking}, traits::{TryInto, Into}}; #[derive(Drop, Copy, Serde)] -struct Stats { // 24 storage bits - strength: u8, // 4 bits +struct Stats { // 26 storage bits + strength: u8, // 5 bits dexterity: u8, // 4 bits - vitality: u8, // 4 bits + vitality: u8, // 5 bits intelligence: u8, // 4 bits wisdom: u8, // 4 bits charisma: u8, // 4 bits @@ -23,11 +23,11 @@ impl StatUtils of IStat { impl StatsPacking of StorePacking { fn pack(value: Stats) -> felt252 { (value.strength.into() - + value.dexterity.into() * TWO_POW_4 - + value.vitality.into() * TWO_POW_8 - + value.intelligence.into() * TWO_POW_12 - + value.wisdom.into() * TWO_POW_16 - + value.charisma.into() * TWO_POW_20) + + value.dexterity.into() * TWO_POW_5 + + value.vitality.into() * TWO_POW_9 + + value.intelligence.into() * TWO_POW_14 + + value.wisdom.into() * TWO_POW_18 + + value.charisma.into() * TWO_POW_22) .try_into() .unwrap() } @@ -35,13 +35,13 @@ impl StatsPacking of StorePacking { fn unpack(value: felt252) -> Stats { let packed = value.into(); let (packed, strength) = integer::U256DivRem::div_rem( - packed, TWO_POW_4.try_into().unwrap() + packed, TWO_POW_5.try_into().unwrap() ); let (packed, dexterity) = integer::U256DivRem::div_rem( packed, TWO_POW_4.try_into().unwrap() ); let (packed, vitality) = integer::U256DivRem::div_rem( - packed, TWO_POW_4.try_into().unwrap() + packed, TWO_POW_5.try_into().unwrap() ); let (packed, intelligence) = integer::U256DivRem::div_rem( packed, TWO_POW_4.try_into().unwrap() @@ -61,11 +61,15 @@ impl StatsPacking of StorePacking { } } +const TWO_POW_22: u256 = 0x400000; +const TWO_POW_9: u256 = 0x200; +const TWO_POW_10: u256 = 0x400; +const TWO_POW_5: u256 = 0x20; const TWO_POW_4: u256 = 0x10; const TWO_POW_8: u256 = 0x100; const TWO_POW_12: u256 = 0x1000; -const TWO_POW_16: u256 = 0x10000; -const TWO_POW_20: u256 = 0x100000; +const TWO_POW_14: u256 = 0x4000; +const TWO_POW_18: u256 = 0x40000; const TWO_POW_24: u256 = 0x1000000; // --------------------------- @@ -95,9 +99,9 @@ mod tests { // storage limit test (2^4 - 1 = 15) let stats = Stats { - strength: 15, + strength: 31, dexterity: 15, - vitality: 15, + vitality: 31, intelligence: 15, wisdom: 15, charisma: 15, diff --git a/contracts/game_entropy/Scarb.lock b/contracts/game_entropy/Scarb.lock new file mode 100644 index 000000000..15fad113b --- /dev/null +++ b/contracts/game_entropy/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "game_entropy" +version = "0.1.0"