Skip to content
This repository has been archived by the owner on Jul 20, 2023. It is now read-only.

Commit

Permalink
Portability & Refactor (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
agcom authored Jul 16, 2023
1 parent 765f677 commit 425424b
Show file tree
Hide file tree
Showing 14 changed files with 1,066 additions and 1,587 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea/
cmake-build-*/
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.22.1)
project(PacXon C)

set(CMAKE_C_STANDARD 11)

find_package(Curses REQUIRED)
include_directories(${CURSES_INCLUDE_DIR})

add_executable(PacXon main.c)
target_link_libraries(PacXon curses)
53 changes: 0 additions & 53 deletions PacXon.cbp

This file was deleted.

22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
# PacXon

A partial PacXon game clone in C & Windows cmd.exe (you can play the original version [here](https://www.pacxon.net/)).
A partial PacXon game clone in C, on CLI (you can play the original version [here](https://www.pacxon.net/)).

This game was my final project for the **computer fundamentals and programming** university course, made in **early 2019**.

![A Screenshot](./Screenshot.png)

## Simple build & run

Open the project in Code::Blocks 17.12 (with MinGW) on a Windows OS, and hit Build and run.
> Pro-tip: use an **IDE** to build and run the project.
> Running the game might be tricky; because it is left behind as a **legacy**, and it is not packaged properly.
### Ubuntu

> Tested on Ubuntu 22.04 LTS.
- `sudo apt install cmake gcc make libncurses-dev`.
- `cmake . && make && ./PacXon`

Or

- `sudo apt install gcc libncurses-dev`
- `gcc main.c -lncurses && ./a.out`

### Other Operating Systems, including Windows

Figure it out yourself :slightly_smiling_face:.

> Fow Windows, you can check out earlier commit [765f67781980fb90d9b2bdfef960878687298926](https://github.com/agcom/pacxon/tree/765f67781980fb90d9b2bdfef960878687298926) and follow the instructions there.
69 changes: 69 additions & 0 deletions dir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#ifndef DIR_C_INCLUDED
#define DIR_C_INCLUDED

#include <stdbool.h>
#include "utils.c"

// Directions' masks
#define VERTICAL 0b0001
#define HORIZONTAL 0b0010
#define LEFT 0b0100
#define UP 0b1000

typedef int dir_t;

// Clock-wise order
const dir_t all_directions[8] = {
VERTICAL | UP, // UP
HORIZONTAL | VERTICAL | UP | !LEFT, // Up Right
HORIZONTAL | !LEFT, // Right
HORIZONTAL | VERTICAL | !UP | !LEFT, // Down Right
VERTICAL | !UP, // Down
HORIZONTAL | VERTICAL | !UP | LEFT, // Down Left
HORIZONTAL | LEFT, // Left
HORIZONTAL | VERTICAL | UP | LEFT // Up Left
};

void print_dir(const dir_t dir) {
bool is_vertical_printed = false;

if (dir & VERTICAL) {
if (dir & UP) printf("Up");
else printf("Down");

is_vertical_printed = true;
}

if (dir & HORIZONTAL) {
if (is_vertical_printed) printf(" ");

if (dir & LEFT) printf("Left");
else printf("Right");
}
}

void print_dir_arr(const int size, const dir_t dirs[size]) {
int i;
for (i = 0; i < size; i++) {
print_dir(dirs[i]);
if (i != size - 1) printf(", ");
}
}

int turn_dir(dir_t dir, const bool clockwise, const int steps) {

// Find its index at directions
int index;
if ((index = linear_int_arr_search(8, all_directions, dir)) == -1)
return SHOULD_NOT_REACH_HERE; // Not a direction

int i;
for (i = 0; i < steps; i++) {
if (clockwise) dir = all_directions[index == 7 ? 0 : index + 1];
else dir = all_directions[index == 0 ? 7 : index - 1];
}

return dir;
}

#endif // DIR_C_INCLUDED
31 changes: 30 additions & 1 deletion ghosts.c
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
#include "ghosts.h"
#ifndef GHOSTS_C_INCLUDED
#define GHOSTS_C_INCLUDED

#include "loc.c"

// Ghosts type coding
typedef enum {
FLOAT_GHOST, RAIL_GHOST, BRICK_ZONE_GHOST
} ghost_type_t;

// Shapes
#define FLOAT_GHOST_CHAR "α"
#define RAIL_GHOST_CHAR "ß"
#define BRICK_ZONE_GHOST_CHAR "δ"

// Locations needed sizes
#define FLOAT_GHOST_LOCS_SIZE 1
#define BRICK_ZONE_GHOST_LOCS_SIZE 1
#define RAIL_GHOST_LOCS_SIZE 2

#define MAX_GHOST_LOCS_SIZE 2

typedef struct {
ghost_type_t type;
int locs_size;
loc_t locs[MAX_GHOST_LOCS_SIZE];
int movement;
} ghost_t;

#endif // GHOSTS_C_INCLUDED
32 changes: 0 additions & 32 deletions ghosts.h

This file was deleted.

14 changes: 14 additions & 0 deletions kbhit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef KBHIT_C_INCLUDED
#define KBHIT_C_INCLUDED

#include <curses.h>

int kbhit() {
const int c = getch();
if (c != ERR) {
ungetch(c);
return 1;
} else return 0;
}

#endif // KBHIT_C_INCLUDED
106 changes: 106 additions & 0 deletions loc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#ifndef LOC_C_INCLUDED
#define LOC_C_INCLUDED

#include <stdlib.h>
#include "dir.c"
#include "utils.c"

// x = row & y = column
typedef struct {
int x, y;
} loc_t;

void rand_loc(loc_t *p, const int min_x, const int max_x, const int min_y, const int max_y) {
p->x = min_x + rand() % (max_x - min_x + 1);
p->y = min_y + rand() % (max_y - min_y + 1);
}

void next_loc(loc_t *next, const dir_t dir) {
if (dir & VERTICAL) {
if (dir & UP) next->x--;
else next->x++;
}

if (dir & HORIZONTAL) {
if (dir & LEFT) next->y--;
else next->y++;
}
}

int reverse_dir(dir_t dir) {
if (dir & HORIZONTAL) dir ^= LEFT;
if (dir & VERTICAL) dir ^= UP;

return dir;
}

int rand_dir(const bool is_diagonal) {
if (is_diagonal) return VERTICAL | HORIZONTAL | (rand_bool() ? LEFT : !LEFT) | (rand_bool() ? UP : !UP);
else {
const int rnd = rand() % 4;
return rnd == 0 ? (HORIZONTAL | LEFT) :
rnd == 1 ? (VERTICAL | UP) :
rnd == 2 ? (HORIZONTAL | !LEFT) :
rnd == 3 ? (VERTICAL | !UP) : SHOULD_NOT_REACH_HERE;
}

}

bool are_equal_locs(const loc_t p1, const loc_t p2) {
return p1.x == p2.x && p1.y == p2.y;
}

bool are_neighbour_locs(const loc_t p1, const loc_t p2) {
if (are_equal_locs(p1, p2)) return false;

int i;
for (i = 0; i < 8; i++) {
loc_t t = p2;
next_loc(&t, all_directions[i]);
if (are_equal_locs(p1, t)) return true;
}

return false;
}

void locs_diff_vector(const loc_t p1, const loc_t p2, loc_t *res) {
res->x = p2.x - p1.x;
res->y = p2.y - p1.y;
}

int loc_vector_to_dir(const loc_t vector) {
if (vector.x < 0 && vector.y < 0) return VERTICAL | HORIZONTAL | LEFT | UP; // Up Left
else if (vector.x < 0 && vector.y == 0) return VERTICAL | UP; // Up
else if (vector.x < 0 && vector.y > 0) return VERTICAL | HORIZONTAL | !LEFT | UP; // Up Right
else if (vector.x == 0 && vector.y < 0) return HORIZONTAL | LEFT; // Left
else if (vector.x == 0 && vector.y > 0) return HORIZONTAL | !LEFT; // Right
else if (vector.x > 0 && vector.y < 0) return HORIZONTAL | VERTICAL | !UP | LEFT; // Down Left
else if (vector.x > 0 && vector.y == 0) return VERTICAL | !UP; // Down
else if (vector.x > 0 && vector.y > 0) return VERTICAL | HORIZONTAL | !UP | !LEFT; // Down Right
else return SHOULD_NOT_REACH_HERE; // Zero vector
}

bool are_size_by_size_locs(const loc_t l1, const loc_t l2, const bool check_being_neighbors) {
if (check_being_neighbors && !are_neighbour_locs(l1, l2)) return false;

loc_t vector;
locs_diff_vector(l1, l2, &vector);

const int diff_dir = loc_vector_to_dir(vector);
if (diff_dir & VERTICAL && diff_dir & HORIZONTAL) return false;
else return true;
}

void print_loc(const loc_t p) {
printf("(%d, %d)", p.x, p.y);
}

void print_loc_arr(const int size, const loc_t locs[size]) {
int i;
for (i = 0; i < size; i++) {
print_loc(locs[i]);
printf(" ");
}
}

#endif // LOC_C_INCLUDED
Loading

0 comments on commit 425424b

Please sign in to comment.