123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2005 - 2006, Russell Bryant
- *
- * Russell Bryant <russell@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
- /*
- * \file
- *
- * \author Russell Bryant <russell@digium.com>
- *
- * \brief curses frontend for selection maintenance
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <string.h>
- #include <signal.h>
- #include <time.h>
- #include <curses.h>
- #include "menuselect.h"
- #define MENU_HELP "Press 'h' for help."
- #define TITLE_HEIGHT 7
- #define MIN_X 80
- #define MIN_Y 27
- #define PAGE_OFFSET 10
- #define SCROLL_NONE 0
- #define SCROLL_DOWN 1
- #define SCROLL_DOWN_INDICATOR "... More ..."
- #define MIN(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a > __b) ? __b : __a);})
- #define MAX(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a < __b) ? __b : __a);})
- extern int changes_made;
- /*! Maximum number of characters horizontally */
- static int max_x = 0;
- /*! Maximum number of characters vertically */
- static int max_y = 0;
- static const char * const help_info[] = {
- "scroll => up/down arrows",
- "toggle selection => Enter",
- "select => y",
- "deselect => n",
- "select all => F8",
- "deselect all => F7",
- "back => left arrow",
- "quit => q",
- "save and quit => x",
- "",
- "XXX means dependencies have not been met",
- " or a conflict exists",
- "",
- "< > means a dependency has been deselected",
- " and will be automatically re-selected",
- " if this item is selected",
- "",
- "( ) means a conflicting item has been",
- " selected",
- };
- /*! \brief Handle a window resize in xterm */
- static void _winch_handler(int sig)
- {
- getmaxyx(stdscr, max_y, max_x);
- if (max_x < MIN_X || max_y < MIN_Y) {
- fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
- max_x = MIN_X - 1;
- max_y = MIN_Y - 1;
- }
- }
- static struct sigaction winch_handler = {
- .sa_handler = _winch_handler,
- };
- /*! \brief Handle a SIGQUIT */
- static void _sigint_handler(int sig)
- {
- }
- static struct sigaction sigint_handler = {
- .sa_handler = _sigint_handler,
- };
- /*! \brief Display help information */
- static void show_help(WINDOW *win)
- {
- int i;
- wclear(win);
- for (i = 0; i < (sizeof(help_info) / sizeof(help_info[0])); i++) {
- wmove(win, i, max_x / 2 - 15);
- waddstr(win, (char *) help_info[i]);
- }
- wrefresh(win);
- getch(); /* display the help until the user hits a key */
- }
- static int really_quit(WINDOW *win)
- {
- int c;
- wclear(win);
- wmove(win, 2, max_x / 2 - 15);
- waddstr(win, "ARE YOU SURE?");
- wmove(win, 3, max_x / 2 - 12);
- waddstr(win, "--- It appears you have made some changes, and");
- wmove(win, 4, max_x / 2 - 12);
- waddstr(win, "you have opted to Quit without saving these changes!");
- wmove(win, 6, max_x / 2 - 12);
- waddstr(win, " Please Enter Y to exit without saving;");
- wmove(win, 7, max_x / 2 - 12);
- waddstr(win, " Enter N to cancel your decision to quit,");
- wmove(win, 8, max_x / 2 - 12);
- waddstr(win, " and keep working in menuselect, or");
- wmove(win, 9, max_x / 2 - 12);
- waddstr(win, " Enter S to save your changes, and exit");
- wmove(win, 10, max_x / 2 - 12);
- wrefresh(win);
- while ((c=getch())) {
- if (c == 'Y' || c == 'y') {
- c = 'q';
- break;
- }
- if (c == 'S' || c == 's') {
- c = 'S';
- break;
- }
- if (c == 'N' || c == 'n') {
- c = '%';
- break;
- }
- }
- return c;
- }
- static void draw_main_menu(WINDOW *menu, int curopt)
- {
- struct category *cat;
- char buf[64];
- int i = 0;
- wclear(menu);
- AST_LIST_TRAVERSE(&categories, cat, list) {
- wmove(menu, i++, max_x / 2 - 10);
- snprintf(buf, sizeof(buf), " %s", strlen_zero(cat->displayname) ? cat->name : cat->displayname);
- waddstr(menu, buf);
- }
- wmove(menu, curopt, (max_x / 2) - 15);
- waddstr(menu, "--->");
- wmove(menu, 0, 0);
- wrefresh(menu);
- }
- static void display_mem_info(WINDOW *menu, struct member *mem, int start, int end)
- {
- char buf[64];
- struct reference *dep;
- struct reference *con;
- struct reference *use;
- wmove(menu, end - start + 2, max_x / 2 - 16);
- wclrtoeol(menu);
- wmove(menu, end - start + 3, max_x / 2 - 16);
- wclrtoeol(menu);
- wmove(menu, end - start + 4, max_x / 2 - 16);
- wclrtoeol(menu);
- wmove(menu, end - start + 5, max_x / 2 - 16);
- wclrtoeol(menu);
- wmove(menu, end - start + 6, max_x / 2 - 16);
- wclrtoeol(menu);
- if (mem->displayname) {
- wmove(menu, end - start + 2, max_x / 2 - 16);
- waddstr(menu, (char *) mem->displayname);
- }
- if (!AST_LIST_EMPTY(&mem->deps)) {
- wmove(menu, end - start + 3, max_x / 2 - 16);
- strcpy(buf, "Depends on: ");
- AST_LIST_TRAVERSE(&mem->deps, dep, list) {
- strncat(buf, dep->displayname, sizeof(buf) - strlen(buf) - 1);
- strncat(buf, dep->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
- if (AST_LIST_NEXT(dep, list))
- strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
- }
- waddstr(menu, buf);
- }
- if (!AST_LIST_EMPTY(&mem->uses)) {
- wmove(menu, end - start + 4, max_x / 2 - 16);
- strcpy(buf, "Can use: ");
- AST_LIST_TRAVERSE(&mem->uses, use, list) {
- strncat(buf, use->displayname, sizeof(buf) - strlen(buf) - 1);
- strncat(buf, use->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
- if (AST_LIST_NEXT(use, list))
- strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
- }
- waddstr(menu, buf);
- }
- if (!AST_LIST_EMPTY(&mem->conflicts)) {
- wmove(menu, end - start + 5, max_x / 2 - 16);
- strcpy(buf, "Conflicts with: ");
- AST_LIST_TRAVERSE(&mem->conflicts, con, list) {
- strncat(buf, con->displayname, sizeof(buf) - strlen(buf) - 1);
- strncat(buf, con->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
- if (AST_LIST_NEXT(con, list))
- strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
- }
- waddstr(menu, buf);
- }
- if (!mem->is_separator) { /* Separators lack support levels */
- { /* support level */
- wmove(menu, end - start + 6, max_x / 2 - 16);
- snprintf(buf, sizeof(buf), "Support Level: %s", mem->support_level);
- if (mem->replacement && *mem->replacement) {
- char buf2[64];
- snprintf(buf2, sizeof(buf2), ", Replaced by: %s", mem->replacement);
- strncat(buf, buf2, sizeof(buf) - strlen(buf) - 1);
- }
- waddstr(menu, buf);
- }
- }
- }
- static void draw_category_menu(WINDOW *menu, struct category *cat, int start, int end, int curopt, int changed, int flags)
- {
- int i = 0;
- int j = 0;
- struct member *mem;
- char buf[64];
- if (!changed) {
- /* If all we have to do is move the cursor,
- * then don't clear the screen and start over */
- AST_LIST_TRAVERSE(&cat->members, mem, list) {
- i++;
- if (curopt + 1 == i) {
- display_mem_info(menu, mem, start, end);
- break;
- }
- }
- wmove(menu, curopt - start, max_x / 2 - 9);
- wrefresh(menu);
- return;
- }
- wclear(menu);
- i = 0;
- AST_LIST_TRAVERSE(&cat->members, mem, list) {
- if (i < start) {
- i++;
- continue;
- }
- wmove(menu, j++, max_x / 2 - 10);
- i++;
- if ((mem->depsfailed == HARD_FAILURE) || (mem->conflictsfailed == HARD_FAILURE)) {
- snprintf(buf, sizeof(buf), "XXX %s", mem->name);
- } else if (mem->is_separator) {
- snprintf(buf, sizeof(buf), " --- %s ---", mem->name);
- } else if (mem->depsfailed == SOFT_FAILURE) {
- snprintf(buf, sizeof(buf), "<%s> %s", mem->enabled ? "*" : " ", mem->name);
- } else if (mem->conflictsfailed == SOFT_FAILURE) {
- snprintf(buf, sizeof(buf), "(%s) %s", mem->enabled ? "*" : " ", mem->name);
- } else {
- snprintf(buf, sizeof(buf), "[%s] %s", mem->enabled ? "*" : " ", mem->name);
- }
- waddstr(menu, buf);
-
- if (curopt + 1 == i)
- display_mem_info(menu, mem, start, end);
- if (i == end - (flags & SCROLL_DOWN ? 1 : 0))
- break;
- }
- if (flags & SCROLL_DOWN) {
- wmove(menu, j, max_x / 2 - sizeof(SCROLL_DOWN_INDICATOR) / 2);
- waddstr(menu, SCROLL_DOWN_INDICATOR);
- }
- wmove(menu, curopt - start, max_x / 2 - 9);
- wrefresh(menu);
- }
- static void play_space(void);
- static int move_up(int *current, int itemcount, int delta, int *start, int *end, int scroll)
- {
- if (*current > 0) {
- *current = MAX(*current - delta, 0);
- if (*current < *start) {
- int diff = *start - MAX(*start - delta, 0);
- *start -= diff;
- *end -= diff;
- return 1;
- }
- }
- return 0;
- }
- static int move_down(int *current, int itemcount, int delta, int *start, int *end, int scroll)
- {
- if (*current < itemcount) {
- *current = MIN(*current + delta, itemcount);
- if (*current > *end - 1 - (scroll & SCROLL_DOWN ? 1 : 0)) {
- int diff = MIN(*end + delta - 1, itemcount) - *end + 1;
- *start += diff;
- *end += diff;
- return 1;
- }
- }
- return 0;
- }
- static int run_category_menu(WINDOW *menu, int cat_num)
- {
- struct category *cat;
- int i = 0;
- int start = 0;
- int end = max_y - TITLE_HEIGHT - 8;
- int c;
- int curopt = 0;
- int maxopt;
- int changed = 1;
- int scroll = SCROLL_NONE;
- AST_LIST_TRAVERSE(&categories, cat, list) {
- if (i++ == cat_num)
- break;
- }
- if (!cat)
- return -1;
- maxopt = count_members(cat) - 1;
- if (maxopt > end) {
- scroll = SCROLL_DOWN;
- }
- draw_category_menu(menu, cat, start, end, curopt, changed, scroll);
- while ((c = getch())) {
- changed = 0;
- switch (c) {
- case KEY_UP:
- changed = move_up(&curopt, maxopt, 1, &start, &end, scroll);
- break;
- case KEY_DOWN:
- changed = move_down(&curopt, maxopt, 1, &start, &end, scroll);
- break;
- case KEY_PPAGE:
- changed = move_up(
- &curopt,
- maxopt,
- MIN(PAGE_OFFSET, max_y - TITLE_HEIGHT - 6 - (scroll & SCROLL_DOWN ? 1 : 0)),
- &start,
- &end,
- scroll);
- break;
- case KEY_NPAGE:
- changed = move_down(
- &curopt,
- maxopt,
- MIN(PAGE_OFFSET, max_y - TITLE_HEIGHT - 6 - (scroll & SCROLL_DOWN ? 1 : 0)),
- &start,
- &end,
- scroll);
- break;
- case KEY_HOME:
- changed = move_up(&curopt, maxopt, curopt, &start, &end, scroll);
- break;
- case KEY_END:
- changed = move_down(&curopt, maxopt, maxopt - curopt, &start, &end, scroll);
- break;
- case KEY_LEFT:
- case 27: /* Esc key */
- return 0;
- case KEY_RIGHT:
- case KEY_ENTER:
- case '\n':
- case ' ':
- toggle_enabled_index(cat, curopt);
- changed = 1;
- break;
- case 'y':
- case 'Y':
- set_enabled(cat, curopt);
- changed = 1;
- break;
- case 'n':
- case 'N':
- clear_enabled(cat, curopt);
- changed = 1;
- break;
- case 'h':
- case 'H':
- show_help(menu);
- changed = 1;
- break;
- case KEY_F(7):
- set_all(cat, 0);
- changed = 1;
- break;
- case KEY_F(8):
- set_all(cat, 1);
- changed = 1;
- default:
- break;
- }
- if (c == 'x' || c == 'X' || c == 'Q' || c == 'q')
- break;
- if (end <= maxopt) {
- scroll |= SCROLL_DOWN;
- } else {
- scroll &= ~SCROLL_DOWN;
- }
- draw_category_menu(menu, cat, start, end, curopt, changed, scroll);
- }
- wrefresh(menu);
- return c;
- }
- static void draw_title_window(WINDOW *title)
- {
- char titlebar[strlen(menu_name) + 9];
- memset(titlebar, '*', sizeof(titlebar) - 1);
- titlebar[sizeof(titlebar) - 1] = '\0';
- wclear(title);
- wmove(title, 1, (max_x / 2) - (strlen(titlebar) / 2));
- waddstr(title, titlebar);
- wmove(title, 2, (max_x / 2) - (strlen(menu_name) / 2));
- waddstr(title, (char *) menu_name);
- wmove(title, 3, (max_x / 2) - (strlen(titlebar) / 2));
- waddstr(title, titlebar);
- wmove(title, 5, (max_x / 2) - (strlen(MENU_HELP) / 2));
- waddstr(title, MENU_HELP);
- wrefresh(title);
- }
- int run_menu(void)
- {
- WINDOW *title;
- WINDOW *menu;
- int maxopt;
- int curopt = 0;
- int c;
- int res = 0;
- setenv("ESCDELAY", "0", 1); /* So that ESC is processed immediately */
- initscr();
- getmaxyx(stdscr, max_y, max_x);
- sigaction(SIGWINCH, &winch_handler, NULL); /* handle window resizing in xterm */
- sigaction(SIGINT, &sigint_handler, NULL); /* handle window resizing in xterm */
- if (max_x < MIN_X || max_y < MIN_Y) {
- fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
- endwin();
- return -1;
- }
- cbreak(); /* don't buffer input until the enter key is pressed */
- noecho(); /* don't echo user input to the screen */
- keypad(stdscr, TRUE); /* allow the use of arrow keys */
- clear();
- refresh();
- maxopt = count_categories() - 1;
-
- /* We have two windows - the title window at the top, and the menu window gets the rest */
- title = newwin(TITLE_HEIGHT, max_x, 0, 0);
- menu = newwin(max_y - TITLE_HEIGHT, max_x, TITLE_HEIGHT, 0);
- draw_title_window(title);
- draw_main_menu(menu, curopt);
-
- while ((c = getch())) {
- switch (c) {
- case KEY_UP:
- if (curopt > 0)
- curopt--;
- break;
- case KEY_DOWN:
- if (curopt < maxopt)
- curopt++;
- break;
- case KEY_HOME:
- curopt = 0;
- break;
- case KEY_END:
- curopt = maxopt;
- break;
- case KEY_RIGHT:
- case KEY_ENTER:
- case '\n':
- case ' ':
- c = run_category_menu(menu, curopt);
- break;
- case 'h':
- case 'H':
- show_help(menu);
- break;
- case 'i':
- case 'I':
- play_space();
- draw_title_window(title);
- default:
- break;
- }
- if (c == 'q' || c == 'Q' || c == 27 || c == 3) {
- if (changes_made) {
- c = really_quit(menu);
- if (c == 'q') {
- res = -1;
- break;
- }
- } else {
- res = -1;
- break;
- }
- }
- if (c == 'x' || c == 'X' || c == 's' || c == 'S')
- break;
- draw_main_menu(menu, curopt);
- }
- endwin();
- return res;
- }
- enum blip_type {
- BLIP_TANK = 0,
- BLIP_SHOT,
- BLIP_BOMB,
- BLIP_ALIEN,
- BLIP_BARRIER,
- BLIP_UFO
- };
- struct blip {
- enum blip_type type;
- int x;
- int y;
- int ox;
- int oy;
- int goingleft;
- int health;
- AST_LIST_ENTRY(blip) entry;
- };
- static AST_LIST_HEAD_NOLOCK(, blip) blips;
- static int respawn = 0;
- static int score = 0;
- static int num_aliens = 0;
- static int alien_sleeptime = 0;
- struct blip *ufo = NULL;
- struct blip *tank = NULL;
- /*! Probability of a bomb, out of 100 */
- #define BOMB_PROB 1
- static int add_barrier(int x, int y)
- {
- struct blip *cur = NULL;
- cur = calloc(1,sizeof(struct blip));
- if(!cur) {
- return -1;
- }
- cur->type=BLIP_BARRIER;
- cur->x = x;
- cur->y=max_y - y;
- cur->health = 1;
- AST_LIST_INSERT_HEAD(&blips, cur,entry);
- return 0;
- }
- static int init_blips(void)
- {
- int i, j;
- struct blip *cur;
- int offset = 4;
- srandom(time(NULL) + getpid());
- /* make tank */
- cur = calloc(1, sizeof(struct blip));
- if (!cur)
- return -1;
- cur->type = BLIP_TANK;
- cur->x = max_x / 2;
- cur->y = max_y - 1;
- AST_LIST_INSERT_HEAD(&blips, cur, entry);
- tank = cur;
- /* 3 rows of 10 aliens */
- num_aliens = 0;
- for (i = 0; i < 3; i++) {
- for (j = 0; j < 10; j++) {
- cur = calloc(1, sizeof(struct blip));
- if (!cur)
- return -1;
- cur->type = BLIP_ALIEN;
- cur->x = (j * 2) + 1;
- cur->y = (i * 2) + 2;
- AST_LIST_INSERT_HEAD(&blips, cur, entry);
- num_aliens++;
- }
- }
- for(i=0; i < 4; i++) {
- if (i > 0)
- offset += 5 + ((max_x) -28) / 3;
- add_barrier(offset + 1, 6);
- add_barrier(offset + 2, 6);
- add_barrier(offset + 3, 6);
- add_barrier(offset, 5);
- add_barrier(offset + 1, 5);
- add_barrier(offset + 2, 5);
- add_barrier(offset + 3, 5);
- add_barrier(offset + 4, 5);
- add_barrier(offset, 4);
- add_barrier(offset + 1, 4);
- add_barrier(offset + 3, 4);
- add_barrier(offset + 4, 4);
- }
- return 0;
- }
- static inline chtype type2chtype(enum blip_type type)
- {
- switch (type) {
- case BLIP_TANK:
- return 'A';
- case BLIP_ALIEN:
- return 'X';
- case BLIP_SHOT:
- return '|';
- case BLIP_BOMB:
- return 'o';
- case BLIP_BARRIER:
- return '*';
- case BLIP_UFO:
- return '@';
- default:
- break;
- }
- return '?';
- }
- static int repaint_screen(void)
- {
- struct blip *cur;
- wmove(stdscr, 0, 0);
- wprintw(stdscr, "Score: %d", score);
- AST_LIST_TRAVERSE(&blips, cur, entry) {
- if (cur->x != cur->ox || cur->y != cur->oy) {
- wmove(stdscr, cur->oy, cur->ox);
- waddch(stdscr, ' ');
- wmove(stdscr, cur->y, cur->x);
- waddch(stdscr, type2chtype(cur->type));
- cur->ox = cur->x;
- cur->oy = cur->y;
- }
- }
- wmove(stdscr, 0, max_x - 1);
- wrefresh(stdscr);
- return 0;
- }
- static int tank_move_left(void)
- {
- if (tank->x > 0)
- tank->x--;
-
- return 0;
- }
- static int tank_move_right(void)
- {
- if (tank->x < (max_x - 1))
- tank->x++;
- return 0;
- }
- static int count_shots(void)
- {
- struct blip *cur;
- int count = 0;
- AST_LIST_TRAVERSE(&blips, cur, entry) {
- if (cur->type == BLIP_SHOT)
- count++;
- }
- return count;
- }
- static int tank_shoot(void)
- {
- struct blip *shot;
- if (count_shots() == 3)
- return 0;
- score--;
- shot = calloc(1, sizeof(struct blip));
- if (!shot)
- return -1;
- shot->type = BLIP_SHOT;
- shot->x = tank->x;
- shot->y = max_y - 2;
- AST_LIST_INSERT_HEAD(&blips, shot, entry);
- return 0;
- }
- static int remove_blip(struct blip *blip)
- {
- if (!blip) {
- return -1;
- }
- AST_LIST_REMOVE(&blips, blip, entry);
- if (blip->type == BLIP_ALIEN) {
- num_aliens--;
- }
- wmove(stdscr, blip->oy, blip->ox);
- waddch(stdscr, ' ');
- free(blip);
- return 0;
- }
- static int move_aliens(void)
- {
- struct blip *cur;
- struct blip *current_barrier;
- AST_LIST_TRAVERSE(&blips, cur, entry) {
- if (cur->type != BLIP_ALIEN) {
- /* do nothing if it's not an alien */
- continue;
- }
- if (cur->goingleft && (cur->x == 0)) {
- cur->y++;
- cur->goingleft = 0;
- } else if (!cur->goingleft && cur->x == (max_x - 1)) {
- cur->y++;
- cur->goingleft = 1;
- } else if (cur->goingleft) {
- cur->x--;
- } else {
- cur->x++;
- }
- /* Alien into the tank == game over */
- if (cur->x == tank->x && cur->y == tank->y)
- return 1;
- AST_LIST_TRAVERSE(&blips, current_barrier, entry){
- if(current_barrier->type!=BLIP_BARRIER)
- continue;
- if(cur->y == current_barrier->y && cur->x == current_barrier -> x)
- remove_blip(current_barrier);
- }
- if (random() % 100 < BOMB_PROB && cur->y != max_y) {
- struct blip *bomb = calloc(1, sizeof(struct blip));
- if (!bomb)
- continue;
- bomb->type = BLIP_BOMB;
- bomb->x = cur->x;
- bomb->y = cur->y + 1;
- AST_LIST_INSERT_HEAD(&blips, bomb, entry);
- }
- }
- return 0;
- }
- static int move_bombs(void)
- {
- struct blip *cur;
- struct blip *current_barrier;
- AST_LIST_TRAVERSE(&blips, cur, entry) {
- int mark = 0;
- if (cur->type != BLIP_BOMB)
- continue;
- cur->y++;
- if (cur->x == tank->x && cur->y == tank->y) {
- return 1;
- }
- AST_LIST_TRAVERSE(&blips, current_barrier, entry) {
- if (current_barrier->type != BLIP_BARRIER)
- continue;
- if (cur->x == current_barrier->x && cur->y == current_barrier->y) {
- mark = 1;
- current_barrier->health--;
- if (current_barrier->health == 0)
- remove_blip(current_barrier);
- }
- }
- if (mark){
- remove_blip(cur);}
- }
- return 0;
- }
- static void move_shots(void)
- {
- struct blip *cur;
- AST_LIST_TRAVERSE(&blips, cur, entry) {
- if (cur->type != BLIP_SHOT)
- continue;
- cur->y--;
- }
- }
- static int ufo_action()
- {
- struct blip *cur;
- AST_LIST_TRAVERSE(&blips, cur, entry) {
- if (cur->type != BLIP_UFO) {
- continue;
- }
- cur->x--;
- if (cur->x < 0) {
- remove_blip(cur);
- respawn += 1;
- }
- }
- if (respawn == 7) {
- respawn = 0;
- /* make new mothership*/
- cur = calloc(1, sizeof(struct blip));
- if(!cur)
- return -1;
- cur->type = BLIP_UFO;
- cur->x = max_x - 1;
- cur->y = 1;
- AST_LIST_INSERT_HEAD(&blips, cur, entry);
- }
- return 0;
- }
- static void game_over(int win)
- {
- clear();
- wmove(stdscr, max_y / 2, max_x / 2 - 10);
- wprintw(stdscr, "Game over! You %s!", win ? "win" : "lose");
- wmove(stdscr, 0, max_x - 1);
- wrefresh(stdscr);
- sleep(1);
- while (getch() != ' ');
- return;
- }
- static int check_shot(struct blip *shot)
- {
- struct blip *cur;
- AST_LIST_TRAVERSE(&blips, cur, entry) {
- if ((cur->type == BLIP_ALIEN || cur->type == BLIP_UFO) && cur->x == shot->x && cur->y == shot->y){
- if (cur->type == BLIP_UFO) {
- score += 80;
- }
- score += 20;
- remove_blip(cur);
- remove_blip(shot);
- respawn += 1;
- if (!num_aliens) {
- if(alien_sleeptime < 101) {
- game_over(1);
- return 1;
- } else {
- alien_sleeptime = alien_sleeptime - 100;
- return 1;
- }
- }
- break;
- }
- if (cur->type == BLIP_BARRIER) {
- if (shot->x == cur->x && shot->y == cur->y) {
- remove_blip(cur);
- remove_blip(shot);
- break;
- }
- }
- }
- return 0;
- }
- static int check_placement(void)
- {
- struct blip *cur;
- AST_LIST_TRAVERSE_SAFE_BEGIN(&blips, cur, entry) {
- if (cur->y <= 0 || cur->y >= max_y) {
- AST_LIST_REMOVE_CURRENT(&blips, entry);
- remove_blip(cur);
- } else if (cur->type == BLIP_SHOT && check_shot(cur))
- return 1;
- }
- AST_LIST_TRAVERSE_SAFE_END
- return 0;
- }
- static void play_space(void)
- {
- int c;
- unsigned int jiffies = 1;
- int quit = 0;
- struct blip *blip;
- alien_sleeptime = 1000;
- score = 0;
- while(alien_sleeptime > 100) {
- jiffies = 1;
- clear();
- nodelay(stdscr, TRUE);
- init_blips();
- repaint_screen();
- for (;;) {
- c = getch();
- switch (c) {
- case ' ':
- tank_shoot();
- break;
- case KEY_LEFT:
- tank_move_left();
- break;
- case KEY_RIGHT:
- tank_move_right();
- break;
- case 'x':
- case 'X':
- case 'q':
- case 'Q':
- quit = 1;
- default:
- /* ignore unknown input */
- break;
- }
- if (quit) {
- alien_sleeptime = 1;
- break;
- }
- if (!(jiffies % 25)) {
- if (move_aliens() || move_bombs() || ufo_action()) {
- alien_sleeptime = 1;
- game_over(0);
- break;
- }
- if (check_placement())
- break;
- }
- if (!(jiffies % 10)) {
- move_shots();
- if (check_placement())
- break;
- }
- repaint_screen();
- jiffies++;
- usleep(alien_sleeptime);
- }
- while ((blip = AST_LIST_REMOVE_HEAD(&blips, entry)))
- free(blip);
- }
- nodelay(stdscr, FALSE);
- }
|