private GridState MoveToNewState( GridState state, int xDelta, int yDelta, int keysBitmask) { int newX = state.Location.X + xDelta; int newY = state.Location.Y + yDelta; var p = new Point(newX, newY); if (!grid.ContainsKey(p)) { return(null); } char c = grid[p]; if (c == '#') { // hit a wall return(null); } if (c >= 'A' && c <= 'Z') { // this is a door // key for this door is the associated lowercase letter char key = (char)(c + 32); int keybit = CharToBit(key); // if the key for this door is not in all the keys if ((keysBitmask & keybit) == 0) { // this key is not in the keys we are looking for // at all, so for part 2 it's in a different // quadrant of the grid return(new GridState { Location = new Point(newX, newY), OriginalLocation = state, BitMask = state.BitMask, Steps = state.Steps + 1 }); } // if the key is in the state's found keys - found the key // for this door already so we can move there if ((state.BitMask & keybit) != 0) { return(new GridState { Location = new Point(newX, newY), BitMask = state.BitMask, OriginalLocation = state, Steps = state.Steps + 1 }); } // can't go here return(null); } if (c >= 'a' && c <= 'z') { // we are at another key, pick it up // and move to this location return(new GridState { Location = new Point(newX, newY), Steps = state.Steps + 1, OriginalLocation = state, BitMask = state.BitMask | CharToBit(c) }); } // otherwise this is an empty location, // move there but don't update keys or anything return(new GridState { Location = new Point(newX, newY), BitMask = state.BitMask, OriginalLocation = state, Steps = state.Steps + 1 }); }