source: abuse/trunk/src/clisp.cpp @ 497

Last change on this file since 497 was 497, checked in by Sam Hocevar, 10 years ago

lisp: implement LSymbol::EvalFunction? and ensure all local pointers are
protected against collection.

File size: 81.5 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
13#include <string.h>
14
15#include "sdlport/joy.h"
16
17#include "ant.h"
18#include "lisp.h"
19#include "game.h"
20#include "jrand.h"
21#include "dev.h"
22#include "pcxread.h"
23#include "menu.h"
24#include "dprint.h"
25#include "clisp.h"
26#include "chars.h"
27#include "lisp_gc.h"
28#include "cop.h"
29#include "loadgame.h"
30#include "nfserver.h"
31#include "demo.h"
32#include "chat.h"
33#include "jdir.h"
34#include "netcfg.h"
35
36#define ENGINE_MAJOR 1
37#define ENGINE_MINOR 20
38
39extern int has_joystick;
40
41// the following are references to lisp symbols
42LSymbol *l_chat_input, *l_post_render;
43
44LSymbol *l_difficulty, *l_easy, *l_hard, *l_medium, *l_extreme,
45    *l_max_hp, *l_max_power,
46    *l_empty_cache;
47
48// FIXME: port these to LSymbol
49void *l_main_menu, *l_logo,*l_state_art,*l_abilities,*l_state_sfx,
50     *l_song_list,*l_filename,*l_sfx_directory,*l_default_font,
51     *l_morph,*l_default_abilities,*l_default_ai_function,
52     *l_tile_files,*l_range,*l_hurt_all,*l_death_handler,
53     *l_title_screen,*l_console_font,*l_fields,*l_dist,*l_pushx,*l_pushy,
54     *l_object,*l_tile,*l_fire_object,*l_FIRE,*l_cop_dead_parts,*l_restart_player,
55     *l_help_screens,*l_player_draw,*l_sneaky_draw,*l_health_image,*l_fly_image,
56     *l_sneaky_image,*l_draw_fast,*l_player_tints,*l_save_order,*l_next_song,
57     *l_level_load_start,
58     *l_level_load_end,        *l_cdc_logo,
59     *l_keep_backup,
60     *l_switch_to_powerful,
61     *l_mouse_can_switch,
62     *l_ask_save_slot,
63     *l_get_local_input,
64     *l_player_text_color,
65     *l_level_loaded;        // called when a new level is loaded
66
67
68char game_name[50];
69void *sensor_ai();
70
71// variables for the status bar
72void        *l_statbar_ammo_x,*l_statbar_ammo_y,
73            *l_statbar_ammo_w,*l_statbar_ammo_h,
74        *l_statbar_ammo_bg_color,
75
76            *l_statbar_health_x,*l_statbar_health_y,
77            *l_statbar_health_w,*l_statbar_health_h,
78        *l_statbar_health_bg_color,
79
80        *l_statbar_logo_x,*l_statbar_logo_y;
81uint8_t chatting_enabled=0;
82
83extern void scatter_line(int x1, int y1, int x2, int y2, int c, int s);
84extern void ascatter_line(int x1, int y1, int x2, int y2, int c1, int c2, int s);
85extern void show_end();
86
87static view *lget_view(void *arg, char const *msg)
88{
89  game_object *o=(game_object *)lpointer_value(arg);
90  view *c=o->controller();
91  if (!c)
92  {
93    dprintf("%s : object does not have a view\n",msg);
94    lbreak("");
95    exit(0);
96  }
97  return c;
98}
99
100extern int get_option(char const *name);
101extern void set_login(char const *name);
102
103void clisp_init()                            // call by lisp_init, defines symbols and functions
104                                             // to irnterface with c
105{
106  l_easy = LSymbol::FindOrCreate("easy");
107  l_medium = LSymbol::FindOrCreate("medium");
108  l_hard = LSymbol::FindOrCreate("hard");
109  l_extreme = LSymbol::FindOrCreate("extreme");
110
111  l_logo = LSymbol::FindOrCreate("logo");
112  l_morph = LSymbol::FindOrCreate("morph");
113
114  l_pushx = LSymbol::FindOrCreate("pushx");
115  l_pushy = LSymbol::FindOrCreate("pushy");
116
117  l_dist = LSymbol::FindOrCreate("dist");
118  l_state_art = LSymbol::FindOrCreate("state_art");
119  l_abilities = LSymbol::FindOrCreate("abilities");
120  l_default_abilities = LSymbol::FindOrCreate("default_abilities");
121  l_state_sfx = LSymbol::FindOrCreate("state_sfx");
122  l_filename = LSymbol::FindOrCreate("filename");
123  l_sfx_directory = LSymbol::FindOrCreate("sfx_directory");
124  l_default_font = LSymbol::FindOrCreate("default_font");
125  l_console_font = LSymbol::FindOrCreate("console_font");
126  l_default_ai_function = LSymbol::FindOrCreate("default_ai");
127  l_tile_files = LSymbol::FindOrCreate("tile_files");
128  l_empty_cache = LSymbol::FindOrCreate("empty_cache");
129  l_range = LSymbol::FindOrCreate("range");
130  l_difficulty = LSymbol::FindOrCreate("difficulty");
131  l_death_handler = LSymbol::FindOrCreate("death_handler");
132  l_title_screen = LSymbol::FindOrCreate("title_screen");
133  l_fields = LSymbol::FindOrCreate("fields");
134  l_FIRE = LSymbol::FindOrCreate("FIRE");
135  l_fire_object = LSymbol::FindOrCreate("fire_object");
136  l_cop_dead_parts = LSymbol::FindOrCreate("cop_dead_parts");
137  l_difficulty->SetValue(l_hard);
138  l_restart_player = LSymbol::FindOrCreate("restart_player");
139  l_help_screens = LSymbol::FindOrCreate("help_screens");
140  l_save_order = LSymbol::FindOrCreate("save_order");
141  l_next_song = LSymbol::FindOrCreate("next_song");
142  l_player_draw = LSymbol::FindOrCreate("player_draw");
143  l_sneaky_draw = LSymbol::FindOrCreate("sneaky_draw");
144  l_keep_backup = LSymbol::FindOrCreate("keep_backup");
145  l_level_loaded = LSymbol::FindOrCreate("level_loaded");
146
147  l_draw_fast = LSymbol::FindOrCreate("draw_fast");
148  l_player_tints = LSymbol::FindOrCreate("player_tints");
149
150  l_max_hp = LSymbol::FindOrCreate("max_hp");
151  l_max_hp->SetNumber(200);
152  l_max_power = LSymbol::FindOrCreate("max_power");
153  l_main_menu = LSymbol::FindOrCreate("main_menu");
154  l_max_power->SetNumber(999);
155
156  LSymbol::FindOrCreate("run_state")->SetNumber(RUN_STATE);
157  LSymbol::FindOrCreate("pause_state")->SetNumber(PAUSE_STATE);
158  LSymbol::FindOrCreate("menu_state")->SetNumber(MENU_STATE);
159  LSymbol::FindOrCreate("scene_state")->SetNumber(SCENE_STATE);
160
161  l_statbar_ammo_x = LSymbol::FindOrCreate("statbar_ammo_x");
162  l_statbar_ammo_y = LSymbol::FindOrCreate("statbar_ammo_y");
163  l_statbar_ammo_w = LSymbol::FindOrCreate("statbar_ammo_w");
164  l_statbar_ammo_h = LSymbol::FindOrCreate("statbar_ammo_h");
165  l_statbar_ammo_bg_color = LSymbol::FindOrCreate("statbar_ammo_bg_color");
166
167  l_statbar_health_x = LSymbol::FindOrCreate("statbar_health_x");
168  l_statbar_health_y = LSymbol::FindOrCreate("statbar_health_y");
169  l_statbar_health_w = LSymbol::FindOrCreate("statbar_health_w");
170  l_statbar_health_h = LSymbol::FindOrCreate("statbar_health_h");
171  l_statbar_health_bg_color = LSymbol::FindOrCreate("statbar_health_bg_color");
172
173  l_statbar_logo_x = LSymbol::FindOrCreate("statbar_logo_x");
174  l_statbar_logo_y = LSymbol::FindOrCreate("statbar_logo_y");
175  l_object = LSymbol::FindOrCreate("object");
176  l_tile = LSymbol::FindOrCreate("tile");
177  l_cdc_logo = LSymbol::FindOrCreate("logo");
178
179  l_switch_to_powerful = LSymbol::FindOrCreate("switch_to_powerful");
180  l_mouse_can_switch = LSymbol::FindOrCreate("mouse_can_switch");
181  l_ask_save_slot = LSymbol::FindOrCreate("ask_save_slot");
182
183  l_level_load_start = LSymbol::FindOrCreate("level_load_start");
184  l_level_load_end = LSymbol::FindOrCreate("level_load_end");
185  l_get_local_input = LSymbol::FindOrCreate("get_local_input");
186  l_chat_input = LSymbol::FindOrCreate("chat_input");
187  l_player_text_color = LSymbol::FindOrCreate("player_text_color");
188
189  int i;
190  for (i=0; i<MAX_STATE; i++)
191    LSymbol::FindOrCreate(state_names[i])->SetNumber(i);
192  for (i=0; i<TOTAL_ABILITIES; i++)
193    LSymbol::FindOrCreate(ability_names[i])->SetNumber(i);
194  for (i=0; i<TOTAL_CFLAGS; i++)
195    LSymbol::FindOrCreate(cflag_names[i])->SetNumber(i);
196
197  l_song_list = LSymbol::FindOrCreate("song_list");
198  l_post_render = LSymbol::FindOrCreate("post_render");
199
200  add_c_function("distx",0,0,                   1);
201  add_c_function("disty",0,0,                   2);
202  add_c_bool_fun("key_pressed",1,1,             3);
203  add_c_bool_fun("local_key_pressed",1,1,       4);
204
205  add_c_function("bg_state",0,0,                5);
206  add_c_function("aitype",0,0,                  6);
207  add_c_function("aistate",0,0,                 7);
208  add_c_function("set_aistate",1,1,             8);
209  add_c_function("random",1,1,                  9);
210  add_c_function("state_time",0,0,             10);
211  add_c_function("state",0,0,                  11);
212  add_c_function("toward",0,0,                 12);
213  add_c_function("move",3,3,                   13);
214  add_c_function("facing",0,0,                 14);
215  add_c_function("otype",0,0,                  15);
216  add_c_bool_fun("next_picture",0,0,           16);
217  add_c_bool_fun("set_fade_dir",1,1,           17);
218  add_c_function("mover",3,3,                  18);
219  add_c_bool_fun("set_fade_count",1,1,         19);
220  add_c_function("fade_count",0,0,             20);
221  add_c_function("fade_dir",0,0,               21);
222  add_c_bool_fun("touching_bg",0,0,            22);
223  add_c_function("add_power",1,1,              23);
224  add_c_function("add_hp",1,1,                 24);
225
226  add_c_bool_fun("draw",0,0,                   27);
227  add_c_bool_fun("edit_mode",0,0,              28);
228  add_c_bool_fun("draw_above",0,0,             29);
229  add_c_function("x",0,0,                      30);
230  add_c_function("y",0,0,                      31);
231  add_c_bool_fun("set_x",1,1,                  32);
232  add_c_bool_fun("set_y",1,1,                  33);
233  add_c_bool_fun("push_characters",2,2,        34);
234
235
236
237  add_c_bool_fun("set_state",1,1,              37);
238  add_c_function("bg_x",0,0,                   38);
239  add_c_function("bg_y",0,0,                   39);
240  add_c_bool_fun("set_aitype",1,1,             40);
241
242  add_c_function("xvel",0,0,                   42);
243  add_c_function("yvel",0,0,                   43);
244  add_c_bool_fun("set_xvel",1,1,               44);
245  add_c_bool_fun("set_yvel",1,1,               45);
246  add_c_function("away",0,0,                   46);
247  add_c_bool_fun("blocked_left",1,1,           47);
248  add_c_bool_fun("blocked_right",1,1,          48);
249
250  add_c_function("add_palette",1,-1,           50);    // name, w,h,x,y,scale, tiles
251  add_c_bool_fun("screen_shot",1,1,            51);    // filename
252
253  add_c_bool_fun("set_zoom",1,1,               52);
254  add_c_function("show_help",1,1,              55);    // type, x,y
255  add_c_function("direction",0,0,              56);
256  add_c_function("set_direction",1,1,          57);
257
258  add_c_bool_fun("freeze_player",1,1,          58);   // freeze time
259
260  add_c_function("menu",1,-1,                  59);
261  add_c_bool_fun("do_command",1,1,             60);   // command string
262  add_c_bool_fun("set_game_state",1,1,         61);
263
264
265// scene control functions, game must first be set to scene mode.
266  add_c_bool_fun("scene:set_text_region",4,4,  62);
267  add_c_bool_fun("scene:set_frame_speed",1,1,  63);
268  add_c_bool_fun("scene:set_scroll_speed",1,1, 64);
269  add_c_bool_fun("scene:set_pan_speed",1,1,    65);
270  add_c_bool_fun("scene:scroll_text",1,1,      66);
271  add_c_bool_fun("scene:pan",3,3,              67);
272  add_c_bool_fun("scene:wait",1,1,             68);
273
274  add_c_bool_fun("level:new",3,3,              74);    // width, height, name
275
276  add_c_bool_fun("do_damage",2,4,              75);    // amount, to_object, [pushx pushy]
277  add_c_function("hp",0,0,                     76);
278  add_c_bool_fun("set_shift_down",2,2,         77);
279  add_c_bool_fun("set_shift_right",2,2,        78);
280  add_c_bool_fun("set_gravity",1,1,            79);
281  add_c_function("tick",0,0,                   80);
282
283  add_c_bool_fun("set_xacel",1,1,              81);
284  add_c_bool_fun("set_yacel",1,1,              82);
285  add_c_bool_fun("set_local_players",1,1,      84);   // set # of players on this machine, unsupported?
286  add_c_function("local_players",0,0,          85);
287
288  add_c_bool_fun("set_light_detail",1,1,       86);
289  add_c_function("light_detail",0,0,           87);
290  add_c_bool_fun("set_morph_detail",1,1,       88);
291  add_c_function("morph_detail",0,0,           89);
292  add_c_bool_fun("morph_into",3,3,             90);       // type aneal frames
293  add_c_bool_fun("link_object",1,1,            91);
294
295  add_c_bool_fun("draw_line",5,5,              92);
296  add_c_function("dark_color",0,0,             93);
297  add_c_function("medium_color",0,0,           94);
298  add_c_function("bright_color",0,0,           95);
299
300  add_c_bool_fun("remove_object",1,1,          99);
301  add_c_bool_fun("link_light",1,1,            100);
302  add_c_bool_fun("remove_light",1,1,          101);
303  add_c_function("total_objects",0,0,         102);
304  add_c_function("total_lights",0,0,          103);
305
306  add_c_bool_fun("set_light_r1",2,2,          104);
307  add_c_bool_fun("set_light_r2",2,2,          105);
308  add_c_bool_fun("set_light_x",2,2,           106);
309  add_c_bool_fun("set_light_y",2,2,           107);
310  add_c_bool_fun("set_light_xshift",2,2,      108);
311  add_c_bool_fun("set_light_yshift",2,2,      109);
312
313  add_c_function("light_r1",1,1,              110);
314  add_c_function("light_r2",1,1,              111);
315  add_c_function("light_x",1,1,               112);
316  add_c_function("light_y",1,1,               113);
317  add_c_function("light_xshift",1,1,          114);
318  add_c_function("light_yshift",1,1,          115);
319
320  add_c_function("xacel",0,0,                 116);
321  add_c_function("yacel",0,0,                 117);
322  add_c_bool_fun("delete_light",1,1,          118);
323
324  add_c_bool_fun("set_fx",1,1,                119);
325  add_c_bool_fun("set_fy",1,1,                120);
326  add_c_bool_fun("set_fxvel",1,1,             121);
327  add_c_bool_fun("set_fyvel",1,1,             122);
328  add_c_bool_fun("set_fxacel",1,1,            123);
329  add_c_bool_fun("set_fyacel",1,1,            124);
330  add_c_function("picture_width",0,0,         125);
331  add_c_function("picture_height",0,0,        126);
332  add_c_bool_fun("trap",0,0,                  127);
333  add_c_bool_fun("platform_push",2,2,         128);
334
335  add_c_function("def_sound",1,2,             133);  // symbol, filename [ or just filenmae]
336  add_c_bool_fun("play_sound",1,4,            134);
337
338  add_c_function("def_particle",2,2,          137);  // symbol, filename
339  add_c_function("add_panim",4,4,             138);  // id, x, y, dir
340
341  add_c_function("weapon_to_type",1,1,        142);  // returns total for type weapon
342  add_c_bool_fun("hurt_radius",6,6,           143);  // x y radius max_damage exclude_object max_push
343
344  add_c_bool_fun("add_ammo",2,2,              144);  // weapon_type, amount
345  add_c_function("ammo_total",1,1,            145);  // returns total for type weapon
346  add_c_function("current_weapon",0,0,        146);  // weapon_type, amount
347  add_c_function("current_weapon_type",0,0,   147);  // returns total for type weapon
348
349  add_c_bool_fun("blocked_up",1,1,            148);
350  add_c_bool_fun("blocked_down",1,1,          149);
351  add_c_bool_fun("give_weapon",1,1,           150);  // type
352  add_c_function("get_ability",1,1,           151);
353  add_c_bool_fun("reset_player",0,0,          152);
354  add_c_function("site_angle",1,1,            153);
355  add_c_bool_fun("set_course",2,2,            154);  // angle, magnitude
356  add_c_bool_fun("set_frame_angle",3,3,       155);  // ang1,ang2, ang
357  add_c_bool_fun("jump_state",1,1,            156);  // don't reset current_frame
358
359  add_c_bool_fun("morphing",0,0,              168);
360  add_c_bool_fun("damage_fun",6,6,            169);
361  add_c_bool_fun("gravity",0,0,               170);
362  add_c_bool_fun("make_view_solid",1,1,       171);
363  add_c_function("find_rgb",3,3,              172);
364
365  add_c_function("player_x_suggest",0,0,      173);  // return player "joystick" x
366  add_c_function("player_y_suggest",0,0,      174);
367  add_c_function("player_b1_suggest",0,0,     175);
368  add_c_function("player_b2_suggest",0,0,     176);
369  add_c_function("player_b3_suggest",0,0,     177);
370
371  add_c_bool_fun("set_bg_scroll",4,4,         178);  // xmul xdiv ymul ydiv
372  add_c_bool_fun("set_ambient_light",2,2,     179);  // player, 0..63 (out of bounds ignored)
373  add_c_function("ambient_light",1,1,         180);  // player
374  add_c_bool_fun("has_object",1,1,            181);  // true if linked with object x
375  add_c_bool_fun("set_otype",1,1,             182);  // otype
376
377  add_c_function("current_frame",0,0,         184);
378  add_c_function("fx",0,0,                    185);
379  add_c_function("fy",0,0,                    186);
380  add_c_function("fxvel",0,0,                 187);
381  add_c_function("fyvel",0,0,                 188);
382  add_c_function("fxacel",0,0,                189);
383  add_c_function("fyacel",0,0,                190);
384  add_c_bool_fun("set_stat_bar",2,2,          191);  // filename, object
385  add_c_bool_fun("set_fg_tile",3,3,           192);  // x,y, tile #
386  add_c_function("fg_tile",2,2,               193);  // x,y
387  add_c_bool_fun("set_bg_tile",3,3,           194);  // x,y, tile #
388  add_c_function("bg_tile",2,2,               195);  // x,y
389  add_c_bool_fun("load_tiles",1,-1,           196);  // filename1, filename2...
390  add_c_bool_fun("load_palette",1,1,          197);  // filename
391  add_c_bool_fun("load_color_filter",1,1,     198);  // filename
392  add_c_bool_fun("create_players",1,1,        199);  // player type, returns true if game is networked
393  add_c_bool_fun("try_move",2,3,              200);  // xv yv (check_top=t) -> returns T if not blocked
394  add_c_function("sequence_length",1,1,       201);  // sequence number
395  add_c_bool_fun("can_see",5,5,               202);  // x1,y1, x2,y2, chars_block
396  add_c_function("load_big_font",2,2,         203);  // filename, name
397  add_c_function("load_small_font",2,2,       204);  // filename, name
398  add_c_function("load_console_font",2,2,     205);  // filename, name
399  add_c_function("set_current_frame",1,1,     206);
400
401  add_c_bool_fun("draw_transparent",2,2,      208);  // count, max
402  add_c_bool_fun("draw_tint",1,1,             209);  // tint id number
403  add_c_bool_fun("draw_predator",0,0,         210);  // tint_number
404
405  add_c_function("shift_down",1,1,            211);  // player
406  add_c_function("shift_right",1,1,           212);  // player
407  add_c_bool_fun("set_no_scroll_range",5,5,   213);  // player, x1,y1,x2,y2
408
409  add_c_function("def_image",2,2,             215);  // filename,name
410  add_c_bool_fun("put_image",3,3,             216);  // x,y,id
411  add_c_function("view_x1",0,0,               217);
412  add_c_function("view_y1",0,0,               218);
413  add_c_function("view_x2",0,0,               219);
414  add_c_function("view_y2",0,0,               220);
415  add_c_function("view_push_down",1,1,        221);
416  add_c_bool_fun("local_player",0,0,          222);
417  add_c_bool_fun("save_game",1,1,             223);  // filename
418  add_c_bool_fun("set_hp",1,1,                224);
419  add_c_bool_fun("request_level_load",1,1,    225);  // filename
420  add_c_bool_fun("set_first_level",1,1,       226);  // filename
421  add_c_function("def_tint",1,1,              227);  // filename
422  add_c_function("tint_palette",3,3,          228);  // radd,gadd,badd
423  add_c_function("player_number",0,0,         229);
424  add_c_bool_fun("set_current_weapon",1,1,    230);  // type
425  add_c_bool_fun("has_weapon",1,1,            231);  // type
426  add_c_bool_fun("ambient_ramp",1,1,          232);
427  add_c_function("total_players",0,0,         233);
428  add_c_bool_fun("scatter_line",6,6,          234);  // x1,y1,x2,y2, color, scatter value
429  add_c_function("game_tick",0,0,             235);
430  add_c_bool_fun("isa_player",0,0,            236);
431  add_c_bool_fun("shift_rand_table",1,1,      237);  // amount
432  add_c_function("total_frames",0,0,          238);
433  add_c_function("raise",0,0,                 239);  // call only from reload constructor!
434  add_c_function("lower",0,0,                 240);  // call only from reload constructor!
435
436  add_c_function("player_pointer_x",0,0,      241);
437  add_c_function("player_pointer_y",0,0,      242);
438  add_c_bool_fun("frame_panic",0,0,           243);
439  add_c_bool_fun("ascatter_line",7,7,         244);  // x1,y1,x2,y2, color1, color2, scatter value
440  add_c_function("rand_on",0,0,               245);
441  add_c_function("set_rand_on",1,1,           246);
442  add_c_function("bar",5,5,                   247);
443  add_c_function("argc",0,0,                  248);
444  add_c_bool_fun("play_song",1,1,             249);  // filename
445  add_c_bool_fun("stop_song",0,0,             250);
446  add_c_bool_fun("targetable",0,0,            251);
447  add_c_bool_fun("set_targetable",1,1,        252);  // T or nil
448  add_c_bool_fun("show_stats",0,0,            253);
449
450  add_c_function("kills",0,0,                 254);
451  add_c_function("tkills",0,0,                255);
452  add_c_function("secrets",0,0,               256);
453  add_c_function("tsecrets",0,0,              257);
454
455  add_c_bool_fun("set_kills",1,1,             258);
456  add_c_bool_fun("set_tkills",1,1,            259);
457  add_c_bool_fun("set_secrets",1,1,           260);
458  add_c_bool_fun("set_tsecrets",1,1,          261);
459  add_c_bool_fun("request_end_game",0,0,      262);
460  add_c_function("get_save_slot",0,0,         263);
461  add_c_bool_fun("mem_report",0,0,            264);
462  add_c_function("major_version",0,0,         265);
463  add_c_function("minor_version",0,0,         266);
464  add_c_bool_fun("draw_double_tint",2,2,      267);  // tint1 id number, tint 2 id number
465  add_c_function("image_width",1,1,           268);  // image number
466  add_c_function("image_height",1,1,          269);  // image number
467  add_c_function("foreground_width",0,0,      270);
468  add_c_function("foreground_height",0,0,     271);
469  add_c_function("background_width",0,0,      272);
470  add_c_function("background_height",0,0,     273);
471  add_c_function("get_key_code",1,1,          274);  // name of key, returns code that can be used with keypressed
472  add_c_bool_fun("set_cursor_shape",3,3,      275);  // image id, x hot, y hot
473  add_c_bool_fun("start_server",0,0,          276);
474  add_c_bool_fun("put_string",4,5,            277);  // font,x,y,string, [color]
475  add_c_function("font_width",1,1,            278);  // font
476  add_c_function("font_height",1,1,           279);  // font
477  add_c_bool_fun("chat_print",1,1,            280);  // chat string
478  add_c_bool_fun("set_player_name",1,1,       281);  // name
479  add_c_bool_fun("draw_bar",5,5,              282);  // x1,y1,x2,y2,color
480  add_c_bool_fun("draw_rect",5,5,             283);  // x1,y1,x2,y2,color
481  add_c_bool_fun("get_option",1,1,            284);
482  add_c_bool_fun("set_delay_on",1,1,          288);  // T or nil
483  add_c_bool_fun("set_login",1,1,             289);  // name
484  add_c_bool_fun("enable_chatting",0,0,       290);
485  add_c_bool_fun("demo_break_enable",0,0,     291);
486  add_c_bool_fun("am_a_client",0,0,           292);
487  add_c_bool_fun("time_for_next_level",0,0,   293);
488  add_c_bool_fun("reset_kills",0,0,           294);
489  add_c_bool_fun("set_game_name",1,1,         295);  // server game name
490  add_c_bool_fun("set_net_min_players",1,1,   296);
491
492  add_c_bool_fun("set_object_tint", 1, 1,    1001);  // set_object_tint
493  add_c_function("get_object_tint", 0, 0,    1002);  // get_object_tint
494  add_c_bool_fun("set_object_team", 1, 1,    1003);  // set_object_team
495  add_c_function("get_object_team", 0, 0,    1004);  // get_object_tint
496
497
498  add_lisp_function("go_state",1,1,              0);
499  add_lisp_function("with_object",2,-1,          1);
500  add_lisp_function("bmove",0,1,                 2);   // returns true=unblocked, nil=block, or object
501  add_lisp_function("me",0,0,                    3);
502  add_lisp_function("bg",0,0,                    4);
503  add_lisp_function("find_closest",1,1,          5);
504  add_lisp_function("find_xclosest",1,1,         6);
505  add_lisp_function("find_xrange",2,2,           7);
506  add_lisp_function("add_object",3,4,            8);    // type, x,y (type)
507  add_lisp_function("first_focus",0,0,           9);
508  add_lisp_function("next_focus",1,1,           10);
509  add_lisp_function("get_object",1,1,           11);
510  add_lisp_function("get_light",1,1,            12);
511  add_lisp_function("with_objects",1,1,         13);
512  add_lisp_function("add_light",7,7,            14);   // type, x, y, r1, r2, xshift, yshift
513  add_lisp_function("find_enemy",1,1,           15);   // exclude
514  add_lisp_function("user_fun",0,-1,            16);   // calls anobject's user function
515  add_lisp_function("time",2,2,                 17);   // returns a fixed point (times and operation)
516  add_lisp_function("name",0,0,                 18);   // returns current object's name (for debugin)
517  add_lisp_function("float_tick",0,0,           19);
518  add_lisp_function("find_object_in_area",5,5,  20);  // x1, y1, x2, y2  type_list
519  add_lisp_function("find_object_in_angle",3,3, 21);  // start_angle end_angle type_list
520  add_lisp_function("add_object_after",3,4,     22);  // type, x,y (type)
521  add_lisp_function("def_char",2,-1,            23);  // needs at least 2 parms
522  add_lisp_function("see_dist",4,4,             24);  // returns longest unblocked path from x1,y1,x2,y2
523  add_lisp_function("platform",0,0,             25);
524  add_lisp_function("level_name",0,0,           26);
525  add_lisp_function("ant_ai",0,0,               27);
526  add_lisp_function("sensor_ai",0,0,            28);
527  add_lisp_function("dev_draw",0,0,             29);
528  add_lisp_function("top_ai",0,0,               30);
529  add_lisp_function("laser_ufun",2,2,           31);
530  add_lisp_function("top_ufun",2,2,             32);
531
532  add_lisp_function("player_rocket_ufun",2,2,   34);
533
534  add_lisp_function("plaser_ufun",2,2,          33);
535  add_lisp_function("lsaber_ufun",2,2,          35);
536
537  add_lisp_function("cop_mover",3,3,            36);
538  add_lisp_function("latter_ai",0,0,            37);
539  add_lisp_function("with_obj0",-1,-1,          38);
540  add_lisp_function("activated",0,0,            39);
541  add_lisp_function("top_draw",0,0,             40);
542  add_lisp_function("bottom_draw",0,0,          41);
543  add_lisp_function("mover_ai",0,0,             42);
544  add_lisp_function("sgun_ai",0,0,              43);
545  add_lisp_function("last_savegame_name",0,0,   44);
546  add_lisp_function("next_savegame_name",0,0,   45);
547  add_lisp_function("argv",1,1,                 46);
548  add_lisp_function("joy_stat",0,0,             47);  // xm ym b1 b2 b3
549  add_lisp_function("mouse_stat",0,0,           48);  // mx my b1 b2 b3
550  add_lisp_function("mouse_to_game",2,2,        49);  // pass in x,y -> x,y
551  add_lisp_function("game_to_mouse",2,2,        50);  // pass in x,y -> x,y
552  add_lisp_function("get_main_font",0,0,        51);
553  add_lisp_function("player_name",0,0,          52);
554  add_lisp_function("get_cwd",0,0,              54);
555  add_lisp_function("system",1,1,               55);
556  add_lisp_function("convert_slashes",2,2,      56);
557  add_lisp_function("get_directory",1,1,        58);  // path
558  add_lisp_function("respawn_ai",0,0,           60);
559
560  add_lisp_function("score_draw",0,0,           61);
561  add_lisp_function("show_kills",0,0,           62);
562  add_lisp_function("mkptr",1,1,                63);
563  add_lisp_function("seq",3,3,                  64);
564}
565
566
567// Note : args for l_caller have not been evaluated yet!
568void *l_caller(long number, void *args)
569{
570  PtrRef r1(args);
571  switch (number)
572  {
573    case 0 :
574    {
575      current_object->set_aistate(lnumber_value(CAR(args)->Eval()));
576      current_object->set_aistate_time(0);
577      void *ai=figures[current_object->otype]->get_fun(OFUN_AI);
578      if (!ai)
579      {
580    lbreak("hrump... call to go_state, and no ai function defined?\n"
581           "Are you calling from move function (not mover)?\n");
582    exit(0);
583      }
584      return ((LSymbol *)ai)->EvalFunction(NULL);
585    } break;
586    case 1 :
587    {
588      game_object *old_cur=current_object;
589      current_object=(game_object *)lpointer_value(CAR(args)->Eval());
590      void *ret=eval_block(CDR(args));
591      current_object=old_cur;
592      return ret;
593    }  break;
594
595
596    case 2 :
597    {
598      int whit;
599      game_object *o;
600      if (args)
601        o=(game_object *)lpointer_value(CAR(args)->Eval());
602      else o=current_object;
603      game_object *hit=current_object->bmove(whit,o);
604      if (hit)
605        return LPointer::Create(hit);
606      else if (whit) return NULL;
607      else return true_symbol;
608    } break;
609
610    case 3 : return LPointer::Create(current_object); break;
611    case 4 :
612    { if (player_list->next)
613        return LPointer::Create(current_level->attacker(current_object));
614      else return LPointer::Create(player_list->focus); } break;
615    case 5 : return LPointer::Create(current_level->find_closest(current_object->x,
616                                 current_object->y,
617                               lnumber_value(CAR(args)->Eval()),
618                                       current_object)); break;
619    case 6 : return LPointer::Create(current_level->find_xclosest(current_object->x,
620                                  current_object->y,
621                                  lnumber_value(CAR(args)->Eval()),
622                                  current_object
623                                  )); break;
624    case 7 :
625    {
626      long n1=lnumber_value(CAR(args)->Eval());
627      long n2=lnumber_value(CAR(CDR(args))->Eval());
628      return LPointer::Create(current_level->find_xrange(current_object->x,
629                             current_object->y,
630                             n1,
631                             n2
632                             ));
633    } break;
634    case 8 :
635    {
636      int type=lnumber_value(CAR(args)->Eval()); args=CDR(args);
637      long x=lnumber_value(CAR(args)->Eval()); args=CDR(args);
638      long y=lnumber_value(CAR(args)->Eval()); args=CDR(args);
639      game_object *o;
640      if (args)
641        o=create(type,x,y,0,lnumber_value(CAR(args)->Eval()));
642      else
643        o=create(type,x,y);
644      if (current_level)
645        current_level->add_object(o);
646      return LPointer::Create(o);
647    } break;
648    case 22 :
649    {
650      int type=lnumber_value(CAR(args)->Eval()); args=CDR(args);
651      long x=lnumber_value(CAR(args)->Eval()); args=CDR(args);
652      long y=lnumber_value(CAR(args)->Eval()); args=CDR(args);
653      game_object *o;
654      if (args)
655        o=create(type,x,y,0,lnumber_value(CAR(args)->Eval()));
656      else
657        o=create(type,x,y);
658      if (current_level)
659        current_level->add_object_after(o,current_object);
660      return LPointer::Create(o);
661    } break;
662
663    case 9 : return LPointer::Create(the_game->first_view->focus); break;
664    case 10 :
665    {
666      view *v=((game_object *)lpointer_value(CAR(args)->Eval()))->controller()->next;
667      if (v)
668        return LPointer::Create(v->focus);
669      else return NULL;
670    } break;
671    case 11 :
672    {
673      return LPointer::Create
674      ((void *)current_object->get_object(lnumber_value(CAR(args)->Eval())));
675    } break;
676    case 12 :
677    {
678      return LPointer::Create
679      ((void *)current_object->get_light(lnumber_value(CAR(args)->Eval())));
680    } break;
681    case 13 :
682    {
683      game_object *old_cur=current_object;
684      void *ret=NULL;
685      for (int i=0; i<old_cur->total_objects(); i++)
686      {
687    current_object=old_cur->get_object(i);
688    ret = CAR(args)->Eval();
689      }
690      current_object=old_cur;
691      return ret;
692    } break;
693    case 14 :
694    {
695      int t=lnumber_value(CAR(args)->Eval()); args=lcdr(args);
696      int x=lnumber_value(CAR(args)->Eval()); args=lcdr(args);
697      int y=lnumber_value(CAR(args)->Eval()); args=lcdr(args);
698      int r1=lnumber_value(CAR(args)->Eval()); args=lcdr(args);
699      int r2=lnumber_value(CAR(args)->Eval()); args=lcdr(args);
700      int xs=lnumber_value(CAR(args)->Eval()); args=lcdr(args);
701      int ys=lnumber_value(CAR(args)->Eval());
702      return LPointer::Create(add_light_source(t,x,y,r1,r2,xs,ys));
703    } break;
704    case 15 :
705    {
706//      return current_lev shit
707    } break;
708    case 16 :
709    {
710      void *f=figures[current_object->otype]->get_fun(OFUN_USER_FUN);
711      if (!f) return NULL;
712      return ((LSymbol *)f)->EvalFunction(args);
713    } break;
714    case 17 :
715    {
716      long trials=lnumber_value(CAR(args)->Eval());
717      args=CDR(args);
718      time_marker start;
719      for (int x=0; x<trials; x++)
720      {
721    clear_tmp();
722    CAR(args)->Eval();
723      }
724      time_marker end;
725      return LFixedPoint::Create((long)(end.diff_time(&start)*(1<<16)));
726    } break;
727    case 18 :
728    { return LString::Create(object_names[current_object->otype]); } break;
729    case 19 :
730    { return current_object->float_tick(); } break;
731    case 20 :
732    {
733      long x1=lnumber_value(CAR(args)->Eval()); args=CDR(args);
734      long y1=lnumber_value(CAR(args)->Eval()); args=CDR(args);
735      long x2=lnumber_value(CAR(args)->Eval()); args=CDR(args);
736      long y2=lnumber_value(CAR(args)->Eval()); args=CDR(args);
737
738      void *list = CAR(args)->Eval();
739      game_object *find=current_level->find_object_in_area(current_object->x,
740                          current_object->y,
741                          x1,y1,x2,y2,list,current_object);
742      if (find) return LPointer::Create(find);
743      else return NULL;
744    } break;
745
746    case 21 :
747    {
748      long a1=lnumber_value(CAR(args)->Eval()); args=CDR(args);
749      long a2=lnumber_value(CAR(args)->Eval()); args=CDR(args);
750
751      void *list = CAR(args)->Eval();
752      PtrRef r1(list);
753      game_object *find=current_level->find_object_in_angle(current_object->x,
754                            current_object->y,
755                            a1,a2,list,current_object);
756      if (find) return LPointer::Create(find);
757      else return NULL;
758    } break;
759    case 23 :         // def_character
760    {
761      LSymbol *sym=(LSymbol *)lcar(args);
762      if (item_type(sym)!=L_SYMBOL)
763      {
764        lbreak("expecting first arg to def-character to be a symbol!\n");
765        exit(0);
766      }
767      int sp=current_space;
768      current_space=PERM_SPACE;
769      sym->SetNumber(total_objects);   // set the symbol value to the object number
770      current_space=sp;
771      if (!total_objects)
772      {
773        object_names=(char **)malloc(sizeof(char *)*(total_objects+1));
774    figures=(character_type **)malloc(sizeof(character_type *)*(total_objects+1));
775      }
776      else
777      {
778        object_names=(char **)realloc(object_names,sizeof(char *)*(total_objects+1));
779    figures=(character_type **)realloc(figures,sizeof(character_type *)*(total_objects+1));
780      }
781
782      object_names[total_objects] = strdup(lstring_value(sym->GetName()));
783      figures[total_objects]=new character_type(CDR(args),sym);
784      total_objects++;
785      return LNumber::Create(total_objects-1);
786    } break;
787    case 24 :
788    {
789      int32_t x1=lnumber_value(CAR(args)->Eval()); args=CDR(args);
790      int32_t y1=lnumber_value(CAR(args)->Eval()); args=CDR(args);
791      int32_t x2=lnumber_value(CAR(args)->Eval()); args=CDR(args);
792      int32_t y2=lnumber_value(CAR(args)->Eval());
793      current_level->foreground_intersect(x1,y1,x2,y2);
794      void *ret=NULL;
795      push_onto_list(LNumber::Create(y2),ret);
796      push_onto_list(LNumber::Create(x2),ret);
797      return ret;
798    } break;
799    case 25 :
800    {
801#ifdef __linux__
802      return LSymbol::FindOrCreate("LINUX");
803#endif
804#ifdef __sgi
805      return LSymbol::FindOrCreate("IRIX");
806#endif
807#ifdef __WIN32
808      return LSymbol::FindOrCreate("WIN32");
809#endif
810    } break;
811    case 26 :
812    {
813      return LString::Create(current_level->name());
814    } break;
815    case 27 : return ant_ai(); break;
816    case 28 : return sensor_ai(); break;
817    case 29 : if (dev&EDIT_MODE) current_object->drawer(); break;
818    case 30 : return top_ai(); break;
819    case 31 : return laser_ufun(args); break;
820    case 32 : return top_ufun(args); break;
821    case 33 : return plaser_ufun(args); break;
822    case 34 : return player_rocket_ufun(args); break;
823    case 35 : return lsaber_ufun(args); break;
824    case 36 :
825    {
826
827      int32_t xm,ym,but;
828      xm=lnumber_value(CAR(args)); args=CDR(args);
829      ym=lnumber_value(CAR(args)); args=CDR(args);
830      but=lnumber_value(CAR(args));
831      return cop_mover(xm,ym,but);
832    } break;
833    case 37 : return ladder_ai(); break;
834    case 38 :
835    {
836      game_object *old_cur=current_object;
837      current_object=current_object->get_object(0);
838      void *ret=eval_block(args);
839      current_object=old_cur;
840      return ret;
841    }  break;
842    case 39 :
843    {
844      if (current_object->total_objects()==0)
845        return true_symbol;
846      else if (current_object->get_object(0)->aistate())
847        return true_symbol;
848      else return NULL;
849    } break;
850    case 40 : top_draw(); break;
851    case 41 : bottom_draw(); break;
852    case 42 : return mover_ai(); break;
853    case 43 : return sgun_ai();
854    case 44 :
855    {
856      char nm[50];
857      last_savegame_name(nm);
858      return LString::Create(nm);
859    } break;
860    case 45 :
861    {
862      char nm[50];
863      sprintf(nm,"save%04d.pcx", load_game(1,symbol_str("LOAD")));
864//      get_savegame_name(nm);
865      the_game->reset_keymap();
866      return LString::Create(nm);
867    } break;
868    case 46 :
869    {
870      return LString::Create(start_argv[lnumber_value(CAR(args)->Eval())]);
871    } break;
872    case 47 :
873    {
874      int xv,yv,b1,b2,b3;
875      if (has_joystick)
876        joy_status(b1,b2,b3,xv,yv);
877      else b1=b2=b3=xv=yv=0;
878
879      void *ret=NULL;
880      PtrRef r1(ret);
881      push_onto_list(LNumber::Create(b3),ret);
882      push_onto_list(LNumber::Create(b2),ret);
883      push_onto_list(LNumber::Create(b1),ret);
884      push_onto_list(LNumber::Create(yv),ret);
885      push_onto_list(LNumber::Create(xv),ret);
886      return ret;
887    } break;
888    case 48 :
889    {
890      void *ret=NULL;
891      {
892    PtrRef r1(ret);
893    push_onto_list(LNumber::Create((last_demo_mbut&4)==4),ret);
894    push_onto_list(LNumber::Create((last_demo_mbut&2)==2),ret);
895    push_onto_list(LNumber::Create((last_demo_mbut&1)==1),ret);
896    push_onto_list(LNumber::Create(last_demo_my),ret);
897    push_onto_list(LNumber::Create(last_demo_mx),ret);
898      }
899      return ret;
900    } break;
901    case 49 :
902    {
903      int32_t x=lnumber_value(CAR(args)->Eval()); args=CDR(args);
904      int32_t y=lnumber_value(CAR(args)->Eval()); args=CDR(args);
905
906      int32_t rx,ry;
907      the_game->mouse_to_game(x,y,rx,ry);
908      void *ret=NULL;
909      {
910    PtrRef r1(ret);
911    push_onto_list(LNumber::Create(ry),ret);
912    push_onto_list(LNumber::Create(rx),ret);
913      }
914      return ret;
915    } break;
916    case 50 :
917    {
918      int32_t x=lnumber_value(CAR(args)->Eval()); args=CDR(args);
919      int32_t y=lnumber_value(CAR(args)->Eval()); args=CDR(args);
920
921      int32_t rx,ry;
922      the_game->game_to_mouse(x,y,current_view,rx,ry);
923      void *ret=NULL;
924      {
925    PtrRef r1(ret);
926    push_onto_list(LNumber::Create(ry),ret);
927    push_onto_list(LNumber::Create(rx),ret);
928      }
929      return ret;
930    } break;
931    case 51 :   return LPointer::Create(wm->font()); break;
932    case 52 :
933    {
934      view *c=current_object->controller();
935      if (!c)
936        lbreak("object is not a player, cannot return name");
937      else
938        return LString::Create(c->name);
939    } break;
940    case 54 :
941    {
942      char cd[150];
943      getcwd(cd,100);
944      return LString::Create(cd);
945    } break;
946    case 55 :
947    { system(lstring_value(CAR(args)->Eval())); } break;
948    case 56 :
949    {
950      void *fn=CAR(args)->Eval(); args=CDR(args);
951      char tmp[200];
952      {
953    PtrRef r1(fn);
954    char *slash=lstring_value(CAR(args)->Eval());
955    char *filename=lstring_value(fn);
956
957    char *s=filename,*tp;
958
959    for (tp=tmp; *s; s++,tp++)
960    {
961      if (*s=='/' || *s=='\\')
962      *tp=*slash;
963      else *tp=*s;
964    }
965    *tp=0;
966      }
967      return LString::Create(tmp);
968    } break;
969    case 58 :
970    {
971      char **files,**dirs;
972      int tfiles,tdirs,i;
973
974      get_directory(lstring_value(CAR(args)->Eval()),files,tfiles,dirs,tdirs);
975      void *fl=NULL,*dl=NULL,*rl=NULL;
976      {
977    PtrRef r1(fl),r2(dl);
978
979    for (i=tfiles-1; i>=0; i--) { push_onto_list(LString::Create(files[i]),fl); free(files[i]); }
980    free(files);
981
982    for (i=tdirs-1; i>=0; i--) { push_onto_list(LString::Create(dirs[i]),dl); free(dirs[i]); }
983    free(dirs);
984
985    push_onto_list(dl,rl);
986    push_onto_list(fl,rl);
987      }
988
989      return rl;
990    } break;
991    case 60 : return respawn_ai(); break;
992    case 61 : return score_draw();  break;
993    case 62 : return show_kills(); break;
994    case 63 :
995    {
996        long x;
997        sscanf(lstring_value(CAR(args)->Eval()),"%lx",&x);
998        return LPointer::Create((void *)(intptr_t)x);
999    } break;
1000    case 64 :
1001    {
1002      char name[256],name2[256];
1003      strcpy(name,lstring_value(CAR(args)->Eval()));  args=CDR(args);
1004      long first=lnumber_value(CAR(args)->Eval());  args=CDR(args);
1005      long last=lnumber_value(CAR(args)->Eval());
1006      long i;
1007      void *ret=NULL;
1008      PtrRef r1(ret);
1009
1010      if (last>=first)
1011      {
1012        for (i=last; i>=first; i--)
1013        {
1014          sprintf(name2,"%s%04ld.pcx",name,i);
1015          push_onto_list(LString::Create(name2),ret);
1016        }
1017      } else
1018      {
1019        for (i=last; i<=first; i++)
1020        {
1021          sprintf(name2,"%s%04ld.pcx",name,i);
1022          push_onto_list(LString::Create(name2),ret);
1023        }
1024      }
1025      return ret;
1026    }
1027  }
1028  return NULL;
1029}
1030
1031//extern bFILE *rcheck,*rcheck_lp;
1032
1033// arguments have already been evaled..
1034long c_caller(long number, void *args)
1035{
1036    PtrRef r1(args);
1037    switch (number)
1038    {
1039        case 1:
1040        {
1041            return abs(current_object->x-current_level->attacker(current_object)->x);
1042        } break;
1043        case 2:
1044        {
1045            return abs(current_object->y-current_level->attacker(current_object)->y);
1046        } break;
1047        case 3:
1048        {
1049            if( !current_object->controller() )
1050            {
1051                lbreak("object is not a player, cannot determine keypresses");
1052            }
1053            else
1054            {
1055                return current_object->controller()->key_down(lnumber_value(CAR(args)));
1056            }
1057        } break;
1058        case 4:
1059        {
1060            return the_game->key_down(lnumber_value(CAR(args)));
1061        } break;
1062        case 5:
1063        {
1064            return current_level->attacker(current_object)->state;
1065        } break;
1066        case 6:
1067        {
1068            return current_object->aitype();
1069        } break;
1070        case 7:
1071        {
1072            if (!current_object->keep_ai_info())
1073                current_object->set_aistate(0);
1074            return current_object->aistate();
1075        } break;
1076        case 8:
1077        {
1078            int ns=lnumber_value(CAR(args));
1079            current_object->set_aistate_time(0);
1080            current_object->set_aistate(ns); return 1;
1081        } break;
1082        case 9:
1083        {
1084/*      if (rcheck_lp)
1085      {
1086    char str[100];
1087    sprintf(str,"\n\nTick %d, Rand_on %d\n",current_level->tick_counter(),rand_on);
1088    rcheck_lp->write(str,strlen(str)+1);
1089    current_print_file=rcheck_lp;
1090    print_trace_stack(6);
1091    current_print_file=NULL;
1092      }*/
1093
1094            return jrandom(lnumber_value(CAR(args)));
1095        } break;
1096        case 10 : return current_object->aistate_time(); break;
1097        case 11 : return current_object->state; break;
1098        case 12:
1099        {
1100            if (current_level->attacker(current_object)->x>current_object->x)
1101                return 1;
1102            else
1103                return -1;
1104        } break;
1105        case 13:
1106        {
1107            return current_object->move(lnumber_value(CAR(args)),lnumber_value(CAR(CDR(args))), lnumber_value(CAR(CDR(CDR(args)))));
1108        } break;
1109        case 14:
1110        {
1111            if (current_object->direction>0)
1112                return 1;
1113            else
1114                return -1;
1115        } break;
1116    case 15 : return current_object->otype; break;
1117    case 16 : return current_object->next_picture(); break;
1118    case 17 : current_object->set_fade_dir(lnumber_value(CAR(args))); return 1; break;
1119    case 18 :
1120    {
1121      int cx=lnumber_value(CAR(args));
1122      args=CDR(args);
1123      int cy=lnumber_value(CAR(args));
1124      args=CDR(args);
1125      int but=lnumber_value(CAR(args));
1126      return current_object->mover(cx,cy,but);
1127    } break;
1128    case 19 : current_object->set_fade_count(lnumber_value(CAR(args))); return 1; break;
1129    case 20 : return current_object->fade_count(); break;
1130    case 21 : return current_object->fade_dir(); break;
1131    case 22 :
1132    {
1133      int32_t x1,y1,x2,y2,xp1,yp1,xp2,yp2;
1134      current_level->attacker(current_object)->picture_space(x1,y1,x2,y2);
1135      current_object->picture_space(xp1,yp1,xp2,yp2);
1136      if (xp1>x2 || xp2<x1 || yp1>y2 || yp2<y1) return 0;
1137      else return 1;
1138    } break;
1139    case 23 : current_object->add_power(lnumber_value(CAR(args))); break;
1140    case 24 : current_object->add_hp(lnumber_value(CAR(args))); break;
1141
1142    case 27 :
1143    { current_object->drawer(); return 1; } break;
1144    case 28 :
1145    { return (dev & EDIT_MODE); } break;
1146    case 29 :
1147    { current_object->draw_above(current_view); return 1; } break;
1148    case 30 : return current_object->x; break;
1149    case 31 : return current_object->y; break;
1150    case 32 :
1151    { int32_t v=lnumber_value(CAR(args));
1152      current_object->x=v;
1153//      current_object->last_x=v;
1154      return 1;
1155    } break;
1156    case 33 :
1157    { int32_t v=lnumber_value(CAR(args));
1158      current_object->y=v;
1159//      current_object->last_y=v;
1160      return 1;
1161    } break;
1162
1163    case 34 : { return current_level->push_characters(current_object,lnumber_value(CAR(args)),
1164                        lnumber_value(CAR(CDR(args))));
1165          } break;
1166
1167    case 37 :
1168    {
1169      int32_t s=lnumber_value(CAR(args));
1170      current_object->set_state((character_state)s);
1171      return (s==current_object->state);
1172    } break;
1173
1174    case 38 : return current_level->attacker(current_object)->x; break;
1175    case 39 : return current_level->attacker(current_object)->y; break;
1176    case 40 : current_object->change_aitype(lnumber_value(CAR(args))); return 1; break;
1177
1178    case 42 : return current_object->xvel(); break;
1179    case 43 : return current_object->yvel(); break;
1180    case 44 : current_object->set_xvel(lnumber_value(CAR(args))); return 1; break;
1181    case 45 : current_object->set_yvel(lnumber_value(CAR(args))); return 1; break;
1182    case 46 : if (current_level->attacker(current_object)->x>current_object->x) return -1;
1183              else return 1; break;
1184    case 47 : return lnumber_value(CAR(args))&BLOCKED_LEFT; break;
1185    case 48 : return lnumber_value(CAR(args))&BLOCKED_RIGHT; break;
1186
1187    case 50 : dev_cont->add_palette(args); break;
1188    case 51 : write_PCX(screen,pal,lstring_value(CAR(args))); break;
1189
1190    case 52 : the_game->zoom=lnumber_value(CAR(args)); the_game->draw(); break;
1191    case 55 : the_game->show_help(lstring_value(CAR(args))); break;
1192
1193    case 56 : return current_object->direction; break;
1194    case 57 : current_object->direction=lnumber_value(CAR(args)); break;
1195    case 58 :
1196    {
1197      int x1=lnumber_value(CAR(args));
1198      if (!current_object->controller())
1199      { lbreak("set_freeze_time : object is not a focus\n"); }
1200      else current_object->controller()->freeze_time=x1; return 1;
1201    } break;
1202    case 59 : return menu(args,big_font); break;
1203    case 60 :
1204    { event ev; dev_cont->do_command(lstring_value(CAR(args)),ev); return 1; } break;
1205    case 61 : the_game->set_state(lnumber_value(CAR(args))); break;
1206
1207    case 62 :
1208    {
1209      int x1=lnumber_value(CAR(args)); args=CDR(args);
1210      int y1=lnumber_value(CAR(args)); args=CDR(args);
1211      int x2=lnumber_value(CAR(args)); args=CDR(args);
1212      int y2=lnumber_value(CAR(args));
1213      scene_director.set_text_region(x1,y1,x2,y2);
1214    } break;
1215    case 63 : scene_director.set_frame_speed(lnumber_value(CAR(args))); break;
1216    case 64 : scene_director.set_scroll_speed(lnumber_value(CAR(args))); break;
1217    case 65 : scene_director.set_pan_speed(lnumber_value(CAR(args))); break;
1218    case 66 : scene_director.scroll_text(lstring_value(CAR(args))); break;
1219    case 67 : scene_director.set_pan(lnumber_value(CAR(args)),
1220                 lnumber_value(CAR(CDR(args))),
1221                 lnumber_value(CAR(CDR(CDR(args))))); break;
1222    case 68 : scene_director.wait(CAR(args)); break;
1223
1224
1225    case 73 : the_game->set_level(new level(lnumber_value(CAR(args)),
1226                        lnumber_value(CAR(CDR(args))),
1227                        lstring_value(CAR(CDR(CDR(args)))))); break;
1228    case 74 :
1229    { if (current_level) delete current_level;
1230      current_level=new level(100,100,"new_level");
1231    } break;
1232    case 75 :
1233    {
1234      int amount=lnumber_value(CAR(args)); args=CDR(args);
1235      game_object *o=((game_object *)lpointer_value(CAR(args))); args=CDR(args);
1236      int xv=0,yv=0;
1237      if (args)
1238      {
1239    xv=lnumber_value(CAR(args)); args=CDR(args);
1240    yv=lnumber_value(CAR(args));
1241      }
1242      o->do_damage(amount,current_object,current_object->x,current_object->y,xv,yv);
1243    } break;
1244    case 76 : return current_object->hp(); break;
1245    case 77 :
1246    {
1247      game_object *o=(game_object *)lpointer_value(CAR(args));
1248      if (!o->controller())
1249    printf("set shift : object is not a focus\n");
1250      else o->controller()->shift_down=lnumber_value(CAR(CDR(args))); return 1;
1251    } break;
1252    case 78 :
1253    {
1254      game_object *o=(game_object *)lpointer_value(CAR(args));
1255      if (!o->controller())
1256    printf("set shift : object is not a focus\n");
1257      else o->controller()->shift_right=lnumber_value(CAR(CDR(args))); return 1;
1258    } break;
1259    case 79 : current_object->set_gravity(lnumber_value(CAR(args))); return 1; break;
1260    case 80 : return current_object->tick(); break;
1261    case 81 : current_object->set_xacel((lnumber_value(CAR(args)))); return 1; break;
1262    case 82 : current_object->set_yacel((lnumber_value(CAR(args)))); return 1; break;
1263    case 84 : set_local_players(lnumber_value(CAR(args))); return 1; break;
1264    case 85 : return total_local_players(); break;
1265    case 86 : light_detail=lnumber_value(CAR(args)); return 1; break;
1266    case 87 : return light_detail; break;
1267    case 88 : morph_detail=lnumber_value(CAR(args)); return 1; break;
1268    case 89 : return morph_detail; break;
1269    case 90 : current_object->morph_into(lnumber_value(CAR(args)),NULL,
1270                     lnumber_value(CAR(CDR(args))),
1271                     lnumber_value(CAR(CDR(CDR(args))))); return 1; break;
1272    case 91 : current_object->add_object((game_object *)lpointer_value(CAR(args))); return 1; break;
1273    case 92 :
1274    {
1275      int32_t cx1,x1=lnumber_value(CAR(args)); args=lcdr(args);
1276      int32_t cy1,y1=lnumber_value(CAR(args)); args=lcdr(args);
1277      int32_t cx2,x2=lnumber_value(CAR(args)); args=lcdr(args);
1278      int32_t cy2,y2=lnumber_value(CAR(args)); args=lcdr(args);
1279      int32_t c=lnumber_value(CAR(args));
1280      the_game->game_to_mouse(x1,y1,current_view,cx1,cy1);
1281      the_game->game_to_mouse(x2,y2,current_view,cx2,cy2);
1282      screen->line(cx1,cy1,cx2,cy2,c);
1283      return 1;
1284    } break;
1285    case 93 : return wm->dark_color(); break;
1286    case 94 : return wm->medium_color(); break;
1287    case 95 : return wm->bright_color(); break;
1288
1289    case 99 : current_object->remove_object((game_object *)lpointer_value(CAR(args))); return 1; break;
1290    case 100 : current_object->add_light((light_source *)lpointer_value(CAR(args))); return 1; break;
1291    case 101 : current_object->remove_light((light_source *)lpointer_value(CAR(args))); return 1; break;
1292    case 102 : return current_object->total_objects(); break;
1293    case 103 : return current_object->total_lights(); break;
1294
1295    case 104 :
1296    { light_source *l=(light_source *)lpointer_value(CAR(args));
1297      int32_t x=lnumber_value(CAR(CDR(args)));
1298      if (x>=1)
1299        l->inner_radius=x;
1300      l->calc_range();
1301      return 1;
1302    } break;
1303    case 105 :
1304    { light_source *l=(light_source *)lpointer_value(CAR(args));
1305      int32_t x=lnumber_value(CAR(CDR(args)));
1306      if (x>l->inner_radius)
1307        l->outer_radius=x;
1308      l->calc_range();
1309      return 1;
1310    } break;
1311    case 106 :
1312    { light_source *l=(light_source *)lpointer_value(CAR(args));
1313      l->x=lnumber_value(CAR(CDR(args)));
1314      l->calc_range();
1315      return 1;
1316    } break;
1317    case 107 :
1318    { light_source *l=(light_source *)lpointer_value(CAR(args));
1319      l->y=lnumber_value(CAR(CDR(args)));
1320      l->calc_range();
1321      return 1;
1322    } break;
1323    case 108 :
1324    { light_source *l=(light_source *)lpointer_value(CAR(args));
1325      l->xshift=lnumber_value(CAR(CDR(args)));
1326      l->calc_range();
1327      return 1;
1328    } break;
1329    case 109 :
1330    { light_source *l=(light_source *)lpointer_value(CAR(args));
1331      l->yshift=lnumber_value(CAR(CDR(args)));
1332      l->calc_range();
1333      return 1;
1334    } break;
1335    case 110 : return ((light_source *)lpointer_value(CAR(args)))->inner_radius; break;
1336    case 111 : return ((light_source *)lpointer_value(CAR(args)))->outer_radius; break;
1337    case 112 : return ((light_source *)lpointer_value(CAR(args)))->x; break;
1338    case 113 : return ((light_source *)lpointer_value(CAR(args)))->y; break;
1339    case 114 : return ((light_source *)lpointer_value(CAR(args)))->xshift; break;
1340    case 115 : return ((light_source *)lpointer_value(CAR(args)))->yshift; break;
1341    case 116 : return current_object->xacel(); break;
1342    case 117 : return current_object->yacel(); break;
1343    case 118 : current_level->remove_light((light_source *)lpointer_value(CAR(args))); break;
1344    case 119 : current_object->set_fx(lnumber_value(CAR(args))); break;
1345    case 120 : current_object->set_fy(lnumber_value(CAR(args))); break;
1346    case 121 : current_object->set_fxvel(lnumber_value(CAR(args))); break;
1347    case 122 : current_object->set_fyvel(lnumber_value(CAR(args))); break;
1348    case 123 : current_object->set_fxacel(lnumber_value(CAR(args))); break;
1349    case 124 : current_object->set_fyacel(lnumber_value(CAR(args))); break;
1350    case 125 : return current_object->picture()->width(); break;
1351    case 126 : return current_object->picture()->height(); break;
1352    case 127 : { dprintf("trap\n"); } break;   // I use this to set gdb break points
1353    case 128 : { return current_level->platform_push(current_object,lnumber_value(CAR(args)),
1354                        lnumber_value(CAR(CDR(args))));
1355                        } break;
1356    case 133 :  // def_sound
1357    {
1358      LSymbol *sym=NULL;
1359      if (CDR(args))
1360      {
1361    sym=(LSymbol *)lcar(args);
1362    if (item_type(sym)!=L_SYMBOL)
1363    {
1364      lbreak("expecting first arg to def-character to be a symbol!\n");
1365      exit(0);
1366    }
1367    args=CDR(args);
1368      }
1369
1370      int sp=current_space;
1371      current_space=PERM_SPACE;
1372      int id=cache.reg(lstring_value(lcar(args)),NULL,SPEC_EXTERN_SFX,1);
1373      if (sym)
1374        sym->SetNumber(id);    // set the symbol value to sfx id
1375      current_space=sp;
1376      return id;
1377    } break;
1378    case 134 :  // play_sound
1379    {
1380      void *a=args;
1381      PtrRef r1(a);
1382      int id=lnumber_value(lcar(a));
1383      if (id<0) return 0;
1384      a=CDR(a);
1385      if (!a)
1386        cache.sfx(id)->play(127);
1387      else
1388      {
1389    int vol=lnumber_value(lcar(a)); a=CDR(a);
1390    if (a)
1391    {
1392      int32_t x=lnumber_value(lcar(a)); a=CDR(a);
1393      if (!a)
1394      {
1395        ((LObject *)args)->Print();
1396        lbreak("expecting y after x in play_sound\n");
1397        exit(1);
1398      }
1399      int32_t y=lnumber_value(lcar(a));
1400      the_game->play_sound(id,vol,x,y);
1401    } else cache.sfx(id)->play(vol);
1402      }
1403
1404    } break;
1405
1406    case 137 : return defun_pseq(args); break;
1407    case 138 :
1408    { int id=lnumber_value(CAR(args)); args=CDR(args);
1409      int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1410      int32_t y=lnumber_value(CAR(args)); args=CDR(args);
1411      int32_t dir=lnumber_value(CAR(args));
1412      add_panim(id,x,y,dir);
1413    } break;
1414    case 142 :
1415    {
1416      int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1417      if (x<0 || x>=total_weapons)
1418      {
1419    lbreak("weapon out of range (%d)\n",x);
1420    exit(0);
1421      }
1422      return weapon_types[x];
1423    } break;
1424    case 143 :
1425    {
1426      int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1427      int32_t y=lnumber_value(CAR(args)); args=CDR(args);
1428      int32_t r=lnumber_value(CAR(args)); args=CDR(args);
1429      int32_t m=lnumber_value(CAR(args)); args=CDR(args);
1430      game_object *o=(game_object *)lpointer_value(CAR(args)); args=CDR(args);
1431      int32_t mp=lnumber_value(CAR(args));
1432      current_level->hurt_radius(x,y,r,m,current_object,o,mp);
1433    } break;
1434
1435    case 144 :
1436    {
1437      view *v=current_object->controller();
1438      if (!v) dprintf("Can't add weapons for non-players\n");
1439      else
1440      {
1441    int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1442    int32_t y=lnumber_value(CAR(args)); args=CDR(args);
1443    if (x<0 || x>=total_weapons)
1444    { lbreak("weapon out of range (%d)\n",x); exit(0); }
1445    v->add_ammo(x,y);
1446      }
1447    } break;
1448    case 145 :
1449    {
1450      view *v=current_object->controller();
1451      if (!v) return 0;
1452      else return v->weapon_total(lnumber_value(CAR(args)));
1453    } break;
1454    case 146 :
1455    {
1456      view *v=current_object->controller();
1457      if (!v) return 0; else return v->current_weapon;
1458    } break;
1459    case 147 :
1460    {
1461      view *v=current_object->controller();
1462      if (!v) { lbreak("current_weapon_type : object cannot hold weapons\n");
1463        return 0; }
1464      else return v->current_weapon;
1465    } break;
1466    case 148 : return lnumber_value(CAR(args))&BLOCKED_UP; break;
1467    case 149 : return lnumber_value(CAR(args))&BLOCKED_DOWN; break;
1468    case 150 :
1469    {
1470      view *v=current_object->controller();
1471      int x=lnumber_value(CAR(args));
1472      if (x<0 || x>=total_weapons)
1473      { lbreak("weapon out of range (%d)\n",x); exit(0); }
1474      if (v) v->give_weapon(x);
1475    } break;
1476    case 151 :
1477    {
1478      int a=lnumber_value(CAR(args));
1479      if (a<0 || a>=TOTAL_ABILITIES)
1480      {
1481    ((LObject *)args)->Print();
1482    lbreak("bad ability number for get_ability, should be 0..%d, not %d\n",
1483        TOTAL_ABILITIES,a);
1484    exit(0);
1485      }
1486      return get_ability(current_object->otype,(ability)a);
1487    } break;
1488    case 152 :
1489    {
1490      view *v=current_object->controller();
1491      if (!v) dprintf("Can't use reset_player on non-players\n");
1492      else
1493        v->reset_player();
1494    } break;
1495    case 153 :
1496    {
1497      game_object *o=(game_object *)lpointer_value(CAR(args));
1498      int32_t x=o->x-current_object->x,
1499        y=-(o->y-o->picture()->height()/2-(current_object->y-(current_object->picture()->height()/2)));
1500      return lisp_atan2(y,x);
1501    } break;
1502    case 154 :
1503    {
1504      int32_t ang=lnumber_value(CAR(args)); args=CDR(args);
1505      int32_t mag=lfixed_point_value(CAR(args));
1506      int32_t xvel=(lisp_cos(ang)>>8)*(mag>>8);
1507      current_object->set_xvel(xvel>>16);
1508      current_object->set_fxvel((xvel&0xffff)>>8);
1509      int32_t yvel=-(lisp_sin(ang)>>8)*(mag>>8);
1510      current_object->set_yvel(yvel>>16);
1511      current_object->set_fyvel((yvel&0xffff)>>8);
1512    } break;
1513    case 155 :
1514    {
1515      int tframes=current_object->total_frames(),f;
1516
1517      int32_t ang1=lnumber_value(CAR(args)); args=CDR(args);
1518      if (ang1<0) ang1=(ang1%360)+360;
1519      else if (ang1>=360) ang1=ang1%360;
1520      int32_t ang2=lnumber_value(CAR(args)); args=CDR(args);
1521      if (ang2<0) ang2=(ang2%360)+360;
1522      else if (ang2>=360) ang2=ang2%360;
1523
1524      int32_t ang=(lnumber_value(CAR(args))+90/tframes)%360;
1525      if (ang1>ang2)
1526      {
1527        if (ang<ang1 && ang>ang2)
1528      return 0;
1529    else if (ang>=ang1)
1530      f=(ang-ang1)*tframes/(359-ang1+ang2+1);
1531    else
1532      f=(359-ang1+ang)*tframes/(359-ang1+ang2+1);
1533      } else if (ang<ang1 || ang>ang2)
1534        return 0;
1535      else f=(ang-ang1)*tframes/(ang2-ang1+1);
1536      if (current_object->direction>0)
1537        current_object->current_frame=f;
1538      else
1539        current_object->current_frame=tframes-f-1;
1540      return 1;
1541    } break;
1542    case 156 :
1543    {
1544      int x=current_object->current_frame;
1545      current_object->set_state((character_state)lnumber_value(CAR(args)));
1546      current_object->current_frame=x;
1547    } break;
1548
1549    case 168 : if (current_object->morph_status()) return 1; else return 0; break;
1550    case 169 :
1551    {
1552      int32_t am=lnumber_value(CAR(args)); args=CDR(args);
1553      game_object *from=(game_object *)lpointer_value(CAR(args)); args=CDR(args);
1554      int32_t hitx=lnumber_value(CAR(args)); args=CDR(args);
1555      int32_t hity=lnumber_value(CAR(args)); args=CDR(args);
1556      int32_t px=lnumber_value(CAR(args)); args=CDR(args);
1557      int32_t py=lnumber_value(CAR(args)); args=CDR(args);
1558      current_object->damage_fun(am,from,hitx,hity,px,py);
1559    } break;
1560    case 170 : return current_object->gravity(); break;
1561    case 171 :
1562    {
1563      view *v=current_object->controller();
1564      if (!v) dprintf("make_view_solid : object has no view\n");
1565      else
1566        v->draw_solid=lnumber_value(CAR(args));
1567    } break;
1568    case 172 :
1569    {
1570      void *a=args;
1571      int r=lnumber_value(CAR(a)); a=CDR(a);
1572      int g=lnumber_value(CAR(a)); a=CDR(a);
1573      int b=lnumber_value(CAR(a));
1574      if (r<0 || b<0 || g<0 || r>255 || g>255 || b>255)
1575      {
1576    ((LObject *)args)->Print();
1577    lbreak("color out of range (0..255) in color lookup\n");
1578    exit(0);
1579      }
1580      return color_table->lookup_color(r>>3,g>>3,b>>3);
1581    } break;
1582    case 173 :
1583    {
1584      view *v=current_object->controller();
1585      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
1586      else return v->x_suggestion;
1587    } break;
1588    case 174 :
1589    {
1590      view *v=current_object->controller();
1591      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
1592      else return v->y_suggestion;
1593    } break;
1594    case 175 :
1595    {
1596      view *v=current_object->controller();
1597      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
1598      else return v->b1_suggestion;
1599    } break;
1600    case 176 :
1601    {
1602      view *v=current_object->controller();
1603      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
1604      else return v->b2_suggestion;
1605    } break;
1606    case 177 :
1607    {
1608      view *v=current_object->controller();
1609      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
1610      else return v->b3_suggestion;
1611    } break;
1612    case 178 :
1613    {
1614      bg_xmul=lnumber_value(CAR(args)); args=CDR(args);
1615      bg_xdiv=lnumber_value(CAR(args)); args=CDR(args);
1616      bg_ymul=lnumber_value(CAR(args)); args=CDR(args);
1617      bg_ydiv=lnumber_value(CAR(args));
1618      if (bg_xdiv==0) { bg_xdiv=1; ((LObject *)args)->Print(); dprintf("bg_set_scroll : cannot set xdiv to 0\n"); }
1619      if (bg_ydiv==0) { bg_ydiv=1; ((LObject *)args)->Print(); dprintf("bg_set_scroll : cannot set ydiv to 0\n"); }
1620    } break;
1621    case 179 :
1622    {
1623      view *v=lget_view(CAR(args),"set_ambient_light");       args=CDR(args);
1624      int32_t x=lnumber_value(CAR(args));
1625      if (x>=0 && x<64) v->ambient=x;
1626    } break;
1627    case 180 : return lget_view(CAR(args),"ambient_light")->ambient; break;
1628    case 181 :
1629    {
1630      int x=current_object->total_objects();
1631      game_object *who=(game_object *)lpointer_value(CAR(args));
1632      for (int i=0; i<x; i++)
1633        if (current_object->get_object(i)==who) return 1;
1634      return 0;
1635    } break;
1636    case 182 : current_object->change_type(lnumber_value(CAR(args))); break;
1637    case 184 : return current_object->current_frame; break;
1638
1639    case 185 : return current_object->fx(); break;
1640    case 186 : return current_object->fy(); break;
1641    case 187 : return current_object->fxvel(); break;
1642    case 188 : return current_object->fyvel(); break;
1643    case 189 : return current_object->fxacel(); break;
1644    case 190 : return current_object->fyacel(); break;
1645    case 191 :
1646    {
1647//      char *fn=lstring_value(CAR(args)); args=CDR(args);
1648//      stat_bar=cache.reg_object(fn,CAR(args),SPEC_IMAGE,1);
1649    } break;
1650    case 192 :
1651    {
1652      int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1653      int32_t y=lnumber_value(CAR(args)); args=CDR(args);
1654      int32_t type=lnumber_value(CAR(args));
1655      if (x<0 || y<0 || x>=current_level->foreground_width() || y>=current_level->foreground_width())
1656        lbreak("%d %d is out of range of fg map",x,y);
1657      else
1658        current_level->put_fg(x,y,type);
1659    } break;
1660    case 193 :
1661    {
1662      int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1663      int32_t y=lnumber_value(CAR(args));
1664      if (x<0 || y<0 || x>=current_level->foreground_width() || y>=current_level->foreground_width())
1665        lbreak("%d %d is out of range of fg map",x,y);
1666      else return current_level->get_fg(x,y);
1667    } break;
1668    case 194 :
1669    {
1670      int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1671      int32_t y=lnumber_value(CAR(args)); args=CDR(args);
1672      int32_t type=lnumber_value(CAR(args));
1673      if (x<0 || y<0 || x>=current_level->background_width() || y>=current_level->background_width())
1674        lbreak("%d %d is out of range of fg map",x,y);
1675      else
1676        current_level->put_bg(x,y,type);
1677    } break;
1678    case 195 :
1679    {
1680      int32_t x=lnumber_value(CAR(args)); args=CDR(args);
1681      int32_t y=lnumber_value(CAR(args));
1682      if (x<0 || y<0 || x>=current_level->background_width() || y>=current_level->background_width())
1683        lbreak("%d %d is out of range of fg map",x,y);
1684      else return current_level->get_bg(x,y);
1685    } break;
1686    case 196 : load_tiles(args); break;
1687    case 197 :
1688    {
1689      bFILE *fp=open_file(lstring_value(CAR(args)),"rb");
1690      if (fp->open_failure())
1691      {
1692    delete fp;
1693        lbreak("load_palette : could not open file %s for reading",lstring_value(CAR(args)));
1694    exit(1);
1695      } else
1696      {
1697    spec_directory sd(fp);
1698    spec_entry *se=sd.find(SPEC_PALETTE);
1699    if (!se) lbreak("File %s has no palette!\n",lstring_value(CAR(args)));
1700    else
1701    {
1702      if (pal) delete pal;
1703      pal=new palette(se,fp);
1704    }
1705    delete fp;
1706      }
1707    } break;
1708    case 198 :
1709    {
1710      bFILE *fp=open_file(lstring_value(CAR(args)),"rb");
1711      if (fp->open_failure())
1712      {
1713    delete fp;
1714        lbreak("load_color_filter : could not open file %s for reading",lstring_value(CAR(args)));
1715    exit(1);
1716      } else
1717      {
1718    spec_directory sd(fp);
1719    spec_entry *se=sd.find(SPEC_COLOR_TABLE);
1720    if (!se) lbreak("File %s has no color filter!",lstring_value(CAR(args)));
1721    else
1722    {
1723      if (color_table) delete color_table;
1724      color_table=new color_filter(se,fp);
1725    }
1726    delete fp;
1727      }
1728    } break;
1729    case 199 :
1730    {
1731      current_start_type=lnumber_value(CAR(args));
1732      set_local_players(1);
1733    } break;
1734    case 200 :
1735    {
1736      int32_t xv=lnumber_value(CAR(args));  args=CDR(args);
1737      int32_t yv=lnumber_value(CAR(args));  args=CDR(args);
1738      int top=2;
1739      if (args)
1740        if (!CAR(args)) top=0;
1741
1742      int32_t oxv=xv,oyv=yv;
1743      current_object->try_move(current_object->x,current_object->y,xv,yv,1|top);
1744      current_object->x+=xv;
1745      current_object->y+=yv;
1746      return (oxv==xv && oyv==yv);
1747    } break;
1748    case 201 :
1749    {
1750      int32_t x=lnumber_value(CAR(args));
1751      return figures[current_object->otype]->get_sequence((character_state)x)->length();
1752    } break;
1753    case 202 :
1754    {
1755      int32_t x1=lnumber_value(CAR(args)); args=CDR(args);
1756      int32_t y1=lnumber_value(CAR(args)); args=CDR(args);
1757      int32_t x2=lnumber_value(CAR(args)); args=CDR(args);
1758      int32_t y2=lnumber_value(CAR(args)); args=CDR(args);
1759      void *block_all=CAR(args);
1760      int32_t nx2=x2,ny2=y2;
1761      current_level->foreground_intersect(x1,y1,x2,y2);
1762      if (x2!=nx2 || y2!=ny2) return 0;
1763
1764      if (block_all)
1765        current_level->all_boundary_setback(current_object,x1,y1,x2,y2);
1766      else
1767        current_level->boundary_setback(current_object,x1,y1,x2,y2);
1768      return (x2==nx2 && y2==ny2);
1769
1770    } break;
1771    case 203 :
1772    {
1773      char *fn=lstring_value(CAR(args)); args=CDR(args);
1774      char *name=lstring_value(CAR(args));
1775      big_font_pict=cache.reg(fn,name,SPEC_IMAGE,1);
1776    } break;
1777    case 204 :
1778    {
1779      char *fn=lstring_value(CAR(args)); args=CDR(args);
1780      char *name=lstring_value(CAR(args));
1781      small_font_pict=cache.reg(fn,name,SPEC_IMAGE,1);
1782    } break;
1783    case 205 :
1784    {
1785      char *fn=lstring_value(CAR(args)); args=CDR(args);
1786      char *name=lstring_value(CAR(args));
1787      console_font_pict=cache.reg(fn,name,SPEC_IMAGE,1);
1788    } break;
1789    case 206 :
1790    {
1791      int32_t x=lnumber_value(CAR(args));
1792      if (x<current_object->total_frames())
1793        current_object->current_frame=x;
1794      else
1795    lbreak("%d out of range for set_current_frame",x);
1796    } break;
1797
1798    case 208 :
1799    {
1800      current_object->draw_trans(lnumber_value(CAR(args)),lnumber_value(CAR(CDR(args))));
1801    } break;
1802    case 209 :
1803    {
1804      current_object->draw_tint(lnumber_value(CAR(args)));
1805    } break;
1806    case 210 :
1807    {
1808      current_object->draw_predator();
1809    } break;
1810    case 211:
1811    { return lget_view(CAR(args),"shift_down")->shift_right; } break;
1812    case 212:
1813    { return lget_view(CAR(args),"shift_right")->shift_down; } break;
1814    case 213 :
1815    { view *v=lget_view(CAR(args),"set_no_scroll_range"); args=CDR(args);
1816      v->no_xleft=lnumber_value(CAR(args)); args=CDR(args);
1817      v->no_ytop=lnumber_value(CAR(args));  args=CDR(args);
1818      v->no_xright=lnumber_value(CAR(args)); args=CDR(args);
1819      v->no_ybottom=lnumber_value(CAR(args));
1820    } break;
1821    case 215 :
1822    {
1823      char *fn=lstring_value(CAR(args)); args=CDR(args);
1824      char *name=lstring_value(CAR(args)); args=CDR(args);
1825      return cache.reg(fn,name,SPEC_IMAGE,1);
1826    } break;
1827    case 216 :
1828    {
1829      int32_t x1=lnumber_value(CAR(args)); args=lcdr(args);
1830      int32_t y1=lnumber_value(CAR(args)); args=lcdr(args);
1831      int32_t id=lnumber_value(CAR(args));
1832      cache.img(id)->put_image(screen,x1,y1,1);
1833    } break;
1834    case 217 :
1835    {
1836      view *v=current_object->controller();
1837      if (!v) lbreak("object has no view : view_x1");
1838      else return v->cx1;
1839    } break;
1840    case 218 :
1841    {
1842      view *v=current_object->controller();
1843      if (!v) lbreak("object has no view : view_x1");
1844      else return v->cy1;
1845    } break;
1846    case 219 :
1847    {
1848      view *v=current_object->controller();
1849      if (!v) lbreak("object has no view : view_x1");
1850      else return v->cx2;
1851    } break;
1852    case 220 :
1853    {
1854      view *v=current_object->controller();
1855      if (!v) lbreak("object has no view : view_x1");
1856      else return v->cy2;
1857    } break;
1858    case 221 :
1859    {
1860      view *v=current_object->controller();
1861      if (!v) lbreak("object has no view : view_push_down");
1862      else v->last_y-=lnumber_value(CAR(args));
1863    } break;
1864    case 222 :
1865    {
1866      view *v=current_object->controller();
1867      if (!v) lbreak("object has no view : local_player");
1868      else return v->local_player();
1869    } break;
1870    case 223 :
1871    {
1872      char *fn=lstring_value(CAR(args));
1873      current_level->save(fn,1);
1874    } break;
1875    case 224 :
1876    {
1877      current_object->set_hp(lnumber_value(CAR(args)));
1878    } break;
1879    case 225 :
1880    {
1881      char fn[255];
1882      // If a save filename is requested, prepend the savegame directory.
1883      if( strncmp( lstring_value( CAR(args) ), "save", 4 ) == 0 )
1884      {
1885        sprintf( fn, "%s%s", get_save_filename_prefix(), lstring_value( CAR(args) ) );
1886      }
1887      else
1888      {
1889        strcpy( fn, lstring_value(CAR(args)) );
1890      }
1891      the_game->request_level_load(fn);
1892    } break;
1893    case 226 :
1894    {
1895      strcpy(level_file,lstring_value(CAR(args)));
1896    } break;
1897    case 227 :
1898    {
1899      return cache.reg(lstring_value(CAR(args)),"palette",SPEC_PALETTE,1);
1900    } break;
1901    case 228 :
1902    {
1903      palette *p=pal->copy();
1904      uint8_t *addr=(uint8_t *)p->addr();
1905      int r,g,b;
1906      int ra=lnumber_value(CAR(args)); args=CDR(args);
1907      int ga=lnumber_value(CAR(args)); args=CDR(args);
1908      int ba=lnumber_value(CAR(args));
1909      for (int i=0; i<256; i++)
1910      {
1911    r=(int)*addr+ra; if (r>255) r=255; else if (r<0) r=0; *addr=(uint8_t)r; addr++;
1912    g=(int)*addr+ga; if (g>255) g=255; else if (g<0) g=0; *addr=(uint8_t)g; addr++;
1913    b=(int)*addr+ba; if (b>255) b=255; else if (b<0) b=0; *addr=(uint8_t)b; addr++;
1914      }
1915      p->load();
1916      delete p;
1917    } break;
1918    case 229 :
1919    {
1920      view *v=current_object->controller();
1921      if (!v) lbreak("object has no view : local_player");
1922      else return v->player_number;
1923    } break;
1924    case 230 :
1925    {
1926      view *v=current_object->controller();
1927      if (!v) lbreak("object has no view : local_player");
1928      else
1929      {
1930    int32_t x=lnumber_value(CAR(args));
1931    if (x<0 || x>=total_weapons)
1932    { lbreak("weapon out of range (%d)\n",x); exit(0); }
1933    v->current_weapon=x;
1934      }
1935    } break;
1936    case 231 :
1937    {
1938      view *v=current_object->controller();
1939      if (!v) lbreak("object has no view : local_player");
1940      else return v->has_weapon(lnumber_value(CAR(args)));
1941    } break;
1942    case 232 :
1943    {
1944      ambient_ramp+=lnumber_value(CAR(args));
1945    } break;
1946
1947    case 233 :
1948    { int x=0; view *v=player_list; for (; v; v=v->next,x++); return x; } break;
1949
1950    case 234 :
1951    {
1952      int32_t cx1,x1=lnumber_value(CAR(args)); args=lcdr(args);
1953      int32_t cy1,y1=lnumber_value(CAR(args)); args=lcdr(args);
1954      int32_t cx2,x2=lnumber_value(CAR(args)); args=lcdr(args);
1955      int32_t cy2,y2=lnumber_value(CAR(args)); args=lcdr(args);
1956      int32_t c=lnumber_value(CAR(args)); args=lcdr(args);
1957      int32_t s=lnumber_value(CAR(args));
1958      the_game->game_to_mouse(x1,y1,current_view,cx1,cy1);
1959      the_game->game_to_mouse(x2,y2,current_view,cx2,cy2);
1960      scatter_line(cx1,cy1,cx2,cy2,c,s);
1961      return 1;
1962
1963    } break;
1964    case 235 :
1965    { if (current_level) return current_level->tick_counter();
1966      else return 0; } break;
1967    case 236 :
1968    {
1969      return current_object->controller()!=NULL;
1970    } break;
1971    case 237 :
1972    {
1973      rand_on+=lnumber_value(CAR(args)); return 1;
1974    } break;
1975    case 238 :
1976    {
1977      return current_object->total_frames();
1978    } break;
1979    case 239 :
1980    { current_level->to_front(current_object); } break;
1981    case 240 :
1982    { current_level->to_back(current_object); } break;
1983    case 241 :
1984    {
1985      view *v=current_object->controller();
1986      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
1987      else return v->pointer_x;
1988    } break;
1989    case 242 :
1990    {
1991      view *v=current_object->controller();
1992      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
1993      else return v->pointer_y;
1994    } break;
1995    case 243 :
1996    {
1997      if (player_list->next || demo_man.current_state()!=demo_manager::NORMAL)
1998        return 0;
1999      else
2000        return (frame_panic>10);
2001    } break;
2002    case 244 :
2003    {
2004      int32_t cx1,x1=lnumber_value(CAR(args)); args=lcdr(args);
2005      int32_t cy1,y1=lnumber_value(CAR(args)); args=lcdr(args);
2006      int32_t cx2,x2=lnumber_value(CAR(args)); args=lcdr(args);
2007      int32_t cy2,y2=lnumber_value(CAR(args)); args=lcdr(args);
2008      int32_t c1=lnumber_value(CAR(args)); args=lcdr(args);
2009      int32_t c2=lnumber_value(CAR(args)); args=lcdr(args);
2010      int32_t s=lnumber_value(CAR(args));
2011      the_game->game_to_mouse(x1,y1,current_view,cx1,cy1);
2012      the_game->game_to_mouse(x2,y2,current_view,cx2,cy2);
2013      ascatter_line(cx1,cy1,cx2,cy2,c1,c2,s);
2014      return 1;
2015
2016    } break;
2017    case 245 :
2018    {
2019      return rand_on;
2020    } break;
2021    case 246 :
2022    {
2023      rand_on=lnumber_value(CAR(args));
2024    } break;
2025    case 247 :
2026    {
2027      int32_t cx1=lnumber_value(CAR(args)); args=lcdr(args);
2028      int32_t cy1=lnumber_value(CAR(args)); args=lcdr(args);
2029      int32_t cx2=lnumber_value(CAR(args)); args=lcdr(args);
2030      int32_t cy2=lnumber_value(CAR(args)); args=lcdr(args);
2031      int32_t c1=lnumber_value(CAR(args)); args=lcdr(args);
2032      screen->bar(cx1,cy1,cx2,cy2,c1);
2033    } break;
2034    case 248 :
2035    {
2036      return start_argc;
2037    } break;
2038    case 249 :
2039    {
2040      if ((sound_avail&MUSIC_INITIALIZED))
2041      {
2042    char *fn=lstring_value(CAR(args));
2043    if (current_song)
2044    {
2045      if (current_song->playing())
2046      current_song->stop();
2047      delete current_song;
2048    }
2049    current_song=new song(fn);
2050    current_song->play(music_volume);
2051    dprintf("Playing %s at volume %d\n",fn,music_volume);
2052      }
2053    } break;
2054    case 250 :
2055    {
2056      if (current_song && current_song->playing())
2057        current_song->stop();
2058      delete current_song;
2059      current_song=NULL;
2060    } break;
2061    case 251 : return current_object->targetable(); break;
2062    case 252 : current_object->set_targetable( CAR(args)==NULL ? 0 : 1); break;
2063    case 253 : show_stats(); break;
2064    case 254 :
2065    {
2066      view *v=current_object->controller();
2067      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2068      else return v->kills;
2069    } break;
2070    case 255 :
2071    {
2072      view *v=current_object->controller();
2073      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2074      else return v->tkills;
2075    } break;
2076    case 256 :
2077    {
2078      view *v=current_object->controller();
2079      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2080      else return v->secrets;
2081    } break;
2082    case 257 :
2083    {
2084      view *v=current_object->controller();
2085      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2086      else return v->tsecrets;
2087    } break;
2088    case 258 :
2089    {
2090      view *v=current_object->controller();
2091      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2092      else v->kills=lnumber_value(CAR(args));
2093    } break;
2094    case 259 :
2095    {
2096      view *v=current_object->controller();
2097      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2098      else v->tkills=lnumber_value(CAR(args));
2099    } break;
2100    case 260 :
2101    {
2102      view *v=current_object->controller();
2103      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2104      else v->secrets=lnumber_value(CAR(args));
2105    } break;
2106    case 261 :
2107    {
2108      view *v=current_object->controller();
2109      if (!v) { ((LObject *)args)->Print(); printf("get_player_inputs : object has no view!\n"); }
2110      else v->tsecrets=lnumber_value(CAR(args));
2111    } break;
2112    case 262 :
2113    {
2114      the_game->request_end();
2115    } break;
2116    case 263 :
2117    {
2118      the_game->reset_keymap();
2119      return load_game(1,symbol_str("SAVE")); //get_save_spot(); shit
2120    } break;
2121    case 264 :
2122    {
2123      printf("mem_report is deprecated\n");
2124    } break;
2125    case 265 :
2126    {
2127      return ENGINE_MAJOR;
2128    } break;
2129    case 266 :
2130    {
2131      return ENGINE_MINOR;
2132    } break;
2133    case 267 :
2134    {
2135      current_object->draw_double_tint(lnumber_value(CAR(args)),lnumber_value(CAR(CDR(args))));
2136    } break;
2137    case 268 :
2138    {
2139      return cache.img(lnumber_value(CAR(args)))->width();
2140    } break;
2141    case 269 :
2142    {
2143      return cache.img(lnumber_value(CAR(args)))->height();
2144    } break;
2145    case 270 :
2146    {
2147      return current_level->foreground_width();
2148    } break;
2149    case 271 :
2150    {
2151      return current_level->foreground_height();
2152    } break;
2153    case 272 :
2154    {
2155      return current_level->background_width();
2156    } break;
2157    case 273 :
2158    {
2159      return current_level->background_height();
2160    } break;
2161    case 274 :
2162    {
2163      return get_keycode(lstring_value(CAR(args)));
2164    }
2165    case 275 :
2166    {
2167      int id=lnumber_value(CAR(args));  args=CDR(args);
2168      int x=lnumber_value(CAR(args));  args=CDR(args);
2169      int y=lnumber_value(CAR(args));
2170      c_target=id;
2171      if (screen)
2172        wm->set_mouse_shape(cache.img(c_target)->copy(),x,y);
2173    } break;
2174    case 276 :
2175    {
2176      if (!main_net_cfg) return 0;
2177      return become_server(game_name);
2178    } break;
2179    case 277 :
2180    {
2181      JCFont *fnt=(JCFont *)lpointer_value(CAR(args)); args=CDR(args);
2182      int32_t x=lnumber_value(CAR(args));       args=CDR(args);
2183      int32_t y=lnumber_value(CAR(args));       args=CDR(args);
2184      char *st=lstring_value(CAR(args));     args=CDR(args);
2185      int color=-1;
2186      if (args)
2187        color=lnumber_value(CAR(args));
2188      fnt->put_string(screen,x,y,st,color);
2189    } break;
2190    case 278 : return ((JCFont *)lpointer_value(CAR(args)))->width(); break;
2191    case 279 : return ((JCFont *)lpointer_value(CAR(args)))->height(); break;
2192    case 280 : if (chat) chat->put_all(lstring_value(CAR(args))); break;
2193    case 281 :
2194    {
2195      view *v=current_object->controller();
2196      if (!v) { lbreak("get_player_name : object has no view!\n"); }
2197      else strcpy(v->name,lstring_value(CAR(args)));
2198    } break;
2199    case 282 :
2200    {
2201      int32_t x1=lnumber_value(CAR(args));   args=CDR(args);
2202      int32_t y1=lnumber_value(CAR(args));   args=CDR(args);
2203      int32_t x2=lnumber_value(CAR(args));   args=CDR(args);
2204      int32_t y2=lnumber_value(CAR(args));   args=CDR(args);
2205      int32_t c=lnumber_value(CAR(args));
2206      screen->bar(x1,y1,x2,y2,c);
2207    } break;
2208    case 283 :
2209    {
2210      int32_t x1=lnumber_value(CAR(args));   args=CDR(args);
2211      int32_t y1=lnumber_value(CAR(args));   args=CDR(args);
2212      int32_t x2=lnumber_value(CAR(args));   args=CDR(args);
2213      int32_t y2=lnumber_value(CAR(args));   args=CDR(args);
2214      int32_t c=lnumber_value(CAR(args));
2215      screen->rectangle(x1,y1,x2,y2,c);
2216    } break;
2217    case 284 :
2218    {
2219      if (get_option(lstring_value(CAR(args))))
2220        return 1;
2221      else return 0;
2222    } break;
2223    case 288 :
2224    {
2225      if (CAR(args)) the_game->set_delay(1); else the_game->set_delay(0);
2226    } break;
2227    case 289 :
2228    {
2229      set_login(lstring_value(CAR(args)));
2230    } break;
2231    case 290 :
2232    {
2233      chatting_enabled=1;
2234    } break;
2235    case 291 :
2236    {
2237      demo_start=1;
2238    } break;
2239    case 292 :
2240    {
2241      if (main_net_cfg && main_net_cfg->state==net_configuration::CLIENT)
2242        return 1;
2243    } break;
2244    case 293 :
2245    {
2246      if (main_net_cfg && (main_net_cfg->state==net_configuration::CLIENT || main_net_cfg->state==net_configuration::SERVER))
2247      {
2248    view *v=player_list;
2249    for (; v; v=v->next)
2250       if (v->kills>=main_net_cfg->kills)
2251         return 1;
2252
2253
2254      } else return 0;
2255    } break;
2256    case 294 :
2257    {
2258      view *v=player_list;
2259      for (; v; v=v->next)
2260      {
2261    v->tkills+=v->kills;
2262
2263        v->kills=0;
2264    game_object *o=current_object;
2265    current_object=v->focus;
2266
2267    ((LSymbol *)l_restart_player)->EvalFunction(NULL);
2268    v->reset_player();
2269    v->focus->set_aistate(0);
2270    current_object=o;
2271      }
2272
2273    } break;
2274    case 295 :
2275    {
2276      strncpy(game_name,lstring_value(CAR(args)),sizeof(game_name));
2277      game_name[sizeof(game_name)-1]=0;
2278
2279    } break;
2280    case 296 :
2281    {
2282      if (main_net_cfg)
2283        main_net_cfg->min_players=lnumber_value(CAR(args));
2284    } break;
2285    case 1001: // (set_object_tint)
2286      if(current_object->Controller)
2287        current_object->Controller->set_tint(lnumber_value(CAR(args)));
2288      else
2289        current_object->set_tint(lnumber_value(CAR(args)));
2290      break;
2291    case 1002: //(get_object_tint)
2292      if(current_object->Controller)
2293        return current_object->Controller->get_tint();
2294      else
2295        return current_object->get_tint();
2296      break;
2297    case 1003: //(set_object_team)
2298      if(current_object->Controller)
2299        current_object->Controller->set_team(lnumber_value(CAR(args)));
2300      else
2301        current_object->set_team(lnumber_value(CAR(args)));
2302      break;
2303    case 1004: //(get_object_team)
2304      if(current_object->Controller)
2305        return current_object->Controller->get_team();
2306      else
2307        return current_object->get_team();
2308      break;
2309    default :
2310      printf("Undefined c function %ld\n",number);
2311      return 0;
2312  }
2313  return 0;
2314}
2315
2316int get_lprop_number(void *symbol, int def)  // returns def if symbol undefined or not number type
2317{
2318  void *v=symbol_value(symbol);
2319  if (v)
2320  {
2321    switch (item_type(v))
2322    {
2323      case L_FIXED_POINT :
2324      case L_NUMBER :
2325      { return lnumber_value(v); } break;
2326      default : return def;
2327    }
2328  } else return def;
2329}
2330
2331
Note: See TracBrowser for help on using the repository browser.