Skip to main content

Code Style Guidelines

Cub3D follows the 42 school norm, a strict coding standard that ensures consistency and readability.

The 42 Norm

Function Length

Maximum 25 lines per function (excluding opening/closing braces)

Line Length

Maximum 80 columns per line

Functions per File

Maximum 5 functions per .c file (flexible for complex modules)

Variables

Maximum 4 variables per function, aligned declarations

Function Header Format

All functions must have the 42 header comment:
Example Header
/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   filename.c                                         :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: username <username@student.42.fr>          +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: YYYY/MM/DD HH:MM:SS by username          #+#    #+#             */
/*   Updated: YYYY/MM/DD HH:MM:SS by username         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

Formatting Rules

Use tabs for indentation, not spaces.
void	function_name(t_map *mapa)
{
	int		i;
	int		count;

	i = 0;
	while (i < 10)
	{
		count++;
		i++;
	}
}
  • One tab per indentation level
  • Align variable declarations with tabs
  • Use tabs between type and variable name

Example: Norm-Compliant Function

Good Example
void	calculate_wall_data(t_map *mapa, double *dist)
{
	if (mapa->side == 0)
		*dist = (mapa->map_x - mapa->xx + (1 - mapa->step_x) / 2)
			/ mapa->ray_dir_x / SIZE;
	else
		*dist = (mapa->map_y - mapa->yy + (1 - mapa->step_y) / 2)
			/ mapa->ray_dir_y / SIZE;
	mapa->line_height = (int)(HEIGHT / *dist);
	if (mapa->side == 0)
		mapa->wall_x = mapa->yy / SIZE + *dist * mapa->ray_dir_y;
	else
		mapa->wall_x = mapa->xx / SIZE + *dist * mapa->ray_dir_x;
	mapa->wall_x -= floor(mapa->wall_x);
}

Adding New Features

General Workflow

1

Plan the feature

  • Identify which module(s) need changes
  • Determine if new files are needed
  • Check if t_map structure needs new fields
  • Consider performance impact
2

Update header file

Add function declarations to cub3.h:
cub3.h
// Add new function declaration
void	new_feature_function(t_map *mapa);

// Add new structure fields if needed
typedef struct s_map
{
	// ... existing fields ...
	int		new_field;
}			t_map;
3

Implement the feature

Create or modify source files following the norm:
new_feature.c
#include "cub3.h"

void	new_feature_function(t_map *mapa)
{
	int		i;
	
	i = 0;
	/* Implementation */
}
4

Update Makefile

Add new source files to SRC variable:
Makefile
SRC = main.c utils.c ... new_feature.c
5

Initialize new fields

If you added fields to t_map, initialize them:
main.c:init_values()
mapa->new_field = 0;
6

Clean up resources

If your feature allocates memory, add cleanup:
freemem.c:freeall()
ft_memdel(map->new_allocated_field);

Example: Adding Minimap Feature

Here’s how to add a minimap display:
/* In structure definition */
typedef struct s_map
{
	/* ... existing fields ... */
	int		minimap_enabled;
	int		minimap_scale;
}			t_map;

/* Add function declaration */
void	draw_minimap(t_map *mapa);

Testing Changes

Build and Test Workflow

1

Clean build

make fclean
make
Ensure no compilation warnings or errors.
2

Test with valid maps

./cub3d maps/valid_map.cub
  • Test movement (W, A, S, D)
  • Test rotation (arrow keys)
  • Test window closing (ESC or X button)
3

Test with invalid maps

./cub3d maps/invalid_unclosed.cub
./cub3d maps/missing_texture.cub
./cub3d maps/invalid_rgb.cub
Verify appropriate error messages appear.
4

Memory check

valgrind --leak-check=full ./cub3d maps/valid_map.cub
Verify no memory leaks in your new code.
5

Edge cases

Test boundary conditions:
  • Empty maps
  • Very large maps
  • Player at map edges
  • Unusual texture sizes

Test Map Collection

Create a comprehensive test suite:
Test Script
#!/bin/bash

echo "Testing valid maps..."
for map in maps/valid/*.cub; do
    echo "Testing $map"
    timeout 5 ./cub3d "$map" || echo "FAILED: $map"
done

echo "\nTesting invalid maps (should error)..."
for map in maps/invalid/*.cub; do
    echo "Testing $map"
    ./cub3d "$map" 2>&1 | grep -q "Error" && echo "OK" || echo "FAILED: $map"
done

Common Test Cases

  • Simple rectangular room
  • Complex maze
  • Large open area
  • Multiple rooms connected
  • Player facing each direction (N, S, E, W)
  • Different texture combinations
  • Various RGB color values
  • Map not closed by walls
  • Multiple players
  • No player
  • Invalid characters in map
  • Missing texture files
  • Invalid RGB values (greater than 255 or less than 0)
  • Duplicate attributes (two NO declarations)
  • Missing required attributes
  • Wrong file extension
  • Player starting position at edge
  • 1x1 room (minimum valid map)
  • Very long corridors
  • Texture file permissions issues
  • Extremely large maps (performance test)
  • Map with only player and walls (no spaces)

Build System

Makefile Targets

Available Commands
make          # Build cub3d executable
make all      # Same as make
make clean    # Remove object files
make fclean   # Remove objects and executable
make re       # Rebuild from scratch (fclean + all)

Makefile Structure

The Makefile automatically handles dependencies:
Makefile:27-36
all: $(MINILIBX) $(LIBFT) $(NAME)
$(NAME): $(MINILIBX) $(OBJS)
	$(CC) $(CFLAGS) -o $(NAME) $(OBJS) -L$(MINILIBX_DIR) -lmlx -L$(LIBFT_DIR) -lft -lm -lX11 -lXext

$(LIBFT):
	make -C $(LIBFT_DIR)

$(MINILIBX):
	make -C $(MINILIBX_DIR)
The Makefile rebuilds libft and minilibx as needed. If you make changes to libft functions, run make re in the libft directory, then make in the main directory.

Adding Compilation Flags

To add custom flags temporarily:
# Debug build without optimization
make CFLAGS="-Wall -Wextra -Werror -g -O0"

# Profile build
make CFLAGS="-Wall -Wextra -Werror -pg"

# Sanitizer build (detect memory errors)
make CFLAGS="-Wall -Wextra -Werror -g -fsanitize=address"

Common Development Tasks

Adding a New Utility Function

1

Choose appropriate utils file

  • utils.c - Map validation
  • utils2.c - String/map copying
  • utils3.c - Flood fill/map checking
  • utils4.c - Color validation
  • utils5.c - Window/input handling
  • utils6.c - Movement/rendering
  • utils7.c - Key events/drawing
Or create utils8.c for new category.
2

Declare in header

cub3.h
/* Add to appropriate section */
int		my_new_function(t_map *mapa, int param);
3

Implement function

utils8.c
#include "cub3.h"

int	my_new_function(t_map *mapa, int param)
{
	int		result;
	
	result = param * 2;
	return (result);
}
4

Update Makefile if new file

SRC = main.c ... utils7.c utils8.c freemem.c ...

Modifying the t_map Structure

Changing t_map requires updating multiple locations:
  1. Structure definition in cub3.h
  2. Initialization in init_values() (main.c)
  3. Cleanup in freeall() if pointer (freemem.c)
Adding a Field
/* 1. In cub3.h:79-162 */
typedef struct s_map
{
	/* ... existing fields ... */
	int		my_new_field;  /* Add new field */
}			t_map;

/* 2. In main.c:init_values() */
void	init_values(t_map *mapa)
{
	/* ... existing initialization ... */
	mapa->my_new_field = 0;  /* Initialize */
}

/* 3. In freemem.c:freeall() - only if pointer */
void	freeall(t_map *map)
{
	freetextures(map);
	freeme(map->toflood_map);
	freeme(map->final_map);
	ft_memdel(map->my_new_field);  /* Free if allocated */
}

Adding New Map Attributes

To add support for new .cub file attributes (e.g., FLOOR_TEXTURE):
1

Add to t_map structure

cub3.h
typedef struct s_map
{
	/* ... */
	char	*floor_texture_path;
}			t_map;
2

Parse in parselineutils.c

parselineutils.c:check_array_for_atributes()
if (!ft_strcmp(arr[0], "FT"))  /* FT = Floor Texture */
{
	if (map->floor_texture_path)
		return (msg(2, MAP_ARG_DUP), 1);
	map->floor_texture_path = ft_strdup(arr[1]);
}
3

Validate in all_atributes_asigned()

parselineutils.c:55-62
if (map->northtexture && map->southtexture && map->easttexture
    && map->westtexture && map->floorcolor && map->ceilingcolor
    && map->floor_texture_path)  /* Add check */
    return (1);
4

Add cleanup

freemem.c:freetextures()
ft_memdel(map->floor_texture_path);

Where to Find Help

Documentation

MiniLibX

Check the MiniLibX documentation in minilibx-linux/ directory

Raycasting Tutorial

42 Norm

Official 42 norm PDF (available in your 42 cluster)

libft Functions

Reference your own libft implementation in libft/ directory

Code References

Use grep to find usage examples:
Finding Examples
# Find all uses of a function
grep -rn "mlx_new_window" .

# Find all map validation code
grep -rn "flood_fill" .

# Find error handling patterns
grep -rn "freeall" .

# Find structure field usage
grep -rn "mapa->ray_dir_x" .

Key Source Files for Reference

TaskReference FileKey Functions
Initializationmain.c:15-72init_values(), cubed_init()
Raycastingraycasting.craycasting(), perform_dda()
Renderingdrawing.cdraw_3d_dda(), draw_wall()
Movementutils6.c:29-91move_cubed(), cubed_render()
Parsingparselineutils.cparsefloorceilingdirections()
Memoryfreemem.cfreeall(), freeme()
Validationutils3.cflood_fill(), checkclosemap()

Debugging Resources

See the Debugging page for:
  • GDB usage with raycasting
  • Valgrind memory checking
  • Common error solutions
  • Performance profiling

Pre-submission Checklist

1

Code quality

  • All code follows 42 norm
  • No compilation warnings
  • Functions are under 25 lines
  • Proper function headers
  • No forbidden functions used
2

Functionality

  • Program compiles with make
  • Works with valid maps
  • Proper error handling for invalid maps
  • Window closes cleanly with ESC or X
  • Movement and rotation work smoothly
  • Textures display correctly
3

Memory management

  • No memory leaks (checked with Valgrind)
  • All allocated memory is freed
  • All error paths free resources
  • No segmentation faults
4

Testing

  • Tested with multiple valid maps
  • Tested all invalid map cases
  • Tested edge cases
  • Performance is acceptable
5

Documentation

  • Code is readable and well-structured
  • Complex algorithms have comments (if allowed)
  • README exists (if required)
Always run make fclean && make before final submission to ensure a clean build from scratch.