+ goalPackets = filter isNatPacket packets
+
+runNetworkUntilTermination :: NatNetwork -> Integer
+-- runNetworkUntilTermination natNet | trace ("Nat: " ++ show (natNet ^. natPacket) ++ " last = " ++ show (natNet ^. natPreviousY)) False = undefined
+runNetworkUntilTermination natNet
+ | part2Termination natNet1 = natNet1 ^. natPacket . packetY
+ | otherwise = runNetworkUntilTermination natNet2
+ where natNet1 = runNetworkUntilIdle natNet
+ np = (natNet1 ^. natPacket) & destination .~ 0
+ net = natNet1 ^. natNetwork
+ net2 = enqueuePacket net np
+ natNet2 = natNet1 & natNetwork .~ net2
+ & natPreviousY .~ (np ^. packetY)
+ & natPacket .~ emptyPacket
+
+part2Termination :: NatNetwork -> Bool
+-- part2Termination natNet | trace ("Term. this: " ++ (show (natNet ^. natPacket)) ++ " prev: " ++ (show (natNet ^. natPreviousY))) False = undefined
+part2Termination natNet = thisY == prevY
+ where thisY = natNet ^. natPacket . packetY
+ prevY = natNet ^. natPreviousY
+
+
+runNetworkUntilIdle :: NatNetwork -> NatNetwork
+runNetworkUntilIdle natNet
+ | isIdle net0 = natNet
+ | otherwise = runNetworkUntilIdle natNet'
+ where net0 = natNet ^. natNetwork
+ net1 = runNetworkStep net0
+ (net2, packets) = extractPackets net1
+ net3 = enqueuePackets net2 packets
+ natPackets = filter isNatPacket packets
+ np = if null natPackets
+ then natNet ^. natPacket
+ else head natPackets
+ natNet' = natNet & natNetwork .~ net3
+ & natPacket .~ np
+
+
+emptyPacket :: Packet
+emptyPacket = Packet {_destination = 0, _packetX = 0, _packetY = 0}
+
+isNatPacket :: Packet -> Bool
+isNatPacket packet = (packet ^. destination) == 255