Skip to content

Commit c8e9cfc

Browse files
RIC-1143: MoreOrLess sample added
1 parent e792d50 commit c8e9cfc

8 files changed

Lines changed: 503 additions & 2 deletions

File tree

art-samples/MoreOrLess/Guesser.art

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
capsule Guesser {
2+
[[rt::impl_preface]]
3+
`
4+
#include <string.h>
5+
#include <stdio.h>
6+
`
7+
8+
[[rt::decl]]
9+
`
10+
private:
11+
unsigned int guess;
12+
Hint hint;
13+
int myId;
14+
char myName[10];
15+
RTActorId numberId;
16+
17+
protected:
18+
void log(const char*);
19+
`
20+
21+
[[rt::impl]]
22+
`
23+
void Guesser::log(const char* msg) {
24+
logP.show("[");
25+
logP.show(myName);
26+
logP.show("] ");
27+
logP.log(msg);
28+
logP.commit();
29+
}
30+
`
31+
32+
/* Ports */
33+
behavior port logP : Log;
34+
behavior port frameP : Frame;
35+
36+
behavior notify port numberP : NumberProt;
37+
behavior service port guesserP : GuesserProt;
38+
39+
/* Parts */
40+
plugin part number [[rt::properties(rule_config="X0039")]] : Number[0..1]; // Expected warning ART_0039 because Number::cmdP is not connected in this composite structure which is OK since we will not use it when the Number capsule is located in this part.
41+
42+
/* Connectors */
43+
connect numberP with number.numberP;
44+
45+
/* State Machine */
46+
statemachine {
47+
state Disconnected;
48+
state Connecting {
49+
entry
50+
`
51+
log("importing 'number'");
52+
53+
if (numberId.isValid()) {
54+
if (!frameP.import(numberId, number, 0)) {
55+
log("problem importing the number capsule");
56+
}
57+
}
58+
`;
59+
};
60+
61+
initial -> Disconnected
62+
`
63+
// what's my pid, i.e., which number of guesser am I?
64+
myId = this->getIndex();
65+
66+
// my name is <capsule part name>+<pid>
67+
char buffer[10];
68+
snprintf(buffer, 10, "%s%d", this->getName(), myId);
69+
strcpy(myName, buffer);
70+
log("starting up");
71+
72+
log("sending 'ready' to Top");
73+
guesserP.ready().send();
74+
`;
75+
76+
beenToldToConnect: Disconnected -> Connecting on guesserP.doConnect
77+
`
78+
log("getting ready to connect");
79+
numberId = *rtdata;
80+
`;
81+
numberImported: Connecting -> Connected.enp on numberP.rtBound
82+
`
83+
log("connected!");
84+
`;
85+
86+
state Connected {
87+
entrypoint enp;
88+
exitpoint exp;
89+
state AskForHint {
90+
entry
91+
`
92+
log("asking for hint");
93+
numberP.askHint().send();
94+
`;
95+
};
96+
state SendGuess {
97+
entry
98+
`
99+
if (hint.isLess) {
100+
guess = hint.current - (hint.current - hint.min) / 2;
101+
}
102+
else {
103+
guess = hint.current + (hint.max - hint.current) / 2;
104+
}
105+
log("guessing: ");
106+
logP.log(guess);
107+
108+
numberP.guess(guess).send();
109+
`;
110+
};
111+
state Disconnecting {
112+
entry
113+
`
114+
if (!frameP.deport(numberId, number)) {
115+
log("problem deporting 'number'");
116+
}
117+
`;
118+
};
119+
enp -> AskForHint;
120+
AskForHint -> SendGuess on numberP.sendHint
121+
`
122+
hint = *rtdata;
123+
`;
124+
choice checkAnswer;
125+
SendGuess -> checkAnswer on numberP.sendAnswer;
126+
found: checkAnswer -> Disconnecting when `*rtdata`
127+
`
128+
guesserP.found(guess).send();
129+
`;
130+
else: checkAnswer -> Disconnecting when `else`
131+
`
132+
guesserP.notFound().send();
133+
`;
134+
numberDeported: Disconnecting -> exp on numberP.rtUnbound
135+
`
136+
log("disconnected!");
137+
`;
138+
};
139+
numberDeported: Connected.exp -> Disconnected;
140+
};
141+
};

art-samples/MoreOrLess/Number.art

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
capsule Number {
2+
[[rt::header_preface]]
3+
`
4+
#include <stdlib.h>
5+
#include <time.h>
6+
`
7+
[[rt::decl]]
8+
`
9+
private:
10+
Hint hint;
11+
unsigned int max = 100;
12+
unsigned int min = 0;
13+
unsigned int mostRecentGuess = 0;
14+
unsigned int secretNumber = 0;
15+
16+
protected:
17+
void log(const char*);
18+
`
19+
20+
[[rt::impl]]
21+
`
22+
void Number::log(const char* msg) {
23+
logP.show("[number ]");
24+
logP.log(msg);
25+
logP.commit();
26+
}
27+
`
28+
29+
/* Ports */
30+
behavior port logP : Log;
31+
32+
service behavior port cmdP~ : CmdProt;
33+
service behavior port numberP~ : NumberProt;
34+
/* Parts */
35+
/* Connectors */
36+
/* State Machine */
37+
statemachine {
38+
state WaitForHintRequest;
39+
state WaitForGuess;
40+
state Done;
41+
42+
initial -> WaitForHintRequest
43+
`
44+
log("starting up");
45+
46+
// receive max, i.e., upper bound of range that secret number can be in
47+
max = * static_cast<const unsigned int*>(rtdata);
48+
49+
/* initialize random seed: */
50+
srand(time(NULL));
51+
secretNumber = rand() % max;
52+
mostRecentGuess = max;
53+
54+
log("secret number is ");
55+
logP.log(secretNumber);
56+
57+
log("sending 'ready' to Top");
58+
cmdP.ready().send();
59+
`;
60+
choice c;
61+
junction j;
62+
gotHintReq: WaitForHintRequest -> c on numberP.askHint
63+
`
64+
hint.current = mostRecentGuess;
65+
hint.min = min;
66+
hint.max = max;
67+
`;
68+
more: c -> j when `mostRecentGuess < secretNumber`
69+
`
70+
log("hint given: most recent guess is");
71+
logP.log(mostRecentGuess);
72+
log("secret number is MORE, but no more than ");
73+
logP.log(max);
74+
hint.isLess = false;
75+
`;
76+
less: c -> j when `else`
77+
`
78+
log("hint given: most recent guess is");
79+
logP.log(mostRecentGuess);
80+
log("secret number is LESS, but no less than ");
81+
logP.log(min);
82+
hint.isLess = true;
83+
`;
84+
sendHint: j -> WaitForGuess
85+
`
86+
numberP.sendHint(hint).send();
87+
`;
88+
choice checkGuess;
89+
WaitForGuess -> checkGuess on numberP.guess
90+
`
91+
mostRecentGuess = *rtdata;
92+
`;
93+
guessCorrect: checkGuess -> Done when `mostRecentGuess == secretNumber`
94+
`
95+
log("guess correct! secret number is ");
96+
logP.log(secretNumber);
97+
numberP.sendAnswer(true).send();
98+
`;
99+
else: checkGuess -> WaitForHintRequest when `else`
100+
`
101+
logP.log("guess incorrect; keep going");
102+
if (mostRecentGuess > secretNumber) {
103+
// it is less
104+
max = mostRecentGuess;
105+
}
106+
else {
107+
// it is more
108+
min = mostRecentGuess;
109+
}
110+
numberP.sendAnswer(false).send();
111+
`;
112+
};
113+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
protocol CmdProt {
2+
/* In Events */
3+
in ready();
4+
/* Out Events */
5+
};
6+
7+
protocol GuesserProt {
8+
/* In Events */
9+
in doConnect(`RTActorId`);
10+
/* Out Events */
11+
out found(`unsigned int`);
12+
out notFound();
13+
out ready();
14+
};
15+
16+
[[rt::decl]]
17+
`
18+
struct [[rt::auto_descriptor]] Hint {
19+
unsigned int current;
20+
bool isLess;
21+
unsigned int max;
22+
unsigned int min;
23+
};
24+
`
25+
26+
protocol NumberProt {
27+
[[rt::header_preface]]
28+
`
29+
#include "Protocols.art.h"
30+
`
31+
32+
/* In Events */
33+
in sendAnswer(`bool` /* hasFound*/ );
34+
in sendHint(`Hint`);
35+
/* Out Events */
36+
out askHint();
37+
out guess(`unsigned int`);
38+
};

art-samples/MoreOrLess/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# MoreOrLess
2+
This sample is a "guess-the-secret-number" game which illustrates the use of plugin capsule parts. A number of `Guesser` capsule instances try to guess a secret number in a round robin fashion. To make a guess an instance of a `Number` capsule is imported into the plugin part `number`. The guesser then asks for a hint if the secret number is more or less than the previous guess made. It can hence narrow down the interval that the secret number must be in. The `Guesser` makes a guess in the middle of the interval. If the guess is correct, the game ends. Otherwise the `Number` is deported from the plugin part so that the next guesser can use it for make a guess.
3+
4+
The application accepts two numeric command-line arguments. The first one specifies the number of guessers (by default 10) and the second specifies the upper bound of the interval for the secret number (by default 100). The lower bound of the interval is always 0.
5+
6+
For example, to let 20 guessers guess a number between 0 and 50:
7+
8+
```
9+
.\Top.EXE -URTS_DEBUG=quit 20 50
10+
```
11+
12+
Credit to [Queen's University](https://research.cs.queensu.ca/home/dingel/cisc844_F23/sampleModels/sampleModels.html) for the implementation.

0 commit comments

Comments
 (0)