El futuro de fondo
En el año 2017, usted y su oponente se enfrentarán en un tiroteo futurista donde solo uno puede sobrevivir. ¿ Tienes suficiente experiencia para derrotar a tu oponente? ¡Ahora es el momento de pulir tus habilidades con las armas en tu lenguaje de programación favorito y luchar contra todo pronóstico!
Resultados del torneo
Este torneo terminó en la mañana del UTC de Feburary 2 nd , 2017. Gracias a nuestros concursantes, hemos tenido un emocionante torneo futurista!
MontePlayer es el ganador final después de una estrecha batalla con CBetaPlayer y StudiousPlayer. Los tres mejores duendes de guen han tomado una fotografía conmemorativa:
MontePlayer - by TheNumberOne
+------------+
CBetaPlayer | | - by George V. Williams
+------------+ # 1 | StudiousPlayer - by H Walters
| +----------------+
| # 2 # 3 |
+------------------------------------------+
The Futurustic Gun Duel @ PPCG.SE 2017
¡Felicitaciones a los ganadores! La tabla de clasificación detallada se ve cerca del final de esta publicación.
Orientación general
- Visita el repositorio oficial del código fuente utilizado en este torneo.
- Entradas de C ++: herede la
Player
clase. - Entradas que no son de C ++: seleccione una interfaz en la sección Interfaz para envíos que no sean de C ++ .
- Lenguajes actualmente no permitidos en C ++: Python 3, Java.
El duelo
- Cada jugador comienza con un arma descargada que puede cargar una cantidad infinita de munición.
- Cada turno, los jugadores elegirán simultáneamente una de las siguientes acciones:
0
- Cargue 1 munición en la pistola.1
- Dispara una bala al oponente; cuesta 1 munición cargada.2
- Dispara un rayo de plasma al oponente; cuesta 2 municiones cargadas.-
- Defiende la bala entrante con un escudo de metal.=
- Defienda el haz de plasma entrante con un deflector térmico.
- Si ambos jugadores sobreviven después de la 100 ª vez, ambos de escape a la muerte, lo que resulta en un empate .
Un jugador pierde el duelo armado si
- Did NO usar el escudo de metal que defender una bala entrante.
- Did NO utilizar el deflector térmico para defender un plasma entrante.
- Dispara un arma sin cargar suficiente munición, en la cual su arma explotará y matará al propietario.
Advertencias
De acuerdo con el Manual para propietarios de armas futuristas :
- Un escudo de metal NO PUEDE defenderse del haz de plasma entrante. Del mismo modo, un deflector térmico NO PUEDE defenderse de la bala entrante.
- El rayo de plasma domina la bala (porque el primero requiere más munición cargada). Por lo tanto, si un jugador dispara un rayo de plasma al oponente que dispara una bala en el mismo turno, el oponente es asesinado.
- Si ambos jugadores se disparan una a la otra en el mismo turno, las balas se cancelan y ambos jugadores sobreviven. Del mismo modo, si ambos jugadores se disparan un rayo de plasma el uno al otro en el mismo turno, ambos jugadores sobreviven.
También es digno de mención que:
- Usted no sabe la acción de su oponente en una vuelta hasta que se termina.
- Desviar los rayos de plasma y las balas de protección NO dañará a tu oponente.
Por lo tanto, hay un total de 25 combinaciones de acción válidas cada turno:
+-------------+---------------------------------------------+
| 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.
Duelo de ejemplo
Aquí hay un duelo que tuve una vez con un amigo. En aquel entonces, no sabíamos mucho sobre programación, así que usamos gestos con las manos y señalábamos a la velocidad de dos vueltas por segundo. De izquierda a derecha, nuestras acciones fueron a su vez:
Me: 001-000-1201101001----2
Friend: 00-10-=1-==--0100-1---1
Según las reglas anteriores, perdí. ¿Ves por qué? Es porque disparé el rayo de plasma final cuando solo tenía 1 munición cargada, haciendo que mi arma explotara.
El reproductor de C ++
Usted , como programador futurista civilizado, no manejará directamente las armas. En cambio, codificas una Player
que lucha contra los demás. Al heredar públicamente la clase c ++ en el proyecto GitHub, puede comenzar a escribir su leyenda urbana.
Player.hpp can be found in Tournament\Player.hpp
An example of a derived class can be found in Tournament\CustomPlayer.hpp
Lo que debes o puedes hacer
- Debe heredar la
Player
clase a través de la herencia pública y declarar su clase final. - Debe anular
Player::fight
, lo que devuelve un valor válidoPlayer::Action
cada vez que se llama. - Opcionalmente, anula
Player::perceive
y vigilaPlayer::declared
las acciones de tu oponente y realiza un seguimiento de tus victorias. - Opcionalmente, use miembros y métodos estáticos privados en su clase derivada para realizar cálculos más complejos.
- Opcionalmente, use otras bibliotecas estándar de C ++.
Lo que NO debes hacer
- NO debes usar ningún método directo para reconocer a tu oponente que no sea el identificador de oponente dado, que se baraja al comienzo de cada torneo. Solo puedes adivinar quién es un jugador a través de su juego dentro de un torneo.
- NO debe anular ningún método en la
Player
clase que no se declare virtual. - NO debe declarar ni inicializar nada en el ámbito global.
- Desde el debut de (ahora descalificado)
BlackHatPlayer
, los jugadores NO pueden mirar o modificar el estado de tu oponente.
Un ejemplo de duelo
El proceso de un duelo de armas se realiza utilizando la GunDuel
clase. Para ver un ejemplo de pelea, mira Source.cpp
en la sección Iniciando un duelo .
Mostramos GunClubPlayer
, HumanPlayer
y la GunDuel
clase, que se puede encontrar en el Tournament\
directorio del repositorio.
En cada duelo, GunClubPlayer
cargará una bala; dispararlo; enjuague y repita. Durante cada turno, HumanPlayer
te pedirá una acción para jugar contra tu oponente. Sus controles de teclado son los personajes 0
, 1
, 2
, -
y =
. En Windows, puede usar HumanPlayer
para depurar su envío.
Iniciando un duelo
Así es como puedes depurar tu reproductor a través de la consola.
// 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();
}
Juegos de ejemplo
La menor cantidad de turnos que necesitas para derrotar GunClubPlayer
es 3. Aquí está la repetición de jugar 0-1
contra GunClubPlayer
. El número en la parántesis es el número de munición cargada para cada jugador cuando finaliza el turno.
:: 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 . . .
La forma más rápida de ser derrotado GunClubPlayer
sin hacer movimientos inválidos es la secuencia 0=
, porque la bala dispara a través del deflector térmico. La repetición es
:: 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 . . .
El torneo
El torneo sigue el formato "Último jugador en pie". En un torneo, todos los envíos válidos (incluido el GunClubPlayer
) se colocan en un grupo. A cada envío se le asigna un identificador aleatorio pero único que permanecerá igual durante todo el torneo. Durante cada ronda:
- Cada envío comienza con 0 puntos y jugará 100 duelos contra cualquier otro envío.
- Cada duelo victorioso otorgará 1 punto; dibujar y perder dan 0 puntos.
- Al final de la ronda, los envíos con los puntos mínimos abandonan el torneo. En caso de empate, el jugador con la menor cantidad de puntos ganados desde el comienzo del torneo se irá.
- Si queda más de un jugador, comenzará la siguiente ronda.
- Los puntos NO se transfieren a la siguiente ronda.
Sumisión
Enviarás un jugador por respuesta. Puede enviar varios archivos para un jugador, siempre que NO interfieran con otras presentaciones. Para mantener las cosas fluyendo, por favor:
- Nombre su archivo de encabezado principal como
<Custom>Player.hpp
, - Nombre sus otros archivos como
<Custom>Player*.*
, por ejemplo,MyLittlePlayer.txt
si el nombre de su clase esMyLittlePlayer
, oEmoPlayerHates.cpp
si su nombre de clase esEmoPlayer
. - Si su nombre contiene
Shooter
o palabras similares que se ajustan al contexto de este torneo, no necesita agregarPlayer
al final. Si cree firmemente que su nombre de envío funciona mejor sin el sufijoPlayer
, tampoco necesita agregarloPlayer
. - Asegúrese de que su código se pueda compilar y vincular en Windows.
Puede comentar para pedir una aclaración o para detectar lagunas. ¡Espero que disfrutes de este duelo de armas futurista y te deseo un feliz año nuevo!
Aclaración
- Se le permite tener un comportamiento aleatorio.
- Se permiten acciones no válidas (disparar cuando la munición cargada no es suficiente).
- Si un jugador realiza una entrada no válida, su arma explotará inmediatamente.
- Puedes estudiar las respuestas.
- Se le permite explícitamente registrar el comportamiento del oponente dentro de cada torneo.
- Cada ronda, jugarás 100 duelos contra cada oponente; Sin embargo, el orden de los 100 duelos es aleatorio: no se garantiza que pelees con el mismo oponente 100 duelos seguidos.
Recursos adicionales
@flawr ha traducido la fuente de C ++ proporcionada a Java como referencia si desea enviar entradas de C ++.
Interfaz para envíos no C ++
Actualmente aceptado: Python 3, Java.
Siga una de las especificaciones a continuación:
Especificación de interfaz 1: código de salida
Su envío se ejecutará una vez por turno.
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.
Puede probar su presentación en PythonPlayer\
y JavaPlayer\
directorios.
Especificación de interfaz 2: stdin / stdout
(Crédito a H Walters)
Tu envío se ejecutará una vez por torneo.
Hay un requisito fijo para todas las entradas sobre cómo hacer E / S, ya que tanto stdin como stdout están conectados al controlador del torneo. Violar esto podría llevar a un punto muerto. Todas las entradas DEBEN seguir este algoritmo EXACTO (en pseudocódigo):
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
Aquí, M es uno de 0
, 1
, 2
, -
, o =
para load / bullet / plasma / metal / thermal
. PROCESO significa responder opcionalmente a lo que hizo tu oponente (incluido el seguimiento de la munición de tu oponente si estás haciendo esto). Tenga en cuenta que la acción del oponente también es una de '0', '1', '2', '-' o '=', y está en el segundo carácter.
Marcador 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 |
El torneo durará hasta el 1 de febrero de 2017 a menos que se indique lo contrario.
Player
implementación que invoque otro proceso para calcular el turno actual. Eso permitiría a las personas participar en cualquier idioma que esté dispuesto a ejecutar en su máquina.
Player::fight
" / "puede heredar Player::perceive
" ... en ambos casos, el término es anular , no heredar .
GunDuel.hpp
, ambos validA
y validB
usoactionA