Use Tell, Don't Ask: instead of asking the objects what they are and then reacting on that, tell the object what to do and then walls or people do decide how they do what they need to do.
For example:
Instead of having something like this:
public class Wall {
// ...
}
public class Person {
// ...
}
// later
public class moveTo(Position pos) {
Object whatIsThere = pos.whatIsThere();
if (whatIsThere instanceof Wall) {
System.err.println("You cannot move into a wall");
}
else if (whatIsThere instanceof Person) {
System.err.println("You bump into " + person.getName());
}
// many more else branches...
}
do something like this:
public interface DungeonFeature {
void moveInto();
}
public class Wall implements DungeonFeature {
@Override
public void moveInto() {
System.err.println("You bump into a wall");
}
// ...
}
public class Person implements DungeonFeature {
private String name;
@Override
public void moveInto() {
System.err.println("You bump into " + name);
}
// ...
}
// and later
public void moveTo(Position pos) {
DungeonFeature df = currentPosition();
df.moveTo(pos);
}
This has some advantages.
First, you don't need to adjust a giant if then else tree each time you add a new dungeon feature.
Second, the code in the dungeon features is self-contained, the logic is all in the said object. You can easily test it and move it.