Let's say I run a bitcoin client for the first time. It downloads a copy of the blockchain from the very beginning and starts validating all the transactions included in all the blocks.
Since there have been some softforks during Bitcoin's timelife, how does the client know which validation rules needs to apply to validate each transaction?
Even if there are some checkpoints so that there is no need to validate the whole blockchain, how does the client handle different rules for different transactions?
Are there different sets of rules included in the source code, together with block heights indicating when they should be used?