Universität Ulm,
Fakultät für Mathematik und Wirtschaftswissenschaften,
SAI
SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library
MODULE Matches
MODULE Matches;
IMPORT ChessClocks, Clocks, Cmds, Conclusions, Conditions, ConstStrings,
Errors, EventConditions, Events, InetTCP, Iterators, Names, Networks,
Paths, Print, Process, Puzzle, PuzzleGames, PuzzleIO, PuzzlePlayers,
Read, RelatedEvents, RemoteChessClocks, RemoteEvents, RemoteObjects,
RemotePGs, RemotePuzzlePlayers, RobustObjects, Services,
StandardPuzzleGames, Streams, Strings, SysSignals, Tasks, Terminals,
Times, UnixNames, UnixTerminals, Write;
CONST
prompt = ": ";
CONST
playerdir = "/etc/puzzle/players";
gamedir = "/etc/puzzle/games";
VAR
errors: RelatedEvents.Object;
PROCEDURE OpenAllKindsOfPorts;
VAR
network: Networks.Network;
it: Iterators.Iterator;
port: Networks.Socket;
address: Networks.Address;
errors: RelatedEvents.Object;
BEGIN
NEW(errors); RelatedEvents.QueueEvents(errors);
Networks.GetNetworks(it);
WHILE Iterators.Get(it, network) DO
IF ~Networks.CreateSomeSocket(port, network, address, errors) OR
~RemoteObjects.AddPort(port, address, errors) THEN
Conclusions.Conclude(errors, Errors.error, "open ports");
END;
END;
END OpenAllKindsOfPorts;
PROCEDURE MakePath(dir, name: ARRAY OF CHAR; VAR path: ARRAY OF CHAR);
BEGIN
COPY(dir, path);
Strings.Concatenate(path, "/");
Strings.Concatenate(path, name);
END MakePath;
PROCEDURE CheckExistance(path: ARRAY OF CHAR) : BOOLEAN;
VAR
node: Names.Node;
BEGIN
IF ~Paths.GetNode(path, NIL, errors, node) THEN
Conclusions.Conclude(errors, Errors.error, path);
RETURN FALSE
END;
RETURN TRUE
END CheckExistance;
PROCEDURE ListDir(dir: ARRAY OF CHAR);
VAR
dirnode: Names.Node;
members: Iterators.Iterator;
member: ConstStrings.String;
BEGIN
IF ~Paths.GetNode(dir, NIL, errors, dirnode) THEN
Conclusions.Conclude(errors, Errors.error, dir);
END;
IF ~Names.GetMembers(dirnode, NIL, members) THEN
Conclusions.Conclude(dirnode, Errors.error, dir);
END;
WHILE Iterators.Get(members, member) DO
ConstStrings.Write(Streams.stdout, member); Write.Ln;
END;
END ListDir;
PROCEDURE GameListing;
VAR
dirnode: Names.Node;
gameType: Services.Type;
members: Iterators.Iterator;
member: ConstStrings.String;
match: ARRAY 80 OF CHAR;
path: ARRAY 512 OF CHAR;
game: PuzzleGames.Game;
name: ARRAY 2, 80 OF CHAR;
situation: Puzzle.Situation;
chessclock: ChessClocks.ChessClock;
PROCEDURE PrintTimeOfClock(index: SHORTINT);
VAR
clock: Clocks.Clock;
time: Times.Time;
timeval: Times.TimeValueRec;
BEGIN
ChessClocks.GetClock(chessclock, index, clock);
Clocks.GetTime(clock, time);
Times.GetValue(time, timeval);
Print.F2(" [%02d:%02d]",
timeval.second DIV 60, timeval.second MOD 60);
END PrintTimeOfClock;
BEGIN (* GameListing *)
IF ~Paths.GetNode(gamedir, NIL, errors, dirnode) THEN
Conclusions.Conclude(errors, Errors.error, gamedir);
END;
IF ~Names.GetMembers(dirnode, NIL, members) THEN
Conclusions.Conclude(dirnode, Errors.error, gamedir);
END;
WHILE Iterators.Get(members, member) DO
ConstStrings.Extract(match, member);
MakePath(gamedir, match, path);
Services.SeekType("PuzzleGames.Game", gameType);
IF ~RobustObjects.GuardedImport(game, gameType, path, NIL, errors) THEN
Conclusions.Conclude(errors, Errors.error, path); RETURN
END;
PuzzleGames.GetNames(game, name[0], name[1]);
PuzzleGames.GetCurrentSituation(game, situation);
Print.F1("%-16s ", match);
IF Puzzle.Finished(situation) THEN
Print.F("F");
ELSE
Print.F("R");
END;
Print.F2(" %02d:%02d",
Puzzle.NumberOfPieces(situation, 0),
Puzzle.NumberOfPieces(situation, 1));
PuzzleGames.GetChessClock(game, chessclock);
IF chessclock # NIL THEN
PrintTimeOfClock(0); PrintTimeOfClock(1);
ELSE
Write.String(" "); Write.String(" ");
END;
Print.F2(" %s vs %s\n", name[0], name[1]);
END;
END GameListing;
PROCEDURE Replay(match: ARRAY OF CHAR);
VAR
path: ARRAY 512 OF CHAR;
gameType: Services.Type;
game: PuzzleGames.Game;
name: ARRAY 2 OF ARRAY 80 OF CHAR;
situation: Puzzle.Situation;
it: Iterators.Iterator;
move: Puzzle.Move;
answer: ARRAY 10 OF CHAR;
BEGIN
MakePath(gamedir, match, path);
IF ~CheckExistance(path) THEN RETURN END;
Services.SeekType("PuzzleGames.Game", gameType);
IF ~RobustObjects.GuardedImport(game, gameType, path, NIL, errors) THEN
Conclusions.Conclude(errors, Errors.error, path); RETURN
END;
PuzzleGames.GetNames(game, name[0], name[1]);
Write.String(name[0]); Write.String(" vs "); Write.String(name[1]);
Write.Line(":");
Puzzle.CreateSituation(situation);
PuzzleGames.IterateMoves(game, it);
PuzzleIO.PrintSituation(Terminals.console, situation);
WHILE Iterators.Get(it, move) &
Puzzle.Valid(situation, move, Puzzle.Onturn(situation)) DO
Write.String("Continue? "); Read.Line(answer);
IF answer[0] = "n" THEN RETURN END;
PuzzleIO.PrintMove(Terminals.console, move); Write.Ln;
Puzzle.MakeMove(situation, move, Puzzle.Onturn(situation));
PuzzleIO.PrintSituation(Terminals.console, situation);
END;
END Replay;
PROCEDURE Kiebitz(match: ARRAY OF CHAR; wait: BOOLEAN);
VAR
path: ARRAY 512 OF CHAR;
gameType: Services.Type;
game: PuzzleGames.Game;
name: ARRAY 2 OF ARRAY 80 OF CHAR;
situation: Puzzle.Situation;
eventType: Events.EventType; event: Events.Event;
eventcond, termcond: Conditions.Condition;
conditions: Conditions.ConditionSet;
BEGIN
MakePath(gamedir, match, path);
IF ~wait & ~CheckExistance(path) THEN RETURN END;
Services.SeekType("PuzzleGames.Game", gameType);
IF ~RobustObjects.GuardedImport(game, gameType, path, NIL, errors) THEN
Conclusions.Conclude(errors, Errors.error, path); RETURN
END;
PuzzleGames.GetNames(game, name[0], name[1]);
Write.String(name[0]); Write.String(" vs "); Write.String(name[1]);
Write.Line(":");
PuzzleGames.GetCurrentSituation(game, situation);
PuzzleIO.PrintSituation(Streams.stdout, situation);
PuzzleGames.TakeInterest(game, eventType);
EventConditions.Create(eventcond, eventType);
EventConditions.Create(termcond, SysSignals.INT);
Conditions.CreateSet(conditions);
Conditions.Incl(conditions, eventcond);
Conditions.Incl(conditions, termcond);
Write.Line("Press CTRL-c to abort kiebitz mode.");
LOOP
Tasks.WaitForOneOf(conditions);
IF Conditions.Test(termcond, NIL) THEN EXIT END;
WHILE EventConditions.TestAndGet(eventcond, event) DO
IF event IS PuzzleGames.Event THEN
WITH event: PuzzleGames.Event DO
PuzzleIO.PrintMove(Streams.stdout, event.move); Write.Ln;
PuzzleIO.PrintSituation(Streams.stdout, event.situation);
END;
END;
END;
END;
EventConditions.Drop(eventcond);
EventConditions.Drop(termcond);
END Kiebitz;
PROCEDURE Match(player1, player2, match: ARRAY OF CHAR;
timelimit: Times.Time);
VAR
pl1, pl2: PuzzlePlayers.Player;
path1, path2, matchpath: ARRAY 512 OF CHAR;
playerType: Services.Type;
game: PuzzleGames.Game;
BEGIN (* Match *)
MakePath(playerdir, player1, path1);
MakePath(playerdir, player2, path2);
IF ~CheckExistance(path1) OR ~CheckExistance(path2) THEN RETURN END;
Services.SeekType("PuzzlePlayers.Player", playerType);
IF ~RobustObjects.GuardedImport(pl1, playerType, path1, NIL, errors) THEN
Conclusions.Conclude(errors, Errors.error, path1); RETURN
END;
IF ~RobustObjects.GuardedImport(pl2, playerType, path2, NIL, errors) THEN
Conclusions.Conclude(errors, Errors.error, path2); RETURN
END;
StandardPuzzleGames.Create(game, pl1, pl2, player1, player2, timelimit);
MakePath(gamedir, match, matchpath);
IF ~RobustObjects.Export(game, NIL, matchpath, NIL, errors) THEN
Conclusions.Conclude(errors, Errors.error, matchpath);
END;
END Match;
PROCEDURE DoCmds;
CONST
matchC = 0; quitC = 1; gamesC = 2; playersC = 3; kiebitzC = 4;
replayC = 5;
VAR
s: Streams.Stream;
nfields: INTEGER;
fields: ARRAY 4 OF ARRAY 80 OF CHAR;
timelimit: Times.Time; tls: Streams.Stream; tli: INTEGER;
wait: BOOLEAN;
BEGIN
s := Streams.stdin;
Cmds.Add(s, gamesC, "games", 0, 1, "[-l]", "list running games");
Cmds.Add(s, kiebitzC, "kiebitz", 1, 2, "[-w] name",
"look at running game");
Cmds.Add(s, matchC, "match", 3, 4, "name pl1 pl2 [timelimit]",
"initiate a match (with given name)");
Cmds.Add(s, playersC, "players", 0, 0, "", "list active players");
Cmds.Add(s, quitC, "quit", 0, 0, "", "leave this program");
Cmds.Add(s, replayC, "replay", 1, 1, "name", "replay game");
LOOP
Write.String(": ");
CASE Cmds.Read(s, nfields, fields) OF
| Cmds.done, Cmds.empty:
| Cmds.error: EXIT
| Cmds.unknown:
Write.Line("Unknown command. Please try ``help''.");
| gamesC:
IF nfields = 0 THEN
ListDir(gamedir);
ELSIF fields[0] = "-l" THEN
GameListing;
ELSE
Write.Line("Invalid option.");
END;
| kiebitzC:
IF nfields = 1 THEN
Kiebitz(fields[0], FALSE);
ELSIF fields[0] = "-w" THEN
Kiebitz(fields[1], TRUE);
ELSE
Write.Line("Invalid option.");
END;
| matchC:
IF nfields = 3 THEN
timelimit := NIL;
ELSE
Strings.Open(tls, fields[3]); Read.IntS(tls, tli);
Streams.Release(tls);
Times.CreateAndSet(timelimit, Times.relative, 0, tli, 0);
END;
Match(fields[1], fields[2], fields[0], timelimit);
| playersC: ListDir(playerdir);
| quitC: EXIT
| replayC: Replay(fields[0]);
END;
END;
END DoCmds;
BEGIN
OpenAllKindsOfPorts;
Streams.stdout := Terminals.console;
NEW(errors); RelatedEvents.QueueEvents(errors);
DoCmds;
Process.Exit(0);
END Matches.
SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library
Andreas Borchert, 26. Juli 1999