summaryrefslogtreecommitdiff
path: root/doc/number-guessing-bot/bot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'doc/number-guessing-bot/bot.cpp')
-rw-r--r--doc/number-guessing-bot/bot.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/doc/number-guessing-bot/bot.cpp b/doc/number-guessing-bot/bot.cpp
new file mode 100644
index 0000000..f14e917
--- /dev/null
+++ b/doc/number-guessing-bot/bot.cpp
@@ -0,0 +1,125 @@
+// Copyright 2024 Huawei Cloud Computing Technology Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstring>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+void print_buffer(char *start, char *end) {
+ ++end;
+ while (start != end) {
+ std::cout << *start++;
+ }
+}
+
+bool ends_with(char *end, std::string const &token) {
+ auto it = token.rbegin();
+ while (it != token.rend()) {
+ if (*it++ != *end--) {
+ return false;
+ }
+ }
+ return true;
+}
+
+int main(int argc, char **argv) {
+ int pipefd_a[2]; // pipefd_a[0] reads from pipe
+ // pipefd_a[1] writes to pipe
+ int pipefd_b[2];
+ if (pipe(pipefd_a) == -1) {
+ perror("pipe error");
+ exit(EXIT_FAILURE);
+ }
+ if (pipe(pipefd_b) == -1) {
+ perror("pipe error");
+ exit(EXIT_FAILURE);
+ }
+
+ auto pid = fork();
+ if (pid == -1) {
+ perror("fork error");
+ exit(EXIT_FAILURE);
+ }
+
+ if (pid == 0) {
+ std::string const s{argv[1]};
+ std::string const token = s.substr(s.rfind('/') + 1);
+ std::cout << "playing: " << s << std::endl;
+
+ // child reads from pipefd_a[0];
+ // writes to pipefd_b[1];
+ dup2(pipefd_b[1], STDOUT_FILENO);
+ dup2(pipefd_a[0], STDIN_FILENO);
+
+ close(pipefd_a[1]); // close unused write end
+ close(pipefd_b[0]); // close unused read end
+ close(pipefd_b[1]);
+ close(pipefd_a[0]);
+ execl(s.c_str(), token.c_str());
+
+ _exit(0);
+ } else {
+ // master reads from pipefd_b[0]
+ // writes to pipefd_a[1];
+ close(pipefd_a[0]);
+ close(pipefd_b[1]);
+
+ bool run = true;
+ int a = 1;
+ int b = 101;
+ int trial = 50;
+
+ char buffer[1024];
+ char *p = buffer;
+ std::string s;
+ while (run) {
+ while (read(pipefd_b[0], p, 1)) {
+ if (*p == '\n') {
+ print_buffer(buffer, p);
+ p = buffer;
+ continue;
+ }
+ if (*p == '!') {
+ if (ends_with(p, "win!")) {
+ run = false;
+ print_buffer(buffer, p);
+ std::cout << std::endl;
+ break;
+ }
+ if (ends_with(p, "small!")) {
+ a = trial;
+ trial = (a + b) / 2;
+ }
+ if (ends_with(p, "big!")) {
+ b = trial;
+ trial = (a + b) / 2;
+ }
+ char trial_buf[80];
+ int len = sprintf(trial_buf, "%d\n", trial);
+ write(pipefd_a[1], trial_buf, len);
+ }
+ if (!run) {
+ break;
+ }
+ ++p;
+ }
+ }
+ close(pipefd_b[0]);
+ close(pipefd_a[1]);
+ int status;
+ waitpid(0, &status, 0);
+ }
+}