scroll.server/crates/logic/tests/lane_assignment.rs
WiseDev 07f0ee5427 converge combat timers, projectile references, pending damage, and the spawn ring
- replay the shooter's combat update a second time when it launches a
  projectile, matching the client's own component-pass re-entry
- carry the shooter's damage effect on every projectile and null a
  shot's target/source when either leaves the board
- derive pending physical damage from the shots actually in flight
  instead of an incremental total, so it can never go negative
- split the spawn ring's two angle registers so three- and five-unit
  cards land where the client puts them
- attribute a combat target left at NONE to the exact site that did it,
  gated to report each object once
- number and annotate every checksum field so a client-reported
  mismatch resolves straight to a name
2026-08-28 16:27:07 +03:00

88 lines
2.5 KiB
Rust

use logic::battle::{get_lane_id, spawn_lane_of, LogicTilemap};
fn arena() -> LogicTilemap {
LogicTilemap::load(
std::path::Path::new("../../assets"),
"locations/goblin_arena.csv",
)
.expect("the goblin arena tilemap")
}
#[test]
fn the_arena_is_36_by_64_subtiles() {
let tm = arena();
assert_eq!((tm.width(), tm.height()), (36, 64));
}
#[test]
fn the_map_rows_are_all_full_width() {
let tm = arena();
assert_eq!(tm.tiles.len(), 64);
for (y, row) in tm.tiles.iter().enumerate() {
assert_eq!(row.len(), 36, "map row {y} is ragged");
}
}
#[test]
fn the_arena_has_its_river_and_both_lanes() {
let tm = arena();
let tiles = || (0..tm.height()).flat_map(|y| (0..tm.width()).map(move |x| (x, y)));
assert_eq!(
tiles().filter(|(x, y)| tm.lane_bits(*x, *y) >= 1).count(),
692
);
assert_eq!(tiles().filter(|(x, y)| tm.is_water(*x, *y)).count(), 112);
}
#[test]
fn the_right_lane_pinches_to_two_columns_at_the_bridge() {
let tm = arena();
for y in [31, 32] {
assert_eq!(
tm.lane_bits(27, y),
0,
"({},{y}) is off-lane at the pinch",
27
);
assert_eq!(
tm.lane_bits(30, y),
0,
"({},{y}) is off-lane at the pinch",
30
);
assert_eq!(tm.lane_bits(28, y), 2);
assert_eq!(tm.lane_bits(29, y), 2);
}
for y in [30, 33, 34, 40, 47] {
for x in 27..31 {
assert_eq!(tm.lane_bits(x, y), 2, "({x},{y}) is the right lane");
}
}
for y in 30..34 {
for x in 24..27 {
assert!(tm.is_water(x, y), "({x},{y}) should be river");
}
assert!(tm.is_water(31, y), "(31,{y}) should be river");
}
}
#[test]
fn a_drop_by_the_right_bridge_takes_the_right_lane() {
let tm = arena();
assert_eq!(get_lane_id(&tm, 12500, 14500), 2);
assert_eq!(get_lane_id(&tm, 10000, 14500), 2);
assert_eq!(get_lane_id(&tm, 11000, 14500), 2);
}
#[test]
fn a_drop_by_the_left_bridge_takes_the_left_lane() {
let tm = arena();
for (x, y) in [(6923, 8500), (7788, 8999), (7788, 8001)] {
assert_eq!(get_lane_id(&tm, x, y), 1, "({x},{y}) is on the left");
}
}
#[test]
fn the_single_spawn_path_clamps_before_it_reads_the_lane() {
let tm = arena();
assert_eq!(
spawn_lane_of(&tm, -5000, 14500),
get_lane_id(&tm, 250, 14500)
);
assert_eq!(
spawn_lane_of(&tm, 999_999, 14500),
get_lane_id(&tm, 36 * 500 - 250, 14500)
);
}