1257 lines
48 KiB
Python
Executable file
1257 lines
48 KiB
Python
Executable file
#!/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")
|