トーナメントのプレイ方法

共同作業なので、私の利益のために

-それは団結します。



マトロスキン



小石を水に投げ込み、それらが形成する円を見てください。そうでなければ、そのような投げは空の楽しみになります。



コズマ・プルトコフ「思考と嫌悪」。




最近、先週の金曜日に、プログラミングトーナメントを開催して、日常生活を少し多様化することにしました。議題はすぐには決定されませんでした。分析データの処理、機械学習についての考えがありましたが、結局、彼らはボードゲームに落ち着きました。イベントに競争の要素を導入したかったのですが、ゲームではないにしても、これを簡単にするものは何ですか?





それで、競争に参加したいチームが利用可能でした、彼らはまた賞金を考え出しました-それはゲームを決定するために残っています。私は「アタリ囲碁」を提案しましたが、その理由は最も説得力がありました。



, '' ''?
— , , . , . (), , (). — 19x19. , , . .



. , , . , , «». , , ( ). , , . , :







. , . , . , , :







(), , . , « » . , , . , , . , « », , .



« » — , . — 9x9 . . , — . , , — , . « » . !



  • — , « »
  • « » , " "
  • , , , "-"
  • , ,


私は最後の点への反対を予見します。はい、確かに、多くのボットはGo用に作成されており、アクセス可能な実装を見つけることはまったく問題ではありませんが、AtariGoは別のゲームです。 Goで個々の石を失ったことは災害とは見なされません。ゲームの目標は完全に異なります。アタリ囲碁では、1石でも失ったことは即敗です。



参加者を1つのプログラミング言語にバインドしたくなかったため、RESTAPIを提供するWebサービスを開発することにしました。トーナメント参加者の動きを登録します。その後、このアイデアは完全に正当化されました。 Javaに加えて、競合他社は開発言語としてC ++、Kotlin、さらにはLuaを使用していました。ボットの実行が計画されているコンピューターのパフォーマンスの違いによる影響を排除するために、同じタイプのミニPCを2セット購入して最初にテストし、Ubuntu Linux OS20バージョンをインストールしました。







ゲーム追跡サービスはNestフレームワークを使用してNode.jsで開発されましたが、それは戦いの半分にすぎませんでした。事実、サーバーはどのゲームの詳細にも依存しないユニバーサルソリューションとして考案されました。そのタスクは、プレーヤーの動きをデータベースに記録し、時間を制御することですが、動き自体が正しいかどうかはチェックしません。移動の正しさを確認し、勝者を決定するのはjQueryライブラリを使用してサーバーに接続する小さなJavaScriptアプリケーションであるArbiterのタスクです



より技術的な詳細
— , . PostgreSQL. « » , , :





user- token-, ( JWT-). games ( « » ). game_sessions. , ( ) user_games. game_moves.



API
{
   "openapi":"3.0.0",
   "info":{
      "title":"Dagaz Server",
      "description":"Dagaz Server API description",
      "version":"0.0.1",
      "contact":{

      }
   },
   "tags":[
      {
         "name":"dagaz",
         "description":""
      }
   ],
   "servers":[

   ],
   "components":{
      "schemas":{
         "User":{
            "type":"object",
            "properties":{
               "id":{
                  "type":"number"
               },
               "is_admin":{
                  "type":"number"
               },
               "name":{
                  "type":"string"
               },
               "username":{
                  "type":"string"
               },
               "password":{
                  "type":"string"
               },
               "email":{
                  "type":"string"
               },
               "created":{
                  "format":"date-time",
                  "type":"string"
               },
               "deleted":{
                  "format":"date-time",
                  "type":"string"
               },
               "last_actived":{
                  "format":"date-time",
                  "type":"string"
               }
            },
            "required":[
               "id",
               "name",
               "username",
               "created",
               "last_actived"
            ]
         },
         "Pref":{
            "type":"object",
            "properties":{
               "id":{
                  "type":"number"
               },
               "user_id":{
                  "type":"number"
               },
               "game_id":{
                  "type":"number"
               },
               "created":{
                  "format":"date-time",
                  "type":"string"
               }
            },
            "required":[
               "game_id"
            ]
         },
         "Sess":{
            "type":"object",
            "properties":{
               "id":{
                  "type":"number"
               },
               "status":{
                  "type":"number"
               },
               "game_id":{
                  "type":"number"
               },
               "game":{
                  "type":"string"
               },
               "filename":{
                  "type":"string"
               },
               "created":{
                  "format":"date-time",
                  "type":"string"
               },
               "creator":{
                  "type":"string"
               },
               "changed":{
                  "format":"date-time",
                  "type":"string"
               },
               "closed":{
                  "format":"date-time",
                  "type":"string"
               },
               "players_total":{
                  "type":"number"
               },
               "winner":{
                  "type":"number"
               },
               "loser":{
                  "type":"number"
               },
               "score":{
                  "type":"number"
               },
               "last_setup":{
                  "type":"string"
               }
            },
            "required":[
               "game_id"
            ]
         },
         "Challenge":{
            "type":"object",
            "properties":{
               "id":{
                  "type":"number"
               },
               "session_id":{
                  "type":"number"
               },
               "user_id":{
                  "type":"number"
               },
               "user":{
                  "type":"string"
               },
               "player_num":{
                  "type":"number"
               }
            },
            "required":[
               "session_id"
            ]
         },
         "Join":{
            "type":"object",
            "properties":{
               "id":{
                  "type":"number"
               },
               "user_id":{
                  "type":"number"
               },
               "user":{
                  "type":"string"
               },
               "session_id":{
                  "type":"number"
               },
               "player_num":{
                  "type":"number"
               },
               "is_ai":{
                  "type":"number"
               }
            },
            "required":[
               "session_id"
            ]
         },
         "Move":{
            "type":"object",
            "properties":{
               "id":{
                  "type":"number"
               },
               "session_id":{
                  "type":"number"
               },
               "user_id":{
                  "type":"number"
               },
               "turn_num":{
                  "type":"number"
               },
               "move_str":{
                  "type":"string"
               },
               "setup_str":{
                  "type":"string"
               },
               "note":{
                  "type":"string"
               },
               "time_delta":{
                  "type":"number"
               },
               "time_limit":{
                  "type":"number"
               },
               "additional_time":{
                  "type":"number"
               }
            },
            "required":[
               "session_id",
               "user_id",
               "move_str"
            ]
         },
         "Result":{
            "type":"object",
            "properties":{
               "id":{
                  "type":"number"
               },
               "session_id":{
                  "type":"number"
               },
               "user_id":{
                  "type":"number"
               },
               "result_id":{
                  "type":"number"
               },
               "score":{
                  "type":"number"
               }
            },
            "required":[
               "session_id",
               "result_id"
            ]
         }
      }
   },
   "paths":{
      "/api/auth/login":{
         "post":{
            "operationId":"AppController_login",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/User"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               }
            },
            "security":[
               {
                  "basic":[

                  ]
               }
            ]
         }
      },
      "/api/auth/refresh":{
         "get":{
            "operationId":"AppController_refresh",
            "parameters":[

            ],
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               }
            },
            "security":[
               {
                  "basic":[

                  ]
               }
            ]
         }
      },
      "/api/users":{
         "get":{
            "operationId":"UsersController_findAll",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         },
         "post":{
            "operationId":"UsersController_update",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/User"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/users/{id}":{
         "get":{
            "operationId":"UsersController_findUsers",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         },
         "delete":{
            "operationId":"UsersController_delete",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "403":{
                  "description":"Forbidden."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/preferences":{
         "get":{
            "operationId":"PreferencesController_findAll",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         },
         "post":{
            "operationId":"PreferencesController_create",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Pref"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/preferences/{id}":{
         "delete":{
            "operationId":"PreferencesController_delete",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/session":{
         "get":{
            "operationId":"SessionController_findAll",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "403":{
                  "description":"Forbidden."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         },
         "post":{
            "operationId":"SessionController_create",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Sess"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/session/{id}":{
         "get":{
            "operationId":"SessionController_getSession",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/session/close":{
         "post":{
            "operationId":"SessionController_close",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Sess"
                        }
                     }
                  }
               }
            },
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "403":{
                  "description":"Forbidden."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/challenge":{
         "get":{
            "operationId":"ChallengeController_findAll",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         },
         "post":{
            "operationId":"ChallengeController_create",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Challenge"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/challenge/{id}":{
         "delete":{
            "operationId":"ChallengeController_delete",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/join/{id}":{
         "get":{
            "operationId":"JoinController_findJoined",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/join":{
         "post":{
            "operationId":"JoinController_join",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Join"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/move/all/{id}":{
         "get":{
            "operationId":"MoveController_getMoves",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "403":{
                  "description":"Forbidden."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/move/unconfirmed/{id}":{
         "get":{
            "operationId":"MoveController_getUnconfirmedMove",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "403":{
                  "description":"Forbidden."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/move/confirmed/{id}":{
         "get":{
            "operationId":"MoveController_getConfirmedMove",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/move":{
         "post":{
            "operationId":"MoveController_update",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Move"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/move/confirm":{
         "post":{
            "operationId":"MoveController_confirm",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Move"
                        }
                     }
                  }
               }
            },
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "403":{
                  "description":"Forbidden."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/result/{id}":{
         "get":{
            "operationId":"ResultController_getMoves",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/result":{
         "post":{
            "operationId":"ResultController_join",
            "parameters":[

            ],
            "requestBody":{
               "required":true,
               "content":{
                  "application/json":{
                     "schema":{
                        "type":"array",
                        "items":{
                           "$ref":"#/components/schemas/Result"
                        }
                     }
                  }
               }
            },
            "responses":{
               "201":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "404":{
                  "description":"Not Found."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      },
      "/api/game":{
         "get":{
            "operationId":"GameController_allGames",
            "parameters":[

            ],
            "responses":{
               "200":{
                  "description":"Successfully."
               },
               "401":{
                  "description":"Unauthorized."
               },
               "500":{
                  "description":"Internal Server error."
               }
            },
            "security":[
               {
                  "bearer":[

                  ]
               }
            ]
         }
      }
   }
}




, (POST api/session), (POST api/challenge) (POST api/move). (GET api/challenge) (POST api/join). , , , (GET api/move/confirmed/:id, id — ) (POST api/move).



, , , . , (games.main_time), (games.additional_time), . ( ), . . , , , .



( ), — , . — , (setup_str), , ( , , , ). , ( ). , ( ).



Atari Goであっても、ボットの開発は困難です。準備のために出場者に割り当てられた3日間は、ボットが単に機能するためだけに十分でした。さらに、コンテストが開催されたミニPCは、デバッグが実行された職場よりも生産性が大幅に低いことが判明しました。これらすべてが、トーナメント中のボットが特別な知性で輝かなかったという事実につながりましたが、それでも面白い瞬間が起こりました。





これは、トーナメントゲームの1つでの最終的な位置の例です。ボットの戦いは面白くて激しいものでした。結局、ホワイトはシチョ相手を捕まえようとしたが、次の動きでブラックがアタリの位置にいることに気づかなかったホワイトのボットは、「はしご」を続けようとしてミスを犯しました。黒はすぐにこれを利用しました-石を取り、ゲームを終了しました。



これはすべて、トーナメント参加者が犯した間違いの性質をよく表しています。
, , , . , , , . :







"" — . « », , «E6», . , , , — , «» , . «», , . .







, , : "", "" "". , , , . , , , . , , , .



,
« », , . , :



1000    ;  
-----
?????
??B??
?B.??
?????
?????


, , 5x5. , , (, «» ). , . , 90, 180 270 , . . .



Dagaz.AI.Patterns.push({re: /.{7}B.{3}B0.{12}/, price: 1000});
Dagaz.AI.Patterns.push({re: /.{11}B0.{4}B.{7}/, price: 1000});
Dagaz.AI.Patterns.push({re: /.{12}0B.{3}B.{7}/, price: 1000});
Dagaz.AI.Patterns.push({re: /.{7}B.{4}0B.{11}/, price: 1000});


, . , heuristic. , . , « », , , , .



, , , . , «».



それでも、参加者全員が応募者全員(白と黒)で2試合を戦うトーナメントの予選ステージは順調に進み、勝利数で2人のファイナリストを決定しました。







さらに、ゲームは3回の勝利まで続き、最初の動きの順序が入れ替わりました。最終スコア3:1で勝ったので、満足した(そして3泊しなかった)勝者は彼の賞を取りました:





彼に拍手を送りましょう!




All Articles