Siendo al mismo tiempo un jugador maestro/contador de historias y un desarrollador, con frecuencia me hallo escribiendo pequeñas herramientas útiles y scripts para ayudarme cuando estoy ejecutando, jugando y planeando juegos. Algunas veces necesito una idea rápida. Otras veces, simplemente necesito toda una pila de nombres para Non-Player Characters (NPCs). Ocasionalmente, necesito idear números, trabajar en algunos contratiempos o integrar algunos juegos de palabras a algún juego. Muchas de estas tareas se tornan más manejables con un poco de trabajo de script adelantado.
Este artículo explorará 10 scripts fundamentales que pueden utilizarse en diferentes tipos de juegos. El archivo de código contiene la fuente completa de cada script que trataremos, y usted puede ver los scripts en acción en chaoticneutral.
Pasaremos por estos scripts bastante rápido. No cubriremos el tema de encontrar un host ni de configurar un servidor. Hay muchas compañías de hospedaje Web que ofrecen PHP, y el instalador XAMPP es fácil de usar si usted desea configurar el suyo propio. No emplearemos mucho tiempo hablando sobre las mejores prácticas PHP ni sobre técnicas de diseño de juegos. Estos scripts están diseñados para ser fáciles de entender, fáciles de usar y de uso rápido.
Muchos juegos y sistemas de juego necesitan dados. Comencemos con algo simple: lanzar un solo dado de seis lados. En esencia, no hay diferencia entre lanzar un dado de seis lados y seleccionar un número al azar entre 1 y 6. En PHP, esto es simple: echo rand(1,6);.
En muchos casos, eso sería más o menos suficiente. Pero cuando hablamos de juegos de oportunidades, nos gustaría algo un poco mejor. PHP ofrece un generador aleatorio de números mucho mejor: mt_rand(). Sin entrar en detalles sobre las diferencias entre los dos, es seguro suponer que mt_rand es un generador aleatorio de números más rápido y mejor: echo mt_rand(1,6);. Generalmente estaríamos más satisfechos si ponemos esto en una función.
Listado 1. Usando la función
mt_rand() de generación aleatoria de números
function roll () {
return mt_rand(1,6);
}
echo roll();
|
Luego podemos pasar el tipo de dado que queremos lanzar como un parámetro para la función.
Listado 2. Pasando el tipo de dado como un parámetro
function roll ($sides) {
return mt_rand(1,$sides);
}
echo roll(6); // roll a six-sided die
echo roll(10); // roll a ten-sided die
echo roll(20); // roll a twenty-sided die
|
Desde aquí, podemos avanzar para lanzar múltiples dados al mismo tiempo, retornando un conjunto de resultados, o lanzar múltiples dados de diferentes tipos al mismo tiempo, dependiendo de nuestras necesidades. Pero este simple script puede usarse para la mayoría de tareas.
Generador aleatorio de nombres
Si usted está ejecutando juegos, escribiendo historias o creando numerosos personajes al mismo tiempo, algunas veces es difícil estar inventando nombres nuevos. Observemos un generador aleatorio simple de nombres que puede usar para resolver este problema. Para empezar, construyamos dos arrays simples — uno de nombres y otro de apellidos.
Listado 3. Dos arrays simples de nombres y apellidos
$male = array(
"William",
"Henry",
"Filbert",
"John",
"Pat",
);
$last = array(
"Smith",
"Jones",
"Winkler",
"Cooper",
"Cline",
);
|
Luego podemos seleccionar un elemento al azar de cada array: echo $male[array_rand($male)] . ' ' . $last[array_rand($last)];. Para tomar un conjunto de nombres al mismo tiempo, simplemente podemos mezclar los arrays y tomar tantos como queramos.
Listado 4. Mezclando los arrays de nombres
shuffle($male);
shuffle($last);
for ($i = 0; $i <= 3; $i++) {
echo $male[$i] . ' ' . $last[$i];
}
|
Tomando este concepto básico, podemos crear archivos de texto para guardar nuestros nombres y apellidos. Si ponemos un nombre por línea en nuestro archivo de texto, podemos separar fácilmente el contenido del archivo en la línea de nuevo personaje para construir nuestros arrays fuentes.
Listado 5. Creando archivos de texto para nuestros nombres
$male = explode('\n', file_get_contents('names.female.txt'));
$last = explode('\n', file_get_contents('names.last.txt'));
|
Construya o encuentre algunos buenos archivos de nombres (se incluyen algunos en el archivo de código), y nunca más necesitaremos crear nombres.
Tomando los mismos principios básicos que hemos usado para crear el generador de nombres, podemos hacer lo que se llama un generador de escenarios. Esto es útil en los juegos de rol o en otras situaciones en las que necesitemos producir un conjunto pseudoaleatorio de circunstancias que puedan utilizarse para jugar un rol, improvisación, escritura, etc. Uno de mis juegos favoritos, Paranoia, incluye algo llamado "mezclador de misiones" en su GM Pack. El mezclador de misiones puede usarse para armar una misión tan rápido como lanzar un dado. Armemos nuestro generador de escenarios.
Contemple el siguiente escenario: Usted se despierta perdido en el bosque. Usted sabe que debe regresar a Nueva York, pero no sabe por qué. Usted puede oír perros ladrando y el inconfundible sonido cercano de las hostiles personas que le buscan. Usted tiene frío, está temblando y está desarmado. Cada frase en ese escenario presenta un aspecto específico del mismo:
- "Usted se despierta perdido en el bosque" — Esto establece el escenario.
- "Usted sabe que debe regresar a Nueva York" — Esto describe un objetivo.
- "Usted puede oír perros ladrando" — Esto presenta a un antagonista.
- "Usted tiene frío, está temblando y está desarmado" — Esto añade una complicación.
Tal como creamos archivos de texto para nuestros nombres y apellidos, comience creando un archivo de texto para cada escenario, objetivo, antagonista y complicación. En el archivo de código se incluyen archivos de muestra. Una vez tengamos estos archivos, el código para generar el escenario es bastante similar al código para generar los nombres.
Listado 6. Generando un escenario
$settings = explode("\n", file_get_contents('scenario.settings.txt'));
$objectives = explode("\n", file_get_contents('scenario.objectives.txt'));
$antagonists = explode("\n", file_get_contents('scenario.antagonists.txt'));
$complications = explode("\n", file_get_contents('scenario.complications.txt'));
shuffle($settings);
shuffle($objectives);
shuffle($antagonists);
shuffle($complications);
echo $settings[0] . ' ' . $objectives[0] . ' ' . $antagonists[0] . ' '
. $complications[0] . "<br />\n";
|
Podemos añadir elementos a nuestros escenarios agregando nuevos archivos de texto, o tal vez deseemos agregar múltiples complicaciones. Entre más agreguemos a nuestros archivos de texto base, más variados serán nuestros escenarios con el tiempo.
Creador y barajador de mazos de cartas
Si usted juega cartas y le interesa trabajar en algún script relacionado con cartas, vamos a construir un mazo de cartas con un barajador incorporado. Para comenzar, vamos a construir un mazo de cartas estándar. Necesitamos construir dos arrays — uno que guarde las pintas y otro que guarde los números y figuras. Más adelante esto aportará flexibilidad si deseamos agregar nuevas pintas o tipos de cartas.
Listado 7. Creación de un mazo de cartas básico
$suits = array (
"Picas", "Corazones", "Tréboles", "Diamantes"
);
$faces = array (
"Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho",
"Nueve", "Diez", "J", "Q", "K", "As"
);
|
Luego construimos un arreglo de mazo que contenga todos los valores de las cartas. Podemos hacer esto simplemente utilizando un par de bucles foreach .
Listado 8. Creación de un array de mazo de cartas
$deck = array();
foreach ($suits as $suit) {
foreach ($faces as $face) {
$deck[] = array ("face"=>$face, "suit"=>$suit);
}
}
|
Cuando tenemos construido el array del mazo, fácilmente podemos barajarlo y repartir una carta al azar.
Listado 9. Barajando el mazo y repartiendo una carta al azar
shuffle($deck); $card = array_shift($deck); echo $card['face'] . ' of ' . $card['suit']; |
Desde aquí, hay un corto trayecto hacia repartir manos de un mismo número establecido de cartas, o para crear un sabot de múltiples mazos.
Calculadora de posibilidades: Repartiendo cartas
Como podemos construir un mazo de cartas como hemos hecho, siguiendo la pinta y el número de cada carta individualmente, podemos utilizar el mazo de forma práctica para hacer algo como calcular las posibilidades de obtener una carta específica. Comencemos repartiendo dos manos de cinco cartas cada una.
Listado 10. Repartiendo dos manos de cinco cartas cada una
$hands = array(1 => array(), 2=>array());
for ($i = 0; $i < 5; $i++) {
$hands[1][] = implode(" of ", array_shift($deck));
$hands[2][] = implode(" of ", array_shift($deck));
}
|
Luego podemos analizar el mazo para ver cuántas cartas quedan y cuáles son las posibilidades de repartir una carta específica. Saber cuántas cartas quedan es fácil. Es simplemente contar cuántos elementos hay en el array $deck . Para obtener las posibilidades de repartir una carta específica, necesitamos una función que analice todo el mazo y que evalúe las cartas restantes para ver si coinciden.
Listado 11. Calculando las probabilidades de repartir una carta específica
function calculate_odds($draw, $deck) {
$remaining = count($deck);
$odds = 0;
foreach ($deck as $card) {
if ( ($draw['face'] == $card['face'] && $draw['suit'] ==
$card['suit'] ) ||
($draw['face'] == '' && $draw['suit'] == $card['suit'] ) ||
($draw['face'] == $card['face'] && $draw['suit'] == '' ) ) {
$odds++;
}
}
return $odds . ' in ' $remaining;
}
|
Ahora podemos seleccionar la carta que estamos tratando de obtener. Para facilitar esto, pase un array que se vea tal como una carta. Podemos buscar una carta específica.
Listado 12. Buscando una carta específica
$draw = array('face' => 'As', 'suit' => 'Picas');
echo implode(" of ", $draw) . ' : ' . calculate_odds($draw, $deck);
|
O podemos buscar una carta de una pinta y número dados.
Listado 13. Buscando una carta de una pinta y número dados
$draw = array('face' => '', 'suit' => 'Picas');
$draw = array('face' => 'As', 'suit' => '');
|
Ahora que tenemos un constructor de mazos de cartas y algo para ayudar a calcular las posibilidades de repartir cartas específicas, podemos armar un repartidor realmente simple para practicar manos de póquer. Para el propósito de este ejemplo, construiremos un repartidor de manos de cinco cartas. El repartidor repartirá cinco cartas del mazo. Usted especifica cuáles cartas desea descartar por número y el repartidor las reemplazará con otras cartas del mazo. No vamos a molestarnos poniendo límites ni reglas de la casa, aunque usted podrá notar que es un ejercicio personal satisfactorio.
Como se mostró en la sección anterior, genere y baraje un mazo y luego cree una mano simple de cinco cartas. Muestre estas cartas por su índice del array para poder especificar cuáles cartas devolver. Puede hacerlo usando recuadros de selección para señalar cuáles cartas va a reemplazar.
Listado 14. Usando recuadros de selección para señalar cuáles cartas va a reemplazar
foreach ($hand as $index =>$card) {
echo "<input type='checkbox' name='card[" . $index . "]'>
" . $card['face'] . ' of ' . $card['suit'] . "<br />";
}
|
Luego, evalúe la entrada array $_POST['card'] para saber cuáles cartas se han marcado para ser reemplazadas.
Listado 15. Evaluando la entrada
$i = 0;
while ($i < 5) {
if (isset($_POST['card'][$i])) {
$hand[$i] = array_shift($deck);
}
}
|
Usando este script, usted puede ensayar su mano — valga la ironía — descubriendo las mejores formas de manejar un conjunto de cartas específico.
El Ahorcado es en esencia un juego de adivinar palabras. Dada una palabra de una longitud definida, tenemos un número limitado de intentos de adivinar letras. Si se adivina una letra que aparece en la palabra, todas las ocurrencias de la letra se llenarán. Después de un número establecido de intentos (usualmente seis) usted habrá perdido el juego. Para armar un juego de ahorcado rudimentario, necesitamos comenzar con una lista de palabras. Por ahora, hagamos un array simple.
Listado 16. Creando una lista de palabras
$words = array (
"gigantes",
"triángulo",
"partícula",
"pajarera",
"mínimo",
"inundación"
);
|
Usando las técnicas cubiertas antes, podemos mover estas palabras hacia un archivo de texto externo de lista de palabras e importarlas como queramos.
En cuanto tenemos la lista de palabras necesitamos seleccionar una al azar, mostrar un espacio en blanco para cada letra y comenzar a recibir los intentos. Necesitamos llevar la cuenta de los intentos correctos y fallidos, tras cada intento. Haremos eso sin complicarnos simplemente serializando los arrays de intentos y pasándolos junto con cada intento. Si deseamos evitar que las personas hagan trampa observando la página fuente, preferiríamos hacer algo un poco más seguro.
Construir arrays que contengan nuestras letras y nuestros intentos correctos/errados. Para intentos correctos, encontraríamos un array con las letras como teclas y los puntos como valores.
Listado 17. Creación de arrays para contener letras e intentos
$letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
'p','q','r','s','t','u','v','w','x','y','z');
$right = array_fill_keys($letters, '.');
$wrong = array();
|
Ahora necesitamos un poco de código para evaluar los intentos y mostrar la palabra a medida que avanza el juego de adivinarla.
Listado 18. Evaluando los intentos y mostrando el avance
if (stristr($word, $guess)) {
$show = '';
$right[$guess] = $guess;
$wordletters = str_split($word);
foreach ($wordletters as $letter) {
$show .= $right[$letter];
}
} else {
$show = '';
$wrong[$guess] = $guess;
if (count($wrong) == 6) {
$show = $word;
} else {
foreach ($wordletters as $letter) {
$show .= $right[$letter];
}
}
}
|
En el archivo fuente podemos ver cómo serializar los arrays de intentos y pasarlos intento tras intento.
Sé que no es la forma correcta, pero algunas veces cuando usted está llenando un crucigrama puede estancarse tratando de buscar una palabra de cinco letras que comience con C y termine con T. Usando la misma lista de palabras que armamos para el Ahorcado, fácilmente podemos buscar palabras que coincidan con cierto patrón. Primero, establezca una forma para pasar palabras. Para facilitar esto, reemplace las letras faltantes con puntos: $guess = "c...t";. Como las expresiones regulares tratan al punto como caracter individual, fácilmente podemos analizar la lista de palabras en busca de coincidencias.
Listado 19. Analizando la lista de palabras
foreach ($words as $word) {
if (preg_match("/^" . $_POST['guess'] . "$/",$word)) {
echo $word . "<br />\n";
}
}
|
Dependiendo de la calidad de nuestra lista de palabras y de la precisión de nuestros intentos, deberíamos poder obtener una lista de palabras razonable para usarla para posibles coincidencias. Usted deberá decidir por sí mismo(a) si "chest" o "cheat" es la mejor para "una palabra de cinco letras que signifique 'no jugar según las reglas'".
Mad Libs es un juego de palabras en el que el jugador toma una corta historia y reemplaza tipos clave de palabras por palabras diferentes del mismo tipo, para crear una versión tonta de la misma historia. Tome el siguiente texto: "Estaba caminando por el parque cuando encontré un lago. Salté a él y tragué mucha agua. Tuve que ir al hospital". Comience reemplazando los tipos de palabras con indicadores de palabras diferentes. Comience cada señal con una raya al piso para evitar coincidencias accidentales de cadenas de caracteres.
Listado 20. Reemplazando tipos de palabras con indicadores de palabras
$text = "Cataba _VERBO_ando en el _LUGAR_ cuando encontré un _SUSTANTIVO_. _VERBO_é a él/ella, y _VERBO_é(í) demasiado(a) _SUSTANTIVO_. Tengo que ir al _LUGAR_."; |
Luego cree un par de listas de palabras básicas. Para este ejemplo, no lo haremos elaborado en exceso.
Listado 21. Creando un par de listas de palabras básicas
$verbs = array('bombear', 'saltar', 'caminar', 'tragar', 'gatear', 'aullar', 'rodar');
$places = array('parque', 'hospital', 'ártico', 'océano', 'tienda', 'sótano',
'ático', 'alcantarilla');
$nouns = array('agua', 'lago', 'asador', 'pies', 'gusano',
'suciedad', 'río', 'motor rotativo de Wankel');
|
Ahora podemos evaluar repetidamente el texto para reemplazar las señales según se necesite.
Listado 22. Evaluando el texto
while (preg_match("/(_VERB_)|(_PLACE_)|(_NOUN_)/", $text, $matches)) {
switch ($matches[0]) {
case '_VERB_' :
shuffle($verbs);
$text = preg_replace($matches[0], current($verbs), $text, 1);
break;
case '_PLACE_' :
shuffle($places);
$text = preg_replace($matches[0], current($places), $text, 1);
break;
case '_NOUN_' :
shuffle($nouns);
$text = preg_replace($matches[0], current($nouns), $text, 1);
break;
}
}
echo $text;
|
Obviamente, este es un ejemplo simple y rudimentario. Entre más precisas sean nuestras listas de palabras, y entre más tiempo dediquemos a nuestro texto base, mejores resultados obtendremos. Ya hemos utilizado archivos de texto para crear listas de nombres y listas de palabras básicas. Usando el mismo principio, podemos crear listas de palabras separadas por tipo y uso para crear Mad Libs más diversos.
Adivinar los seis números correctos en una lotería es, por decirlo de alguna forma, estadísticamente improbable. A pesar de ello, muchas personas aún pagan por jugar, y si le gustan los números, puede ser divertido ver las tendencias. Vamos a armar un script que nos permita hacer seguimiento de los números ganadores y proporcionar los seis números menos seleccionados de nuestra lista.
(Aviso de límite de responsabilidad: Esto no le ayudará a ganar la lotería, así que por favor no gaste su dinero en los tiquetes. Esto sólo es por diversión.)
Guardamos los números ganadores de la lotería en un archivo de texto. Separamos los números individuales con una coma y ponemos cada conjunto de números en su propia línea. Cuando obtengamos el resultado del archivo, lo dividimos en líneas nuevas y separamos cada línea por comas, para obtener algo que se ve como el Listado 23.
Listado 23. Guardando los números ganadores de la lotería en un archivo de texto
$picks = array(
array('6', '10', '18', '21', '34', '40'),
array('2', '8', '13', '22', '30', '39'),
array('3', '9', '14', '25', '31', '35'),
array('11', '12', '16', '24', '36', '37'),
array('4', '7', '17', '26', '32', '33')
);
|
Obviamente, esto no es un muy buen archivo base para generar estadísticas. Pero es un comienzo y lo suficiente para ilustrar los principios.
Establezca un array base para guardar el rango seleccionado. Por ejemplo, si seleccionamos números del 1 al 40 (esto es, $numbers = array_fill(1,40,0);, luego analizamos nuestros ganadores, incrementando los valores coincidentes apropiados.
Listado 24. Analizando nuestros ganadores
foreach ($picks as $pick) {
foreach ($pick as $number) {
$numbers[$number]++;
}
}
|
Finalmente, ordenamos los números con base en el valor. Esto debe poner a los números que menos han ganado al frente del array.
Listado 25. Ordenando los números con base en el valor
asort($numbers);
$pick = array_slice($numbers,0,6,true);
echo implode(',', array_keys($pick));
|
Al agregar regularmente números ganadores reales de la lotería al archivo de texto que contiene nuestra lista de ganadores, podemos buscar una tendencia de los números seleccionados en el largo plazo. Es interesante ver la frecuencia con que aparecen algunos números.
Este artículo es un recurso para que usted dé un salto hacia el uso de PHP para ayudar a enriquecer su experiencia de juego. En la Parte 2 de esta serie de "30 scripts de juegos que usted puede escribir en PHP", construiremos el código que se encuentra aquí y profundizaremos en scripts más complejos que le pueden beneficiar más.
| Descripción | Nombre | tamaño | Metodo de descarga |
|---|---|---|---|
| 10 PHP scripts | os-php-gamescripts1-php10games1.zip | 377KB | HTTP |
Información sobre métodos de descarga
Aprender
-
Getting started with XAMPP: XAMPP es una distribución Apache muy fácil d e instalar que contiene MySQL, PHP y Perl.
-
Observe ejemplos funcionales de todos los scripts.
-
U.S. Census Bureau es una excelente fuente de listas de nombres.
-
Obtenga algo de información sobre Paranoia.
-
Aprenda las reglas básicas para Five-card draw.
-
Aquí hay algunas listas de palabras útiles. Y ManyThings.org tiene aún más.
-
Visite el sitio oficial Mad Libs.
-
Apache V2 and PHP Installation: Lea un artículo sobre cómo obtener Apache V2 y PHP V4.x (también puede usar PHP V5.x) trabajando conjuntamente en Linux.
-
"Connecting PHP applications to Apache Derby" muestra cómo instalar y configurar PHP en Windows (algunos pasos aplican para Linux).
-
Lea "Learning PHP, Part 1" para aprender lo básico de PHP. Lea luego la Parte 2 para aprender cómo cargar archivos a ubicaciones no accesibles por la Web, usando DOM y SAX. Y la Parte 3 completa el flujo de trabajo de la aplicación.
-
Consulte el
Manual PHP para aprender más sobre los objetos de datos PHP y sus capacidades.
-
PHP.net es el recurso central para desarrolladores PHP.
-
Consulte la "Recommended PHP reading list."
-
Navegue por todo el contenido PHP en developerWorks.
-
Expanda sus habilidades PHP consultando los recursos del proyecto PHP de IBM developerWorks.
-
Para escuchar interesantes entrevistas y discusiones para desarrolladores de software, consulte los podcasts developerWorks.
-
¿Usando una base de datos con PHP? Consulte
Zend Core for
IBM, un entorno HP para desarrollo y producción, fácil de usar, de instalar y listo para usarse que soporta IBM DB2 V9.
-
Manténgase actualizado(a) con los eventos técnicos y webcasts developerWorks.
-
Consulte las próximas conferencias, ferias comerciales, webcasts y otros Eventos en todo el mundo que son de interés para desarrolladores de fuente abierta IBM.
-
Visite la zona Open source para información extensa "cómo hacer", herramientas y actualizaciones de proyectos, para ayudarle a desarrollar con tecnologías de fuente abierta y utilizarlas con productos IBM.
-
Observe y aprenda sobre IBM y sobre tecnologías de fuente abierta y funciones de productos con los demostrativos developerWorks on-demand gratuitos.
Obtener los productos y tecnologías
-
Innove en su próximo proyecto de desarrollo de fuente abierta con
software de prueba IBM, disponible para descarga o en DVD.
-
Descargue versiones de evaluación de productos IBM y practique con herramientas de desarrollo de aplicaciones y con productos de middleware de IBM DB2®, Lotus®, Rational®, Tivoli® y WebSphere®.
Comentar
-
Participe en los blogs de developerWorks e intégrese con la comunidad developerWorks.
-
Participe en el PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS), de developerWorks.