From 495ca4836fb3c4f078c1e89f1d7ba18c4d4e6006 Mon Sep 17 00:00:00 2001 From: Alireza Ghasemi Date: Sun, 16 Jul 2023 12:07:21 +0330 Subject: [PATCH] Commit original project from early 2019 --- LICENSE.txt | 201 ++++++++++ PacXon.cbp | 53 +++ README.md | 13 + Screenshot.png | Bin 0 -> 16277 bytes ghosts.c | 1 + ghosts.h | 32 ++ main.c | 1017 ++++++++++++++++++++++++++++++++++++++++++++++++ pacman.h | 17 + utils.c | 436 +++++++++++++++++++++ utils.h | 98 +++++ 10 files changed, 1868 insertions(+) create mode 100644 LICENSE.txt create mode 100755 PacXon.cbp create mode 100644 README.md create mode 100644 Screenshot.png create mode 100755 ghosts.c create mode 100755 ghosts.h create mode 100755 main.c create mode 100755 pacman.h create mode 100755 utils.c create mode 100755 utils.h diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/PacXon.cbp b/PacXon.cbp new file mode 100755 index 0000000..87d0603 --- /dev/null +++ b/PacXon.cbp @@ -0,0 +1,53 @@ + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c85dc8 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# PacXon + +A partial PacXon game clone in C & Windows cmd.exe (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. + +> Running the game might be tricky; because it is a legacy software now, and it was not packaged professionally. \ No newline at end of file diff --git a/Screenshot.png b/Screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..6f647745334b983a399099b891633fdb7064464d GIT binary patch literal 16277 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 literal 0 HcmV?d00001 diff --git a/ghosts.c b/ghosts.c new file mode 100755 index 0000000..075fd70 --- /dev/null +++ b/ghosts.c @@ -0,0 +1 @@ +#include "ghosts.h" diff --git a/ghosts.h b/ghosts.h new file mode 100755 index 0000000..5e8116b --- /dev/null +++ b/ghosts.h @@ -0,0 +1,32 @@ +#ifndef GHOSTS_H_INCLUDED +#define GHOSTS_H_INCLUDED + +#include "utils.h" + +//ghosts type coding +#define FLOAT_GHOST 0 +#define RAIL_GHOST 1 +#define BRICK_ZONE_GHOST 2 + +//shapes +#define FLOAT_GHOST_CHAR 224 +#define RAIL_GHOST_CHAR 225 +#define BRICK_ZONE_GHOST_CHAR 235 + +#define A_GHOST_MAX_LOCATIONS 10 + +#define FLOAT_GHOST_LOCATIONSS 1 +#define BRICK_ZONE_GHOST_LOCATIONSS 1 +#define RAIL_GHOST_LOCATIONSS 2 + +//a ghost +typedef struct { + + int type; + int locationss; + Location locations[A_GHOST_MAX_LOCATIONS]; + int movement; + +} Ghost; + +#endif // GHOSTS_H_INCLUDED diff --git a/main.c b/main.c new file mode 100755 index 0000000..df956e7 --- /dev/null +++ b/main.c @@ -0,0 +1,1017 @@ +/** +to dos : + - brick zone ghost creation : appears after 5% + - brick zone ghost move algorithm + - power ups + - progress != 100% bug + - score + - collisions... + - restart + - save and load + - levels + - menu + - reflectDirection method + - colored char struct +**/ + +#include +#include +#include +#include "utils.h" +#include "ghosts.h" +#include "pacman.h" + +#define MAX_GHOSTS 100 //maximum capacity of the ghosts array + +#define REFRESH_RATE 120 //Hz; affects velocity of things in game (pac man, ghosts) + +//shapes +#define BRICK_CHAR 178 + +//the whole game boar dimensions +#define ROWS 30 +#define COLUMNS 70 + +#define WIN_PROGRESS 80 //win condition + +//global variables +int float_ghosts = 2; +int rail_ghosts = 1; +int brick_zone_ghosts = 0; +int ghosts_quantity; //count of active ghosts +Ghost ghosts[MAX_GHOSTS]; //ghosts pool +int bricks[ROWS][COLUMNS]; //-1 for bricks, >= 0 for zones +int view_validation = 0; //the drawn picture is the current state or not, if not redraw it +PacMan pm; //the hero +char picture[ROWS][COLUMNS]; //the whole things view except the header +int score = 0; //score +int progress = 0; //current progress; from 100 +int ghosts_speed_ratio = 3; //ghosts speed = pac man speed / this ratio + +//how ghosts start +//f = count of float ghosts +//r = count of rail ghosts +//b = count of brick zone ghosts +//f + r + b == ghosts_quantity +void initGhosts() { + + int append_index = 0; + + int i; + for(i = 0; i < float_ghosts; i++) { //float ghosts + + addGhost(FLOAT_GHOST, append_index); + append_index++; + + } + + for(i = 0; i < rail_ghosts; i++) { //rail ghosts + + addGhost(RAIL_GHOST, append_index); + append_index++; + + } + + for(i = 0; i < brick_zone_ghosts; i++) { //brick zone ghosts + + addGhost(BRICK_ZONE_GHOST, append_index); + append_index++; + + } + +} + +//for initGhosts method +void addGhost(int type, int index) { + + ghosts[index].type = type; + + switch(type) { + + case FLOAT_GHOST : { + + ghosts[index].locationss = 1; + randPoint(&(ghosts[index].locations[0]), 1, ROWS - 2, 1, COLUMNS - 2); + ghosts[index].movement = randDirection(1); + + break; + } + + case RAIL_GHOST : { + + ghosts[index].locationss = 2; + + int bricks_count = (ROWS * 2 + COLUMNS * 2) - 4; //count of bricks at the start of the game + + int rand_room = rand() % bricks_count; + + //rand_room to location + int i, counter = 0; + for(i = 0; i < ROWS; i++) { + + int j; + for(j = 0; j < COLUMNS; j++) { + + if(bricks[i][j] == -1) { + + if(counter == rand_room) { + + ghosts[index].locations[0].x = i; + ghosts[index].locations[0].y = j; + + //break both loops + i = ROWS; + break; + + } + + counter++; + + } + + } + + } + + //choose a random possible direction + int possiblitites[2]; + int possiblitites_append = 0; + for(i = 0; i < 8; i++) { + + Location t = ghosts[index].locations[0]; + nextLocation(&t, directions[i]); + + if(isBrickThere(t)) { + + possiblitites[possiblitites_append++] = directions[i]; + + printf("%d", possiblitites_append); + + } + + } + + ghosts[index].movement = possiblitites[rand()%2]; + + ghosts[index].locations[1] = ghosts[index].locations[0]; + + if(ghosts[index].movement & VERTICAL) { //vertical + + //left or right + if(ghosts[index].locations[0].y == 0) { //right + + nextLocation(&ghosts[index].locations[1], HORIZONTAL | !LEFT); + + } else { //left + + nextLocation(&ghosts[index].locations[1], HORIZONTAL | LEFT); + + } + + } else { //horizontal + + //up or down + if(ghosts[index].locations[0].x == 0) { //down + + nextLocation(&ghosts[index].locations[1], VERTICAL | !UP); + + } else { //up + + nextLocation(&ghosts[index].locations[1], VERTICAL | UP); + + } + + } + + break; + + } + + case BRICK_ZONE_GHOST : { + + //should initialize the location after the first zone captured + ghosts[index].locationss = 1; + ghosts[index].locations[0].x = -1; + ghosts[index].locations[0].y = -1; + ghosts[index].movement = randDirection(1); + + break; + } + + } + + index++; + +} + +//how pac man starts +void initPacMan() { + + pm.location.x = 0; + pm.location.y = 0; + + pm.movement = -1; + pm.lives = 3; + +} + +//bricks layout at the start +void initBricks() { + + int i; + for(i = 0; i < ROWS; i++) { + + int j; + for(j = 0; j < COLUMNS; j++) { + + if(i == 0 || i == ROWS - 1 || j == 0 || j == COLUMNS - 1) bricks[i][j] = -1; + else bricks[i][j] = 0; //first zone + + } + + } + +} + +//draws whole things +void drawGame() { + + if(view_validation) return; + + updatePicture(); + + cls(); + + //print the header + drawHeader(); + + //print the picture + print2DCharArray(ROWS, COLUMNS, picture); + +} + +void init() { + + ghosts_quantity = float_ghosts + rail_ghosts + brick_zone_ghosts; + + initBricks(); + initGhosts(); + initPacMan(); + +} + +void updatePicture() { + + int i; + for(i = 0; i < ROWS; i++) { + + int j; + for(j = 0; j < COLUMNS; j++) { + + if(bricks[i][j] == -1) picture[i][j] = BRICK_CHAR; //brick here + else if(bricks[i][j] == -2) picture[i][j] = PAC_MAN_TRACE_CHAR;//pacman trace + else picture[i][j] = ' '; //empty + + } + + } + + //add pac man + picture[pm.location.x][pm.location.y] = PAC_MAN_CHAR; + + //add ghosts + for(i = 0; i < ghosts_quantity; i++) { + + int j; + for(j = 0; j < ghosts[i].locationss; j++) { + + picture[ghosts[i].locations[j].x][ghosts[i].locations[j].y] = (ghosts[i].type == FLOAT_GHOST ? FLOAT_GHOST_CHAR : ghosts[i].type == RAIL_GHOST ? RAIL_GHOST_CHAR : ghosts[i].type == BRICK_ZONE_GHOST ? BRICK_ZONE_GHOST_CHAR : SHOULD_NOT_REACH_HERE); + + } + + + } + + view_validation = 1; + +} + +void drawHeader() { + + printf("Lives: %d\tScore: %d\tProgress: %d/%d%c\n", pm.lives, score, progress, WIN_PROGRESS, PERCENT_CHAR); + +} + +void controlAutoMoves() { + + moveGhosts(); + + if(pm.movement != -1) movePacMan(pm.movement, 1); + +} + +//controls ghosts movement +void moveGhosts() { + + static int called_times = 0; + called_times++; + + if(called_times == ghosts_speed_ratio) { + + int i; + for(i = 0; i < ghosts_quantity; i++) { + + moveGhost(i); + + } + + called_times = 0; + + } + +} + +void moveGhost(int i) { + + switch(ghosts[i].type) { + + case FLOAT_GHOST : { + + if(ghosts[i].movement == -1) break; + + Location next = ghosts[i].locations[0]; + + nextLocation(&next, ghosts[i].movement); + + if(!isBrickThere(next)) { //execute the move + + ghosts[i].locations[0] = next; + view_validation = 0; + + } else { //opposite the vertical movement + + ghosts[i].movement = ghosts[i].movement ^ UP; //opposite it + //reset the point + next = ghosts[i].locations[0]; + nextLocation(&next, ghosts[i].movement); + + if(!isBrickThere(next)) { //execute the move + + ghosts[i].locations[0] = next; + view_validation = 0; + + } else { //opposite the horizontal movement + + ghosts[i].movement = ghosts[i].movement ^ UP; //undo vertical changes + ghosts[i].movement = ghosts[i].movement ^ LEFT; //opposite it + //reset the point + next = ghosts[i].locations[0]; + nextLocation(&next, ghosts[i].movement); + + if(!isBrickThere(next)) { //execute the move + + ghosts[i].locations[0] = next; + view_validation = 0; + + } else { //reverse both movements + + ghosts[i].movement = ghosts[i].movement ^ UP; + //reset the point + next = ghosts[i].locations[0]; + nextLocation(&next, ghosts[i].movement); + + if(!isBrickThere(next)) { //execute the move + + ghosts[i].locations[0] = next; + view_validation = 0; + + } else { //stuck + + //stuck in a rail + + //find possible moving directions + + int pdai = 0; //possible directions append index + int possible_directions[4]; + + int j; + for(j = 0; j < 8; j++) { + + if(directions[j] & VERTICAL && directions[j] & HORIZONTAL) continue; //skip 2D directions + + Location t = ghosts[i].locations[0]; + nextLocation(&t, directions[j]); + + if(!isBrickThere(t)) { //add + + possible_directions[pdai++] = directions[j]; + + } + + } + + //debug +// printf("possible directions : "); +// printDirectionsArray(pdai, possible_directions); +// printf("\n"); + + if(pdai == 0); //actually stuck + else { + + //undo changes + ghosts[i].movement = reverseDirection(ghosts[i].movement); + + //debug +// printf("current direction : "); +// printDirection(ghosts[i].movement); +// printf("\n"); + + //find nearest direction to current moving direction from possible_directions + int nearest_direction_index = -1; + int nearest_direction_changes = -1; + + //clockwise and non + for(j = 0; j <= 1; j++) { + + int k; + for(k = 0; k < pdai; k++) { + + int changes = 0; + int direction = ghosts[i].movement; + + while(direction != possible_directions[k]) { + + direction = turnDirection(direction, j, 1); + changes++; + + } + + if(nearest_direction_index == -1 || changes < nearest_direction_changes) { + + nearest_direction_index = k; + nearest_direction_changes = changes; + + } + +// printf("%s To ", j == 1 ? "clockwise" : "non_clockwise"); +// printDirection(possible_directions[k]); +// printf(" = %d\t", changes); + + } + + } + + //update direction on this algorithm + + if(pdai == 1) { + + ghosts[i].movement = reverseDirection(ghosts[i].movement); + + } else { + + if(possible_directions[nearest_direction_index] & HORIZONTAL) { + + ghosts[i].movement ^= UP; + + } else { //vertical + + ghosts[i].movement ^= LEFT; + + } + + } + + //move on nearest direction + nextLocation(&ghosts[i].locations[0], possible_directions[nearest_direction_index]); + view_validation = 0; + + } + + } + + } + + } + + } + + break; + } + + case RAIL_GHOST : { + + //first and second locations should be sync + + int fpai = 0; //first possibilities append index + int first_possibilities[4]; + + int spai = 0; //second possibilities append index + int second_possibilities[4]; + + //check first location moving possibilities + int j; + for(j = 0; j < 8; j++) { + + if(directions[j] & VERTICAL && directions[j] & HORIZONTAL) continue; //skip 2D directions + + Location next = ghosts[i].locations[0]; + nextLocation(&next, directions[j]); + + if(isBrickThere(next)) { //possible + + first_possibilities[fpai++] = directions[j]; + + } + + } + + //check second location moving possibilities + for(j = 0; j < 8; j++) { + + if(directions[j] & VERTICAL && directions[j] & HORIZONTAL) continue; //skip 2D directions + + Location next = ghosts[i].locations[1]; + nextLocation(&next, directions[j]); + + if(!isBrickThere(next)) { //possible + + second_possibilities[spai++] = directions[j]; + + } + + } + + //current moving direction possibility + int first_possibility = linearIntArraySearch(fpai, first_possibilities, ghosts[i].movement) != -1; + int second_possibility = linearIntArraySearch(spai, second_possibilities, ghosts[i].movement) != -1; + + int should_change_first_direction = 0; + int should_change_second_direction = 0; + + if(first_possibility) { + + Location next = ghosts[i].locations[0]; + nextLocation(&next, ghosts[i].movement); + + //check to stay neighbors + if(areNeighborPoints(next, ghosts[i].locations[1])) { //execute it + + ghosts[i].locations[0] = next; + view_validation = 0; + + } else should_change_first_direction = 1; + + } else should_change_first_direction = 1; + + if(second_possibility) { + + Location next = ghosts[i].locations[1]; + nextLocation(&next, ghosts[i].movement); + + //check to stay neighbors + if(areNeighborPoints(next, ghosts[i].locations[0])) { //execute it + + ghosts[i].locations[1] = next; + view_validation = 0; + + } else should_change_second_direction = 1; + + } else should_change_second_direction = 1; + + if(should_change_first_direction && should_change_second_direction) { + + //find common possible directions then remove the reverse of current direction + int commons[2]; + int cai = findCommonElementsOfIntArrays(2, fpai, spai, commons, first_possibilities, second_possibilities); //commons append index + + if(cai != 0) { //found some commons + +// printf("remove index : %d\n", linearIntArraySearch(cai, commons, reverseDirection(ghosts[i].movement))); +// printf("commons before remove %d : ", cai); +// printDirectionsArray(cai, commons); +// printf("\n"); +// +// printf("first p %d : ", fpai); +// printDirectionsArray(fpai, first_possibilities); +// printf("\n"); +// +// printf("second p %d : ", spai); +// printDirectionsArray(spai, second_possibilities); +// printf("\n"); + + //remove the reverse of current direction + if(shiftLeftIntArray(cai, commons, linearIntArraySearch(cai, commons, reverseDirection(ghosts[i].movement)))) cai--; +// else bugAlert("reverse of current direction not removed!\n"); + +// printf("commons %d : ", cai); +// printDirectionsArray(cai, commons); +// printf("\n"); +// printf("current movement : "); +// printDirection(ghosts[i].movement); +// printf("\n"); +// printf("reverse of current movement : "); +// printDirection(reverseDirection(ghosts[i].movement)); +// printf("\n"); +// Sleep(1000); + + if(cai != 0) { + + ghosts[i].movement = commons[0]; + + //if ghosts are not side by side reach that else normal move + if(!areSideBySideLocations(ghosts[i].locations[1], ghosts[i].locations[0], 0)) { //are not side by side + +// bugAlert("are not sbs\n"); + + Location next = ghosts[i].locations[0]; + nextLocation(&next, ghosts[i].movement); + + //check if now side by side + if(!areSideBySideLocations(ghosts[i].locations[1], next, 0)) { //are not side by side + + next = ghosts[i].locations[1]; + nextLocation(&next, ghosts[i].movement); + + //check if now side by side + if(!areSideBySideLocations(next, ghosts[i].locations[0], 0)) { //stuck + + ///wtf + + } else { //execute + + ghosts[i].locations[1] = next; + view_validation = 0; + + } + + } else { //are side by side; execute the move + + ghosts[i].locations[0] = next; + view_validation = 0; + + } + + } else { //are side by side; do a normal move + + moveGhost(i); + + } + + } else { //no commons after removing reverse direction of current moving direction + + //find a direction based on being side by side but not reverse of current direction + for(j = 0; j < 8; j++) { + + if((directions[j] & VERTICAL && directions[j] & HORIZONTAL) || directions[j] == reverseDirection(ghosts[i].movement)) continue; //skip 2D directions and reverse direction of current direction + + Location next = ghosts[i].locations[0]; + nextLocation(&next, directions[j]); + + if(isBrickThere(next)) { //check to be side by side + +// printf("sbs = "); +// printDirection(sbs); +// printf("\n"); + + if(!areSideBySideLocations(ghosts[i].locations[1], next, 0)) continue; //not side by side + else { //found it; execute the move + +// printf("found it : "); +// printDirection(directions[j]); +// printf("\n"); +// Sleep(1000); + + ghosts[i].movement = directions[j]; + + moveGhost(i); + + break; + + } + + } + + } + + } + + } else { //stuck + +// printf("stuckio!\n"); + + //find a direction based on being side by side but not reverse of current direction + for(j = 0; j < 8; j++) { + + if((directions[j] & VERTICAL && directions[j] & HORIZONTAL) || directions[j] == reverseDirection(ghosts[i].movement)) continue; //skip 2D directions and reverse direction of current direction + + Location next = ghosts[i].locations[0]; + nextLocation(&next, directions[j]); + + if(isBrickThere(next)) { + +// printf("sbs = "); +// printDirection(sbs); +// printf("\n"); + + if(!areSideBySideLocations(ghosts[i].locations[1], next, 0)) continue; //not side by side + else { //found it; execute the move + +// printf("found it : "); +// printDirection(directions[j]); +// printf("\n"); +// Sleep(1000); + + ghosts[i].movement = directions[j]; + + moveGhost(i); + + break; + + } + + } + + } + + } + + } + + break; + } + + case BRICK_ZONE_GHOST : { + + /// + + break; + } + + } + +} + +int isBrickThere(Location p) { + + //check location to be in bounds + if(p.x < 0 || p.x > ROWS - 1 || p.y < 0 || p.y > COLUMNS - 1) return 0; //out of bound location + + return bricks[p.x][p.y] < 0; + +} + +int canPacManMove(int direction) { + + if(direction & HORIZONTAL) { + + if(direction & LEFT) return pm.location.y - 1 >= 0; //left + else return pm.location.y + 1 < COLUMNS; //right + + } + + if(direction & VERTICAL) { + + if(direction & UP) return pm.location.x - 1 >= 0; //up + else return pm.location.x + 1 < ROWS; //down + + } + + return SHOULD_NOT_REACH_HERE; + +} + +void updateZones() { + + int current_color = 0; + int current_color_use_time = 0; + + //replace pac man trace with bricks + Replace2DintArray(ROWS, COLUMNS, bricks, -2, -1); + + int i; + for(i = 0; i < ROWS; i++) { + + int j; + for(j = 0; j < COLUMNS; j++) { + + if(bricks[i][j] == -1) { + + if(current_color_use_time > 0) current_color++; + + } else { + + bricks[i][j] = current_color; + current_color_use_time++; + + } + + } + + } + + for(i = 0; i < ROWS; i++) { + + int j; + for(j = 0; j < COLUMNS; j++) { + + if(bricks[i][j] != -1) { + + //check neighbors + Location l; + + int k; + for(k = 0; k < 8; k++) { + + //reset + l.x = i; + l.y = j; + + nextLocation(&l, directions[k]); + + if(bricks[l.x][l.y] == -1) continue; + else { //a zone number + + int o; + for(o = 0; o < ROWS; o++) { + + int p; + for(p = 0; p < COLUMNS; p++) { + + if(bricks[o][p] == -1) continue; + else if(bricks[o][p] == bricks[i][j]) bricks[o][p] = bricks[l.x][l.y]; + + } + + } + + } + + } + + } + + } + + } + +} + +void tryCaptureZones() { + + int ghosts_zones[float_ghosts * FLOAT_GHOST_LOCATIONSS + rail_ghosts * RAIL_GHOST_LOCATIONSS + brick_zone_ghosts * BRICK_ZONE_GHOST_LOCATIONSS]; + + int i; + for(i = 0; i < ghosts_quantity; i++) { + + int j; + for(j = 0; j < ghosts[i].locationss; j++) { + + ghosts_zones[i] = bricks[ghosts[i].locations[j].x][ghosts[i].locations[j].y]; + + } + + } + + for(i = 0; i < ROWS; i++) { + + int j; + for(j = 0; j < COLUMNS; j++) { + + if(bricks[i][j] == -1) continue; + else if(linearIntArraySearch(ghosts_quantity, ghosts_zones, bricks[i][j]) == -1) { + + Replace2DintArray(ROWS, COLUMNS, bricks, bricks[i][j], -1); + + } + + } + + } + +} + +void updateProgress() { + + int bricks_count = 0; + + int i; + for(i = 0; i < ROWS; i++) { + + int j; + for(j = 0; j < COLUMNS; j++) { + + if(bricks[i][j] == -1) bricks_count++; + + } + + } + + static int all_bricks_count = (ROWS - 2) * (COLUMNS - 2); + + progress = ((float) bricks_count - (2 * (ROWS + COLUMNS))) / (float) all_bricks_count * 100; + view_validation = 0; + +} + +int movePacMan(int direction, int auto_call) { + + if(!canPacManMove(direction)) return 0; + + if(!auto_call && pm.movement != -1) { + + if(reverseDirection(pm.movement) != direction) pm.movement = direction; + + return 0; + + } + + nextLocation(&pm.location, direction); + + if(bricks[pm.location.x][pm.location.y] != -1) { //stepped out of the safe zone, run! + + bricks[pm.location.x][pm.location.y] = -2; + + pm.movement = direction; + + } else { //reached the end or moving on the safe zone + + if(pm.movement != -1) { //reached the end + + updateZones(); + tryCaptureZones(); + updateProgress(); + pm.movement = -1; + + } + + } + + view_validation = 0; + + return 1; + +} + +int arrowToDirection(char a) { + + switch(a) { + + case UAKCC : return VERTICAL | UP; + case DAKCC : return VERTICAL | !UP; + case LAKCC : return HORIZONTAL | LEFT; + case RAKCC : return HORIZONTAL | !LEFT; + + } + + return SHOULD_NOT_REACH_HERE; + +} + +int main(){ + + srand(time(NULL)); //for absolute random + system("chcp 437"); //support ascii characters + cls(); //clear Active Code Page : 437 + + init(); + + drawGame(); + + while(1) { + + if(_kbhit()) { + + char c = _getch(); + + switch(c) { //key press handler + + case AKCCM : { //arrow key + + movePacMan(arrowToDirection(_getch()), 0); + + break; + } + + case SKCC : { + + bricks[pm.location.x][pm.location.y] = 0; + updateZones(); + tryCaptureZones(); + + } + + //default : printf("%d\t", c); + + } + + } + + purgePressedKeys(); + controlAutoMoves(); + drawGame(); + Sleep(1000/REFRESH_RATE); + } + + return 0; + +} diff --git a/pacman.h b/pacman.h new file mode 100755 index 0000000..0a139d0 --- /dev/null +++ b/pacman.h @@ -0,0 +1,17 @@ +#ifndef PACMAN_H_INCLUDED +#define PACMAN_H_INCLUDED + +#include "utils.h" + +#define PAC_MAN_CHAR 'O' +#define PAC_MAN_TRACE_CHAR 176 + +typedef struct { + + Location location; + int movement; + int lives; + +} PacMan; + +#endif // PACMAN_H_INCLUDED diff --git a/utils.c b/utils.c new file mode 100755 index 0000000..f20c485 --- /dev/null +++ b/utils.c @@ -0,0 +1,436 @@ +#include "utils.h" + +#include +#include +#include + +int randFlag() { + + return rand()%2; + +} + +void randPoint(Location * p, int minx, int maxx, int miny, int maxy) { + + p->x = minx + rand() % (maxx - minx + 1); + p->y = miny + rand() % (maxy - miny + 1); + +} + +void print2DCharArray(int rows, int columns, char c[rows][columns]) { + + int i; + for(i = 0; i < rows; i++) { + + int j; + for(j = 0; j < columns; j++) { + + printf("%c", c[i][j]); + + } + + printf("\n"); + + } + +} + +void printIntArray(int length, int array[length]) { + + int i; + for(i = 0; i < length; i++) { + + printf("%d", array[i]); + + if(i != length - 1) printf(", "); + + } + +} + +void printDirectionsArray(int length, int directions[length]) { + + int i; + for(i = 0; i < length; i++) { + + printDirection(directions[i]); + + if(i != length - 1) printf(", "); + + } + +} + +void printDirection(int direction) { + + int vertical_printed = 0; + + if(direction & VERTICAL) { + + if(direction & UP) printf("Up"); + else printf("Down"); + + vertical_printed = 1; + + } + + if(direction & HORIZONTAL) { + + if(direction & LEFT) { + + if(vertical_printed) printf(" Left"); + else printf("Left"); + + } else { + + if(vertical_printed) printf(" Right"); + else printf("Right"); + + } + + } + + +} + +int Replace2DintArray(int rows, int columns, int array[rows][columns], int key, int replace) { + + int replaceds = 0; + + int i; + for(i = 0; i < rows; i++) { + + int j; + for(j = 0; j < columns; j++) { + + if(array[i][j] == key) { + + array[i][j] = replace; + replaceds++; + + } + + } + + } + + return replaceds; + +} + +int linearIntArraySearch(const int N, int array[N], int key) { + + int i; + for(i = 0; i < N; i++) { + + if(array[i] == key) return i; + + } + + return -1; + +} + +void cls() { + + system("cls"); + +} + +void nextLocation(Location * next, int direction) { + + if(direction & VERTICAL) { + + if(direction & UP) { //up + + next->x--; + + } else { //down + + next->x++; + + } + + } + + if(direction & HORIZONTAL) { + + if(direction & LEFT) { //left + + next->y--; + + } else { //right + + next->y++; + + } + + } + +} + +int reverseDirection(int direction) { + + if(direction & HORIZONTAL) direction ^= LEFT; + + if(direction & VERTICAL) direction ^= UP; + + return direction; + +} + +int randDirection(int diagonal) { + + if(diagonal) { + + return VERTICAL | HORIZONTAL | (randFlag() ? LEFT : !LEFT) | (randFlag() ? UP : !UP); + + } else { + + 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; + + + } + +} + +void purgePressedKeys() { + + while(_kbhit()) _getch(); + +} + +int areNeighborPoints(Location p1, Location p2) { + + if(areEqualPoints(p1, p2)) return 0; + + int i; + for(i = 0; i < 8; i++) { + + Location temp = p2; + + nextLocation(&temp, directions[i]); + + if(areEqualPoints(p1, temp)) return 1; + + } + + return 0; + +} + +int areEqualPoints(Location p1, Location p2) { + + return p1.x == p2.x && p1.y == p2.y; + +} + +void printPointArray(int length, Location p[length]) { + + int i; + for(i = 0; i < length; i++) { + + printf("(%d, %d) ", p[i].x, p[i].y); + + } + +} + +void pVector(Location p1, Location p2, Location * result) { + + result->x = p2.x - p1.x; + result->y = p2.y - p1.y; + +} + +int vectorToDirection(Location vector) { + + if(vector.x < 0 && vector.y < 0) { //up left + + return VERTICAL | HORIZONTAL | LEFT | UP; + + } else if(vector.x < 0 && vector.y == 0) { //up + + return VERTICAL | UP; + + } else if(vector.x < 0 && vector.y > 0) { //up right + + return VERTICAL | HORIZONTAL | !LEFT | UP; + + } else if(vector.x == 0 && vector.y < 0) { //left + + return HORIZONTAL | LEFT; + + } else if(vector.x == 0 && vector.y == 0) { //zero vector + + return SHOULD_NOT_REACH_HERE; + + } else if(vector.x == 0 && vector.y > 0) { //right + + return HORIZONTAL | !LEFT; + + } else if(vector.x > 0 && vector.y < 0) { //down left + + return HORIZONTAL | VERTICAL | !UP | LEFT; + + } else if(vector.x > 0 && vector.y == 0) { //down + + return VERTICAL | !UP; + + } else if(vector.x > 0 && vector.y > 0) { //down right + + return VERTICAL | HORIZONTAL | !UP | !LEFT; + + } + +} + +int areSideBySideLocations(Location l1, Location l2, int check_being_neighbors) { + + if(check_being_neighbors && !areNeighborPoints(l1, l2)) return 0; + + Location vector; + + pVector(l1 ,l2, &vector); + + int sbs = vectorToDirection(vector); + + if(sbs & VERTICAL && sbs & HORIZONTAL) return 0; + else return 1; + +} + +void printPoint(Location p) { + + printf("(%d, %d)", p.x, p.y); + +} + +int reflectDirection(int direction, int mirror_position) { + + /// + +} + +int findCommonElementsOfIntArrays(int result_length, int array1_length, int array2_length, int result[result_length], int array1[array1_length], int array2[array2_length]) { + + int rai = 0; //result append index + int has_space = result_length != 0; + + //set the smaller length array as base + + if(array1_length < array2_length) { + + int i; + for(i = 0; i < array1_length; i++) { + + if(linearIntArraySearch(array2_length, array2, array1[i]) != -1) { //found a common int + + if(has_space) result[rai] = array1[i]; + + rai++; + + if(rai == result_length) has_space = 0; + + } + + } + + } else { + + int i; + for(i = 0; i < array2_length; i++) { + + if(linearIntArraySearch(array1_length, array1, array2[i]) != -1) { //found a common int + + if(has_space) result[rai] = array2[i]; + + rai++; + + if(rai == result_length) has_space = 0; + + } + + } + + } + + return rai; + +} + +void insertionSortIntArray(int length, int array[length]) { + + int i; + for(i = 1; i < length; i++) { + + int j; + for(j = i; array[j] < array[j-1] && j > 0; j--) { + + int t = array[j]; + array[j] = array[j-1]; + array[j-1] = t; + + } + + } + +} + +int shiftLeftIntArray(int N, int array[N], int remove_index) { + + if(remove_index < 0) return 0; + if(remove_index == N - 1) return 1; + + int executed = 0; + + int i; + for(i = remove_index + 1; i < N; i++) { + + int t = array[i]; + array[i] = array[i-1]; + array[i-1] = t; + + if(!executed) executed = 1; + + } + + return executed; + +} + +void bugAlert(char * msg) { + + printf("Bug : %s", msg); + Sleep(1000); + +} + +int turnDirection(int direction, int clockwise, int steps) { + + //find its index at directions + int index; + if((index = linearIntArraySearch(8, directions, direction)) == -1) return SHOULD_NOT_REACH_HERE; //not a direction + + int i; + for(i = 0; i < steps; i++) { + + if(clockwise) { + + direction = directions[index == 7 ? 0 : index + 1]; + + } else { + + direction = directions[index == 0 ? 7 : index - 1]; + + } + + } + + return direction; + +} + + diff --git a/utils.h b/utils.h new file mode 100755 index 0000000..eb0e53b --- /dev/null +++ b/utils.h @@ -0,0 +1,98 @@ +#ifndef UTILS_H_INCLUDED +#define UTILS_H_INCLUDED + +#include +#include +#include + +//directions +#define VERTICAL 0b0001 +#define HORIZONTAL 0b0010 +#define LEFT 0b0100 +#define UP 0b1000 + +//Key Char Codes = KCC +#define AKCCM -32 //Arrow Key Char Code Modifier +#define LAKCC 75 //Left Arrow Key Char Code +#define RAKCC 77 //Right Arrow Key Char Code +#define UAKCC 72 //Up Arrow Key Char Code +#define DAKCC 80 //Down Arrow Key Char Code +#define SKCC 32 //Enter Key Char Code + +//something +#define SHOULD_NOT_REACH_HERE -1 + +#define PERCENT_CHAR 37 //percent character + +//point = location; x = row, y = column +typedef struct { + + int x, y; + +} Location; + +//clockwise order +static int 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 + +//random boolean +int randFlag(); + +//fills the passed point with random x, y within inclusive specified bounds +void randPoint(Location * p, int minx, int maxx, int miny, int maxy); + +//prints the 2D char array +void print2DCharArray(int rows, int columns, char c[rows][columns]); + +//clear dos +void cls(); + +//next step of the move by the specified direction +//next : current location; will be replaced by the new location +void nextLocation(Location * next, int movement); + +int randDirection(int diagonal); + +void printIntArray(int length, int a[length]); + +void printPointArray(int length, Location p[length]); + +void printPoint(Location p); + +void pVector(Location p1, Location p2, Location * result); + +int areEqualPoints(Location p1, Location p2); + +int areNeighborPoints(Location p1, Location p2); + +int reverseDirection(int direction); + +void printIntArray(int length, int array[length]); + +void printDirection(int direction); + +int linearIntArraySearch(const int N, int array[N], int key); + +int Replace2DintArray(int rows, int columns, int array[rows][columns], int key, int replace); + +void insertionSortIntArray(int length, int array[length]); + +//returns founded elements count; result array filled length +int findCommonElementsOfIntArrays(int result_length, int array1_length, int array2_length, int result[result_length], int array1[array1_length], int array2[array2_length]); + +//returns the shift execution +int shiftLeftIntArray(int N, int array[N], int remove_index); + +void bugAlert(char * msg); + +int areSideBySideLocations(Location l1, Location l2, int check_being_neighbors); + +int turnDirection(int direction, int clockwise, int steps); + +#endif // UTILS_H_INCLUDED