I found a way to get the behavior you want, but with a different syntax than what you present. You have to specify each choice with a unique parameter name/value pair. If that's ok, then the following works:
parser = argparse.ArgumentParser(prog='game.py')
parser.add_argument('--p1', choices=['a', 'b', 'c'], action='append')
args = parser.parse_args(['--p1', 'a', '--p1', 'b'])
print(args)
Result:
Namespace(p1=['a', 'b'])
but this fails appropriately:
parser = argparse.ArgumentParser(prog='game.py')
parser.add_argument('--p1', choices=['a', 'b', 'c'], action='append')
args = parser.parse_args(['--p1', 'a', '--p1', 'b', '--p1', 'x'])
print(args)
Result:
usage: game.py [-h] [--p1 {a,b,c}]
game.py: error: argument --p1: invalid choice: 'x' (choose from 'a', 'b', 'c')
I can find nothing in the docs that suggests that ArgumentParser will take a list of valid values as a parameter value, which is what your version would require.