--- /dev/null
+0 1 wait
+1 3 move
+2 10 pick_up
+3 3 drop
+4 30 use
extern void init_command_db()
{
char * f_name = "init_command_db()";
- char * err_s = "Trouble in init_cmds() with textfile_sizes().";
+ char * err_s = "Trouble in init_command_db() with textfile_sizes().";
char * path = "config/commands";
FILE * file = try_fopen(path, "r", f_name);
#include "control.h"
#include <stdint.h> /* for uint8_t */
+#include <string.h> /* for strcmp() */
#include "windows.h" /* for cycle_active_win(), shift_active_win(), struct Win,
* struct WinMeta
*/
* growshrink_active_window(),toggle_winconfig(),
* toggle_win_height_type(), toggle_win_width_type()
*/
-#include "map_object_actions.h" /* for player_wait(), move_player(),
- * player_drop(), player_pick()
+#include "map_object_actions.h" /* for struct MapObjAct, actor_wait(),
+ * actor_move(), actor_drop(), actor_pick(),
+ * actor_pick()
*/
#include "command_db.h" /* for is_command_id_shortdsc() */
#include "misc.h" /* for reload_interface_conf(), save_interface_conf(),
- * nav_inventory()
+ * nav_inventory(), turn_over()
*/
+#include "map_objects.h" /* for get_player() */
-/* If "cmd" (either (type = "i") command or (type = "k") keybinding identifier)
- * matches "match" in is_cmd_id_shortdsc() or get_available_keycode_to_action(),
- * execute "f" with provided char arguments and return 1; else only return 0.
+/* If "cmd" matches "match" in get_available_keycode_to_action(), execute "f"
+ * with provided char arguments and return 1; else only return 0.
*/
-static uint8_t try_cmd_0args(char type, int cmd, char * match, void (* f) ());
-static uint8_t try_cmd_1args(char type, int cmd, char * match,
- void (* f) (char), char c);
-static uint8_t try_cmd_2args(char type, int cmd, char * match,
+static uint8_t try_cmd_0args(int cmd, char * match, void (* f) ());
+static uint8_t try_cmd_1args(int cmd, char * match, void (* f) (char), char c);
+static uint8_t try_cmd_2args(int cmd, char * match,
void (* f) (char, char), char c1, char c2);
+/* try_player_cmd() helper, returns world.map_obj_acts action id for "name". */
+static uint8_t get_moa_id_by_name(char * name);
+
+/* If "action" is id of command named "match", set player->arg, ->command and
+ * call turn_over().
+ */
+static uint8_t try_player_cmd(int action, char * match, char * command,
+ uint8_t arg);
+
/* Return pointer to global keybindings or to keybindings for wingeometry config
* (c = "g") or winkeys config (c = "k") or active window's keybindings ("w").
*/
-static uint8_t try_cmd_0args(char type, int cmd, char * match, void (* f) ())
+static uint8_t try_cmd_0args(int cmd, char * match, void (* f) ())
{
- if ( ('k' == type && cmd == get_available_keycode_to_action(match))
- || ('i' == type && is_command_id_shortdsc(cmd, match)))
+ if (cmd == get_available_keycode_to_action(match))
{
f();
return 1;
-static uint8_t try_cmd_1args(char type, int cmd, char * match,
- void (* f) (char), char c)
+static uint8_t try_cmd_1args(int cmd, char * match, void (* f) (char), char c)
{
- if ( ('k' == type && cmd == get_available_keycode_to_action(match))
- || ('i' == type && is_command_id_shortdsc(cmd, match)))
+ if (cmd == get_available_keycode_to_action(match))
{
f(c);
return 1;
-static uint8_t try_cmd_2args(char type, int cmd, char * match,
+static uint8_t try_cmd_2args(int cmd, char * match,
void (* f) (char, char), char c1, char c2)
{
- if ( ('k' == type && cmd == get_available_keycode_to_action(match))
- || ('i' == type && is_command_id_shortdsc(cmd, match)))
+ if (cmd == get_available_keycode_to_action(match))
{
f(c1, c2);
return 1;
+static uint8_t get_moa_id_by_name(char * name)
+{
+ struct MapObjAct * moa = world.map_obj_acts;
+ while (NULL != moa)
+ {
+ if (0 == strcmp(moa->name, name))
+ {
+ break;
+ }
+ moa = moa->next;
+ }
+ exit_err(NULL == moa, "get_moa_id_name() did not find map object action.");
+ return moa->id;
+}
+
+
+
+static uint8_t try_player_cmd(int action, char * match, char * command,
+ uint8_t arg)
+{
+ if (is_command_id_shortdsc(action, match))
+ {
+ struct MapObj * player = get_player();
+ player->arg = arg;
+ player->command = get_moa_id_by_name(command);
+ turn_over(get_command_id(match));
+ return 1;
+ }
+ return 0;
+}
+
+
+
static struct KeyBiData * select_keybidata_pointer(char c)
{
struct KeyBiData * kbd;
+
extern uint8_t player_control_by_id(int action)
{
- if ( try_cmd_0args('i', action, "wait", player_wait)
- || try_cmd_0args('i', action, "drop", player_drop)
- || try_cmd_0args('i', action, "pick", player_pick)
- || try_cmd_0args('i', action, "use", player_use)
- || try_cmd_1args('i', action, "player_u", move_player, 'N')
- || try_cmd_1args('i', action, "player_d", move_player, 'S')
- || try_cmd_1args('i', action, "player_r", move_player, 'E')
- || try_cmd_1args('i', action, "player_l", move_player, 'W'))
+ if ( try_player_cmd(action, "wait", "wait", 0)
+ || try_player_cmd(action, "drop", "drop", world.inventory_select)
+ || try_player_cmd(action, "pick", "pick_up", 0)
+ || try_player_cmd(action, "use", "use", world.inventory_select)
+ || try_player_cmd(action, "player_u", "move", 'N')
+ || try_player_cmd(action, "player_d", "move", 'S')
+ || try_player_cmd(action, "player_r", "move", 'E')
+ || try_player_cmd(action, "player_l", "move", 'W'))
{
return 1;
}
extern uint8_t wingeom_control(int key)
{
- if ( try_cmd_0args('k', key, "to_height_t", toggle_win_height_type)
- || try_cmd_0args('k', key, "to_width_t", toggle_win_width_type)
- || try_cmd_1args('k', key, "grow_h", growshrink_active_window, '*')
- || try_cmd_1args('k', key, "shri_h", growshrink_active_window, '_')
- || try_cmd_1args('k', key, "grow_v", growshrink_active_window, '+')
- || try_cmd_1args('k', key, "shri_v", growshrink_active_window, '-')
- || try_cmd_1args('k', key, "shift_f", shift_active_win, 'f')
- || try_cmd_1args('k', key, "shift_b", shift_active_win, 'b'))
+ if ( try_cmd_0args(key, "to_height_t", toggle_win_height_type)
+ || try_cmd_0args(key, "to_width_t", toggle_win_width_type)
+ || try_cmd_1args(key, "grow_h", growshrink_active_window, '*')
+ || try_cmd_1args(key, "shri_h", growshrink_active_window, '_')
+ || try_cmd_1args(key, "grow_v", growshrink_active_window, '+')
+ || try_cmd_1args(key, "shri_v", growshrink_active_window, '-')
+ || try_cmd_1args(key, "shift_f", shift_active_win, 'f')
+ || try_cmd_1args(key, "shift_b", shift_active_win, 'b'))
{
return 1;
}
extern uint8_t winkeyb_control(int key)
{
- if ( try_cmd_1args('k', key, "w_keys_m", wrap_mod_selected_keyb, 'w')
- || try_cmd_2args('k', key, "w_keys_u", wrap_mv_kb_mod, 'w', 'u')
- || try_cmd_2args('k', key, "w_keys_d", wrap_mv_kb_mod, 'w', 'd'))
+ if ( try_cmd_1args(key, "w_keys_m", wrap_mod_selected_keyb, 'w')
+ || try_cmd_2args(key, "w_keys_u", wrap_mv_kb_mod, 'w', 'u')
+ || try_cmd_2args(key, "w_keys_d", wrap_mv_kb_mod, 'w', 'd'))
{
return 1;
}
{
uint8_t ret = (key == get_available_keycode_to_action("quit"));
if ( (0 == ret)
- && ( try_cmd_0args('k', key, "winconf", toggle_winconfig)
- || try_cmd_0args('k', key, "reload_conf", reload_interface_conf)
- || try_cmd_0args('k', key, "save_conf", save_interface_conf)
- || try_cmd_0args('k', key, "map_c", map_center)
- || try_cmd_1args('k', key, "scrl_r", scroll_pad, '+')
- || try_cmd_1args('k', key, "scrl_l", scroll_pad, '-')
- || try_cmd_1args('k', key, "to_a_keywin", toggle_window, 'k')
- || try_cmd_1args('k', key, "to_g_keywin", toggle_window, '0')
- || try_cmd_1args('k', key, "to_wg_keywin", toggle_window, '1')
- || try_cmd_1args('k', key, "to_wk_keywin", toggle_window, '2')
- || try_cmd_1args('k', key, "to_mapwin", toggle_window, 'm')
- || try_cmd_1args('k', key, "to_infowin", toggle_window, 'i')
- || try_cmd_1args('k', key, "to_inv", toggle_window, 'c')
- || try_cmd_1args('k', key, "to_logwin", toggle_window, 'l')
- || try_cmd_1args('k', key, "cyc_win_f", cycle_active_win, 'f')
- || try_cmd_1args('k', key, "cyc_win_b", cycle_active_win, 'b')
- || try_cmd_1args('k', key, "g_keys_m", wrap_mod_selected_keyb, 'G')
- || try_cmd_1args('k', key, "wg_keys_m", wrap_mod_selected_keyb, 'g')
- || try_cmd_1args('k', key, "wk_keys_m", wrap_mod_selected_keyb, 'k')
- || try_cmd_1args('k', key, "inv_u", nav_inventory, 'u')
- || try_cmd_1args('k', key, "inv_d", nav_inventory, 'd')
- || try_cmd_1args('k', key, "map_u", map_scroll, 'N')
- || try_cmd_1args('k', key, "map_d", map_scroll, 'S')
- || try_cmd_1args('k', key, "map_r", map_scroll, 'E')
- || try_cmd_1args('k', key, "map_l", map_scroll, 'W')
- || try_cmd_2args('k', key, "g_keys_u", wrap_mv_kb_mod, 'G', 'u')
- || try_cmd_2args('k', key, "g_keys_d", wrap_mv_kb_mod, 'G', 'd')
- || try_cmd_2args('k', key, "wg_keys_u", wrap_mv_kb_mod, 'g', 'u')
- || try_cmd_2args('k', key, "wg_keys_d", wrap_mv_kb_mod, 'g', 'd')
- || try_cmd_2args('k', key, "wk_keys_u", wrap_mv_kb_mod, 'k', 'u')
- || try_cmd_2args('k', key, "wk_keys_d", wrap_mv_kb_mod, 'k', 'd')))
+ && ( try_cmd_0args(key, "winconf", toggle_winconfig)
+ || try_cmd_0args(key, "reload_conf", reload_interface_conf)
+ || try_cmd_0args(key, "save_conf", save_interface_conf)
+ || try_cmd_0args(key, "map_c", map_center)
+ || try_cmd_1args(key, "scrl_r", scroll_pad, '+')
+ || try_cmd_1args(key, "scrl_l", scroll_pad, '-')
+ || try_cmd_1args(key, "to_a_keywin", toggle_window, 'k')
+ || try_cmd_1args(key, "to_g_keywin", toggle_window, '0')
+ || try_cmd_1args(key, "to_wg_keywin", toggle_window, '1')
+ || try_cmd_1args(key, "to_wk_keywin", toggle_window, '2')
+ || try_cmd_1args(key, "to_mapwin", toggle_window, 'm')
+ || try_cmd_1args(key, "to_infowin", toggle_window, 'i')
+ || try_cmd_1args(key, "to_inv", toggle_window, 'c')
+ || try_cmd_1args(key, "to_logwin", toggle_window, 'l')
+ || try_cmd_1args(key, "cyc_win_f", cycle_active_win, 'f')
+ || try_cmd_1args(key, "cyc_win_b", cycle_active_win, 'b')
+ || try_cmd_1args(key, "g_keys_m", wrap_mod_selected_keyb, 'G')
+ || try_cmd_1args(key, "wg_keys_m", wrap_mod_selected_keyb, 'g')
+ || try_cmd_1args(key, "wk_keys_m", wrap_mod_selected_keyb, 'k')
+ || try_cmd_1args(key, "inv_u", nav_inventory, 'u')
+ || try_cmd_1args(key, "inv_d", nav_inventory, 'd')
+ || try_cmd_1args(key, "map_u", map_scroll, 'N')
+ || try_cmd_1args(key, "map_d", map_scroll, 'S')
+ || try_cmd_1args(key, "map_r", map_scroll, 'E')
+ || try_cmd_1args(key, "map_l", map_scroll, 'W')
+ || try_cmd_2args(key, "g_keys_u", wrap_mv_kb_mod, 'G', 'u')
+ || try_cmd_2args(key, "g_keys_d", wrap_mv_kb_mod, 'G', 'd')
+ || try_cmd_2args(key, "wg_keys_u", wrap_mv_kb_mod, 'g', 'u')
+ || try_cmd_2args(key, "wg_keys_d", wrap_mv_kb_mod, 'g', 'd')
+ || try_cmd_2args(key, "wk_keys_u", wrap_mv_kb_mod, 'k', 'u')
+ || try_cmd_2args(key, "wk_keys_d", wrap_mv_kb_mod, 'k', 'd')))
{
;
}
#include "control.h" /* for control_by_id(), player_control(),
* get_available_keycode_to_action()
*/
+#include "map_object_actions.h" /* for init_map_object_actions() */
char * f_name = "main()";
world.turn = 0; /* Turns to 1 when map and objects are initalized. */
+ /* Initialize commands and map object actions. */
init_command_db();
set_cleanup_flag(CLEANUP_COMMAND_DB);
+ init_map_object_actions();
+ set_cleanup_flag(CLEANUP_MAPOBJACTS);
/* Check for corrupted savefile / recordfile savings. */
char * recordfile = "record";
struct Map;
struct MapObjDef;
struct MapObj;
+struct MapObjAct;
struct MapObjDef * map_obj_defs; /* Map object type definitions chain. */
struct MapObj * map_objs; /* Pointer to map objects chain start. */
uint8_t inventory_select; /* Player's inventory selection index. */
- uint8_t old_inventory_select; /* Temporarily stores for recordfile */
-} world; /* writing inventory selection index. */
+ struct MapObjAct * map_obj_acts; /* Pointer to map object actions chain. */
+} world;
struct Win * win_map = get_win_by_id('m');
win_map->center = player->pos;
}
+
+
+
+extern uint8_t is_passable(struct Map * map, struct yx_uint16 pos)
+{
+ uint8_t passable = 0;
+ if (0 <= pos.x && pos.x < map->size.x && 0 <= pos.y && pos.y < map->size.y)
+ {
+ passable = (('.' == map->cells[pos.y * map->size.x + pos.x]));
+ }
+ return passable;
+}
/* Center map on player. */
extern void map_center();
+/* Check if coordinate pos on (or beyond) map is accessible to map object
+ * movement.
+ */
+extern uint8_t is_passable(struct Map * map, struct yx_uint16 pos);
+
#endif
/* map_object_actions.c */
#include "map_object_actions.h"
-#include <string.h> /* for strlen() */
+#include <stdint.h> /* for uint8_t */
+#include <string.h> /* for strlen(), strcmp() */
#include "yx_uint16.h" /* for yx_uint16 struct, mv_yx_in_dir(),
* yx_uint16_cmp()
*/
#include "map_objects.h" /* for MapObj, MapObjDef structs, get_player(),
* set_object_position(), own_map_object()
*/
-#include "misc.h" /* for update_log(), turn_over() */
-#include "map.h" /* for Map struct */
+#include "misc.h" /* for update_log(), try_malloc() */
+#include "map.h" /* for is_passable() */
#include "main.h" /* for world global */
-#include "command_db.h" /* for get_command_id() */
+#include "readwrite.h" /* for try_fopen(), try_fclose(), get_linemax() */
+#include "rexit.h" /* for exit_err() */
+/* If "name" fits "moa"->name, set "moa"->func to "func". */
+static uint8_t try_func_name(struct MapObjAct * moa,
+ char * name, void (* func) (struct MapObj *));
+
/* One actor "wounds" another actor, decrementing his lifepoints and, if they
* reach zero in the process, killing it. Generates appropriate log message.
*/
static void actor_hits_actor(struct MapObj * hitter, struct MapObj * hitted);
+/* Bonus stuff to actor_*() to happen if actor==player. Mostly writing of log
+ * messages; _pick and _drop also decrement world.inventory_select by 1 if >0.
+ */
+static void playerbonus_wait();
+static void playerbonus_move(char d, uint8_t passable);
+static void playerbonus_drop(uint8_t owns_none);
+static void playerbonus_pick(uint8_t picked);
+static void playerbonus_use(uint8_t no_object, uint8_t wrong_object);
+
+
+
+static uint8_t try_func_name(struct MapObjAct * moa,
+ char * name, void (* func) (struct MapObj *))
+{
+ if (0 == strcmp(moa->name, name))
+ {
+ moa->func = func;
+ return 1;
+ }
+ return 0;
+}
+
static void actor_hits_actor(struct MapObj * hitter, struct MapObj * hitted)
-extern uint8_t move_actor(struct MapObj * actor, char d)
+static void playerbonus_wait()
{
- struct yx_uint16 target = mv_yx_in_dir(d, actor->pos);
- struct MapObj * other_actor;
- for (other_actor = world.map_objs;
- other_actor != 0;
- other_actor = other_actor->next)
- {
- if (0 == other_actor->lifepoints || other_actor == actor)
- {
- continue;
- }
- if (yx_uint16_cmp(&target, &other_actor->pos))
- {
- actor_hits_actor(actor, other_actor);
- return 2;
- }
- }
- if (is_passable(world.map, target))
- {
- set_object_position(actor, target);
- return 0;
- }
- return 1;
+ update_log("\nYou wait.");
}
-extern void move_player(char d)
+static void playerbonus_move(char d, uint8_t passable)
{
- char * dsc_dir;
- char * action_dsc_prototype = "player_";
- uint8_t len_action_dsc_prototype = strlen(action_dsc_prototype);
- char action_dsc[len_action_dsc_prototype + 2];
- memcpy(action_dsc, action_dsc_prototype, len_action_dsc_prototype);
- if ('N' == d)
- {
- dsc_dir = "north";
- action_dsc[len_action_dsc_prototype] = 'u';
- }
- else if ('E' == d)
+ char * dsc_dir = "north";
+ if ('E' == d)
{
dsc_dir = "east" ;
- action_dsc[len_action_dsc_prototype] = 'r';
}
else if ('S' == d)
{
dsc_dir = "south";
- action_dsc[len_action_dsc_prototype] = 'd';
}
else if ('W' == d)
{
dsc_dir = "west" ;
- action_dsc[len_action_dsc_prototype] = 'l';
}
- action_dsc[len_action_dsc_prototype + 1] = '\0';
- uint8_t res = move_actor(get_player(), d);
- if (1 >= res)
+ char * dsc_move = "You move ";
+ if (0 == passable)
{
- char * dsc_move = "You fail to move ";
- if (0 == res)
- {
- dsc_move = "You move ";
- }
- char msg[strlen(dsc_move) + strlen (dsc_dir) + 3];
- sprintf(msg, "\n%s%s.", dsc_move, dsc_dir);
- update_log(msg);
+ dsc_move = "You fail to move ";
}
- turn_over(get_command_id(action_dsc));
+ char msg[strlen(dsc_move) + strlen (dsc_dir) + 3];
+ sprintf(msg, "\n%s%s.", dsc_move, dsc_dir);
+ update_log(msg);
}
-extern void player_wait()
+static void playerbonus_drop(uint8_t owns_none)
{
- update_log("\nYou wait.");
- turn_over(get_command_id("wait"));
+ if (0 != owns_none)
+ {
+ update_log("\nYou try to drop an object, but you own none.");
+ }
+ else
+ {
+ update_log("\nYou drop an object.");
+ if (0 < world.inventory_select)
+ {
+ world.inventory_select--;
+ }
+ }
}
-extern char is_passable(struct Map * map, struct yx_uint16 pos)
+static void playerbonus_pick(uint8_t picked)
{
- uint8_t passable = 0;
- if (0 <= pos.x && pos.x < map->size.x && 0 <= pos.y && pos.y < map->size.y)
+ if (picked)
{
- passable = (('.' == map->cells[pos.y * map->size.x + pos.x]));
+ update_log("\nYou pick up an object.");
+ }
+ else
+ {
+ update_log("\nYou try to pick up an object, but there is none.");
}
- return passable;
}
-extern void player_drop()
+static void playerbonus_use(uint8_t no_object, uint8_t wrong_object)
{
- struct MapObj * player = get_player();
- if (NULL == player->owns)
+ if (no_object)
{
- update_log("\nYou try to drop an object, but you own none.");
- world.old_inventory_select = 0;
+ update_log("\nYou try to use an object, but you own none.");
+ }
+ else if (wrong_object)
+ {
+ update_log("\nYou try to use this object, but fail.");
}
else
{
- world.old_inventory_select = world.inventory_select;
- struct MapObj * owned = player->owns;
- uint8_t i = 0;
- for (; i != world.inventory_select; i++, owned = owned->next);
+ update_log("\nYou consume MAGIC MEAT.");
if (0 < world.inventory_select)
{
world.inventory_select--;
}
- own_map_object(&world.map_objs, &player->owns, owned->id);
- update_log("\nYou drop an object.");
}
- turn_over(get_command_id("drop"));
}
-extern void player_pick()
+extern void init_map_object_actions()
{
- struct MapObj * player = get_player();
- struct MapObj * picked;
- for (picked = world.map_objs; NULL != picked; picked = picked->next)
+ char * f_name = "init_map_object_actions()";
+
+ char * path = "config/map_object_actions";
+ FILE * file = try_fopen(path, "r", f_name);
+ uint16_t linemax = get_linemax(file, f_name);
+ char line[linemax + 1];
+
+ struct MapObjAct ** moa_ptr_ptr = &world.map_obj_acts;
+ char * delim = " ";
+ while (fgets(line, linemax + 1, file))
{
- if (picked != player && yx_uint16_cmp(&picked->pos, &player->pos))
+ if ('\n' == line[0] || 0 == line[0])
{
break;
}
+ struct MapObjAct * moa = try_malloc(sizeof(struct MapObjAct), f_name);
+ moa->id = atoi(strtok(line, delim));
+ moa->effort = atoi(strtok(NULL, delim));
+ char * funcname = strtok(NULL, "\n");
+ uint8_t len_name = strlen(funcname) + 1;
+ moa->name = try_malloc(len_name, f_name);
+ memcpy(moa->name, funcname, len_name);
+ if (!( try_func_name(moa, "move", actor_move)
+ || try_func_name(moa, "pick_up", actor_pick)
+ || try_func_name(moa, "drop", actor_drop)
+ || try_func_name(moa, "use", actor_use)))
+ {
+ moa->func = actor_wait;
+ }
+ moa->next = NULL;
+ * moa_ptr_ptr = moa;
+ moa_ptr_ptr = &moa->next;
}
- if (NULL == picked)
+ try_fclose(file, f_name);
+}
+
+
+
+extern void free_map_object_actions(struct MapObjAct * moa)
+{
+ if (NULL == moa)
{
- update_log("\nYou try to pick up an object, but there is none.");
+ return;
}
- else
+ free(moa->name);
+ free_map_object_actions(moa->next);
+ free(moa);
+}
+
+
+
+extern void actor_wait(struct MapObj * mo)
+{
+ if (mo == get_player())
{
- own_map_object(&player->owns, &world.map_objs, picked->id);
- set_object_position(picked, player->pos);
- update_log("\nYou pick up an object.");
+ playerbonus_wait();
}
- turn_over(get_command_id("pick"));
}
-extern void player_use()
+extern void actor_move(struct MapObj * mo)
{
- struct MapObj * player = get_player();
- if (NULL == player->owns)
+ char d = mo->arg;
+ struct yx_uint16 target = mv_yx_in_dir(d, mo->pos);
+ struct MapObj * other_mo;
+ for (other_mo = world.map_objs; other_mo != 0; other_mo = other_mo->next)
{
- update_log("\nYou try to use an object, but you own none.");
- world.old_inventory_select = 0;
+ if (0 == other_mo->lifepoints || other_mo == mo)
+ {
+ continue;
+ }
+ if (yx_uint16_cmp(&target, &other_mo->pos))
+ {
+ actor_hits_actor(mo, other_mo);
+ return;
+ }
}
- else
+ uint8_t passable = is_passable(world.map, target);
+ if (passable)
+ {
+ set_object_position(mo, target);
+ }
+ if (mo == get_player())
+ {
+ playerbonus_move(d, passable);
+ }
+}
+
+
+
+extern void actor_drop(struct MapObj * mo)
+{
+ uint8_t owns_none = (NULL == mo->owns);
+ if (!owns_none)
{
+ uint8_t select = mo->arg;
+ struct MapObj * owned = mo->owns;
uint8_t i = 0;
- struct MapObj * selected = player->owns;
- for (; i != world.inventory_select; i++, selected = selected->next);
+ for (; i != select; i++, owned = owned->next);
+ own_map_object(&world.map_objs, &mo->owns, owned->id);
+ }
+ if (mo == get_player())
+ {
+ playerbonus_drop(owns_none);
+ }
+}
+
+
+
+extern void actor_pick(struct MapObj * mo)
+{
+ struct MapObj * picked;
+ for (picked = world.map_objs; NULL != picked; picked = picked->next)
+ {
+ if (picked != mo && yx_uint16_cmp(&picked->pos, &mo->pos))
+ {
+ break;
+ }
+ }
+ if (NULL != picked)
+ {
+ own_map_object(&mo->owns, &world.map_objs, picked->id);
+ set_object_position(picked, mo->pos);
+ }
+ if (mo == get_player())
+ {
+ playerbonus_pick(NULL != picked);
+ }
+}
+
+
+
+extern void actor_use(struct MapObj * mo)
+{
+ uint8_t wrong_object = 1;
+ uint8_t no_object = (NULL == mo->owns);
+ if (!no_object)
+ {
+ uint8_t select = mo->arg;
+ uint8_t i = 0;
+ struct MapObj * selected = mo->owns;
+ for (; i != select; i++, selected = selected->next);
struct MapObjDef * mod = get_map_object_def(selected->type);
if (!strcmp("MAGIC MEAT", mod->name))
{
+ wrong_object = 0;
struct MapObj * next = selected->next;
free(selected);
- if (0 < world.inventory_select)
+ if (0 < select)
{
- world.old_inventory_select = world.inventory_select;
- world.inventory_select--;
- for (i = 0, selected = player->owns;
- i != world.inventory_select;
+ select--;
+ for (i = 0, selected = mo->owns;
+ i != select;
i++, selected = selected->next);
selected->next = next;
}
else
{
- player->owns = next;
+ mo->owns = next;
}
- player->lifepoints++;
- update_log("\nYou consume MAGIC MEAT.");
- }
- else
- {
- update_log("\nYou try to use this object, but fail.");
+ mo->lifepoints++;
}
}
- turn_over(get_command_id("use"));
+ if (mo == get_player())
+ {
+ playerbonus_use(no_object, wrong_object);
+ }
}
/* map_object_actions.h
*
- * Routines for the actions available to map objects.
+ * Actions that can be performed my map objects / "actors". Note that apart
+ * from the consequences described below, each action may also trigger log
+ * messages and other minor stuff if the actor is equal to the player.
*/
#ifndef MAP_OBJECT_ACTIONS_H
#define MAP_OBJECT_ACTIONS_H
-#include "yx_uint16.h" /* for yx_uint16 coordinates */
-struct Map;
+#include <stdint.h> /* for uint8_t */
struct MapObj;
-/* Try to move "actor" one step in direction "d" (where east is 'E', north 'N'
- * etc.) and handle the consequences: either the move succeeds, or another actor
- * is encountered and hit (which leads to its lifepoint decreasing by one and
- * potentially its death), or the target square is not passable, the move fails.
- */
-extern uint8_t move_actor(struct MapObj * actor, char d);
+struct MapObjAct
+{
+ struct MapObjAct * next;
+ uint8_t id; /* unique id of map object action */
+ char * name; /* human-readable identifier */
+ uint8_t effort; /* how many turn the action takes */
+ void (* func) (struct MapObj *); /* function called after .effort turns */
+};
-/* Wrapper for using move_actor() on the MapObj representing the player; updates
- * the game log with appropriate messages on the move attempt and its results;
- * turns over to turn_over() when finished.
- */
-extern void move_player(char d);
-/* Make player wait one turn, i.e. only update_log with a "you wait" message
- * and turn control over to the enemy.
- */
-extern void player_wait();
-/* Check if coordinate pos on (or beyond) map is accessible to map object
- * movement.
+/* Init MapObjAct chain at world.map_obj_acts from config/map_object_actions. */
+extern void init_map_object_actions();
+
+/* Free MapObjAct * chain starting at "moa". */
+extern void free_map_object_actions(struct MapObjAct * moa);
+
+/* Actor "mo" does nothing. */
+extern void actor_wait(struct MapObj * mo);
+
+/* Actor "mo" tries to move one step in direction described by char mo->arg
+ * (where east is 'E', north 'N') etc. Move either succeeds, or another actor is
+ * encountered and hit (which leads ot its lifepoint decreasing by one and
+ * eventually death), or the move fails due to an impassable target square.
*/
-extern char is_passable(struct Map * map, struct yx_uint16 pos);
+extern void actor_move(struct MapObj * mo);
-/* Make player drop to ground map ojbect indexed by world.inventory_select. */
-extern void player_drop();
+/* Actor "mo" tries to drop from inventory object indexed by number mo->args. */
+extern void actor_drop(struct MapObj * mo);
-/* Make player pick up map object from ground. */
-extern void player_pick();
+/* Actor "mo" tries to pick up object from ground into its inventory. */
+extern void actor_pick(struct MapObj * mo);
-/* Make player use object indexed by world.inventory_select. */
-extern void player_use();
+/* Actor "mo" tries to use inventory object indexed by number mo->args.
+ * (Currently the only valid use is consuming "MAGIC MEAT".
+ */
+extern void actor_use(struct MapObj * mo);
for (; NULL != mo_ptr; mo_ptr = mo_ptr->next, i++);
uint8_t size = 3+1 + 3+1 + 3+1 + 5+1 + 5 + ((1+3)*i) + 1 + 1;
char line[size];
- sprintf(line, "%d %d %d %d %d",
- mo->id, mo->type, mo->lifepoints, mo->pos.y, mo->pos.x);
+ sprintf(line, "%d %d %d %d %d %d %d %d",
+ mo->id, mo->type, mo->lifepoints, mo->pos.y, mo->pos.x,
+ mo->progress, mo->command, mo->arg);
for (mo_ptr = mo->owns; NULL != mo_ptr; mo_ptr = mo_ptr->next)
{
sprintf(line + strlen(line), " %d", mo_ptr->id);
exit_err(-1 == fgetpos(file, &pos), f_name);
while (try_fgets(line, linemax + 1, file, f_name))
{
- mo = malloc(sizeof(struct MapObj));
+ mo = try_malloc(sizeof(struct MapObj), f_name);
mo->next = NULL;
mo->id = atoi(strtok(line, delim));
mo->type = atoi(strtok(NULL, delim));
mo->lifepoints = atoi(strtok(NULL, delim));
mo->pos.y = atoi(strtok(NULL, delim));
mo->pos.x = atoi(strtok(NULL, delim));
+ mo->progress = atoi(strtok(NULL, delim));;
+ mo->command = atoi(strtok(NULL, delim));;
+ mo->arg = atoi(strtok(NULL, delim));;
mo->owns = NULL;
if (mo->id > world.map_obj_count)
{
while (try_fgets(line, linemax + 1, file, f_name))
{
uint8_t id = atoi(strtok(line, delim));
- strtok(NULL, delim);
- strtok(NULL, delim);
- strtok(NULL, delim);
- strtok(NULL, delim);
+ uint8_t i;
+ for (i = 0; i < 7; i++)
+ {
+ strtok(NULL, delim);
+ }
char * owned = strtok(NULL, "\n");
if (NULL != owned)
{
break;
}
}
+ mo->progress = 0;
+ mo->command = 0;
+ mo->arg = 0;
mo->owns = NULL;
mo->next = NULL;
struct MapObj ** last_ptr_ptr = &world.map_objs;
uint8_t type; /* ID of appropriate map object definition */
uint8_t lifepoints; /* 0: object is inanimate; >0: hitpoints */
struct yx_uint16 pos; /* coordinate on map */
+ uint8_t command; /* command map object tries to realize now*/
+ uint8_t arg; /* optional field for command argument */
+ uint8_t progress; /* turns already passed to realize .command */
};
struct MapObjDef
#include "map_objects.h" /* for struct MapObj, get_player(), read_map_objects(),
* write_map_objects()
*/
-#include "map_object_actions.h" /* for is_passable(), move_actor() */
-#include "map.h" /* for Map struct */
+#include "map_object_actions.h" /* for struct MapObjAct */
+#include "map.h" /* for Map struct, is_passable() */
#include "main.h" /* for world global */
#include "yx_uint16.h" /* for yx_uint16 struct */
#include "rrand.h" /* for rrand(), rrand_seed() */
if ( is_command_id_shortdsc(action, "drop")
|| is_command_id_shortdsc(action, "use"))
{
- uint8_t inventory_select = world.old_inventory_select;
- exit_err(write_uint8(inventory_select, file_new), err_write);
+ exit_err(write_uint8(world.inventory_select, file_new), err_write);
}
try_fclose_unlink_rename(file_new, recordfile_tmp, recordfile, f_name);
}
- world.turn++;
rrand_seed(world.seed * world.turn);
- struct MapObj * monster;
- for (monster = world.map_objs; monster != 0; monster = monster->next)
+
+ struct MapObj * player = get_player();
+ struct MapObj * map_object = player;
+ uint8_t first_round = 1;
+ while (0 < player->lifepoints)
{
- if (0 < monster->lifepoints && 0 != monster->id)
+ if (NULL == map_object)
{
- char * sel = "\0NSEW";
- move_actor(monster, sel[rrand() % 5]);
+ world.turn++;
+ map_object = world.map_objs;
+ }
+ if (0 < map_object->lifepoints) /* map_object is animate. */
+ {
+ if (0 == first_round && 0 == map_object->progress)
+ {
+ if (map_object == player)
+ {
+ break;
+ }
+ char * sel = "NSEW";
+ map_object->command = 1;
+ map_object->arg = sel[rrand() % 4];
+ }
+ first_round = 0;
+ map_object->progress++;
+ struct MapObjAct * moa = world.map_obj_acts;
+ while (moa->id != map_object->command)
+ {
+ moa = moa->next;
+ }
+ if (map_object->progress == moa->effort)
+ {
+ moa->func(map_object);
+ map_object->progress = 0;
+ }
}
+ map_object = map_object->next;
}
}
#include "windows.h" /* for Win struct, free_win(), free_winmeta() */
#include "map_objects.h" /* for free_map_objects, free_map_object_defs() */
#include "misc.h" /* for unload_interface_conf() */
+#include "map_object_actions.h" /* for free_map_object_actions() */
{
free_command_db();
}
+ if (cleanup_flags & CLEANUP_MAPOBJACTS)
+ {
+ free_map_object_actions(world.map_obj_acts);
+ }
if (cleanup_flags & CLEANUP_MAP)
{
free(world.map->cells);
}
if (cleanup_flags & CLEANUP_INTERFACE_CONF)
{
- unload_interface_conf(/*&world*/);
+ unload_interface_conf();
}
if (cleanup_flags & CLEANUP_WIN_META)
{
CLEANUP_MAP = 0x0002,
CLEANUP_LOG = 0x0004,
CLEANUP_COMMAND_DB = 0x0008,
- CLEANUP_MAP_OBJECTS = 0x0010,
- CLEANUP_MAP_OBJECT_DEFS = 0x0020,
- CLEANUP_WIN_META = 0x0040,
- CLEANUP_INTERFACE_CONF = 0x0080
+ CLEANUP_MAPOBJACTS = 0x0010,
+ CLEANUP_MAP_OBJECTS = 0x0020,
+ CLEANUP_MAP_OBJECT_DEFS = 0x0040,
+ CLEANUP_WIN_META = 0x0080,
+ CLEANUP_INTERFACE_CONF = 0x0100
};
extern void set_cleanup_flag(enum cleanup_flag flag);