Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Polytech DevOps - System Programming Project

## Rules

Students MUST pick one out of the [four proposed topics](topics).

Before the project deadline, students MUST turn in an [architecture document](#architecture-and-documentation) and an [implementation](#implementation) for the selected topic, in the form of a [GitHub pull request](#project-contribution).

## Topics

Four different topics are proposed:

1. [A networking port scanner](topics/port-scanner).
1. [A peer-to-peer file transfer protocol](topics/p2p-transfer-protocol).
1. [A web scraper](topics/web-scraper).
1. [A tic-tac-toe AI agent](topics/tic-tac-toe).

## Grade

Your work will be evaluated based on the following criteria:

### Architecture and Documentation

**This accounts for 40% of the final grade**

You MUST provide a short, `markdown` formatted and English written document describing your project architecture.

It MUST live under a projects top level folder called `docs/`, e.g. `docs/architecture.md`.

It SHOULD at least contain the following sections:

1. Project definition: What is it? What are the goals of the tool/project?
1. Components and modules: Describe which modules compose your project, and how they interact together. Briefly justify why you architectured it this way.
1. Usage: How can one use it? Give usage examples.

### Implementation

**This accounts for 40% of the final grade**

The project MUST be implemented in Rust.

The implementation MUST be formatted, build without warnings (including `clippy` warnings) and commented.

The implementation modules and crates MAY be unit tested.

### Project Contribution

**This accounts for 20% of the final grade**

The project MUST be submitted as one single GitHub pull request (PR) against the [current](https://github.com/dev-sys-do/project-2427) repository, for the selected project.

For example, a student picking the `p2p-transfer-protocol` topic MUST send a PR that adds all deliverables (source code, documentation) to the `topics/p2p-transfer-protocol/` folder.

All submitted PRs will not be evaluated until the project deadline. They can thus be incomplete, rebased, closed, and modified until the project deadline.

A pull request quality is evaluated on the following criteria:
* Commit messages: Each git commit message should provide a clear description and explanation of what the corresponding change brings and does.
* History: The pull request git history MUST be linear (no merge points) and SHOULD represent the narrative of the underlying work. It is a representation of the author's logical work in putting the implementation together.

A very good reference on the topic: https://github.blog/developer-skills/github/write-better-commits-build-better-projects/

### Grade Factor

All proposed topics have a grade factor, describing their relative complexity.

The final grade is normalized against the selected topic's grade factor: `final_grade = grade * topic_grade_factor`.

For example, a grade of `8/10` for a topic which grade factor is `1.1` will generate a final grade of `8.8/10`.


## Deadline

All submitted PRs will be evaluated on October 30th, 2025 at 11:00 PM UTC.
29 changes: 29 additions & 0 deletions topics/p2p-transfer-protocol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# A P2P Transfer Protocol

## Description and Goal

Build a CLI tool that allows two users on the same network to transfer a single file to each other.
The tool should be able to act as both the sender and the receiver, without a central server.

It is expected for a sender to know the IP of the receiver, i.e. there is no discovery protocol.

```shell
# Receiving a file on port 9000
p2p-tool listen --port 9000 --output ./shared

# Sending a file
p2p-tool send --file report.pdf --to 192.168.1.100 --port 9000
```

## Hints and Suggestions

- Define and document a simple networking protocol with a few commands. For example
- HELLO: For the sender to offer a file to the receiver. It takes a file size argument.
- ACK: For the receiver to tell the sender it is ready to receive a proposed file.
- NACK: For the receiver to reject a proposed file.
- SEND: Send, for the sender to actually send a file. It also takes a file size argument, that must match the `HELLO` offer.
- Start a receiving thread for every sender connection.

## Grade Factor

The grade factor for this project is *1*.
25 changes: 25 additions & 0 deletions topics/port-scanner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Network Port Scanner

## Description and Goal

Build a *multi-threaded* command-line application that scans a range of ports at a URL or IP to check if they are open.

The tool displays all open ports at the target URL.

```shell
Usage: scanner [OPTIONS] URL/IP

Options:
-p, --ports <PORT_RANGE> TCP or UDP port ranges. Can be set multiple times.
-t, --threads <THREADS> Max number of threads.
-h, --help Print help (see more with '--help')
-V, --version Print version
```

## References

[nmap](https://nmap.org/)

## Grade Factor

The grade factor for this project is *0.9*.
7 changes: 7 additions & 0 deletions topics/tic-tac-toe/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions topics/tic-tac-toe/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "tic-tac-toe"
version = "0.1.0"
edition = "2024"

[dependencies]
25 changes: 25 additions & 0 deletions topics/tic-tac-toe/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# A Simple Tic-Tac-Toe Agent

## Description and Goal

The goal is to build a command-line [Tic-Tac-Toe](https://en.wikipedia.org/wiki/Tic-tac-toe) game where a human player can play against an AI opponent.

The AI should be "smart" enough to play optimally, meaning it can't be beaten and will either win or draw every game.

## Game State Representation

A simple 2D array or a 1D array of a fixed size is a good choice.

## Agent Algorithm

The recommended choice for the Agent algorithm is the `Minimax` algorithm with a depth-first search: The AI assumes its opponent will always make the best possible move, and it will choose its own move to minimize the maximum possible loss (or, conversely, maximize the minimum possible gain).

A simpler, alternative option is the tree search one: The algorithm builds a game tree to explore all possible future moves. The agent assigns scores to the board's end states (+1 for an AI win, -1 for a human win, 0 for a draw) and "propagates" those scores up the tree to find the best move.

## References

[Minimax and tic-tac-toe](https://www.neverstopbuilding.com/blog/minimax)

## Grade Factor

The grade factor for this project is *1.2*.
85 changes: 85 additions & 0 deletions topics/tic-tac-toe/docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# A Simple Tic-Tac-Toe Agent
Implemented by Pierre-Louis Leclerc

## Project Description

This project is a command-line Tic-Tac-Toe game implemented in Rust that features an intelligent AI opponent using the minimax algorithm. The game allows a human player to compete against a perfect-playing robot in a traditional 3x3 grid tic-tac-toe match.

### Goals
- **Perfect AI Implementation**: Create an unbeatable AI opponent using the minimax algorithm
- **Clean Architecture**: Demonstrate modular design with separation of concerns
- **Interactive Gameplay**: Provide an engaging command-line interface for human players
- **Educational Value**: Showcase game theory concepts and AI decision-making algorithms

## Components and Modules

The project is structured using a modular architecture with clear separation of responsibilities:

### Core Modules

#### 1. **Board Module** (`src/game/board.rs`)
- **Purpose**: Manages the game state and board operations
- **Key Features**:
- 3x3 grid representation using `[[Option<char>; 3]; 3]`
- Position-based input system (1-9 numbering)
- Win condition detection (rows, columns, diagonals)
- Draw detection (full board check)
- Move validation and symbol placement
- **Justification**: Encapsulates all board-related logic, making it easy to test and maintain game state

#### 2. **Robot Module** (`src/game/robot.rs`)
- **Purpose**: Implements the AI opponent using minimax algorithm
- **Key Features**:
- Perfect play strategy through minimax decision tree
- Recursive game state evaluation
- Optimal move selection with depth consideration
- Strategic scoring system (wins, losses, draws)
- **Justification**: Separates AI logic from game flow, allowing for easy algorithm swapping or improvements

#### 3. **Game Module** (`src/game/game.rs`)
- **Purpose**: Orchestrates the overall game flow and user interaction
- **Key Features**:
- Turn-based game loop management
- Human vs Robot player coordination
- Input handling and validation
- Game state transitions and end conditions
- **Justification**: Acts as the controller, coordinating between board state and AI decisions

#### 4. **Main Module** (`src/main.rs`)
- **Purpose**: Entry point and game initialization
- **Key Features**:
- Game instance creation
- Application startup
- **Justification**: Keeps the entry point minimal and focused

### Module Interactions

```
main.rs
↓ creates
Game
↓ manages
Board ←→ Robot
↑ ↓
└─ reads state
makes moves
```

- **Game** coordinates between human input and robot decisions
- **Board** maintains authoritative game state for both players
- **Robot** analyzes board state to make optimal moves

## Usage

### Building and Running

```bash
# Navigate to the project directory
cd topics/tic-tac-toe

# Build the project
cargo build

# Run the game
cargo run
```
104 changes: 104 additions & 0 deletions topics/tic-tac-toe/src/game/board.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#[derive(Clone)]
pub struct Board {
cells: [[Option<char>; 3]; 3]
}

impl Board {
pub fn new() -> Self {
Board {
cells: [[None; 3]; 3]
}
}

pub fn display(&self) {
println!("Choose a position (1-9):");
let mut position = 1;
for row in &self.cells {
for cell in row {
match cell {
Some(symbol) => print!("| {} |", symbol),
None => print!("| {} |", position),
}
position += 1;
}
println!();
}
}

pub fn place_symbol_by_position(&mut self, position: usize, symbol: char) -> bool {
if position < 1 || position > 9 {
return false;
}

let (row, col) = self.position_to_coords(position);
if self.cells[row][col].is_none() {
self.cells[row][col] = Some(symbol);
true
} else {
false
}
}

fn position_to_coords(&self, position: usize) -> (usize, usize) {
let index = position - 1; // Convert to 0-based index
let row = index / 3;
let col = index % 3;
(row, col)
}

pub fn is_full(&self) -> bool {
for row in &self.cells {
for cell in row {
if cell.is_none() {
return false;
}
}
}
true
}

pub fn check_winner(&self) -> Option<char> {
// Check rows
for row in &self.cells {
if let Some(symbol) = row[0] {
if row[1] == Some(symbol) && row[2] == Some(symbol) {
return Some(symbol);
}
}
}

// Check columns
for col in 0..3 {
if let Some(symbol) = self.cells[0][col] {
if self.cells[1][col] == Some(symbol) && self.cells[2][col] == Some(symbol) {
return Some(symbol);
}
}
}

// Check diagonals
// Top-left to bottom-right
if let Some(symbol) = self.cells[0][0] {
if self.cells[1][1] == Some(symbol) && self.cells[2][2] == Some(symbol) {
return Some(symbol);
}
}

// Top-right to bottom-left
if let Some(symbol) = self.cells[0][2] {
if self.cells[1][1] == Some(symbol) && self.cells[2][0] == Some(symbol) {
return Some(symbol);
}
}

None
}

pub fn is_position_empty(&self, row: usize, col: usize) -> bool {
if row < 3 && col < 3 {
self.cells[row][col].is_none()
} else {
false
}
}
}
Loading