Skip to content

Commit

Permalink
Merge develop branch into Master branch - Release v1.1.0 (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
hozlucas28 authored Sep 20, 2024
2 parents a261be3 + 77a4b6a commit b9b7d36
Show file tree
Hide file tree
Showing 116 changed files with 57,713 additions and 406 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ obj/
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
Expand Down
44 changes: 36 additions & 8 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,62 @@
"& (mkdir \"${workspaceFolder}\\libs\\bin\\Release\")"
],
"group": {"kind": "build", "isDefault": false},
"label": "Create \\libs\\obj\\Release and \\libs\\bin\\Release folders",
"label": "Create `\\libs\\obj\\Release` and `\\libs\\bin\\Release` folders",
"type": "shell"
},
{
"command": [
"(gcc -Wall -O2 -pedantic-errors -c \"${workspaceFolder}\\libs\\utilities.c\" -o \"${workspaceFolder}\\libs\\obj\\Release\\utilities.o\")",
"& (gcc -Wall -O2 -pedantic-errors -c \"${workspaceFolder}\\libs\\validators.c\" -o \"${workspaceFolder}\\libs\\obj\\Release\\validators.o\")",
"& (gcc -Wall -O2 -pedantic-errors -c \"${workspaceFolder}\\libs\\patterns\\constructors.c\" -o \"${workspaceFolder}\\libs\\obj\\Release\\constructors.o\")",
"& (gcc -Wall -O2 -pedantic-errors -c \"${workspaceFolder}\\libs\\patterns\\methods.c\" -o \"${workspaceFolder}\\libs\\obj\\Release\\methods.o\")",
"& (ar -r -s \"${workspaceFolder}\\libs\\bin\\Release\\libs.a\" \"${workspaceFolder}\\libs\\obj\\Release\\constructors.o\" \"${workspaceFolder}\\libs\\obj\\Release\\methods.o\" \"${workspaceFolder}\\libs\\obj\\Release\\utilities.o\" \"${workspaceFolder}\\libs\\obj\\Release\\validators.o\")"
"& (gcc -Wall -O2 -pedantic-errors -c \"${workspaceFolder}\\libs\\game\\methods.c\" -o \"${workspaceFolder}\\libs\\obj\\Release\\game-methods.o\")",
"& (gcc -Wall -O2 -pedantic-errors -c \"${workspaceFolder}\\libs\\patterns\\constructors.c\" -o \"${workspaceFolder}\\libs\\obj\\Release\\patterns-constructors.o\")",
"& (gcc -Wall -O2 -pedantic-errors -c \"${workspaceFolder}\\libs\\patterns\\methods.c\" -o \"${workspaceFolder}\\libs\\obj\\Release\\patterns-methods.o\")",
"& (ar -r -s \"${workspaceFolder}\\libs\\bin\\Release\\libs.a\" \"${workspaceFolder}\\libs\\obj\\Release\\game-methods.o\" \"${workspaceFolder}\\libs\\obj\\Release\\patterns-constructors.o\" \"${workspaceFolder}\\libs\\obj\\Release\\patterns-methods.o\" \"${workspaceFolder}\\libs\\obj\\Release\\utilities.o\" \"${workspaceFolder}\\libs\\obj\\Release\\validators.o\")"
],
"group": {"kind": "build", "isDefault": false},
"label": "Compile libs project",
"type": "shell",
"dependsOn": "Create \\libs\\obj\\Release and \\libs\\bin\\Release folders"
"dependsOn": "Create `\\libs\\obj\\Release` and `\\libs\\bin\\Release` folders"
},
{
"command": [
"(if exist \"${workspaceFolder}\\src\\obj\" rmdir /s /q \"${workspaceFolder}\\src\\obj\")",
"& (mkdir \"${workspaceFolder}\\src\\obj\\Release\")",
"& (if exist \"${workspaceFolder}\\src\\bin\" rmdir /s /q \"${workspaceFolder}\\src\\bin\")",
"& (mkdir \"${workspaceFolder}\\src\\bin\\Release\")"
],
"group": {"kind": "build", "isDefault": false},
"label": "Create `\\src\\obj\\Release` and `\\src\\bin\\Release` folders",
"type": "shell"
},
{
"command": "copy \"${workspaceFolder}\\src\\SDL2.dll\" \"${workspaceFolder}\\src\\bin\\Release\\SDL2.dll\"",
"dependsOn": "Create `\\src\\obj\\Release` and `\\src\\bin\\Release` folders",
"group": {"kind": "build", "isDefault": false},
"label": "Copy `SDL2.dll` file from `.\\src\\` into `.\\src\\bin\\Release\\",
"type": "shell"
},
{
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"${workspaceFolder}\\src\\*.c",
"${workspaceFolder}\\src\\sdl\\*.c",
"-o",
"${fileDirname}\\bin\\Release\\${fileBasenameNoExtension}.exe",
"${workspaceFolder}\\src\\bin\\Release\\src.exe",
"-I${workspaceFolder}\\src\\sdl\\SDL2\\include\\SDL2",
"-I${workspaceFolder}\\src\\sdl\\SDL2\\include",
"-L${workspaceFolder}\\src\\sdl\\SDL2\\lib",
"-lSDL2",
"-lSDL2main",
"-s",
"${workspaceFolder}\\libs\\bin\\Release\\libs.a"
],
"command": "gcc",
"dependsOn": "Compile libs project",
"dependsOn": [
"Compile libs project",
"Copy `SDL2.dll` file from `.\\src\\` into `.\\src\\bin\\Release\\"
],
"group": {"kind": "build", "isDefault": true},
"label": "C/C++: gcc.exe build active file",
"problemMatcher": ["$gcc"],
Expand Down
71 changes: 71 additions & 0 deletions libs/game/macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@

#ifndef GAME_MACROS_H_INCLUDED
#define GAME_MACROS_H_INCLUDED

/**
* @def DASHBOARD_ROWS
* @brief Defines the number of rows in a grid.
*
* This macro is used to define the number of rows in a grid.
* It is typically used in conjunction with the `DASHBOARD_COLS` macro to define
* the size of a grid.
*
* @warning The value of `DASHBOARD_ROWS` must be a positive integer.
*/
#define DASHBOARD_ROWS 56

/**
* @def DASHBOARD_COLS
* @brief Defines the number of columns in a grid.
*
* This macro is used to define the number of columns in a grid.
* It is typically used in conjunction with the `DASHBOARD_ROWS` macro to define
* the size of a grid.
*
* @warning The value of `DASHBOARD_COLS` must be a positive integer.
*/
#define DASHBOARD_COLS 110

/**
* @def ALIVE_CELL
* @brief Represents a live cell.
*
* @warning The value of `ALIVE_CELL` must be a single character.
*/
#define ALIVE_CELL 'o'

/**
* @def ALIVE_CELL_NG
* @brief Represents a cell that is going to be alive in the next generation.
*
* @warning The value of `ALIVE_CELL_NG` must be a single character and must not be equal to
* `ALIVE_CELL`, `DEAD_CELL`, or `DEAD_CELL_NG` macros.
*/
#define ALIVE_CELL_NG '1'

/**
* @def DEAD_CELL
* @brief Represents a dead cell.
*
* @warning The value of `DEAD_CELL` must be a single character.
*/
#define DEAD_CELL ' '

/**
* @def DEAD_CELL_NG
* @brief Represents a cell that is going to be dead in the next generation.
*
* @warning The value of `DEAD_CELL_NG` must be a single character and must not be equal to
* `ALIVE_CELL`, `ALIVE_CELL_NG`, or `DEAD_CELL` macros.
*/
#define DEAD_CELL_NG '0'

/**
* @def NEIGHBORHOOD_RADIUS
* @brief Defines the radius of the neighborhood.
*
* @warning The value of `NEIGHBORHOOD_RADIUS` must be greater or equal to 1.
*/
#define NEIGHBORHOOD_RADIUS 1

#endif // GAME_MACROS_H_INCLUDED
10 changes: 10 additions & 0 deletions libs/game/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

#ifndef GAME_MAIN_H_INCLUDED
#define GAME_MAIN_H_INCLUDED

// Root
#include "./macros.h"
#include "./methods.h"
#include "./structs.h"

#endif // GAME_MAIN_H_INCLUDED
233 changes: 233 additions & 0 deletions libs/game/methods.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@

#include "./methods.h"

#include <limits.h>
#include <stdio.h>

#include "../patterns/main.h"
#include "./macros.h"
#include "./structs.h"

int countAliveNeighbors(TGame* pGame, int cellRow, int cellCol, int radius) {
int i;
int j;

int startRow = cellRow - radius;
int startCol = cellCol - radius;

int endRow = cellRow + radius + 1;
int endCol = cellCol + radius + 1;

int aliveNeighbors = 0;

for (i = startRow; i < endRow; i++) {
if (i > pGame->rows - 1) break;
if (i < 0) continue;

for (j = startCol; j < endCol; j++) {
if (j > pGame->cols - 1) break;
if (j < 0) continue;

if (i == cellRow && j == cellCol) continue;

if (pGame->dashboard[i][j] == ALIVE_CELL || pGame->dashboard[i][j] == DEAD_CELL_NG)
aliveNeighbors++;
}
}

return aliveNeighbors;
}

void drawPattern(TGame* pGame, char* pattern) {
TPattern SPattern;

char arr[PATTERN_ROWS][PATTERN_COLS];

SPattern.arr = arr;

fillDashboard(pGame, DEAD_CELL);

if (strcmpi(pattern, "glider") == 0) {
newGliderPattern(&SPattern);
pGame->cellsAlive = 5;
} else if (strcmpi(pattern, "glider cannon") == 0) {
newGliderCannonPattern(&SPattern);
pGame->cellsAlive = 36;
} else if (strcmpi(pattern, "press") == 0) {
newPressPattern(&SPattern);
pGame->cellsAlive = 48;
} else if (strcmpi(pattern, "toad") == 0) {
newToadPattern(&SPattern);
pGame->cellsAlive = 6;
} else {
return;
}

pGame->cellsDead = (pGame->cols * pGame->rows) - pGame->cellsAlive;
pGame->generation = 0;

drawPatternInDashboard(pGame, &SPattern);
}

void drawPatternInDashboard(TGame* pGame, TPattern* pPattern) {
int i;
int j;

int pI = 0;
int pJ = 0;

int startRow = pGame->center[0] - pPattern->center[0];
int startCol = pGame->center[1] - pPattern->center[1];

for (i = startRow; pI < pPattern->rows; i++) {
if (i < 0) continue;
if (i > pGame->rows - 1) break;

for (j = startCol; pJ < pPattern->cols; j++) {
if (j < 0) continue;
if (j > pGame->cols - 1) break;

pGame->dashboard[i][j] = pPattern->arr[pI][pJ];
pJ++;
};

pJ = 0;
pI++;
}
}

void fillDashboard(TGame* pGame, char with) {
int i;
int j;

for (i = 0; i < pGame->rows; i++) {
for (j = 0; j < pGame->cols; j++) {
pGame->dashboard[i][j] = with;
}
}
}

void generateNextGeneration(TGame* pGame) {
int i;
int j;

int aliveNeighbors;

for (i = 0; i < pGame->rows; i++) {
for (j = 0; j < pGame->cols; j++) {
aliveNeighbors = countAliveNeighbors(pGame, i, j, NEIGHBORHOOD_RADIUS);

if (pGame->dashboard[i][j] == DEAD_CELL) {
if (aliveNeighbors == 3) {
pGame->cellsDead--;
pGame->cellsAlive++;
pGame->dashboard[i][j] = ALIVE_CELL_NG;
};

continue;
}

if (aliveNeighbors < 2 || aliveNeighbors > 3) {
pGame->cellsAlive--;
pGame->cellsDead++;
pGame->dashboard[i][j] = DEAD_CELL_NG;
};
}
}

for (i = 0; i < pGame->rows; i++) {
for (j = 0; j < pGame->cols; j++) {
if (pGame->dashboard[i][j] == DEAD_CELL_NG) {
pGame->dashboard[i][j] = DEAD_CELL;
continue;
}

if (pGame->dashboard[i][j] == ALIVE_CELL_NG) pGame->dashboard[i][j] = ALIVE_CELL;
}
}
}

void printDashboardByConsole(TGame* pGame) {
int i;
int j;

for (i = 0; i < pGame->rows; i++) {
printf("\n");

for (j = 0; j < pGame->cols; j++) {
printf("%c", pGame->dashboard[i][j]);
}
}
}

void printGameByConsole(TGame* pGame) {
int i;
int j;

// Print header
for (i = 0; i < pGame->cols + 2; i++) printf("-");

printf("\n| Cells alive: %*d |", pGame->cols - 17 + 2, pGame->cellsAlive);
printf("\n| Cells dead: %*d |", pGame->cols - 16 + 2, pGame->cellsDead);
printf("\n| Generation: %*d |", pGame->cols - 16 + 2, pGame->generation);

if (pGame->maximumGeneration == INT_MAX) {
printf("\n| Maximum generation: %*s |", pGame->cols - 25 + 3, "infinity");
} else {
printf("\n| Maximum generation: %*d |", pGame->cols - 25 + 3, pGame->maximumGeneration);
}

printf("\n| Delay between generations: %*d ms |\n", pGame->cols - 35 + 3,
pGame->delayBetweenGenerations);

// Print dashboard
for (i = 0; i < pGame->cols + 2; i++) printf("-");

for (i = 0; i < pGame->rows; i++) {
printf("\n|");

for (j = 0; j < pGame->cols; j++) {
printf("%c", pGame->dashboard[i][j]);
}

printf("|");
}

printf("\n");
for (i = 0; i < pGame->cols + 2; i++) printf("-");
}

void setDashboardCenter(TGame* pGame) {
int row = pGame->rows / 2;
int col = pGame->cols / 2;

pGame->center[0] = row;
pGame->center[1] = col;
}

void startGameByConsole(TGame* pGame, int maxGeneration, int delayBetweenGenerations) {
int generation = 0;
int isToInfinity = maxGeneration == INT_MAX;

pGame->generation = 0;
pGame->maximumGeneration = maxGeneration;
pGame->delayBetweenGenerations = delayBetweenGenerations;

system("cls");
printGameByConsole(pGame);
if (generation == maxGeneration) return;
sleep(delayBetweenGenerations);

while (isToInfinity || generation < maxGeneration) {
generateNextGeneration(pGame);

if (generation != INT_MAX) {
generation++;
pGame->generation = generation;
};

system("cls");
printGameByConsole(pGame);
if (generation != maxGeneration) sleep(delayBetweenGenerations);
}
}
Loading

0 comments on commit b9b7d36

Please sign in to comment.