1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
// Provenance: own design — shared run scripts (spec §6; one hook shape for §4.2 capabilities, see Actions)
namespace Godosa.Core.Runs.Scripts;
/// <summary>A game's run-script adapter. <see cref="Actions"/> holds the lib's game-hooked verbs by their lib name
/// (<c>talk</c>, <c>walk-to</c>, <c>cheat</c>, …) and the game's own verbs. Player-kind actions return input plans only;
/// the lib injects them.</summary>
public interface IRunGame
{
string Name { get; }
string ContentVersion { get; }
IInputRouter Input { get; }
IReadOnlyDictionary<string, IProbe> Probes { get; }
IReadOnlyDictionary<string, long> Constants { get; }
IReadOnlyDictionary<string, ILocator> Locators { get; }
IReadOnlyDictionary<string, IRunAction> Actions { get; }
IRunRng? Rng { get; }
bool SupportsSnapshot { get; }
byte[] SnapshotSave();
/// <summary>Why the current state can't be checkpointed faithfully (e.g. state the snapshot doesn't hold), or null.
/// A refused checkpoint is not cached (warning); failure snapshots are still taken.</summary>
string? SnapshotRefusal() => null;
void SnapshotRestore(byte[] data);
/// <summary>The restore completes after this frame (a window rebuilds its game view): the runner pauses one frame
/// (<see cref="ScriptRunner.Restoring"/>), in which the host advances no game frame.</summary>
bool RestoreDeferred => false;
ulong Digest();
string Dump();
void Advance();
}
public interface IProbe
{
int MinArgs { get; }
int MaxArgs { get; }
RunValue Eval(IReadOnlyList<string> args);
}
public readonly record struct LocatorResult(int X, int Y, string? Error)
{
public static LocatorResult Ok(int x, int y) => new(x, y, null);
public static LocatorResult Fail(string message) => new(0, 0, message);
public bool IsOk => Error == null;
}
/// <summary>Finds where to aim (virtual-screen position) from game state, as a player reads the screen.</summary>
public interface ILocator
{
LocatorResult Locate(IReadOnlyList<string> args);
}
/// <summary>Begin returns an input plan to inject (player) and/or an immediate status (debug: usually Done); after the
/// plan is sent, Poll runs each frame until Done or Fault.</summary>
public interface IRunAction
{
VerbKind Kind { get; }
int MinArgs { get; }
int MaxArgs { get; }
ActionStart Begin(IReadOnlyList<string> args);
StepStatus Poll();
}
public sealed record ActionStart(InputPlan? Plan = null, StepStatus? Status = null);
public interface IRunRng
{
void Seed(long seed);
void ForceNext(string kind, long value);
}
|