/* * Verrückte Turing-Maschinen — A turing complete game * Copyright (C) 2016-2018 kcf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ module mod_vtm { export module mod_model { export module mod_game { /** * @author kcf */ export type type_game = { world : mod_world.type_world; token : lib_errormonade.type_errormonade; task : mod_task.type_task; testindex : lib_errormonade.type_errormonade; mode : mod_mode.type_mode; listeners : {[event : string] : Array<(data ?: any)=>void>}; } ; /** * @author kcf */ export function create ( task : mod_task.type_task ) : type_game { let game : type_game = { "world": undefined, "token": undefined, "task": task, "testindex": undefined, "mode": undefined, "listeners": { "change_task": [], "change_world": [], "change_token": [], "change_mode": [], } , } ; world_clear(game, false); reset(game, false); return game; } /** * @author kcf */ export function listen ( game : type_game, event : string, procedure : (data ?: any)=>void ) : void { if (event in game.listeners) { game.listeners[event].push(procedure); } else { const message : string = "kein Ereignis mit diesem Name"; throw (new Error(message)); } } /** * @author kcf */ function notify ( game : type_game, event : string, data : any = {} ) : void { if (game.listeners.hasOwnProperty(event)) { game.listeners[event] .forEach ( (procedure) => { procedure(data); } ) ; } else { const message : string = "kein Ereignis mit diesem Name"; throw (new Error(message)); } } /** * @author kcf */ export function reset ( game : type_game, inform : boolean = true ) : void { game.token = (lib_errormonade.create_nothing()); game.testindex = (lib_errormonade.create_nothing()); game.mode = mod_mode.initial; if (inform) { notify(game, "change_token", {}); notify(game, "change_mode", {}); } else { // nothing tun } } /** * @author kcf */ export function task_read ( game : type_game ) : mod_task.type_task { return game.task; } /** * @author kcf */ export function task_set ( game : type_game, task : mod_task.type_task ) : void { game.task = task; // game.world_clear(); notify(game, "change_task", {}); reset(game); } /** * @author kcf */ export function world_read ( game : type_game ) : mod_world.type_world { return game.world; } /** * @author kcf */ export function world_set ( game : type_game, world : mod_world.type_world, inform : boolean = true ) : void { game.world = world; if (inform) { notify(game, "change_world", {}); } else { // nothing tun } } /** * @author kcf */ export function world_clear ( game : type_game, inform : boolean = true ) : void { game.world = mod_world.blanko(); if (inform) { notify(game, "change_world", {}); } else { // nothing tun } } /** * @author kcf */ export function token_read ( game : type_game ) : lib_errormonade.type_errormonade { return game.token; } /** * @author kcf */ export function mode_read ( game : type_game ) : mod_mode.type_mode { return game.mode; } /** * @author kcf */ export function world_tile_change ( game : type_game, spot : mod_spot.type_spot, inverted : boolean = false ) : void { if (! (game.mode === mod_mode.initial)) { const message : string = "gesperrt"; } else { mod_world.tile_change(game.world, spot, inverted); notify ( game, "change_world", { "kind": "tile_change", "data": { "spot": spot, "inverted": inverted, "tile": mod_world.tile_get(game.world, spot), } } ) ; } } /** * @author kcf */ export function world_tile_rotate ( game : type_game, spot : mod_spot.type_spot, increment : int = +1 ) : void { if (! (game.mode === mod_mode.initial)) { const message : string = "gesperrt"; } else { mod_world.tile_rotate(game.world, spot, increment); notify(game, "change_world", {}); } } /** * @author kcf */ export function resume ( game : type_game ) : void { switch (game.mode) { case mod_mode.initial: { game.mode = mod_mode.uncertain; game.testindex = (lib_errormonade.create_just(0)); notify(game, "change_mode", {}); break; } case mod_mode.uncertain: { if (! lib_errormonade.filled(game.token)) { const test : mod_test.type_test = mod_task.tests(game.task)[lib_errormonade.read(game.testindex)]; const tape : Array = lib_list.copy(mod_test.input(test)); const spot : mod_spot.type_spot = mod_world.generator_finden(game.world); game.token = ( lib_errormonade.create_just ( mod_token.create ( tape, spot ) ) ); } else { const token : mod_token.type_token = lib_errormonade.read(game.token); const spot : mod_spot.type_spot = mod_token.spot_read(token); const actuator_ : lib_errormonade.type_errormonade = mod_world.tile_get(game.world, spot); const actuator : mod_actuator.type_actuator = ( lib_errormonade.filled(actuator_) ? lib_errormonade.read(actuator_) : mod_actuator.mod_rejector.create_extended() ); mod_actuator.use(actuator, token); const state : mod_state.type_state = mod_token.state_read(token); if (state === mod_state.running) { // nothing tun } else if ((state === mod_state.accepted) || (state === mod_state.rejected)) { const accepted : boolean = (state === mod_state.accepted); const output : Array = mod_token.tape_read(token); game.token = (lib_errormonade.create_nothing()); let testindex : int = lib_errormonade.read(game.testindex); const tests : Array = mod_task.tests(game.task); const test : mod_test.type_test = tests[testindex]; if (! mod_test.pruefen(test, accepted, output)) { game.mode = mod_mode.wrong; notify(game, "change_mode", {}); } else { testindex += 1; if (testindex < tests.length) { // nächsten Test auswählen game.testindex = (lib_errormonade.create_just(testindex)); } else { // auf Modus "correct" change game.testindex = (lib_errormonade.create_nothing()); game.mode = mod_mode.correct; notify(game, "change_mode", {}); } } } else { const message : string = "unbehandelter Zustand"; throw (new Error(message)); } } notify(game, "change_token", {}); break; } case mod_mode.wrong: { // do nothing break; } case mod_mode.correct: { // do nothing break; } default: { const message : string = "unbehandelter Modus"; throw (new Error(message)); break; } } } } } }