1002 lines · 17.9 KB · C
RawDownload
/* 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t