/* * Verrückte Turing-Maschinen — A turing complete game * Copyright (C) 2016 Christian Fraß * * 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_round { /** * @author kcf */ export type type_round = { 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_round { let round : type_round = { "world": undefined, "token": undefined, "task": task, "testindex": undefined, "mode": undefined, "listeners": undefined, } ; round.listeners = { "aendrung_task": [], "aendrung_world": [], "aendrung_token": [], "aendrung_mode": [], } ; world_clear(round, false); reset(round, false); return round; } /** * @author kcf */ export function lauschen ( round : type_round, event : string, procedure : (data ?: any)=>void ) : void { if (event in round.listeners) { round.listeners[event].push(procedure); } else { let message : string = "kein Ereignis mit diesem Name"; throw (new Error(message)); } } /** * @author kcf */ function notify ( round : type_round, event : string, data : any = {} ) : void { if (event in round.listeners) { round.listeners[event].forEach ( procedure => { procedure(data); } ) ; } else { let message : string = "kein Ereignis mit diesem Name"; throw (new Error(message)); } } /** * @author kcf */ export function reset ( round : type_round, inform : boolean = true ) : void { round.token = (lib_errormonade.create_nothing()); round.testindex = (lib_errormonade.create_nothing()); round.mode = mod_mode.initial; if (inform) { notify(round, "aendrung_token", {}); notify(round, "aendrung_mode", {}); } else { // nothing tun } } /** * @author kcf */ export function task_read ( round : type_round ) : mod_task.type_task { return round.task; } /** * @author kcf */ export function task_set ( round : type_round, task : mod_task.type_task ) : void { round.task = task; // round.world_clear(); notify(round, "aendrung_task", {}); reset(round); } /** * @author kcf */ export function world_read ( round : type_round ) : mod_world.type_world { return round.world; } /** * @author kcf */ export function world_set ( round : type_round, world : mod_world.type_world, inform : boolean = true ) : void { round.world = world; if (inform) { notify(round, "aendrung_world", {}); } else { // nothing tun } } /** * @author kcf */ export function world_clear ( round : type_round, inform : boolean = true ) : void { round.world = mod_world.blanko(); if (inform) { notify(round, "aendrung_world", {}); } else { // nothing tun } } /** * @author kcf */ export function token_read ( round : type_round ) : lib_errormonade.type_errormonade { return round.token; } /** * @author kcf */ export function mode_read ( round : type_round ) : mod_mode.type_mode { return round.mode; } /** * @author kcf */ export function world_tile_wechseln ( round : type_round, spot : mod_spot.type_spot, umgekehrt : boolean = false ) : void { if (! (round.mode === mod_mode.initial)) { let message : string = "gesperrt"; } else { mod_world.tile_wechseln(round.world, spot, umgekehrt); notify ( round, "aendrung_world", { "kind": "tile_wechseln", "data": { "spot": spot, "umgekehrt": umgekehrt, "tile": mod_world.tile_get(round.world, spot), } } ) ; } } /** * @author kcf */ export function world_tile_rotate ( round : type_round, spot : mod_spot.type_spot, inkrement : int = +1 ) : void { if (! (round.mode === mod_mode.initial)) { let message : string = "gesperrt"; } else { mod_world.tile_rotate(round.world, spot, inkrement); notify(round, "aendrung_world", {}); } } /** * @author kcf */ export function resume ( round : type_round ) : void { switch (round.mode) { case mod_mode.initial: { round.mode = mod_mode.uncertain; round.testindex = (lib_errormonade.create_just(0)); notify(round, "aendrung_mode", {}); break; } case mod_mode.uncertain: { if (! lib_errormonade.filled(round.token)) { let test : mod_test.type_test = mod_task.tests(round.task)[lib_errormonade.read(round.testindex)]; let tape : Array = mod_vtm.mod_helfer.list_copy(mod_test.input(test)); let spot : mod_spot.type_spot = mod_world.erzeuger_finden(round.world); round.token = ( lib_errormonade.create_just ( mod_token.create ( tape, spot ) ) ); } else { let token : mod_token.type_token = lib_errormonade.read(round.token); let spot : mod_spot.type_spot = mod_token.spot_read(token); let actuator_ : lib_errormonade.type_errormonade = mod_world.tile_get(round.world, spot); let actuator : mod_actuator.type_actuator = ( lib_errormonade.filled(actuator_) ? lib_errormonade.read(actuator_) : mod_actuator.mod_verwerfer.create_actuator() ); mod_actuator.use(actuator, token); let 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)) { let accepted : boolean = (state === mod_state.accepted); let ausgabe : Array = mod_token.tape_read(token); round.token = (lib_errormonade.create_nothing()); let testindex : int = lib_errormonade.read(round.testindex); let tests : Array = mod_task.tests(round.task); let test : mod_test.type_test = tests[testindex]; if (! mod_test.pruefen(test, accepted, ausgabe)) { round.mode = mod_mode.wrong; notify(round, "aendrung_mode", {}); } else { testindex += 1; if (testindex < tests.length) { // nächsten Test auswählen round.testindex = (lib_errormonade.create_just(testindex)); } else { // auf Modus "correct" wechseln round.testindex = (lib_errormonade.create_nothing()); round.mode = mod_mode.correct; notify(round, "aendrung_mode", {}); } } } else { let message : string = "unbehandelter Zustand"; throw (new Error(message)); } } notify(round, "aendrung_token", {}); break; } case mod_mode.wrong: { // nothing tun break; } case mod_mode.correct: { // nothing tun break; } default: { let message : string = "unbehandelter Modus"; throw (new Error(message)); break; } } } } } }