1313from getpass import getpass
1414from typing import Optional
1515
16- from .engine import Rules
16+ from .engine import Rules , validate_guess
1717from .game import Game
1818from .scoreboard import ScoreEntry , calculate_score , save_score , top_scores
1919
@@ -24,7 +24,7 @@ def play(
2424 allow_duplicates : bool ,
2525 mode : str = "pvc" ,
2626 max_attempts : int = 10 ,
27- seed : Optional [int ] = None
27+ seed : Optional [int ] = None ,
2828) -> None :
2929 """
3030 Run an interactive game loop in the terminal.
@@ -54,15 +54,12 @@ def play(
5454 print ("(It will not be displayed on screen)" )
5555
5656 while True :
57- secret = getpass (
58- f"Secret code ({ length } characters from '{ alphabet } '): "
59- ).strip ()
57+ secret = getpass (f"Secret code ({ length } characters from '{ alphabet } '): " ).strip ()
6058 try :
61- from .engine import validate_guess
6259 validate_guess (secret , rules )
6360 break
64- except ValueError as e :
65- print (f"Invalid secret: { e } " )
61+ except ValueError as exc :
62+ print (f"Invalid secret: { exc } " )
6663 print ("Please try again.\n " )
6764
6865 game = Game (rules = rules , mode = "pvp" , max_attempts = max_attempts , secret = secret )
@@ -76,14 +73,12 @@ def play(
7673 while not game .is_over ():
7774 attempt_num = game .attempts_used + 1
7875
79- guess = input (
80- f"Attempt { attempt_num } /{ max_attempts } - Your guess: "
81- ).strip ()
76+ guess = input (f"Attempt { attempt_num } /{ max_attempts } - Your guess: " ).strip ()
8277
8378 try :
8479 result = game .make_guess (guesser_name , guess )
85- except ValueError as e :
86- print (f"Invalid guess: { e } \n " )
80+ except ValueError as exc :
81+ print (f"Invalid guess: { exc } \n " )
8782 continue
8883
8984 bulls = result ["bulls" ]
@@ -101,27 +96,30 @@ def play(
10196 print (f"The secret was: { result ['secret' ]} " )
10297 print ()
10398 break
104- else :
105- print (f"Remaining attempts: { result ['remaining_attempts' ]} \n " )
99+
100+ print (f"Remaining attempts: { result ['remaining_attempts' ]} \n " )
101+
102+ # At this point, the game is finished; ensure `won` is treated as bool for typing.
103+ won : bool = bool (game .won )
106104
107105 # Calculate and save score
108106 score_value = calculate_score (
109- won = game . won ,
107+ won = won ,
110108 attempts_used = game .attempts_used ,
111109 max_attempts = max_attempts ,
112- mode = mode
110+ mode = mode ,
113111 )
114112
115113 print (f"Your score: { score_value } " )
116114
117115 entry = ScoreEntry (
118116 player_name = guesser_name ,
119117 mode = mode ,
120- won = game . won ,
118+ won = won ,
121119 attempts_used = game .attempts_used ,
122120 max_attempts = max_attempts ,
123121 score = score_value ,
124- timestamp = ""
122+ timestamp = "" ,
125123 )
126124
127125 save_score (entry )
@@ -132,11 +130,11 @@ def play(
132130 print ("-" * 60 )
133131 top = top_scores (limit = 5 )
134132 if top :
135- for i , e in enumerate (top , 1 ):
136- won_flag = "YES" if e .won else "NO"
133+ for i , entry_item in enumerate (top , 1 ):
134+ won_flag = "YES" if entry_item .won else "NO"
137135 print (
138- f"{ i } . { e .player_name :15} | { won_flag } | Score: { e .score :3} | "
139- f"{ e .mode .upper ()} | { e .attempts_used } /{ e .max_attempts } attempts"
136+ f"{ i } . { entry_item .player_name :15} | { won_flag } | Score: { entry_item .score :3} | "
137+ f"{ entry_item .mode .upper ()} | { entry_item .attempts_used } /{ entry_item .max_attempts } attempts"
140138 )
141139 else :
142140 print ("No scores yet. You're the first!" )
@@ -146,12 +144,14 @@ def play(
146144def main () -> None :
147145 parser = argparse .ArgumentParser (
148146 prog = "mastermind" ,
149- description = "Play Mastermind in your terminal."
147+ description = "Play Mastermind in your terminal." ,
150148 )
151149 parser .add_argument ("--length" , type = int , default = 4 )
152150 parser .add_argument ("--alphabet" , type = str , default = "012345" )
153- parser .add_argument ("--allow-duplicates" , action = "store_true" , default = True )
151+ parser .add_argument ("--allow-duplicates" , action = "store_true" )
154152 parser .add_argument ("--no-duplicates" , dest = "allow_duplicates" , action = "store_false" )
153+ parser .set_defaults (allow_duplicates = True )
154+
155155 parser .add_argument ("--mode" , type = str , choices = ["pvc" , "pvp" ], default = "pvc" )
156156 parser .add_argument ("--max-attempts" , type = int , default = 10 )
157157 parser .add_argument ("--seed" , type = int , default = None )
@@ -168,7 +168,7 @@ def main() -> None:
168168 args .allow_duplicates ,
169169 args .mode ,
170170 args .max_attempts ,
171- args .seed
171+ args .seed ,
172172 )
173173 else :
174174 parser .print_help ()
0 commit comments