With a small simulation, as far as I can tell the meanings are:
60 - uniquely mapped read, regardless of number of mismatches / indels
1 - multiply mapped, perfect match or few mismatches / indels
0 - unmapped, or multiply mapped and with lots of mismatches / indels
Sadly, I don't know how many are "few" and "lots", but nonetheless, multiply mapped reads have either MAPQ 0 or 1, whereas uniquely mapped reads have MAPQ of 60.
Looking quickly at the code is more confusing. Apparently, the relevant bits are in
unique.cpp. There are three versions of a MAPQ algorithm. The code seems to be inherited from Bowtie2, and there are several passages with values like 44, 42, 40, 24, 23, and so on. For example, on
// There is no valid second-best alignment and the best alignment has a
// perfect score.
const TMapq pair_nosec_perf = 44;
unique.h, on the V2 of the MAPQ algorithm:
// End-to-end alignment
if (bestOver >= diff * (double)0.8f) ret = 42;
else if(bestOver >= diff * (double)0.7f) ret = 40;
else if(bestOver >= diff * (double)0.6f) ret = 24;
else if(bestOver >= diff * (double)0.5f) ret = 23;
else if(bestOver >= diff * (double)0.4f) ret = 8;
else if(bestOver >= diff * (double)0.3f) ret = 3;
else ret = 0;
So, at first glance, like for Bowtie2 ( How does bowtie2 assign MAPQ scores? ), mismatches would affect MAPQ. However, this is not what happens, and my C++ skills have been nearly exhausted with this exercise.
edit: I am not the first one to have been fooled by the code, see MAPQ values are really useful but their implementation is a mess.