Review Board 1.7.16


Mothership cmenuselect easteregg addition

Review Request #1555 - Created Nov. 1, 2011 and submitted

Jonathan Rose
menuselect
ASTERISK-18801
Reviewers
asterisk-dev
jrose
Menuselect
Adds a mothership bonus target to cmenuselect.  This target appears intermittently after killing a number of aliens, and will award bonus if shot.

Submitted by proxy for John Gould
Made sure motherships could be shot, made sure it didn't make the game unwinnable or win too soon.

Diff revision 1 (Latest)

  1. /trunk/menuselect_curses.c: Loading...
/trunk/menuselect_curses.c
Revision 953 New Change
1
/*
1
/*
2
 * Asterisk -- An open source telephony toolkit.
2
 * Asterisk -- An open source telephony toolkit.
3
 *
3
 *
4
 * Copyright (C) 2005 - 2006, Russell Bryant
4
 * Copyright (C) 2005 - 2006, Russell Bryant
5
 *
5
 *
6
 * Russell Bryant <russell@digium.com>
6
 * Russell Bryant <russell@digium.com>
7
 *
7
 *
8
 * See http://www.asterisk.org for more information about
8
 * See http://www.asterisk.org for more information about
9
 * the Asterisk project. Please do not directly contact
9
 * the Asterisk project. Please do not directly contact
10
 * any of the maintainers of this project for assistance;
10
 * any of the maintainers of this project for assistance;
11
 * the project provides a web site, mailing lists and IRC
11
 * the project provides a web site, mailing lists and IRC
12
 * channels for your use.
12
 * channels for your use.
13
 *
13
 *
14
 * This program is free software, distributed under the terms of
14
 * This program is free software, distributed under the terms of
15
 * the GNU General Public License Version 2. See the LICENSE file
15
 * the GNU General Public License Version 2. See the LICENSE file
16
 * at the top of the source tree.
16
 * at the top of the source tree.
17
 */
17
 */
18

    
   
18

   
19
/*
19
/*
20
 * \file
20
 * \file
21
 *
21
 *
22
 * \author Russell Bryant <russell@digium.com>
22
 * \author Russell Bryant <russell@digium.com>
23
 * 
23
 * 
24
 * \brief curses frontend for selection maintenance
24
 * \brief curses frontend for selection maintenance
25
 */
25
 */
26

    
   
26

   
27
#include <stdlib.h>
27
#include <stdlib.h>
28
#include <stdio.h>
28
#include <stdio.h>
29
#include <sys/types.h>
29
#include <sys/types.h>
30
#include <unistd.h>
30
#include <unistd.h>
31
#include <string.h>
31
#include <string.h>
32
#include <signal.h>
32
#include <signal.h>
33
#include <time.h>
33
#include <time.h>
34
#include <curses.h>
34
#include <curses.h>
35

    
   
35

   
36
#include "menuselect.h"
36
#include "menuselect.h"
37

    
   
37

   
38
#define MENU_HELP	"Press 'h' for help."
38
#define MENU_HELP	"Press 'h' for help."
39

    
   
39

   
40
#define TITLE_HEIGHT	7
40
#define TITLE_HEIGHT	7
41

    
   
41

   
42
#define MIN_X		80
42
#define MIN_X		80
43
#define MIN_Y		27
43
#define MIN_Y		27
44

    
   
44

   
45
#define PAGE_OFFSET	10
45
#define PAGE_OFFSET	10
46

    
   
46

   
47
#define SCROLL_NONE     0
47
#define SCROLL_NONE     0
48
#define SCROLL_DOWN     1
48
#define SCROLL_DOWN     1
49

    
   
49

   
50
#define SCROLL_DOWN_INDICATOR "... More ..."
50
#define SCROLL_DOWN_INDICATOR "... More ..."
51

    
   
51

   
52
#define MIN(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a > __b) ? __b : __a);})
52
#define MIN(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a > __b) ? __b : __a);})
53
#define MAX(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a < __b) ? __b : __a);})
53
#define MAX(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a < __b) ? __b : __a);})
54

    
   
54

   
55
extern int changes_made;
55
extern int changes_made;
56

    
   
56

   
57
/*! Maximum number of characters horizontally */
57
/*! Maximum number of characters horizontally */
58
static int max_x = 0;
58
static int max_x = 0;
59
/*! Maximum number of characters vertically */
59
/*! Maximum number of characters vertically */
60
static int max_y = 0;
60
static int max_y = 0;
61

    
   
61

   
62
static const char * const help_info[] = {
62
static const char * const help_info[] = {
63
	"scroll              => up/down arrows",
63
	"scroll              => up/down arrows",
64
	"toggle selection    => Enter",
64
	"toggle selection    => Enter",
65
	"select              => y",
65
	"select              => y",
66
	"deselect            => n",
66
	"deselect            => n",
67
	"select all          => F8",
67
	"select all          => F8",
68
	"deselect all        => F7",
68
	"deselect all        => F7",
69
	"back                => left arrow",
69
	"back                => left arrow",
70
	"quit                => q",
70
	"quit                => q",
71
	"save and quit       => x",
71
	"save and quit       => x",
72
	"",
72
	"",
73
	"XXX means dependencies have not been met",
73
	"XXX means dependencies have not been met",
74
	"    or a conflict exists",
74
	"    or a conflict exists",
75
	"",
75
	"",
76
	"< > means a dependency has been deselected",
76
	"< > means a dependency has been deselected",
77
	"    and will be automatically re-selected",
77
	"    and will be automatically re-selected",
78
	"    if this item is selected",
78
	"    if this item is selected",
79
	"",
79
	"",
80
	"( ) means a conflicting item has been",
80
	"( ) means a conflicting item has been",
81
	"    selected",
81
	"    selected",
82
};
82
};
83

    
   
83

   
84
/*! \brief Handle a window resize in xterm */
84
/*! \brief Handle a window resize in xterm */
85
static void _winch_handler(int sig)
85
static void _winch_handler(int sig)
86
{
86
{
87
	getmaxyx(stdscr, max_y, max_x);
87
	getmaxyx(stdscr, max_y, max_x);
88

    
   
88

   
89
	if (max_x < MIN_X || max_y < MIN_Y) {
89
	if (max_x < MIN_X || max_y < MIN_Y) {
90
		fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
90
		fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
91
		max_x = MIN_X - 1;
91
		max_x = MIN_X - 1;
92
		max_y = MIN_Y - 1;
92
		max_y = MIN_Y - 1;
93
	}
93
	}
94
}
94
}
95

    
   
95

   
96
static struct sigaction winch_handler = {
96
static struct sigaction winch_handler = {
97
	.sa_handler = _winch_handler,
97
	.sa_handler = _winch_handler,
98
};
98
};
99

    
   
99

   
100
/*! \brief Handle a SIGQUIT */
100
/*! \brief Handle a SIGQUIT */
101
static void _sigint_handler(int sig)
101
static void _sigint_handler(int sig)
102
{
102
{
103

    
   
103

   
104
}
104
}
105

    
   
105

   
106
static struct sigaction sigint_handler = {
106
static struct sigaction sigint_handler = {
107
	.sa_handler = _sigint_handler,
107
	.sa_handler = _sigint_handler,
108
};
108
};
109

    
   
109

   
110
/*! \brief Display help information */
110
/*! \brief Display help information */
111
static void show_help(WINDOW *win)
111
static void show_help(WINDOW *win)
112
{
112
{
113
	int i;
113
	int i;
114

    
   
114

   
115
	wclear(win);
115
	wclear(win);
116
	for (i = 0; i < (sizeof(help_info) / sizeof(help_info[0])); i++) {
116
	for (i = 0; i < (sizeof(help_info) / sizeof(help_info[0])); i++) {
117
		wmove(win, i, max_x / 2 - 15);
117
		wmove(win, i, max_x / 2 - 15);
118
		waddstr(win, (char *) help_info[i]);
118
		waddstr(win, (char *) help_info[i]);
119
	}
119
	}
120
	wrefresh(win);
120
	wrefresh(win);
121
	getch(); /* display the help until the user hits a key */
121
	getch(); /* display the help until the user hits a key */
122
}
122
}
123

    
   
123

   
124
static int really_quit(WINDOW *win)
124
static int really_quit(WINDOW *win)
125
{
125
{
126
	int c;
126
	int c;
127
	wclear(win);
127
	wclear(win);
128
	wmove(win, 2, max_x / 2 - 15);
128
	wmove(win, 2, max_x / 2 - 15);
129
	waddstr(win, "ARE YOU SURE?");
129
	waddstr(win, "ARE YOU SURE?");
130
        wmove(win, 3, max_x / 2 - 12);
130
        wmove(win, 3, max_x / 2 - 12);
131
	waddstr(win, "--- It appears you have made some changes, and");
131
	waddstr(win, "--- It appears you have made some changes, and");
132
	wmove(win, 4, max_x / 2 - 12);
132
	wmove(win, 4, max_x / 2 - 12);
133
	waddstr(win, "you have opted to Quit without saving these changes!");
133
	waddstr(win, "you have opted to Quit without saving these changes!");
134
	wmove(win, 6, max_x / 2 - 12);
134
	wmove(win, 6, max_x / 2 - 12);
135
	waddstr(win, "  Please Enter Y to exit without saving;");
135
	waddstr(win, "  Please Enter Y to exit without saving;");
136
	wmove(win, 7, max_x / 2 - 12);
136
	wmove(win, 7, max_x / 2 - 12);
137
	waddstr(win, "  Enter N to cancel your decision to quit,");
137
	waddstr(win, "  Enter N to cancel your decision to quit,");
138
	wmove(win, 8, max_x / 2 - 12);
138
	wmove(win, 8, max_x / 2 - 12);
139
	waddstr(win, "     and keep working in menuselect, or");
139
	waddstr(win, "     and keep working in menuselect, or");
140
	wmove(win, 9, max_x / 2 - 12);
140
	wmove(win, 9, max_x / 2 - 12);
141
	waddstr(win, "  Enter S to save your changes, and exit");
141
	waddstr(win, "  Enter S to save your changes, and exit");
142
	wmove(win, 10, max_x / 2 - 12);
142
	wmove(win, 10, max_x / 2 - 12);
143
	wrefresh(win);
143
	wrefresh(win);
144
	while ((c=getch())) {
144
	while ((c=getch())) {
145
		if (c == 'Y' || c == 'y') {
145
		if (c == 'Y' || c == 'y') {
146
			c = 'q';
146
			c = 'q';
147
			break;
147
			break;
148
		}
148
		}
149
		if (c == 'S' || c == 's') {
149
		if (c == 'S' || c == 's') {
150
			c = 'S';
150
			c = 'S';
151
			break;
151
			break;
152
		}
152
		}
153
		if (c == 'N' || c == 'n') {
153
		if (c == 'N' || c == 'n') {
154
			c = '%';
154
			c = '%';
155
			break;
155
			break;
156
		}
156
		}
157
	}
157
	}
158
	return c;
158
	return c;
159
}
159
}
160

    
   
160

   
161
static void draw_main_menu(WINDOW *menu, int curopt)
161
static void draw_main_menu(WINDOW *menu, int curopt)
162
{
162
{
163
	struct category *cat;
163
	struct category *cat;
164
	char buf[64];
164
	char buf[64];
165
	int i = 0;
165
	int i = 0;
166

    
   
166

   
167
	wclear(menu);
167
	wclear(menu);
168

    
   
168

   
169
	AST_LIST_TRAVERSE(&categories, cat, list) {
169
	AST_LIST_TRAVERSE(&categories, cat, list) {
170
		wmove(menu, i++, max_x / 2 - 10);
170
		wmove(menu, i++, max_x / 2 - 10);
171
		snprintf(buf, sizeof(buf), " %s", strlen_zero(cat->displayname) ? cat->name : cat->displayname);
171
		snprintf(buf, sizeof(buf), " %s", strlen_zero(cat->displayname) ? cat->name : cat->displayname);
172
		waddstr(menu, buf);
172
		waddstr(menu, buf);
173
	}
173
	}
174

    
   
174

   
175
	wmove(menu, curopt, (max_x / 2) - 15);
175
	wmove(menu, curopt, (max_x / 2) - 15);
176
	waddstr(menu, "--->");
176
	waddstr(menu, "--->");
177
	wmove(menu, 0, 0);
177
	wmove(menu, 0, 0);
178

    
   
178

   
179
	wrefresh(menu);
179
	wrefresh(menu);
180
}
180
}
181

    
   
181

   
182
static void display_mem_info(WINDOW *menu, struct member *mem, int start, int end)
182
static void display_mem_info(WINDOW *menu, struct member *mem, int start, int end)
183
{
183
{
184
	char buf[64];
184
	char buf[64];
185
	struct reference *dep;
185
	struct reference *dep;
186
	struct reference *con;
186
	struct reference *con;
187
	struct reference *use;
187
	struct reference *use;
188

    
   
188

   
189
	wmove(menu, end - start + 2, max_x / 2 - 16);
189
	wmove(menu, end - start + 2, max_x / 2 - 16);
190
	wclrtoeol(menu);
190
	wclrtoeol(menu);
191
	wmove(menu, end - start + 3, max_x / 2 - 16);
191
	wmove(menu, end - start + 3, max_x / 2 - 16);
192
	wclrtoeol(menu);
192
	wclrtoeol(menu);
193
	wmove(menu, end - start + 4, max_x / 2 - 16);
193
	wmove(menu, end - start + 4, max_x / 2 - 16);
194
	wclrtoeol(menu);
194
	wclrtoeol(menu);
195
	wmove(menu, end - start + 5, max_x / 2 - 16);
195
	wmove(menu, end - start + 5, max_x / 2 - 16);
196
	wclrtoeol(menu);
196
	wclrtoeol(menu);
197
	wmove(menu, end - start + 6, max_x / 2 - 16);
197
	wmove(menu, end - start + 6, max_x / 2 - 16);
198
	wclrtoeol(menu);
198
	wclrtoeol(menu);
199

    
   
199

   
200
	if (mem->displayname) {
200
	if (mem->displayname) {
201
		wmove(menu, end - start + 2, max_x / 2 - 16);
201
		wmove(menu, end - start + 2, max_x / 2 - 16);
202
		waddstr(menu, (char *) mem->displayname);
202
		waddstr(menu, (char *) mem->displayname);
203
	}
203
	}
204
	if (!AST_LIST_EMPTY(&mem->deps)) {
204
	if (!AST_LIST_EMPTY(&mem->deps)) {
205
		wmove(menu, end - start + 3, max_x / 2 - 16);
205
		wmove(menu, end - start + 3, max_x / 2 - 16);
206
		strcpy(buf, "Depends on: ");
206
		strcpy(buf, "Depends on: ");
207
		AST_LIST_TRAVERSE(&mem->deps, dep, list) {
207
		AST_LIST_TRAVERSE(&mem->deps, dep, list) {
208
			strncat(buf, dep->displayname, sizeof(buf) - strlen(buf) - 1);
208
			strncat(buf, dep->displayname, sizeof(buf) - strlen(buf) - 1);
209
			strncat(buf, dep->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
209
			strncat(buf, dep->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
210
			if (AST_LIST_NEXT(dep, list))
210
			if (AST_LIST_NEXT(dep, list))
211
				strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
211
				strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
212
		}
212
		}
213
		waddstr(menu, buf);
213
		waddstr(menu, buf);
214
	}
214
	}
215
	if (!AST_LIST_EMPTY(&mem->uses)) {
215
	if (!AST_LIST_EMPTY(&mem->uses)) {
216
		wmove(menu, end - start + 4, max_x / 2 - 16);
216
		wmove(menu, end - start + 4, max_x / 2 - 16);
217
		strcpy(buf, "Can use: ");
217
		strcpy(buf, "Can use: ");
218
		AST_LIST_TRAVERSE(&mem->uses, use, list) {
218
		AST_LIST_TRAVERSE(&mem->uses, use, list) {
219
			strncat(buf, use->displayname, sizeof(buf) - strlen(buf) - 1);
219
			strncat(buf, use->displayname, sizeof(buf) - strlen(buf) - 1);
220
			strncat(buf, use->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
220
			strncat(buf, use->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
221
			if (AST_LIST_NEXT(use, list))
221
			if (AST_LIST_NEXT(use, list))
222
				strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
222
				strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
223
		}
223
		}
224
		waddstr(menu, buf);
224
		waddstr(menu, buf);
225
	}
225
	}
226
	if (!AST_LIST_EMPTY(&mem->conflicts)) {
226
	if (!AST_LIST_EMPTY(&mem->conflicts)) {
227
		wmove(menu, end - start + 5, max_x / 2 - 16);
227
		wmove(menu, end - start + 5, max_x / 2 - 16);
228
		strcpy(buf, "Conflicts with: ");
228
		strcpy(buf, "Conflicts with: ");
229
		AST_LIST_TRAVERSE(&mem->conflicts, con, list) {
229
		AST_LIST_TRAVERSE(&mem->conflicts, con, list) {
230
			strncat(buf, con->displayname, sizeof(buf) - strlen(buf) - 1);
230
			strncat(buf, con->displayname, sizeof(buf) - strlen(buf) - 1);
231
			strncat(buf, con->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
231
			strncat(buf, con->member ? "(M)" : "(E)", sizeof(buf) - strlen(buf) - 1);
232
			if (AST_LIST_NEXT(con, list))
232
			if (AST_LIST_NEXT(con, list))
233
				strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
233
				strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1);
234
		}
234
		}
235
		waddstr(menu, buf);
235
		waddstr(menu, buf);
236
	}
236
	}
237

    
   
237

   
238
	if (!mem->is_separator) { /* Separators lack support levels */
238
	if (!mem->is_separator) { /* Separators lack support levels */
239
		{ /* support level */
239
		{ /* support level */
240
			wmove(menu, end - start + 6, max_x / 2 - 16);
240
			wmove(menu, end - start + 6, max_x / 2 - 16);
241
			snprintf(buf, sizeof(buf), "Support Level: %s", mem->support_level);
241
			snprintf(buf, sizeof(buf), "Support Level: %s", mem->support_level);
242
			if (mem->replacement && *mem->replacement) {
242
			if (mem->replacement && *mem->replacement) {
243
				char buf2[64];
243
				char buf2[64];
244
				snprintf(buf2, sizeof(buf2), ", Replaced by: %s", mem->replacement);
244
				snprintf(buf2, sizeof(buf2), ", Replaced by: %s", mem->replacement);
245
				strncat(buf, buf2, sizeof(buf) - strlen(buf) - 1);
245
				strncat(buf, buf2, sizeof(buf) - strlen(buf) - 1);
246
			}
246
			}
247
			waddstr(menu, buf);
247
			waddstr(menu, buf);
248
		}
248
		}
249
	}
249
	}
250
}
250
}
251

    
   
251

   
252
static void draw_category_menu(WINDOW *menu, struct category *cat, int start, int end, int curopt, int changed, int flags)
252
static void draw_category_menu(WINDOW *menu, struct category *cat, int start, int end, int curopt, int changed, int flags)
253
{
253
{
254
	int i = 0;
254
	int i = 0;
255
	int j = 0;
255
	int j = 0;
256
	struct member *mem;
256
	struct member *mem;
257
	char buf[64];
257
	char buf[64];
258

    
   
258

   
259
	if (!changed) {
259
	if (!changed) {
260
		/* If all we have to do is move the cursor, 
260
		/* If all we have to do is move the cursor, 
261
		 * then don't clear the screen and start over */
261
		 * then don't clear the screen and start over */
262
		AST_LIST_TRAVERSE(&cat->members, mem, list) {
262
		AST_LIST_TRAVERSE(&cat->members, mem, list) {
263
			i++;
263
			i++;
264
			if (curopt + 1 == i) {
264
			if (curopt + 1 == i) {
265
				display_mem_info(menu, mem, start, end);
265
				display_mem_info(menu, mem, start, end);
266
				break;
266
				break;
267
			}
267
			}
268
		}
268
		}
269
		wmove(menu, curopt - start, max_x / 2 - 9);
269
		wmove(menu, curopt - start, max_x / 2 - 9);
270
		wrefresh(menu);
270
		wrefresh(menu);
271
		return;
271
		return;
272
	}
272
	}
273

    
   
273

   
274
	wclear(menu);
274
	wclear(menu);
275

    
   
275

   
276
	i = 0;
276
	i = 0;
277
	AST_LIST_TRAVERSE(&cat->members, mem, list) {
277
	AST_LIST_TRAVERSE(&cat->members, mem, list) {
278
		if (i < start) {
278
		if (i < start) {
279
			i++;
279
			i++;
280
			continue;
280
			continue;
281
		}
281
		}
282
		wmove(menu, j++, max_x / 2 - 10);
282
		wmove(menu, j++, max_x / 2 - 10);
283
		i++;
283
		i++;
284
		if ((mem->depsfailed == HARD_FAILURE) || (mem->conflictsfailed == HARD_FAILURE)) {
284
		if ((mem->depsfailed == HARD_FAILURE) || (mem->conflictsfailed == HARD_FAILURE)) {
285
			snprintf(buf, sizeof(buf), "XXX %s", mem->name);
285
			snprintf(buf, sizeof(buf), "XXX %s", mem->name);
286
		} else if (mem->is_separator) {
286
		} else if (mem->is_separator) {
287
			snprintf(buf, sizeof(buf), "    --- %s ---", mem->name);
287
			snprintf(buf, sizeof(buf), "    --- %s ---", mem->name);
288
		} else if (mem->depsfailed == SOFT_FAILURE) {
288
		} else if (mem->depsfailed == SOFT_FAILURE) {
289
			snprintf(buf, sizeof(buf), "<%s> %s", mem->enabled ? "*" : " ", mem->name);
289
			snprintf(buf, sizeof(buf), "<%s> %s", mem->enabled ? "*" : " ", mem->name);
290
		} else if (mem->conflictsfailed == SOFT_FAILURE) {
290
		} else if (mem->conflictsfailed == SOFT_FAILURE) {
291
			snprintf(buf, sizeof(buf), "(%s) %s", mem->enabled ? "*" : " ", mem->name);
291
			snprintf(buf, sizeof(buf), "(%s) %s", mem->enabled ? "*" : " ", mem->name);
292
		} else {
292
		} else {
293
			snprintf(buf, sizeof(buf), "[%s] %s", mem->enabled ? "*" : " ", mem->name);
293
			snprintf(buf, sizeof(buf), "[%s] %s", mem->enabled ? "*" : " ", mem->name);
294
		}
294
		}
295
		waddstr(menu, buf);
295
		waddstr(menu, buf);
296
		
296
		
297
		if (curopt + 1 == i)
297
		if (curopt + 1 == i)
298
			display_mem_info(menu, mem, start, end);
298
			display_mem_info(menu, mem, start, end);
299

    
   
299

   
300
		if (i == end - (flags & SCROLL_DOWN ? 1 : 0))
300
		if (i == end - (flags & SCROLL_DOWN ? 1 : 0))
301
			break;
301
			break;
302
	}
302
	}
303

    
   
303

   
304
	if (flags & SCROLL_DOWN) {
304
	if (flags & SCROLL_DOWN) {
305
		wmove(menu, j, max_x / 2 - sizeof(SCROLL_DOWN_INDICATOR) / 2);
305
		wmove(menu, j, max_x / 2 - sizeof(SCROLL_DOWN_INDICATOR) / 2);
306
		waddstr(menu, SCROLL_DOWN_INDICATOR);
306
		waddstr(menu, SCROLL_DOWN_INDICATOR);
307
	}
307
	}
308

    
   
308

   
309
	wmove(menu, curopt - start, max_x / 2 - 9);
309
	wmove(menu, curopt - start, max_x / 2 - 9);
310
	wrefresh(menu);
310
	wrefresh(menu);
311
}
311
}
312

    
   
312

   
313
static void play_space(void);
313
static void play_space(void);
314

    
   
314

   
315
static int move_up(int *current, int itemcount, int delta, int *start, int *end, int scroll)
315
static int move_up(int *current, int itemcount, int delta, int *start, int *end, int scroll)
316
{
316
{
317
	if (*current > 0) {
317
	if (*current > 0) {
318
		*current = MAX(*current - delta, 0);
318
		*current = MAX(*current - delta, 0);
319
		if (*current < *start) {
319
		if (*current < *start) {
320
			int diff = *start - MAX(*start - delta, 0);
320
			int diff = *start - MAX(*start - delta, 0);
321
			*start  -= diff;
321
			*start  -= diff;
322
			*end    -= diff;
322
			*end    -= diff;
323
			return 1;
323
			return 1;
324
		}
324
		}
325
	}
325
	}
326
	return 0;
326
	return 0;
327
}
327
}
328

    
   
328

   
329
static int move_down(int *current, int itemcount, int delta, int *start, int *end, int scroll)
329
static int move_down(int *current, int itemcount, int delta, int *start, int *end, int scroll)
330
{
330
{
331
	if (*current < itemcount) {
331
	if (*current < itemcount) {
332
		*current = MIN(*current + delta, itemcount);
332
		*current = MIN(*current + delta, itemcount);
333
		if (*current > *end - 1 - (scroll & SCROLL_DOWN ? 1 : 0)) {
333
		if (*current > *end - 1 - (scroll & SCROLL_DOWN ? 1 : 0)) {
334
			int diff = MIN(*end + delta - 1, itemcount) - *end + 1;
334
			int diff = MIN(*end + delta - 1, itemcount) - *end + 1;
335
			*start  += diff;
335
			*start  += diff;
336
			*end    += diff;
336
			*end    += diff;
337
			return 1;
337
			return 1;
338
		}
338
		}
339
	}
339
	}
340
	return 0;
340
	return 0;
341
}
341
}
342

    
   
342

   
343
static int run_category_menu(WINDOW *menu, int cat_num)
343
static int run_category_menu(WINDOW *menu, int cat_num)
344
{
344
{
345
	struct category *cat;
345
	struct category *cat;
346
	int i = 0;
346
	int i = 0;
347
	int start = 0;
347
	int start = 0;
348
	int end = max_y - TITLE_HEIGHT - 8;
348
	int end = max_y - TITLE_HEIGHT - 8;
349
	int c;
349
	int c;
350
	int curopt = 0;
350
	int curopt = 0;
351
	int maxopt;
351
	int maxopt;
352
	int changed = 1;
352
	int changed = 1;
353
	int scroll = SCROLL_NONE;
353
	int scroll = SCROLL_NONE;
354

    
   
354

   
355
	AST_LIST_TRAVERSE(&categories, cat, list) {
355
	AST_LIST_TRAVERSE(&categories, cat, list) {
356
		if (i++ == cat_num)
356
		if (i++ == cat_num)
357
			break;
357
			break;
358
	}
358
	}
359
	if (!cat)
359
	if (!cat)
360
		return -1;
360
		return -1;
361

    
   
361

   
362
	maxopt = count_members(cat) - 1;
362
	maxopt = count_members(cat) - 1;
363

    
   
363

   
364
	if (maxopt > end) {
364
	if (maxopt > end) {
365
		scroll = SCROLL_DOWN;
365
		scroll = SCROLL_DOWN;
366
	}
366
	}
367

    
   
367

   
368
	draw_category_menu(menu, cat, start, end, curopt, changed, scroll);
368
	draw_category_menu(menu, cat, start, end, curopt, changed, scroll);
369

    
   
369

   
370
	while ((c = getch())) {
370
	while ((c = getch())) {
371
		changed = 0;
371
		changed = 0;
372
		switch (c) {
372
		switch (c) {
373
		case KEY_UP:
373
		case KEY_UP:
374
			changed = move_up(&curopt, maxopt, 1, &start, &end, scroll);
374
			changed = move_up(&curopt, maxopt, 1, &start, &end, scroll);
375
			break;
375
			break;
376
		case KEY_DOWN:
376
		case KEY_DOWN:
377
			changed = move_down(&curopt, maxopt, 1, &start, &end, scroll);
377
			changed = move_down(&curopt, maxopt, 1, &start, &end, scroll);
378
			break;
378
			break;
379
		case KEY_PPAGE:
379
		case KEY_PPAGE:
380
			changed = move_up(
380
			changed = move_up(
381
				&curopt,
381
				&curopt,
382
				maxopt,
382
				maxopt,
383
				MIN(PAGE_OFFSET, max_y - TITLE_HEIGHT - 6 - (scroll & SCROLL_DOWN ? 1 : 0)),
383
				MIN(PAGE_OFFSET, max_y - TITLE_HEIGHT - 6 - (scroll & SCROLL_DOWN ? 1 : 0)),
384
				&start,
384
				&start,
385
				&end,
385
				&end,
386
				scroll);
386
				scroll);
387
			break;
387
			break;
388
		case KEY_NPAGE:
388
		case KEY_NPAGE:
389
			changed = move_down(
389
			changed = move_down(
390
				&curopt,
390
				&curopt,
391
				maxopt,
391
				maxopt,
392
				MIN(PAGE_OFFSET, max_y - TITLE_HEIGHT - 6 - (scroll & SCROLL_DOWN ? 1 : 0)),
392
				MIN(PAGE_OFFSET, max_y - TITLE_HEIGHT - 6 - (scroll & SCROLL_DOWN ? 1 : 0)),
393
				&start,
393
				&start,
394
				&end,
394
				&end,
395
				scroll);
395
				scroll);
396
			break;
396
			break;
397
		case KEY_HOME:
397
		case KEY_HOME:
398
			changed = move_up(&curopt, maxopt, curopt, &start, &end, scroll);
398
			changed = move_up(&curopt, maxopt, curopt, &start, &end, scroll);
399
			break;
399
			break;
400
		case KEY_END:
400
		case KEY_END:
401
			changed = move_down(&curopt, maxopt, maxopt - curopt, &start, &end, scroll);
401
			changed = move_down(&curopt, maxopt, maxopt - curopt, &start, &end, scroll);
402
			break;
402
			break;
403
		case KEY_LEFT:
403
		case KEY_LEFT:
404
		case 27:	/* Esc key */
404
		case 27:	/* Esc key */
405
			return 0;
405
			return 0;
406
		case KEY_RIGHT:
406
		case KEY_RIGHT:
407
		case KEY_ENTER:
407
		case KEY_ENTER:
408
		case '\n':
408
		case '\n':
409
		case ' ':
409
		case ' ':
410
			toggle_enabled_index(cat, curopt);
410
			toggle_enabled_index(cat, curopt);
411
			changed = 1;
411
			changed = 1;
412
			break;
412
			break;
413
		case 'y':
413
		case 'y':
414
		case 'Y':
414
		case 'Y':
415
			set_enabled(cat, curopt);
415
			set_enabled(cat, curopt);
416
			changed = 1;
416
			changed = 1;
417
			break;
417
			break;
418
		case 'n':
418
		case 'n':
419
		case 'N':
419
		case 'N':
420
			clear_enabled(cat, curopt);
420
			clear_enabled(cat, curopt);
421
			changed = 1;
421
			changed = 1;
422
			break;
422
			break;
423
		case 'h':
423
		case 'h':
424
		case 'H':
424
		case 'H':
425
			show_help(menu);
425
			show_help(menu);
426
			changed = 1;
426
			changed = 1;
427
			break;
427
			break;
428
		case KEY_F(7):
428
		case KEY_F(7):
429
			set_all(cat, 0);
429
			set_all(cat, 0);
430
			changed = 1;
430
			changed = 1;
431
			break;
431
			break;
432
		case KEY_F(8):
432
		case KEY_F(8):
433
			set_all(cat, 1);
433
			set_all(cat, 1);
434
			changed = 1;
434
			changed = 1;
435
		default:
435
		default:
436
			break;	
436
			break;	
437
		}
437
		}
438
		if (c == 'x' || c == 'X' || c == 'Q' || c == 'q')
438
		if (c == 'x' || c == 'X' || c == 'Q' || c == 'q')
439
			break;
439
			break;
440

    
   
440

   
441
		if (end <= maxopt) {
441
		if (end <= maxopt) {
442
			scroll |= SCROLL_DOWN;
442
			scroll |= SCROLL_DOWN;
443
		} else {
443
		} else {
444
			scroll &= ~SCROLL_DOWN;
444
			scroll &= ~SCROLL_DOWN;
445
		}
445
		}
446

    
   
446

   
447
		draw_category_menu(menu, cat, start, end, curopt, changed, scroll);
447
		draw_category_menu(menu, cat, start, end, curopt, changed, scroll);
448
	}
448
	}
449

    
   
449

   
450
	wrefresh(menu);
450
	wrefresh(menu);
451

    
   
451

   
452
	return c;
452
	return c;
453
}
453
}
454

    
   
454

   
455
static void draw_title_window(WINDOW *title)
455
static void draw_title_window(WINDOW *title)
456
{
456
{
457
	char titlebar[strlen(menu_name) + 9];
457
	char titlebar[strlen(menu_name) + 9];
458

    
   
458

   
459
	memset(titlebar, '*', sizeof(titlebar) - 1);
459
	memset(titlebar, '*', sizeof(titlebar) - 1);
460
	titlebar[sizeof(titlebar) - 1] = '\0';
460
	titlebar[sizeof(titlebar) - 1] = '\0';
461
	wclear(title);
461
	wclear(title);
462
	wmove(title, 1, (max_x / 2) - (strlen(titlebar) / 2));
462
	wmove(title, 1, (max_x / 2) - (strlen(titlebar) / 2));
463
	waddstr(title, titlebar);
463
	waddstr(title, titlebar);
464
	wmove(title, 2, (max_x / 2) - (strlen(menu_name) / 2));
464
	wmove(title, 2, (max_x / 2) - (strlen(menu_name) / 2));
465
	waddstr(title, (char *) menu_name);
465
	waddstr(title, (char *) menu_name);
466
	wmove(title, 3, (max_x / 2) - (strlen(titlebar) / 2));
466
	wmove(title, 3, (max_x / 2) - (strlen(titlebar) / 2));
467
	waddstr(title, titlebar);
467
	waddstr(title, titlebar);
468
	wmove(title, 5, (max_x / 2) - (strlen(MENU_HELP) / 2));
468
	wmove(title, 5, (max_x / 2) - (strlen(MENU_HELP) / 2));
469
	waddstr(title, MENU_HELP);
469
	waddstr(title, MENU_HELP);
470
	wrefresh(title);
470
	wrefresh(title);
471
}
471
}
472

    
   
472

   
473
int run_menu(void)
473
int run_menu(void)
474
{
474
{
475
	WINDOW *title;
475
	WINDOW *title;
476
	WINDOW *menu;
476
	WINDOW *menu;
477
	int maxopt;
477
	int maxopt;
478
	int curopt = 0;
478
	int curopt = 0;
479
	int c;
479
	int c;
480
	int res = 0;
480
	int res = 0;
481

    
   
481

   
482
	setenv("ESCDELAY", "0", 1); /* So that ESC is processed immediately */
482
	setenv("ESCDELAY", "0", 1); /* So that ESC is processed immediately */
483

    
   
483

   
484
	initscr();
484
	initscr();
485
	getmaxyx(stdscr, max_y, max_x);
485
	getmaxyx(stdscr, max_y, max_x);
486
	sigaction(SIGWINCH, &winch_handler, NULL); /* handle window resizing in xterm */
486
	sigaction(SIGWINCH, &winch_handler, NULL); /* handle window resizing in xterm */
487
	sigaction(SIGINT, &sigint_handler, NULL); /* handle window resizing in xterm */
487
	sigaction(SIGINT, &sigint_handler, NULL); /* handle window resizing in xterm */
488

    
   
488

   
489
	if (max_x < MIN_X || max_y < MIN_Y) {
489
	if (max_x < MIN_X || max_y < MIN_Y) {
490
		fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
490
		fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
491
		endwin();
491
		endwin();
492
		return -1;
492
		return -1;
493
	}
493
	}
494

    
   
494

   
495
	cbreak(); /* don't buffer input until the enter key is pressed */
495
	cbreak(); /* don't buffer input until the enter key is pressed */
496
	noecho(); /* don't echo user input to the screen */
496
	noecho(); /* don't echo user input to the screen */
497
	keypad(stdscr, TRUE); /* allow the use of arrow keys */
497
	keypad(stdscr, TRUE); /* allow the use of arrow keys */
498
	clear();
498
	clear();
499
	refresh();
499
	refresh();
500

    
   
500

   
501
	maxopt = count_categories() - 1;
501
	maxopt = count_categories() - 1;
502
	
502
	
503
	/* We have two windows - the title window at the top, and the menu window gets the rest */
503
	/* We have two windows - the title window at the top, and the menu window gets the rest */
504
	title = newwin(TITLE_HEIGHT, max_x, 0, 0);
504
	title = newwin(TITLE_HEIGHT, max_x, 0, 0);
505
	menu = newwin(max_y - TITLE_HEIGHT, max_x, TITLE_HEIGHT, 0);
505
	menu = newwin(max_y - TITLE_HEIGHT, max_x, TITLE_HEIGHT, 0);
506
	draw_title_window(title);	
506
	draw_title_window(title);	
507
	draw_main_menu(menu, curopt);
507
	draw_main_menu(menu, curopt);
508
	
508
	
509
	while ((c = getch())) {
509
	while ((c = getch())) {
510
		switch (c) {
510
		switch (c) {
511
		case KEY_UP:
511
		case KEY_UP:
512
			if (curopt > 0)
512
			if (curopt > 0)
513
				curopt--;
513
				curopt--;
514
			break;
514
			break;
515
		case KEY_DOWN:
515
		case KEY_DOWN:
516
			if (curopt < maxopt)
516
			if (curopt < maxopt)
517
				curopt++;
517
				curopt++;
518
			break;
518
			break;
519
		case KEY_HOME:
519
		case KEY_HOME:
520
			curopt = 0;
520
			curopt = 0;
521
			break;
521
			break;
522
		case KEY_END:
522
		case KEY_END:
523
			curopt = maxopt;
523
			curopt = maxopt;
524
			break;
524
			break;
525
		case KEY_RIGHT:
525
		case KEY_RIGHT:
526
		case KEY_ENTER:
526
		case KEY_ENTER:
527
		case '\n':
527
		case '\n':
528
		case ' ':
528
		case ' ':
529
			c = run_category_menu(menu, curopt);
529
			c = run_category_menu(menu, curopt);
530
			break;
530
			break;
531
		case 'h':
531
		case 'h':
532
		case 'H':
532
		case 'H':
533
			show_help(menu);
533
			show_help(menu);
534
			break;
534
			break;
535
		case 'i':
535
		case 'i':
536
		case 'I':
536
		case 'I':
537
			play_space();
537
			play_space();
538
			draw_title_window(title);
538
			draw_title_window(title);
539
		default:
539
		default:
540
			break;	
540
			break;	
541
		}
541
		}
542
		if (c == 'q' || c == 'Q' || c == 27 || c == 3) {
542
		if (c == 'q' || c == 'Q' || c == 27 || c == 3) {
543
			if (changes_made) {
543
			if (changes_made) {
544
				c = really_quit(menu);
544
				c = really_quit(menu);
545
				if (c == 'q') {
545
				if (c == 'q') {
546
					res = -1;
546
					res = -1;
547
					break;
547
					break;
548
				}
548
				}
549
			} else {
549
			} else {
550
				res = -1;
550
				res = -1;
551
				break;
551
				break;
552
			}
552
			}
553
		}
553
		}
554
		if (c == 'x' || c == 'X' || c == 's' || c == 'S')
554
		if (c == 'x' || c == 'X' || c == 's' || c == 'S')
555
			break;	
555
			break;	
556
		draw_main_menu(menu, curopt);
556
		draw_main_menu(menu, curopt);
557
	}
557
	}
558

    
   
558

   
559
	endwin();
559
	endwin();
560

    
   
560

   
561
	return res;
561
	return res;
562
}
562
}
563

    
   
563

   
564
enum blip_type {
564
enum blip_type {
565
	BLIP_TANK = 0,
565
	BLIP_TANK = 0,
566
	BLIP_SHOT,
566
	BLIP_SHOT,
567
	BLIP_BOMB,
567
	BLIP_BOMB,
568
	BLIP_ALIEN
568
	BLIP_ALIEN,

    
   
569
	BLIP_UFO
569
};
570
};
570

    
   
571

   
571
struct blip {
572
struct blip {
572
	enum blip_type type;
573
	enum blip_type type;
573
	int x;
574
	int x;
574
	int y;
575
	int y;
575
	int ox;
576
	int ox;
576
	int oy;
577
	int oy;
577
	int goingleft;
578
	int goingleft;
578
	AST_LIST_ENTRY(blip) entry;
579
	AST_LIST_ENTRY(blip) entry;
579
};
580
};
580

    
   
581

   
581
static AST_LIST_HEAD_NOLOCK(, blip) blips;
582
static AST_LIST_HEAD_NOLOCK(, blip) blips;
582

    
   
583

   

    
   
584
static int respawn = 0;
583
static int score = 0;
585
static int score = 0;
584
static int num_aliens = 0;
586
static int num_aliens = 0;
585
static int alien_sleeptime = 0;
587
static int alien_sleeptime = 0;

    
   
588
struct blip *ufo = NULL;
586
struct blip *tank = NULL;
589
struct blip *tank = NULL;
587

    
   
590

   
588
/*! Probability of a bomb, out of 100 */
591
/*! Probability of a bomb, out of 100 */
589
#define BOMB_PROB   1
592
#define BOMB_PROB   1
590

    
   
593

   
591
static int init_blips(void)
594
static int init_blips(void)
592
{
595
{
593
	int i, j;
596
	int i, j;
594
	struct blip *cur;
597
	struct blip *cur;
595

    
   
598

   
596
	srandom(time(NULL) + getpid());
599
	srandom(time(NULL) + getpid());
597

    
   
600

   
598
	/* make tank */
601
	/* make tank */
599
	cur = calloc(1, sizeof(struct blip));
602
	cur = calloc(1, sizeof(struct blip));
600
	if (!cur)
603
	if (!cur)
601
		return -1;
604
		return -1;
602
	cur->type = BLIP_TANK;
605
	cur->type = BLIP_TANK;
603
	cur->x = max_x / 2;
606
	cur->x = max_x / 2;
604
	cur->y = max_y - 1;
607
	cur->y = max_y - 1;
605
	AST_LIST_INSERT_HEAD(&blips, cur, entry);
608
	AST_LIST_INSERT_HEAD(&blips, cur, entry);
606
	tank = cur;
609
	tank = cur;
607

    
   
610

   
608
	/* 3 rows of 10 aliens */
611
	/* 3 rows of 10 aliens */
609
	num_aliens = 0;
612
	num_aliens = 0;
610
	for (i = 0; i < 3; i++) {
613
	for (i = 0; i < 3; i++) {
611
		for (j = 0; j < 10; j++) {
614
		for (j = 0; j < 10; j++) {
612
			cur = calloc(1, sizeof(struct blip));
615
			cur = calloc(1, sizeof(struct blip));
613
			if (!cur)
616
			if (!cur)
614
				return -1;
617
				return -1;
615
			cur->type = BLIP_ALIEN;
618
			cur->type = BLIP_ALIEN;
616
			cur->x = (j * 2) + 1;
619
			cur->x = (j * 2) + 1;
617
			cur->y = (i * 2) + 1;
620
			cur->y = (i * 2) + 2;
618
			AST_LIST_INSERT_HEAD(&blips, cur, entry);
621
			AST_LIST_INSERT_HEAD(&blips, cur, entry);
619
			num_aliens++;
622
			num_aliens++;
620
		}
623
		}
621
	}
624
	}
622

    
   
625

   
623
	return 0;
626
	return 0;
624
}
627
}
625

    
   
628

   
626
static inline chtype type2chtype(enum blip_type type)
629
static inline chtype type2chtype(enum blip_type type)
627
{
630
{
628
	switch (type) {
631
	switch (type) {
629
	case BLIP_TANK:
632
	case BLIP_TANK:
630
		return 'A';
633
		return 'A';
631
	case BLIP_ALIEN:
634
	case BLIP_ALIEN:
632
		return 'X';
635
		return 'X';
633
	case BLIP_SHOT:
636
	case BLIP_SHOT:
634
		return '|';
637
		return '|';
635
	case BLIP_BOMB:
638
	case BLIP_BOMB:
636
		return 'o';
639
		return 'o';

    
   
640
	case BLIP_UFO:

    
   
641
		return '@';
637
	default:
642
	default:
638
		break;
643
		break;
639
	}
644
	}
640
	return '?';
645
	return '?';
641
}
646
}
642

    
   
647

   
643
static int repaint_screen(void)
648
static int repaint_screen(void)
644
{
649
{
645
	struct blip *cur;
650
	struct blip *cur;
646

    
   
651

   
647
	wmove(stdscr, 0, 0);
652
	wmove(stdscr, 0, 0);
648
	wprintw(stdscr, "Score: %d", score);
653
	wprintw(stdscr, "Score: %d", score);
649

    
   
654

   
650
	AST_LIST_TRAVERSE(&blips, cur, entry) {
655
	AST_LIST_TRAVERSE(&blips, cur, entry) {
651
		if (cur->x != cur->ox || cur->y != cur->oy) {
656
		if (cur->x != cur->ox || cur->y != cur->oy) {
652
			wmove(stdscr, cur->oy, cur->ox);
657
			wmove(stdscr, cur->oy, cur->ox);
653
			waddch(stdscr, ' ');
658
			waddch(stdscr, ' ');
654
			wmove(stdscr, cur->y, cur->x);
659
			wmove(stdscr, cur->y, cur->x);
655
			waddch(stdscr, type2chtype(cur->type));	
660
			waddch(stdscr, type2chtype(cur->type));	
656
			cur->ox = cur->x;
661
			cur->ox = cur->x;
657
			cur->oy = cur->y;
662
			cur->oy = cur->y;
658
		}
663
		}
659
	}
664
	}
660

    
   
665

   
661
	wmove(stdscr, 0, max_x - 1);
666
	wmove(stdscr, 0, max_x - 1);
662

    
   
667

   
663
	wrefresh(stdscr);
668
	wrefresh(stdscr);
664

    
   
669

   
665
	return 0;
670
	return 0;
666
}
671
}
667

    
   
672

   
668
static int tank_move_left(void)
673
static int tank_move_left(void)
669
{
674
{
670
	if (tank->x > 0)
675
	if (tank->x > 0)
671
		tank->x--;
676
		tank->x--;
672
	
677
	
673
	return 0;
678
	return 0;
674
}
679
}
675

    
   
680

   
676
static int tank_move_right(void)
681
static int tank_move_right(void)
677
{
682
{
678
	if (tank->x < (max_x - 1))
683
	if (tank->x < (max_x - 1))
679
		tank->x++;
684
		tank->x++;
680

    
   
685

   
681
	return 0;
686
	return 0;
682
}
687
}
683

    
   
688

   
684
static int count_shots(void)
689
static int count_shots(void)
685
{
690
{
686
	struct blip *cur;
691
	struct blip *cur;
687
	int count = 0;
692
	int count = 0;
688

    
   
693

   
689
	AST_LIST_TRAVERSE(&blips, cur, entry) {
694
	AST_LIST_TRAVERSE(&blips, cur, entry) {
690
		if (cur->type == BLIP_SHOT)
695
		if (cur->type == BLIP_SHOT)
691
			count++;
696
			count++;
692
	}
697
	}
693

    
   
698

   
694
	return count;
699
	return count;
695
}
700
}
696

    
   
701

   
697
static int tank_shoot(void)
702
static int tank_shoot(void)
698
{
703
{
699
	struct blip *shot;
704
	struct blip *shot;
700

    
   
705

   
701
	if (count_shots() == 3)
706
	if (count_shots() == 3)
702
		return 0;
707
		return 0;
703

    
   
708

   
704
	score--;
709
	score--;
705

    
   
710

   
706
	shot = calloc(1, sizeof(struct blip));
711
	shot = calloc(1, sizeof(struct blip));
707
	if (!shot)
712
	if (!shot)
708
		return -1;
713
		return -1;
709
	shot->type = BLIP_SHOT;
714
	shot->type = BLIP_SHOT;
710
	shot->x = tank->x;
715
	shot->x = tank->x;
711
	shot->y = max_y - 2;
716
	shot->y = max_y - 2;
712
	AST_LIST_INSERT_HEAD(&blips, shot, entry);
717
	AST_LIST_INSERT_HEAD(&blips, shot, entry);
713

    
   
718

   
714
	return 0;
719
	return 0;
715
}
720
}
716

    
   
721

   
717
static int move_aliens(void)
722
static int move_aliens(void)
718
{
723
{
719
	struct blip *cur;
724
	struct blip *cur;
720

    
   
725

   
721
	AST_LIST_TRAVERSE(&blips, cur, entry) {
726
	AST_LIST_TRAVERSE(&blips, cur, entry) {
722
		if (cur->type != BLIP_ALIEN) {
727
		if (cur->type != BLIP_ALIEN) {
723
			/* do nothing if it's not an alien */
728
			/* do nothing if it's not an alien */
724
			continue;
729
			continue;
725
		}
730
		}
726
		if (cur->goingleft && (cur->x == 0)) {
731
		if (cur->goingleft && (cur->x == 0)) {
727
			cur->y++;
732
			cur->y++;
728
			cur->goingleft = 0;
733
			cur->goingleft = 0;
729
		} else if (!cur->goingleft && cur->x == (max_x - 1)) {
734
		} else if (!cur->goingleft && cur->x == (max_x - 1)) {
730
			cur->y++;
735
			cur->y++;
731
			cur->goingleft = 1;
736
			cur->goingleft = 1;
732
		} else if (cur->goingleft) {
737
		} else if (cur->goingleft) {
733
			cur->x--;
738
			cur->x--;
734
		} else {
739
		} else {
735
			cur->x++;
740
			cur->x++;
736
		}
741
		}
737
		/* Alien into the tank == game over */
742
		/* Alien into the tank == game over */
738
		if (cur->x == tank->x && cur->y == tank->y)
743
		if (cur->x == tank->x && cur->y == tank->y)
739
			return 1;
744
			return 1;
740
		if (random() % 100 < BOMB_PROB && cur->y != max_y) {
745
		if (random() % 100 < BOMB_PROB && cur->y != max_y) {
741
			struct blip *bomb = calloc(1, sizeof(struct blip));
746
			struct blip *bomb = calloc(1, sizeof(struct blip));
742
			if (!bomb)
747
			if (!bomb)
743
				continue;
748
				continue;
744
			bomb->type = BLIP_BOMB;
749
			bomb->type = BLIP_BOMB;
745
			bomb->x = cur->x;
750
			bomb->x = cur->x;
746
			bomb->y = cur->y + 1;
751
			bomb->y = cur->y + 1;
747
			AST_LIST_INSERT_HEAD(&blips, bomb, entry);
752
			AST_LIST_INSERT_HEAD(&blips, bomb, entry);
748
		}
753
		}
749
	}
754
	}
750

    
   
755

   
751
	return 0;
756
	return 0;
752
}
757
}
753

    
   
758

   
754
static int move_bombs(void)
759
static int move_bombs(void)
755
{
760
{
756
	struct blip *cur;
761
	struct blip *cur;
757

    
   
762

   
758
	AST_LIST_TRAVERSE(&blips, cur, entry) {
763
	AST_LIST_TRAVERSE(&blips, cur, entry) {
759
		if (cur->type != BLIP_BOMB)
764
		if (cur->type != BLIP_BOMB)
760
			continue;
765
			continue;
761
		cur->y++;
766
		cur->y++;
762
		if (cur->x == tank->x && cur->y == tank->y)
767
		if (cur->x == tank->x && cur->y == tank->y)
763
			return 1;
768
			return 1;
764
	}
769
	}
765

    
   
770

   
766
	return 0;
771
	return 0;
767
}
772
}
768

    
   
773

   
769
static void move_shots(void)
774
static void move_shots(void)
770
{
775
{
771
	struct blip *cur;
776
	struct blip *cur;
772

    
   
777

   
773
	AST_LIST_TRAVERSE(&blips, cur, entry) {
778
	AST_LIST_TRAVERSE(&blips, cur, entry) {
774
		if (cur->type != BLIP_SHOT)
779
		if (cur->type != BLIP_SHOT)
775
			continue;
780
			continue;
776
		cur->y--;
781
		cur->y--;
777
	}
782
	}
778
}
783
}
779

    
   
784

   
780
static int remove_blip(struct blip *blip)
785
static int remove_blip(struct blip *blip)
781
{
786
{
782
	if (!blip)
787
	if (!blip)
783
		return -1;
788
		return -1;
784

    
   
789

   
785
	AST_LIST_REMOVE(&blips, blip, entry);
790
	AST_LIST_REMOVE(&blips, blip, entry);
786

    
   
791

   
787
	if (blip->type == BLIP_ALIEN)
792
	if (blip->type == BLIP_ALIEN)
788
		num_aliens--;
793
		num_aliens--;
789

    
   
794

   
790
	wmove(stdscr, blip->oy, blip->ox);
795
	wmove(stdscr, blip->oy, blip->ox);
791
	waddch(stdscr, ' ');
796
	waddch(stdscr, ' ');
792

    
   
797

   
793
	free(blip);
798
	free(blip);
794

    
   
799

   
795
	return 0;	
800
	return 0;	
796
}
801
}
797

    
   
802

   

    
   
803
static int ufo_action()

    
   
804
{

    
   
805
	struct blip *cur;

    
   
806

   

    
   
807

   

    
   
808
	AST_LIST_TRAVERSE(&blips, cur, entry) {

    
   
809
		if (cur->type != BLIP_UFO) {

    
   
810
			continue;

    
   
811
		}

    
   
812

   

    
   
813
		cur->x--;

    
   
814

   

    
   
815
		if (cur->x < 0) {

    
   
816
			remove_blip(cur);

    
   
817
			respawn += 1;

    
   
818
		}

    
   
819

   

    
   
820
	}

    
   
821

   

    
   
822
	if (respawn == 7) {

    
   
823
		respawn = 0;

    
   
824
		/* make new mothership*/

    
   
825
		cur = calloc(1, sizeof(struct blip));

    
   
826
		if(!cur)

    
   
827
			return -1;

    
   
828
		cur->type = BLIP_UFO;

    
   
829
		cur->x = max_x - 1;

    
   
830
		cur->y = 1;

    
   
831
		AST_LIST_INSERT_HEAD(&blips, cur, entry);

    
   
832
	}

    
   
833

   

    
   
834
	return 0;

    
   
835
}

    
   
836

   

    
   
837

   
798
static void game_over(int win)
838
static void game_over(int win)
799
{
839
{
800
	clear();
840
	clear();
801

    
   
841

   
802
	wmove(stdscr, max_y / 2, max_x / 2 - 10);
842
	wmove(stdscr, max_y / 2, max_x / 2 - 10);
803
	wprintw(stdscr, "Game over!  You %s!", win ? "win" : "lose");
843
	wprintw(stdscr, "Game over!  You %s!", win ? "win" : "lose");
804

    
   
844

   
805
	wmove(stdscr, 0, max_x - 1);
845
	wmove(stdscr, 0, max_x - 1);
806

    
   
846

   
807
	wrefresh(stdscr);
847
	wrefresh(stdscr);
808

    
   
848

   
809
	sleep(1);
849
	sleep(1);
810

    
   
850

   
811
	while (getch() != ' ');
851
	while (getch() != ' ');
812

    
   
852

   
813
	return;
853
	return;
814
}
854
}
815

    
   
855

   
816
static int check_shot(struct blip *shot)
856
static int check_shot(struct blip *shot)
817
{
857
{
818
	struct blip *cur;
858
	struct blip *cur;
819
	
859
	
820
	AST_LIST_TRAVERSE(&blips, cur, entry) {
860
	AST_LIST_TRAVERSE(&blips, cur, entry) {
821
		if (cur->type != BLIP_ALIEN)
861
		if (cur->type != BLIP_ALIEN && cur->type != BLIP_UFO)
822
			continue;
862
			continue;
823
		if (cur->x == shot->x && cur->y == shot->y) {
863
		if (cur->x == shot->x && cur->y == shot->y) {

    
   
864
			if (cur->type == BLIP_UFO) {

    
   
865
				score += 80;

    
   
866
			}
824
			score += 20;
867
			score += 20;
825
			remove_blip(shot);
868
			remove_blip(shot);
826
			remove_blip(cur);
869
			remove_blip(cur);

    
   
870
			respawn += 1;
827
			if (!num_aliens) {
871
			if (!num_aliens) {
828
				if(alien_sleeptime < 101) {
872
				if(alien_sleeptime < 101) {
829
					game_over(1);
873
					game_over(1);
830
					return 1;
874
					return 1;
831
				} else {
875
				} else {
832
					alien_sleeptime = alien_sleeptime - 100;
876
					alien_sleeptime = alien_sleeptime - 100;
833
					return 1;
877
					return 1;
834
				}
878
				}
835
			}
879
			}
836
		}
880
		}
837
	}
881
	}
838

    
   
882

   
839
	return 0;
883
	return 0;
840
}
884
}
841

    
   
885

   
842
static int check_placement(void)
886
static int check_placement(void)
843
{
887
{
844
	struct blip *cur;
888
	struct blip *cur;
845

    
   
889

   
846
	AST_LIST_TRAVERSE_SAFE_BEGIN(&blips, cur, entry) {
890
	AST_LIST_TRAVERSE_SAFE_BEGIN(&blips, cur, entry) {
847
		if (cur->y <= 0 || cur->y >= max_y) {
891
		if (cur->y <= 0 || cur->y >= max_y) {
848
			AST_LIST_REMOVE_CURRENT(&blips, entry);
892
			AST_LIST_REMOVE_CURRENT(&blips, entry);
849
			remove_blip(cur);
893
			remove_blip(cur);
850
		} else if (cur->type == BLIP_SHOT && check_shot(cur))
894
		} else if (cur->type == BLIP_SHOT && check_shot(cur))
851
			return 1;
895
			return 1;
852
	}
896
	}
853
	AST_LIST_TRAVERSE_SAFE_END
897
	AST_LIST_TRAVERSE_SAFE_END
854

    
   
898

   
855
	return 0;
899
	return 0;
856
}
900
}
857

    
   
901

   
858
static void play_space(void)
902
static void play_space(void)
859
{
903
{
860
	int c;
904
	int c;
861
	unsigned int jiffies = 1;
905
	unsigned int jiffies = 1;
862
	int quit = 0;
906
	int quit = 0;
863
	struct blip *blip;
907
	struct blip *blip;
864
	alien_sleeptime = 1000;
908
	alien_sleeptime = 1000;
865
	score = 0;
909
	score = 0;
866

    
   
910

   
867
	while(alien_sleeptime > 100) {
911
	while(alien_sleeptime > 100) {
868

    
   
912

   
869
		jiffies = 1;
913
		jiffies = 1;
870
		clear();
914
		clear();
871
		nodelay(stdscr, TRUE);
915
		nodelay(stdscr, TRUE);
872
		init_blips();
916
		init_blips();
873
		repaint_screen();
917
		repaint_screen();
874

    
   
918

   
875
		for (;;) {
919
		for (;;) {
876
			c = getch();
920
			c = getch();
877
			switch (c) {
921
			switch (c) {
878
			case ' ':
922
			case ' ':
879
				tank_shoot();
923
				tank_shoot();
880
				break;
924
				break;
881
			case KEY_LEFT:
925
			case KEY_LEFT:
882
				tank_move_left();
926
				tank_move_left();
883
				break;
927
				break;
884
			case KEY_RIGHT:
928
			case KEY_RIGHT:
885
				tank_move_right();
929
				tank_move_right();
886
				break;
930
				break;
887
			case 'x':
931
			case 'x':
888
			case 'X':
932
			case 'X':
889
			case 'q':
933
			case 'q':
890
			case 'Q':
934
			case 'Q':
891
				quit = 1;
935
				quit = 1;
892
			default:
936
			default:
893
				/* ignore unknown input */
937
				/* ignore unknown input */
894
				break;
938
				break;
895
			}
939
			}
896
			if (quit) {
940
			if (quit) {
897
				alien_sleeptime = 1;
941
				alien_sleeptime = 1;
898
				break;
942
				break;
899
			}
943
			}
900
			if (!(jiffies % 25)) {
944
			if (!(jiffies % 25)) {
901
				if (move_aliens() || move_bombs()) {
945
				if (move_aliens() || move_bombs() || ufo_action()) {
902
					alien_sleeptime = 1;
946
					alien_sleeptime = 1;
903
					game_over(0);
947
					game_over(0);
904
					break;
948
					break;
905
				}
949
				}
906
				if (check_placement())
950
				if (check_placement())
907
					break;
951
					break;
908
			}
952
			}
909
			if (!(jiffies % 10)) {
953
			if (!(jiffies % 10)) {
910
				move_shots();
954
				move_shots();
911
				if (check_placement())
955
				if (check_placement())
912
					break;
956
					break;
913
			}
957
			}
914
			repaint_screen();
958
			repaint_screen();
915
			jiffies++;
959
			jiffies++;
916
			usleep(alien_sleeptime);
960
			usleep(alien_sleeptime);
917
		}
961
		}
918

    
   
962

   
919
		while ((blip = AST_LIST_REMOVE_HEAD(&blips, entry)))
963
		while ((blip = AST_LIST_REMOVE_HEAD(&blips, entry)))
920
			free(blip);
964
			free(blip);
921
	}
965
	}
922

    
   
966

   
923
	nodelay(stdscr, FALSE);
967
	nodelay(stdscr, FALSE);
924
}
968
}
  1. /trunk/menuselect_curses.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.