The Great Robot Race Exercise - Getting required positional argument

Why am I getting these required positional arguments errors? It looks like it’s the correct number of arguments to me, but obviously I’m missing something.

Link to excercise: https://www.codecademy.com/courses/learn-intermediate-python-3/projects/the-great-robot-race-python-project

import robot_race_functions as rr from collections import deque, Counter, namedtuple from time import time, sleep maze_file_name = 'maze_data_1.csv' seconds_between_turns = 0.3 max_turns = 35 # Initialize the robot race maze_data = rr.read_maze(maze_file_name) rr.print_maze(maze_data) walls, goal, bots = rr.process_maze_init(maze_data) # Populate a deque of all robot commands for the provided maze (Checkpoint #5) robot_moves = deque() num_of_turns = 0 while not rr.is_race_over(bots) and num_of_turns < max_turns: # For every bot in the list of bots, if the bot has not reached the end, add a new move to the robot_moves deque # Add your code below! for bot in bots: if bot.has_finished == False: robot_moves.append(rr.compute_robot_logic(walls, goal, bot)) num_of_turns += 1 # Count the number of moves based on the robot names # Add your code below! move_count = Counter(move[0] for move in robot_moves) # Count the number of collisions by robot name # Add your code below! collision_count = Counter(move[0] for move in robot_moves if move[2] == True) # Create a namedtuple to keep track of our robots' points # Add your code below! BotScoreData = namedtuple('name', ['num_moves', 'num_collisions', 'score']) # Calculate the scores (moves + collisions) for each robot and append it to bot_scores # Add your code below! bot_scores = [] # scores = move_count + collision_count for bot in bots: bot_scores.append(BotScoreData(bot.name, [move_count, collision_count, move_count + collision_count])) # bot_scores.append(BotScoreData(bot.name, [move_count, collision_count, move_count + collision_count])) # Populate a dict to keep track of the robot movements # Add your code below! bot_data = {} for bot in bots: bot_data[bot.name] = bot # Move the robots and update the map based on the moves deque while len(robot_moves) > 0: # Make sure to pop moves from the front of the deque # Add your code below! bot_name, direction, has_collided = robot_moves.popleft() bot_data[bot_name].process_move(direction) # Update the maze characters based on the robot positions and print it to the console rr.update_maze_characters(maze_data, bots) rr.print_maze(maze_data) sleep(seconds_between_turns - time() % seconds_between_turns) # Print out the results! rr.print_results(bot_scores)

I am getting the following Trace back for line 46.

Traceback (most recent call last):
File “robot_race.py”, line 46, in
bot_scores.append(BotScoreData(bot.name, [move_count, collision_count, move_count + collision_count]))
TypeError: new() missing 1 required positional argument: 'score

The code is supposed to calculate the ‘score’ (move_count + collission_count)

What have I tried:
This is what I had originally with the square brackets removed. This returns an error 4 positions required, 5 given.

for bot in bots: bot_scores.append(BotScoreData(bot.name, move_count, collision_count, move_count + collision_count))

I then tried using the square brackets to match the syntax of the namedtuple BotScoreData
That is now giving me the ‘missing 1 required position error’.

I also tried deleting the score item all together, and the program runs but will not print out the bots scores.

I had a very different version of that namedtuple:

BotScoreData = namedtuple('BotScoreData', ['name', 'num_moves', 'num_collisions', 'score'])

and then in the loop, I had

  score_data = BotScoreData(name, moves, collisions, score)

I think the arguments for BotScoreData are not just the list, but a bunch of stuff (or I guess you could use a list with the * in front).

2 Likes

I think it might be case of misinterpreting the initialisation of the new type from the collections.namedtuple function.

@blog7119281363 that first argument namedtuple('name'... should be the new type name, typically set to identifier you bind to this new type e.g. BotScoreData = namedtuple('BotScoreData',...
https://docs.python.org/3/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields

Like the way @janbazant1107978602 uses it, the name of the bot is probably one the fields you pass in the second argument and when creating an instance of this new type you would pass them as single arguments in the construct call.

1 Like

Oh man, I knew it would be something simple that I simply wasn’t seeing. Thank you so much. That was the issue.

1 Like