Background

About me

Hi, I’m Anssi. I’m a software developer from Finland who enjoys solving technical problems and turning ideas into working projects.

I studied software development at Hive Helsinki and have experience with C, C++, TypeScript, React, Node.js, SQL, Docker, Linux, Git, Unity, and C#. My projects have included full-stack web development, backend integrations, real-time systems, and independent software development.

I also have hands-on experience across the game development process. I have independently designed and built complete game projects, including gameplay programming, creating and animating 3D models in Blender, and integrating assets and systems in Unity.

I enjoy understanding how systems work together, investigating problems, and improving solutions through experimentation and iteration. My interests span software development, QA and testing, cybersecurity, IT infrastructure, and game development.

Selected work

Projects

Games and interactive work

Playable releases and game prototypes.

Gameplay view showing the fish, curved fishing meter, and overlap-based positioning challenge.

Playable release

Gone Humaning

A 3D reverse-fishing game where the player controls the fish, tracks an AI fisherman along a curved meter, and fights back through positioning and timed reactions. Created by a three-person team for ASM Game Jam 2026.

UnityC#Game Jam

Case study

Gone Humaning

A reverse-fishing game that turns the fish into the player and the fisherman into the catch.

The central mechanic is inspired by timing and positioning minigames such as the fishing system in Breath of Fire III, but the player takes the role of the fish instead of the fisherman. The idea grew from the game jam theme, “Beneath.” The player controls a green bar along a curved meter while an AI-controlled fisherman icon moves unpredictably through the same space. Keeping the two aligned lets the fish resist the pull and gradually drain the fisherman’s energy; losing contact drains the fish’s energy instead.

At intervals, the fisherman performs a special action. A warning icon appears briefly, giving the player a short window to be correctly positioned and press the action input. A successful response damages the fisherman and triggers visual, movement, and sound feedback. Missing it costs the player a significant amount of energy, creating a rhythm between continuous positional control and short reaction-based challenges.

The encounter ends when either participant runs out of energy. If the fish wins, the fisherman is pulled underwater and presented as the fish’s catch, humorously reversing the usual fishing result screen. If the player loses, the fish is pulled out of the water. The game also includes selectable fish appearances, animated camera movement, audio feedback, and dedicated victory and defeat sequences.

Key features

  • AI-controlled fishermanRandomized movement targets and timing make positioning unpredictable.
  • Timed reaction eventsSpecial actions create short response windows with meaningful success and failure consequences.
  • Dynamic feedbackUI color, fish movement, audio, and animation respond to distance, positioning, and major actions.
  • Complete game flowIncludes fish selection, a main menu, pause handling, victory, defeat, and restart flows.

My role

I originated the concept and was responsible for its overall direction, gameplay design, user interface, menu flow, and the complete implementation of the core fishing minigame through FishingGameController.

My design work included defining the reversed premise, establishing the interaction loop, designing the curved interface, balancing positioning against reaction-based actions, and determining how player and fisherman energy should behave. I also designed and assembled the gameplay indicators, status messaging, energy displays, menus, pause flow, fish-selection interface, and game-over presentation.

  • Read reel, action, and pause inputs through Unity’s Input System
  • Move the player bar smoothly in response to held input
  • Generate randomized fisherman movement and place both elements along a curved elliptical UI path
  • Rotate UI elements along the path and detect overlap between them
  • Slow the fisherman while the player reels successfully and manage both energy systems
  • Trigger randomized fisherman actions, reaction windows, and gradual damage
  • Update status, energy, and distance-based color feedback
  • Coordinate sound, animation, menus, pausing, game-over states, and restarts
  • Save and restore the player’s selected fish

Team contributions

This was a three-person project. Although each member had primary areas of ownership, features and presentation details were refined collaboratively through team discussion and shared planning. I also integrated my gameplay controller with my teammates’ camera movement, fish animation, fishing-line behavior, audio cues, and victory and defeat systems.

  • juj: Supporting gameplay scripts, camera behavior, animation-driven feedback, end sequences, and gameplay video
  • j8nvs: All art assets, main-menu artwork, environmental design, visual presentation, and 3D models
  • Shared: Feature planning, mechanic refinement, balancing, visual feedback, and system integration decisions
Stone arena while aiming a shot, with targets arranged across the play area.

Playable release

Stone Flicking Minigame

A Unity physics prototype inspired by traditional tabletop games such as Ohajiki, built around precise flicking, collision-based scoring, and modular stage design. Developed as a standalone proof of concept for a larger game project.

UnityC#Blender

Case study

Stone Flicking Minigame

A physics-based precision game built in Unity, inspired by traditional tabletop games such as Ohajiki.

The player controls a stone token and clears targets by carefully aiming each flick. Shot strength, impact position, and angle all affect how the token moves, allowing the player to use both direct hits and glancing strikes with spin. The focus is on precision and understanding the physical interaction between the pieces rather than simply using maximum force.

I originally designed the minigame as one activity within a larger historically inspired game project. Because the small physical scale of the pieces made Unity’s physics difficult to tune reliably, I separated the mechanic into a standalone prototype so I could develop and test the underlying systems independently. The current playable version contains tutorial stages that demonstrate the core mechanics and serves as a proof of concept, with additional stages and balancing still planned.

During development, I focused on building a reliable turn-resolution system, natural-feeling physics interactions, reusable stage layouts, multiple play areas, tutorial progression, and a complete gameplay loop. I also added an optional explosion mechanic after playtesting showed that a less realistic but more chaotic mode made the game more entertaining.

Technical highlights

  • Physics-based flickingUses a temporary physical striker instead of applying force directly to the player token, allowing contact position and impact angle to affect movement and spin.
  • Turn resolutionTracks collisions, movement, field exits, and pre-existing contacts before determining whether a shot produces a valid score.
  • Modular stage systemEach board defines its geometry, camera settings, spawn areas, and layout, allowing stages and rule variations to be developed independently.
  • Tutorial and game flowIncludes fixed tutorial layouts, contextual instructions, menus, scoring, retries, randomized standard stages, and completion logic.
  • Playtesting and iterationBegan with an emphasis on realistic, historically plausible play; testing led to optional mechanics such as explosive targets for a more chaotic variation.

Case study

Berry Connected

A berry-picking game about the interconnected layers of land, resources, and community.

Berry Connected was developed during Siida Game Jam 2026 around the theme “Layers.” The player moves through layers of forest, gathers berries and flowers, and encounters small reminders that the environment is more than a source of resources. The game’s topics and actions were informed by knowledge shared by the Sámi Museum Siida and the game jam organizers.

The main activity is a timed 2D berry-picking scene. The player advances through the forest with the keyboard and uses the mouse to interact with overlapping elements: collectables can be picked, grass pushed aside, and foreground obstacles dragged out of the way. Procedurally arranged rows of bushes, birches, grass, and flowers keep the layered scene changing as the player moves forward.

The gathering systems also give the player’s choices consequences. Bushes contain a randomized number of berries, but the final berry is left behind. Some bushes rustle and may reveal a hidden lemming, creating an encounter that can end the run. Counters, a timer, start and pause states, menus, and distinct completion outcomes bring these mechanics together into a complete game jam experience.

Technical highlights

  • Layer-aware interactionSelects the visually topmost object from overlapping 2D colliders while respecting sorting groups and explicit interaction priorities.
  • Procedural forest compositionBuilds and recycles layered rows of bushes, birches, flowers, and grass with randomized placement and spacing constraints.
  • Gathering rulesRandomizes resources, tracks separate collectable types, and prevents the player from stripping every berry from a bush.
  • Environmental interactionsSupports collectables, draggable foreground objects, animated grass, rustling bushes, and hidden lemming encounters through reusable interaction components.
  • Complete game flowCoordinates scene navigation, timed play, counters, start and pause states, completion screens, and encounter-driven failure.

My role

I worked on the game’s code and design. My implementation focused on the berry-picking experience and the systems that support it, from the initial Unity setup and scene interaction model to procedural environment generation, gathering rules, encounters, game states, menus, and UI integration.

I also assembled the gameplay scene around the team’s art, graphics, narrative, and supporting code, adapting the individual contributions into a consistent playable experience within the short game jam schedule.

  • Build the layered mouse-interaction system for collectables, movable obstacles, and animated occluders
  • Generate and recycle forest rows while controlling placement, spacing, visual sorting, and randomized resource amounts
  • Implement berry and flower gathering, counters, and the rule that leaves the final berry on each bush
  • Create rustling-bush and lemming encounter behaviour
  • Coordinate the timer, start, pause, completion, failure, scene-navigation, and menu flows
  • Integrate the team’s visual and narrative work into the gameplay scenes and user interface

Team contributions

This was created by a three-person core team, with a separate artist contributing selected assets. Design decisions and the final presentation were developed collaboratively during the jam.

  • Kristoffer: Graphics and supporting code
  • ide4fix: Design and narrative
  • lemon: Additional main-menu background and UI art
  • Shared: Concept development, design decisions, integration, and game jam iteration

Systems and software

A selection of web, mobile, systems, networking, graphics, and infrastructure projects.

Solo project

Expo Finance App

A personal expense-tracking prototype built with Expo, React Native, and TypeScript. Supports expense tracking, monthly budgets, spending charts, and multiple currencies, with locally stored data and no account or backend required.

ExpoReact NativeTypeScriptSQLite

Case study

Expo Finance App

A cross-platform expense-tracking prototype focused on simple everyday use and keeping user data local.

I started this project after a friend asked whether I could build an expense-tracking app. I handled the design and development independently, while she contributed ideas and feedback from testing. I also wanted to explore building an app for both Android and iPhone, which led me to try Expo and React Native.

The app supports adding and editing expenses, organizing entries with categories and tags, filtering records, setting monthly budgets, and reviewing spending through summaries and graphs. It also supports custom currencies and formatting, with manually entered conversion rates for combining expenses in a chosen currency.

One of the main design goals was to avoid accounts, cloud storage, and unnecessary requests for personal information. Expense data stays on the user’s device or browser rather than being sent to a backend. I added encryption as an extra layer of protection for stored data, but made it optional in the browser after my friend found repeatedly entering a passphrase inconvenient. This allowed her to choose simpler access without the additional encryption step.

Most testing took place in desktop browsers, with additional Android testing through Expo. The project was intended for both Android and iOS, but I have not tested the iOS version or released it through an app store. Development is currently paused; improving the graphs would be my next priority.

Technical highlights

  • Expense managementSupports entry creation, editing, filtering, categories, and tags.
  • Budgets and summariesCombines monthly budgets, spending totals, and graphical views.
  • Multiple currenciesSupports custom currency formats and manually configured monthly conversion rates.
  • Cross-platform structureShares application logic while using platform-specific storage and date inputs.
  • Local data storageRequires no account or backend, with SQLite storage on native platforms and optional passphrase-based encryption in the browser.
An alternate local two-player arena with additional horizontal barriers that change the ball’s possible paths.

Team project

ft_transcendence

A five-person full-stack project built around a browser-based, local two-player Pong game, tournaments, player statistics, and authenticated accounts. I developed the complete game and its frontend page, rebuilt the tournament experience, and extended the application’s data handling to support gameplay and match results.

TypeScriptReactBabylon.jsTailwind CSS

Case study

ft_transcendence

A local two-player 3D Pong game integrated into a full-stack web platform with tournaments, persistent match data, and authenticated user accounts.

ft_transcendence was a five-person team project completed at Hive Helsinki. The application combines a React and TypeScript frontend with separate backend services for authentication, player statistics, tournament data, and other platform features.

I was responsible for the game feature within the frontend, including the Pong implementation and its surrounding page. I developed the gameplay systems and connected them to player selection, settings, tournaments, match results, navigation, and the application’s backend services.

The game includes local two-player controls, collision handling, scoring, configurable match formats, multiple arenas, visual effects, sound, and additional mechanics such as boosts and temporary shields. I also designed its interface and presentation to fit the visual style established elsewhere in the application.

The game page manages the full lifecycle around each match: preparing player data, configuring the game, starting and ending matches, displaying results, advancing tournaments, and submitting the resulting data. This made the feature a complete part of the platform rather than an isolated game embedded in a webpage.

Integrating the game required extending an existing frontend data-fetching implementation. I modified the shared flow so the necessary player, match, and tournament information was available, submitted correctly, and displayed consistently. I worked with the backend developers to communicate data requirements and investigate integration problems, while using the project’s existing token-based authentication system for protected frontend operations.

Technical highlights

  • Complete frontend game featureDeveloped both the Pong game and its surrounding React page, including configuration, player data, match lifecycle, results, tournament progression, navigation, and backend integration.
  • Local two-player gameplayImplemented controls, ball and paddle interactions, scoring, match resolution, pausing, restarting, effects, and sound.
  • Configurable game systemsAdded multiple arenas, speeds, match lengths, custom controls, boost mechanics, and temporary shields.
  • Tournament systemBuilt tournament setup, player configuration, match progression, bracket visualization, winner handling, and history views.
  • Game data flowExtended the existing player-data process and ensured match and tournament information was retained, submitted, retrieved, and presented correctly.
  • Authenticated requestsConnected protected frontend operations to the project’s existing token system.
  • Cross-team integrationWorked with the backend developers to align frontend requirements with the available services and diagnose problems across system boundaries.

My role

I owned the game feature within the frontend and rebuilt the tournament experience from an initial placeholder. I followed the patterns established by the frontend team and made sure the game felt visually consistent with the rest of the application.

  • Develop the browser-based Pong game and its supporting scene, object, map, material, effect, and interface systems
  • Build the React game page around player preparation, settings, match states, results, and tournament progression
  • Connect normal and tournament match results to the application’s frontend data flows
  • Extend the existing player-data process to retain the information required by the game
  • Build tournament creation, player selection, aliases, brackets, winner handling, and tournament-history views
  • Use authenticated frontend requests for protected operations and communicate backend requirements to the responsible developers
  • Adapt the game’s interface and presentation to the existing website design

Team collaboration

This was a five-person project with shared frontend and backend foundations. I did not develop the backend services or their authentication implementation, but I worked closely with the responsible developers to define the data needed by the game, report backend issues, and troubleshoot the integration between the systems.

Case study

miniRT

An introductory ray tracer built from first principles to explore 3D geometry, per-pixel rendering, lighting, and interactive scene manipulation.

miniRT reads a scene from a structured .rt file and renders it pixel by pixel into a MiniLibX window. Each camera ray is tested against the objects in the scene, and the closest intersection is shaded using object colour, ambient light, diffuse light, distance, and hard-shadow calculations.

The renderer supports planes, spheres, and finite cylinders with end caps. It also handles camera orientation from direction vectors, surface normals, cameras positioned inside objects, and small intersection offsets that reduce self-shadowing artifacts.

The displayed scene can be explored and adjusted without restarting the program. Keyboard controls allow the user to select, move, rotate, and resize objects; reposition and rotate the camera; move the light; and adjust both direct and ambient brightness before re-rendering the scene.

We developed the ray-tracing logic through shared mathematical reasoning, reference research, iterative testing, and debugging. My implementation work focused on bringing the individual calculations together into a complete renderer, parser, interactive control system, and reliable application flow.

Technical highlights

  • Scene parsing and validationReads cameras, lights, colours, orientation vectors, and primitive objects from .rt files while rejecting malformed or out-of-range input cleanly.
  • Per-pixel ray tracingGenerates a ray for every pixel, tests it against every scene object, and retains the nearest valid intersection for shading.
  • Object intersectionsSupports planes, spheres, and finite cylinders with separate side and end-cap calculations.
  • Lighting and shadowsCombines base colour, ambient light, distance attenuation, diffuse lighting, and secondary shadow rays.
  • Camera and object transformsBuilds camera basis vectors from its direction and uses vector, matrix, and quaternion-related operations for movement and rotation.
  • Interactive scene controlsObjects, camera position and orientation, light position, dimensions, and brightness can be changed at runtime before the scene is rendered again.

My contribution

My implementation work covered the main application structure and the systems that turn a scene description into an interactive rendered image. I also connected and refined the mathematical components we developed as a team so they behaved consistently across different objects, viewpoints, and lighting situations.

  • Build the .rt parser, input validation, allocation, error handling, and cleanup flow
  • Generate camera rays and coordinate the per-pixel rendering pipeline
  • Implement sphere intersections and integrate the complete intersection, surface-normal, lighting, colour, and shadow pipeline
  • Create interactive controls for objects, the camera, direct light, and ambient light
  • Handle movement, rotation, resizing, re-rendering, and camera orientation
  • Integrate the renderer with MiniLibX window, image-buffer, and keyboard events
  • Test complex scenes and resolve edge cases involving object interiors, shadows, orientation, and invalid input

Collaboration

This was a two-person project. We worked together on the rendering logic and the mathematics behind rays, vectors, intersections, and lighting, using documentation and test scenes to reason through difficult cases. My teammate researched .rt examples and technical references and contributed mathematical helper functions and cylinder intersection and rendering calculations. We tested, debugged, and refined the combined renderer together.

Case study

ft_irc

A non-blocking IRC server built around TCP sockets, epoll, IRC message parsing, shared channel state, and compatibility with a real IRC client.

ft_irc was a three-person systems and networking project completed at Hive Helsinki. The goal was to build an IRC server that could accept multiple simultaneous clients and support real-time private and channel communication through an established IRC client rather than a custom interface.

The server uses non-blocking TCP sockets and an epoll event loop to accept connections and process activity from multiple clients without creating a process or thread for each connection. Incoming stream data is buffered until complete CRLF-terminated IRC messages are available, then parsed, validated, and dispatched to the relevant command handler.

The implementation maintains clients, nicknames, registration state, channels, memberships, invitations, operators, topics, and channel modes. It supports the main registration and messaging commands as well as the numeric replies and state changes expected by IRC clients.

The project required compatibility with an existing IRC client, and our team chose Irssi. My main contribution was implementing and refining selected server commands, then testing full workflows with Irssi and correcting the connected logic. Its automatic CAP, WHO, WHOIS, PING, and MODE exchanges exposed edge cases that were easy to miss when testing individual commands manually through Netcat.

Technical highlights

  • Non-blocking multi-client serverUses TCP sockets and epoll to accept and process multiple client connections through a single event loop.
  • Stream-aware message parsingRetains partial socket data, extracts complete CRLF-terminated messages, and handles multiple commands arriving in the same read.
  • IRC command handlingSupports PASS, NICK, USER, QUIT, JOIN, PART, PRIVMSG, KICK, INVITE, TOPIC, MODE, CAP, PING, WHO, and WHOIS.
  • Channel state and permissionsTracks membership, invitations, operators, topics, passwords, user limits, and the required invite-only, topic, key, operator, and limit modes.
  • Irssi compatibilityHandles the automatic capability negotiation, presence queries, keep-alive traffic, and mode requests generated during normal Irssi use.
  • Protocol-level testingTests registration, messaging, permissions, disconnections, numeric errors, and multi-user state as complete client workflows rather than isolated function calls.

My contribution

I implemented and refined selected IRC command handlers and concentrated on making the combined server operate reliably with Irssi. Much of this work involved tracing behaviour across the parser, client registration, channel state, replies, and command logic to find why a valid client action did not produce the expected result.

  • Implement and refine selected command handlers, validation paths, replies, and state changes
  • Test the complete Irssi registration sequence, including capability negotiation and user registration
  • Investigate automatic WHO, WHOIS, PING, and MODE requests that do not appear in simple manual tests
  • Identify and correct differences between strict raw IRC syntax and the commands users enter through Irssi
  • Verify private messages, channel messages, joins, departures, invitations, topics, operator actions, and channel modes
  • Exercise failure paths such as duplicate nicknames, missing parameters, insufficient permissions, invalid targets, and unexpected disconnects
  • Repeat multi-client scenarios to find state-management bugs that only appeared across sequences of commands

Team collaboration

The server was developed by a three-person team. Its networking, protocol parsing, client and channel models, command handlers, and replies needed to work as one stateful system, so implementation and debugging regularly crossed individual areas of ownership. We tested the combined server together and coordinated fixes when behaviour in one component affected another.

Case study

ft_inception

A three-service web stack built from the operating-system base image to explore containerization, service isolation, networking, TLS, persistence, and infrastructure automation.

ft_inception was an individual infrastructure project completed at Hive Helsinki. I built a small WordPress hosting environment inside a Linux virtual machine without using preconfigured application images for the main services. NGINX, WordPress with PHP-FPM, and MariaDB each have their own Dockerfile, startup script, runtime process, and container.

NGINX is the only service exposed to the host and accepts HTTPS traffic on port 443 using TLS 1.2 or 1.3. PHP requests are forwarded to the WordPress container over the private Docker network, while MariaDB remains accessible only to the other services on that network.

Docker Compose defines the service relationships, dedicated bridge network, restart behaviour, environment-based configuration, and bind-mounted data directories. WordPress files and MariaDB data remain outside the disposable container layers so that rebuilding or replacing a container does not erase the site.

Custom entrypoint scripts perform the first-run setup for each service. They initialize the database and accounts, wait for dependencies, configure PHP-FPM, install WordPress through WP-CLI, create its users and configuration, generate TLS material and NGINX configuration, set file permissions, and finally start each service in the foreground.

Technical highlights

  • Custom service imagesBuilds NGINX, WordPress with PHP-FPM, and MariaDB from Debian base images using separate Dockerfiles and entrypoint scripts.
  • Isolated service architectureExposes only NGINX on port 443 while WordPress and MariaDB communicate internally through a dedicated bridge network.
  • HTTPS terminationGenerates a self-signed certificate, enables TLS 1.2 and 1.3, and routes PHP requests from NGINX to PHP-FPM.
  • Persistent application dataUses bind-mounted host directories for the WordPress installation and MariaDB database so data survives container rebuilds.
  • Automated provisioningInitializes the database and WordPress installation only when needed, creates configured users, applies permissions, and waits for service dependencies.
  • Lifecycle toolingProvides Makefile commands for checking Docker, preparing host directories, building, starting, stopping, restarting, and rebuilding the complete stack.

Implementation details

I designed and implemented the complete infrastructure independently, from individual container images and service configuration to orchestration, persistence, startup sequencing, and operational tooling. I also created a second Debian version while refining the final Debian 11.11 submission and documented how to build, run, inspect, and troubleshoot the environment.

  • Create separate Dockerfiles and entrypoint scripts for NGINX, WordPress with PHP-FPM, and MariaDB
  • Design the Docker Compose services, private network, dependencies, restart policies, ports, and persistent volumes
  • Configure HTTPS-only NGINX routing and FastCGI communication with the WordPress container
  • Automate MariaDB initialization, database creation, application-user privileges, and persistent startup
  • Automate WordPress download, configuration, installation, user creation, salts, permissions, and PHP-FPM startup
  • Add Makefile lifecycle commands and checks for Docker availability and local data directories
  • Test clean builds, repeated startups, persistent data, service recreation, permissions, and failure recovery inside the virtual machine

Case study

minishell

A small Unix shell built to understand how command parsing, processes, pipes, file descriptors, environment state, and signals work together.

minishell recreates a focused subset of Bash behaviour in C. It displays an interactive prompt with command history, resolves executables through PATH, runs external programs, and provides the required built-ins: echo, cd, pwd, export, unset, env, and exit.

User input passes through quote-aware parsing, environment-variable expansion, tokenization, syntax validation, and grouping into commands. The execution layer then coordinates child processes, pipelines, input and output redirections, append mode, heredocs, built-ins that must affect the parent shell, and the resulting exit status.

Correct behaviour depends on the interaction between these systems. Pipes and redirections must apply in the right order, file descriptors must be closed in both parent and child processes, environment changes must persist when appropriate, and signals must behave differently at the prompt, during command execution, and while reading a heredoc.

We compared the shell against Bash across normal use and deliberately difficult input. My work included maintaining a detailed test and investigation log, tracing failures across parser and execution boundaries, checking memory and open file descriptors with Valgrind, and fixing subtle cases involving quotes, empty input, chained redirections, heredocs, failed forks, built-in options, and exit codes.

Technical highlights

  • Quote-aware parsing and expansionHandles single and double quotes, environment variables, exit-status expansion, operators without surrounding spaces, and syntax validation.
  • Processes and pipelinesUses fork, pipe, dup2, execve, and waitpid to connect commands and report the status of the resulting process chain.
  • Redirections and heredocsSupports input, overwrite, append, and heredoc redirections while coordinating precedence, descriptor restoration, delimiter quoting, and variable expansion.
  • Built-ins and environment stateImplements the required shell built-ins and preserves changes from commands such as cd, export, and unset in the parent shell.
  • Context-sensitive signalsCoordinates Ctrl-C, Ctrl-D, and Ctrl-\ behaviour across the interactive prompt, child processes, and heredoc input while maintaining Bash-like exit statuses.
  • Edge-case and memory testingUses a repeatable Bash comparison list and Valgrind runs with child tracing, descriptor tracking, and Readline suppressions to investigate failures and resource handling.

My contribution

My primary implementation areas were the parser and shell control flow, redirections and heredocs, signal handling, selected built-ins, and the integration work needed to make independently developed components behave like one shell. The project history also reflects a strong focus on testing and late-stage fixes across the whole program.

  • Develop quote-aware parsing, environment expansion, operator separation, syntax checks, and command preparation
  • Implement file-descriptor operations for input, overwrite, append, and heredoc redirections
  • Build heredoc collection, quoted-delimiter handling, expansion behaviour, interruption, and descriptor cleanup
  • Implement and refine signal handling and exit-status updates for prompts, commands, failures, and heredocs
  • Develop and correct selected built-in behaviour, including echo option handling
  • Integrate parsing, token groups, redirections, pipelines, built-ins, external commands, and cleanup into the main shell loop
  • Create detailed Bash-comparison and Valgrind test workflows and fix cross-system edge cases found through them

Team collaboration

This was a two-person project. My teammate’s main areas included tokenization, pipeline foundations, command and path handling, and most of the environment-related built-ins. Execution and debugging crossed these boundaries frequently, so we integrated and refined each other’s components, tested the complete shell together, and coordinated fixes where parsing, process control, or environment state affected another part of the program.

Case study

Philosophers

A concurrency project focused on synchronization, timing, and shared-resource management.

Philosophers was a solo Hive Helsinki project based on the classic dining philosophers problem. Each philosopher alternates between thinking, eating, and sleeping, and needs access to both neighbouring forks before they can eat. Since the forks are shared between philosophers, the program has to coordinate multiple threads without allowing them to interfere with each other.

I implemented the simulation in C using POSIX threads and mutexes. Each philosopher runs in its own thread, while mutexes protect access to the forks, shared simulation data, and terminal output. The simulation can be configured through command-line arguments, including the number of philosophers, the maximum time between meals, eating and sleeping times, and an optional number of meals to complete.

The program continuously monitors the philosophers to detect when one has gone too long without eating and to determine when the simulation should stop. The project required careful handling of timing, shared state, thread synchronization, and cleanup, and gave me practical experience working with concurrent code in C.

Technical highlights

  • Multithreaded simulationRuns each philosopher in its own POSIX thread with an independent activity cycle and meal tracking.
  • Mutex synchronizationUses mutexes to control access to shared forks, simulation state, and terminal output.
  • Timing and monitoringTracks meal times and continuously checks whether a philosopher has exceeded the allowed time without eating.
  • Configurable simulationSupports different philosopher counts and timing values through command-line arguments, along with an optional meal target.
  • Cleanup and thread managementStops the simulation through shared state, joins the worker threads, and releases allocated resources and mutexes cleanly.

Case study

push_swap

An algorithm project focused on sorting efficiently with a restricted set of stack operations.

push_swap was a solo Hive Helsinki project where the goal was to sort a list of integers using two stacks and only a small set of allowed operations. These include swapping values, pushing values between stacks, and rotating the stacks in either direction. Instead of outputting the sorted numbers directly, the program has to produce the sequence of operations needed to sort them, so keeping the instruction count low is an important part of the project.

I represented the stacks as linked lists and assigned each value a rank based on its position in the fully sorted list. The sorting logic uses these ranks to move values to the second stack in groups, sort the remaining values, and then move everything back into the correct order. The program also chooses whether to rotate upward or downward depending on where a value is located and combines rotations of both stacks when that reduces the number of operations.

I also added a way to test several possible chunk sizes before running the final sort. The program makes copies of the input, simulates the sorting process with different chunk sizes, compares the estimated operation counts, and then uses the best option from those trials for the real run. I also implemented a separate checker that reads a sequence of operations, applies them to the stacks, and verifies whether the result is correctly sorted. The project gave me practical experience with linked lists, sorting strategies, optimization, and validating algorithm output.

Technical highlights

  • Restricted stack operationsImplements swaps, pushes, rotations, and reverse rotations for two linked-list stacks, including operations that affect both stacks at once.
  • Rank-based sortingAssigns each value a sorted rank and uses rank ranges to move values between the stacks in manageable groups.
  • Chunk-size testingTests several chunk sizes on copies of the input and chooses the one with the lowest estimated operation count from those trials.
  • Rotation optimizationChooses rotation direction based on element position and combines rotations of both stacks when it reduces the total number of instructions.
  • Separate checkerReads an operation sequence from standard input, applies it to the stacks, and verifies whether the final result is valid.

Case study

C++ Foundations & Algorithms

Ten C++ modules that built on my earlier C experience and introduced object-oriented and generic programming.

I completed CPP00–CPP09 independently as part of my studies at Hive Helsinki. The modules gradually introduced C++ concepts on top of the procedural programming experience I already had from C. They started with classes, references, streams, and basic object design, and later moved into inheritance, exceptions, templates, STL containers, and algorithms.

The exercises covered areas such as operator overloading, class hierarchies, virtual functions, abstract base classes, and managing dynamically allocated data through constructors, destructors, copying, and assignment. Later modules introduced exception handling, runtime type identification, reusable templates, iterators, and more extensive use of the C++ standard library.

The final modules focused more on applying these concepts in complete command-line programs. I used maps to work with historical exchange-rate data, a stack to evaluate reverse Polish notation, and templated sorting logic with both vector and deque containers. Across the modules, I became more comfortable with object lifetimes, choosing suitable data structures, separating interfaces from implementation, and writing reusable C++ code.

Technical highlights

  • Object-oriented programmingUses encapsulation, operator overloading, inheritance, virtual functions, and abstract base classes across multiple exercises.
  • Object lifetime and copyingWorks with constructors, destructors, copy construction, assignment, dynamic allocation, and deep copying of owned data.
  • Exceptions and type handlingUses exception handling, scalar conversions, and runtime type identification in different exercises.
  • Templates and iteratorsImplements reusable function and class templates and works with iterator-based operations across different data types.
  • STL containers and algorithmsUses maps, stacks, vectors, and deques for data lookup, expression evaluation, numeric operations, and sorting.

Module overview

  • CPP09 — applied STL containers to historical exchange-rate lookup, a reverse Polish notation calculator, and sorting with vector and deque processing-time comparisons.
  • CPP08 — worked with STL algorithms and iterators through container searches, shortest and longest numeric spans, and a stack extended with iterator access.
  • CPP07 — introduced function and class templates through generic utilities, an array iteration function, and a templated array class.
  • CPP06 — covered C++ casts through scalar conversions, pointer-to-integer serialization, and runtime type identification.
  • CPP05 — used exceptions, abstract forms, and permission checks to model signing and executing forms, with a factory for creating different form types.
  • CPP04 — explored polymorphism, virtual functions, abstract base classes, and deep copying of dynamically allocated data.
  • CPP03 — introduced inheritance through related character classes, including multiple inheritance and constructor/destructor behaviour.
  • CPP02 — built a fixed-point number class with conversions, copy operations, and overloaded arithmetic and comparison operators.
  • CPP01 — covered pointers, references, dynamic allocation, file-based text replacement, member-function pointers, and switch statements.
  • CPP00 — introduced classes, member functions, streams, and static members through small programs including a phonebook and an account class.

Toolkit

Capabilities

These are the areas I have worked with across my projects. Open a project below to see how I used them in practice.

Games & interactive systems

Gameplay programming, physics, UI, and prototyping in Unity and C#, alongside game design and Blender asset workflows.

Web & backend integration

React and TypeScript interfaces, browser-based gameplay, and connecting frontend features to backend APIs, player data, and token-based authentication.

Cross-platform apps

Expo and React Native development with shared TypeScript logic, platform-specific storage and inputs, and local expense and budget data management.

Networking & protocols

IRC command handling in C++, client-server communication, and testing and refining server behaviour with the Irssi client.

Graphics programming

Ray tracing in C, ray-object intersections, camera projection, lighting, and shadows, with MiniLibX for displaying rendered scenes.

Systems & concurrency

Unix processes, pipes, redirections, and signals, alongside POSIX threads, mutex synchronization, timing, and shared-resource management.

Algorithms & data structures

Sorting under constraints, linked lists, and strategy testing in C, plus object-oriented design, templates, and STL containers in C++.

Containers & infrastructure

Custom Docker images, Docker Compose, service networking, HTTPS configuration, persistent data, and automated setup for a WordPress stack.

Get in touch

Contact

Find me on GitHub, LinkedIn, and itch.io.