Level 7: Challenge 2 - IncrediCoders/Python1 GitHub Wiki
Syntax Turtle added this page on June 6, 2025
It's time for your second challenge for Level 7!
Hopefully, Challenge 1 wasn't too hard. :)
This challenge is going to be harder. If you think about it, this is the last level of the book, and the second/last challenge of the last level! So, this should be the most difficult of the challenges! They aren't called "challenges" for no reason!
However, we (Syntax and Grafika) are going to help you through each step! You can do it!
For this challenge, you're going to add a second attack option to the game, the Coded Attack! First, you always delivery one hit of damage to the opponent card. This is important, because unlike the TechType Attack, you're guaranteed to deliver this one point of damage!
The Coded Attack also gives your card a special ability, if you get Heads on the coin flip!
What are the Coded Attack special abilities?
What that special ability is, depends on the card. Each card has one of these special abilities (if the coin lands on Heads):
- You deliver an extra hit, totaling two damage.
- You get another turn!
- You get one health back.
- You make your opponent get Tails in their next turn!
To find the Level 7 Challenge 2 code template, open the Level 7 folder, the Challenges folder, and then the Challenge2 folder. (In our GitHub repo, you can find the code template in the Challenge2 folder.) You should already have the files all set up and ready to go (see Set up the files). Open the IncrediCards_Challenge2.py file to build the program, by following along with my instructions below!
I broke these instructions down into a few sections:
You should have your IncrediCards_Challenge2.py file loaded into your code editor.
On Line 1, from init import * imports code from the init.py file, which sets up the game and includes the features and functions that you'll use throughout this game. The asterisk specifies that we're importing everything from the file.
Line 3 includes the comment, # Create all of the cards. This comment explains that Lines 4-24 (this section of code between the spaces on Lines 2 and 25) create the cards' objects that provide all the details.
NEW CODE: On Line 4, we have our first #TODO code comment! As the comment says, you're going to add another argument to Lines 5-24. See the next section, "Write Your Own Code" below, with instructions on how you're going to add one more parameter to each character card's function. It's the name of the Coded Attack. For now, let's keep explaining the code that's already in the file!
Lines 5-24 create all the cards, including the primary variables for the cards. Then, we also create all the attributes for the cards... the names on the cards, the primary programming languages that each student uses (we call these their "TechTypes"), the TechTypes that they are weak to, the TechTypes that they are strong/resistant to, their PNG file variables (such as annie_conda_img), and their TechType icon variables (such as icon_python). These PNG and icon variables are what show the images on the screen. For example, on Line 5, we have the code, annie_conda = Card('Annie Conda', 'python', 'java', 'bash', annie_conda_img, icon_python, 'gain_health', 'Super Squeeze').
Can you describe what content is in each variable?
On Line 26, the code DECK = [] creates the DECK list. A list is a variable that's an array. (Other programming languages use the term array, but Python uses the term list instead.) You can put a lot of information into the one list, like other variables, strings, numbers, etc. It's just like how you can use multiple drawers in one filing cabinet. Each drawer is like a spot in that list. Annie mentioned this to Paul back in Level 3.
Lines 29-48 append our variables into different spots in our DECK list. For example, on Line 45, DECK.append(viralmuto) appends all the attributes (back from Line 21) into the one spot in the DECK list. As the code comment on Line 28 explains, this adds all the cards to the deck.
On Line 50, random.shuffle(DECK) shuffles the cards that are in the deck. This means that all the variables (the cards) that are in the DECK list are arranged in a random order. That way, when you start the game, you'll likely have a different set of cards that you play with, every time!
On Line 52, you'll see the code, class PlayScreen(GameState): The game's play screen is one of a few different game states, which are like modes or screens, that the player can move between. Most of the game takes place on the play screen. Other examples of game states are the welcome screen and the game over screen.
In Lines 54-72, we pass the self variable into our _init_() function, to set up (or initialize) the play screen, with all the graphics on it.
NEW CODE: On Line 60, you'll see the code comment, #TODO: Copy the code to add the Coded Attack button and the action_params attribute below. In the "Write Your Own Code" section below, we'll show you the code to add to Lines 61-62.
NEW CODE: Next, on Line 63, you'll find the code comment, #TODO: Change the instructions argument for the Info Box to use the CHALLENGE_INSTRUCTIONS instead. In the "Write Your Own Code" section below, we'll show you how to change Line 64 to add our new Coded Attack messages in the Info Box.
On Line 74, we define the start() function, with the code, def start(self, players): Lines 75-77 are in that function block and set up the self.players, self.player1, and self.player2 variables, so that we can use them later in the game.
On Line 79, we set the active player to be the attacker. This is based on the coin toss that the players see, before they pick their cards.
On Line 80, we set the defender, which is the player who is going to be attacked for that turn.
On Line 82, we set the card that gets displayed as the active card for Player 1. This is based on which card you picked to start with, on the "choose hand" screen. Or whenever you click a new card in your On Deck box, this is the function that displays that card as your new active card.
On Line 83, we set the card that gets displayed as the active card for Player 2.
On Lines 85-86, we display the players' health bars. This is what visually shows how much life the players have left.
On Lines 88-89, we display the current cards in the players' On Deck boxes.
On Line 91, self.dialog_box = DialogBox((200,300), (X_CENTER-100, 50)) displays the dialog box in the middle of the screen, between the two players' cards. This is the box where the players will see the instructions and information about the game they're playing.
On Lines 93-98, you define the get_event() function. It allows the program to grab the events when the currently active player clicks the TechType Attack button or the Coded Attack button. It also gets the events when either player clicks any of the On Deck cards, in order to switch their card. (The players can switch their cards even when they aren't the active player.)
On Lines 100-105, you define the button_action() function. This function flips the coin when the active player clicks the TechType Attack button.
On Lines 107-217, you define the update() function. This is the main function of the game. It updates the graphics on the screen, transitions between the players' turns, and it displays the messages that describe the results of each turn. This function is a lot longer for Challenge 2, because this is where we put the logic for the new CodedAttack button!
We're now going to break down the update() function to see all the different things that this function does!
Lines 108-115 update the players' health bars, On Deck boxes, and displayed cards, if needed. For example, if Player 1 picked a new On Deck card, then when the update() function runs, it will show the new displayed card on the screen, and it will update what cards are listed in Player 1's On Deck box.
On Lines 117-120, we check if the coin is flipping during this turn. If so, then we animate the coin flipping.
On Lines 122-124, we then check if the turn is ready to move on to the action part, where a change happens (after the coin flip). If so, we set which card is attacking (the offense_card) and which card is defending (defense_card).
On Lines 126-128, we add the messages into the message variable, to update the players on what happened with the attack. Later, we display these messages in the Dialog box in the middle of the screen.
Lines 131-156 contain our logic for running the TechType Attack (as the code comment on Line 130 explains). On Line 131, the code if not self.coded_attack: makes sure you clicked the TechType Attack button and not the Coded Attack button. You previously wrote some of the code when you first made this game (following along with the book's instructions). For more details, see the Level 7: Help Glossary of Terms, #35-46, to follow through this process more. The Advice on Writing the Code section also gives more details.
Because we already covered the TechType Attack logic, the else: statement on Line 159 begins our logic for the new Coded Attack option.
NEW CODE: Next, you're going to write the code on Line 161. See the next section, "Write Your Own Code." Let's keep explaining the rest of the code.
Line 163 includes the code comment, # Flip the coin for the offense card's extra effect, to explain what the if block does on Lines 164-194.
On Line 164, you'll see the code, if self.side_up == 'Heads': This if statement checks if the coin lands on heads (for the Coded Attack). As the code comment on Line 165 explains, if the coin lands on heads, then there are four different paths that the code logic can take. Those are the four if statements on Lines 168, 175, 178, and 189. Let's take a look at each one!
On Line 168, you'll see the statement, if offense_card.coded_type == 'extra_hit': This statements checks if the particular character card uses the Coded Attack special ability known as 'extra hit'. This ability makes it so that the attacking card deals an extra one point of damage, for a total of two pointes of damage.
The TechType Attack can deal three damage, but it only deals two damage if your opponent is resistant to your TechType, and you only have a 50% chance of success. With this Coded Attack, you always deal one damage to your opponent, and you have a 50% chance of dealing two damage instead. So, you can see why this attack can be valuable in certain situations.
NEW CODE: Next, you're going to write the code on Line 170, which makes the defense card take an extra point of damage. As usual, you're going to add this line of code under a #TODO code comment, which in this case is the comment on Line 169: #TODO: Add the code to make the defense card take 1 damage. See the next section, "Write Your Own Code."
Line 171 displays the message to announce that the attacking card has dealt two damage points to the defending card.
NEW CODE: Next, you're going to write the code on Line 173, which switches to the active player. This is under the code comment on Line 172, #TODO: Add the code to switch the active player. This function switches the players on the new turn, so the player who was on defense, is now on offense. See the next section, "Write Your Own Code."
See the code comment on Line 174, # Extra Turn - This gives the active player an extra turn, does not switch active player. This explains Lines 175-176.
On Lines 175-176, this if statement gives the active player an extra turn! This statement checks if the particular character card uses the Coded Attack special ability known as 'extra turn'. This Coded Attack will allow the player to continue playing without switching the active player to the other player! In other words, the current player gets an extra turn.
Next, you'll see the code comment on Line 177, # Gain Health - This adds 1 health to the active card if it has damage (or to any other card in the player's hand with damage) and then it switches the active player. This explains the if block on Lines 179-186. The Gain Health feature adds one health to the active card if the active card has taken a hit (has less than 15 health). If the active card has full health, then the game looks at the first card in On Deck (and adds one health if it has taken damage). If the first card has all its health, then it checks the second card in the On Deck box (and adds one health if it has taken damage). If none of the cards have taken damage, then the message on Line 182 explains to the user (in the Dialog box in the middle of the screen) that all the player's cards already have max health.
On Line 178, you'll see our third type of special ability, with the code, if offense_card.coded_type == 'gain_health':
Each character card is already assigned to one of the four Coded Attack special abilities (each card includes text that explains its Coded Attack special ability). For this 'gain_health' ability, your character gains one health back (if you flipped heads).
On Line 179, you'll see the code comment, #TODO: Add the code to make the offense player gain 1 health point (Hint: Players have a method called gain_health()). This comment describes the code that you're going to complete on Line 180.
NEW CODE: Line 180 was started for you! You're going to add the second part of that line of code, to call the gain_health() method, which adds 1 health back to your character. If your current card already has full health, you'll get a health point back on another card (if applicable). See the next section, "Write Your Own Code."
On Line 181, the if statement checks to see if all the cards have full health. That means no cards can be healed. The message on Line 182 announces to the players that all the cards have full health.
On Line 183, the else: statement runs to display a message (Line 184) that tells the players which character gained back 1 health point.
On Line 185, you'll see the code comment, #TODO: Add the code to switch the active player.
NEW CODE: Next, you're going to write the code on Line 186, which switches the active player, for the next turn. For example, if Player 1's turn is over, then this code switches to Player 2's turn. See the next section, "Write Your Own Code."
On Line 188, you'll see the code comment, # Opponent Tails - This forces the next spin to be a 'Tails' and switches the active player. This comment describes what the code does in the if block, on Lines 189-194.
It's time for the last Coded Attack special ability! On Line 189, the if statement checks if the attacking player's Coded Attack special ability is 'opponent_tails'. This special ability forces your opponent to get tails on their next turn's coin flip (no matter what attack they choose). (If they're smart, they'd pick the Coded Attack, because at least then they'd still do one damage to their opponent.)
On Line 190, you'll see the code comment, #TODO: Add the code to set the game's attribute for forcing tails to be 'True'. This instruction is for what you're going to write on Line 191.
NEW CODE: Next, you're going to write the code on Line 191, which makes the opponent get tails in their next turn's coin flip. See the next section, "Write Your Own Code."
On Line 192, the code displays a message that lets the players know that the opponent will get tails on their next coin flip.
On Line 193, you'll see the code comment, #TODO: Add the code to switch the active player. This describes the code that you'll add on Line 194.
NEW CODE: Next, you're going to write the code on Line 194, which switches the active player, for the next turn. You should be great at writing that line of code by now! See the next section, "Write Your Own Code."
Line 196 is another else: statement. This one runs if the attacking player gets tails for their Coded Attack. The defending player still takes 1 damage point.
On Line 197, you'll see the comment, # Coded attack fails; defense still takes 1 damage, and the game switches the active player. This comment describes the context of this else block (on Lines 196-200) and what happens in the block of code.
On Line 198, the code displays the message on the screen, explaining that the defending player took 1 damage point. It's time to switch players again!
The code comment on Line 199 instructs you to add the code that switches the players.
NEW CODE: Next, you're going to write the code on Line 200, which switches the active player, for the next turn. See the next section, "Write Your Own Code."
On Line 202, you'll see the code comment, # The following needs to happen for every Coded Attack scenario. This describes the code on Lines 203-204.
On Lines 203-204, the code adds the last turn's message to the dialog box, based on the outcome of the turn.
On Lines 206-207, we refresh the hands of the players, for the new turn. For example, if one card lost, then the next card becomes the attacking card.
On Line 209, you'll see the code comment, #TODO: Add the code to set the game's coded attack attribute to 'False' (Hint: Look at line 70).
NEW CODE: Next, you're going to write the code on Line 210, which turns off the Coded Attack, to reset it for the next turn. See the next section, "Write Your Own Code."
Line 211 resets the action for the next turn. The turn is now over, and it sets up the next turn. This is a signal for the coin animation to reset, so that it's ready for the next turn.
Line 212 increments 1 to the counter, so that the game counts the total number of turns and knows which turn we're on.
Lines 214-217 check if a player ran out of cards and if there's a winner. If so, then it sets the winner and ends the game.
Lines 219-224 define the flip_coin() function. It randomly determines which side is up, and then it returns that information (in the side variable).
Lines 226-235 complete the steps of switching the attacking player to the defending player and vice versa.
Lines 237-245 define the check_game_end() function. This function checks the status of both players. If there is only one surviving player, then we end the game (see Line 245).
Lines 247-265 define the draw() function. It updates all of the graphics on the screen, for each new round.
On Lines 267-274, states = {} declares a collection of states (which are different screens) that are needed for the game. This is also called a state machine, which provides the overall structure for the game logic. That includes any different modes or screens. It's a logical structure for your game code, where you don't need to put all your code into a loop to run the game.
Line 268 enters the TitleScreen() into the state machine, which is the screen you see when you start the game. Line 269 adds in GetNameScreen(), which is the screen where you enter in the names of the two players. Line 270 adds in the CoinFlipScreen(), which is where you flip a coin to see who goes first.
Line 271 adds in ChooseHandScreen(DECK), which is where you pick the card that you want to start with. Line 272 adds in PlayScreen(), which is the main game screen. And, finally, Line 273 adds in VictoryScreen(), which is the screen you go to when the game is over.
Line 276 is game = GameRunner(SCREEN, states, "Title"). It's the line that starts the game runner. Everything up to this line was all the setup, but this line starts running the code.
On Line 4, we have our first #TODO code comment! You're going to add one more parameter to each character card's function. It's the name of the Coded Attack.
Lines 5-24 create all the cards, including the primary variables for the cards. First, you'll add in the missing attributes... the names of the Coded Attacks.
On Line 5, Annie Conda's Coded Attack was already added in for you, as the last attribute in the function. It's called 'Super Squeeze'.
On Lines 6-24, you're going to add in the 8th attribute for each character card:
- Inside (to the left of) the end parenthesis, add a comma.
- After the comma, add a space.
- Type in the name of the character's CodedAttack. Be sure to use title casing (where the first letter of each word is capitalized) and put the title in single quotes.
- Make sure each line ends with the end parenthesis.
Here are the character card CodedAttack names to add in:
- On Line 6, for Bayo Wolf, add in
'Bitter Bite'as the eighth attribute. - On Line 7, for Captain Javo, add in
'Punch Line'as the eighth attribute. - On Line 8, for Cryptic Creeper, add in
'Viper Strike'as the eighth attribute. - On Line 9, for Emily Airheart, add in
'Helmet Headbutt'as the eighth attribute. - On Line 10, for Grafika Turtle, add in
'Shell Smash'as the eighth attribute. - On Line 11, for Intelli-Scents, add in
'Cranium Caning'as the eighth attribute. - On Line 12, for Java Lynn, add in
'Flying Kick'as the eighth attribute. - On Line 13, for Jitter Bug, add in
'Dance Fight'as the eighth attribute. - On Line 14, for Justin Timbersnake, add in
'Pop'as the eighth attribute. - On Line 15, for Mrs. Scratcher, add in
'Purrfect Pounce'as the eighth attribute. - On Line 16, for Paul Python, add in
'Mech Mash'as the eighth attribute. - On Line 17, for Queen Cobra, add in
'Class Lecture'as the eighth attribute. - On Line 18, for RAM and ROM, add in
'Twin Spin'as the eighth attribute. - On Line 19, for SideWinder, add in
'Goth Glare'as the eighth attribute. - On Line 20, for Syntax Turtle, add in
'Board Slam'as the eighth attribute. - On Line 21, for ViralMuto, add in
'Cape Whip'as the eighth attribute. - On Line 22, for Virobotica, add in
'Scepter Smash'as the eighth attribute. - On Line 23, for the Virobots, add in
'Dog Pile'as the eighth attribute. - On Line 24, for Woodchuck norrs, add in
'Roundhouse Kick'as the eighth attribute.
The next section where you need to add in missing code is at Lines 61-62.
On Line 60, you'll find the comment that explains this next task: #TODO: Copy the code to add the Coded Attack button and the action_params attribute below.
Line 61 is similar to what you wrote on Line 58:
- Make sure you're indented at the same level as Lines 59 and 60.
- On Line 61, type in the
self.coded_attack_buttonvariable. - Next, type in a space, an equal sign, and another space.
- Then type in the
Button()function. - This time, it won't be the "TechType Attack" text. Instead, type in
"Coded Attack",as the text that appears on the button. (Be sure to use the comma.) This is the first attribute for this function. - Next, still inside the function parentheses, type
X_CENTER-85, 575, 170, 40,to determine the position/placement of the button. -
Type
coin_yellow, coin_dark_yellow,to make the color of the button and the button outline to be different shades of yellow. ("Coin yellow" is a color that means it's yellow, like how you'd expect a gold coin to appear.) - The last code you're going to add (still in the function's parentheses) is the same as Line 58. Type in
parent = selfto make the button independent (so it's not attached to a parent element or object on the screen). Make sure you end the line with the closing parenthesis.
On Line 62:
- Make sure you're indented at the same level as Lines 58-61.
-
Type in a long variable:
self.coded_attack_button.action_params
- That's all one variable, so there should be no spaces.
- Add a space, an equal sign, and another space.
- Type in "coded" with the quotation marks.
- The line should look similar to Line 59 (which was for the Tech Attack, not the Coded Attack).
This line changes the function of the button to the Coded Attack function (and features) for each card. In other words, this line sets up the button_action function on Line 100, to go into the Coded Attack (instead of the TechType Attack).
Now we're moving onto the next line of code that you'll need to update, Line 64.
Line 63 explains the next task with the code comment, #TODO: Change the instructions argument for the Info Box to use the CHALLENGE_INSTRUCTIONS instead.
On Line 64, you're given this line of code: self.instructions_box = InfoBox(INSTRUCTIONS, dialog_inst, BLACK, (200, 300), (X_CENTER, 200), 200). Next, you need to change it so that the argument for the Info Box uses the CHALLENGE_INSTRUCTIONS instead. This calls the new instructions into the info box, which explain the new Coded Attack feature.
Here's what you need to change:
-
Replace
INSTRUCTIONSwithCHALLENGE_INSTRUCTIONSinstead.
This is the first parameter in the InfoBox() function.
Now, let's hop on down to Line 161! You're going to add a line of code that makes the defense card take 1 damage. (The Coded Attack always gives the opponent one point of damage, even if the player flips the coin to Tails.)
On Line 160, you'll see the code comment, #TODO: Add the code to make the defense card take 1 damage (Hint: Cards have a method called take_damage()).
On Line 161, add the following code:
-
Type in
defense_cardto identify the variable. This points to the card that you're going to attack. - Next, type in a period
.with no spaces. This signals you're going to be calling a function on thedefense_cardvariable. - Then type the function
take_damage()to cause the defense card to take damage. -
Type the number
1in the parentheses. The card will take one damage.
Next, you're going to add in Line 170. Find the code comment on Line 169, #TODO: Add the code to make the defense card take 1 damage.
Line 170 is the exact same text as Line 161:
- Type in the code from Line 161!
Just like before, the defense card takes 1 damage. We run Line 170 when the attacking card has the extra_hit Coded Attack special ability that provides an extra hit!
Next is Line 173. Find the code comment on Line 172, #TODO: Add the code to switch the active player. You're going to add code that switches to the active player (for the next turn).
On Line 173, type in the code:
-
Type in
selfas the variable that you're running the function on. The variableselfrepresents the game screen. We're just telling the game screen to switch players. - Next, type in a period
.with no spaces. This signals you're going to be calling a function on the variable. - Finally, type in the
switch_active_player()function. You don't need to add any parameters in the parentheses.
Now let's move on to Line 186! Find the code comment on Line 185, #TODO: Add the code to switch the active player. You're going to do the same thing that you did on Line 173, where you switch to the active character. It's exact same code!
On Line 186, type in the same code from Line 173. This switches the active player so the other player can take a turn.
Now, move down to Line 191. Find the code comment on Line 190, #TODO: Add the code to set the game's attribute for forcing tails to be 'True'. This time, you're adding code that sets the game's attribute to force tails to be True.
On Line 191:
-
Type in the
self.force_tailsvariable. This variable will make sure the next time the coin is flipped, it lands on tails. - Add a space, an equal sign, and then another space.
-
Type in
Trueto end the line with the Boolean keyword that activates this state.
Next, you're going to write the code on Line 194, which switches the active player again (for the new turn). Find the code comment on Line 193, #TODO: Add the code to switch the active player.
On Line 194:
- Write the same code that you did on Line 186. It's also the same code on Line 173.
In the first part, the self variable represents the game screen. After the period, you added the function that switches to the active character, for the new turn. You can use this function, switch_active_player(), with no parameters needed (nothing inside the parentheses). Don't forget to add a . between the variable and the function. This one sets up the Coded Card attack that forces the opponent to get tails on the next coin flip.
On Line 200, you're going to add the code to switch the active player again. On Line 199, find the code commend, #TODO: Add the code to switch the active player.
On Line 200:
- Type in the same code that you added on Lines 173, 186, and 194.
This time, your code isn't indented as far. Make sure it's indented at the same level as Lines 197-199. Line 200 runs after a Coded Attack gets tails. The defending player still takes one damage.
Next, jump on down to Line 210. Find the code comment on Line 209, #TODO: Add the code to set the game's coded attack attribute to 'False' (Hint: Look at line 70). You are going to add the code to set the game's coded attack attribute to False this time.
On Line 210:
-
Type in the
selfvariable. -
Type in a
.symbol (a period). (No space.) -
Type in the
coded_attackpart of the variable after the period (no spaces). -
Add a space, add equals
=(an equals sign), and another space. -
Type in
Falseto turn off the Coded Attack mode. We'll turn it back on when the current offensive player clicks the Coded Attack button.
Make sure you're indented at the same level as Lines 209 and 211. Refer back to Line 70 if you need more help putting it together (it's the same line of code).
I included a solution file for Level 7, Challenge 2. This file has all the code filled in, so if you run into any issues with your code (for example, if it doesn't compile/run, or if something isn't working correctly in your program), then you can take a look at the final code file to see what you did differently:
IMPORTANT: Please don't cheat yourself! Finish the game first!
In addition to these Level 7 challenges, we also have the Help page for the book, Online Articles, a Learning Quiz, an Unplugged Activity, and a Rewards article:
-
Level 7: Help - This page helps you complete the instructions in the book, in case you get stuck.
-
Level 7: Online Articles - I made you a list of different web pages I found, which will help you learn more about the lessons we covered in Level 7.
-
Level 7: Learning Quiz - I wrote some questions in case you want to quiz yourself about what you learned. Or you can teach others and quiz them!
-
Level 7: Unplugged Activity - In this game, we recreate the basic aspects of the IncrediCards game, but in real life!
-
Level 7: Rewards - If you completed the IncrediCards project that we talked about in our text messages, then I set up this page to act as a reward. You can see some illustrations of how the art of the card game was made!