Rooms and trapdoors - for-loop and while-loop efficiency
First things first, stop caring about the number of lines. Unless you are trying to make a code golf competition entry, minimizing the number of lines is the last thing you want to optimize for. This code is hard to read and follow because it is deeply nested and there is very little context to describe what is being done on each line. This code should be broken down into sub functions that encapsulate sections of work.

Compare this line

if knownSafe(roomwidth, roomheight, e, ns0):


to this line

if trapdoor[ns0/roomwidth][ns0 % roomwidth] is "0":


Without knowing anything about the code, I know that the if block is executed if the given arguments describe a location that is known to be safe. Meanwhile, I have no idea why you are indexing into this nested list structure or what the "0" represents.



is does an identity comparison. == does an equivalence comparison. The fact that Two string containing just the character 0 might not always be represented by the same object. The fact that they are is an implementation detail of the Python interpreter you are currently using. Do not use is when you are checking if two values represent the same thing.



for i,m in enumerate(hazardflr):
safetiles.append((m,step))


This is not valid Python. It is likely an issue with posting the question, but as of now, the code in the question does not compile.



Use the Python variable name conventions. Currently, you have a mix of all lower case and camel case. The Python convention is underscore_spaced.

Single letters are rarely good variable names. i is a common convention for index. However, I have no idea what m of e stands for. You also use ns0. From that code, I can see that it is the first element in the nextSafe list. However, that doesn't tell me anything. Why is nextSafe[0] different fromnextSafe[1]? If it is just the current safe location as you iterate over all of the locations, make the variable name curr_safe_location.



You need to pick better data types to represent your state. Lists and strings are great, but they aren't the best way to represent all things. A large portion of your question is describing how your code is structured and what value represent what. This is an indication that the code is hard to read and can be written better. Even if it not required, sometimes making a class is very helpful because it will give value clear descriptive names.

If strings like "X" and "0" are going to have special meanings, at the very least, you should define them as constants. This will give your code more context. Then, if the representation changes, you don't have to look for all instances of "0" and hope every occurrence means the same thing.