/* object.c - Object manipulation opcodes * Copyright (c) 1995-1997 Stefan Jokisch * * This file is part of Frotz. * * Frotz is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Frotz is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "frotz.h" #define MAX_OBJECT 2000 #define O1_PARENT 4#define O1_SIBLING 5#define O1_CHILD 6#define O1_PROPERTY_OFFSET 7#define O1_SIZE 9 #define O4_PARENT 6#define O4_SIBLING 8#define O4_CHILD 10#define O4_PROPERTY_OFFSET 12#define O4_SIZE 14 /* * object_address * * Calculate the address of an object. * */static zword object_address (zword obj){/* zchar obj_num[10]; */ /* Check object number */ if (obj > ((h_version <= V3) ? 255 : MAX_OBJECT)) { print_string("@Attempt to address illegal object "); print_num(obj); print_string(". This is normally fatal."); new_line(); runtime_error (ERR_ILL_OBJ); } /* Return object address */ if (h_version <= V3) return h_objects + ((obj - 1) * O1_SIZE + 62); else return h_objects + ((obj - 1) * O4_SIZE + 126); }/* object_address */ /* * object_name * * Return the address of the given object's name. * */zword object_name (zword object){ zword obj_addr; zword name_addr; obj_addr = object_address (object); /* The object name address is found at the start of the properties */ if (h_version <= V3) obj_addr += O1_PROPERTY_OFFSET; else obj_addr += O4_PROPERTY_OFFSET; LOW_WORD (obj_addr, name_addr) return name_addr; }/* object_name */ /* * first_property * * Calculate the start address of the property list associated with * an object. * */static zword first_property (zword obj){ zword prop_addr; zbyte size; /* Fetch address of object name */ prop_addr = object_name (obj); /* Get length of object name */ LOW_BYTE (prop_addr, size) /* Add name length to pointer */ return prop_addr + 1 + 2 * size; }/* first_property */ /* * next_property * * Calculate the address of the next property in a property list. * */static zword next_property (zword prop_addr){ zbyte value; /* Load the current property id */ LOW_BYTE (prop_addr, value) prop_addr++; /* Calculate the length of this property */ if (h_version <= V3) value >>= 5; else if (!(value & 0x80)) value >>= 6; else { LOW_BYTE (prop_addr, value) value &= 0x3f; if (value == 0) value = 64; /* demanded by Spec 1.0 */ } /* Add property length to current property pointer */ return prop_addr + value + 1; }/* next_property */ /* * unlink_object * * Unlink an object from its parent and siblings. * */static void unlink_object (zword object){ zword obj_addr; zword parent_addr; zword sibling_addr; if (object == 0) { runtime_error (ERR_REMOVE_OBJECT_0); return; } obj_addr = object_address (object); if (h_version <= V3) { zbyte parent; zbyte younger_sibling; zbyte older_sibling; zbyte zero = 0; /* Get parent of object, and return if no parent */ obj_addr += O1_PARENT; LOW_BYTE (obj_addr, parent) if (!parent) return; /* Get (older) sibling of object and set both parent and sibling pointers to 0 */ SET_BYTE (obj_addr, zero) obj_addr += O1_SIBLING - O1_PARENT; LOW_BYTE (obj_addr, older_sibling) SET_BYTE (obj_addr, zero) /* Get first child of parent (the youngest sibling of the object) */ parent_addr = object_address (parent) + O1_CHILD; LOW_BYTE (parent_addr, younger_sibling) /* Remove object from the list of siblings */ if (younger_sibling == object) SET_BYTE (parent_addr, older_sibling) else { do { sibling_addr = object_address (younger_sibling) + O1_SIBLING; LOW_BYTE (sibling_addr, younger_sibling) } while (younger_sibling != object); SET_BYTE (sibling_addr, older_sibling) } } else { zword parent; zword younger_sibling; zword older_sibling; zword zero = 0; /* Get parent of object, and return if no parent */ obj_addr += O4_PARENT; LOW_WORD (obj_addr, parent) if (!parent) return; /* Get (older) sibling of object and set both parent and sibling pointers to 0 */ SET_WORD (obj_addr, zero) obj_addr += O4_SIBLING - O4_PARENT; LOW_WORD (obj_addr, older_sibling) SET_WORD (obj_addr, zero) /* Get first child of parent (the youngest sibling of the object) */ parent_addr = object_address (parent) + O4_CHILD; LOW_WORD (parent_addr, younger_sibling) /* Remove object from the list of siblings */ if (younger_sibling == object) SET_WORD (parent_addr, older_sibling) else { do { sibling_addr = object_address (younger_sibling) + O4_SIBLING; LOW_WORD (sibling_addr, younger_sibling) } while (younger_sibling != object); SET_WORD (sibling_addr, older_sibling) } } }/* unlink_object */ /* * z_clear_attr, clear an object attribute. * * zargs[0] = object * zargs[1] = number of attribute to be cleared * */void z_clear_attr (void){ zword obj_addr; zbyte value; if (story_id == SHERLOCK) if (zargs[1] == 48) return; if (zargs[1] > ((h_version <= V3) ? 31 : 47)) runtime_error (ERR_ILL_ATTR); /* If we are monitoring attribute assignment display a short note */ if (f_setup.attribute_assignment) { stream_mssg_on (); print_string ("@clear_attr "); print_object (zargs[0]); print_string (" "); print_num (zargs[1]); stream_mssg_off (); } if (zargs[0] == 0) { runtime_error (ERR_CLEAR_ATTR_0); return; } /* Get attribute address */ obj_addr = object_address (zargs[0]) + zargs[1] / 8; /* Clear attribute bit */ LOW_BYTE (obj_addr, value) value &= ~(0x80 >> (zargs[1] & 7)); SET_BYTE (obj_addr, value) }/* z_clear_attr */ /* * z_jin, branch if the first object is inside the second. * * zargs[0] = first object * zargs[1] = second object * */void z_jin (void){ zword obj_addr; /* If we are monitoring object locating display a short note */ if (f_setup.object_locating) { stream_mssg_on (); print_string ("@jin "); print_object (zargs[0]); print_string (" "); print_object (zargs[1]); stream_mssg_off (); } if (zargs[0] == 0) { runtime_error (ERR_JIN_0); branch (0 == zargs[1]); return; } obj_addr = object_address (zargs[0]); if (h_version <= V3) { zbyte parent; /* Get parent id from object */ obj_addr += O1_PARENT; LOW_BYTE (obj_addr, parent) /* Branch if the parent is obj2 */ branch (parent == zargs[1]); } else { zword parent; /* Get parent id from object */ obj_addr += O4_PARENT; LOW_WORD (obj_addr, parent) /* Branch if the parent is obj2 */ branch (parent == zargs[1]); } }/* z_jin */ /* * z_get_child, store the child of an object. * * zargs[0] = object * */void z_get_child (void){ zword obj_addr; /* If we are monitoring object locating display a short note */ if (f_setup.object_locating) { stream_mssg_on (); print_string ("@get_child "); print_object (zargs[0]); stream_mssg_off (); } if (zargs[0] == 0) { runtime_error (ERR_GET_CHILD_0); store (0); branch (FALSE); return; } obj_addr = object_address (zargs[0]); if (h_version <= V3) { zbyte child; /* Get child id from object */ obj_addr += O1_CHILD; LOW_BYTE (obj_addr, child) /* Store child id and branch */ store (child); branch (child); } else { zword child; /* Get child id from object */ obj_addr += O4_CHILD; LOW_WORD (obj_addr, child) /* Store child id and branch */ store (child); branch (child); } }/* z_get_child */ /* * z_get_next_prop, store the number of the first or next property. * * zargs[0] = object * zargs[1] = address of current property (0 gets the first property) * */void z_get_next_prop (void){ zword prop_addr; zbyte value; zbyte mask; if (zargs[0] == 0) { runtime_error (ERR_GET_NEXT_PROP_0); store (0); return; } /* Property id is in bottom five (six) bits */ mask = (h_version <= V3) ? 0x1f : 0x3f; /* Load address of first property */ prop_addr = first_property (zargs[0]); if (zargs[1] != 0) { /* Scan down the property list */ do { LOW_BYTE (prop_addr, value) prop_addr = next_property (prop_addr); } while ((value & mask) > zargs[1]); /* Exit if the property does not exist */ if ((value & mask) != zargs[1]) runtime_error (ERR_NO_PROP); } /* Return the property id */ LOW_BYTE (prop_addr, value) store ((zword) (value & mask)); }/* z_get_next_prop */ /* * z_get_parent, store the parent of an object. * * zargs[0] = object * */void z_get_parent (void){ zword obj_addr; /* If we are monitoring object locating display a short note */ if (f_setup.object_locating) { stream_mssg_on (); print_string ("@get_parent "); print_object (zargs[0]); stream_mssg_off (); } Lines 1–500 of 1002. Load more
/* object.c - Object manipulation opcodes * Copyright (c) 1995-1997 Stefan Jokisch * * This file is part of Frotz. * * Frotz is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Frotz is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "frotz.h" #define MAX_OBJECT 2000 #define O1_PARENT 4 #define O1_SIBLING 5 #define O1_CHILD 6 #define O1_PROPERTY_OFFSET 7 #define O1_SIZE 9 #define O4_PARENT 6 #define O4_SIBLING 8 #define O4_CHILD 10 #define O4_PROPERTY_OFFSET 12 #define O4_SIZE 14 /* * object_address * * Calculate the address of an object. * */ static zword object_address (zword obj) { /* zchar obj_num[10]; */ /* Check object number */ if (obj > ((h_version <= V3) ? 255 : MAX_OBJECT)) { print_string("@Attempt to address illegal object "); print_num(obj); print_string(". This is normally fatal."); new_line(); runtime_error (ERR_ILL_OBJ); } /* Return object address */ if (h_version <= V3) return h_objects + ((obj - 1) * O1_SIZE + 62); else return h_objects + ((obj - 1) * O4_SIZE + 126); }/* object_address */ /* * object_name * * Return the address of the given object's name. * */ zword object_name (zword object) { zword obj_addr; zword name_addr; obj_addr = object_address (object); /* The object name address is found at the start of the properties */ if (h_version <= V3) obj_addr += O1_PROPERTY_OFFSET; else obj_addr += O4_PROPERTY_OFFSET; LOW_WORD (obj_addr, name_addr) return name_addr; }/* object_name */ /* * first_property * * Calculate the start address of the property list associated with * an object. * */ static zword first_property (zword obj) { zword prop_addr; zbyte size; /* Fetch address of object name */ prop_addr = object_name (obj); /* Get length of object name */ LOW_BYTE (prop_addr, size) /* Add name length to pointer */ return prop_addr + 1 + 2 * size; }/* first_property */ /* * next_property * * Calculate the address of the next property in a property list. * */ static zword next_property (zword prop_addr) { zbyte value; /* Load the current property id */ LOW_BYTE (prop_addr, value) prop_addr++; /* Calculate the length of this property */ if (h_version <= V3) value >>= 5; else if (!(value & 0x80)) value >>= 6; else { LOW_BYTE (prop_addr, value) value &= 0x3f; if (value == 0) value = 64; /* demanded by Spec 1.0 */ } /* Add property length to current property pointer */ return prop_addr + value + 1; }/* next_property */ /* * unlink_object * * Unlink an object from its parent and siblings. * */ static void unlink_object (zword object) { zword obj_addr; zword parent_addr; zword sibling_addr; if (object == 0) { runtime_error (ERR_REMOVE_OBJECT_0); return; } obj_addr = object_address (object); if (h_version <= V3) { zbyte parent; zbyte younger_sibling; zbyte older_sibling; zbyte zero = 0; /* Get parent of object, and return if no parent */ obj_addr += O1_PARENT; LOW_BYTE (obj_addr, parent) if (!parent) return; /* Get (older) sibling of object and set both parent and sibling pointers to 0 */ SET_BYTE (obj_addr, zero) obj_addr += O1_SIBLING - O1_PARENT; LOW_BYTE (obj_addr, older_sibling) SET_BYTE (obj_addr, zero) /* Get first child of parent (the youngest sibling of the object) */ parent_addr = object_address (parent) + O1_CHILD; LOW_BYTE (parent_addr, younger_sibling) /* Remove object from the list of siblings */ if (younger_sibling == object) SET_BYTE (parent_addr, older_sibling) else { do { sibling_addr = object_address (younger_sibling) + O1_SIBLING; LOW_BYTE (sibling_addr, younger_sibling) } while (younger_sibling != object); SET_BYTE (sibling_addr, older_sibling) } } else { zword parent; zword younger_sibling; zword older_sibling; zword zero = 0; /* Get parent of object, and return if no parent */ obj_addr += O4_PARENT; LOW_WORD (obj_addr, parent) if (!parent) return; /* Get (older) sibling of object and set both parent and sibling pointers to 0 */ SET_WORD (obj_addr, zero) obj_addr += O4_SIBLING - O4_PARENT; LOW_WORD (obj_addr, older_sibling) SET_WORD (obj_addr, zero) /* Get first child of parent (the youngest sibling of the object) */ parent_addr = object_address (parent) + O4_CHILD; LOW_WORD (parent_addr, younger_sibling) /* Remove object from the list of siblings */ if (younger_sibling == object) SET_WORD (parent_addr, older_sibling) else { do { sibling_addr = object_address (younger_sibling) + O4_SIBLING; LOW_WORD (sibling_addr, younger_sibling) } while (younger_sibling != object); SET_WORD (sibling_addr, older_sibling) } } }/* unlink_object */ /* * z_clear_attr, clear an object attribute. * * zargs[0] = object * zargs[1] = number of attribute to be cleared * */ void z_clear_attr (void) { zword obj_addr; zbyte value; if (story_id == SHERLOCK) if (zargs[1] == 48) return; if (zargs[1] > ((h_version <= V3) ? 31 : 47)) runtime_error (ERR_ILL_ATTR); /* If we are monitoring attribute assignment display a short note */ if (f_setup.attribute_assignment) { stream_mssg_on (); print_string ("@clear_attr "); print_object (zargs[0]); print_string (" "); print_num (zargs[1]); stream_mssg_off (); } if (zargs[0] == 0) { runtime_error (ERR_CLEAR_ATTR_0); return; } /* Get attribute address */ obj_addr = object_address (zargs[0]) + zargs[1] / 8; /* Clear attribute bit */ LOW_BYTE (obj_addr, value) value &= ~(0x80 >> (zargs[1] & 7)); SET_BYTE (obj_addr, value) }/* z_clear_attr */ /* * z_jin, branch if the first object is inside the second. * * zargs[0] = first object * zargs[1] = second object * */ void z_jin (void) { zword obj_addr; /* If we are monitoring object locating display a short note */ if (f_setup.object_locating) { stream_mssg_on (); print_string ("@jin "); print_object (zargs[0]); print_string (" "); print_object (zargs[1]); stream_mssg_off (); } if (zargs[0] == 0) { runtime_error (ERR_JIN_0); branch (0 == zargs[1]); return; } obj_addr = object_address (zargs[0]); if (h_version <= V3) { zbyte parent; /* Get parent id from object */ obj_addr += O1_PARENT; LOW_BYTE (obj_addr, parent) /* Branch if the parent is obj2 */ branch (parent == zargs[1]); } else { zword parent; /* Get parent id from object */ obj_addr += O4_PARENT; LOW_WORD (obj_addr, parent) /* Branch if the parent is obj2 */ branch (parent == zargs[1]); } }/* z_jin */ /* * z_get_child, store the child of an object. * * zargs[0] = object * */ void z_get_child (void) { zword obj_addr; /* If we are monitoring object locating display a short note */ if (f_setup.object_locating) { stream_mssg_on (); print_string ("@get_child "); print_object (zargs[0]); stream_mssg_off (); } if (zargs[0] == 0) { runtime_error (ERR_GET_CHILD_0); store (0); branch (FALSE); return; } obj_addr = object_address (zargs[0]); if (h_version <= V3) { zbyte child; /* Get child id from object */ obj_addr += O1_CHILD; LOW_BYTE (obj_addr, child) /* Store child id and branch */ store (child); branch (child); } else { zword child; /* Get child id from object */ obj_addr += O4_CHILD; LOW_WORD (obj_addr, child) /* Store child id and branch */ store (child); branch (child); } }/* z_get_child */ /* * z_get_next_prop, store the number of the first or next property. * * zargs[0] = object * zargs[1] = address of current property (0 gets the first property) * */ void z_get_next_prop (void) { zword prop_addr; zbyte value; zbyte mask; if (zargs[0] == 0) { runtime_error (ERR_GET_NEXT_PROP_0); store (0); return; } /* Property id is in bottom five (six) bits */ mask = (h_version <= V3) ? 0x1f : 0x3f; /* Load address of first property */ prop_addr = first_property (zargs[0]); if (zargs[1] != 0) { /* Scan down the property list */ do { LOW_BYTE (prop_addr, value) prop_addr = next_property (prop_addr); } while ((value & mask) > zargs[1]); /* Exit if the property does not exist */ if ((value & mask) != zargs[1]) runtime_error (ERR_NO_PROP); } /* Return the property id */ LOW_BYTE (prop_addr, value) store ((zword) (value & mask)); }/* z_get_next_prop */ /* * z_get_parent, store the parent of an object. * * zargs[0] = object * */ void z_get_parent (void) { zword obj_addr; /* If we are monitoring object locating display a short note */ if (f_setup.object_locating) { stream_mssg_on (); print_string ("@get_parent "); print_object (zargs[0]); stream_mssg_off (); }