diff --git a/crates/logic/src/battle/logic_simulation.rs b/crates/logic/src/battle/logic_simulation.rs index fdad36e..59c6e15 100644 --- a/crates/logic/src/battle/logic_simulation.rs +++ b/crates/logic/src/battle/logic_simulation.rs @@ -96,18 +96,6 @@ impl LogicCharacterStats { self.speed == 0 } } -pub fn integer_sqrt(value: i64) -> i64 { - if value <= 0 { - return 0; - } - let mut root = value; - let mut next = (root + 1) / 2; - while next < root { - root = next; - next = (root + value / root) / 2; - } - root -} pub fn distance_squared(from: (i32, i32), to: (i32, i32)) -> i32 { let dx = to.0 - from.0; let dy = to.1 - from.1; @@ -353,16 +341,14 @@ impl LogicBattle { }; let from = positions[index]; let stand_off = stats.range; - let straight = integer_sqrt( - ((goal.0 - from.0) as i64).pow(2) + ((goal.1 - from.1) as i64).pow(2), - ); + let straight = crate::logic_sqrt(distance_squared(from, goal)) as i64; if straight <= stand_off as i64 || straight == 0 { continue; } let waypoint = self.next_waypoint(index, from, goal, stats.flying); let dx = (waypoint.0 - from.0) as i64; let dy = (waypoint.1 - from.1) as i64; - let leg = integer_sqrt(dx * dx + dy * dy); + let leg = crate::logic_sqrt(distance_squared(from, waypoint)) as i64; if leg == 0 { continue; } @@ -424,7 +410,7 @@ impl LogicBattle { if square > sum.saturating_mul(sum) { continue; } - let distance = integer_sqrt(square as i64).max(1); + let distance = crate::logic_sqrt(square).max(1) as i64; let other_mass = if other_stats.is_building() { MASS_FOR_STATIC } else { diff --git a/crates/logic/src/lib.rs b/crates/logic/src/lib.rs index 270eb6e..ad93664 100644 --- a/crates/logic/src/lib.rs +++ b/crates/logic/src/lib.rs @@ -6,7 +6,9 @@ pub mod factory; pub mod home; pub mod logic_random; pub mod messages; +pub mod logic_math; pub mod model; +pub use logic_math::{logic_sqrt, SQRT_TABLE}; pub use commands::{ chest_source, command_type, CommandMeta, CommandOutcome, Execute, LogicBuyCardCommand, LogicBuyChestCommand, LogicBuyResourcePackCommand, LogicClaimAchievementRewardCommand, diff --git a/crates/logic/src/logic_math.rs b/crates/logic/src/logic_math.rs new file mode 100644 index 0000000..d88d896 --- /dev/null +++ b/crates/logic/src/logic_math.rs @@ -0,0 +1,74 @@ +pub const SQRT_TABLE: [i32; 256] = [ + 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, + 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, + 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, + 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, + 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, + 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180, + 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, + 192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, + 202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, + 212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, + 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, + 230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, + 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, + 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255, +]; +pub fn logic_sqrt(value: i32) -> i32 { + if value < 0x10000 { + if value < 256 { + if value < 0 { + return -1; + } + return SQRT_TABLE[value as usize] >> 4; + } + let seed = if value < 4096 { + if value < 1024 { + SQRT_TABLE[(value >> 2) as usize] >> 3 + } else { + SQRT_TABLE[(value >> 4) as usize] >> 2 + } + } else if value < 0x4000 { + SQRT_TABLE[(value >> 6) as usize] >> 1 + } else { + SQRT_TABLE[(value >> 8) as usize] + }; + let next = seed + 1; + return if next.wrapping_mul(next) > value { seed } else { next }; + } + let refined = if value < 0x1000000 { + let seed = if value < 0x100000 { + if value < 0x40000 { + 2 * SQRT_TABLE[(value >> 10) as usize] + } else { + 4 * SQRT_TABLE[(value >> 12) as usize] + } + } else if value < 0x400000 { + 8 * SQRT_TABLE[(value >> 14) as usize] + } else { + 16 * SQRT_TABLE[(value >> 16) as usize] + }; + (seed | 1) + value / seed + } else { + let seed = if value < 0x10000000 { + if value < 0x4000000 { + 32 * SQRT_TABLE[(value >> 18) as usize] + } else { + SQRT_TABLE[(value >> 20) as usize] << 6 + } + } else if value < 0x40000000 { + SQRT_TABLE[(value >> 22) as usize] << 7 + } else { + if value == i32::MAX { + return 0xFFFF; + } + SQRT_TABLE[(value >> 24) as usize] << 8 + }; + let half = ((seed | 1) + value / seed) >> 1; + value / half + half + 1 + }; + let root = refined >> 1; + root - i32::from(root.wrapping_mul(root) > value) +}