Initial import of early custom changes after fork from https://codeberg.org/gwync...
authorMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 4 Apr 2023 03:07:28 +0000 (03:07 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 4 Apr 2023 03:07:28 +0000 (03:07 +0000)
17 files changed:
MATT-README.txt [new file with mode: 0644]
src/Makefile.am
src/Makefile.in
src/check_collision.cpp
src/enemy_shoot.cpp
src/enemy_shoot.h
src/init.cpp
src/main.cpp
src/mishaps.cpp
src/mishaps.h
src/motion.cpp
src/play_sound_effect.cpp
src/play_sound_effect.h
src/powerup.cpp
src/powerup.h
src/radar_plot.cpp
src/randmac.h [new file with mode: 0644]

diff --git a/MATT-README.txt b/MATT-README.txt
new file mode 100644 (file)
index 0000000..3799e0d
--- /dev/null
@@ -0,0 +1,146 @@
+
+NOTES
+=====
+
+Apparently was inspired by Datastorm for the Amiga, itself inspired
+by Defender.
+
+https://listman.redhat.com/archives/fedora-package-review/2010-January/msg00685.html
+https://bugzilla.redhat.com/show_bug.cgi?id=552999
+
+
+After writing Aquatron-inspired Espadon for SDL and then AnalogTerm2,
+I planned on writing a Defender-inspired game, seeing that no such
+package existed on Debian or Ubuntu.  I however eventually found
+this one, especially when searching for "ncurses" instead of "ascii".
+It seemed promising with improvements and worth paying with.  After
+my changes, notably fixing the clock, I definitely had some fun
+playing it, enough to reach level 10 with a score of 1593 on the
+second day.  Cool project!
+
+Since I'm not completely satisfied at the changes, especially the
+autoconfiguration/build ones and optional SDL support, I just forked
+and posted it for now.
+
+
+BUILD
+=====
+
+The configure system couldn't locate my ncurses package.  This
+should eventually be improved.  I also commented out SDL library
+dependencies for now.  Note that for some reason "make distclean"
+destroys the configuration by unexpectedly deleting some necessary
+files.
+
+Removed -lSDL2 -lSDL2_mixer from:
+Makefile.am
+Makefile.in
+
+$ ./configure CXXFLAGS='-I/usr/pkg/include -I/usr/pkg/include/ncurses' LDFLAGS='-L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib -lncurses'
+$ make
+$ src/curblaster
+
+
+GENERAL CHANGES
+===============
+
+- SDL support was made optional and various fixes were made so it
+  builds successfully.  I often run terminal programs remotely and
+  there's no point in having SDL on a server.  My systerms with
+  SDL also used 1.2, not v2 which this depended on, but to which
+  not all SDL utility libs were ported.  This should really be
+  redone in an autoconf friendly way.
+
+- Increased the maximum player speed from 4 to 5 in process_direction().
+
+- Introduced randmac.h which now defaults to srandom(3) and random(3)
+  rather than weaker srand(3)/rand(3).  Easy to change via the
+  definitions.
+
+- Added an endwin(3) cleanup handler as well as error check for
+  initscr(3).  Because some systems like OSX also do not properly
+  restore the original terminal state at endwin(3), explicit termios
+  tcgetattr(2)/tcsetattr(2) and cleanup handler were added.
+
+
+BUGS FIXED
+==========
+
+- A bug existed producing more than one screen clear per frame.
+  The resulting blinking was not noticed on refresh-rate controlled
+  AnalogTerm2 that is somewhat equivalent to double-buffering, but
+  was more visible in XTerm and URxvt.  This was fixed by using
+  clearok(win, FALSE) after the main clear(), so that subsequent
+  [w]refresh() avoid implicit extra re-clearing.
+
+- Objects high up on the map appeared on the floor rather than on
+  the first map line.  Line = 0 was supposed to be line = 1.
+
+- Another bug was discovered where with the way the timer and game
+  click was implemented, the game accelerates stepping immediately
+  with user action.  Was fixed by using a stable timer and a custom
+  getch(3) replacement, not interrupted by user keys but where the
+  last user key if any is acknowledged at the next clock tick.  I
+  had a previous successful test of such an interactive program
+  using getch(3) for input and setitimer(2).  The clock was set
+  for 10 FPS, which appeared to be the intened rate.
+
+- ncurses and curses support the interpretation of terminal-specific
+  arrow sequences but the original code did not use it, instead
+  ignoring ESC and [ then but looking explicitly for some characters
+  used in VT100 sequences.  This also explains why my initial stable
+  timer code wasn't working for navigation anymore.  The code now
+  uses KEY_* macros while also supporting alternative navigation
+  keys.
+
+- The ship's speed was not reset when completing a level.
+
+- The random staging can cause the ship to immediately boom without
+  action if it appears too close to another object.  Either the
+  ship should temporarily be invulnerable, placed at a more
+  intelligently selected location like an empty screen, or both.
+  To mitigate this a temporarily non-costing shield is now up.
+
+
+TODO AND OTHER BUGS
+===================
+
+- Maybe the ship's position should be reset when a level completes?
+
+- The configure script should be regenerated so that it supports
+  searching for the ncurses prefix or allows to specify it, instead
+  of having to use custom CXXFLAGS/LDFLAGS.  It may also be possible
+  to use the native curses(3) on systems that have it, like NetBSD.
+
+- In this game, like in Espadon, our ship remains at the center,
+  when in Defender it moves within a window to leave more room for
+  sight ahead.  This might be considered.  Interestingly, Nadir's
+  Gorgon for the Apple ][ inverses this, possibly a bug.
+
+- It would be possible to embed nbrandom, the NetBSD libc
+  random(3)/srandom(3) implementation, like was done for Espadon.
+  It's not under GPL, though.  If we eventually wanted to support
+  stable staging with a fixed seed somewhere, it would be important
+  for the same PRNG to be used on all systems instead of relying
+  on each particular libc.
+
+- The game currently saves one high score but not the levels.
+  Ideally it should have a scoreboard and allow the user to enter
+  their name, etc.  The code dealing with files could also be safer.
+
+- Some command line options may be useful, like changing the FPS
+  rate, maximum player speed, perhaps a few cheating options.
+
+- The use of color would be nice.  It would also be possible to
+  optionally use some graphics characters when available.  I could
+  also add AnalgTerm2 specific features like loading a custom OCR
+  or Square font set, or even alter some characters for special
+  graphics.
+
+- When we hit foes with hit points that don't immediately explode
+  at the first hit, there is no effect showing that they have been
+  hit.  A few mini-explosion artifacts like * would be nice.
+
+- It's still possible that I eventually write my own ASCII shooter,
+  it'd follow my coding style, be C99, use my libraries and be
+  under BSDL.
index 7ade511..f663899 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS = curblaster
 curblaster_SOURCES = age_bullet.cpp age_bullet.h check_collision.cpp check_collision.h draw.cpp draw.h enemy_shoot.cpp enemy_shoot.h gravitize.cpp gravitize.h init.cpp init.h main.cpp mishaps.cpp mishaps.h motion.cpp motion.h object_out.cpp object_out.h play_sound_effect.cpp play_sound_effect.h powerup.cpp powerup.h radar_plot.cpp radar_plot.h
-curblaster_LDADD = -lncurses -lSDL2 -lSDL2_mixer
+curblaster_LDADD = -lncurses
 
 curblasterdir = $(datadir)/curblaster/data
 curblaster_DATA = ../data/boom.ogg ../data/enshot.ogg ../data/missile.ogg ../data/pup-take.ogg ../data/shot.ogg ../data/crazify.ogg ../data/laser.ogg ../data/pickup.ogg ../data/shielddown.ogg ../data/title_music.ogg ../data/dropoff.ogg ../data/level_end.ogg ../data/pup-create.ogg ../data/shieldup.ogg ../data/warning.ogg
index 0b93d47..913d1ae 100644 (file)
@@ -305,7 +305,7 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 curblaster_SOURCES = age_bullet.cpp age_bullet.h check_collision.cpp check_collision.h draw.cpp draw.h enemy_shoot.cpp enemy_shoot.h gravitize.cpp gravitize.h init.cpp init.h main.cpp mishaps.cpp mishaps.h motion.cpp motion.h object_out.cpp object_out.h play_sound_effect.cpp play_sound_effect.h powerup.cpp powerup.h radar_plot.cpp radar_plot.h
-curblaster_LDADD = -lncurses -lSDL2 -lSDL2_mixer
+curblaster_LDADD = -lncurses
 curblasterdir = $(datadir)/curblaster/data
 curblaster_DATA = ../data/boom.ogg ../data/enshot.ogg ../data/missile.ogg ../data/pup-take.ogg ../data/shot.ogg ../data/crazify.ogg ../data/laser.ogg ../data/pickup.ogg ../data/shielddown.ogg ../data/title_music.ogg ../data/dropoff.ogg ../data/level_end.ogg ../data/pup-create.ogg ../data/shieldup.ogg ../data/warning.ogg
 dist_curblaster_DATA = $(curblaster_DATA)
index 809c2da..683b1e3 100644 (file)
@@ -18,4 +18,4 @@ int check_collision(game_object object1, game_object object2){
   };
 
   return collided;
-};
\ No newline at end of file
+};
index 300c72e..e3cc8c6 100644 (file)
@@ -1,13 +1,23 @@
+#ifdef __USE_SDL__
 #include "SDL2/SDL.h"
 #include "SDL2/SDL_mixer.h"
+#endif
 
 #include "game_object.h"
+#ifdef __USE_SDL__
 #include "play_sound_effect.h"
+#endif
 
+#ifdef __USE_SDL__
 game_object enemy_shoot(game_object enemy, game_object player, game_object shot, int enshotchannel, Mix_Chunk *enshotsound){
+#else
+game_object enemy_shoot(game_object enemy, game_object player, game_object shot){
+#endif
 
   int multiplier = 1;
+#ifdef __USE_SDL__
   play_sound_effect(enshotsound, enshotchannel);
+#endif
   shot.active=1;
   //set direction
   if(player.y<enemy.y){ 
@@ -27,4 +37,4 @@ game_object enemy_shoot(game_object enemy, game_object player, game_object shot,
   shot.y = enemy.y + (enemy.speed * multiplier);
 
   return shot;
-};
\ No newline at end of file
+};
index 6fcf5e8..f0a3b15 100644 (file)
@@ -1 +1,5 @@
+#ifdef __USE_SDL__
 game_object enemy_shoot(game_object, game_object, game_object, int, Mix_Chunk*);
+#else
+game_object enemy_shoot(game_object, game_object, game_object);
+#endif
index 927bfac..4cdccd6 100644 (file)
@@ -1,12 +1,13 @@
 #include <cstdlib>
 
 #include "game_object.h"
+#include "randmac.h"
 
 game_object pod_init(game_object pod){
   pod.active=1;
   pod.x = 18;  //always start on ground
-  pod.y = rand()%620; //anywhere along the surface
-  pod.direction = rand()%1000;
+  pod.y = RAND()%620; //anywhere along the surface
+  pod.direction = RAND()%1000;
   if(pod.direction<500){
     pod.direction = 4;
   } else {
@@ -19,9 +20,9 @@ game_object pod_init(game_object pod){
 
 game_object lander_init(game_object lander){
   lander.active=1;
-  lander.x = rand()%17;
-  lander.y = rand()%600+20;
-  lander.direction = rand()%1000;
+  lander.x = RAND()%17;
+  lander.y = RAND()%600+20;
+  lander.direction = RAND()%1000;
   if(lander.direction<500){
     lander.direction = 4;
   } else {
@@ -35,8 +36,8 @@ game_object lander_init(game_object lander){
 game_object crawler_init(game_object crawler){
   crawler.active=1;
   crawler.x = 18;
-  crawler.y = rand()%600+20;
-  crawler.direction = rand()%1000;
+  crawler.y = RAND()%600+20;
+  crawler.direction = RAND()%1000;
   if(crawler.direction<500){
     crawler.direction = 4;
   } else {
@@ -49,9 +50,9 @@ game_object crawler_init(game_object crawler){
 
 game_object boss_init(game_object boss, int level){
   boss.active=1;
-  boss.x = rand()%17;
-  boss.y = rand()%600+20;
-  boss.direction = rand()%1000;
+  boss.x = RAND()%17;
+  boss.y = RAND()%600+20;
+  boss.direction = RAND()%1000;
   if(boss.direction<500){
     boss.direction = 4;
   } else {
@@ -65,7 +66,7 @@ game_object boss_init(game_object boss, int level){
 
 game_object player_init(game_object player){
   player.x = 18;
-  player.y = rand()%600+20;
+  player.y = RAND()%600+20;
   player.direction = 5;
   player.face = 1;
   player.speed = 0;
index 8cee644..fa6043a 100644 (file)
@@ -1,6 +1,7 @@
 /*
    Curblaster
    Copyright (C) 2022 Gwyn Ciesla
+   Copyright (C) 2023 Matthew Mondor
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -17,19 +18,27 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
 */
 
+#include <err.h>
 #include <ncurses.h>
 #include <cstring>
 #include <cstdlib>
 #include <time.h>
 #include <cstdio>
 #include <math.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
 #include <string>
+#include <termios.h>
+#include <unistd.h>
 #include <vector>
+#ifdef __USE_SDL__
 #include "SDL2/SDL.h"
 #include "SDL2/SDL_mixer.h"
+#endif
 
 #include "game_object.h"
 #include "check_collision.h"
@@ -40,9 +49,166 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "init.h"
 #include "draw.h"
 #include "powerup.h"
+#ifdef __USE_SDL__
 #include "play_sound_effect.h"
+#endif
 #include "mishaps.h"
 #include "enemy_shoot.h"
+#include "randmac.h"
+
+
+
+/*
+ * Stable game clock and related utilities
+ * Try this at 15, it's already limit, try 30!
+ */
+
+#define ANIM_FPS       10              /* 10Hz ticks */
+#define TEMP_SHIELD    (ANIM_FPS * 2)  /* 2 secs */
+
+static void clock_init(void);
+static void sighandler(int);
+static void cleanup(void);
+
+static bool clock_expired = false;
+
+static int uc = ERR;
+
+static WINDOW *win = NULL;
+
+void
+clock_init(void)
+{
+       struct sigaction act;
+       struct itimerval itv;
+
+       /* Setup signal handler */
+       act.sa_handler = sighandler;
+       act.sa_flags = 0; /* ~SA_RESTART to detect interruptions */
+       if (sigemptyset(&act.sa_mask) != 0)
+               err(EXIT_FAILURE, "sigemptyset()");
+       if (sigaction(SIGALRM, &act, NULL) != 0)
+               err(EXIT_FAILURE, "sigaction(SIGALRM)");
+       if (sigaction(SIGINT, &act, NULL) != 0)
+               err(EXIT_FAILURE, "sigaction(SIGINT)");
+       if (sigaction(SIGTERM, &act, NULL) != 0)
+               err(EXIT_FAILURE, "sigaction(SIGTERM)");
+       if (sigaction(SIGHUP, &act, NULL) != 0)
+               err(EXIT_FAILURE, "sigaction(SIGHUP)");
+
+       /* Setup interval timer */
+       timerclear(&itv.it_interval);
+       timerclear(&itv.it_value);
+       itv.it_interval.tv_sec = 0;
+       itv.it_interval.tv_usec = 1000000 / ANIM_FPS;
+       itv.it_value.tv_sec = itv.it_interval.tv_sec;
+       itv.it_value.tv_usec = itv.it_interval.tv_usec;
+       if (setitimer(ITIMER_REAL, &itv, NULL) != 0)
+               err(EXIT_FAILURE, "setitimer()");
+}
+
+static void
+sighandler(int sig)
+{
+
+       switch (sig) {
+       case SIGALRM:
+               clock_expired = true;
+               break;
+       case SIGINT:
+       case SIGTERM: /* FALLTHROUGH */
+       case SIGHUP: /* FALLTHROUGH */
+               exit(EXIT_SUCCESS);
+               break;
+       }
+}
+
+static void
+cleanup(void)
+{
+
+       if (win != NULL) {
+               endwin();
+               win = NULL;
+       }
+}
+
+/*
+ * This getch(3) variant is designed to wait until the next clock tick and to
+ * return user input if any, also using the curses internal terminal sequence
+ * interpretation for special keys like arrows.  ERR is returned if there was
+ * no user input.  The wgetch(3) function reads in blocking mode and could
+ * wait forever, but is awaken by the regular interval timer that sets an
+ * expired flag.  If it awakes because of user input before the timer expired,
+ * we record the key and block on read again.  This ensures that unlike with
+ * halfdelay(3), we have a stable clock even when extensive user input occurs.
+ */
+static int
+stable_getch(void)
+{
+       int c;
+
+       (void)keypad(win, TRUE);
+       (void)timeout(-1);
+
+       for (clock_expired = false; !clock_expired; ) {
+               if ((c = wgetch(win)) != ERR)
+                       uc = c;
+       }
+
+       c = uc;
+       uc = ERR;
+
+       return c;
+}
+
+
+/*
+ * On some systems like OSX [n]curses endwin() is not enough to properly
+ * restore the original terminal state.  We can do it explicitly.
+ */
+
+static void            term_save(void);
+static void            term_load(void);
+
+static struct termios  old_tios;
+
+static void
+term_save(void)
+{
+
+       if (tcgetattr(STDIN_FILENO, &old_tios) == -1)
+               err(EXIT_FAILURE, "tcgetattr()");
+       /* Exit cleanup hook to restore normal terminal */
+       (void)atexit(term_load);
+
+}
+
+static void
+term_load(void)
+{
+
+       (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_tios);
+}
+
+
+
+static void tempshield(void);
+
+int shieldup = 0;
+int temp_shield = 0;
+int super_shield = 0;
+
+static void
+tempshield(void)
+{
+
+       shieldup = 1;
+       temp_shield = TEMP_SHIELD;
+       super_shield += TEMP_SHIELD;
+}
+
+
 
 const int podmax = 8;
 const int bulletmax = 10;
@@ -63,7 +229,6 @@ int shieldsleft = 400;
 int tripshot = 0;
 int laser = 0;
 int missile = 0;
-int super_shield = 0;
 int sound = 1;
 int newgame = 0;
 
@@ -73,7 +238,7 @@ int main(int argc, char *argv[]){
   
   if(argc==2&&strcmp(argv[1], "--nosound")==0){ sound = 0; };
  
-  srand(time(NULL));
+  SRAND(time(NULL));
 
   level = 1;
   score = 0;
@@ -178,18 +343,18 @@ int main(int argc, char *argv[]){
 
   //pods
   game_object pods[podmax] = {
-    { 2, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 3, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 4, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 5, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 6, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 7, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 8, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 9, 1, 18, rand()%620, 0, 0, 1, 0, 0 }
+    { 2, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 3, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 4, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 5, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 6, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 7, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 8, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 9, 1, 18, RAND()%620, 0, 0, 1, 0, 0 }
  };
 
   for(int podloop = 0; podloop<podmax; podloop=podloop+2){ 
-    if(rand()%1000>=500){
+    if(RAND()%1000>=500){
       pods[podloop].direction = 4;
     } else {
       pods[podloop].direction = 6;
@@ -205,7 +370,7 @@ int main(int argc, char *argv[]){
   };
 
   for(int podloop = 1; podloop<podmax+1; podloop=podloop+2){ 
-    if(rand()%1000>=500){
+    if(RAND()%1000>=500){
       pods[podloop].direction = 4;
     } else {
       pods[podloop].direction = 6;
@@ -241,22 +406,22 @@ int main(int argc, char *argv[]){
 
   //landers
   game_object landers[landermax] = {
-    { 60, 1, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 61, 1, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 62, 1, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 63, 1, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 64, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 65, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 66, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 67, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 68, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 69, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 70, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 },
-    { 71, 0, rand()%16, rand()%620, 0, 0, 1, 0, 0 }
+    { 60, 1, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 61, 1, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 62, 1, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 63, 1, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 64, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 65, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 66, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 67, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 68, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 69, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 70, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 },
+    { 71, 0, RAND()%16, RAND()%620, 0, 0, 1, 0, 0 }
   };
   
   for(int landerloop = 0; landerloop<landermax; landerloop++){ 
-    if(rand()%1000>=500){
+    if(RAND()%1000>=500){
       landers[landerloop].direction = 4;
     } else {
       landers[landerloop].direction = 6;
@@ -386,16 +551,16 @@ int main(int argc, char *argv[]){
 
   //crawlers 
   game_object crawlers[crawlermax] = {
-    { 30, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 31, 1, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 32, 0, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 33, 0, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 34, 0, 18, rand()%620, 0, 0, 1, 0, 0 },
-    { 35, 0, 18, rand()%620, 0, 0, 1, 0, 0 }
+    { 30, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 31, 1, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 32, 0, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 33, 0, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 34, 0, 18, RAND()%620, 0, 0, 1, 0, 0 },
+    { 35, 0, 18, RAND()%620, 0, 0, 1, 0, 0 }
   };
   
   for(int crawlerloop = 0; crawlerloop<crawlermax; crawlerloop++){ 
-    if(rand()%1000>=500){
+    if(RAND()%1000>=500){
       crawlers[crawlerloop].direction = 4;
     } else {
       crawlers[crawlerloop].direction = 6;
@@ -469,7 +634,11 @@ int main(int argc, char *argv[]){
     missiles[missileloop].chase = -1;
   };
 
-  initscr();
+  clock_init();
+  term_save();
+
+  if ((win = initscr()) == NULL)
+         err(EXIT_FAILURE, "initscr()");
 
   //Check screen size 80x24 and exit if not big enough
   int maxx, maxy;
@@ -482,6 +651,8 @@ int main(int argc, char *argv[]){
     exit(1);
   };
 
+  (void)atexit(cleanup);
+
   //main loop
 
   int loopvar = 0;
@@ -494,11 +665,10 @@ int main(int argc, char *argv[]){
   int alertleft = 0;
   int alertright = 0;
   int smartbombs = 2;
-  int shieldup = 0;
   int drawlaser = 0;
 
   cbreak();
-  halfdelay(1);
+  halfdelay(1); /* XXX */
   noecho();
 
   //print title screen
@@ -521,8 +691,9 @@ int main(int argc, char *argv[]){
   //Version
   mvprintw(12,34,"Version %1.2f",version);
 
-  //Copyright
+  //Copyright/credits
   mvprintw(14,22,"Copyright (C) 2022 Gwyn Ciesla");
+  mvprintw(15,22,"Copyright (C) 2023 Matthew Mondor");
 
   //player, lander, pods, gate
   mvprintw(17,5,"<_==>     -   - - - ");
@@ -568,6 +739,7 @@ int main(int argc, char *argv[]){
   mvprintw(23,79,"-");
 
   //load sound, music
+#ifdef __USE_SDL__
   Mix_Chunk *shotsound = NULL;
   int shotchannel = -1;
   Mix_Chunk *boomsound = NULL;
@@ -598,12 +770,14 @@ int main(int argc, char *argv[]){
   int levelendchannel = -1;        
 
   Mix_Music *title = NULL;
+#endif
 
   char *env_tty;
   env_tty = getenv("SSH_TTY");
 
   struct stat datatest;
     
+#ifdef __USE_SDL__
   if(env_tty == NULL && sound == 1){
 
     int audio_rate = 22050;
@@ -611,7 +785,6 @@ int main(int argc, char *argv[]){
     int audio_channels = 6;
     int audio_buffers = 4096;
 
-
     SDL_Init(SDL_INIT_AUDIO);
 
     if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) {
@@ -649,6 +822,11 @@ int main(int argc, char *argv[]){
 
   //start title music
   Mix_PlayMusic(title, -1);
+#else
+  sound = 0;
+#endif
+
+  tempshield();
 
   //hold until SPACE pressed
   pause_game = 0;
@@ -671,16 +849,22 @@ int main(int argc, char *argv[]){
     counter++;
     //halfdelay(1);
   };
-  
+#ifdef __USE_SDL__
   Mix_HaltMusic();
   Mix_FreeMusic(title);
   title = NULL;
+#endif
   
   while(loopvar == 0){
 
     int input = 0;
-    
+
     clear();
+    /* Without this the next wrefresh() clears twice producing unnecessary
+     * flickering on some terminals. */
+    clearok(win, FALSE);
+
     // Draw board
     draw_board(score, lives, level, shieldsleft, missile);
 
@@ -706,7 +890,7 @@ int main(int argc, char *argv[]){
              pods[podloop].vtime = 1;
              pods[podloop].chase = -1;
              pods[podloop].speed = 1;
-             if(rand()%1000>=500){
+             if(RAND()%1000>=500){
                pods[podloop].direction = 4;
              } else {
                pods[podloop].direction = 6;
@@ -735,7 +919,11 @@ int main(int argc, char *argv[]){
          missiles[missileloop] = process_motion(missiles[missileloop], player);
          //missiles[missileloop] = age_bullet(missiles[missileloop]);  //Something to think about
         } else {
+#ifdef __USE_SDL__
          drawlocation = boom_object(drawlocation, boomstuff, missiles[missileloop], boomsound, boomchannel);
+#else
+         drawlocation = boom_object(drawlocation, boomstuff, missiles[missileloop]);
+#endif
          missiles[missileloop] = object_out(missiles[missileloop]);
         };
       };
@@ -762,7 +950,11 @@ int main(int argc, char *argv[]){
        };
        if(landers[landerloop].chase>=0&&landers[landerloop].phase==4){ //decode which pod to kill
          pods[landers[landerloop].chase] = object_out(pods[landers[landerloop].chase]);
+#ifdef __USE_SDL__
          crazies[landerloop] = encrazify(landers[landerloop], crazies[landerloop], crazifysound, crazifychannel);
+#else
+         crazies[landerloop] = encrazify(landers[landerloop], crazies[landerloop]);
+#endif
          landers[landerloop] = object_out(landers[landerloop]);
        };
       };
@@ -921,14 +1113,18 @@ int main(int argc, char *argv[]){
     //alerts
     if(alertright>0){
       if(alertright%2==0){
+#ifdef __USE_SDL__
         warningchannel = play_sound_effect(warningsound, warningchannel);
+#endif
        mvprintw(19,50," >> ");
       };
       alertright--;
     };
     if(alertleft>0){
       if(alertleft%2==0){
+#ifdef __USE_SDL__
         warningchannel = play_sound_effect(warningsound, warningchannel);
+#endif
        mvprintw(19,40," << ");
       };
       alertleft--;
@@ -953,14 +1149,15 @@ int main(int argc, char *argv[]){
     mvprintw(23,79,"|");
 
 
-    input = getch();
+    input = stable_getch();
     
     //quit
     if(input=='q'){
+    char quit;
     cbreak();
     clear();
-    printw("Really quit? (y/n)");
-    char quit = getch();
+    printw("Really quit (y/n)? ");
+    for (quit = ERR; quit != 'y' && quit != 'n'; quit = getch()) ;
     if(quit=='y'){
       printw("\nBye Bye!\n");
       loopvar=1;       
@@ -973,11 +1170,15 @@ int main(int argc, char *argv[]){
       if(shieldup==0){
        if(shieldsleft>=1){
          shieldup=1;
+#ifdef __USE_SDL__
          shieldupchannel = play_sound_effect(shieldupsound, shieldupchannel);
+#endif
        };
       } else {
        shieldup=0;
+#ifdef __USE_SDL__
        shielddownchannel = play_sound_effect(shielddownsound, shielddownchannel);
+#endif
       };
     };
 
@@ -994,16 +1195,48 @@ int main(int argc, char *argv[]){
 
     //deplete shields if necessary.
     if(shieldup==1){
+      if (temp_shield > 0) {
+             if (--temp_shield == 0)
+                     shieldup = 0;
+      } else
       if(shieldsleft>0){
        shieldsleft--;
       } else {
        shieldup=0;
+#ifdef __USE_SDL__
        shielddownchannel = play_sound_effect(shielddownsound, shielddownchannel);
+#endif
       };
     };
 
     //check for / process direction change
-    if(input==66||input==68||input==67||input==65||input==69){
+    switch (input) {
+    case KEY_UP:
+    case '8': /* FALLTHROUGH */
+    case 'i': /* FALLTHROUGH */
+           input = 8;
+           break;
+    case KEY_DOWN:
+    case '2': /* FALLTHROUGH */
+    case 'k': /* FALLTHROUGH */
+    case 'm': /* FALLTHROUGH */
+           input = 2;
+           break;
+    case KEY_LEFT:
+    case '4': /* FALLTHROUGH */
+    case 'j': /* FALLTHROUGH */
+           input = 4;
+           break;
+    case KEY_RIGHT:
+    case '6': /* FALLTHROUGH */
+    case 'l': /* FALLTHROUGH */
+           input = 6;
+           break;
+    case '5': /* Apparently unused */
+           input = 5;
+           break;
+    }
+    if(input==8||input==2||input==4||input==6||input==5){
       player = process_direction(player, input);
     };
 
@@ -1022,7 +1255,9 @@ int main(int argc, char *argv[]){
     //check for powerup pickup
     for(int puploop = 0; puploop<4; puploop++){
       if((powerups[puploop].active==1)&&(check_collision(powerups[puploop], player)==1)){
+#ifdef __USE_SDL__
         puptakechannel = play_sound_effect(puptakesound, puptakechannel);
+#endif
        powerups[puploop] = object_out(powerups[puploop]);
        if(strncmp(powerups[puploop].line0, "T", 1)==0){
          tripshot = tripshot + 100;
@@ -1057,7 +1292,9 @@ int main(int argc, char *argv[]){
     //check for / process pod pickup
     for(int podloop = 0; podloop<podmax; podloop++){ 
       if((pod_in==0)&&(pods[podloop].active==1)&&(check_collision(pods[podloop], player)==1)){
+#ifdef __USE_SDL__
         pickupchannel = play_sound_effect(pickupsound, pickupchannel);
+#endif
        pod_in = pods[podloop].number;
        pods[podloop].chase = -1;
        //stop the chase if we steal the pod
@@ -1080,7 +1317,9 @@ int main(int argc, char *argv[]){
     //if pod in hand, check for gate dropoff
     if(pod_in>0){
       if((abs(player.y-gate.y)<player.speed)&&(player.x>10)){
+#ifdef __USE_SDL__
         dropoffchannel = play_sound_effect(dropoffsound, dropoffchannel);
+#endif
        //set pod inactive
        for(int podloop = 0; podloop<podmax; podloop++){ if(pod_in==pods[podloop].number){ pods[podloop] = object_out(pods[podloop]); }; };
        
@@ -1098,13 +1337,20 @@ int main(int argc, char *argv[]){
       //if laser, do that
       if(laser>0){
        drawlaser=1;
+#ifdef __USE_SDL__
        laserchannel = play_sound_effect(lasersound, laserchannel);
+#endif
        //kill landers
        for(int landerloop = 0; landerloop<landermax; landerloop++){
          if(((abs(player.y-landers[landerloop].y)<=80)||(abs(player.y-landers[landerloop].y)>=540))&&(player.x==landers[landerloop].x)&&((player.face==0&&(landers[landerloop].y<player.y))||(player.face==1&&(landers[landerloop].y>player.y)))){
            const game_object power_obj = landers[landerloop];
+#ifdef __USE_SDL__
            determine_powerup(powerups, power_obj, 800, pupcreatesound, pupcreatechannel);
            drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop], boomsound, boomchannel);
+#else
+           determine_powerup(powerups, power_obj, 800);
+           drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop]);
+#endif
            landers[landerloop] = object_out(landers[landerloop]);
            score = score + 15;
          };
@@ -1113,8 +1359,13 @@ int main(int argc, char *argv[]){
        for(int crazyloop = 0; crazyloop<landermax; crazyloop++){
          if(((abs(player.y-crazies[crazyloop].y)<=80)||(abs(player.y-crazies[crazyloop].y)>=540))&&(player.x==crazies[crazyloop].x)&&((player.face==0&&(crazies[crazyloop].y<player.y))||(player.face==1&&(crazies[crazyloop].y>player.y)))){
            const game_object power_obj = crazies[crazyloop];
+#ifdef __USE_SDL__
            determine_powerup(powerups, power_obj, 800, pupcreatesound, pupcreatechannel);
            drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop], boomsound, boomchannel);
+#else
+           determine_powerup(powerups, power_obj, 800);
+           drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop]);
+#endif
            crazies[crazyloop] = object_out(crazies[crazyloop]);
            score = score + 15;
          };
@@ -1123,8 +1374,13 @@ int main(int argc, char *argv[]){
        for(int crawlerloop = 0; crawlerloop<crawlermax; crawlerloop++){
          if(((abs(player.y-crawlers[crawlerloop].y)<=80)||(abs(player.y-crawlers[crawlerloop].y)>=540))&&(player.x==crawlers[crawlerloop].x)&&((player.face==0&&(crawlers[crawlerloop].y<player.y))||(player.face==1&&(crawlers[crawlerloop].y>player.y)))){
            const game_object power_obj = crawlers[crawlerloop];
+#ifdef __USE_SDL__
            determine_powerup(powerups, power_obj, 800, pupcreatesound, pupcreatechannel);
            drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop], boomsound, boomchannel);
+#else
+           determine_powerup(powerups, power_obj, 800);
+           drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop]);
+#endif
            crawlers[crawlerloop] = object_out(crawlers[crawlerloop]);
            score = score + 15;
          };
@@ -1136,8 +1392,13 @@ int main(int argc, char *argv[]){
              bosses[bossloop].phase = bosses[bossloop].phase - 5;
              if(bosses[bossloop].phase<=0){
                const game_object power_obj = bosses[bossloop];
+#ifdef __USE_SDL__
                determine_powerup(powerups, power_obj, 600, pupcreatesound, pupcreatechannel);
                drawlocation = boom_object(drawlocation, boomstuff, bosses[bossloop], boomsound, boomchannel);
+#else
+               determine_powerup(powerups, power_obj, 600);
+               drawlocation = boom_object(drawlocation, boomstuff, bosses[bossloop]);
+#endif
                bosses[bossloop] = object_out(bosses[bossloop]);
                score = score + 75;
              };
@@ -1147,7 +1408,9 @@ int main(int argc, char *argv[]){
        laser--;
       } else {
         //shot sound
+#ifdef __USE_SDL__
         if(sound==1){shotchannel = play_sound_effect(shotsound, shotchannel);};
+#endif
        //get next inactive bullet, give it player's direction, speed, height, location +speed in direction, active.
        for(int bulletloop = 0; bulletloop<bulletmax; bulletloop++){ 
          if(bullets[bulletloop].active==0){ 
@@ -1202,8 +1465,13 @@ int main(int argc, char *argv[]){
       for(int landerloop = 0; landerloop<landermax; landerloop++){
         if(landers[landerloop].active==1){
          if((abs(player.y-landers[landerloop].y)<=40)||(abs(player.y-landers[landerloop].y)>=580)){
+#ifdef __USE_SDL__
            determine_powerup(powerups, landers[landerloop], 800, pupcreatesound, pupcreatechannel);
            drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop], boomsound, boomchannel);
+#else
+           determine_powerup(powerups, landers[landerloop], 800);
+           drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop]);
+#endif
            landers[landerloop] = object_out(landers[landerloop]);
            score = score + 5;
          };
@@ -1212,7 +1480,11 @@ int main(int argc, char *argv[]){
       for(int crazyloop = 0; crazyloop<landermax; crazyloop++){
         if(crazies[crazyloop].active==1){
          if((abs(player.y-crazies[crazyloop].y)<=40)||(abs(player.y-crazies[crazyloop].y)>=580)){
+#ifdef __USE_SDL__
            drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop], boomsound, boomchannel);
+#else
+           drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop]);
+#endif
            crazies[crazyloop] = object_out(crazies[crazyloop]);
            score = score + 5;
          };
@@ -1221,7 +1493,11 @@ int main(int argc, char *argv[]){
       for(int crawlerloop = 0; crawlerloop<crawlermax; crawlerloop++){
         if(crawlers[crawlerloop].active==1){
          if((abs(player.y-crawlers[crawlerloop].y)<=40)||(abs(player.y-crawlers[crawlerloop].y)>=580)){
+#ifdef __USE_SDL__
            drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop], boomsound, boomchannel);
+#else
+           drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop]);
+#endif
            crawlers[crawlerloop] = object_out(crawlers[crawlerloop]);
            score = score + 5;
          };
@@ -1232,7 +1508,11 @@ int main(int argc, char *argv[]){
          if((abs(player.y-bosses[bossloop].y)<=40)||(abs(player.y-bosses[bossloop].y)>=580)){
            bosses[bossloop].phase = bosses[bossloop].phase - 5;
            if(bosses[bossloop].phase<=0){
+#ifdef __USE_SDL__
              drawlocation = boom_object(drawlocation, boomstuff, bosses[bossloop], boomsound, boomchannel);
+#else
+             drawlocation = boom_object(drawlocation, boomstuff, bosses[bossloop]);
+#endif
              bosses[bossloop] = object_out(bosses[bossloop]);
              score = score + 50;
            };
@@ -1259,8 +1539,13 @@ int main(int argc, char *argv[]){
          if(landers[landerloop].active==1){
            if(check_collision(bullets[bulletloop], landers[landerloop])==1){
              //kill lander and bullet
+#ifdef __USE_SDL__
              determine_powerup(powerups, landers[landerloop], 800, pupcreatesound, pupcreatechannel);
              drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop], boomsound, boomchannel);
+#else
+             determine_powerup(powerups, landers[landerloop], 800);
+             drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop]);
+#endif
              landers[landerloop] = object_out(landers[landerloop]);
              bullets[bulletloop] = object_out(bullets[bulletloop]);
              //add to score
@@ -1273,8 +1558,13 @@ int main(int argc, char *argv[]){
          if(crazies[crazyloop].active==1){
            if(check_collision(bullets[bulletloop], crazies[crazyloop])==1){
              //kill crazy and bullet
-             determine_powerup(powerups, crazies[crazyloop], 800, pupcreatesound, pupcreatechannel);         
+#ifdef __USE_SDL__
+             determine_powerup(powerups, crazies[crazyloop], 800, pupcreatesound, pupcreatechannel);
              drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop], boomsound, boomchannel);
+#else
+             determine_powerup(powerups, crazies[crazyloop], 800);
+             drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop]);
+#endif
              crazies[crazyloop] = object_out(crazies[crazyloop]);
              bullets[bulletloop] = object_out(bullets[bulletloop]);
              //add to score
@@ -1287,8 +1577,13 @@ int main(int argc, char *argv[]){
          if(crawlers[crawlerloop].active==1){
            if(check_collision(bullets[bulletloop], crawlers[crawlerloop])==1){
              //kill crawler and bullet
+#ifdef __USE_SDL__
              determine_powerup(powerups, crawlers[crawlerloop], 800, pupcreatesound, pupcreatechannel);
              drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop], boomsound, boomchannel);
+#else
+             determine_powerup(powerups, crawlers[crawlerloop], 800);
+             drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop]);
+#endif
              crawlers[crawlerloop] = object_out(crawlers[crawlerloop]);
              bullets[bulletloop] = object_out(bullets[bulletloop]);
              //add to score
@@ -1303,8 +1598,13 @@ int main(int argc, char *argv[]){
              //hurt or kill boss, kill bullet
              bosses[bossloop].phase = bosses[bossloop].phase - 1;
              if(bosses[bossloop].phase<=0){
+#ifdef __USE_SDL__
                determine_powerup(powerups, bosses[bossloop], 600, pupcreatesound, pupcreatechannel);
                drawlocation = boom_object(drawlocation, boomstuff, bosses[bossloop], boomsound, boomchannel);
+#else
+               determine_powerup(powerups, bosses[bossloop], 600);
+               drawlocation = boom_object(drawlocation, boomstuff, bosses[bossloop]);
+#endif
                bosses[bossloop] = object_out(bosses[bossloop]);
                bullets[bulletloop] = object_out(bullets[bulletloop]);
                //add to score
@@ -1325,9 +1625,14 @@ int main(int argc, char *argv[]){
          lives--;
          //add to score
          score = score + 10;
+#ifdef __USE_SDL__
          drawlocation = boom_object(drawlocation, boomstuff, player, boomsound, boomchannel);
+#else
+         drawlocation = boom_object(drawlocation, boomstuff, player);
+#endif
          newgame = life_loss(lives, score);
          player = player_init(player);
+         tempshield();
          drawlocation = player.y-20;
          //kill any carried pods
          if(pod_in>0){
@@ -1344,7 +1649,11 @@ int main(int argc, char *argv[]){
        if(shieldup==1&&super_shield>0){
          for(int shieldloop = 0; shieldloop<12; shieldloop++){
            if(check_collision(landers[landerloop], shields[shieldloop])==1){
+#ifdef __USE_SDL__
              drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop], boomsound, boomchannel);
+#else
+             drawlocation = boom_object(drawlocation, boomstuff, landers[landerloop]);
+#endif
              landers[landerloop] = object_out(landers[landerloop]);
              score = score + 10;
            };
@@ -1362,9 +1671,14 @@ int main(int argc, char *argv[]){
          lives--;
          //add to score
          score = score + 10;
+#ifdef __USE_SDL__
          drawlocation = boom_object(drawlocation, boomstuff, player, boomsound, boomchannel);
+#else
+         drawlocation = boom_object(drawlocation, boomstuff, player);
+#endif
          newgame = life_loss(lives, score);
          player = player_init(player);
+         tempshield();
          drawlocation = player.y-20;
          //kill any carried pods
          if(pod_in>0){
@@ -1381,7 +1695,11 @@ int main(int argc, char *argv[]){
        if(shieldup==1&&super_shield>0){
          for(int shieldloop = 0; shieldloop<12; shieldloop++){
            if(check_collision(crazies[crazyloop], shields[shieldloop])==1){
+#ifdef __USE_SDL__
              drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop], boomsound, boomchannel);
+#else
+             drawlocation = boom_object(drawlocation, boomstuff, crazies[crazyloop]);
+#endif
              crazies[crazyloop] = object_out(crazies[crazyloop]);
              score = score + 10;
            };
@@ -1399,9 +1717,14 @@ int main(int argc, char *argv[]){
          lives--;
          //add to score
          score = score + 10;
+#ifdef __USE_SDL__
          drawlocation = boom_object(drawlocation, boomstuff, player, boomsound, boomchannel);
+#else
+         drawlocation = boom_object(drawlocation, boomstuff, player);
+#endif
          newgame = life_loss(lives, score);
          player = player_init(player);
+         tempshield();
          drawlocation = player.y-20;
          //kill any carried pods
          if(pod_in>0){
@@ -1418,7 +1741,11 @@ int main(int argc, char *argv[]){
        if(shieldup==1&&super_shield>0){
          for(int shieldloop = 0; shieldloop<12; shieldloop++){
            if(check_collision(crawlers[crawlerloop], shields[shieldloop])==1){
+#ifdef __USE_SDL__
              drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop], boomsound, boomchannel);
+#else
+             drawlocation = boom_object(drawlocation, boomstuff, crawlers[crawlerloop]);
+#endif
              crawlers[crawlerloop] = object_out(crawlers[crawlerloop]);
              score = score + 10;
            };
@@ -1433,9 +1760,14 @@ int main(int argc, char *argv[]){
         if(check_collision(player, bosses[bossloop])==1){
          //kill player only
          lives--;
+#ifdef __USE_SDL__
          drawlocation = boom_object(drawlocation, boomstuff, player, boomsound, boomchannel);
+#else
+         drawlocation = boom_object(drawlocation, boomstuff, player);
+#endif
          newgame = life_loss(lives, score);
          player = player_init(player);
+         tempshield();
          drawlocation = player.y-20;
          //kill any carried pods
          if(pod_in>0){
@@ -1457,8 +1789,13 @@ int main(int argc, char *argv[]){
       if(missiles[missileloop].active == 1){
         if(check_collision(landers[missiles[missileloop].chase], missiles[missileloop])==1){
          //kill missile and lander
+#ifdef __USE_SDL__
          drawlocation = boom_object(drawlocation, boomstuff, landers[missiles[missileloop].chase], boomsound, boomchannel);
          drawlocation = boom_object(drawlocation, boomstuff, missiles[missileloop], boomsound, boomchannel);
+#else
+         drawlocation = boom_object(drawlocation, boomstuff, landers[missiles[missileloop].chase]);
+         drawlocation = boom_object(drawlocation, boomstuff, missiles[missileloop]);
+#endif
          landers[missiles[missileloop].chase] = object_out(landers[missiles[missileloop].chase]);
          missiles[missileloop] = object_out(missiles[missileloop]);
         };
@@ -1468,11 +1805,15 @@ int main(int argc, char *argv[]){
     // Lander shots
     for(int landerloop = 0; landerloop<landermax; landerloop++){
       if(landers[landerloop].active==1&&landers[landerloop].chase<=0){
-       if(rand()%1000>500){
+       if(RAND()%1000>500){
          // lander shoot
          for(int landershotloop = 0; landershotloop<landershotmax; landershotloop++){ 
            if(landershot[landershotloop].active==0){
+#ifdef __USE_SDL__
              landershot[landershotloop] = enemy_shoot(landers[landerloop], player, landershot[landershotloop], enshotchannel, enshotsound);
+#else
+             landershot[landershotloop] = enemy_shoot(landers[landerloop], player, landershot[landershotloop]);
+#endif
              break;
            };
          };
@@ -1483,11 +1824,15 @@ int main(int argc, char *argv[]){
     // Crazy shots
     for(int crazyloop = 0; crazyloop<landermax; crazyloop++){
       if(crazies[crazyloop].active==1){
-       if(rand()%1000>200){
+       if(RAND()%1000>200){
          // crazy shoot
          for(int crazyshotloop = 0; crazyshotloop<landershotmax; crazyshotloop++){ 
            if(landershot[crazyshotloop].active==0){ 
+#ifdef __USE_SDL__
              landershot[crazyshotloop] = enemy_shoot(crazies[crazyloop], player, landershot[crazyshotloop], enshotchannel, enshotsound);
+#else
+             landershot[crazyshotloop] = enemy_shoot(crazies[crazyloop], player, landershot[crazyshotloop]);
+#endif
              break;
            };
          };
@@ -1498,11 +1843,15 @@ int main(int argc, char *argv[]){
     // Crawler shots
     for(int crawlerloop = 0; crawlerloop<crawlermax; crawlerloop++){
       if(crawlers[crawlerloop].active==1&&crawlers[crawlerloop].chase<=0){
-       if(rand()%1000>500){
+       if(RAND()%1000>500){
          // crawler shoot
          for(int crawlershotloop = 0; crawlershotloop<landershotmax; crawlershotloop++){ 
            if(landershot[crawlershotloop].active==0){ 
+#ifdef __USE_SDL__
              landershot[crawlershotloop] = enemy_shoot(crawlers[crawlerloop], player, landershot[crawlershotloop], enshotchannel, enshotsound);
+#else
+             landershot[crawlershotloop] = enemy_shoot(crawlers[crawlerloop], player, landershot[crawlershotloop]);
+#endif
              break;
            };
          };
@@ -1513,11 +1862,15 @@ int main(int argc, char *argv[]){
     // boss shots
     for(int bossloop = 0; bossloop<6; bossloop++){
       if(bosses[bossloop].active==1){
-        if(rand()%1000>100){
+        if(RAND()%1000>100){
          // boss shoot
          for(int bossshotloop = 0; bossshotloop<landershotmax; bossshotloop++){ 
            if(landershot[bossshotloop].active==0){ 
+#ifdef __USE_SDL__
              landershot[bossshotloop] = enemy_shoot(bosses[bossloop], player, landershot[bossshotloop], enshotchannel, enshotsound);
+#else
+             landershot[bossshotloop] = enemy_shoot(bosses[bossloop], player, landershot[bossshotloop]);
+#endif
              break;
            };
          };
@@ -1532,9 +1885,14 @@ int main(int argc, char *argv[]){
          //kill landershot and player
          lives--;
          landershot[landershotloop] = object_out(landershot[landershotloop]);  
+#ifdef __USE_SDL__
          drawlocation = boom_object(drawlocation, boomstuff, player, boomsound, boomchannel);
+#else
+         drawlocation = boom_object(drawlocation, boomstuff, player);
+#endif
          newgame = life_loss(lives, score);
          player = player_init(player);
+         tempshield();
          drawlocation = player.y-20;
          //kill any carried pods
          if(pod_in>0){
@@ -1566,7 +1924,12 @@ int main(int argc, char *argv[]){
       //Reset level
       level = 1;
       //Drop shields
+      /* XXX
       shieldup = 0;
+      */
+      tempshield();
+      player.speed = 0;
+      player.vspeed = 0;
       //Zero laser
       laser = 0;
       //Zero triple shot
@@ -1620,8 +1983,8 @@ int main(int argc, char *argv[]){
     //decide to grab a pod
     for(int landerloop = 0; landerloop<landermax; landerloop++){
       if(landers[landerloop].active==1&&landers[landerloop].chase==-1){
-       //if(rand()%10000<=10){
-       if(rand()%1000<=10){
+       //if(RAND()%10000<=10){
+       if(RAND()%1000<=10){
          //choose a pod
          for(int podloop = 0; podloop<podmax; podloop++){
            if(landers[landerloop].chase==-1&&pods[podloop].chase==-1&&pods[podloop].active==1){
@@ -1647,7 +2010,9 @@ int main(int argc, char *argv[]){
               if(missiles[missileloop].chase==-1){
                 missiles[missileloop].chase = landerloop;
                 //play missle launch sound
+#ifdef __USE_SDL__
                 missilechannel = play_sound_effect(missilesound, missilechannel);
+#endif
                 //init missle
                 missiles[missileloop] = missile_init(missiles[missileloop], player, landers[landerloop]);
                 missile--;
@@ -1668,7 +2033,11 @@ int main(int argc, char *argv[]){
         //crazy the landers
         for(int landerloop = 0; landerloop<landermax; landerloop++){ 
           if(landers[landerloop].active==1){
+#ifdef __USE_SDL__
             crazies[landerloop] = encrazify(landers[landerloop], crazies[landerloop], crazifysound, crazifychannel);
+#else
+            crazies[landerloop] = encrazify(landers[landerloop], crazies[landerloop]);
+#endif
             landers[landerloop] = object_out(landers[landerloop]);
           };
         };
@@ -1685,7 +2054,9 @@ int main(int argc, char *argv[]){
         bosscount = 0;
         for(int bossloop = 0; bossloop<6; bossloop++){ bosscount = bosscount + bosses[bossloop].active; };
        if(landercount<=0&&bosscount<=0){
+#ifdef __USE_SDL__
          levelendchannel = play_sound_effect(levelendsound, levelendchannel);
+#endif
          //Tally bonuses
          //Award lives, if any
          if(lives<4){lives++;};
@@ -1708,8 +2079,12 @@ int main(int argc, char *argv[]){
          halfdelay(1);
          //Advance level
          level++;
-         //Drop shields
-         shieldup = 0;
+         //Drop shields XXX
+         //shieldup = 0;
+         tempshield();
+         // Reset speed
+         player.speed = 0;
+         player.vspeed = 0;
          //Reactivate pods if not zombied
          if((level-1) % 4 == 0){
            for(int podloop = 0; podloop<podmax; podloop++){ pods[podloop] = pod_init(pods[podloop]); };
@@ -1771,9 +2146,10 @@ int main(int argc, char *argv[]){
        };
       };  
     };
-    
+    //wrefresh(win);
   }; //end main loop
 
+#ifdef __USE_SDL__
   if(sound==1){
     Mix_FreeChunk(shotsound);
     Mix_FreeChunk(boomsound);
@@ -1795,8 +2171,7 @@ int main(int argc, char *argv[]){
     Mix_CloseAudio();
     SDL_Quit();
   };
+#endif
   
-  endwin();
-  
-  return 0;  
+  exit(EXIT_SUCCESS);
 }
index 21a6481..031afe2 100644 (file)
@@ -1,15 +1,27 @@
 #include <ncurses.h>
 #include <math.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
+#ifdef __USE_SDL__
 #include "SDL2/SDL.h"
 #include "SDL2/SDL_mixer.h"
+#endif
 
 #include "game_object.h"
 #include "draw.h"
+#ifdef __USE_SDL__
 #include "play_sound_effect.h"
+#endif
 
+#include "randmac.h"
+
+#ifdef __USE_SDL__
 game_object encrazify(game_object lander, game_object crazy, Mix_Chunk *sound, int channel){
   play_sound_effect(sound, channel);
+#else
+game_object encrazify(game_object lander, game_object crazy){
+#endif
   crazy.active=1;
   crazy.x = lander.x;
   crazy.y = lander.y;  
@@ -22,20 +34,26 @@ game_object encrazify(game_object lander, game_object crazy, Mix_Chunk *sound, i
   return crazy;
 }
 
+#ifdef __USE_SDL__
 int boom_object(int drawlocation, game_object boomstuff, game_object object, Mix_Chunk *sound, int channel){
+#else
+int boom_object(int drawlocation, game_object boomstuff, game_object object){
+#endif
 
   int deathcycle=1;
   int loop=1;
   boomstuff.active=1;
+#ifdef __USE_SDL__
   play_sound_effect(sound, channel);
+#endif
   while(deathcycle<=7){
     for(int boomx=object.x-10;boomx<=object.x+10;boomx++){
       for(int boomy=object.y-10;boomy<=object.y+10;boomy++){
        if(sqrt((abs(object.y-boomy)*abs(object.y-boomy))+(abs(object.x-boomx)*abs(object.x-boomx)))<=deathcycle){
-         if(rand()%1000>900){
+         if(RAND()%1000>900){
            boomstuff.x = boomx;
            boomstuff.y = boomy;
-           if(rand()%1000>500){
+           if(RAND()%1000>500){
              boomstuff.face = 0;
            } else {
              boomstuff.face = 1;
index 074856c..7c0e093 100644 (file)
@@ -1,3 +1,8 @@
+#ifdef __USE_SDL__
 game_object encrazify(game_object, game_object, Mix_Chunk*, int);
 int boom_object(int, game_object, game_object, Mix_Chunk*, int);
+#else
+game_object encrazify(game_object, game_object);
+int boom_object(int, game_object, game_object);
+#endif
 int life_loss(int, int);
index 699578f..49872e4 100644 (file)
@@ -3,14 +3,15 @@
 #include "game_object.h"
 #include "gravitize.h"
 #include "object_out.h"
+#include "randmac.h"
 
 game_object change_elevation(game_object object){
 
-  if(rand()%100<=5){  
+  if(RAND()%100<=5){  
 
     int adjust = 0;
 
-    if(rand()%100<=50){
+    if(RAND()%100<=50){
       adjust++;
     } else {
       adjust--;
@@ -250,11 +251,6 @@ game_object process_motion(game_object object, game_object player){
 }
 
 game_object process_direction(game_object object, int input){
-  if(input==65){input=8;};
-  if(input==67){input=6;};
-  if(input==68){input=4;};
-  if(input==66){input=2;};
-  if(input==69){input=5;};
   if(input==object.direction){
     object.speed++;
   } else {
@@ -281,7 +277,7 @@ game_object process_direction(game_object object, int input){
   
   if(input==4||input==1||input==7){object.face=0;};
   if(input==6||input==3||input==9){object.face=1;};
-  if(object.speed>4){object.speed=4;};
+  if(object.speed>5){object.speed=5;};
   return object;
 
 }
index ebf85e9..0208322 100644 (file)
@@ -1,7 +1,9 @@
+#ifdef __USE_SDL__
 #include "SDL2/SDL.h"
 #include "SDL2/SDL_mixer.h"
 
 int play_sound_effect(Mix_Chunk *chunk, int channel){
   channel = Mix_PlayChannel(-1, chunk, 0);
   return channel;
-};
\ No newline at end of file
+};
+#endif
index 203e9a2..7edbedc 100644 (file)
@@ -1 +1,3 @@
+#ifdef __USE_SDL__
 int play_sound_effect(Mix_Chunk*, int);
+#endif
index c6b6331..5ea3145 100644 (file)
@@ -1,24 +1,30 @@
 #include <cstdlib>
 #include <string.h>
+#ifdef __USE_SDL__
 #include "SDL2/SDL.h"
 #include "SDL2/SDL_mixer.h"
+#endif
 
 #include "game_object.h"
+#ifdef __USE_SDL__
 #include "play_sound_effect.h"
+#endif
+
+#include "randmac.h"
 
 game_object powerup_init(game_object powerup, game_object object){
   //Call immediately before an object_out
   powerup.active = 1;
   powerup.x = object.x;
   powerup.y = object.y;
-  if(rand()%1000>=500){
+  if(RAND()%1000>=500){
       powerup.direction = 4;
     } else {
       powerup.direction = 6;
     };
   powerup.speed = 1;
   
-  int fodder = rand()%1500;
+  int fodder = RAND()%1500;
 
   if(fodder>=1200){
     strncpy(powerup.line0, "M", 2);
@@ -45,11 +51,17 @@ game_object powerup_init(game_object powerup, game_object object){
   return powerup;
 };
 
+#ifdef __USE_SDL__
 void determine_powerup(game_object powerups[], const game_object& object, int odds, Mix_Chunk *sound, int channel){
-  if(rand()%1000>odds){
+#else
+void determine_powerup(game_object powerups[], const game_object& object, int odds){
+#endif
+  if(RAND()%1000>odds){
     for(int puploop = 0; puploop<4; puploop++){
       if(powerups[puploop].active==0){
+#ifdef __USE_SDL__
         play_sound_effect(sound, channel);
+#endif
         powerups[puploop] = powerup_init(powerups[puploop], object);
        break;
       };
index 7c79584..9f1fe3b 100644 (file)
@@ -1,2 +1,6 @@
 game_object powerup_init(game_object, game_object);
+#ifdef __USE_SDL__
 void determine_powerup(game_object[], const game_object&, int, Mix_Chunk*, int);
+#else
+void determine_powerup(game_object[], const game_object&, int);
+#endif
index b7c8913..8401255 100644 (file)
@@ -20,7 +20,7 @@ void radar_plot(game_object object, int drawlocation){
       line = 3;
     } else if(object.x>=16&&object.x<=18){
       line = 4;
-    } else {line = 0;};
+    } else {line = 1;};
     
     //set longitude based on location
     div_t quotrem;
diff --git a/src/randmac.h b/src/randmac.h
new file mode 100644 (file)
index 0000000..dca9337
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __RANDMAC_H__
+#define __RANDMAC_H__
+
+
+#include <stdlib.h>
+
+
+#define SRAND  srandom
+#define RAND   random
+
+
+#endif