1 /*
2  * actions.c  --  xrobots
3  *
4  * Copyright 1989 Brian Warkentine
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the author's name not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  The author makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
18  * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
19  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * The author's current employer has no connection with this software, as it
24  * was written before being employed at Sun.  The following address is for
25  * contacting the author only and does not imply any responsibility on the
26  * behalf of Sun Microsystems.
27  *
28  * Contact the author at:
29  * 	Brian Warkentine  (brianw@Sun.COM)
30  * 	Sun Microsystems
31  * 	2550 Garcia Avenue
32  * 	Mountain View, Ca 94043-1100
33  *
34  */
35 
36 #include <X11/X.h>
37 #include <X11/Intrinsic.h>
38 #include <X11/StringDefs.h>
39 #include <math.h>
40 #include <stdlib.h>
41 #include "xrobots.h"
42 
43 extern Widget sonic_command;
44 
45 void
sonic_action()46 sonic_action()
47 {
48   static Arg arg = { XtNsensitive, False};
49   if(!game_active) return;
50   XtSetValues(sonic_command,&arg,1);
51   sonic_screwdriver();
52 }
53 
54 void
reset_sonic_button()55 reset_sonic_button()
56 {
57   static Arg arg = { XtNsensitive, True };
58   XtSetValues(sonic_command,&arg,1);
59 }
60 
61 /*ARGSUSED*/
62 XtActionProc
do_nothing_action(w,event,params,num_params)63 do_nothing_action(w,event,params,num_params)
64   Widget w;
65   XEvent *event;
66   String *params;
67   Cardinal *num_params;
68 {
69   /* do nothing */
70   return NULL;
71 }
72 
73 
74 /*----------------------------------------------------------------------*/
75 
76 
77 int
determine_direction(button_x,button_y)78 determine_direction(button_x,button_y)
79   int button_x,button_y;
80 {
81 /*
82  * Given the mouse's x&y position, this routine determines the direction
83  * relative to the player, and returns the result coded into a int.
84  */
85   float slope, invslope;
86   int direction = 0;
87   int coord_x = pos_to_coord(human_x) + CELLSIZE/2,
88       coord_y = pos_to_coord(human_y) + CELLSIZE/2;
89 
90   if( (abs(coord_x - button_x) < (CELLSIZE/2)+2) &&
91       (abs(coord_y - button_y) < (CELLSIZE/2)+2))
92     return(STILL);      /* cursor is directly over the player */
93 
94   if(button_x - coord_x != 0) {
95     slope = fabs((float)(button_y - coord_y) / (float)(button_x - coord_x));
96 
97     if( button_x > coord_x ) {			/* in coordinates 1 or 4 */
98       if( (slope < 2) && (human_x < MAXX) )
99         direction = RIGHT;
100     }
101     else 					/* in coordinates 2 or 3 */
102       if( (slope < 2) && (human_x > -1) )
103         direction = LEFT;
104   }
105 
106   if(button_y - coord_y != 0) {
107     invslope = fabs((float)(button_x - coord_x) / (float)(button_y - coord_y));
108 
109     if( button_y > coord_y ) {			/* in coordinates 1 or 2 */
110       if( (invslope < 2) && (human_y < MAXY) )
111         direction |= DOWN;
112     }
113 
114     else 					/* in coordinates 3 or 4 */
115       if( (invslope < 2) && (human_y > -1) )
116         direction |= UP;
117   }
118   return(direction);
119 }
120 
121 /*----------------------------------------------------------------------*/
122 
123 static int
get_next_position(diff_x,diff_y,mousex,mousey,params,num_params)124 get_next_position(diff_x, diff_y, mousex, mousey, params, num_params)
125   int *diff_x, *diff_y, mousex, mousey, num_params;
126   String *params;
127 {
128   int direction;
129 
130   *diff_x = *diff_y = 0;
131 
132   if(!num_params) {	/* no parameters - the mouse was used pointer */
133 
134     direction = determine_direction(mousex,mousey);
135     if(!direction)  return -1;
136 
137     if(direction & UP)    *diff_y = -1;
138     if(direction & DOWN)  *diff_y = 1;
139     if(direction & LEFT)  *diff_x = -1;
140     if(direction & RIGHT) *diff_x = 1;
141 
142     return 0;
143   }
144 
145   while(num_params--) {
146       /* else pull the direction out of the parameters. */
147 
148     if(!strcmp("right",*(params+num_params)))	*diff_x = 1;
149     if(!strcmp("left", *(params+num_params)))	*diff_x = -1;
150     if(!strcmp("up",   *(params+num_params)))	*diff_y = -1;
151     if(!strcmp("down", *(params+num_params)))	*diff_y = 1;
152   }
153     return 0;
154 }
155 
156 /*----------------------------------------------------------------------*/
157 
158 
159 /*ARGSUSED*/
160 XtActionProc
move_action(w,event,params,num_params)161 move_action(w,event,params,num_params)
162   Widget w;
163   XButtonEvent *event;
164   String *params;
165   Cardinal *num_params;
166 {
167 /*
168  *  Called to move the player's icon.  This action can be called
169  *  when a mouse button is pressed or when a key is pressed.
170  */
171   int diff_x, diff_y;
172   int num_wasted;
173 
174   if(!game_active) return NULL;
175 
176   if(get_next_position(&diff_x, &diff_y, event->x, event->y,
177                         params, *num_params))
178 	return NULL;
179 
180   last_human_x = human_x;
181   last_human_y = human_y;
182 
183   if( can_go(human_x+diff_x,human_y+diff_y) ) {
184     human_x += diff_x;
185     human_y += diff_y;
186     num_wasted = chase(0);
187     show_movement();
188     add_score(num_wasted);
189     if(!num_robots)
190       new_level();
191     else
192       display_possible_moves();
193     auto_teleport();
194     pointer_moved((Widget)0,(caddr_t)0,event);
195   }
196   XFlush(display);
197 }
198 
199 
200 
201 /*ARGSUSED*/
202 XtActionProc
jump_action(w,event,params,num_params)203 jump_action(w,event,params,num_params)
204   Widget w;
205   XButtonEvent *event;
206   String *params;
207   Cardinal *num_params;
208 {
209 /*
210  * don't just move once, move until it can't go any farther.
211  */
212   int diff_x, diff_y;
213   int num_wasted;
214 
215   if(!game_active) return NULL;
216 
217   if(get_next_position(&diff_x, &diff_y, event->x, event->y,
218                         params, *num_params))
219 	return NULL;
220 
221   if(! can_go(human_x+diff_x,human_y+diff_y) )
222 	return NULL;
223 
224   while( can_go(human_x+diff_x,human_y+diff_y) ) {
225     last_human_x = human_x;
226     last_human_y = human_y;
227     human_x += diff_x;
228     human_y += diff_y;
229     num_wasted = chase(0);
230     if(app_data.showjumps)
231       show_movement();
232     add_score(num_wasted);
233     if(!num_robots)
234       break;
235     XFlush(display);
236   }
237   if(!num_robots)
238     new_level();
239   else
240     if(!app_data.showjumps)
241       display_level();
242   display_possible_moves();
243   auto_teleport();
244   pointer_moved((Widget)0,(caddr_t)0,event);
245   XFlush(display);
246 }
247 
248 
249 
250 /*ARGSUSED*/
251 XtActionProc
go_here_action(w,event,params,num_params)252 go_here_action(w,event,params,num_params)
253   Widget w;
254   XButtonEvent *event;
255   String *params;
256   Cardinal *num_params;
257 {
258 /*
259  * This action causes player's icon to try to go to a spot in the
260  * play area.  It stops if a move cannot be made.
261  */
262   int direction;
263   int tmp_human_x, tmp_human_y;
264   int num_wasted;
265 
266   if(!game_active) return NULL;
267 
268   while(direction = determine_direction(event->x,event->y)) {
269     if(direction == STILL) break;
270     tmp_human_x = human_x;
271     tmp_human_y = human_y;
272 
273     if(direction & UP)    tmp_human_y--;
274     if(direction & DOWN)  tmp_human_y++;
275     if(direction & LEFT)  tmp_human_x--;
276     if(direction & RIGHT) tmp_human_x++;
277 
278     if( !can_go(tmp_human_x,tmp_human_y) )
279       break;
280     last_human_x = human_x;
281     last_human_y = human_y;
282     human_x = tmp_human_x;
283     human_y = tmp_human_y;
284     num_wasted = chase(0);
285     if(app_data.showjumps)
286       show_movement();
287     add_score(num_wasted);
288     if(!num_robots)
289       break;
290     if(app_data.spiffy)
291       pointer_moved((Widget)0,(caddr_t)0,event);
292     XFlush(display);
293   }
294   if(!num_robots)
295       new_level();
296   else
297     if(!app_data.showjumps)
298       display_level();
299   display_possible_moves();
300   auto_teleport();
301   pointer_moved((Widget)0,(caddr_t)0,event);
302   XFlush(display);
303 }
304 
305 
306 
307 /*ARGSUSED*/
308 XtEventHandler
pointer_moved(w,closure,event)309 pointer_moved(w, closure, event)
310   Widget w;
311   caddr_t closure;
312   XPointerMovedEvent *event;
313 {
314   if(game_active)
315     /* could probably suck up any other pointer motion events here... */
316     update_pointer( determine_direction(event->x,event->y) );
317 }
318 
319