xref: /original-bsd/games/robots/move.c (revision 32923f9e)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)move.c	5.4 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 # include	"robots.h"
13 # include	<ctype.h>
14 
15 # define	ESC	'\033'
16 
17 /*
18  * get_move:
19  *	Get and execute a move from the player
20  */
21 get_move()
22 {
23 	register int	c;
24 	register int	y, x, lastmove;
25 	static COORD	newpos;
26 
27 	if (Waiting)
28 		return;
29 
30 #ifdef	FANCY
31 	if (Pattern_roll) {
32 		if (Next_move >= Move_list)
33 			lastmove = *Next_move;
34 		else
35 			lastmove = -1;	/* flag for "first time in" */
36 	}
37 #endif
38 	for (;;) {
39 		if (Teleport && must_telep())
40 			goto teleport;
41 		if (Running)
42 			c = Run_ch;
43 		else if (Count != 0)
44 			c = Cnt_move;
45 #ifdef	FANCY
46 		else if (Num_robots > 1 && Stand_still)
47 			c = '>';
48 		else if (Num_robots > 1 && Pattern_roll) {
49 			if (*++Next_move == '\0') {
50 				if (lastmove < 0)
51 					goto over;
52 				Next_move = Move_list;
53 			}
54 			c = *Next_move;
55 			mvaddch(0, 0, c);
56 			if (c == lastmove)
57 				goto over;
58 		}
59 #endif
60 		else {
61 over:
62 			c = getchar();
63 			if (isdigit(c)) {
64 				Count = (c - '0');
65 				while (isdigit(c = getchar()))
66 					Count = Count * 10 + (c - '0');
67 				if (c == ESC)
68 					goto over;
69 				Cnt_move = c;
70 				if (Count)
71 					leaveok(stdscr, TRUE);
72 			}
73 		}
74 
75 		switch (c) {
76 		  case ' ':
77 		  case '.':
78 			if (do_move(0, 0))
79 				goto ret;
80 			break;
81 		  case 'y':
82 			if (do_move(-1, -1))
83 				goto ret;
84 			break;
85 		  case 'k':
86 			if (do_move(-1, 0))
87 				goto ret;
88 			break;
89 		  case 'u':
90 			if (do_move(-1, 1))
91 				goto ret;
92 			break;
93 		  case 'h':
94 			if (do_move(0, -1))
95 				goto ret;
96 			break;
97 		  case 'l':
98 			if (do_move(0, 1))
99 				goto ret;
100 			break;
101 		  case 'b':
102 			if (do_move(1, -1))
103 				goto ret;
104 			break;
105 		  case 'j':
106 			if (do_move(1, 0))
107 				goto ret;
108 			break;
109 		  case 'n':
110 			if (do_move(1, 1))
111 				goto ret;
112 			break;
113 		  case 'Y': case 'U': case 'H': case 'J':
114 		  case 'K': case 'L': case 'B': case 'N':
115 		  case '>':
116 			Running = TRUE;
117 			if (c == '>')
118 				Run_ch = ' ';
119 			else
120 				Run_ch = tolower(c);
121 			leaveok(stdscr, TRUE);
122 			break;
123 		  case 'q':
124 		  case 'Q':
125 			if (query("Really quit?"))
126 				quit();
127 			refresh();
128 			break;
129 		  case 'w':
130 		  case 'W':
131 			Waiting = TRUE;
132 			leaveok(stdscr, TRUE);
133 			flushok(stdscr, FALSE);
134 			goto ret;
135 		  case 't':
136 		  case 'T':
137 teleport:
138 			Running = FALSE;
139 			mvaddch(My_pos.y, My_pos.x, ' ');
140 			My_pos = *rnd_pos();
141 			mvaddch(My_pos.y, My_pos.x, PLAYER);
142 			leaveok(stdscr, FALSE);
143 			refresh();
144 			flush_in();
145 			goto ret;
146 		  case CTRL(L):
147 			wrefresh(curscr);
148 			break;
149 		  case EOF:
150 			break;
151 		  default:
152 			putchar(CTRL(G));
153 			reset_count();
154 			fflush(stdout);
155 			break;
156 		}
157 	}
158 ret:
159 	if (Count > 0)
160 		if (--Count == 0)
161 			leaveok(stdscr, FALSE);
162 }
163 
164 /*
165  * must_telep:
166  *	Must I teleport; i.e., is there anywhere I can move without
167  * being eaten?
168  */
169 must_telep()
170 {
171 	register int	x, y;
172 	static COORD	newpos;
173 
174 #ifdef	FANCY
175 	if (Stand_still && Num_robots > 1 && eaten(&My_pos))
176 		return TRUE;
177 #endif
178 
179 	for (y = -1; y <= 1; y++) {
180 		newpos.y = My_pos.y + y;
181 		if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE)
182 			continue;
183 		for (x = -1; x <= 1; x++) {
184 			newpos.x = My_pos.x + x;
185 			if (newpos.x <= 0 || newpos.x >= X_FIELDSIZE)
186 				continue;
187 			if (Field[newpos.y][newpos.x] > 0)
188 				continue;
189 			if (!eaten(&newpos))
190 				return FALSE;
191 		}
192 	}
193 	return TRUE;
194 }
195 
196 /*
197  * do_move:
198  *	Execute a move
199  */
200 do_move(dy, dx)
201 int	dy, dx;
202 {
203 	static COORD	newpos;
204 
205 	newpos.y = My_pos.y + dy;
206 	newpos.x = My_pos.x + dx;
207 	if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE ||
208 	    newpos.x <= 0 || newpos.x >= X_FIELDSIZE ||
209 	    Field[newpos.y][newpos.x] > 0 || eaten(&newpos)) {
210 		if (Running) {
211 			Running = FALSE;
212 			leaveok(stdscr, FALSE);
213 			move(My_pos.y, My_pos.x);
214 			refresh();
215 		}
216 		else {
217 			putchar(CTRL(G));
218 			reset_count();
219 		}
220 		return FALSE;
221 	}
222 	else if (dy == 0 && dx == 0)
223 		return TRUE;
224 	mvaddch(My_pos.y, My_pos.x, ' ');
225 	My_pos = newpos;
226 	mvaddch(My_pos.y, My_pos.x, PLAYER);
227 	if (!jumping())
228 		refresh();
229 	return TRUE;
230 }
231 
232 /*
233  * eaten:
234  *	Player would get eaten at this place
235  */
236 eaten(pos)
237 register COORD	*pos;
238 {
239 	register int	x, y;
240 
241 	for (y = pos->y - 1; y <= pos->y + 1; y++) {
242 		if (y <= 0 || y >= Y_FIELDSIZE)
243 			continue;
244 		for (x = pos->x - 1; x <= pos->x + 1; x++) {
245 			if (x <= 0 || x >= X_FIELDSIZE)
246 				continue;
247 			if (Field[y][x] == 1)
248 				return TRUE;
249 		}
250 	}
251 	return FALSE;
252 }
253 
254 /*
255  * reset_count:
256  *	Reset the count variables
257  */
258 reset_count()
259 {
260 	Count = 0;
261 	Running = FALSE;
262 	leaveok(stdscr, FALSE);
263 	refresh();
264 }
265 
266 /*
267  * jumping:
268  *	See if we are jumping, i.e., we should not refresh.
269  */
270 jumping()
271 {
272 	return (Jump && (Count || Running || Waiting));
273 }
274