Exemple #1
0
def test_set_own_property_v5(zork_v5_obj_table: ZMachineObjectTable):
    # Property #46 is a two-byte property
    zorkmid = zork_v5_obj_table.object(122)

    zorkmid.properties.set(46, ZWord(b'\x12\x34'))
    assert ZWord(b'\x12\x34') == zorkmid.properties.value(46)

    you = zork_v5_obj_table.object(21)
    with pytest.raises(ZMachineIllegalOperation,
                       match='size 8 with a value of size '):
        you.properties.set(46, ZWord(b'\x12\x34'))
Exemple #2
0
def test_attributes_v5(zork_v5_obj_table: ZMachineObjectTable):
    cretin = zork_v5_obj_table.object(46)
    assert cretin.attributes == {23, 25, 31, 46}

    cretin.update_attribute(23, False)
    cretin.update_attribute(25, False)
    cretin.update_attribute(31, False)
    cretin.update_attribute(46, False)
    assert cretin.attributes == set()

    # Flip each attribute individually
    for i in range(48):
        cretin.update_attribute(i, True)
        assert cretin.attributes == {
            i
        }, f'attribute {i} should be set in the attributes set'
        assert cretin.is_attribute_set(
            i) == True, f'attribute {i} should be set'

        cretin.update_attribute(i, False)
        assert cretin.attributes == set(
        ), f'attribute {i} should be set in the attributes set'
        assert cretin.is_attribute_set(
            i) == False, f'attribute {i} should be set'

    # Gotta' set 'em all
    for i in range(48):
        cretin.update_attribute(i, True)

    assert cretin.attributes == set(range(48))
Exemple #3
0
def test_attributes_v3(zork_v3_obj_table: ZMachineObjectTable):
    cretin = zork_v3_obj_table.object(4)
    assert cretin.attributes == {7, 9, 14, 30}

    cretin.update_attribute(7, False)
    cretin.update_attribute(9, False)
    cretin.update_attribute(14, False)
    cretin.update_attribute(30, False)
    assert cretin.attributes == set()

    # Flip each attribute individually
    for i in range(32):
        cretin.update_attribute(i, True)
        assert cretin.attributes == {
            i
        }, f'attribute {i} should be set in the attributes set'
        assert cretin.is_attribute_set(
            i) == True, f'attribute {i} should be set'

        cretin.update_attribute(i, False)
        assert cretin.attributes == set(
        ), f'attribute {i} should be set in the attributes set'
        assert cretin.is_attribute_set(
            i) == False, f'attribute {i} should be set'

    # Gotta' set 'em all
    for i in range(32):
        cretin.update_attribute(i, True)

    assert cretin.attributes == set(range(32))
Exemple #4
0
def main(argv):
    header, data = header_and_data(argv[1])
    obj_table = ZMachineObjectTable(data, header)

    obj_num = int(argv[2])
    obj = obj_table.object(obj_num)
    print_object(obj_num, obj)

    return 0
Exemple #5
0
def main(argv):
    header, data = header_and_data(argv[1])
    obj_table = ZMachineObjectTable(data, header)

    for i in range(1, 223):
        if obj_table.object(i).parent == 0:
            obj_tree = obj_table.obj_tree(i)
            print_obj_tree(obj_tree)

    return 0
Exemple #6
0
def test_set_own_property_v3(zork_v3_obj_table: ZMachineObjectTable):
    # Property #16 is a single-byte property
    pair_of_hands = zork_v3_obj_table.object(1)

    # Set with a single byte
    pair_of_hands.properties.set(16, ZByte(b'\x42'))
    assert ZByte(b'\x42') == pair_of_hands.properties.value(16), \
        'a single byte property is set with a single byte value'

    # Set with two bytes
    pair_of_hands.properties.set(16, ZWord.from_int(-6))
    assert ZByte.from_int(-6) == pair_of_hands.properties.value(16), \
        'a single byte property is set with a two byte value'

    # Property #18 is a two-byte property
    zorkmid = zork_v3_obj_table.object(2)

    zorkmid.properties.set(18, ZWord(b'\x12\x34'))
    assert ZWord(b'\x12\x34') == zorkmid.properties.value(18)
Exemple #7
0
def test_remove_obj_from_parent_last_child_v3(
        zork_v3_obj_table: ZMachineObjectTable):
    zork_v3_obj_table.remove_obj_from_parent(160)
    west_of_house_tree = zork_v3_obj_table.obj_tree(180)

    assert len(west_of_house_tree['children']) == 1
    assert west_of_house_tree['children'][0]['number'] == 181

    small_mailbox_obj = zork_v3_obj_table.object(160)
    assert small_mailbox_obj.parent == 0
    assert small_mailbox_obj.sibling == 0
Exemple #8
0
def test_remove_obj_from_parent_first_child_v5(
        zork_v5_obj_table: ZMachineObjectTable):
    zork_v5_obj_table.remove_obj_from_parent(239)
    west_of_house_tree = zork_v5_obj_table.obj_tree(68)

    assert len(west_of_house_tree['children']) == 1
    assert west_of_house_tree['children'][0]['number'] == 127

    small_mailbox_obj = zork_v5_obj_table.object(239)
    assert small_mailbox_obj.parent == 0, 'object should no longer have a parent'
    assert small_mailbox_obj.sibling == 0, 'object should no longer have a sibling'
Exemple #9
0
def test_remove_obj_from_parent_first_child_v3(
        zork_v3_obj_table: ZMachineObjectTable):
    zork_v3_obj_table.remove_obj_from_parent(181)
    west_of_house_tree = zork_v3_obj_table.obj_tree(180)

    assert len(west_of_house_tree['children']) == 1
    assert west_of_house_tree['children'][0]['number'] == 160

    door_obj = zork_v3_obj_table.object(181)
    assert door_obj.parent == 0, 'object should no longer have a parent'
    assert door_obj.sibling == 0, 'object should no longer have a sibling'
Exemple #10
0
def test_remove_obj_from_parent_last_child_v5(
        zork_v5_obj_table: ZMachineObjectTable):
    zork_v5_obj_table.remove_obj_from_parent(127)
    west_of_house_tree = zork_v5_obj_table.obj_tree(68)

    assert len(west_of_house_tree['children']) == 1
    assert west_of_house_tree['children'][0]['number'] == 239

    door_obj = zork_v5_obj_table.object(127)
    assert door_obj.parent == 0
    assert door_obj.sibling == 0
Exemple #11
0
def test_remove_obj_from_parent_middle_child_v3(
        zork_v3_obj_table: ZMachineObjectTable):
    zork_v3_obj_table.remove_obj_from_parent(91)
    maintenance_room_tree = zork_v3_obj_table.obj_tree(199)

    assert len(maintenance_room_tree['children']) == 8
    assert maintenance_room_tree['children'][0]['number'] == 200
    assert maintenance_room_tree['children'][1]['number'] == 99

    wrench_obj = zork_v3_obj_table.object(91)
    assert wrench_obj.parent == 0
    assert wrench_obj.sibling == 0
Exemple #12
0
def test_default_properties_v5(zork_v5_obj_table: ZMachineObjectTable):
    door = zork_v5_obj_table.object(127)

    # Get default properties and spot check
    default_1 = door.properties.default_value(1)
    default_63 = door.properties.default_value(63)

    # ensure default falls through if own property isn't defined
    assert default_1 == door.properties.value_or_default(
        1), 'default property 1 should have been returned'
    assert default_63 == door.properties.value_or_default(
        63), 'default property 63 should have been returned'
Exemple #13
0
def test_remove_obj_from_parent_middle_child_v5(
        zork_v5_obj_table: ZMachineObjectTable):
    zork_v5_obj_table.remove_obj_from_parent(203)
    maintenance_room_tree = zork_v5_obj_table.obj_tree(233)

    assert len(maintenance_room_tree['children']) == 8
    assert maintenance_room_tree['children'][0]['number'] == 245
    assert maintenance_room_tree['children'][1]['number'] == 120

    tube_obj = zork_v5_obj_table.object(203)
    assert tube_obj.parent == 0
    assert tube_obj.sibling == 0
Exemple #14
0
def test_own_properties_v5(zork_v5_obj_table: ZMachineObjectTable):
    door = zork_v5_obj_table.object(127)

    # Get own properties
    own_properties = door.properties.all()
    assert 46 in own_properties
    assert own_properties[46] == ZWord(b'\x4d\xff')

    assert 45 in own_properties
    assert own_properties[45] == ZWord(b'\x3e\x24')

    assert 44 in own_properties
    assert own_properties[44].hex() == '50364a60'

    assert own_properties[46] == door.properties.value(46)
    assert own_properties[45] == door.properties.value(45)
    assert own_properties[44] == door.properties.value(44)
Exemple #15
0
def test_umem_quetzal_chunk(zork_v3_obj_table: ZMachineObjectTable):
    original_memory = bytes(zork_v3_obj_table._memory)

    cretin = zork_v3_obj_table.object(4)
    cretin.properties.set(18, ZWord(bytes.fromhex('ffff')))
    prop_address = cretin.properties.get(18).value_address

    cmem_chunk = UMemQuetzalChunk(zork_v3_obj_table._memory)

    restored_chunk, offset = UMemQuetzalChunk.read(cmem_chunk.bytes())
    assert offset == len(cmem_chunk.bytes())
    restored_memory = restored_chunk.saved_memory()

    for i in range(len(restored_memory)):
        if i not in [prop_address, prop_address + 1]:
            assert restored_memory[i] == original_memory[
                i], f'memory different at {hex(i)} should be different at {hex(prop_address)}'
        else:
            assert restored_memory[i] != original_memory[
                i], f'memory should be different at {hex(i)} for prop at address {hex(prop_address)}'
Exemple #16
0
def test_own_properties_v3(zork_v3_obj_table: ZMachineObjectTable):
    door = zork_v3_obj_table.object(181)

    # Get own properties
    own_properties = door.properties.all()
    assert 18 in own_properties
    assert own_properties[18] == ZWord(b'\x3f\x9d')

    assert 17 in own_properties
    assert own_properties[17] == ZWord(b'\x6d\x57')

    assert 16 in own_properties
    assert own_properties[16] == ZWord(b'\xc9\xca')

    assert own_properties[18] == door.properties.get(18).value
    assert own_properties[17] == door.properties.get(17).value
    assert own_properties[16] == door.properties.get(16).value

    assert own_properties[18] == door.properties.value(18)
    assert own_properties[17] == door.properties.value(17)
    assert own_properties[16] == door.properties.value(16)
Exemple #17
0
def test_first_own_property_v3(zork_v3_obj_table: ZMachineObjectTable):
    smelly_room = zork_v3_obj_table.object(22)
    first_prop = next(iter(smelly_room.properties))
    assert first_prop.number == 28
Exemple #18
0
def test_object_name_prop_v5(obj_num: int, expected_name: str,
                             zork_v5_obj_table: ZMachineObjectTable):
    assert zork_v5_obj_table.object(obj_num).name == expected_name
Exemple #19
0
def test_tree_v3(zork_v3_obj_table: ZMachineObjectTable):
    west_of_house = zork_v3_obj_table.object(180)
    assert west_of_house.parent == 82
    assert west_of_house.child == 181
    assert west_of_house.sibling == 15
Exemple #20
0
def compare_machine_state(interpreter: ZMachineInterpreter, state_data_dir: str, num_objects: int = 250) -> dict:
    """ Compare the state of the interpreter with state saved on disk.

    The files on disk should have the filenames of:
    * "mem-{step_num}" : binary file containing all of a Z-Machine's memory
    * "state-{step_num}.json" : JSON file containing machine state external to the memory in the following format,
                                note that all values are hexadecimal strings, not ints, and only the current routine
                                stack frame is accounted.
    ```json
    {
      "pc": "0x5479",                      # Program counter
      "local_vars": ["0x8010", "0xffff"],  # Local variables, in oder from 0-n
      "stack": [],                         # Routine stack
      "ret_var": "0x0",                    # Variable number to return value to
      "ret_pc": "0x4f0e"                   : PC to return to after routine exits
    }
    ```

    :param interpreter: Interpreter to compare the state to
    :param state_data_dir: Directory where state data can be found
    :param num_objects: Number of objects to scan
    :return: Differences in state on disk and interpreter
    """
    with open(path.join(state_data_dir, f'mem-{interpreter.step_count}'), 'br') as f:
        memory = f.read()

    with open(path.join(state_data_dir, f'state-{interpreter.step_count}.json'), 'r') as f:
        state = json.load(f)

    comp_header = get_header(memory)
    assert comp_header.version == interpreter.header.version

    diffs = dict()

    # Compare objects
    obj_table = ZMachineObjectTable(memory, comp_header)
    for obj_num in range(1, num_objects + 1):
        obj_diffs = dict()
        comp_obj = obj_table.object(obj_num)
        obj = interpreter.object_table.object(obj_num)

        if comp_obj.parent != obj.parent:
            obj_diffs['parent'] = dict(expected=comp_obj.parent,
                                       found=obj.parent)

        if comp_obj.sibling != obj.sibling:
            obj_diffs['sibling'] = dict(expected=comp_obj.sibling,
                                        found=obj.sibling)

        if comp_obj.child != obj.child:
            obj_diffs['child'] = dict(expected=comp_obj.child,
                                      found=obj.child)

        if comp_obj.attributes != obj.attributes:
            obj_diffs['attributes'] = dict(expected=comp_obj.attributes,
                                           found=obj.attributes)

        if comp_obj.properties.all() != obj.properties.all():
            obj_diffs['properties'] = dict(expected=comp_obj.properties.all(),
                                           found=obj.properties.all())

        if obj_diffs:
            diffs.setdefault('objects', dict())
            diffs['objects'][obj_num] = obj_diffs

    # Compare global variables
    variables = ZMachineVariables(memory, comp_header, ZMachineStack())
    for global_num in range(0xef):
        if variables.global_val(global_num) != interpreter.variables.global_val(global_num):
            diffs.setdefault('globals', dict())
            diffs['globals'][global_num] = dict(expected=variables.global_val(global_num),
                                                found=interpreter.variables.global_val(global_num))

    # Compare external state
    if state['pc'] != hex(int(interpreter.pc)):
        diffs['pc'] = dict(expected=state['pc'],
                           found=hex(int(interpreter.pc)))

    # Local vars
    if len(state['local_vars']) != len(interpreter.stack.routine_frame.local_vars):
        diffs['num_local_vars'] = dict(expected=len(state['local_vars']))
    else:
        for i in range(len(state['local_vars'])):
            expected = state['local_vars'][i]
            found = '0x' + interpreter.stack.routine_frame.local_vars[i].hex()
            if expected != found:
                diffs.setdefault('local_vars', {})
                diffs['local_vars'][i] = dict(expected=expected, found=found)

    # Routine stack
    if len(state['stack']) != len(interpreter.stack.routine_frame.stack_data):
        diffs['routine_stack_size'] = dict(expected=len(state['stack']),
                                           found=len(interpreter.stack.routine_frame.stack_data))
    else:
        for i in range(len(state['stack'])):
            expected = state['stack'][i]
            found = '0x' + interpreter.stack.routine_frame.stack_data[i].hex()

            if expected != found:
                diffs.setdefault('routine_stack', {})
                diffs['routine_stack'][i] = dict(expected=expected, found=found)

    # ret var
    found_res_var = '0x' + interpreter.stack.routine_frame.result_var.hex() if interpreter.stack.routine_frame.result_var is not None else None
    if state['ret_var'] != found_res_var:
        diffs['result_var'] = dict(expected=state['ret_var'], found=found_res_var)

    found_ret_pc = hex(int(interpreter.stack.routine_frame.return_pc)) if interpreter.stack.routine_frame.return_pc is not None else '0x0000'
    if state['ret_pc'] != found_ret_pc:
        diffs['return_pc'] = dict(expected=state['ret_pc'], found=found_ret_pc)

    return diffs