I would use a voice recorder to "switch" between players:
other = {'A':'B', 'B':'A'}
Then, if serving is equal to 'A' , then other[serving] will be equal to 'B' , and if serving is equal to 'B' , then other[serving] will be equal to 'A' .
You can also use collections.Counter to track scores:
In [1]: import collections In [2]: score = collections.Counter() In [3]: score['A'] += 1 In [4]: score['A'] += 1 In [5]: score['B'] += 1 In [6]: score Out[6]: Counter({'A': 2, 'B': 1})
Also notice how in this code snippet
if serving == "A": for i in range(2): if random() < probA: scoreA += 1 else: scoreB += 1 else: for i in range(2): if random() < probB: scoreB +=1 else: scoreA += 1
there are two blocks that basically repeat the same idea twice. This is a sign that the code can be tightened using the function. For example, we could define a serve function that, when prob and the player ( A or B ) returns the player who wins:
def serve(prob, player): if random.random() < prob: return player else: return other[player]
then the above code will become
for i in range(2): winner = serve(prob[serving], serving) score[winner] += 1
This way you can simplify your code a bit like this:
import random import collections other = {'A':'B', 'B':'A'} def serve(prob, player): if random.random() < prob: return player else: return other[player] def simOneSet(probA, probB): prob = {'A':probA, 'B':probB} score = collections.Counter() serving = "A" while not setOver(score['A'], score['B']): for i in range(2): winner = serve(prob[serving], serving) score[winner] += 1 if score['A'] == 10 and score['B'] == 10: winner = serve(prob[serving], serving) score[winner] += 1 serving = winner return score['A'], score['B'] def setOver(scoreA, scoreB): return max(scoreA, scoreB) >= 21 print(simOneSet(0.5,0.5))