1use gdlib::{
2 cclocallevels::{
3 gdlevel::GDLevel,
4 gdobj::{
5 GDObject,
6 ids::{objects::TRIGGER_ADVANCED_RANDOM, properties::RANDOM_PROBABILITIES_LIST},
7 structs::Group,
8 },
9 },
10 core::rand::{check_seed_advanced_random, next_seed_mut},
11};
12
13fn main() {
14 let level = GDLevel::from_gmd("test_gmds/Chompstep.gmd").unwrap();
15 let mut objects = level.get_decrypted_data().unwrap().objects;
16
17 objects.retain(|o| o.id == TRIGGER_ADVANCED_RANDOM && o.config.pos.0 > 0.0);
19 objects.sort_by(|a, b| a.config.pos.0.total_cmp(&b.config.pos.0));
20
21 let expected = vec![
24 2, -1, 2, -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, 2, 2, 2, 2, 2,
25 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
26 ];
27 let mut seed = 0;
28
29 while !crack_seed(seed, &expected[..25], &objects) {
32 seed += 1;
33 if seed % 1000000 == 0 {
34 println!("checked seeds until {seed}");
35 }
36 }
37
38 println!("got seed: {seed}");
40}
41
42fn crack_seed(seed: u64, expected: &[i16], objects: &Vec<GDObject>) -> bool {
43 let mut seed_clone = seed;
44
45 for (idx, obj) in objects.iter().enumerate() {
46 if idx == expected.len() {
47 return true; }
49 if expected[idx] == -1 {
50 continue; }
52
53 if !check_object(seed_clone, obj, expected[idx]) {
54 return false;
55 }
56 next_seed_mut(&mut seed_clone);
58 }
59
60 true
61}
62
63fn check_object(seed: u64, object: &GDObject, expected_group: i16) -> bool {
64 let probabilities = object.get_property(RANDOM_PROBABILITIES_LIST).unwrap();
65
66 match check_seed_advanced_random(seed, &probabilities) {
67 Some(Group::Regular(g)) => g == expected_group,
68 _ => false, }
70}