Your browser lacks required capabilities. Please upgrade it or switch to another to continue.
<<set $state to {
"x": 0, "y": 0, "min_x": 0, "max_x": 0, "min_y": 0, "max_y": 0,
"scenes": [],
"hp": 6, "hpmax": 6,
"level": 1,
"xp": 0,
"xplevel": 1000,
"at_bonus": 1,
"df_bonus": 1,
"inv":[
{ name: "una daga",
"at_bonus": 1, "eq": true, type: "weapon",
family: "equipment" },
{ name: "un chaleco",
"df_bonus": 1, "eq": true, type: "armor",
family: "equipment" },
]}>>
<<if not $savegames>>
<<set $savegames to {}>>
<</if>>
<<set $log to "<b>PANTHOR</b>\nUna epopeya conversacional por Remaches2K y BearL8<br/><br/>Release 1 / Serial number 190327 / Inform 7 build 6L38 (I6/v6.33 lib 6/12N)\n\nDurante tu ausencia en una escaramuza lejana el reino de Panthor ha sido invadido por hordas de monstruos salvajes. Han arrasado todas las aldeas y ciudades a su paso y se han hecho con el control. Ahora debes iniciar una revolución contra el Señor de la Muerte y liberar Panthor de sus hostiles invasores.\n\n[Escribe AYUDA si es la primera vez que juegas]\n\n"+parser.describe($state)>>
<<goto "Input">><<set $log to parser.trim_buffer($log)>>
<<set $log = $log + "> " + $player_input + "\n" >>
<<set $state.phase = 0>>
<<if $state.prompt neq null>>
<<set $state.confirm to $player_input.toLowerCase()>>
<<goto $state.prompt>>
<<else>>
<<if $state.gameover>>
<<goto ACT_GAMEOVER>>
<<else>>
<<if $player_input != null && $player_input.length > 0>>
<<set $command = parser.parse($player_input)>>
<</if>>
<<if $command>>
<<goto $command.action.id>>
<<else>>
<<goto ACT_ERROR>>
<</if>>
<</if>>
<</if>><div id="log" onclick="focusOnInput();">$log</div>\
> <<textbox "$player_input" "" "Parser" autofocus>>
<<set $command = parser.parse(" DeJar LÁmPaRa ") >>
<<print $command.action.id>>
<<print $command.args[$command.args.length-1]>>
<<print parser.localeEquals('barbaro', 'bárbaro')>>
<<print JSON.stringify(parser.findObj('restos'))>>
<<print JSON.stringify(parser.parseObj('barbaro',{encounter:{type:'bárbaro'}}))>>
<<print retro_parser.parseObj("consola").desc>>
Encuentros:
<<print JSON.stringify(parser.create_encounter({'x':0,'y':0}))>>
<<print JSON.stringify(parser.create_encounter({'x':4,'y':0}))>>
<<print JSON.stringify(parser.create_encounter({'x':9,'y':0}))>>
<<print JSON.stringify(parser.create_encounter({'x':16,'y':0}))>>
<<print JSON.stringify(parser.create_encounter({'x':25,'y':0}))>>
Ataques:
<<for _a = 1; _a < 10; _a ++>>
<<for _d = 1; _d < 10; _d ++>>
lvl: _a vs _d
<<print JSON.stringify(parser.create_attack(_a,0,_d,0))>>
<<print JSON.stringify(parser.create_attack(_a,0,_d,0))>>
<<print JSON.stringify(parser.create_attack(_a,0,_d,0))>>
<<print JSON.stringify(parser.create_attack(_a,0,_d,0))>>
<<print JSON.stringify(parser.create_attack(_a,0,_d,0))>>
<</for>>
<</for>>
Iniciativa:
<<for _a = 1; _a < 10; _a ++>>
<<for _d = 1; _d < 10; _d ++>>
lvl: _a vs _d
<<print JSON.stringify(parser.roll_initiative(_a,_d))>>
<<print JSON.stringify(parser.roll_initiative(_a,_d))>>
<<print JSON.stringify(parser.roll_initiative(_a,_d))>>
<<print JSON.stringify(parser.roll_initiative(_a,_d))>>
<<print JSON.stringify(parser.roll_initiative(_a,_d))>>
<<print JSON.stringify(parser.roll_initiative(_a,_d))>>
<</for>>
<</for>>
Items:
<<for _level = 1; _level < 10; _level ++>>
lvl _level:
<<for _i = 1; _i < 10; _i ++>>
<<print JSON.stringify(parser.roll_item(_level))>>
<</for>>
<</for>>
Critial rolls:
<<set _rolls to []>>
<<for _level = 0; _level < 100; _level ++>>
<<run _rolls.push(parser.d6m()) >>
<</for>>
<<print JSON.stringify(_rolls)>>
<<set _arg = $command.args[$command.args.length-1] >>
<<if not $state.inv[_arg-1] >>
<<set $log += "Debes indicar el número de objeto del inventario que quieras descartar.\n" >>
<<else>>
<<set _obj to $state.inv[_arg-1]>>
<<if _obj.eq >>
<<set $log += "El objeto está en uso.\n" >>
<<else>>
<<include "Timer">>
<<set $log += "Abandonas " +_obj.name +".\n" >>
<<run $state.inv.deleteAt(_arg-1) >>
<<include "Timer">>
<</if>>
<</if>>
<<goto Input>>
<<set $log = $log + "No puedes hacer eso.\n" >>
<<goto Input>><<if $state.encounter neq null and $state.encounter.boss>>
<<set $log+= "No puedes huir. Este es tu destino.\n">>
<<else>>
<<set _direction = $command.args[$command.args.length-1].charAt(0).toLowerCase() >>
<<set _table = {"n":[0,1],"s":[0,-1],"e":[1,0],"o":[-1,0]} >>
<<set _mov = _table[_direction ] >>
<<include "Timer">>
<<if _mov and $state.hp > 0>> /* valid direction and pc alive */
<<set $state.x = $state.x+_mov[0]>>
<<set $state.y = $state.y+_mov[1]>>
<<if $state.encounter neq null >>
<<if $state.encounter.hp > 0>>
<<set $log += "Huyes del encuentro.\n">>
<</if>>
<<set $state.encounter to null>>
<</if>>
<<set $log += parser.describe($state) >>
<<include "Scenes">>
<</if>>
<<include "Timer">>
<</if>>
<<goto Input>><<include "Timer">>
<<set $log = $log + parser.describe($state) >>
<<include "Timer">>
<<goto Input>><<set _arg = $command.args[$command.args.length-1] >>
<<include "Timer">>
<<set _obj = parser.parseObj(_arg, $state) >>
<<if _obj>>
<<set $log = $log + _obj.desc($state) +"\n" >>
<<if _obj is parser.findObj("enemigo") and
$state.encounter.hp <= 0 >>
<<include "Treasure">>
<</if>>
<<else>>
<<set _obj to $state.inv[_arg-1]>>
<<if _obj >>
<<switch _obj.type>>
<<case "weapon">>
<<set $log += "Es un arma que puedes EQUIPAR.\n">>
<<case "armor" "shield" "headwear">>
<<set $log += "Es una pieza de armadura que puedes EQUIPAR.\n">>
<<case "heal">>
<<set $log += "Puedes usarla para recuperarte de tus heridas.\n">>
<<case "map">>
<<set $log += "Puedes usarlo para localizar tu posición.\n">>
<<case "missile" "fireball" "icestorm">>
<<set $log += "Es un conjuro de un solo uso.\n">>
<<case "teleport">>
<<set $log+= "TODO...\n">>
<</switch>>
<<else>>
<<set $log += "No veo eso que dices (para examinar objetos del inventario indica su número).\n" >>
<</if>>
<</if>>
<<include "Timer">>
<<goto Input>><<if $state.inv.length == 0>>
<<set $log += "No llevas nada.\n" >>
<<else>>
<<set $log += "Llevas:<ol>" >>
<<for _item range $state.inv>>
<<set $log += "<li>" +_item.name >>
<<if _item.eq>>
<<set $log += " (en uso)" >>
<</if>>
<<set $log += "</li>">>
<</for>>
<<set $log += "</ol>">>
<</if>>
<<goto Input>><<if $state.confirm eq null>>
<<set $state.prompt = "ACT_SALIR">>
<<set $log = $log + "¿Seguro que quieres abandonar el juego? (S/N)\n">>
<<goto "Input">>
<<else>>
<<if $state.confirm is "s" >>
<<goto "Game Cover">>
<<else>>
<<set $state.confirm = null>>
<<set $state.prompt = null>>
<<goto "Input">>
<</if>>
<</if>>
<<include "Retro Graphic">>
<div id="log" onclick="focusOnInput();">$retro_log</div><<nobr>>
><<textbox "$player_input" "" "Retro Parser" autofocus>><</nobr>><<set $retro_state to {"on": false, "caida": false, "t":0} >>
<<set $retro_log to "Una nueva explosion sacude la estacion orbital.\n\nSales del laboratorio y te deslizas por el tunel hasta la capsula de salvamento. Confias en que todavia funcione despues de todo lo que ha pasado.\n\nCierras la puerta de la capsula y te sientas frente a la consola.">>
<<goto "Retro Input">><<set $retro_log = "> " + $player_input + "\n">>
<<if $retro_state.prompt neq null>>
<<set $retro_state.confirm to null>>
<<if $player_input.toLowerCase().startsWith("s")>>
<<set $retro_state.confirm to "s">>
<<else>>
<<set $retro_state.confirm to "n">>
<</if>>
<<goto $retro_state.prompt>>
<<else>>
<<set $command = retro_parser.parse($player_input) >>
<<if $command>>
<<goto $command.action.id>>
<<else>>
<<goto ZX_ERROR>>
<</if>>
<</if>>
<<set $retro_log = $retro_log + "No ves ninguna salida.\n" >>
<<goto "Retro Input">><<set _obj = retro_parser.parseObj($command.args[$command.args.length-1]) >>
<<if _obj>>
<<set $retro_log = $retro_log + _obj.desc($retro_state) +"\n" >>
<<else>>
<<set $retro_log = $retro_log + "No ves nada de eso aqui.\n" >>
<</if>>
<<include "Retro Timer">>
<<goto "Retro Input">><<set $retro_log = $retro_log + "No entiendo.\n" >>
<<goto "Retro Input">><<include "comp-nav">>
<div class="comp-body">\
<h1>MetaComp</h1>\
<h2>Una competición de Ficción Interactiva.</h2>
Un concurso de aventuras como cualquier otro. La mecánica es sencilla: juega y vota las obras presentadas.
<<include "README">>
</div><<include "comp-nav">>
<div class="comp-body">\
<h1>Acerca de</h1>\
A pesar de lo que lees en estas páginas tienes la impresión de que hay algo que no encaja en esta presunta competición de ficción interactiva. El formato, los autores, las obras... nada parece de verdad.
Una de las posibilidades que se te ocurren es que <<print either(
[
'tú también escribas ficción interactiva y estés soñando. Esta pesadilla es una manifestación del estrés que sientes para completar y publicar una obra.',
'en realidad estás en una instalación secreta del gobierno y pretenden extraer de ti alguna información. Esto sería un escenario de realidad virtual como los de Howling Dogs.',
'en realidad estás en coma, debatiéndote entre la vida y la muerte. Tu cerebro expresa este conflicto utilizando huellas mnémicas que le son familiares. Si en vez de jugador de FI fueras atleta te parecería estar en unas Olimpiadas.',
'has muerto y estás en una versión del Purgatorio producida a medida para autores y jugadores de ficción interactiva. Esto explicaría la calidad de las obras.',
'esto no sea más que una ficción interactiva más. Una especie de broma "meta" y, desde luego, de muy mal gusto. ¿Cuántos niveles de realidad simulada puede haber? ¿Estás en el más externo?'
]
)>>
</div><<include "comp-nav">>
<div class="comp-body">\
<h1>Obras</h1>\
<<include "metadata">>\
<<for _i, _item range $metadata>>\
<<capture _i>>\
<div class="works-item">\
<div class="works-image">\
[img[_item.title|_item.image][Game Cover][$work to _i]]\
</div>\
<div class="works-info">\
[[_item.title|Game Cover][$work to _i]] por _item.author
_item.blurb
</div>\
</div>\
<</capture>>
<</for>>\
</div><<if not $retro_state.caida>>
<<set $retro_log += "Empujas la palanca de propulsion a la posicion de actividad. La capsula esta todavia atracada en la estacion y la ignicion la destruye.\n\n *** Has muerto ***\n">>
<<goto "ZX_GAMEOVER">>
<<else>>
<<if $retro_state.on>>
<<set $retro_log += "La palanca ya esta en posicion de actividad.\n">>
<<else>>
<<set $retro_log += "Empujas la palanca de propulsion en posicion de actividad.\n">>
<<set $retro_state.on = true >>
<</if>>
<<include "Retro Timer">>
<<goto "Retro Input">>
<</if>>
<<if not $retro_state.on>>
<<set $retro_log = $retro_log + "La palanca ya esta en posicion de inactividad.\n">>
<<else>>
<<set $retro_log = $retro_log + "Tiras de la palanca de propulsion para desactivarla.\n">>
<<set $retro_state.on = false >>
<</if>>
<<include "Retro Timer">>
<<goto "Retro Input">><<set $retro_log = $retro_log + "El tiempo pasa.\n" >>
<<include "Retro Timer">>
<<goto "Retro Input">><<set $retro_log = $retro_log + "Estas en el asiento de una capsula de reentrada. Tienes delante una consola, y puedes ver el satelite sobre el que orbitaba tu estacion.\n" >>
<<include "Retro Timer">>
<<goto "Retro Input">><<if not $retro_state.caida>>
<<set _startCaida to true>>
<<set $retro_log = $retro_log + "Presionas con fuerza el boton. El mecanismo a anclaje libera la capsula. Comienzas el descenso en caida libre hacia el satelite. La consola se ilumina, mostrando los datos del proceso de reentrada.\n\n(El juego transcurre ahora en tiempo real)\n" >>
<<else>>
<<set $retro_log = $retro_log + "La capsula ya esta descendiendo.\n" >>
<</if>>
<<include "Retro Timer">>
<<if _startCaida>>
<<set $retro_state.caida to true>>
<<set $retro_state.ht to 10000>>
<<set $retro_state.v to 0>>
<<set $retro_state.f to 100>>
<<set $retro_state.t to Date.now()>>
<</if>>
<<goto "Retro Input">><<if $retro_state.confirm eq null>>
<<set $retro_state.prompt = "ZX_QUIT">>
<<set $retro_log = $retro_log + "Quieres abandonar? (S/N)\n">>
<<goto "Retro Input">>
<<else>>
<<if $retro_state.confirm is "s" >>
<<goto "Game Cover">>
<<else>>
<<set $retro_state.confirm = null>>
<<set $retro_state.prompt = null>>
<<set $retro_log = $retro_log + "Ok.\n">>
<<goto "Retro Input">>
<</if>>
<</if>>
<<set $retro_state.t = $retro_state.t + 1 >>
<<if $retro_state.t is 4 and not $retro_state.caida>>
<<set $retro_log to $retro_log + "\nLa estacion estalla y tu capsula, aun atracada en ella, tambien.\n\n *** Has muerto ***\n">>
<<goto "ZX_GAMEOVER">>
<</if>>
<<if $retro_state.caida>>
/* En caida? */
<<if $retro_state.on and $retro_state.f > 0>>
<<set _wasOn to true>>
<<set $retro_log to $retro_log + "Los motores de propulsion rugen con estruendo, haciendo vibrar la capsula.\n">>
<</if>>
<<run retro_parser.stepCaida($retro_state)>>
/* Combustible gastado? */
<<if _wasOn and $retro_state.f is 0>>
<<set $retro_log to $retro_log + "El combustible se ha terminado y los motores se detienen.\n">>
<</if>>
/* Aterrizaje! */
<<if $retro_state.ht <= 0>>
/* Finalizado */
<<if $retro_state.v < -40>>
<<set $retro_log to $retro_log + "La capsula choca con la superficie a "+ (- $retro_state.v) +" m/s. El impacto destruye la capsula y termina con tu vida.\n\n *** Has muerto ***\n">>
<<else>>
<<set $retro_log to $retro_log + "La capsula impacta en la superficie a "+ (- $retro_state.v) +" m/s. El aterrizaje ha sido brusco pero sigues de una pieza. La emisora de emergencia transmite tus coordenadas. Si en una base de superficie te han visto caer quiza te puedan venir a rescatar antes de que se termine el oxigeno.\n\n *** Has ganado ***\n">>
<<include "Achieved">>\
<<set $achieved[0] to true>>\
<</if>>
<<set $retro_state.caida to false >>
<<goto "ZX_GAMEOVER">>
<<else>>
/* Aun no finalizado */
<<set $retro_log to $retro_log
+ "Altura: "+$retro_state.ht+" m\n">>
<<set $retro_log to $retro_log
+ "Velocidad de caida: "+ (- $retro_state.v)+" m/s\n">>
<<set $retro_log to $retro_log
+ "Combustible: "+Math.floor($retro_state.f)+" %\n">>
<</if>>
<</if>> /* en caida */
<<if $retro_state.confirm eq null>>
<<set $retro_state.prompt = "ZX_GAMEOVER">>
<<set $retro_log = $retro_log + "Jugar de nuevo? (S/N)\n">>
<<goto "Retro Input">>
<<else>>
<<if $retro_state.confirm is "s" >>
<<goto "Launch retro">>
<<else>>
<<goto "Game Cover">>
<</if>>
<</if>><<if $state.phase eq 0>>
/* Pre PC-action timer */
/* <<set $log to $log + "Pre-action timer: "+$state.phase+"\n">> */
<<include "Encounter">>
<<set $state.phase to 1>>
<<else>>
/* Post PC-action timer */
/* <<set $log to $log + "Post-action timer: "+$state.phase+"\n">> */
<<include "Encounter">>
<</if>>
<<if $state.encounter eq null>>
/* Not in encounter. Roll new one? */
<<if $state.phase eq 1 >>
<<set $state.encounter to parser.roll_encounter($state)>>
<<if $state.encounter>>
<<set $log to $log+"Aparece un "+$state.encounter.type+".\n">>
<</if>>
<</if>>
<<else>>
/* In encounter. Calculate turn */
<<if $state.phase eq 0 >>
<<set $state.encounter.initiative to
parser.roll_initiative(
$state.encounter.level,
$state.level)>>
<</if>>
<<if $state.phase eq $state.encounter.initiative and
$state.encounter.hp > 0 >>
<<set $log to $log + "El enemigo ataca.\n">>
<<set _attack to parser.create_attack(
$state.encounter.level,
$state.encounter.at_bonus,
$state.level,
$state.df_bonus)>>
<<if _attack.result eq 1>>
<<set $state.hp to
Math.max(0, $state.hp - _attack.damage)>>
<<set $log = $log + "Te alcanza y te hace "+_attack.damage+" puntos de daño.\n">>
<<if $state.debug>>
<<set $state.hp to $state.hpmax>>
<<set $log += "[Debug: salud recuperada]\n">>
<</if>>
<<if $state.hp eq 0>>
<<goto "Death">>
<</if>>
<<else>>
<<set $log = $log + "Falla.\n">>
<</if>>
<</if>>
<</if>><<include "Timer">>
<<if $state.encounter and $state.encounter.hp>0>>
<<set $log = $log + "No puedes descansar en un encuentro.\n" >>
<<else>>
<<set $log = $log + "Esperas.\n" >>
<<if $state.hp < $state.hpmax>>
<<set $state.hp to $state.hp+1>>
<<set $log to $log + "Descansando recuperas un punto de vida.\n">>
<</if>>
<<if $state.encounter and $state.encounter.hp is 0 >>
<<set $log += either(
"Los restos del enemigo se convierten en polvo y se los lleva una ráfaga de viento.",
"Los restos del enemigo se convierten en ácido y se infiltran en el suelo.",
"Los restos del enemigo se inflaman espontáneamente y se desintegran.")
+"\n" >>
<<set $state.encounter to null>>
<</if>>
<</if>>
<<include "Timer">>
<<goto "Input">><<include "Timer">>
<<set _encounter to $state.encounter>>
<<if not _encounter or _encounter.hp eq 0>>
<<set $log = $log + "No hay nada que atacar.\n" >>
<<else>>
<<if $state.hp > 0>>
<<set $log = $log +
"Lanzas un ataque contra el "
+ _encounter.type +". ">>
<<set _attack to parser.create_attack(
$state.level, $state.at_bonus,
_encounter.level, _encounter.df_bonus)>>
<<if _attack.result eq 1>>
<<set _encounter.hp to
Math.max(0,_encounter.hp - _attack.damage)>>
<<set $log = $log + "Tu ataque inflige "+_attack.damage+" puntos de daño.\n">>
<<include "Combat Over">>
<<else>>
<<set $log = $log + "Fallas.\n">>
<</if>>
<</if>> /* if player alive */
<</if>>
<<include "Timer">>
<<goto "Input">><<if $state.confirm eq null>>
<<set $state.prompt = "ACT_GAMEOVER">>
<<set $log = $log + "¿Quieres REINICIAR, RECUPERAR un juego guardado o TERMINAR?\n">>
<<set $state.gameover to true>>
<<goto "Input">>
<<else>>
<<switch $state.confirm>>
<<case "reiniciar">>
<<goto "Launch parser">>
<<case "terminar">>
<<goto "Game Cover">>
<<case "recuperar">>
<<set $state.confirm to null>>
<<goto "ACT_RESTORE">>
<<default>>
<<set $log = $log +
"Por favor, da una de las respuestas anteriores.\n">>
<<goto "Input">>
<</switch>>
<</if>><<include "Timer">>
<<set $log = $log +
" Puntos de vida: " + $state.hp + "\n"+
" Puntos de experiencia: " + $state.xp + "\n"+
" Nivel: "+$state.level + "\n"
>>
<<include "Timer">>
<<goto "Input">><<if $state.xp >= $state.xplevel>>
<<set $state.level to $state.level+1>>
<<set $state.xplevel to $state.xplevel + ($state.level*1000)>>
<<set _hpup = random(2,6)>>
<<set $state.hpmax to $state.hpmax + _hpup>>
<<set $state.hp to $state.hp + _hpup>>
<<set $log to $log + "[ Has ganado un nivel ]\n">>
<</if>><<if $state.confirm eq null>>
<<set $state.prompt = "ACT_SAVE">>
<<set $log = $log + "Introduce un nombre para la partida:\n">>
<<else>>
<<set _confirm to $state.confirm>>
<<if _confirm eq 0>>
<<set $log = $log + "Juego no guardado.\n">>
<<set $state.confirm = null>>
<<set $state.prompt = null>>
<<else>>
<<set $log = $log + 'Guardada partida "'+_confirm + '".\n'>>
<<set $state.confirm = null>>
<<set $state.prompt = null>>
<<set $savegames[_confirm] to clone($state)>>
<</if>>
<</if>>
<<goto "Input">>
<<if $state.confirm eq null>>
<<set $state.prompt = "ACT_RESTORE">>
<<set $log = $log + "Partida a cargar:\n">>
<<else>>
<<if $state.confirm.length eq 0>>
<<set $log = $log + "Carga cancelada.\n">>
<<set $state.confirm = null>>
<<if not $state.gameover>>
<<set $state.prompt = null>>
<<else>>
<<set $state.prompt = "ACT_GAMEOVER">>
<</if>>
<<else>>
<<if $savegames[$state.confirm] eq null>>
<<set $log = $log + 'Partida no encontrada: "' +
$state.confirm + '".\n'>>
<<set $state.confirm = null>>
<<if not $state.gameover>>
<<set $state.prompt = null>>
<<else>>
<<set $state.prompt = "ACT_GAMEOVER">>
<</if>>
<<else>>
<<set $log = $log + 'Cargando partida "' +
$state.confirm + '".\n'>>
<<set $state to clone($savegames[$state.confirm]) >>
<<set $log = $log + "Partida cargada.\n">>
<<set $state.debug to false>>
<</if>>
<</if>>
<</if>>
<<goto "Input">><<set $log = $log + "\n <b>*** Has muerto ***</b>\n\n">>
<<goto ACT_GAMEOVER>><<if not $state.encounter.searched>>
<<set $treasure to parser.roll_item($state.encounter.level) >>
<</if>>
<<if $state.encounter.searched or not $treasure>>
<<set $log= $log + "Registras los restos sin encontrar nada.\n">>
<<else>>
<<set $log = $log + "¡Entre los restos encuentras "+$treasure.name+"! (se ha añadido al inventario)\n">>
<<run $state.inv.push($treasure) >>
<</if>>
<<set $state.encounter.searched to true>><<set _arg = $command.args[$command.args.length-1] >>
<<if not $state.inv[_arg-1] >>
<<set $log += "Indica un número del objeto del inventario.\n" >>
<<else>>
<<set _obj to $state.inv[_arg-1]>>
<<if _obj.eq >>
<<set $log += "Ya está en uso.\n" >>
<<else>>
<<if _obj.family eq "equipment">>
<<include "Equipment">>
<</if>>
<<if _obj.family eq "special">>
<<include "Special">>
<</if>>
<</if>>
<</if>>
<<goto Input>>
<<set _q to $quiz_questions[$quiz_state.current]>>
<div class="quiz-container">
_q.t
<<for _response range _q.r>>\
<<capture _response>>\
[[_response.t|Eval][$exec to _response.x]]
<</capture>>\
<</for>>\
</div><<set _q to $quiz_questions[$current]>>
<<if $exec>>
<<set $quiz_state.attr[0] to ($quiz_state.attr[0] + ($exec[0]))>>
<<set $quiz_state.attr[1] to ($quiz_state.attr[1] + ($exec[1]))>>
<<set $quiz_state.attr[2] to ($quiz_state.attr[2] + ($exec[2]))>>
<<set $quiz_state.attr[3] to ($quiz_state.attr[3] + ($exec[3]))>>
<</if>>
<<for $quiz_state.current to $quiz_state.current+1;
$quiz_questions[$quiz_state.current] and
$quiz_questions[$quiz_state.current]['check'] and
not
$quiz_questions[$quiz_state.current].check();
$quiz_state.current = $quiz_state.current + 1 >>
<</for>>
<<if $quiz_state.current >= $quiz_questions.length>>
<<goto "Quiz End">>
<<else>>
<<goto "Quiz Input">>
<</if>>
<<set $quiz_state to {
"current": 0,
"attr": [0,0,0,0]}>>
/* art, com, exp, div */
<<set $quiz_questions to [
{
t: "En estos momentos la Ficción Interactiva (en adelante, FI) está más viva que nunca.",
r: [
{t: "Sí", x: [0, 0, 1, 1]},
{t: "No", x: [0, 0, -1, -1]}
]
},
{
t: "Me interesa sobre todo el valor literario de la FI, por encima del resto de aspectos.",
r: [
{t: "Sí", x: [1, 0, 0, 0]},
{t: "No", x: [-1, 0, 0, 0]}
]
},
{
t: "La jugabilidad me parece un aspecto secundario en la FI comparado con otros, como el discurso artístico o la calidad de la escritura.",
check: function check() {
return $quiz_state.attr[0] > 0;
},
r: [
{t: "Sí", x: [1, -1, 1, 0]},
{t: "No", x: [-1, 1, 0, 0]}
]
},
{
t: "La FI ideal ofrece entornos inmersivos y lo más interactivos posible para explorar libremente.",
r: [
{t: "Sí", x: [0, 0, 1, 0]},
{t: "No", x: [0, 0, -1, 0]}
]
},
{
t: "El cuidado de la estética y la presentación visual van en detrimento de lo verdaderamente importante en la FI.",
r: [
{t: "Sí", x: [-1, -1, 0, -1]},
{t: "No", x: [1, 1, 0, 1]}
]
},
{
t: "La FI es ante todo un reencuentro con sensaciones y recuerdos del pasado.",
r: [
{t: "Sí", x: [0, 0, -1, 0]},
{t: "No", x: [0, 0, 1, 0]}
]
},
{
t: "La aparición de iniciativas comerciales es positiva para la FI en su conjunto.",
r: [
{t: "Sí", x: [0, 1, 0, 0]},
{t: "No", x: [0, -1, 0, 0]}
]
},
{
t: "¿Consideraría comprar, o pagar de alguna forma por una obra de FI?",
r: [
{t: "Sí", x: [0, 1, 0, 0]},
{t: "Sólo en soporte físico", x: [0, 1, 1, 0]},
{t: "No", x: [0, -1, 0, 0]}
]
},
{
t: "Es importante en la FI su aspecto de hobby, altruista y desinteresado.",
check: function check() {
return $quiz_state.attr[1] < -3;
},
r: [
{t: "Sí", x: [0, -1, 0, 0]},
{t: "No", x: [0, 1, 0, 0]}
]
},
{
t: "La promoción personal, el ánimo de lucro y el culto al autor desvirtúan lo que debe ser el espíritu de la FI.",
check: function check() {
return $quiz_state.attr[1] < -4;
},
r: [
{t: "Sí", x: [1, 1, 0, 0] },
{t: "No", x: [-1, -1, 0, 0]}
]
},
{
t: "Veo la FI como algo inseparable del fenómeno retroinformático.",
r: [
{t: "Sí", x: [0, 0, -1, 0]},
{t: "No", x: [0, 0, 1, 0]}
]
},
{
t: "Para mí son bienvenidos todos los formatos de FI.",
r: [
{t: "Sí", x: [0, 0, 1, 1]},
{t: "No", x: [0, 0, -1, -1]}
]
},
{
t: "La auténtica FI son las aventuras conversacionales o juegos de parser.",
check: function check() {
return $quiz_state.attr[3] < 0 && $quiz_state.attr[2] < 0;
},
r: [
{t: "Sí", x: [0, 0, -1, -1]},
{t: "No", x: [0, 0, 1, 1]}
]
},
{
t: "En las competiciones de FI se debe separar la categoría de parser y el resto (librojuegos, etc.).",
r: [
{t: "Sí", x: [0, 0, -1, -1]},
{t: "No", x: [0, 0, 1, 1]}
]
},
{
t: "En una competición de IF con obras de formatos variados...",
check: function check() {
return $quiz_state.attr[3] < -4;
},
r: [
{t: "Probaré de todo juzgando cada cosa por sus propios méritos.", x: [1, 0, 1, 1]},
{t: "Selecciono un formato preferido e ignoro lo que no me interesa.", x: [0, 0, 0, -1]},
{t: "Voto contra cierto formato para expulsarlo de la comunidad.", x: [-1, 0, -1, -1]}
]
},
{
t: "Como jugador o (inter)lector estoy dispuesto a seguir a los autores a canales de publicación propios.",
r: [
{t: "Sí", x: [0, 1, 1, 1]},
{t: "No", x: [0, -1, -1, -1]}
]
},
{
t: "Es importante que los nuevos autores de FI trabajen en las comunidades y archivos existentes.",
check: function check() {
return $quiz_state.attr[1] < 0;
},
r: [
{t: "Sí", x: [0, -1, 0, -1]},
{t: "No", x: [0, 1, 0, 1]}
]
},
{
t: "Al probar una IF me gusta identificarme con los personajes protagonistas.",
r: [
{ t: "Sí", x: [1, 0, 0, 1]},
{ t: "No", x: [-1, 0, 0, -1]}
]
},
{
t: "Me interesa que la FI me acerque temas sociales y políticos, aunque estos queden lejos de mi experiencia inmediata.",
check: function check() {
return $quiz_state.attr[3] > 0;
},
r: [
{t: "Sí", x: [1, 0, 0, 1]},
{t: "No", x: [-1, 0, 0, -1]}
]
},
{
t: "Hay una tendencia en la FI (y en otros ámbitos del fandom) a introducir temáticas que polarizan innecesariamente las comunidades.",
check: function check() {
return $quiz_state.attr[3] < 0;
},
r: [
{t: "Sí", x: [-1, 0, 0, -1]},
{t: "No", x: [1, 0, 0, 1]}
]
},
{
t: "Es necesaria cierta autocrítica y análisis de valores en las comunidades de FI, como la que se promueve con los códigos de conducta.",
check: function check() {
return $quiz_state.attr[3] > 5;
},
r: [
{t: "Sí", x: [1, 0, 1, 1]},
{t: "No", x: [-1, 0, -1, -1]}
]
},
{
t: "Ciertos colectivos están insistiendo en poner la FI al servicio de su agenda, hasta el punto de desvirtuarla.",
check: function check() {
return $quiz_state.attr[3] < -8;
},
r: [
{t: "Sí", x: [0, 0, 0, -1]},
{t: "No", x: [0, 0, 0, 1]}
]
},
{
t: "El movimiento SJW está arruinando la FI (como tantas otras cosas).",
check: function check() {
return $quiz_state.attr[3] < -9;
},
r: [
{t: "Sí", x: [0, 0, -1, -1]},
{t: "No", x: [0, 0, 1, 1]}
]
}
]>>
<<goto "Quiz Input">><div class="quiz-container">
<h2>Estado de la Cuestión</h2>\
El resultado del test de actitudes es: /*art, com, exp, div */
<<if $quiz_state.attr[0] < 0>>\
EN CONTRA de la orientación artística de la IF.
<</if>>\
<<if $quiz_state.attr[0] > 0>>\
A FAVOR de la orientación artística de la IF.
<</if>>\
<<if $quiz_state.attr[1] < 0>>\
EN CONTRA de las propuestas comerciales o profesionales.
<</if>>\
<<if $quiz_state.attr[1] > 0>>\
A FAVOR de las propuestas comerciales o profesionales.
<</if>>\
<<if $quiz_state.attr[2] < 0>>\
EN CONTRA de la experimentación en IF.
<</if>>\
<<if $quiz_state.attr[2] > 0>>\
A FAVOR de la experimentación en IF.
<</if>>\
<<if $quiz_state.attr[3] < 0>>\
EN CONTRA de la diversidad en la IF.
<</if>>\
<<if $quiz_state.attr[3] > 0>>\
A FAVOR de la diversidad en la IF.
<</if>>\
<<if $quiz_state.attr[0] == 0 && $quiz_state.attr[1] == 0 &&
$quiz_state.attr[2] == 0 && $quiz_state.attr[3] == 0 >>
Totalmente neutral en cuanto al carácter artístico, comercial, experimental o diverso en la IF.
<</if>>
/* Fin: $quiz_state.attr */
<<include "Achieved">>\
<<set $achieved[2] to true>>\
[[Repetir->Launch Quiz]]
[[Terminar->Game Cover]]
</div>
<<include "Quiz End Image">><div class="comp-nav">\
[[MetaComp->Front]] \
[[Obras->Works]] \
[[Acerca de]] \
<div class="comp-nav-last">\
<<link "Reiniciar">>\
<<script>>
Save.clear();
UI.restart();
<</script>>\
<</link>>\
</div>\
</div><<include "comp-nav">>
<<include "metadata">>\
<div class="comp-body" style="display:flex">\
<div style="width:80%">\
<h1>$metadata[$work].title</h1>
[img[$metadata[$work].image]]
Por $metadata[$work].author
<h3>Sinopsis</h3>\
<p>$metadata[$work].description</p>\
<h3>Valoraciones</h3>\
<<for _comment range $metadata[$work].comments>>\
<p>\
<<switch _comment.rating>>\
<<case 1>>★☆☆☆☆\
<<case 2>>★★☆☆☆\
<<case 3>>★★★☆☆\
<<case 4>>★★★★☆\
<<case 5>>★★★★★\
<</switch>>\
<b>_comment.title</b>
_comment.text (_comment.author)
</p>\
<</for>>\
<<include "Ratings">>
</div>
<div style="
width: 20%;
margin: .67em 0;
text-align: center;
background: #f0f0f0;">
<<button "Jugar online" $metadata[$work].passage>><</button>>
</div>
</div><<set $metadata to [
{
title: 'El Descenso',
author: 'Rob Retro',
image: $images.ganymede,
passage: 'Retro cover',
blurb: 'Aventura simulacionista retro.',
description: 'Un accidente destruye la estación orbital en la que trabajas, y debes ejecutar la maniobra de alunizaje. Nanoaventura simulacionista en tiempo real.',
comments: [
{
rating: 2,
title: "Pereza de 8 bits",
text: "Obra que adolece de falta de agencia e interactividad. Implementación aceptable de un concepto demasiado visto, simple y sin interés.",
author: "Interlector Malherido"
}
]
},
{
title: 'Panthor',
author: 'Remaches2K y BearL8',
image: $images.helmet,
passage: 'Launch parser',
blurb: 'Roguelike místico conversacional.',
description: 'El reino de Panthor ha sido invadido por hordas de monstruos que han arrasado todo a su paso. Ahora debes prepararte y derrotar al Señor de la Muerte.\n<ul><li>Un mundo ilimitado para explorar.</li><li>Decenas de objetos que puedes encontrar y equipar.</li><li>Sistema de combate y experiencia: aumenta tu poder para incrementar tus oportunidades.</li></ul><i>"Cuando comenzamos a diseñar el juego estábamos realmente agobiados. No sabíamos cómo realizar esta colosal producción compaginando nuestros trabajos y quehaceres diarios. Digo esto porque, sinceramente, creo que nadie podría crear un conversacional tan épico y brutal como el que tenemos aquí."</i>',
comments: [
{
rating: 5,
title: "Brutal",
text: "Es increíble explorar el mundo de Panthor. Los autores se han esforzado a tope en cada elemento del juego para que lo experimentes al máximo. No es exagerado decir que no existe ningún conversacional comparable con el trabajo de estos genios.",
author: "Wonky"
}
]
},
{
title: 'Estado de la Cuestión',
author: 'Anita Saskatchewan',
image: $images.anova,
passage: 'Launch Quiz',
blurb: 'Una Encuesta de Actitudes hacia la Ficción Interactiva.',
description: 'Cuestionario de evaluación de diferentes parámetros actitudinales en el marco de la comunidad de ficción interactiva, y posible herramienta de introspección personal.',
comments: [
{
rating: 1,
title: "No es un juego",
text: "No sé qué pinta esta obra en una Comp de Ficción Interactiva.",
author: "Denethor"
}
]
},
{
title: 'Ouroboros',
author: 'Weltgeist',
image: $images.ouroboros,
passage: 'Snake',
blurb: 'Un arcade zen.',
description: 'Un juego de acción basado en el concepto nietzscheano del eterno retorno.',
notAchieved: 'Crees que debes ver la obra antes de votarla.',
comments: [
{
rating: 1,
title: "¿Dónde está la IF?",
text: "Un arcade abstracto sin nada de narración.",
author: "FIrfurcio"
},
{
rating: 5,
title: "Está todo aquí",
text: "Me parece una pasada esta obra. Nos habla de la escasez de recursos, el consumismo... una representación del capitalismo terminal.",
author: "ernest_costra"
}
]
},
]>>
<<set _arg = $command.args[$command.args.length-1] >>
<<set _obj to $state.inv[_arg-1]>>
<<include "Timer">>
<<if $state.hp > 0>>
<<set $log += "Equipas " +_obj.name +".\n" >>
<<run $state.inv
.filter(function(o) { return o.type == _obj.type;})
.forEach(function(o) { return (o.eq = false);})>>
<<set _obj.eq to true >>
/* Recalculate at_bonus and df_bonus */
<<set $state.at_bonus = 0 >>
<<set $state.df_bonus = 0 >>
<<for _item range $state.inv >>
<<if _item.eq and _item.df_bonus>>
<<set $state.df_bonus += _item.df_bonus>>
<</if>>
<<if _item.eq and _item.at_bonus>>
<<set $state.at_bonus += _item.at_bonus>>
<</if>>
<</for>>
<<include "Timer">>
<</if>> /* if player alive */<<set _arg = $command.args[$command.args.length-1] >>
<<set _obj to $state.inv[_arg-1]>>
<<include "Timer">>
<<if $state.hp > 0>>
<<set $log += "Usas " +_obj.name +".\n" >>
<<switch _obj.type>>
<<case "heal">>
<<set $log += "Recuperas tu salud.\n" >>
<<set $state.hp to $state.hpmax >>
<<run $state.inv.deleteAt(_arg-1) >>
<<case "superheal">>
<<set $log += "Notas aumentar tus energías.\n" >>
<<set $state.hp += $state.hpmax >>
<<run $state.inv.deleteAt(_arg-1) >>
<<case "map">>
<<include "Map">>
<<case "missile" "fireball" "icestorm" "identify">>
<<include "Spell">>
<</switch>>
<<include "Timer">>
<</if>> /* if player alive */<<if $state.x == 0 and $state.y == 0>>
<<set $log += "Te encuentras en el punto de partida.">>
<<else>>
<<set _posY to Math.abs($state.y)>>
<<set _posX to Math.abs($state.x)>>
<<if $state.y > 0>><<set _dirY to "norte">><</if>>
<<if $state.y < 0>><<set _dirY to "sur">><</if>>
<<if $state.x > 0>><<set _dirX to "este">><</if>>
<<if $state.x < 0>><<set _dirX to "oeste">><</if>>
<<if _posY > 0 and _posX > 0>>
<<set $log +=
"Te encuentras a "+_posY+" localidad(es) al "+_dirY +
" y " +_posX + " al "+_dirX+ " del punto de partida.\n">>
<<else>>
<<if _posY > 0>>
<<set $log +=
"Te encuentras a "+_posY+" localidad(es) al "+_dirY +
" del punto de partida.\n">>
<</if>>
<<if _posX > 0>>
<<set $log +=
"Te encuentras a "+_posX+" localidad(es) al "+_dirX +
" del punto de partida.\n">>
<</if>>
<</if>>
<</if>><<set _arg = $command.args[$command.args.length-1] >>
<<set _obj to $state.inv[_arg-1]>>
<<switch _obj.type>>
<<case "missile">>
<<set $log+= "¡Lanzas un proyectil mágico!\n">>
<<set _damageDice to 4>>
<<case "fireball">>
<<set $log+= "¡Lanzas una bola de fuego!\n">>
<<set _damageDice to 8>>
<<case "icestorm">>
<<set $log+= "¡Lanzas una tormenta de hielo!\n">>
<<set _damageDice to 12>>
<<case "identify">>
<<set $log+= "El conjuro hace brillar con el fulgor de la magia algunas de tus pertenencias...<ol>">>
<<for _item range $state.inv>>
<<if _item.at_bonus or _item.df_bonus>>
<<set $log += "<li>" +_item.name >>
<<if _item.at_bonus>>
<<set $log += " +"+_item.at_bonus>>
<</if>>
<<if _item.df_bonus>>
<<set $log += " +"+_item.df_bonus>>
<</if>>
<<set $log += "</li>">>
<</if>>
<</for>>
<<set $log+= "</ol>">>
<</switch>>
<<if _damageDice>>
<<set _encounter to $state.encounter >>
<<if _encounter and _encounter.hp > 0>>
<<set _damage = 0>>
<<for _die to 0; _die lt _damageDice; _die++>>
<<set _damage += parser.d6() >>
<</for>>
<<set _encounter.hp to
Math.max(0,_encounter.hp - _damage)>>
<<set $log += "El conjuro hace "+_damage+" puntos de daño.\n">>
<<include "Combat Over">>
<<else>>
<<set $log += "El efecto del conjuro se pierde en el aire.\n">>
<</if>>
<</if>> /* _damageDice */
<<run $state.inv.deleteAt(_arg-1) >>
<<set $log+= "El pergamino se deshace en cenizas después de leerlo.\n">>
<<if $state.encounter.hp eq 0>>
<<if not $state.encounter.boss>>
<<set $log = $log +
"Has terminado con tu contrincante.\n">>
<<set _xpup to $state.encounter.level * 100 >>
<<set $log = $log +
"[ Ganas "+_xpup+" puntos de experiencia ]\n">>
<<set $state.xp to $state.xp + _xpup>>
<<include "Level">>
<<else>>
<<goto Endgame>>
<</if>>
<</if>><div class="quiz-container">
<h2>Estado de la Cuestión</h2>\
por Anita Saskatchewan
La presente obra simula un cuestionario de investigación sociológica sobre la experiencia de la Ficción Interactiva. Gracias por participar.
[[Empezar->Quiz Init]]
</div>
<div style="width:420px;height:420px;position:absolute;bottom:0%;left:40%;overflow:hidden">\
<img style="margin-left:-220px;margin-top:-220px;opacity:0.2" @src="$images.stain_c">\
</div>\<<set _newGround to
$state.x < $state.min_x or $state.x > $state.max_x or
$state.y < $state.min_y or $state.y > $state.max_y >>
<<set $state.min_x to Math.min($state.x, $state.min_x)>>
<<set $state.max_x to Math.max($state.x, $state.max_x)>>
<<set $state.min_y to Math.min($state.y, $state.min_y)>>
<<set $state.max_y to Math.max($state.y, $state.max_y)>>
<<if _newGround>>
<<set _scene to parser.roll_scene($state) >>
<</if>>
<<if _scene>>
<<switch _scene>>
<<case 1>>
<<set $log += "\nPor el camino has encontrado los restos de un grupo de casas aún ardiendo. Un joven superviviente estaba recogiendo algunos restos de sus pertenencias de entre las brasas. Al preguntarle por lo sucedido contestó:\n- Nadie sabe exactamente lo que ha pasado. Aquí oímos primero una especie de tormenta. Después... empezaron a llegar los monstruos y a matar a todo el mundo.\n\nContinuaste tu camino, dejándolo atrás.\n">>
<<case 2>>
<<set $log += "\nUna diezmada caravana de sabios se cruza en tu camino. Viendo que portas armas te miran con recelo, pero uno de ellos te cuenta que los astros habían profetizado esta catástrofe. Según la cosmovisión de su escuela, los advenimientos del Señor de la Muerte y sus hordas marcan los cambios de Era.\n">>
<<case 3>>
<<set $log += "\nTe encuentras con un grupo de niños que parecen huérfanos. Te informan de que la destrucción parece originarse en la dirección a la que te diriges.\n\nCuando te preguntan por un sitio seguro donde ir no tienes una respuesta. El reino parece estar sumido en el caos.\n">>
<<case 4>>
<<set $log += "\nHas pasado algún tiempo con una partida de aventureros que te has encontrado. Con ellos viajaba una mujer con poderes adivinatorios. Se ha ofrecido a leer tu futuro y has aceptado.\n\nTe sentaste frente a ella y empezó a escudriñar su bola de cristal. Antes de que pudiera decir nada su expresión se inundó de terror. Profirió un grito desgarrador y la bola estalló en pedazos. Tras un momento de confusión y sin perderte de vista del todo fue a buscar al resto del grupo y emprendieron la marcha inmediatamente.\n">>
<<case 5>>
<<set $log += "\nEl dolor de cabeza más intenso que nunca has sentido te obliga a detenerte. Cuando termina te parece haber perdido la noción de tu propio ser. ¿Quién eres realmente? ¿De dónde has venido?\n">>
<<case 6>>
<<set $log += "\nEn un momento de especial confusión recapitulas lo que sabes del reino de Panthor. Según tu conocimiento, algún tipo de cataclismo en tiempos antiguos liberó las energías mágicas que dan poder a los conjuros. Esta energía también provocó la aparición de mutaciones monstruosas.\n">>
<<case 7>>
<<set $log += "\nHas vuelto a sufrir otro ataque. Intentas hacer memoria pero en tu mente hay un gran vacío. Tu única seguridad es esta misión, el destructivo camino hacia ninguna parte que has emprendido.\n">>
<<case 8>>
<<set $log += "\nLos ataques se hacen más frecuentes y en cada uno de ellos percibes que el Señor de la Muerte está cada vez más cerca. El momento de la verdad se aproxima.\n">>
<<case 9>>
<<set $log += "\nEn este punto ya ni siquiera puedes descartar que todo este mundo sea solamente una proyección de tu propia mente. ¿Es el Señor de la Muerte hacia el que te diriges una creación tuya?\n">>
<<case 10>>
<<set $log += "\nDelante de ti se materializa una forma gigantesca. Se trata del Señor de la Muerte. Necesitarías hacer muchas preguntas, pero es el momento de combatir.\n">>
<<set $state.encounter to {
"type": "Señor de la Muerte",
"hp": 100,
"level": 20,
"at_bonus": 20,
"df_bonus": 20,
"boss": true} >>
<</switch>>
<<run $state.scenes.push(_scene)>>
<</if>><<set $state.debug to not $state.debug>>
<<set $log += "[Debug "+$state.debug +"]\n">>
<<run window.console.log($state)>>
<<goto "Input">>
<<if $state.confirm eq null>>
<<set $state.prompt = "ACT_RESTART">>
<<set $log = $log + "¿Seguro que quieres reiniciar el juego? (S/N)\n">>
<<goto "Input">>
<<else>>
<<if $state.confirm is "s" >>
<<goto "Launch parser">>
<<else>>
<<set $state.confirm = null>>
<<set $state.prompt = null>>
<<goto "Input">>
<</if>>
<</if>><<set $log += "\nLa gigantesca forma del Señor de la Muerte se derrumba y se deshace en polvo, hundiéndose en el terreno. La tierra tiembla durante unos momentos, y un velo parece retirarse de tus ojos. El cielo y el paisaje parecen recuperar la vida.\n\nPero, ¿es real lo que está pasando? ¿Quién eres tú realmente? ¿Cuál es el significado último de todo? No crees que puedas saberlo nunca.\n\n <b>*** Fin ***</b>\n\n">>
<<include "Achieved">>
<<set $achieved[1] to true>>
<<goto ACT_GAMEOVER>><<if not $ratings>>\
<<set $ratings to [null, null, null, null]>>\
<</if>>\
<<if not $ratings[$work]>>
<<linkappend "Deja tu opinión sobre esta obra">>:
<<include "Achieved">>\
<<if $achieved[$work]>>\
<<include "Form">>\
<<else>>\
<<if $metadata[$work].notAchieved>>\
$metadata[$work].notAchieved
<<else>>\
//Deberías completar la obra para poder votarla.//
<</if>>\
<</if>>\
<</linkappend>>
<<else>>\
<p>\
<<switch $ratings[$work].rating>>\
<<case 1>>★☆☆☆☆\
<<case 2>>★★☆☆☆\
<<case 3>>★★★☆☆\
<<case 4>>★★★★☆\
<<case 5>>★★★★★\
<</switch>>\
<b>$ratings[$work].title</b>
$ratings[$work].text (Tú)
<<link "Borrar comentario" "Game Cover">>\
<<set $ratings[$work] to null>>
<</link>>\
</p>\
<</if>>\
<<timed 500ms>>E\
<<next>>l \
<<next>>D\
<<next>>e\
<<next>>s\
<<next>>c\
<<next>>e\
<<next>>n\
<<next>>s\
<<next>>o
<<next>>
(c) Robert Retro
<<next>>
<img @src="$images.ganymede_retro"/>
<<next 5s>><<goto "Launch retro">>
<</timed>><<if $ratings.includes(null)>>
<<goto "Game Cover">>
<<else>>
<<goto "Ending">>
<</if>><<timed 3s>>!MetaComp
<<next>>Una ficción interactiva.
<<next>>Copyright © 2019 n-n
<<next>>
<<include README>>
<<next>><<include Trivia>>
<<next>>
<<link "Reiniciar">>
<<script>>
Save.clear();
UI.restart();
<</script>>\
<</link>>\
<</timed>><<include "Achieved">>\
<div class="snake-container">\
[[Salir->Game Cover][$achieved[3] to true]]
<div class="canvas-container">\
<canvas id="game-canvas" width="320" height="200"></canvas>
</div>
<div class="button-container">
<button class="ctrl" id="ctrlUp"> ↑ </button> \
<button class="ctrl" id="ctrlDown"> ↓ </button> \
<button class="ctrl" id="ctrlLeft"> ← </button> \
<button class="ctrl" id="ctrlRight"> → </button>
</div>
</div>
<<script>>
var SCREEN_X = 320;
var SCREEN_Y = 200;
var GRID_STEP = 10;
var GRID_X = 32;
var GRID_Y = 20;
var LEFT = 1;
var UP = 2;
var RIGHT = 4
var DOWN = 8;
var gridpositions = [];
var foodposition_x = -1;
var foodposition_y = -1;
var direction = 0;
var ingame = false;
function init() {
var head = [Math.floor(GRID_X / 2), Math.floor(GRID_Y / 2)]
gridpositions = [
[head[0] - 1, head[1]], head
];
direction = RIGHT;
foodposition_x = head[0];
foodposition_y = head[1];
putFood();
ingame = true;
}
// true if crash with own tail (2x snake)
function move() {
var head = gridpositions[gridpositions.length - 1];
var newhead = [head[0], head[1]];
switch (direction) {
case LEFT:
newhead[0] = (head[0] + GRID_X - 1) % GRID_X;
break;
case UP:
newhead[1] = (head[1] + GRID_Y - 1) % GRID_Y;
break;
case RIGHT:
newhead[0] = (head[0] + GRID_X + 1) % GRID_X;
break;
case DOWN:
newhead[1] = (head[1] + GRID_Y + 1) % GRID_Y;
break;
}
gridpositions.push(newhead);
if (!(foodposition_x == newhead[0] && foodposition_y == newhead[1])) {
var tail = gridpositions.shift();
// 2x snake crashes with own tail?
if (tail[0] == newhead[0] && tail[1] == newhead[1]) {
return true;
}
}
return false;
}
function putFood() {
var head = gridpositions[gridpositions.length - 1];
if (foodposition_x == head[0] &&
foodposition_y == head[1]) {
foodposition_x = Math.floor(Math.random() * (GRID_X));
foodposition_y = Math.floor(Math.random() * (GRID_Y));
}
}
function draw() {
var canvas = document.getElementById("game-canvas");
if (!canvas) { return; }
var ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect(0, 0, SCREEN_X, SCREEN_Y);
ctx.fillStyle = "white";
for (var i = 0; i < gridpositions.length; i++) {
ctx.fillRect(gridpositions[i][0] * GRID_STEP, gridpositions[i][1] * GRID_STEP,
GRID_STEP, GRID_STEP);
}
ctx.fillStyle = "yellow";
ctx.fillRect(foodposition_x * GRID_STEP, foodposition_y * GRID_STEP,
GRID_STEP, GRID_STEP);
}
function drawGameOver() {
var canvas = document.getElementById("game-canvas");
if (!canvas) { return; }
var ctx = canvas.getContext("2d");
ctx.fillStyle = "white";
ctx.fillRect(0, 0, SCREEN_X, SCREEN_Y);
ctx.fillStyle = "black";
for (var i = 0; i < gridpositions.length; i++) {
if (i < gridpositions.length - 1) {
ctx.fillStyle = "red";
}
ctx.fillRect(gridpositions[i][0] * GRID_STEP, gridpositions[i][1] * GRID_STEP,
GRID_STEP, GRID_STEP);
}
}
function isGameOver() {
var head = gridpositions[gridpositions.length - 1];
for (var i = 0; i < gridpositions.length - 1; i++) {
if (head[0] == gridpositions[i][0] && head[1] == gridpositions[i][1]) {
return true;
}
}
}
function gameStep() {
if (!document.getElementById("game-canvas")){ return; }
var gameOver = move();
putFood();
draw();
if (!gameOver && !isGameOver()) {
setTimeout(
function() {
window.requestAnimationFrame(gameStep);
}, 125);
} else {
ingame = false;
drawGameOver();
}
}
function command(e) {
if (!ingame) {
start();
return;
}
switch (e.keyCode) {
case 37:
direction = LEFT;
break;
case 38:
direction = UP;
break;
case 39:
direction = RIGHT;
break;
case 40:
direction = DOWN;
break;
}
}
function clicked(dir){
if (!ingame) {
start();
return;
}
direction = dir;
}
function start() {
init();
window.requestAnimationFrame(gameStep);
}
function setup(){
$(document).off('keydown', command);
$(document).on('keydown', command);
$('.ctrl').unbind('click');
$('#ctrlUp').click(function(){ clicked(UP); });
$('#ctrlDown').click(function(){ clicked(DOWN); });
$('#ctrlLeft').click(function(){ clicked(LEFT); });
$('#ctrlRight').click(function(){ clicked(RIGHT); });
}
window.setTimeout(function(){setup(); start();},100);
<</script>>
<<set _graphs to $images>>\
<<if $retro_state.on>>\
<<set _thrust to 'on'>>\
<<else>>\
<<set _thrust to 'off'>>\
<</if>>\
<<if $retro_state.ht > 5000>>\
<<set _position to 'high'>>\
<<else>>\
<<set _position to 'low'>>\
<</if>>
<<if not $retro_state.caida and not $retro_state.ht>>\
[img[Cápsula atracada en estación|_graphs.docked]]\
<<else>>\
[img[En caída|_graphs[ _position + '_' + _thrust ]]]\
<</if>>\
Versión: 0.1.20190805152657
Licencia: CC BY-SA 4.0
Contacto: no2nsense@gmail.com
Imágenes: "Blood Splatter Vector" by transparentpng.com (CC BY 4.0), ElisaRiva (Pixabay), NASA/JPL, kisscc0
Pruebas: Comely, RuberEaglenest<<linkappend "Curiosidades">>
<<linkappend '- ¿De dónde sale todo esto?'>>
Este experimento empezó como una prueba de control por entrada de texto de historias SugarCube. Conseguí una réplica aceptable de un interfaz de párser para SC 1 y pensé que el siguiente paso sería integrar una fase controlada por línea de comandos dentro de una historia de hipertexto.
El proyecto se quedó parado a falta de una historia. Hasta que la Rayuela Jam 2019, dedicada al Realismo Mágico, me sugirió una idea un tanto borgiana: un concurso de aventuras simulado, una historia con otras historias dentro (a lo //Inception//). Desafortunadamente no llegué a tiempo para presentarla a la Jam, y el resultado tampoco ha sido exactamente lo que había planeado.
Tenía la intención de que cada juego fuese una forma arquetípica de Ficción Interactiva y que a la vez estuviesen relacionados entre sí, con una trama común atravesando todos ellos. No conseguí materializar esa idea con éxito y el resultado ha sido esta recopilación de juegos independientes y muy esquemáticos.
Cuando estaba bastante avanzado el desarrollo se me ocurrió buscar inspiración adicional en un texto que para mí fue formativo, <a href="https://sites.google.com/view/manuelalfonseca/home/libros#h.p_rliodr-p9J-8" target="_blank">"Cómo Construir Juegos de Aventura"</a> (Manuel Alfonseca, 1986). Al ojearlo encontré que dos de las entradas son muy parecidas a ejemplos que se desarrollan en el libro. Tengo por tanto que acreditar este libro como influencia, aunque haya sido inconsciente.
<</linkappend>>
<<linkappend '- Sobre "El Descenso"'>>
Tenía que ser una aventura pequeña pero detallada, exigente en la planificación de los turnos y con aspecto retro. El estilo pretende imitar las aventuras de ZX Spectrum, con una tipografía tomada de dicho ordenador. Los gráficos de localidad, no obstante, tienen una paleta más amplia y no respetan las restricciones de atributos de color del Speccy.
Decidí que la temática sería la ciencia-ficción. En concreto el subgénero de desastres en el espacio, que tiene una gran tradición aventurera con representantes como Planetfall o Goteras.
<<linkappend '¿Cómo funciona la simulación?'>>
El núcleo de la historia es un tipo de juego de "aterrizaje lunar" que se remonta a antes del Apolo XI. En este caso me basé en <a href="https://www.spaceacademy.net.au/flight/sim/lunasim.htm" target="_blank">un ejemplo QBASIC relativamente moderno</a>. El control de propulsión del original permitía ir asignando valores entre 0 y 255, y en esta adaptación he preferido simplificarlo a un estado binario, on-off.
<</linkappend>>\
<</linkappend>>
<<linkappend '- Sobre "Panthor"'>>
Es el descendiente directo de la primera prueba de concepto de interfaz de línea de comandos para Twine/SugarCube que hice.
Se me ocurrió homenajear a Panthem, una obra que se anunció en los foros del CAAD creando gran expectación, y que nunca se llegó a lanzar. Creo que dicho juego habría terminado sido extenso pero superficial, y eso es lo que he intentado replicar. Las diferencias con el modelo son probablemente muchas. El corazón de Panthor es un sistema de combate inspirado por Dungeons&Dragons, con fórmulas de progresión de niveles y objetos muy sencillas.
<</linkappend>>
<<linkappend '- Sobre "Estado de la Cuestión"'>>
Aunque la idea original era explorar ideas de control diferentes a lo que se suele hacer con Twine también quería que la cultura que hay alrededor de la herramienta estuviese representada.
Pensé en una obra reflexiva que pusiese al jugador frente a diferentes actitudes y dinámicas que se vienen dando en el fandom, especialmente desde 2014. Si hay algún mensaje aquí (<<linkappend "pista">>: lo hay<</linkappend>>) es a favor de la diversidad y la inclusión.
Como el resto de entradas imaginarias, esta también ha visto su alcance drásticamente reducido. Se me ocurrió intentar algo parecido al Mind Mirror de Timothy Leary, en el que el jugador analiza su propia personalidad y después se somete a pruebas mediante escenas interactivas de juego de rol. Se ha quedado como un cuestionario dinámico en el que cada respuesta puede modificar el resultado a lo largo de varias escalas (cuatro, concretamente).
<</linkappend>>
<<linkappend '- Sobre "Ouroboros"'>>
La cantidad de tres entradas resulta escasa para una competición de IF que se precie, aunque sea ficticia. Para completar pensé en añadir un representante, digamos, off-topic.
Tenía este minijuego arcade ya hecho y se me ocurrió reciclarlo y, de paso, probar a integrar rutinas JavaScript dentro de un pasaje Twine. Que esto haya funcionado abre la puerta a cosas más elaboradas: mapas, diagramas interactivos, una simulación de conducción para desplazarse por las localidades de una historia o un shooter 3D hecho con WebGL, ¿por qué no?.
<</linkappend>>\
<</linkappend>>\<<set $retro_log += "Has tenido que escapar a toda prisa de la estacion. Solo tienes una vieja foto (que llevabas siempre contigo) y las notas de tus experimentos.\n">>
<<include "Retro Timer">>
<<goto "Retro Input">><<set $retro_log += "En el reducido habitaculo de la capsula no puedes coger ni dejar nada.\n">>
<<include "Retro Timer">>
<<goto "Retro Input">><<set $log += "El juego se controla tecleando órdenes simples y finalizándolas con la tecla ENTER. Pulsando ENTER sin escribir nada repetirás la última orden.\n\nAlgunos comandos básicos son:\n\nNORTE, SUR, ESTE y OESTE para moverte (puedes abreviar con N, S, E, O).\nATACAR (no es necesario especificar a quién)\nEXAMINAR objeto (puedes abreviar con 'X objeto')\nSTATUS (muestra el estado de tu personaje)\nESPERAR (puedes abreviar con Z)\nINVENTARIO (puedes abreviar con I)\n\nLas acciones sobre objetos del inventario se especifican con su número:\n\nDEJAR número de objeto (descartarlo inmediatamente)\nEQUIPAR número de objeto\nUSAR número de objeto\n\nSALVAR (guarda la partida para recuperarla después)\nRECUPERAR (continúa una partida salvada)\nSALIR (abandona el juego)\n\n" >>
<<goto Input>> <<set _draft to {}>>
Puntuación: <<listbox "_draft.rating">>
<<option "★★★★★" 5>>
<<option "★★★★☆" 4>>
<<option "★★★☆☆" 3>>
<<option "★★☆☆☆" 2>>
<<option "★☆☆☆☆" 1>>
<</listbox>>
Título del comentario: <<textbox "_draft.title" "">>
Texto del comentario:
<<textarea "_draft.text" "">>
<<button Aceptar "Vote">><<set $ratings[$work] to _draft>><</button>><<if not $achieved>>\
<<set $achieved to [false, false, false, false]>>\
<</if>>\<<set $work to random(2)>>
<<include "metadata">>
<<goto $metadata[$work].passage>><<set _evil to $quiz_state.attr[3]<-10>>\
<<if not _evil>>\
<div style="width:420px;height:420px;position:absolute;bottom:0%;left:40%;overflow:hidden">\
<img style="margin-left:-220px;margin-top:-220px;opacity:0.2" @src="$images.stain_c">\
</div>\
<<else>>\
<<timed 2s>>\
<img style="opacity:0.8;position:absolute;bottom:-30%;left:35%" @src="$images.stain_b">
<</timed>>
<</if>>\
<<if window.isProduction()>>\
<<set $images to {
ganymede_retro: 'images/Ganymede_g1_true_2.zx.png',
docked: 'images/docked.png',
high_on: 'images/high-on.png',
high_off: 'images/high-off.png',
low_on: 'images/low-on.png',
low_off: 'images/low-off.png',
ganymede: 'images/ganymede.jpg',
helmet: 'images/helmet.png',
anova: 'images/anova.png',
ouroboros: 'images/ouroboros.png',
stain_c: 'images/stain-1831699_640.png',
stain_b: 'images/blood-splatter-png-14061.png'
}>>
<<else>>\
<<set $images to {
ganymede_retro: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2FGanymede_g1_true_2.zx.png?1556738939325',
docked: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fdocked.png?1556746809494',
high_on: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fhigh-on.png?1556747081966',
high_off: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fhigh-off.png?1556747082071',
low_on: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Flow-on.png?1556747082136',
low_off: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Flow-off.png?1556747082201',
ganymede: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fganymede.jpg?1557081078725',
helmet: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fhelmet.png?1557081078009',
anova: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fanova.png?1557081078285',
ouroboros: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fouroboros.png?1557081078093',
stain_c: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fstain-1831699_640.png',
stain_b: 'https://cdn.glitch.com/2e2d790c-5aeb-4305-9a77-28fb1758196f%2Fblood-splatter-png-14061.png'
}>>
<</if>>\