#!/usr/bin/env python3 # probes.py - the test games JoeyAGI's host gate runs (scripts/test-agi.sh) # and scripts/oracle.sh runs on Sierra's own interpreter for comparison. # # Each probe is a tiny AGI game built from scratch with agiGame.py plus an # input script (the format tests/hostPort.c and tests/tools/dosDrive.py # both read). Most probes record what the interpreter did, cycle by cycle, # into variables and print them with display at the end, so the result is # the same however fast the machine runs. # # probes.py build OUTDIR [NAME...] write OUTDIR/NAME/ (game + probe.scr) # probes.py list the probe names import os import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from agiGame import (Logic, cel, view, sound, writeGame, PIC_COLOR, PIC_NO_COLOR, PIC_PRIORITY, PIC_NO_PRIORITY, PIC_Y_CORNER, PIC_X_CORNER, PIC_LINE, PIC_REL_LINE, PIC_FILL, PIC_PEN, PIC_PLOT, PIC_END) # Variables and flags the interpreter owns (specification 3.4). V_ROOM = 0 V_EGO_EDGE = 2 V_OBJ_EDGE_OBJ = 4 V_OBJ_EDGE = 5 V_EGO_DIR = 6 V_BAD_WORD = 9 V_CYCLE_DELAY = 10 V_SECONDS = 11 V_MINUTES = 12 V_PRINT_TIMEOUT = 21 F_EGO_ON_WATER = 0 F_SAID_OK = 2 F_EGO_TOUCHING = 3 F_SAID_ACCEPTED = 4 F_NEW_ROOM = 5 F_SOUND = 9 # What the probes use for themselves. V_INIT = 200 V_PIC = 201 V_CYCLE = 212 PROBE_ROOM = 250 EMPTY_PIC = bytes([PIC_END]) DIR_RIGHT = 3 DIR_DOWN = 5 DIR_LEFT = 7 # ----- Shared resources ----- def walkerCel(c, loop): # 7x20: a head, a body with a marker that walks along it as the cel # changes, and legs that alternate - every cel looks different. head = ["..666..", ".66666.", ".66666.", "..666.."] body = [] for r in range(8): row = list("1111111") row[(c + r) % 7] = "e" if loop == 0: row[6] = "c" elif loop == 3: row[3] = "9" body.append("".join(row)) legs = ["22...22", ".22.22."] if c % 2 == 0 else [".22.22.", "22...22"] return cel(head + body + legs * 4, transparent=0) def walkerView(): # Loops 0 right, 1 left (loop 0 flipped), 2 front, 3 back. return view([[walkerCel(c, 0) for c in range(6)], ("mirror", 0), [walkerCel(c, 2) for c in range(4)], [walkerCel(c, 3) for c in range(4)]]) def boxView(): # Loop 0: one 12x8 box. Loop 1: five 8x8 cels for the loop commands. box = ["cccccccccccc"] + ["c4444444444c"] * 6 + ["cccccccccccc"] frames = [] for c in range(5): frames.append(cel(["%x" % (c + 9) * 8] * (c + 4) + ["a.a.a.a."] * (4 - c), transparent=0)) return view([[cel(box, transparent=0)], frames]) def itemView(): # An inventory close-up with a description, for show.obj. art = [] for r in range(12): art.append("".join("%x" % ((r + x) % 6 + 9) for x in range(20))) return view([[cel(art, transparent=0)]], description="A shiny test widget.\nIt does nothing at all.") def postView(): # A thin 3x40 post for priority tests. return view([[cel(["555"] * 40, transparent=0)]]) VIEWS = {0: walkerView(), 1: boxView(), 2: itemView(), 3: postView()} def roomLogic(body): # Logic 0 sends the game to the probe room; body(L) fills it in. L0 = Logic() with L0.If(("equaln", V_ROOM, 0)): L0.new_room(PROBE_ROOM) L0.call_v(V_ROOM) L0.return_() L = Logic() body(L) L.return_() return {0: L0.build(), PROBE_ROOM: L.build()} def showPic(L, num=1): L.assignn(V_PIC, num) L.load_pic(V_PIC) L.draw_pic(V_PIC) L.discard_pic(V_PIC) def series(L, rows, cycles, record, base=20, stride=13, sep=" "): # Record each row's value on cycles 1..cycles into v[base + i*stride + c], # then display the rows two cycles later. for c in range(1, cycles + 1): with L.If(("equaln", V_CYCLE, c)): for i, row in enumerate(rows): record(L, row, base + i * stride + c) with L.If(("equaln", V_CYCLE, cycles + 2)): for i, row in enumerate(rows): txt = row[0] + ":" + sep.join("%%v%d" % (base + i * stride + c) for c in range(1, cycles + 1)) L.display(i + 1, 0, L.m(txt)) def recordFlag(L, flag, var): with L.If(("isset", flag)): L.assignn(var, 1) # ----- Probes ----- def probePictures(): # Every picture command: colours on and off, corners, absolute and # relative lines, nested fills (visual, priority-only and both) and # every pen: solid and splatter, circle and rectangle, all sizes. p = bytearray() p += bytes([PIC_COLOR, 1, PIC_PRIORITY, 4, PIC_LINE, 0, 0, 159, 0, 159, 167, 0, 167, 0, 0]) p += bytes([PIC_COLOR, 2, PIC_PRIORITY, 7, PIC_LINE, 10, 10, 70, 10, 70, 60, 10, 60, 10, 10]) p += bytes([PIC_FILL, 30, 30]) p += bytes([PIC_COLOR, 14, PIC_LINE, 20, 20, 60, 50, PIC_LINE, 60, 20, 20, 50]) p += bytes([PIC_FILL, 40, 24, 22, 35, 58, 35]) p += bytes([PIC_NO_COLOR, PIC_PRIORITY, 11, PIC_LINE, 80, 10, 150, 10, 150, 60, 80, 60, 80, 10]) p += bytes([PIC_FILL, 100, 30]) p += bytes([PIC_COLOR, 4, PIC_NO_PRIORITY, PIC_Y_CORNER, 85, 15, 95, 25, 105, 35, 115]) p += bytes([PIC_X_CORNER, 120, 15, 130, 25, 140, 35]) p += bytes([PIC_COLOR, 5, PIC_PRIORITY, 9, PIC_REL_LINE, 100, 45, 0x22, 0x40, 0x06, 0xCC, 0x77, 0x71, 0x99]) p += bytes([PIC_COLOR, 6, PIC_LINE, 5, 70, 154, 160, PIC_LINE, 154, 70, 5, 160, PIC_LINE, 80, 66, 80, 166, PIC_LINE, 3, 115, 156, 115]) p += bytes([PIC_COLOR, 3, PIC_PRIORITY, 13, PIC_FILL, 80, 100, 40, 115, 120, 115, 80, 140]) x = 12 for pen in range(16): style = (0x20 if pen >= 8 else 0) | (0x10 if pen % 2 else 0) | (pen % 8) p += bytes([PIC_COLOR, 1 + (pen % 14), PIC_PRIORITY, 4 + (pen % 10), PIC_PEN, style, PIC_PLOT]) y = 78 if pen < 8 else 98 if style & 0x20: p += bytes([(pen * 13) & 0xFE, x, y, (pen * 29) & 0xFE, x + 4, y + 10]) else: p += bytes([x, y, x + 4, y + 10]) x = x + 18 if pen != 7 else 12 p += bytes([PIC_PEN, 0x00, PIC_PLOT, 150, 160, 151, 161]) p.append(PIC_END) def body(L): with L.If(("isset", F_NEW_ROOM)): showPic(L) L.show_pic() with L.If(("have.key",)): L.show_pri_screen() script = "wait 3\nshot visual\nkey Return\nwait 2\nshot priority\n" return dict(logics=roomLogic(body), pics={1: bytes(p)}), script def probeWindows(): # print wrapping (the 30-column default, long words, explicit breaks), # print.at, display, text attributes and the status line. msgs = ["Hello.", "This message is exactly thirty.", "A message that is a good deal longer than forty characters, so it must wrap across lines.", "Line one\nLine two is longer\nThree", "A lad of seventeen who has lived for as long as he can remember with a wizard, in a house on a mountain far from anywhere.", "Supercalifragilisticexpialidociousantidisestablishmentarianism word"] def body(L): with L.If(("isset", F_NEW_ROOM)): showPic(L) L.show_pic() for t in msgs: L.print(L.m(t)) L.print_at(L.m("print.at 2,3 width 20 with some text to wrap"), 2, 3, 20) L.print_at(L.m("print.at 10,2 width 25"), 10, 2, 25) L.display(22, 0, L.m("display at row 22 col 0")) L.set_text_attribute(14, 1) L.display(23, 5, L.m("attr 14,1 row 23 col 5")) L.print(L.m("after display")) L.status_line_on() L.print(L.m("status on")) L.clear_lines(22, 22, 0) L.print(L.m("row 22 cleared")) script = "wait 3\nshot w01\n" + "".join("key Return\nwait 1.5\nshot w%02d\n" % i for i in range(2, 13)) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}), script def probeTiming(): # Motion and animation counters cycle by cycle: step.size/step.time, # move.obj, end.of.loop, cycle.time and reverse.loop. N = 12 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) L.load_view(0) L.load_view(1) L.assignn(202, 1) L.assignn(203, DIR_RIGHT) L.assignn(204, 2) def mk(o, x, y, v, loop): L.animate_obj(o) L.set_view(o, v) L.set_loop(o, loop) L.set_cel(o, 0) L.position(o, x, y) L.ignore_objs(o) L.fix_loop(o) mk(1, 20, 60, 0, 0) L.set_dir(1, 203) L.draw(1) mk(2, 20, 100, 0, 0) L.draw(2) L.move_obj(2, 30, 100, 3, 50) mk(3, 20, 140, 1, 1) L.draw(3) L.end_of_loop(3, 51) mk(4, 90, 60, 0, 0) L.step_time(4, 204) L.set_dir(4, 203) L.draw(4) mk(5, 90, 100, 0, 0) L.cycle_time(5, 204) L.draw(5) mk(6, 90, 140, 1, 1) L.set_cel(6, 3) L.draw(6) L.reverse_loop(6, 52) L.show_pic() L.increment(V_CYCLE) rows = [("x1", lambda L, v: L.get_posn(1, v, 99)), ("c1", lambda L, v: L.current_cel(1, v)), ("x2", lambda L, v: L.get_posn(2, v, 99)), ("f50", lambda L, v: recordFlag(L, 50, v)), ("c3", lambda L, v: L.current_cel(3, v)), ("f51", lambda L, v: recordFlag(L, 51, v)), ("x4", lambda L, v: L.get_posn(4, v, 99)), ("c5", lambda L, v: L.current_cel(5, v)), ("c6", lambda L, v: L.current_cel(6, v)), ("f52", lambda L, v: recordFlag(L, 52, v))] with L.If(("equaln", V_CYCLE, N + 2)): for o in range(1, 7): L.erase(o) series(L, rows, N, lambda L, row, v: row[1](L, v)) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 5\nshot a\n" def probeMotion(): # step.size against move.obj's arrival, move.obj's own step size, # diagonal moves and a move to where the object already is. N = 12 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) L.load_view(0) L.assignn(202, 1) L.assignn(203, 2) L.assignn(204, 5) def mk(o, x, y): L.animate_obj(o) L.set_view(o, 0) L.set_loop(o, 0) L.set_cel(o, 0) L.position(o, x, y) L.ignore_objs(o) L.stop_cycling(o) mk(1, 20, 60) L.draw(1) L.move_obj(1, 31, 60, 3, 50) mk(2, 20, 80) L.step_size(2, 203) L.draw(2) L.move_obj(2, 31, 80, 3, 51) mk(3, 20, 100) L.step_size(3, 204) L.draw(3) L.move_obj(3, 31, 100, 0, 52) mk(4, 20, 140) L.draw(4) L.move_obj(4, 40, 120, 2, 53) mk(5, 100, 140) L.draw(5) L.move_obj(5, 100, 140, 2, 54) L.show_pic() L.increment(V_CYCLE) rows = [("x1", lambda L, v: L.get_posn(1, v, 19)), ("f50", lambda L, v: recordFlag(L, 50, v)), ("x2", lambda L, v: L.get_posn(2, v, 19)), ("f51", lambda L, v: recordFlag(L, 51, v)), ("x3", lambda L, v: L.get_posn(3, v, 19)), ("f52", lambda L, v: recordFlag(L, 52, v)), ("x4", lambda L, v: L.get_posn(4, v, 19)), ("y4", lambda L, v: L.get_posn(4, 19, v)), ("f53", lambda L, v: recordFlag(L, 53, v)), ("f54", lambda L, v: recordFlag(L, 54, v)), ("d1", lambda L, v: L.get_dir(1, v))] with L.If(("equaln", V_CYCLE, N + 2)): for o in range(1, 6): L.erase(o) series(L, rows, N, lambda L, row, v: row[1](L, v)) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 5\nshot a\n" def probeCounters(): # When step and cycle counters start: objects drawn before or after # set.dir, step.time and cycle.time, and end.of.loop on drawn objects. N = 12 tests = [("A", 1, 30, "x"), ("B", 2, 40, "x"), ("C", 3, 50, "x"), ("D", 4, 60, "x"), ("E", 5, 70, "x"), ("F", 6, 80, "x"), ("G", 7, 90, "c"), ("H", 8, 100, "c"), ("I", 9, 110, "c"), ("J", 10, 120, "x"), ("K", 11, 130, "x")] def body(L): def mk(o, y, loop=0): L.animate_obj(o) L.set_view(o, 0) L.set_loop(o, loop) L.set_cel(o, 0) L.position(o, 20, y) L.ignore_objs(o) L.fix_loop(o) L.stop_cycling(o) with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) L.load_view(0) for var, val in ((202, 1), (203, DIR_RIGHT), (204, 2), (205, 3)): L.assignn(var, val) mk(1, 30) L.set_dir(1, 203) L.draw(1) mk(2, 40) L.draw(2) L.set_dir(2, 203) mk(3, 50) L.step_time(3, 204) L.set_dir(3, 203) L.draw(3) mk(4, 60) L.draw(4) L.step_time(4, 204) L.set_dir(4, 203) mk(5, 70) L.step_time(5, 205) L.set_dir(5, 203) L.draw(5) mk(6, 80) L.step_time(6, 202) L.set_dir(6, 203) L.draw(6) mk(7, 90) L.cycle_time(7, 205) L.start_cycling(7) L.draw(7) mk(8, 100, 2) L.end_of_loop(8, 51) L.draw(8) mk(9, 110, 2) L.cycle_time(9, 204) L.draw(9) L.end_of_loop(9, 52) mk(10, 120) L.draw(10) L.show_pic() L.increment(V_CYCLE) with L.If(("equaln", V_CYCLE, 3)): L.set_dir(10, 203) mk(11, 130) L.set_dir(11, 203) L.draw(11) with L.If(("equaln", V_CYCLE, N + 2)): for t in tests: L.erase(t[1]) def record(L, t, v): if t[3] == "x": L.get_posn(t[1], v, 99) else: L.current_cel(t[1], v) series(L, tests, N, record) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 5\nshot a\n" def probeRedraw(): # What erase/draw, set.view, set.loop, set.cel, animate.obj and position # do to a moving object's position and counters. N = 12 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) L.load_view(0) L.assignn(203, DIR_RIGHT) for o in range(1, 8): L.animate_obj(o) L.set_view(o, 0) L.set_loop(o, 0) L.set_cel(o, 0) L.position(o, 20, 20 + 15 * o) L.ignore_objs(o) L.fix_loop(o) L.stop_cycling(o) L.set_dir(o, 203) L.draw(o) L.show_pic() L.increment(V_CYCLE) with L.If(("equaln", V_CYCLE, 5)): L.erase(1) L.set_view(1, 0) L.draw(1) L.erase(2) L.draw(2) L.erase(3) L.animate_obj(3) L.draw(3) L.erase(4) L.set_loop(4, 0) L.draw(4) L.erase(5) L.set_cel(5, 0) L.draw(5) L.set_view(6, 0) L.erase(7) L.position(7, 20, 125) L.draw(7) with L.If(("equaln", V_CYCLE, N + 2)): for o in range(1, 8): L.erase(o) rows = [("%d" % o, o) for o in range(1, 8)] series(L, rows, N, lambda L, row, v: L.get_posn(row[1], v, 19)) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 5\nshot a\n" def probeSetView(): # set.view and set.loop with loops and cels the new view lacks. def body(L): with L.If(("isset", F_NEW_ROOM)): showPic(L) for v in (0, 1, 2, 3): L.load_view(v) def mk(o, v, loop, c): L.animate_obj(o) L.set_view(o, v) L.set_loop(o, loop) L.set_cel(o, c) def rec(o, base): L.current_loop(o, base) L.current_cel(o, base + 1) L.current_view(o, base + 2) mk(1, 0, 3, 3) L.set_view(1, 1) rec(1, 150) mk(2, 0, 0, 5) L.set_loop(2, 2) rec(2, 153) mk(3, 0, 2, 3) L.set_view(3, 2) rec(3, 156) mk(4, 1, 1, 4) L.set_view(4, 3) rec(4, 159) mk(5, 0, 1, 2) L.set_view(5, 1) rec(5, 162) L.show_pic() L.display(1, 0, L.m("A %v150/%v151 B %v153/%v154 C %v156/%v157")) L.display(2, 0, L.m("D %v159/%v160 E %v162/%v163")) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 3\nshot a\n" def controlPicture(): # Control lines on the priority screen, drawn in matching colours. p = bytearray() def vline(pri, x, y0, y1, vis): p.extend([PIC_COLOR, vis, PIC_PRIORITY, pri, PIC_LINE, x, y0, x, y1]) vline(0, 60, 20, 60, 0) vline(1, 60, 70, 110, 1) vline(2, 60, 120, 140, 2) p.extend([PIC_COLOR, 3, PIC_PRIORITY, 3, PIC_LINE, 100, 145, 140, 145, 140, 165, 100, 165, 100, 145, PIC_FILL, 120, 155]) p.append(PIC_END) return bytes(p) def probeControl(): # Barriers (unconditional and conditional), signal lines, water and # land, and priority 15 ignoring them all; ego crossing a signal line # (f3) and the first object to reach an edge (v4, v5). Positions are # recorded at cycles 20, 60 and 140, then shown. objs = [(1, 40, ""), (2, 50, "ib"), (3, 80, ""), (4, 95, "ib"), (0, 130, ""), (6, 40, "p15"), (7, 90, "p15"), (8, 155, ""), (9, 155, "water"), (10, 100, "land")] snaps = (20, 60, 140) done = 150 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.load_view(0) L.assignn(202, 1) L.assignn(203, DIR_RIGHT) for (o, y, fl) in objs: L.animate_obj(o) L.set_view(o, 0) L.set_loop(o, 0) L.set_cel(o, 0) x = {8: 85, 9: 110}.get(o, 40) L.position(o, x, y) L.step_size(o, 202) L.step_time(o, 202) if "ib" in fl: L.ignore_blocks(o) if "p15" in fl: L.set_priority(o, 15) if fl == "water": L.object_on_water(o) if fl == "land": L.object_on_land(o) L.draw(o) L.set_dir(o, 203) L.show_pic() L.increment(V_CYCLE) with L.If(("!", "equaln", V_OBJ_EDGE, 0), ("equaln", 216, 0)): L.assignv(216, V_OBJ_EDGE_OBJ) L.assignv(217, V_OBJ_EDGE) L.assignv(218, V_CYCLE) with L.If(("isset", F_EGO_TOUCHING), ("equaln", 219, 0)): L.assignv(219, V_CYCLE) for k, when in enumerate(snaps): with L.If(("equaln", V_CYCLE, when)): for i, (o, y, fl) in enumerate(objs): L.get_posn(o, 150 + 10 * k + i, 99) with L.If(("equaln", V_CYCLE, done)): for (o, y, fl) in objs: L.erase(o) for k, when in enumerate(snaps): L.display(1 + 2 * k, 0, L.m("t%d: " % when + " ".join("%%v%d" % (150 + 10 * k + i) for i in range(5)))) L.display(2 + 2 * k, 0, L.m(" " + " ".join("%%v%d" % (150 + 10 * k + i) for i in range(5, 10)))) L.display(8, 0, L.m("edge obj %v216 edge %v217 at %v218")) L.display(9, 0, L.m("f3 first at %v219")) return dict(logics=roomLogic(body), pics={1: controlPicture()}, views=VIEWS), "wait 10\nshot a\n" def probeCollide(): # Objects meeting objects, and where draw puts an object that starts # on a barrier, on another object, off the edge or above the horizon. pic = bytes([PIC_NO_COLOR, PIC_PRIORITY, 0, PIC_LINE, 100, 120, 100, 160, PIC_LINE, 10, 150, 30, 150, PIC_END]) def body(L): def mk(o, x, y): L.animate_obj(o) L.set_view(o, 0) L.set_loop(o, 0) L.set_cel(o, 0) L.stop_cycling(o) L.position(o, x, y) with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) L.load_view(0) L.assignn(203, DIR_RIGHT) L.assignn(207, DIR_LEFT) L.assignn(205, DIR_DOWN) mk(1, 20, 40) L.draw(1) L.set_dir(1, 203) mk(2, 60, 40) L.draw(2) L.set_dir(2, 207) mk(3, 20, 60) L.draw(3) L.set_dir(3, 203) mk(4, 50, 60) L.draw(4) L.stop_update(4) mk(5, 70, 75) L.draw(5) L.set_dir(5, 205) mk(6, 68, 90) L.draw(6) L.stop_update(6) mk(7, 97, 130) L.draw(7) mk(8, 120, 100) L.draw(8) mk(9, 121, 100) L.draw(9) mk(10, 158, 110) L.draw(10) mk(11, 140, 20) L.draw(11) mk(12, 15, 150) L.draw(12) L.show_pic() L.increment(V_CYCLE) with L.If(("equaln", V_CYCLE, 30)): for o in range(1, 13): L.get_posn(o, 150 + 2 * o, 151 + 2 * o) for o in range(1, 13): L.erase(o) for row in range(3): txt = " ".join("%d:%%v%d,%%v%d" % (o, 150 + 2 * o, 151 + 2 * o) for o in range(1 + 4 * row, 5 + 4 * row)) L.display(row + 1, 0, L.m(txt)) return dict(logics=roomLogic(body), pics={1: pic}, views=VIEWS), "wait 6\nshot a\n" def probePriority(): # Objects at fixed priorities passing through a priority band and a # fixed-priority static object, then add.to.pic with every margin. pic = bytes([PIC_PRIORITY, 9, PIC_LINE, 0, 100, 159, 100, PIC_COLOR, 1, PIC_PRIORITY, 7, PIC_LINE, 0, 60, 159, 60, PIC_COLOR, 2, PIC_PRIORITY, 12, PIC_LINE, 0, 130, 159, 130, 159, 167, 0, 167, 0, 130, PIC_FILL, 80, 150, PIC_END]) def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) for v in (0, 1, 3): L.load_view(v) L.animate_obj(1) L.set_view(1, 1) L.position(1, 60, 120) L.set_priority(1, 12) L.ignore_objs(1) L.ignore_blocks(1) L.draw(1) L.stop_update(1) L.animate_obj(2) L.set_view(2, 0) L.position(2, 40, 122) L.set_priority(2, 6) L.ignore_objs(2) L.ignore_blocks(2) L.assignn(202, 1) L.step_size(2, 202) L.assignn(203, DIR_RIGHT) L.set_dir(2, 203) L.draw(2) L.animate_obj(3) L.set_view(3, 0) L.position(3, 30, 140) L.ignore_objs(3) L.set_dir(3, 203) L.draw(3) L.add_to_pic(0, 0, 0, 10, 50, 0, 4) L.add_to_pic(0, 0, 0, 25, 50, 12, 0) L.add_to_pic(0, 0, 0, 120, 90, 6, 1) L.add_to_pic(0, 2, 0, 135, 125, 0, 2) L.add_to_pic(0, 2, 1, 150, 125, 5, 3) L.add_to_pic(3, 0, 0, 100, 110, 15, 0) L.show_pic() with L.If(("have.key",)): L.show_pri_screen() L.increment(V_CYCLE) # Freeze everything where it is after 15 and 40 cycles. for when, row in ((15, 22), (40, 23)): with L.If(("equaln", V_CYCLE, when)): for o in (2, 3): L.stop_motion(o) L.stop_cycling(o) L.get_posn(2, 210, 211) L.get_posn(3, 213, 214) L.display(row, 0, L.m("c%d: 2 at %%v210,%%v211 3 at %%v213,%%v214" % when)) with L.If(("equaln", V_CYCLE, 25)): for o in (2, 3): L.start_motion(o) L.start_cycling(o) L.set_dir(o, 203) script = "wait 2\nshot a\nwait 3\nshot b\nkey Return\nwait 1\nshot p\n" return dict(logics=roomLogic(body), pics={1: pic}, views=VIEWS), script def probeFollow(): # follow.ego from near and far, with and without a bigger step. N = 9 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.load_view(0) L.animate_obj(0) L.set_view(0, 0) L.position(0, 80, 120) L.draw(0) L.animate_obj(1) L.set_view(1, 0) L.position(1, 20, 60) L.draw(1) L.follow_ego(1, 10, 50) L.animate_obj(2) L.set_view(2, 0) L.position(2, 140, 160) L.draw(2) L.follow_ego(2, 1, 51) L.assignn(202, 2) L.step_size(2, 202) L.show_pic() L.increment(V_CYCLE) for k in range(1, N + 1): with L.If(("equaln", V_CYCLE, 10 * k)): L.get_posn(1, 150 + k, 160 + k) L.get_posn(2, 170 + k, 180 + k) recordFlag(L, 50, 190 + k) recordFlag(L, 51, 230 + k) with L.If(("equaln", V_CYCLE, 10 * N + 2)): for o in range(3): L.erase(o) for row, (name, base) in enumerate((("x1", 150), ("y1", 160), ("x2", 170), ("y2", 180), ("f50", 190), ("f51", 230))): L.display(row + 1, 0, L.m(name + ":" + " ".join("%%v%d" % (base + k) for k in range(1, N + 1)))) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 7\nshot a\n" def probeEgo(): # The player walking ego with the arrow keys: x and loop for the first # 12 cycles of walking left, then ego stopped by a barrier, the bottom # edge (v2) and the horizon. A letter key shows the results. (The cel # depends on when the key went down, so it is left out.) N = 12 pic = bytes([PIC_COLOR, 0, PIC_PRIORITY, 0, PIC_LINE, 40, 0, 40, 100, PIC_END]) def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) L.load_view(0) L.animate_obj(0) L.set_view(0, 0) L.position(0, 80, 80) L.draw(0) L.show_pic() with L.If(("!", "equaln", V_EGO_DIR, 0), ("lessn", V_CYCLE, N)): L.increment(V_CYCLE) for c in range(1, N + 1): with L.If(("equaln", V_CYCLE, c)): L.get_posn(0, 150 + c, 99) L.current_loop(0, 165 + c) with L.If(("!", "equaln", V_EGO_EDGE, 0), ("equaln", 199, 0)): L.assignv(199, V_EGO_EDGE) L.get_posn(0, 197, 198) L.current_loop(0, 196) with L.If(("have.key",)): L.get_posn(0, 194, 195) L.current_loop(0, 193) L.erase(0) L.display(1, 0, L.m("x:" + " ".join("%%v%d" % (150 + c) for c in range(1, N + 1)))) L.display(2, 0, L.m("loop:" + " ".join("%%v%d" % (165 + c) for c in range(1, N + 1)))) L.display(4, 0, L.m("edge %v199 at %v197,%v198 loop %v196")) L.display(5, 0, L.m("end %v194,%v195 loop %v193 dir %v6")) script = "wait 2\nkey Left\nwait 6\nkey Down\nwait 10\nkey Up\nwait 15\nkey a\nwait 1\nshot a\n" return dict(logics=roomLogic(body), pics={1: pic}, views=VIEWS), script def probeEgoDirection(): # What steers ego: set.dir and v6 under player and program control, # and move.obj on ego. Each phase restarts ego at (80,100) and reads # its direction after 3 cycles and its position after 10. phases = [("A", lambda L: L.set_dir(0, 203)), ("B", lambda L: L.assignn(V_EGO_DIR, DIR_LEFT)), ("C", lambda L: (L.program_control(), L.set_dir(0, 205))), ("D", lambda L: L.assignn(V_EGO_DIR, 1)), ("E", lambda L: L.move_obj(0, 80, 60, 1, 60)), ("F", lambda L: (L.player_control(), L.set_dir(0, 207)))] def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.load_view(0) L.animate_obj(0) L.set_view(0, 0) L.position(0, 80, 100) L.draw(0) L.show_pic() L.assignn(203, DIR_RIGHT) L.assignn(205, DIR_DOWN) L.assignn(207, DIR_LEFT) L.increment(V_CYCLE) for i, (name, setup) in enumerate(phases): start = 5 + i * 12 with L.If(("equaln", V_CYCLE, start)): L.stop_motion(0) L.reposition_to(0, 80, 100) L.start_motion(0) setup(L) with L.If(("equaln", V_CYCLE, start + 3)): L.get_dir(0, 150 + 4 * i) L.assignv(151 + 4 * i, V_EGO_DIR) with L.If(("equaln", V_CYCLE, start + 10)): L.get_posn(0, 152 + 4 * i, 153 + 4 * i) with L.If(("equaln", V_CYCLE, 5 + 12 * len(phases))): L.erase(0) for i, (name, setup) in enumerate(phases): L.display(1 + i, 0, L.m("%s dir %%v%d v6 %%v%d at %%v%d,%%v%d" % (name, 150 + 4 * i, 151 + 4 * i, 152 + 4 * i, 153 + 4 * i))) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 6\nshot a\n" def probeSteering(): # The cycle a change of steering takes effect: v6 set by a logic, then # cleared; set.dir on ego; reposition.to and reposition of a walking # object; move.obj of an object and of ego. Each row is the x read by # the logic on seven cycles from the one before the change. rows = [("G", 0, 4), ("H", 0, 19), ("I", 1, 29), ("J", 2, 39), ("K", 0, 49), ("L", 1, 59)] def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.load_view(0) for o, x, y in ((0, 80, 100), (1, 20, 120), (2, 80, 140)): L.animate_obj(o) L.set_view(o, 0) L.position(o, x, y) L.draw(o) L.show_pic() L.assignn(203, DIR_RIGHT) L.assignn(207, DIR_LEFT) L.assignn(204, 5) L.assignn(205, 0) L.set_dir(1, 203) L.increment(V_CYCLE) with L.If(("equaln", V_CYCLE, 5)): L.assignn(V_EGO_DIR, DIR_RIGHT) with L.If(("equaln", V_CYCLE, 15)): L.assignn(V_EGO_DIR, 0) with L.If(("equaln", V_CYCLE, 20)): L.set_dir(0, 207) with L.If(("equaln", V_CYCLE, 30)): L.reposition_to(1, 80, 120) with L.If(("equaln", V_CYCLE, 40)): L.move_obj(2, 120, 140, 1, 61) with L.If(("equaln", V_CYCLE, 50)): L.move_obj(0, 120, 100, 1, 62) with L.If(("equaln", V_CYCLE, 60)): L.reposition(1, 204, 205) for i, (name, o, start) in enumerate(rows): for k in range(7): with L.If(("equaln", V_CYCLE, start + k)): L.get_posn(o, 100 + i * 10 + k, 99) with L.If(("equaln", V_CYCLE, 70)): for o in (0, 1, 2): L.erase(o) for i, (name, o, start) in enumerate(rows): L.display(1 + i, 0, L.m("%s c%d: " % (name, start) + " ".join("%%v%d" % (100 + i * 10 + k) for k in range(7)))) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 5\nshot a\n" def probeCycling(): # Cels of ego standing, walking (v6) and stopping, under player and # program control, beside an object that walks and is stopped by # stop.motion and one that never moves. N = 30 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.load_view(0) for o, y in ((0, 60), (1, 90), (2, 120)): L.animate_obj(o) L.set_view(o, 0) L.position(o, 80, y) L.draw(o) L.show_pic() L.assignn(203, DIR_RIGHT) L.increment(V_CYCLE) with L.If(("equaln", V_CYCLE, 5)): L.assignn(V_EGO_DIR, DIR_RIGHT) L.set_dir(2, 203) with L.If(("equaln", V_CYCLE, 10)): L.assignn(V_EGO_DIR, 0) L.stop_motion(2) with L.If(("equaln", V_CYCLE, 18)): L.program_control() with L.If(("equaln", V_CYCLE, 22)): L.assignn(V_EGO_DIR, DIR_RIGHT) with L.If(("equaln", V_CYCLE, 26)): L.assignn(V_EGO_DIR, 0) rows = [("e", 0), ("s", 1), ("w", 2)] with L.If(("equaln", V_CYCLE, N + 2)): for o in (0, 1, 2): L.erase(o) series(L, rows, N, lambda L, row, v: L.current_cel(row[1], v), base=100, stride=35, sep="") return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS), "wait 4\nshot a\n" def probeClock(): # A print with v21 set closes by itself after v21 half-seconds: # measured against the clock (v11 counts real seconds), each window # opening just after v11 ticks; the cycles from its closing to the # next tick give the fraction. Then windows that wait for Enter, with # a letter, space and Escape pressed at them. timeouts = [6, 4, 2, 1] phase = 230 prev = 231 index = 232 count = 233 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.show_pic() L.assignv(prev, V_SECONDS) for i, k in enumerate(timeouts): with L.If(("equaln", index, i)): with L.If(("equaln", phase, 0), ("!", "equalv", V_SECONDS, prev)): L.assignv(150 + 3 * i, V_SECONDS) L.assignn(V_PRINT_TIMEOUT, k) L.print(L.m("Timed window: v21=%d" % k)) L.assignn(V_PRINT_TIMEOUT, 0) L.assignv(prev, V_SECONDS) L.assignn(phase, 1) L.assignn(count, 0) with L.If(("equaln", phase, 1)): L.increment(count) with L.If(("!", "equalv", V_SECONDS, prev)): L.assignv(151 + 3 * i, V_SECONDS) L.assignv(152 + 3 * i, count) L.assignn(phase, 0) L.assignv(prev, V_SECONDS) L.increment(index) with L.If(("equaln", index, len(timeouts))): L.increment(index) for i, k in enumerate(timeouts): L.display(1 + i, 0, L.m("v21=%d: open at %%v%d, next tick %%v%d, %%v%d cycles after" % (k, 150 + 3 * i, 151 + 3 * i, 152 + 3 * i))) L.print(L.m("Press a letter key")) L.print(L.m("Press space")) L.print(L.m("Press Escape")) L.print(L.m("Done")) script = "wait 22\nshot k0\nkey a\nwait 1\nshot k1\nkey space\nwait 1\nshot k2\nkey Escape\nwait 1\nshot k3\n" return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}), script # Words for the parser probe. 0 is ignored, 1 is any word and 9999 the # rest of the line. VOCAB = {"the": 0, "a": 0, "at": 0, "look": 10, "examine": 10, "get": 11, "take": 11, "pick up": 11, "widget": 20, "box": 21, "door": 22, "open": 12, "inventory": 13, "inv": 13, "quit": 14, "show": 15} ITEMS = [("?", 0), ("test widget", 255), ("blue box", 250), ("old key", 0)] def probeParser(): # Typed input: said with synonyms, ignored words, multi-word entries, # anyword and rest-of-line; an unknown word (v9, f2/f4); the menu bar # and a menu item; the inventory screen and show.obj. ctl = {"file": 1, "about": 2, "inv": 3, "widget": 4, "off": 5, "menu": 20} def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 2) showPic(L) L.show_pic() L.load_view(2) L.status_line_on() L.accept_input() L.set_key(27, 0, ctl["menu"]) L.set_menu(L.m("File")) L.set_menu_item(L.m("About "), ctl["about"]) L.set_menu_item(L.m("Off item"), ctl["off"]) L.set_menu(L.m("Things")) L.set_menu_item(L.m("Inventory"), ctl["inv"]) L.set_menu_item(L.m("Widget "), ctl["widget"]) L.submit_menu() L.disable_item(ctl["off"]) with L.If(("controller", ctl["menu"])): L.menu_input() with L.If(("controller", ctl["about"])): L.print(L.m("About was chosen.")) with L.If(("or", [("controller", ctl["inv"]), ("said", 13)])): L.status() with L.If(("controller", ctl["widget"])): L.show_obj(2) with L.If(("said", 10)): L.print(L.m("You look around.")) with L.If(("said", 10, 20)): L.print(L.m("It is a widget.")) with L.If(("said", 11, 20)): L.get(1) L.print(L.m("Taken.")) with L.If(("said", 11, 1)): L.print(L.m("Take what? (%w2)")) with L.If(("said", 12, 9999)): L.print(L.m("Open: rest of line.")) with L.If(("isset", F_SAID_OK), ("!", "isset", F_SAID_ACCEPTED)): L.print(L.m("No match. v9=%v9")) L.display(22, 0, L.m("f2=%v214 f4=%v215 v9=%v9 ")) L.assignn(214, 0) L.assignn(215, 0) recordFlag(L, F_SAID_OK, 214) recordFlag(L, F_SAID_ACCEPTED, 215) script = ("wait 2\nshot p01\n" "type look\nkey Return\nwait 1\nshot p02\nkey Return\nwait 1\n" "type look at the widget\nkey Return\nwait 1\nshot p03\nkey Return\nwait 1\n" "type examine box\nkey Return\nwait 1\nshot p04\nkey Return\nwait 1\n" "type take box\nkey Return\nwait 1\nshot p05\nkey Return\nwait 1\n" "type pick up widget\nkey Return\nwait 1\nshot p06\nkey Return\nwait 1\n" "type open the door now\nkey Return\nwait 1\nshot p07\nkey Return\nwait 1\n" "type xyzzy plugh\nkey Return\nwait 1\nshot p08\nkey Return\nwait 1\n" "type look widget, please\nkey Return\nwait 1\nshot p09\nkey Return\nwait 1\n" "type inv\nkey Return\nwait 1\nshot p10\nkey Return\nwait 1\n" "key Escape\nwait 1\nshot m01\nkey Down\nwait 0.5\nshot m02\nkey Return\nwait 1\nshot m03\nkey Return\nwait 1\n" "key Escape\nwait 1\nkey Right\nwait 0.5\nshot m04\nkey Down\nwait 0.5\nkey Return\nwait 1\nshot m05\nkey Return\nwait 1\n" "key Escape\nwait 1\nkey Right\nwait 0.5\nkey Return\nwait 1\nshot m06\nkey Return\nwait 1\nshot m07\n") return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, views=VIEWS, vocabulary=VOCAB, items=ITEMS), script def probeSound(): # When a sound's flag is set: tunes of known lengths (1/60 s ticks), # one note or many; the first voice decides, however long the others # (Sierra's PC interpreter plays only that one), an empty first voice # ends at once; a sound started with sound off (f9 clear) and one cut # short by stop.sound. Shown as cycles after the start. tunes = {1: sound([[(30, 254, 2), (30, 190, 2)], [(20, 300, 4)], [], [(40, 4, 8)]]), 2: sound([[(6, 254, 2)]]), 3: sound([[(120, 254, 2)]]), 4: sound([[(3, 254 - k, 2) for k in range(20)]]), 5: sound([[(21, 254, 2)], [(60, 200, 2)], [(90, 180, 2)], [(120, 4, 2)]]), 6: sound([[], [(60, 200, 2)]])} # (sound, flag, start cycle, sound on?) plays = [(1, 60, 3, True), (2, 61, 30, True), (3, 62, 40, True), (4, 63, 90, True), (1, 64, 120, False), (3, 65, 125, True), (5, 66, 140, True), (6, 67, 160, True)] stopAt = 130 showAt = 170 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.show_pic() for n in tunes: L.load_sound(n) L.increment(V_CYCLE) for i, (n, flag, start, on) in enumerate(plays): with L.If(("equaln", V_CYCLE, start)): if on: L.set(F_SOUND) else: L.reset(F_SOUND) L.sound(n, flag) with L.If(("isset", flag), ("equaln", 220 + i, 0)): L.assignv(220 + i, V_CYCLE) L.subn(220 + i, start) with L.If(("equaln", V_CYCLE, stopAt)): L.stop_sound() with L.If(("equaln", V_CYCLE, showAt)): L.display(1, 0, L.m("4 voices %v220 6 ticks %v221")) L.display(2, 0, L.m("120 ticks %v222 20 notes %v223")) L.display(3, 0, L.m("sound off %v224 stopped %v225")) L.display(4, 0, L.m("long tails %v226 no voice 0 %v227")) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}, sounds=tunes), "wait 10\nshot a\n" def probeTextScreen(): # The text screen: attributes, display, clear.lines, then back to the # picture. def body(L): with L.If(("isset", F_NEW_ROOM)): showPic(L) L.show_pic() L.status_line_on() with L.If(("have.key",)): L.increment(V_CYCLE) with L.If(("equaln", V_CYCLE, 1)): L.text_screen() L.display(2, 2, L.m("Text screen, default colours")) L.set_text_attribute(14, 1) L.display(4, 2, L.m("Yellow on blue")) L.set_text_attribute(0, 15) L.display(6, 2, L.m("Black on white")) L.clear_lines(10, 12, 4) L.set_text_attribute(15, 0) with L.If(("equaln", V_CYCLE, 2)): L.graphics() script = "wait 2\nshot g1\nkey Return\nwait 1\nshot t1\nkey Return\nwait 1\nshot g2\n" return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}), script def probeFont(): # Every printable character, for reading text in screenshots # (tests/tools/compareFrames.py --fonts). rows = ['!"#$&\'()*+,-./0123456789:;<=>?', '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^', '_`abcdefghijklmnopqrstuvwxyz{|', '}~'] def body(L): with L.If(("isset", F_NEW_ROOM)): for i, text in enumerate(rows): L.display(i, 0, L.m(text)) return dict(logics=roomLogic(body)), "wait 3\nshot font\n" def probeShake(): # shake.screen(1), (2) and (3): the whole screen -- picture, status # line, displayed text and the input line -- moves and comes back, # recorded frame by frame (tests/tools/shakeMeasure.py reads it). pic = bytes([PIC_COLOR, 1, PIC_LINE, 0, 0, 0, 167, PIC_COLOR, 2, PIC_LINE, 159, 0, 159, 167, PIC_COLOR, 4, PIC_LINE, 0, 0, 159, 0, PIC_COLOR, 5, PIC_LINE, 0, 167, 159, 167, PIC_COLOR, 0, PIC_LINE, 80, 20, 80, 150, PIC_LINE, 20, 84, 140, 84, PIC_COLOR, 3, PIC_LINE, 30, 30, 50, 30, 50, 50, 30, 50, 30, 30, PIC_FILL, 40, 40, PIC_END]) def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.load_view(0) L.animate_obj(0) L.set_view(0, 0) L.position(0, 100, 120) L.stop_cycling(0) L.draw(0) L.show_pic() L.status_line_on() L.set_string(0, L.m(">")) L.set_cursor_char(L.m("_")) L.accept_input() L.display(22, 0, L.m("row 22 display text")) L.increment(V_CYCLE) for when, times in ((20, 1), (40, 2), (60, 3)): with L.If(("equaln", V_CYCLE, when)): L.shake_screen(times) return dict(logics=roomLogic(body), pics={1: pic}, views=VIEWS), "wait 0.5\nrecord shake\nwait 12\nstop\n" def probeWindowEdge(): # print.at windows at columns 0, 1 and 2 on a coloured picture. Sierra's # interpreter keeps a window's x in a byte and walks the screen as one # line of 160-pixel rows, so a box left of the screen (column 0 or 1) # is saved, filled and put back 256 pixels on -- a row down, 96 in -- # and runs on into the row below; closing it leaves part of the window # behind. The texts have spaces where a restore cuts through a cell (an # interpreter's font shows there only in part). pic = bytes([PIC_COLOR, 2, PIC_FILL, 80, 80, PIC_COLOR, 1, PIC_LINE, 0, 0, 159, 167, PIC_LINE, 0, 100, 159, 20, PIC_END]) cases = [(5, 0, 0, "AAAA"), (5, 1, 0, "BBBB"), (5, 1, 20, "DDDD DDDD DDDD DDDD DDDD DDDD DDDD"), (5, 2, 0, "CCCC"), (12, 1, 36, "AAAAAAAAA BBBBBBBBB CC DDDDDDDDDDD"), (5, 3, 0, "EEEE"), (2, 1, 0, "F"), (15, 1, 10, "GGGG GGGG GGGG GGGG GGGG GGGG"), (5, 0, 30, "HHHHHHHHHHHHHH HHHHHHH HHHHHH HHHH HHHH")] step = 230 wait = 231 def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.show_pic() L.assignn(wait, 20) with L.If(("greatern", wait, 0)): L.decrement(wait) with L.If(("equaln", wait, 0)): for k, (row, col, width, text) in enumerate(cases): with L.If(("equaln", step, k)): showPic(L) L.show_pic() L.print_at(L.m(text), row, col, width) L.assignn(wait, 20) L.increment(step) script = "".join("wait 1.5\nshot e%d_open\nkey Return\nwait 0.5\nshot e%d_closed\n" % (k, k) for k in range(len(cases))) return dict(logics=roomLogic(body), pics={1: pic}), script def probeCursor(): # The command line's echo when set.cursor.char changes mid-line (F1 # takes the cursor away, F2 makes it '#', F3 '*'). Sierra's interpreter # echoes from where it last left off and steps back over the cursor # before each character whenever there is one -- drawn or not -- so a # cursor set mid-line overwrites the last character typed, and rubbing # out can run back over the prompt; a cursor taken away is left on the # line. keys = {"F1": (59, 1, ""), "F2": (60, 2, "#"), "F3": (61, 3, "*")} def body(L): with L.If(("isset", F_NEW_ROOM)): L.assignn(V_CYCLE_DELAY, 1) showPic(L) L.show_pic() L.set_string(0, L.m(">")) L.set_cursor_char(L.m("_")) L.accept_input() for scan, controller, _ in keys.values(): L.set_key(0, scan, controller) for _, controller, cursor in keys.values(): with L.If(("controller", controller)): L.set_cursor_char(L.m(cursor)) steps = ["type abc", "c1", "key BackSpace", "c2", "key BackSpace", "c3", "type d", "c4", "key Return", "c5", "type pq", "c6", "key F1", "type r", "c7", "key BackSpace", "c8", "key BackSpace", "c9", "key F2", "type st", "d1", "key BackSpace", "d2", "key Return", "d3", "type uv", "d4", "key F1", "key Return", "d5", "type wx", "d6", "key BackSpace", "d7", "key F3", "type yz", "d8", "key BackSpace", "d9", "key BackSpace", "e1", "key BackSpace", "e2"] script = "wait 2\n" + "".join(("%s\nwait 0.5\n" % st) if " " in st else ("shot %s\n" % st) for st in steps) return dict(logics=roomLogic(body), pics={1: EMPTY_PIC}), script PROBES = { "font": probeFont, "pictures": probePictures, "windows": probeWindows, "timing": probeTiming, "motion": probeMotion, "counters": probeCounters, "redraw": probeRedraw, "setview": probeSetView, "control": probeControl, "collide": probeCollide, "priority": probePriority, "follow": probeFollow, "ego": probeEgo, "egodir": probeEgoDirection, "steering": probeSteering, "cycling": probeCycling, "clock": probeClock, "parser": probeParser, "sound": probeSound, "textscreen": probeTextScreen, "shake": probeShake, "winedge": probeWindowEdge, "cursor": probeCursor, } def build(outDir, names): for name in names: resources, script = PROBES[name]() path = os.path.join(outDir, name) writeGame(path, **resources) with open(os.path.join(path, "probe.scr"), "w") as f: f.write(script) if __name__ == "__main__": if len(sys.argv) >= 2 and sys.argv[1] == "list": print("\n".join(PROBES)) elif len(sys.argv) >= 3 and sys.argv[1] == "build": build(sys.argv[2], sys.argv[3:] or list(PROBES)) else: sys.exit("usage: probes.py build OUTDIR [NAME...] | probes.py list")