Skip to content

Instantly share code, notes, and snippets.

@kouya
Created July 17, 2017 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kouya/0df62394281cb65f69f02e9f3659374d to your computer and use it in GitHub Desktop.
Save kouya/0df62394281cb65f69f02e9f3659374d to your computer and use it in GitHub Desktop.
Snownews' christmas mini-game, stand-alone version
/* Santa Hunta!
* Snownews' christmas mini-game
* Stand-alone version
*
* Compile with:
* gcc -lncurses -lm -o santa_hunta santa_hunta.c
*
* Needs C toolchain and ncurses5 dev headers.
*
* Part of:
* Snownews - A lightweight console RSS newsreader
* $Id: about.c 1080 2005-06-05 09:50:33Z kiza $
*
* Copyright 2003-2004 Oliver Feiler <kiza@kcore.de>
* http://kiza.kcore.de/software/snownews/
*
* about.c
*
* Please read the file README.patching before changing any code in this file!
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <math.h>
/* Santa Hunta */
typedef struct shot {
int x;
int y;
int fired;
} shot;
typedef struct santa {
int x;
int y;
int height;
int length;
int speed;
int anim;
char *gfx;
char *gfx_line2;
char *altgfx;
char *altgfx_line2;
} santa;
typedef struct scoreDisplay {
int score;
int x;
int y;
int rounds;
} scoreDisplay;
void SHDrawGun (int gun_pos) {
move (LINES-3, 0);
clrtoeol();
move (LINES-2, 0);
clrtoeol();
attron (WA_BOLD);
mvaddstr (LINES-3, gun_pos-3, "___/\\___");
mvaddstr (LINES-2, gun_pos-3, "|######|");
attroff (WA_BOLD);
}
void SHDrawStatus (void) {
attron (WA_BOLD);
mvaddstr (LINES-1, 1, "Move: cursor; shoot: space; quit: q");
move (LINES-1, COLS-1);
attroff (WA_BOLD);
}
void SHDrawScore (int score, int level) {
int i, len;
char scorestr[16];
char levelstr[16];
attron (WA_REVERSE);
for (i = 0; i < COLS; i++) {
mvaddch (0, i, ' ');
}
mvaddstr (0, 1, "Santa Hunta!");
snprintf (scorestr, sizeof(scorestr), "Score: %d", score);
len = strlen (scorestr);
mvaddstr (0, COLS-1-len, scorestr);
snprintf (levelstr, sizeof(levelstr), "Level: %d", level);
len = strlen (levelstr);
mvaddstr (0, COLS/2-len/2, levelstr);
attroff (WA_REVERSE);
}
void SHClearScreen (void) {
int i;
for (i = 0; i < LINES; i++) {
move (i, 0);
clrtoeol();
}
}
void SHDrawProjectile (shot shot) {
attron (WA_BOLD);
mvaddstr (shot.y, shot.x, "|");
attroff (WA_BOLD);
}
void SHDrawSanta (santa santa) {
int len;
char *draw_string;
len = COLS - santa.x;
if (santa.anim == 0) {
if (santa.x < 0) {
draw_string = santa.gfx+abs(santa.x);
mvaddnstr (santa.y, 0, draw_string, len);
} else
mvaddnstr (santa.y, santa.x, santa.gfx, len);
if (santa.x < 0) {
draw_string = santa.gfx_line2+abs(santa.x);
mvaddnstr (santa.y+1, 0, draw_string, len);
} else
mvaddnstr (santa.y+1, santa.x, santa.gfx_line2, len);
} else {
if (santa.x < 0) {
draw_string = santa.altgfx+abs(santa.x);
mvaddnstr (santa.y, 0, draw_string, len);
} else
mvaddnstr (santa.y, santa.x, santa.altgfx, len);
if (santa.x < 0) {
draw_string = santa.altgfx_line2+abs(santa.x);
mvaddnstr (santa.y+1, 0, draw_string, len);
} else
mvaddnstr (santa.y+1, santa.x, santa.altgfx_line2, len);
}
attron (COLOR_PAIR(10));
mvaddch (santa.y, santa.x + santa.length - 1, '*');
attroff (COLOR_PAIR(10));
}
void newSanta (santa * santa, int level) {
santa->x = -27;
santa->y = 1+((float)rand() / (float)RAND_MAX * (LINES-7));
santa->speed = level + ((float)rand() / (float)RAND_MAX * 3);
santa->anim = 0;
santa->height = 2;
santa->length = 27;
santa->gfx = "##___ __-+---+/*__-+---+/*";
santa->gfx_line2 = "_|__|_) /\\ /\\ /\\ /\\ "; /* Append 2 spaces! */
santa->altgfx = "##___ __-+---+/*__-+---+/*";
santa->altgfx_line2 = "_|__|_) /| |\\ /| |\\ "; /* Append 1 space! */
}
int SHHit (shot shot, santa santa) {
if ((shot.x >= santa.x) && (shot.x <= santa.x + santa.length) &&
((shot.y == santa.y) || (shot.y == santa.y+1)))
return 1;
else
return 0;
}
int SHAddScore (santa santa) {
return 100 / santa.y * santa.speed;
}
void SHDrawHitScore (scoreDisplay score) {
int rand_color;
rand_color = 10 + ((float)rand() / (float)RAND_MAX * 6);
attron (WA_BOLD);
attron (COLOR_PAIR(rand_color));
mvprintw (score.y, score.x, "%d", score.score);
attroff (COLOR_PAIR(rand_color));
attroff (WA_BOLD);
}
void printFinalScore (int score) {
int i, j, pos, number_count;
char *numbers[10][5] = {
{"_______","| _ |","| | | |","| |_| |","|_____|"}, /* 0 */
{" ____ "," / | ","/_/| | "," | | "," |_| "}, /* 1 */
{"_______","|___ |","| ____|","| |____","|_____|"}, /* 2 */
{"_______","|___ |"," ___ |","___| |","|_____|"}, /* 3 */
{"___ ___","| |_| |","|____ |"," | |"," |_|"}, /* 4 */
{"_______","| ___|","|___ |","____| |","|_____|"}, /* 5 */
{" __ "," / / "," / \\","| O /"," \\___/ "}, /* 6 */
{"_______","|___ |"," | |"," | |"," |_|"}, /* 7 */
{"_______","| _ |","| |_| |","| |_| |","|_____|"}, /* 8 */
{" ___ "," / \\ ","| O |"," \\ / "," \\__\\ "} /* 9 */
};
int y;
int divisor;
int digit;
if (score == 0)
number_count = 1;
else
number_count = log10(score) + 1;
pos = COLS/2 - ((number_count * 8) / 2);
for (i = 0; i < number_count; i++) {
y = 12;
divisor = pow (10, number_count-1-i);
digit = score / divisor;
score -= digit * divisor;
for (j = 0; j < 5; j++) {
mvaddstr (y, pos + (i * 8), numbers[digit][j]);
y++;
}
}
refresh();
}
void SHFinalScore (int score) {
int rand_color;
attron (WA_BOLD);
mvaddstr (9, COLS/2-6, "Final score:");
refresh();
sleep(1);
for (;;) {
if (getch() == 'q')
break;
rand_color = 10 + ((float)rand() / (float)RAND_MAX * 6);
attron (WA_BOLD);
attron (COLOR_PAIR(rand_color));
printFinalScore(score);
attroff (COLOR_PAIR(rand_color));
attroff (WA_BOLD);
move (LINES-1, COLS-1);
refresh();
}
attroff (WA_BOLD);
}
void santaHunta (void) {
int input;
int score = 0;
int last_score;
int gun_pos = COLS/2;
int count = 0;
int level = 1;
struct timeval before;
struct timeval after;
struct timeval delay;
int draw_loop = 0;
long draw_delay = 0;
shot shot;
santa santa;
int targets = 0;
int hitcount = 0;
scoreDisplay scoreDisplay;
shot.fired = 0;
shot.x = 0;
shot.y = 0;
scoreDisplay.rounds = 0;
/* Set ncurses halfdelay mode.
* Max resolution is 1/10sec */
halfdelay (1);
for (;;) {
gettimeofday (&before, NULL);
input = getch();
gettimeofday (&after, NULL);
if (after.tv_sec > before.tv_sec)
after.tv_usec += 1000000;
delay.tv_sec = 0;
delay.tv_usec = abs(100000 - (after.tv_usec - before.tv_usec));
if (!targets) {
newSanta(&santa, level);
targets = 1;
}
/* Pad drawing resolution to 1/10sec */
draw_delay += after.tv_usec - before.tv_usec;
if (draw_delay > 100000) {
draw_delay = 0;
draw_loop++;
SHClearScreen();
if (targets)
SHDrawSanta(santa);
if (santa.anim == 0)
santa.anim = 1;
else
santa.anim = 0;
if (santa.x >= COLS)
targets = 0;
if (shot.fired)
SHDrawProjectile(shot);
if (scoreDisplay.rounds > 0)
SHDrawHitScore(scoreDisplay);
if (SHHit(shot, santa)) {
targets = 0;
hitcount++;
last_score = SHAddScore(santa);
score += last_score;
scoreDisplay.x = shot.x;
scoreDisplay.y = shot.y;
scoreDisplay.score = last_score;
scoreDisplay.rounds = 20;
}
santa.x += santa.speed;
scoreDisplay.rounds--;
shot.y--;
if (shot.y == 0)
shot.fired = 0;
if (hitcount == 10) {
hitcount = 0;
level++;
}
}
count++;
if (input == KEY_RIGHT) {
if (gun_pos < COLS-5)
gun_pos++;
} else if (input == KEY_LEFT) {
if (gun_pos > 3)
gun_pos--;
} else if (input == ' ') {
if (!shot.fired) {
attron (WA_BOLD);
attron (COLOR_PAIR(12));
mvaddstr (LINES-4, gun_pos-2, "\\***/");
attroff (COLOR_PAIR(12));
attroff (WA_BOLD);
shot.x = gun_pos;
shot.y = LINES-4;
shot.fired = 1;
}
} else if (input == 'q') {
SHFinalScore(score);
break;
}
SHDrawGun(gun_pos);
SHDrawScore(score, level);
SHDrawStatus();
refresh();
}
/* Leave halfdelay mode. */
cbreak();
}
void initCurses (void) {
initscr();
keypad (stdscr, TRUE);
cbreak();
noecho();
clear();
curs_set(0);
refresh();
start_color();
use_default_colors();
init_pair (10, 1, -1); /* red */
init_pair (11, 2, -1); /* green */
init_pair (12, 3, -1); /* orange */
init_pair (13, 4, -1); /* blue */
init_pair (14, 5, -1); /* magenta */
init_pair (15, 6, -1); /* cyan */
init_pair (16, 7, -1); /* gray */
/* Default terminal color color pair */
init_pair (63, -1, -1);
}
int main (void) {
initCurses();
santaHunta();
endwin();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment