Le futur de fond
En 2017, vous et votre adversaire s'affronterez dans une bataille d'armes à feu futuriste où un seul d'entre eux pourrait survivre. Êtes- vous assez expérimenté pour vaincre votre adversaire? Il est maintenant temps de perfectionner vos compétences en armes à feu dans votre langage de programmation préféré et de vous battre contre toute attente!
Résultats du tournoi
Ce tournoi terminé à l'UTC matin du Feburary 2 e 2017. Merci à nos concurrents, nous avons eu un tournoi futuriste passionnant!
MontePlayer est le vainqueur final après une bataille serrée avec CBetaPlayer et StudiousPlayer. Les trois meilleurs duels de guen ont pris une photo commémorative:
MontePlayer - by TheNumberOne
+------------+
CBetaPlayer | | - by George V. Williams
+------------+ # 1 | StudiousPlayer - by H Walters
| +----------------+
| # 2 # 3 |
+------------------------------------------+
The Futurustic Gun Duel @ PPCG.SE 2017
Félicitations aux gagnants! Classement détaillé est vu vers la fin de ce post.
Orientation générale
- Visitez le dépôt officiel pour le code source utilisé dans ce tournoi.
- Entrées C ++: veuillez hériter de la
Player
classe. - Entrées non C ++: sélectionnez une interface dans la section Interface pour les soumissions non C ++ .
- Langages actuellement non autorisés: Python 3, Java.
Le duel
- Chaque joueur commence avec un pistolet non chargé pouvant charger une quantité infinie de munitions.
- À chaque tour, les joueurs choisiront simultanément l'une des actions suivantes:
0
- Charge 1 munition dans le pistolet.1
- tirer une balle sur l'adversaire; coûte 1 munitions chargées.2
- tirer un faisceau de plasma sur l'adversaire; coûte 2 munitions chargées.-
- Défendre la balle en utilisant un bouclier métallique.=
- Défendre le faisceau de plasma entrant à l'aide d'un déflecteur thermique.
- Si les deux joueurs survivent après le 100 e tour, ils s'épuisent à la mort, ce qui entraîne un match nul .
Un joueur perd le duel lorsqu’il
- N'a PAS utilisé le bouclier métallique pour défendre une balle entrante.
- N'a PAS utilisé le déflecteur thermique pour défendre un plasma entrant.
- Tirez avec une arme à feu sans charger assez de munitions, dans laquelle leur arme explose et tue le propriétaire.
Mises en garde
Selon le Manuel du propriétaire d'armes futuriste :
- Un bouclier métallique NE PEUT PAS se défendre du faisceau de plasma entrant. De même, un déflecteur thermique NE PEUT PAS se défendre contre les balles entrantes.
- Le faisceau de plasma domine la balle (car la première nécessite des munitions plus chargées). Par conséquent, si un joueur tire un faisceau de plasma sur l'adversaire qui tire une balle dans le même tour, l'adversaire est tué.
- Si les deux joueurs se tirent une balle dans le même tour, les balles s'annulent et les deux joueurs survivent. De même, si les deux joueurs se lancent un faisceau de plasma au cours du même tour, ils survivent.
Il convient également de noter que:
- Vous ne connaîtrez PAS l'action de votre adversaire dans un tour jusqu'à la fin.
- La déviation des faisceaux de plasma et des balles de protection ne nuira pas à votre adversaire.
Par conséquent, il y a un total de 25 combinaisons d'actions valides à chaque tour:
+-------------+---------------------------------------------+
| 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.
Exemple de duel
Voici un duel que j'ai eu une fois avec un ami. À l'époque, nous ne savions pas grand chose à propos de la programmation, nous avons donc utilisé des gestes de la main et signalé à la vitesse de deux tours par seconde. De gauche à droite, nos actions ont été à leur tour:
Me: 001-000-1201101001----2
Friend: 00-10-=1-==--0100-1---1
Selon les règles ci-dessus, j'ai perdu. Tu vois pourquoi? C'est parce que j'ai tiré le dernier faisceau de plasma alors que je n'avais qu'une cartouche chargée, ce qui a fait exploser mon arme.
Le lecteur C ++
En tant que programmeur futuriste civilisé, vous ne manipulerez pas directement les armes. Au lieu de cela, vous codez un Player
qui se bat contre les autres. En héritant publiquement de la classe c ++ du projet GitHub, vous pouvez commencer à écrire votre légende urbaine.
Player.hpp can be found in Tournament\Player.hpp
An example of a derived class can be found in Tournament\CustomPlayer.hpp
Ce que vous devez ou pouvez faire
- Vous devez hériter d'une
Player
classe par héritage public et déclarer votre classe finale. - Vous devez remplacer
Player::fight
, ce qui retourne une valeur valide àPlayer::Action
chaque appel. - Vous pouvez éventuellement passer outre
Player::perceive
,Player::declared
surveiller les actions de votre adversaire et garder trace de vos victoires. - Utilisez éventuellement des membres et des méthodes statiques privés dans votre classe dérivée pour effectuer des calculs plus complexes.
- Utilisez éventuellement d'autres bibliothèques standard C ++.
Ce que vous ne devez PAS faire
- Vous ne devez PAS utiliser une méthode directe pour reconnaître votre adversaire autre que l'identifiant donné de l'adversaire, qui est mélangé au début de chaque tournoi. Vous êtes seulement autorisé à deviner qui est un joueur grâce à son jeu dans un tournoi.
- Vous ne devez PAS écraser les méthodes de la
Player
classe qui ne sont pas déclarées virtuelles. - Vous devez pas déclarer ou initialiser quoi que ce soit dans la portée globale.
- Depuis le début de (maintenant disqualifié)
BlackHatPlayer
, les joueurs ne sont PAS autorisés à jeter un coup d'œil ou à modifier l'état de votre adversaire.
Un exemple de duel
Le processus d'un duel d'armes à feu est effectué en utilisant la GunDuel
classe. Pour un exemple de combat, voir la Source.cpp
section Initiation d’un duel .
Nous présentons GunClubPlayer
, HumanPlayer
et la GunDuel
classe, qui peuvent être trouvés dans le Tournament\
répertoire du référentiel.
Dans chaque duel, GunClubPlayer
chargera une balle; tirez-le; rincer et répéter. À chaque tour, HumanPlayer
vous demandera une action à jouer contre votre adversaire. Vos commandes du clavier sont les personnages 0
, 1
, 2
, -
et =
. Sous Windows, vous pouvez utiliser HumanPlayer
pour déboguer votre soumission.
Initier un duel
Voici comment vous pouvez déboguer votre lecteur via la console.
// 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();
}
Exemple de jeux
Le nombre de tours minimum que vous devez vaincre GunClubPlayer
est de 3. Voici la répétition de jouer 0-1
contre GunClubPlayer
. Le nombre entre parenthèses est le nombre de munitions chargées pour chaque joueur à la fin du tour.
:: 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 . . .
Le moyen le plus rapide pour être vaincu GunClubPlayer
sans faire de mouvements invalides est la séquence 0=
, car la balle tire à travers le déflecteur thermique. La rediffusion est
:: 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 . . .
Le tournoi
Le tournoi suit le format "Dernier joueur debout". Dans un tournoi, toutes les soumissions valables (y compris les GunClubPlayer
) sont placées dans un pool. Chaque soumission se voit attribuer un identifiant aléatoire mais unique qui restera le même pendant tout le tournoi. À chaque tour:
- Chaque candidature commence par 0 point et disputera 100 duels contre toutes les autres candidatures.
- Chaque duel victorieux accordera 1 point; dessiner et perdre donne 0 points.
- À la fin du tour, les soumissions avec le minimum de points quittent le tournoi. En cas d'égalité, le joueur avec le moins de points gagnés depuis le début du tournoi partira.
- S'il reste plus d'un joueur, le tour suivant commence.
- Les points NE sont PAS reportés au tour suivant.
Soumission
Vous allez soumettre un joueur par réponse. Vous pouvez soumettre plusieurs fichiers pour un joueur, à condition qu'ils n'interfèrent PAS avec d'autres soumissions. Pour que les choses continuent de couler, s'il vous plaît:
- Nommez votre fichier d'en-tête principal comme suit
<Custom>Player.hpp
: - Nommez vos autres fichiers comme
<Custom>Player*.*
, par exemple,MyLittlePlayer.txt
si votre nom de classe estMyLittlePlayer
ouEmoPlayerHates.cpp
si votre nom de classe estEmoPlayer
. - Si votre nom contient
Shooter
des mots similaires qui correspondent au contexte de ce tournoi, vous n’aurez pas besoin d’ajouterPlayer
à la fin. Si vous êtes fermement convaincu que votre nom de soumission fonctionne mieux sans suffixePlayer
, vous n'avez pas besoin d'ajouterPlayer
. - Assurez-vous que votre code peut être compilé et lié sous Windows.
Vous pouvez commenter pour demander des éclaircissements ou pour repérer des échappatoires. J'espère que vous apprécierez ce duel d'armes futuriste et vous souhaite une bonne année!
Clarification
- Vous êtes autorisé à avoir un comportement aléatoire.
- Les actions non valides (tirer lorsque des munitions chargées ne suffisent pas) sont autorisées.
- Si un joueur fait une entrée invalide, son arme explose immédiatement.
- Vous êtes autorisé à étudier les réponses.
- Vous êtes explicitement autorisé à enregistrer le comportement de votre adversaire dans chaque tournoi.
- Chaque tour, vous jouerez 100 duels contre chaque adversaire; Cependant, l'ordre des 100 duels est aléatoire. Vous n'êtes pas assuré de combattre le même adversaire 100 duels d'affilée.
Ressources additionnelles
@flawr a traduit la source C ++ fournie en Java en tant que référence si vous souhaitez soumettre des entrées C ++.
Interface pour les soumissions non C ++
Actuellement accepté: Python 3, Java.
Veuillez suivre l'une des spécifications ci-dessous:
Spécification d'interface 1: code de sortie
Votre soumission sera exécutée une fois par tour.
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.
Vous pouvez tester votre soumission dans PythonPlayer\
et des JavaPlayer\
répertoires.
Spécification d'interface 2: stdin / stdout
(Crédit à H Walters)
Votre soumission sera exécutée une fois par tournoi.
Il existe une exigence fixe pour toutes les entrées sur la manière de faire des E / S, puisque stdin et stdout sont tous les deux connectés au pilote du tournoi. Violer cela pourrait mener à une impasse. Toutes les entrées DOIVENT suivre cet algorithme EXACT (en pseudo-code):
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
Ici, F est l' un 0
, 1
, 2
, -
ou =
pour load / bullet / plasma / metal / thermal
. PROCESSUS signifie éventuellement répondre à ce que votre adversaire a fait (y compris le suivi des munitions de votre adversaire si vous le faites). Notez que l'action de l'adversaire est également l'une des actions "0", "1", "2", "-" ou "=", et se trouve dans le deuxième caractère.
Tableau de bord final
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 |
Le tournoi durera jusqu'au 1er février 2017, sauf indication contraire.
Player
implémentation qui appelle un autre processus pour calculer le tournant actuel. Cela permettrait aux gens de participer à n’importe quelle langue que vous êtes heureux d’utiliser sur votre machine.
Player::fight
" / "vous pouvez hériter Player::perceive
" ... dans les deux cas, le terme est redéfini , pas hérité .
GunDuel.hpp
deux validA
et que vous les validB
utilisezactionA