agent

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
4
3 """
4 Initialize a new bowling game.
5 """
6 self.rolls = []
7 self.current_roll = 0
8
59 def roll(self, pins):
6 pass
7
10 """
11 Record a roll in the game.
12
13 Args:
14 pins (int): Number of pins knocked down in this roll.
15
16 Raises:
17 ValueError: If the number of pins is invalid.
18 """
19 # Edge Case: Invalid pin count (negative or more than 10)
20 if pins < 0 or pins > 10:
21 raise ValueError("Pins must be between 0 and 10")
22
23 # Edge Case: Too many pins in a frame
24 # Only check for regular frames (not fill balls)
25 if self.current_roll < 18 and self.current_roll % 2 == 1 and self.rolls[-1] + pins > 10:
26 # Special case: if previous roll was a strike, this is the start of a new frame
27 if self.rolls[-1] != 10:
28 raise ValueError("Cannot knock down more than 10 pins in a frame")
29
30 self.rolls.append(pins)
31 self.current_roll += 1
32
33 # Edge Case: Game already complete
34 # Check if game is over after this roll
35 if self.is_game_complete():
36 # If someone tries to roll after game is complete
37 if self.current_roll > self.get_max_rolls():
38 raise ValueError("Game has ended")
39
840 def score(self):
9 pass
41 """
42 Calculate the total score for the game.
43
44 Returns:
45 int: The total score of the game.
46
47 Raises:
48 ValueError: If the game is not yet complete.
49 """
50 # Check if game is complete
51 if not self.is_game_complete():
52 raise ValueError("Game is not yet complete")
53
54 total_score = 0
55 roll_index = 0
56
57 for frame in range(10):
58 if frame < 9: # Frames 1-9
59 if self.is_strike(roll_index):
60 total_score += 10 + self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
61 roll_index += 1
62 elif self.is_spare(roll_index):
63 total_score += 10 + self.rolls[roll_index + 2]
64 roll_index += 2
65 else:
66 total_score += self.rolls[roll_index] + self.rolls[roll_index + 1]
67 roll_index += 2
68 else: # 10th frame
69 # 10th frame scoring: just sum all rolls in 10th frame
70 total_score += sum(self.rolls[roll_index:])
71
72 return total_score
73
74 def is_strike(self, roll_index):
75 """
76 Check if a roll is a strike.
77
78 Args:
79 roll_index (int): Index of the roll to check.
80
81 Returns:
82 bool: True if the roll is a strike, False otherwise.
83 """
84 # Edge Case: Index out of bounds
85 if roll_index >= len(self.rolls):
86 return False
87 return self.rolls[roll_index] == 10
88
89 def is_spare(self, roll_index):
90 """
91 Check if a frame is a spare.
92
93 Args:
94 roll_index (int): Index of the first roll in the frame.
95
96 Returns:
97 bool: True if the frame is a spare, False otherwise.
98 """
99 # Edge Case: Index out of bounds
100 if roll_index + 1 >= len(self.rolls):
101 return False
102 return self.rolls[roll_index] + self.rolls[roll_index + 1] == 10
103
104 def strike_bonus(self, roll_index):
105 """
106 Calculate the bonus for a strike.
107
108 Args:
109 roll_index (int): Index of the strike roll.
110
111 Returns:
112 int: The bonus points for the strike.
113 """
114 # Edge Case: Not enough rolls for bonus calculation
115 if roll_index + 2 >= len(self.rolls):
116 return 0
117 return self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
118
119 def spare_bonus(self, roll_index):
120 """
121 Calculate the bonus for a spare.
122
123 Args:
124 roll_index (int): Index of the first roll in the spare frame.
125
126 Returns:
127 int: The bonus points for the spare.
128 """
129 # Edge Case: Not enough rolls for bonus calculation
130 if roll_index + 2 >= len(self.rolls):
131 return 0
132 return self.rolls[roll_index + 2]
133
134 def sum_of_balls_in_frame(self, roll_index):
135 """
136 Calculate the sum of pins knocked down in a frame.
137
138 Args:
139 roll_index (int): Index of the first roll in the frame.
140
141 Returns:
142 int: The sum of pins knocked down in the frame.
143 """
144 # Edge Case: Index out of bounds
145 if roll_index >= len(self.rolls):
146 return 0
147 # Edge Case: Only one roll in frame (strike)
148 if roll_index + 1 >= len(self.rolls):
149 return self.rolls[roll_index]
150 return self.rolls[roll_index] + self.rolls[roll_index + 1]
151
152 def is_game_complete(self):
153 """
154 Check if the game is complete.
155
156 Returns:
157 bool: True if the game is complete, False otherwise.
158 """
159 # Count frames completed
160 frames_completed = 0
161 roll_index = 0
162
163 while roll_index < len(self.rolls) and frames_completed < 10:
164 if frames_completed < 9: # Frames 1-9
165 if self.rolls[roll_index] == 10: # Strike
166 roll_index += 1
167 frames_completed += 1
168 else: # Not a strike
169 if roll_index + 1 < len(self.rolls):
170 roll_index += 2
171 frames_completed += 1
172 else:
173 break
174 else: # 10th frame
175 # 10th frame is complete when we have:
176 # - 2 rolls if no strike/spare
177 # - 3 rolls if strike or spare
178 if roll_index + 1 < len(self.rolls):
179 if self.rolls[roll_index] == 10: # Strike
180 return len(self.rolls) - roll_index >= 3
181 elif self.rolls[roll_index] + self.rolls[roll_index + 1] == 10: # Spare
182 return len(self.rolls) - roll_index >= 3
183 else: # Open frame
184 return len(self.rolls) - roll_index >= 2
185 else:
186 break
187
188 return frames_completed >= 10
189
190 def get_max_rolls(self):
191 """
192 Get the maximum number of rolls allowed for this game.
193
194 Returns:
195 int: Maximum number of rolls allowed.
196 """
197 if len(self.rolls) >= 18:
198 tenth_frame_start = 18
199 if len(self.rolls) > tenth_frame_start:
200 if self.rolls[tenth_frame_start] == 10:
201 # Strike in 10th frame allows 2 bonus rolls
202 return tenth_frame_start + 3
203 elif len(self.rolls) > tenth_frame_start + 1 and self.rolls[tenth_frame_start] + self.rolls[tenth_frame_start + 1] == 10:
204 # Spare in 10th frame allows 1 bonus roll
205 return tenth_frame_start + 3
206
207 # Regular game or 10th frame without strike/spare
208 return 20
209
210 # Handled Edge Cases: Invalid pin count, too many pins in a frame, game already complete, extra rolls after game completion
211 # Handled Edge Cases: Game not complete, strike in regular frames, spare in regular frames, open frame in regular frames, 10th frame scoring
212 # Handled Edge Cases: Index out of bounds, not enough rolls for bonus calculation, only one roll in frame
Test NameStatus
test_the_second_bonus_rolls_after_a_strike_in_the_last_frame_cannot_be_a_strike_if_the_first_one_is_not_a_strike
Fail
test_two_bonus_rolls_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Fail
test_a_roll_cannot_score_more_than_10_points
Pass
test_a_spare_followed_by_zeros_is_worth_ten_points
Pass
test_a_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once
Pass
test_a_strike_earns_ten_points_in_a_frame_with_a_single_roll
Pass
test_a_strike_in_the_last_frame_gets_a_two_roll_bonus_that_is_counted_once
Pass
test_a_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus
Pass
test_all_strikes_is_a_perfect_game
Pass
test_an_incomplete_game_cannot_be_scored
Pass
test_an_unstarted_game_cannot_be_scored
Pass
test_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Pass
test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_cannot_roll_after_bonus_roll_for_spare
Pass
test_cannot_roll_after_bonus_rolls_for_strike
Pass
test_cannot_roll_if_game_already_has_ten_frames
Pass
test_consecutive_spares_each_get_a_one_roll_bonus
Pass
test_consecutive_strikes_each_get_the_two_roll_bonus
Pass
test_last_two_strikes_followed_by_only_last_bonus_with_non_strike_points
Pass
test_points_scored_in_the_roll_after_a_spare_are_counted_twice
Pass
test_points_scored_in_the_two_rolls_after_a_strike_are_counted_twice_as_a_bonus
Pass
test_rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll
Pass
test_rolls_cannot_score_negative_points
Pass
test_second_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Pass
test_should_be_able_to_score_a_game_with_all_zeros
Pass
test_should_be_able_to_score_a_game_with_no_strikes_or_spares
Pass
test_strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls
Pass
test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike
Pass
test_two_rolls_in_a_frame_cannot_score_more_than_10_points
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.