Various improvements:
authorMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 12 Apr 2023 08:41:18 +0000 (08:41 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 12 Apr 2023 08:41:18 +0000 (08:41 +0000)
- Use getopt(3) and atoi(3) instead of ad-hoc argument management
- Make UFO missiles two animated rows to be closer to those in the
  original game.
- Add a curses(3) atexit(3) cleanup handler.
- Use stdlib EXIT_SUCCESS/EXIT_FAILURE.

MATT-README.txt [new file with mode: 0644]
aliens.c
globals.c
nInvaders.c
view.c

diff --git a/MATT-README.txt b/MATT-README.txt
new file mode 100644 (file)
index 0000000..d40f615
--- /dev/null
@@ -0,0 +1,38 @@
+This code was based on ninvaders-0.1.1 then forked by Matthew
+Mondor, mostly for personal use.
+
+
+BUG FIXES
+
+- Header files were a mess some containing globals that should have
+  been in modules then declared in a header if needed, others
+  lacking proper prototypes, causing ABI and stability issues on
+  64-bit.  Fixed.
+
+
+IMPROVEMENTS
+
+- Allow to build against BSD or other X/Open standard curses(3)
+
+- Use getopt(3) and atoi(3) instead of ad-hoc argument management
+
+- Make UFO missiles two animated rows to be closer to those in the
+  original game.
+
+- Add a curses(3) atexit(3) cleanup handler.
+
+- Use stdlib EXIT_SUCCESS/EXIT_FAILURE.
+
+
+TODO
+
+- Display the last score+level on the title screen if any after a
+  game
+
+- Maybe allow to shoot UFO missiles
+
+- Make difficulty levels more gradual, from 0 to 1 is a chasm
+  already, when it goes up to 9.  It would be more reasonable if
+  the default was around 3 or 5, with 1 rather difficult.  It may
+  also be more intuitive if the difficulty increased with the level,
+  9 being the hardest.
index 242ddb2..ac1f67e 100644 (file)
--- a/aliens.c
+++ b/aliens.c
@@ -223,14 +223,14 @@ int aliensMissileMove()
                        aliensMissileClear(alienshotx[i],alienshoty[i]);        // clear old position
                                
                        // if missile hit the bunkers   
-                       if (bunkersHitCheck(alienshotx[i], alienshoty[i]) == 1) {
+                       if (bunkersHitCheck(alienshotx[i], alienshoty[i] + 1) == 1) {
                                alienshotx[i] = 0;              // value of zero reloads missile
                        }
                        
                        alienshoty[i]++;                        // move missile downwards
                        
                        // check if player was hit by an alien missile
-                       if (playerHitCheck(alienshotx[i], alienshoty[i]) == 1) {
+                       if (playerHitCheck(alienshotx[i], alienshoty[i] + 1) == 1) {
                                alienshotx[i] = 0;              // value of zero reloads missile
                                fPlayerWasHit = 1;
                        }
@@ -253,7 +253,7 @@ int aliensMissileMove()
                // display missiles if still running or just launched; could have been modified in the above code
                if (alienshotx[i] != 0) {
                        // if missile is out of battlefield 
-                       if (alienshoty[i] == SCREENHEIGHT - 1) {
+                       if (alienshoty[i] == SCREENHEIGHT - 2) {
                                alienshotx[i] = 0;      // reload missile       
                        } else {
                                aliensMissileDisplay(alienshotx[i], alienshoty[i]); // display Missile at new position
index 8c0204c..a7ca058 100644 (file)
--- a/globals.c
+++ b/globals.c
@@ -72,7 +72,7 @@ void showUsage(void)
        fprintf(stderr, "   where -l 0=NIGHTMARE\n");
        fprintf(stderr, "         -l 1=okay\n");
        fprintf(stderr, "         -l 9=May I play daddy?!\n");
-       fprintf(stderr, "\n         -gpl shows you the license file\n");
+       fprintf(stderr, "\n         -L display the distribution license\n");
 }
 
 
index 57a756d..d59b387 100644 (file)
 
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/time.h>
+#include <unistd.h>
+
 #include "nInvaders.h"
 #include "player.h"
 #include "aliens.h"
@@ -68,27 +71,32 @@ static void initLevel(void)
  */
 static void evaluateCommandLine(int argc, char **argv)
 {
-       
-       // -l : set skill level
-       if (argc == 3 && strcmp(argv[1], "-l") == 0) {
-               if (argv[2][0] >= '0' && argv[2][0] <= '9') {
-                       skill_level = argv[2][0] - 48;
-               } else {
-                       argc = 2;
+       int ch, i;
+
+       while ((ch = getopt(argc, argv, "?l:L")) != -1) {
+               switch (ch) {
+               case 'l':
+                       if ((i = atoi(optarg)) > -1 && i < 10)
+                               skill_level = i;
+                       else {
+                               showUsage();
+                               exit(EXIT_FAILURE);
+                       }
+                       break;
+               case 'L':
+                       showGpl();
+                       exit(EXIT_SUCCESS);
+                       break;
+               case '?':
+               default: /* FALLTHROUGH */
+                       showVersion();
+                       showUsage();
+                       exit(EXIT_FAILURE);
+                       break;
                }
        }
-
-       // -gpl : show GNU GPL
-       if (argc == 2 && strcmp(argv[1], "-gpl") == 0) {
-               showGpl();
-       }
-
-       // wrong command line: show usage
-       if (argc == 2 || (argc == 3 && strcmp(argv[1], "-l") != 0)) {
-               showVersion();
-               showUsage();
-               exit(1);
-       }
+       argc -= optind;
+       argv += optind;
 }
 
 
@@ -349,8 +357,8 @@ int main(int argc, char **argv)
                // do movements and key-checking
                readInput();
        } while (0 == 0);
-       
-       return 0;
+
+       exit(EXIT_SUCCESS);
 }
 
 
diff --git a/view.c b/view.c
index 6196971..7e5b2f9 100644 (file)
--- a/view.c
+++ b/view.c
 
 #include "view.h"
 #include "globals.h"
+#include <stdbool.h>
 #include <stdlib.h>    
 #include <unistd.h>
 #include <signal.h>
 
+/* Pairs */
 #define RED 1
 #define GREEN 2
 #define YELLOW 3
@@ -36,6 +38,8 @@
 #define MAGENTA 6
 #define WHITE 7
 
+bool curses_initialized = false;
+
 WINDOW *wBattleField;
 WINDOW *wEmpty;
 WINDOW *wScores;       
@@ -44,12 +48,15 @@ WINDOW *wPlayer;
 WINDOW *wPlayerMissile;
 WINDOW *wAliens;
 WINDOW *wAliensMissile;        
+WINDOW *wAliensMissile1;       
+WINDOW *wAliensMissile2;       
 WINDOW *wBunkers;
 WINDOW *wGameOver;
 WINDOW *wUfo;
 WINDOW *wStatus;
 WINDOW *wTitleScreen;
 
+
 /**
  * initialize player sprites
  */
@@ -171,10 +178,22 @@ void aliensClear(int x, int y, int wid, int hgt)
  */
 static void aliensMissileInit(void)
 {
-       wAliensMissile = newpad(1, 1);          // new pad
-       wclear(wAliensMissile);                 // clear pad
-       wattrset(wAliensMissile, COLOR_PAIR(CYAN));     // set color
-       waddch(wAliensMissile, ':');                    // set sprite
+       wAliensMissile1 = newpad(2, 1);                 // new pad
+       wclear(wAliensMissile1);                        // clear pad
+       wattrset(wAliensMissile1, COLOR_PAIR(CYAN));    // set color
+       mvwaddch(wAliensMissile1, 0, 0, '|');           // set sprite
+       mvwaddch(wAliensMissile1, 1, 0, ')');           // set sprite
+       wrefresh(wAliensMissile1);
+
+       wAliensMissile2 = newpad(2, 1);                 // new pad
+       wclear(wAliensMissile2);                        // clear pad
+       wattrset(wAliensMissile2, COLOR_PAIR(CYAN));    // set color
+       mvwaddch(wAliensMissile2, 0, 0, '(');           // set sprite
+       mvwaddch(wAliensMissile2, 1, 0, '|');           // set sprite
+       wrefresh(wAliensMissile2);
+
+       /* This pointer will alternate between the two shapes */
+       wAliensMissile = wAliensMissile1;
 }
 
 
@@ -183,7 +202,12 @@ static void aliensMissileInit(void)
  */
 void aliensMissileDisplay(int x, int y) 
 {
-       copywin(wAliensMissile,wBattleField,0,0,y,x,y,x,0);
+       int r = rand() % 2;
+
+       copywin(wAliensMissile,wBattleField,0,0,y,x,y + 1,x,0);
+
+       /* Toggle between shapes */
+       wAliensMissile = (r == 0 ? wAliensMissile1 : wAliensMissile2);
 }
 
 
@@ -192,7 +216,7 @@ void aliensMissileDisplay(int x, int y)
  */
 void aliensMissileClear(int x, int y) 
 {
-       copywin(wEmpty,wBattleField,0,0,y,x,y,x,0);
+       copywin(wEmpty,wBattleField,0,0,y,x,y + 1,x,0);
 }
 
 
@@ -547,9 +571,16 @@ void refreshScreen(void)
  */
 static void finish(int sig)
 {
-       curs_set(1);
-       endwin();       // <curses.h> reset terminal into proper non-visual mode
-       exit(0);
+       exit(EXIT_SUCCESS);
+}
+
+static void cleanup(void)
+{
+       if (curses_initialized) {
+               curses_initialized = false;
+               (void) curs_set(1);
+               (void) endwin();
+       }
 }
 
 
@@ -558,8 +589,13 @@ static void finish(int sig)
  */
 void graphicEngineInit(void)
 {
+       (void) atexit(cleanup);
+
        (void) signal(SIGINT, finish);  // <signal.h> on signal "SIGINT" call method "finish"
+
        (void) initscr();               // <curses.h> do initialization work 
+       curses_initialized = true;
+
        curs_set(0);
        keypad(stdscr, TRUE);           // <curses.h> enable keypad for input
        (void) nonl();                  // <curses.h> disable translation return/ newline for detection of return key