背景フューチャー
2017年、あなたとあなたの対戦相手は、1人だけが生き残ることができる未来の銃撃戦で対戦します。対戦相手を倒すのに十分な経験がありますか?今こそ、お気に入りのプログラミング言語で銃のスキルを磨き、あらゆる可能性と戦う時です!
トーナメント結果
このトーナメントは2月2のUTCの午前中に終了ND、私たちの出場者に2017のおかげで、我々はエキサイティングな未来的なトーナメントがありました!
CBetaPlayerおよびStudiousPlayerとの緊密な戦いの後、MontePlayerが最終的な勝者です。上位3名の決闘者が記念写真を撮りました。
MontePlayer - by TheNumberOne
+------------+
CBetaPlayer | | - by George V. Williams
+------------+ # 1 | StudiousPlayer - by H Walters
| +----------------+
| # 2 # 3 |
+------------------------------------------+
The Futurustic Gun Duel @ PPCG.SE 2017
受賞者の皆さん、おめでとうございます!詳細なリーダーボードは、この投稿の終わり近くで見られます。
一般的なガイダンス
- このトーナメントで使用されるソースコードの公式リポジトリをご覧ください。
- C ++エントリ:
Player
クラスを継承してください。 - 非C ++エントリ:セクション非C ++提出用インターフェイスで1つのインターフェイスを選択します。
- 現在許可されている非C ++言語:Python 3、Java。
決闘
- 各プレイヤーは、無限の弾薬を装填できる無装填の銃から始めます。
- 各ターン、プレイヤーは以下のアクションのいずれかを同時に選択します。
0
-弾薬1個を銃に装填します。1
-敵に弾丸を発射します。装填弾薬1個のコスト。2
-敵にプラズマビームを発射します。装填弾薬2個の費用がかかります。-
-金属シールドを使用して、入ってくる弾丸を守ります。=
-熱偏向器を使用して、入射プラズマビームを防御します。
- 両方のプレイヤーが100 番目のターン後に生き残った場合、両方とも消耗して死に、引き分けになります。
プレイヤーは、彼らが銃の決闘を失う
- 入ってくる弾丸を守るために金属シールドを使用しませんでした。
- 入ってくるプラズマを保護するために熱偏向板を使用しませんでした。
- 十分な弾薬を装填せずに銃を発射します。銃は自己爆発し、所有者を殺します。
注意事項
未来の銃所有者のためのマニュアルによると:
- 金属シールドは、入射プラズマビームから保護できません。同様に、サーマルデフレクターは、入ってくる弾丸から防御できません。
- プラズマビームは弾丸を圧倒します(前者はより多くの弾薬を装填する必要があるため)。したがって、プレイヤーが同じターンに弾丸を発射する敵にプラズマビームを発射すると、敵は殺されます。
- 両方のプレイヤーが同じターンに互いに弾丸を発射した場合、弾丸はキャンセルされ、両方のプレイヤーは生き残ります。同様に、両方のプレイヤーが同じターンに互いにプラズマビームを発射した場合、両方のプレイヤーは生き残ります。
次のことも注目に値します。
- あなたはなりませそれが終了するまで順番に相手の行動を知っています。
- プラズマビームを偏向させ、弾丸をシールドしても、相手に害はありません。
したがって、各ターンには合計25の有効なアクションの組み合わせがあります。
+-------------+---------------------------------------------+
| Outcome | P L A Y E R B |
| Table +--------+-----------------+------------------+
| for Players | Load | Bullet Plasma | Metal Thermal |
+---+---------+--------+--------+--------+--------+---------+
| P | Load | | B wins | B wins | | |
| L +---------+--------+--------+--------+--------+---------+
| A | Bullet | A wins | | B wins | | A wins |
| Y | +--------+--------+--------+--------+---------+
| E | Plasma | A wins | A wins | | A wins | |
| R +---------+--------+--------+--------+--------+---------+
| | Metal | | | B wins | | |
| | +--------+--------+--------+--------+---------+
| A | Thermal | | B wins | | | |
+---+---------+--------+--------+---------------------------+
Note: Blank cells indicate that both players survive to the next turn.
例の決闘
これは私がかつて友人と持っていた決闘です。当時、私たちはプログラミングについてあまり知らなかったので、手のジェスチャーを使用して、1秒あたり2回転の速度で信号を送りました。左から順に、私たちの行動は次のとおりです。
Me: 001-000-1201101001----2
Friend: 00-10-=1-==--0100-1---1
上記のルールに従って、私は負けました。理由がわかりますか?これは、弾薬が1つしか装填されていないときに最終プラズマビームを発射し、銃が爆発したためです。
C ++プレーヤー
あなたは、文明化された未来的なプログラマーとして、銃を直接扱いません。代わりに、Player
他の人と戦うコードを作成します。GitHubプロジェクトでc ++クラスをパブリックに継承することにより、都市伝説を書き始めることができます。
Player.hpp can be found in Tournament\Player.hpp
An example of a derived class can be found in Tournament\CustomPlayer.hpp
あなたがしなければならないことまたはできること
Player
パブリック継承を介してクラスを継承し、クラスをfinalとして宣言する必要があります。- をオーバーライドする必要があります
Player::fight
。これは、Player::Action
呼び出されるたびに有効な値を返します。 - 必要に応じて、上書き
Player::perceive
してPlayer::declared
相手の行動に目を維持し、あなたの勝利を追跡するために。 - 必要に応じて、派生クラスでプライベートな静的メンバーとメソッドを使用して、より複雑な計算を実行します。
- オプションで、他のC ++標準ライブラリを使用します。
してはいけないこと
- 各トーナメントの開始時にシャッフルされる特定の対戦相手識別子以外の対戦相手を認識するために、直接的な方法を使用してはいけません。トーナメント内でゲームプレイをしているプレイヤーを推測することしかできません。
- あなたは必要がありませ内の任意のメソッドオーバーライドする
Player
仮想宣言されていないクラスを。 - あなたは必要がありませグローバルスコープで何かを宣言するか、初期化します。
- (現在は失格)のデビュー以来
BlackHatPlayer
、プレイヤーは相手の状態を覗いたり変更したりすることはできません。
決闘の例
銃の決闘のプロセスは、GunDuel
クラスを使用して実行されます。戦いの例については、「決闘の開始」Source.cpp
セクションを参照してください。
私たちは、ショーケースGunClubPlayer
、HumanPlayer
そしてGunDuel
中に見つけることができるクラス、Tournament\
リポジトリのディレクトリ。
各決闘でGunClubPlayer
、弾丸をロードします。それを発射します。すすぎ、繰り返します。毎ターン、HumanPlayer
対戦相手と対戦するためのアクションを促します。キーボードのコントロールが文字である0
、1
、2
、-
と=
。Windowsでは、HumanPlayer
送信をデバッグするために使用できます。
決闘を開始する
これは、コンソールからプレーヤーをデバッグする方法です。
// Source.cpp
// An example duel between a HumanPlayer and GunClubPlayer.
#include "HumanPlayer.hpp"
#include "GunClubPlayer.hpp"
#include "GunDuel.hpp"
int main()
{
// Total number of turns per duel.
size_t duelLength = 100;
// Player identifier 1: HumanPlayer.
HumanPlayer human(2);
// Player identifier 2: GunClubPlayer.
GunClubPlayer gunClub(1);
// Prepares a duel.
GunDuel duel(human, gunClub, duelLength);
// Start a duel.
duel.fight();
}
サンプルゲーム
あなたが敗北する必要ターンの最低額はGunClubPlayer
ここ3で遊んでからのリプレイです0-1
反対GunClubPlayer
。括弧内の数字は、ターン終了時の各プレイヤーの弾薬数です。
:: Turn 0
You [0/12/-=] >> [0] load ammo (1 ammo)
Opponent selects [0] load ammo (1 ammo)
:: Turn 1
You [0/12/-=] >> [-] defend using metal shield (1 ammo)
Opponent selects [1] fire a bullet (0 ammo)
:: Turn 2
You [0/12/-=] >> [1] fire a bullet (0 ammo)
Opponent selects [0] load ammo (1 ammo)
:: You won after 3 turns!
:: Replay
YOU 0-1
FOE 010
Press any key to continue . . .
弾丸はサーマルデフレクターを突き抜けるので、GunClubPlayer
無効な動きをせずに負ける最も簡単な方法はシーケンス0=
です。リプレイは
:: Turn 0
You [0/12/-=] >> [0] load ammo (1 ammo)
Opponent selects [0] load ammo (1 ammo)
:: Turn 1
You [0/12/-=] >> [=] defend using thermal deflector (1 ammo)
Opponent selects [1] fire a bullet (0 ammo)
:: You lost after 2 turns!
:: Replay
YOU 0=
FOE 01
Press any key to continue . . .
トーナメント
トーナメントは「Last Player Standing」形式に従います。トーナメントでは、すべての有効な提出物(を含むGunClubPlayer
)はプールに入れられます。各提出には、トーナメント全体を通して同じままであるランダム化された一意の識別子が割り当てられます。各ラウンド中:
- 各提出は0ポイントで始まり、他のすべての提出に対して100の決闘をします。
- 勝利した決闘ごとに1ポイントが付与されます。描画と負けは0ポイントを与えます。
- ラウンドの終わりに、最低ポイントの提出はトーナメントを去ります。同点の場合、トーナメントの開始以降に獲得したポイントが最も少ないプレーヤーが退場します。
- 複数のプレイヤーが残っている場合、次のラウンドが開始されます。
- ポイントは次のラウンドに持ち越されません。
提出
回答ごとに1人のプレイヤーを送信します。他の送信に干渉しない限り、プレーヤーに複数のファイルを送信できます。物事を円滑に進めるために、次のことを行ってください。
- あなたのメインのヘッダファイルに名前を付け
<Custom>Player.hpp
、 <Custom>Player*.*
たとえばMyLittlePlayer.txt
、クラス名がの場合MyLittlePlayer
、またはクラス名がの場合、他のファイルに名前を付けます。EmoPlayerHates.cpp
EmoPlayer
- 名前
Shooter
にこのトーナメントのコンテキストに適合する単語または類似の単語が含まれている場合Player
、最後に追加する必要はありません。あなたの投稿名がサフィックスなしでよりよく働くと強く感じるならPlayer
、あなたも追加する必要はありませんPlayer
。 - Windowsでコードをコンパイルおよびリンクできることを確認してください。
コメントして説明を求めたり、抜け穴を見つけたりできます。この未来の銃決闘をお楽しみいただき、おめでとうございます!
明確化
- ランダム化された動作が許可されます。
- 無効なアクション(装填された弾薬で十分でない場合の発射)は許可されます。
- プレイヤーが無効な入力を行うと、彼らの銃はすぐに爆発します。
- 答えを勉強することができます。
- 各トーナメント内の対戦相手の行動を記録することが明示的に許可されています。
- 各ラウンドでは、各対戦相手に対して100の決闘をプレイします。ただし、100の決闘の順序はランダムです。同じ対戦相手と100の決闘を続けて戦うことは保証されていません。
追加のリソース
@flawrは、 C ++エントリを送信する場合、提供されたC ++ソースを参照としてJavaに変換しました。
非C ++送信用のインターフェイス
現在受け入れられているもの:Python 3、Java。
以下の仕様のいずれかに従ってください。
インターフェイス仕様1:終了コード
提出は1ターンに1回実行されます。
Expected Command Line Argument Format:
<opponent-id> <turn> <status> <ammo> <ammo-opponent> <history> <history-opponent>
Expected Return Code: The ASCII value of a valid action character.
'0' = 48, '1' = 49, '2' = 50, '-' = 45, '=' = 61
<opponent-id> is an integer in [0, N), where N is size of tournament.
<turn> is 0-based.
If duel is in progress, <status> is 3.
If duel is draw / won / lost, <status> is 0 / 1 / 2.
<history> and <history-opponent> are strings of actions, e.g. 002 0-=
If turn is 0, <history> and <history-opponent> are not provided.
You can ignore arguments you don't particularly need.
提出PythonPlayer\
をJavaPlayer\
ディレクトリでテストできます。
インターフェイス仕様2:stdin / stdout
(H Waltersへのクレジット)
提出はトーナメントごとに1回実行されます。
stdinとstdoutの両方がトーナメントドライバーに接続されているため、I / Oの実行方法に関するすべてのエントリには固定要件があります。これに違反すると、デッドロックが発生する可能性があります。すべてのエントリは、この正確なアルゴリズムに従う必要があります(擬似コードで):
LOOP FOREVER
READ LINE INTO L
IF (LEFT(L,1) == 'I')
INITIALIZE ROUND
// i.e., set your/opponent ammo to 0, if tracking them
// Note: The entire line at this point is a unique id per opponent;
// optionally track this as well.
CONTINUE LOOP
ELSE IF (LEFT(L,1) == 'F')
WRITELN F // where F is your move
ELSE IF (LEFT(L,1) == 'P')
PROCESS MID(L,2,1) // optionally perceive your opponent's action.
END IF
CONTINUE LOOP
QUIT
ここで、Fはの一つであり0
、1
、2
、-
、または=
のためにload / bullet / plasma / metal / thermal
。PROCESSとは、対戦相手が行ったことにオプションで応答することを意味します(これを行っている場合、対戦相手の弾薬の追跡を含む)。相手のアクションも「0」、「1」、「2」、「-」、または「=」のいずれかであり、2番目のキャラクターにあることに注意してください。
最終スコアボード
08:02 AM Tuesday, February 2, 2017 Coordinated Universal Time (UTC)
| Player | Language | Points | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|:------------------ |:---------- | ------:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:| -----:|
| MontePlayer | C++ | 11413 | 1415 | 1326 | 1247 | 1106 | 1049 | 942 | 845 | 754 | 685 | 555 | 482 | 381 | 287 | 163 | 115 | 61 |
| CBetaPlayer | C++ | 7014 | 855 | 755 | 706 | 683 | 611 | 593 | 513 | 470 | 414 | 371 | 309 | 251 | 192 | 143 | 109 | 39 |
| StudiousPlayer | C++ | 10014 | 1324 | 1233 | 1125 | 1015 | 907 | 843 | 763 | 635 | 555 | 478 | 403 | 300 | 201 | 156 | 76 |
| FatedPlayer | C++ | 6222 | 745 | 683 | 621 | 655 | 605 | 508 | 494 | 456 | 395 | 317 | 241 | 197 | 167 | 138 |
| HanSoloPlayer | C++ | 5524 | 748 | 668 | 584 | 523 | 490 | 477 | 455 | 403 | 335 | 293 | 209 | 186 | 153 |
| SurvivorPlayer | C++ | 5384 | 769 | 790 | 667 | 574 | 465 | 402 | 354 | 338 | 294 | 290 | 256 | 185 |
| SpecificPlayer | C++ | 5316 | 845 | 752 | 669 | 559 | 488 | 427 | 387 | 386 | 340 | 263 | 200 |
| DeceptivePlayer | C++ | 4187 | 559 | 445 | 464 | 474 | 462 | 442 | 438 | 369 | 301 | 233 |
| NotSoPatientPlayer | C++ | 5105 | 931 | 832 | 742 | 626 | 515 | 469 | 352 | 357 | 281 |
| BarricadePlayer | C++ | 4171 | 661 | 677 | 614 | 567 | 527 | 415 | 378 | 332 |
| BotRobotPlayer | C++ | 3381 | 607 | 510 | 523 | 499 | 496 | 425 | 321 |
| SadisticShooter | C++ | 3826 | 905 | 780 | 686 | 590 | 475 | 390 |
| TurtlePlayer | C++ | 3047 | 754 | 722 | 608 | 539 | 424 |
| CamtoPlayer | C++ | 2308 | 725 | 641 | 537 | 405 |
| OpportunistPlayer | C++ | 1173 | 426 | 420 | 327 |
| GunClubPlayer | C++ | 888 | 500 | 388 |
| PlasmaPlayer | C++ | 399 | 399 |
トーナメントは、特に明記しない限り、2017年2月1日まで続きます。
Player
は、別のプロセスを呼び出して現在のターンを計算する実装を許可できます。そうすれば、あなたのマシンで実行したい言語なら誰でも参加できます。
Player::fight
ます "/"継承できますPlayer::perceive
」...どちらの場合も、用語はinheritではなくoverrideです。
GunDuel.hpp
の両方、validA
およびvalidB
使用actionA