@@ -3,7 +3,7 @@ use std::{env, path::Path};
33use anyhow:: { Context , Result , bail} ;
44use hashbrown:: HashMap ;
55use maprando:: {
6- randomize:: { DifficultyConfig , Preprocessor } ,
6+ randomize:: { DifficultyConfig , LockedDoor , Preprocessor , make_locked_door_data } ,
77 settings:: {
88 DisableETankSetting , InitialMapRevealSettings , ItemProgressionSettings , Objective ,
99 ObjectiveSettings , OtherSettings , QualityOfLifeSettings , RandomizerSettings ,
@@ -12,8 +12,8 @@ use maprando::{
1212 traverse:: { LockedDoorData , Traverser } ,
1313} ;
1414use maprando_game:: {
15- Capacity , GameData , LinksDataGroup , NodeId , NotableId , ObstacleMask , RoomId , VertexId ,
16- VertexKey ,
15+ BeamType , Capacity , DoorPtrPair , DoorType , GameData , LinksDataGroup , NodeId , NotableId ,
16+ ObstacleMask , RoomId , VertexId , VertexKey ,
1717} ;
1818use maprando_logic:: { GlobalState , Inventory , LocalState , ResourceLevel } ;
1919use serde:: Deserialize ;
@@ -45,6 +45,8 @@ struct Scenario {
4545 #[ serde( default ) ]
4646 settings : ScenarioSettings ,
4747 global_state : Option < ScenarioGlobalState > ,
48+ #[ serde( default ) ]
49+ locked_doors : Vec < ScenarioLockedDoor > ,
4850 start_room_id : usize ,
4951 start_node_id : usize ,
5052 #[ serde( default ) ]
@@ -111,6 +113,28 @@ struct ScenarioGlobalState {
111113 pool_max_power_bombs : Option < Capacity > ,
112114}
113115
116+ #[ derive( Debug , Deserialize ) ]
117+ #[ serde( rename_all = "camelCase" ) ]
118+ struct ScenarioLockedDoor {
119+ room_id : RoomId ,
120+ node_id : NodeId ,
121+ type_ : ScenarioLockedDoorType ,
122+ }
123+
124+ #[ derive( Debug , Deserialize ) ]
125+ #[ serde( rename_all = "camelCase" ) ]
126+ enum ScenarioLockedDoorType {
127+ Red ,
128+ Green ,
129+ Yellow ,
130+ Charge ,
131+ Ice ,
132+ Spazer ,
133+ Wave ,
134+ Plasma ,
135+ Wall ,
136+ }
137+
114138#[ derive( Debug , Deserialize ) ]
115139#[ serde( rename_all = "camelCase" ) ]
116140struct ScenarioNotable {
@@ -355,6 +379,7 @@ fn get_global_state(
355379 game_data : & GameData ,
356380 difficulty : & DifficultyConfig ,
357381 scenario : & Scenario ,
382+ locked_door_data : & LockedDoorData ,
358383) -> Result < GlobalState > {
359384 let mut flags = vec ! [ false ; game_data. flag_isv. keys. len( ) ] ;
360385
@@ -449,7 +474,7 @@ fn get_global_state(
449474 inventory,
450475 pool_inventory,
451476 flags,
452- doors_unlocked : vec ! [ ] ,
477+ doors_unlocked : vec ! [ false ; locked_door_data . locked_doors . len ( ) ] ,
453478 weapon_mask,
454479 } )
455480}
@@ -542,7 +567,31 @@ fn test_scenario(
542567 game_data. vertex_isv . keys . len ( ) ,
543568 game_data. base_links_data . links . len ( ) ,
544569 ) ;
545- let global_state = get_global_state ( game_data, & difficulty, scenario) ?;
570+
571+ let mut locked_doors: Vec < LockedDoor > = vec ! [ ] ;
572+ for door in scenario. locked_doors . iter ( ) {
573+ let door_ptr_pair = get_door_ptr_pair ( door. room_id , door. node_id ) ;
574+ let door_type = match door. type_ {
575+ ScenarioLockedDoorType :: Red => DoorType :: Red ,
576+ ScenarioLockedDoorType :: Green => DoorType :: Green ,
577+ ScenarioLockedDoorType :: Yellow => DoorType :: Yellow ,
578+ ScenarioLockedDoorType :: Charge => DoorType :: Beam ( BeamType :: Charge ) ,
579+ ScenarioLockedDoorType :: Ice => DoorType :: Beam ( BeamType :: Ice ) ,
580+ ScenarioLockedDoorType :: Spazer => DoorType :: Beam ( BeamType :: Spazer ) ,
581+ ScenarioLockedDoorType :: Wave => DoorType :: Beam ( BeamType :: Wave ) ,
582+ ScenarioLockedDoorType :: Plasma => DoorType :: Beam ( BeamType :: Plasma ) ,
583+ ScenarioLockedDoorType :: Wall => DoorType :: Wall ,
584+ } ;
585+ locked_doors. push ( LockedDoor {
586+ src_ptr_pair : door_ptr_pair,
587+ dst_ptr_pair : ( None , None ) ,
588+ door_type,
589+ bidirectional : false ,
590+ } ) ;
591+ }
592+ let locked_door_data = make_locked_door_data ( locked_doors, game_data) ;
593+
594+ let global_state = get_global_state ( game_data, & difficulty, scenario, & locked_door_data) ?;
546595 let start_local_state = get_local_state ( & scenario. start_state ) ;
547596 let end_local_state = get_local_state ( & scenario. end_state ) ;
548597 let objectives = vec ! [
@@ -585,11 +634,6 @@ fn test_scenario(
585634 . context ( "End vertex not found" ) ?;
586635
587636 let num_vertices = game_data. vertex_isv . keys . len ( ) ;
588- let locked_door_data = LockedDoorData {
589- locked_doors : vec ! [ ] ,
590- locked_door_node_map : HashMap :: new ( ) ,
591- locked_door_vertex_ids : vec ! [ ] ,
592- } ;
593637 let inventory = & global_state. inventory ;
594638
595639 for ( state, name) in [ ( start_local_state, "start" ) , ( end_local_state, "end" ) ] {
@@ -834,6 +878,11 @@ fn test_scenario(
834878 Ok ( ( ) )
835879}
836880
881+ fn get_door_ptr_pair ( room_id : RoomId , node_id : NodeId ) -> DoorPtrPair {
882+ let fake_ptr = ( room_id << 16 ) | node_id;
883+ ( Some ( fake_ptr) , Some ( fake_ptr) )
884+ }
885+
837886#[ test]
838887fn test_logic_scenarios ( ) -> Result < ( ) > {
839888 let base_game_data = GameData :: load_minimal ( Path :: new ( ".." ) ) ?;
@@ -849,6 +898,16 @@ fn test_logic_scenarios() -> Result<()> {
849898 game_data. load_rooms ( & room_pattern) ?;
850899 game_data. make_links_data ( & |_, _| ( 0 , 1 ) ) ;
851900
901+ for & ( room_id, node_id) in game_data. node_json_map . keys ( ) . clone ( ) {
902+ let node_json = & game_data. node_json_map [ & ( room_id, node_id) ] ;
903+ if node_json[ "nodeType" ] == "door" {
904+ let ptr_pair = get_door_ptr_pair ( room_id, node_id) ;
905+ game_data
906+ . door_ptr_pair_map
907+ . insert ( ptr_pair, ( room_id, node_id) ) ;
908+ }
909+ }
910+
852911 let connections_path = entry. path ( ) . join ( "connections.json" ) ;
853912 let connections_list: ConnectionsList = if connections_path. exists ( ) || num_rooms > 1 {
854913 let connections_str = std:: fs:: read_to_string ( connections_path. clone ( ) )
0 commit comments