| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-12-26 17:13:33 +0100 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-12-26 17:13:33 +0100 |
| commit | 9c46df53ad401e060664aafe8fdfbcb9a3da5731 (patch) | |
| tree | cbe3e412bc04e322ddab5ca52bdb776c63b3fdc2 | |
Initial commit.
| -rw-r--r-- | Makefile | 36 | ||||
| -rw-r--r-- | elm.json | 27 | ||||
| -rw-r--r-- | src/ElmModule/Init.elm | 18 | ||||
| -rw-r--r-- | src/ElmModule/Subscriptions.elm | 15 | ||||
| -rw-r--r-- | src/ElmModule/Update.elm | 23 | ||||
| -rw-r--r-- | src/ElmModule/View.elm | 26 | ||||
| -rw-r--r-- | src/Main.elm | 25 | ||||
| -rw-r--r-- | src/Struct/Event.elm | 19 | ||||
| -rw-r--r-- | src/Struct/Flags.elm | 43 | ||||
| -rw-r--r-- | src/Struct/Model.elm | 29 | ||||
| -rw-r--r-- | src/Struct/UI.elm | 24 | ||||
| -rw-r--r-- | src/Tonkadur/Compute.elm | 377 | ||||
| -rw-r--r-- | src/Tonkadur/Execute.elm | 301 | ||||
| -rw-r--r-- | src/Tonkadur/PlayerInput.elm | 85 | ||||
| -rw-r--r-- | src/Tonkadur/Types.elm | 268 |
15 files changed, 1316 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4fabb97 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +################################################################################ +## CONFIG ###################################################################### +################################################################################ +SRC_DIR ?= src +WWW_DIR ?= www +WWW_SCRIPT_DIR ?= $(WWW_DIR)/script + +ELM_CC ?= elm make + +MAIN_MODULE ?= $(SRC_DIR)/Main.elm + +################################################################################ +## MAKEFILE MAGIC ############################################################## +################################################################################ +SUB_MODULES = $(shell find $(SRC_DIR) -type f | grep "elm$$") + +################################################################################ +## SANITY CHECKS ############################################################### +################################################################################ + +################################################################################ +## TARGET RULES ################################################################ +################################################################################ +build: $(WWW_SCRIPT_DIR)/main.js + +clean: + rm -f $(WWW_SCRIPT_DIR)/main.js + +reset: + rm -rf elm-stuff + +################################################################################ +## INTERNAL RULES ############################################################## +################################################################################ +$(WWW_SCRIPT_DIR)/main.js: $(MAIN_MODULE) $(SUB_MODULES) + $(ELM_CC) $(MAIN_MODULE) --output $@ diff --git a/elm.json b/elm.json new file mode 100644 index 0000000..923a948 --- /dev/null +++ b/elm.json @@ -0,0 +1,27 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.1", + "elm/core": "1.0.2", + "elm/html": "1.0.0", + "elm/http": "2.0.0", + "elm/json": "1.1.2", + "elm/time": "1.0.0", + "elm/url": "1.0.0" + }, + "indirect": { + "elm/bytes": "1.0.7", + "elm/file": "1.0.1", + "elm/virtual-dom": "1.0.2" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} diff --git a/src/ElmModule/Init.elm b/src/ElmModule/Init.elm new file mode 100644 index 0000000..9af3cce --- /dev/null +++ b/src/ElmModule/Init.elm @@ -0,0 +1,18 @@ +module ElmModule.Init exposing (init) + +-- Local Module ---------------------------------------------------------------- +import Struct.Flags +import Struct.Event +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +init : Struct.Flags.Type -> (Struct.Model.Type, (Cmd Struct.Event.Type)) +init flags = + -- TODO: read flags and request story. + (model, Cmd.none) diff --git a/src/ElmModule/Subscriptions.elm b/src/ElmModule/Subscriptions.elm new file mode 100644 index 0000000..c2b9fbe --- /dev/null +++ b/src/ElmModule/Subscriptions.elm @@ -0,0 +1,15 @@ +module ElmModule.Subscriptions exposing (..) + +-- Local Module ---------------------------------------------------------------- +import Struct.Model +import Struct.Event + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +subscriptions : Struct.Model.Type -> (Sub Struct.Event.Type) +subscriptions model = Sub.none diff --git a/src/ElmModule/Update.elm b/src/ElmModule/Update.elm new file mode 100644 index 0000000..a4b827a --- /dev/null +++ b/src/ElmModule/Update.elm @@ -0,0 +1,23 @@ +module ElmModule.Update exposing (update) + +-- Elm ------------------------------------------------------------------------- + +-- Local Module ---------------------------------------------------------------- +import Struct.Event +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +update : ( + Struct.Event.Type -> + Struct.Model.Type -> + (Struct.Model.Type, (Cmd Struct.Event.Type)) + ) +update event model = + case event of + Struct.Event.None -> (model, Cmd.none) diff --git a/src/ElmModule/View.elm b/src/ElmModule/View.elm new file mode 100644 index 0000000..fb99b89 --- /dev/null +++ b/src/ElmModule/View.elm @@ -0,0 +1,26 @@ +module ElmModule.View exposing (view) + +-- Elm ------------------------------------------------------------------------- +import Html +import Html.Attributes + +-- Local Module ---------------------------------------------------------------- +import Struct.Event +import Struct.Model + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +view : Struct.Model.Type -> (Html.Html Struct.Event.Type) +view model = + (Html.div + [ + (Html.Attributes.class "fullscreen-module") + ] + [ + ] + ) diff --git a/src/Main.elm b/src/Main.elm new file mode 100644 index 0000000..0f8f61a --- /dev/null +++ b/src/Main.elm @@ -0,0 +1,25 @@ +module Main exposing (main) + +-- Elm ------------------------------------------------------------------------ +import Browser + +-- Local Module ---------------------------------------------------------------- +import ElmModule.Init +import ElmModule.Subscriptions +import ElmModule.View +import ElmModule.Update + +import Struct.Flags +import Struct.Model +import Struct.Event + +main : (Program Shared.Struct.Flags.Type Struct.Model.Type Struct.Event.Type) +main = + (Browser.element + { + init = ElmModule.Init.init, + view = ElmModule.View.view, + update = ElmModule.Update.update, + subscriptions = ElmModule.Subscriptions.subscriptions + } + ) diff --git a/src/Struct/Event.elm b/src/Struct/Event.elm new file mode 100644 index 0000000..78079d2 --- /dev/null +++ b/src/Struct/Event.elm @@ -0,0 +1,19 @@ +module Struct.Event exposing (..) + +-- Elm ------------------------------------------------------------------------- + +-- Local Module ---------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type Type = + EventType0 + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- diff --git a/src/Struct/Flags.elm b/src/Struct/Flags.elm new file mode 100644 index 0000000..43fc7c2 --- /dev/null +++ b/src/Struct/Flags.elm @@ -0,0 +1,43 @@ +module Struct.Flags exposing + ( + Type, + force_get_parameter, + get_parameters_as_url + ) + +-- Elm ------------------------------------------------------------------------- +import List + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + url_parameters : (List (List String)) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +parameter_as_url : (List String) -> String +parameter_as_url parameter = + case parameter of + [name, value] -> (name ++ "=" ++ value) + _ -> "" + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +force_get_parameter : String -> Type -> String +force_get_parameter parameter flags = "" + -- TODO: implement using Tactician Online's, but without Shared.Util.List + +get_parameters_as_url : Type -> String +get_parameters_as_url flags = + (List.foldl + (\parameter -> \current_parameters -> + (current_parameters ++ "&" ++ (parameter_as_url parameter)) + ) + "" + flags.url_parameters + ) diff --git a/src/Struct/Model.elm b/src/Struct/Model.elm new file mode 100644 index 0000000..a11db5c --- /dev/null +++ b/src/Struct/Model.elm @@ -0,0 +1,29 @@ +module Struct.Model exposing + ( + Type + ) + +-- Elm ------------------------------------------------------------------------- + +-- Tonkadur -------------------------------------------------------------------- +import Tonkadur.Types + +-- Local Module ---------------------------------------------------------------- +import Struct.UI + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + tonkadur : Tonkadur.Types.State, + ui : Struct.UI.Type + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- diff --git a/src/Struct/UI.elm b/src/Struct/UI.elm new file mode 100644 index 0000000..53348f6 --- /dev/null +++ b/src/Struct/UI.elm @@ -0,0 +1,24 @@ +module Struct.UI exposing + ( + Type + ) + +-- Elm ------------------------------------------------------------------------- +import List +import String + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias Type = + { + displayed_options : (List String) + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- diff --git a/src/Tonkadur/Compute.elm b/src/Tonkadur/Compute.elm new file mode 100644 index 0000000..489ab3b --- /dev/null +++ b/src/Tonkadur/Compute.elm @@ -0,0 +1,377 @@ +module Tonkadur.Compute exposing (compute) + +-- Elm ------------------------------------------------------------------------- +import Dict +import List + +-- Tonkadur -------------------------------------------------------------------- +import Tonkadur.Types + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +add_text_effect : ( + Tonkadur.Types.State -> + String -> + (List Tonkadur.Types.Computation) -> + Tonkadur.Types.Value + ) +add_text_effect state name parameters content = + (TextValue + (AugmentedText + { + content = (List.map (compute state) content), + effect_name = name, + effect_parameters = parameters + } + ) + ) + +address : ( + Tonkadur.Types.State -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +address state param = + case (compute state param) of + (PointerValue address) -> (PointerValue address) + (StringValue singleton) -> (PointerValue (List.singleton singleton)) + _ -> (PointerValue []) + +unsupported_cast : String -> String -> Tonkadur.Types.Value +unsupported_cast from to = + (StringValue ("Unsupported cast from " + from + " to " + to + ".")) + +cast : ( + Tonkadur.Types.State -> + String -> + String -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +cast state from to param = + case (compute state param) of + (BoolValue bool) -> + case to of + "string" -> + if bool + then (StringValue "true") + else (StringValue "false") + + "text" -> + if bool + then (TextValue (StringText "true")) + else (TextValue (StringText "false")) + + "bool" -> (BoolValue bool) + _ -> (unsupported_cast from to) + + (FloatValue float) -> + case to of + "string" -> (StringValue (String.fromFloat float)) + "text" -> (TextValue (StringText (String.fromFloat float))) + "int" -> (IntValue (Math.floor float)) + "float" -> (FloatValue float) + _ -> (unsupported_cast from to) + + (IntValue int) -> + case to of + "string" -> (StringValue (String.fromInt int)) + "text" -> (TextValue (StringText (String.fromInt int))) + "float" -> (FloatValue (Math.toFloat int)) + "int" -> (IntValue int) + _ -> (unsupported_cast from to) + + (TextValue text) -> + let as_string = (Tonkadur.Types.value_to_string (TextValue text)) in + case to of + "string" -> (StringValue as_string) + "float" -> + case (String.toFloat as_string) of + Nothing -> (unsupported_cast from to) + (Just result) -> (FloatValue result) + + "int" -> + case (String.toInt as_string) of + Nothing -> (unsupported_cast from to) + (Just result) -> (IntValue result) + + "text" -> (TextValue text) + _ -> (unsupported_cast from to) + + (StringValue string) -> + case to of + "string" -> (StringValue string) + "float" -> + case (String.fromFloat string) of + Nothing -> (unsupported_cast from to) + (Just result) -> (FloatValue result) + + "int" -> + case (String.toInt string) of + Nothing -> (unsupported_cast from to) + (Just result) -> (IntValue result) + + "text" -> (TextValue (StringText string)) + + _ -> (unsupported_cast from to) + + _ -> (unsupported_cast from to) + +constant : ( + Tonkadur.Types.State -> + String -> + String -> + Tonkadur.Types.Value + ) +constant state target_type as_string = + (cast state "string" target_type as_string) + +extra_computation : ( + Tonkadur.Types.State -> + String -> + (List Tonkadur.Types.Computation) -> + Tonkadur.Types.Value + ) +extra_computation state name parameters = + case name of + _ -> (StringValue ("Unsupported extra computation '" + name + "'")) + +if_else : ( + Tonkadur.Types.State -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +if_else state condition if_true if_false = + if (WyrdType.to_boolean (compute state condition)) + then (compute state if_true) + else (compute state if_false) + +last_choice_index : Tonkadur.Types.State -> Tonkadur.Types.Value +last_choice_index state = (IntValue state.last_choice_index) + +newline : Tonkadur.Types.State -> Tonkadur.Types.Value +newline state = (TextValue Newline) + +next_allocable_address : Tonkadur.Types.State -> Tonkadur.Types.Value +next_allocable_address state = (IntValue state.next_allocable_address) + +operation : ( + Tonkadur.Types.State -> + String -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +operation state name param0 param1 = + let + value0 = (compute state param0) + value1 = (compute state param1) + in + case name of + "divide" -> + case value0 of + (IntValue val) -> + (IntValue (val // (Tonkadur.Types.value_to_int value1))) + + _ -> + (FloatValue + ( + (Tonkadur.Types.value_to_float value0) + / (Tonkadur.Types.value_to_float value1) + ) + ) + + "minus" -> + case value0 of + (IntValue val) -> + (IntValue (val - (Tonkadur.Types.value_to_int value1))) + + _ -> + (FloatValue + ( + (Tonkadur.Types.value_to_float value0) + - (Tonkadur.Types.value_to_float value1) + ) + ) + + "modulo" -> + (IntValue + (modBy + (Tonkadur.Types.value_to_int value0) + (Tonkadur.Types.value_to_int value1) + ) + ) + + "plus" -> + case value0 of + (IntValue val) -> + (IntValue (val + (Tonkadur.Types.value_to_int value1))) + + _ -> + (FloatValue + ( + (Tonkadur.Types.value_to_float value0) + + (Tonkadur.Types.value_to_float value1) + ) + ) + + "power" -> + case value0 of + (IntValue val) -> + (IntValue (val ^ (Tonkadur.Types.value_to_int value1))) + + _ -> + (FloatValue + ( + (Tonkadur.Types.value_to_float value0) + ^ (Tonkadur.Types.value_to_float value1) + ) + ) + + "times" -> + case value0 of + (IntValue val) -> + (IntValue (val * (Tonkadur.Types.value_to_int value1))) + + _ -> + (FloatValue + ( + (Tonkadur.Types.value_to_float value0) + * (Tonkadur.Types.value_to_float value1) + ) + ) + + "and" -> + (BoolValue + (and + (Tonkadur.Types.value_to_bool value0) + (Tonkadur.Types.value_to_bool value1) + ) + ) + + "not" -> (BoolValue (not (Tonkadur.Types.value_to_bool value0))) + + "less_than" -> + case value0 of + (BoolValue bool) -> + (and (Tonkadur.Types.value_to_bool value1) (not boot)) + + (FloatValue float) -> + (BoolValue (float < (Tonkadur.Types.value_to_float value1))) + + (IntValue int) -> + (BoolValue (int < (Tonkadur.Types.value_to_int value1))) + + (StringValue str) -> + (BoolValue (str < (Tonkadur.Types.value_to_string value1))) + + (PointerValue ptr) -> + (BoolValue + ( + (Tonkadur.Types.compare_pointers + ptr + (Tonadur.Wyrd.value_to_dict value1) + ) + > 0 + ) + ) + + "equals" -> (value0 == value1) + +relative_address : ( + Tonkadur.Types.State -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +relative_address state base extra = + (PointerValue + (List.append + (Tonkadur.Types.value_to_list (compute state base)) + (Tonkadur.Types.value_to_list (compute state extra)) + ) + ) + +size : ( + Tonkadur.Types.State -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +size state computation = + (IntValue + (Dict.size (Tonkadur.Types.value_to_dict (compute state computation))) + ) + + +text : ( + Tonkadur.Types.State -> + (List Tonkadur.Types.Computation) -> + Tonkadur.Types.Value + ) +text state content = + (List.foldl + (\addition result -> + (TextValue + (Tonkadur.Types.append_text_content + (Tonkadur.Types.value_to_text result) + (Tonkadur.Types.value_to_text (compute state addition)) + ) + ) + ) + (TextValue (Tonkadur.Types.default_text_data)) + content + ) + +value_of : ( + Tonkadur.Types.State -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +value_of state computation = + (List.foldl + (\next_step object -> + case (Dict.get next_step (Tonkadur.Types.value_to_dict object)) of + Nothing -> (StringValue "Segmentation Fault (incorrect address)") + (Just value) -> value + ) + (StructureValue state.memory) + (Tonkadur.Types.value_to_list (compute state computation)) + ) + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +compute : ( + Tonkadur.Types.State -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Value + ) +compute state computation = + case computation of + (AddTextEffect effect_name effect_parameters content) -> + (add_text_effect state effect_name effect_parameters content) + + (Address param) -> (address state param) + (Cast from to value) -> (cast state from to value) + (Constant true_type as_string) -> (constant state true_type as_string) + (ExtraComputation name parameters) -> + (extra_computation state name parameters) + + (IfElse condition if_true if_false) -> + (if_else state condition if_true if_false) + + LastChoiceIndex -> (last_choice_index state) + Newline -> (newline state) + NextAllocableAddress -> (next_allocable_address state) + (Operation name arg_0 arg_1) -> (operation state name arg_0 arg_1) + (RelativeAddress base extra) -> (relative_address state base extra) + (Size value) -> (size state value) + (Text content) -> (text state content) + (ValueOf address) -> (value_of state address) diff --git a/src/Tonkadur/Execute.elm b/src/Tonkadur/Execute.elm new file mode 100644 index 0000000..98eb680 --- /dev/null +++ b/src/Tonkadur/Execute.elm @@ -0,0 +1,301 @@ +module Tonkadur.Execute exposing (execute) + +-- Elm ------------------------------------------------------------------------- +import Dict +import List + +-- Tonkadur -------------------------------------------------------------------- +import Tonkadur.Types + +import Tonkadur.Compute + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +increment_program_counter : Tonkadur.Types.State -> Tonkadur.Types.State +increment_program_counter state = + {state | program_counter = program_counter + 1} + +---- INSTRUCTIONS -------------------------------------------------------------- +add_event_option : ( + String -> + (List Tonkadur.Types.Computation) -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +add_event_option name parameters state = + (Tonkadur.Types.append_option + (Event name (List.map (Tonkadur.Compute.compute state) parameters)) + state + ) + +add_text_option : ( + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +add_text_option label state = + (Tonkadur.Types.append_option + (Choice (Tonkadur.Compute.compute label state)) + state + ) + +assert : ( + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +assert condition label state = + if (Tonkadur.Types.value_to_bool (Tonkadur.Compute.compute state condition)) + then + -- TODO: some special error report + state + else state + +display : ( + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State +) +display label state = + -- TODO: where do we put displayed values? + state + +end : Tonkadur.Types.State -> Tonkadur.Types.State +end state = + -- TODO: what do we do with this? + state + +extra_instruction : ( + String -> + (List Tonkadur.Types.Computation) -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +extra_instruction name parameters state = + -- No extra instruction supported. + -- TODO: error report. + +initialize : ( + String -> + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +initialize type_name address state = + {state | + memory = + (Tonkadur.Types.apply_at_address + (Tonkadur.Types.value_to_list + (Tonkadur.Compute.compute state address) + ) + (\last_addr dict -> + (Dict.insert + last_addr + (Tonkadur.Types.get_default state type_name) + dict + ) + ) + state.memory + ) + } + +prompt_command : ( + Tonkadur.Types.PromptInstructionData -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +prompt_command prompt_data state = + {state | + memorized_target = (Tonkadur.Compute.compute state prompt_data.address), + last_instruction_effect = + (PromptCommand + (Tonkadur.Compute.compute state prompt_data.min) + (Tonkadur.Compute.compute state prompt_data.max) + (Tonkadur.Compute.compute state prompt_data.label) + ) + } + +prompt_string : ( + Tonkadur.Types.PromptInstructionData -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +prompt_string prompt_data state = + {state | + memorized_target = (Tonkadur.Compute.compute state prompt_data.address), + last_instruction_effect = + (PromptString + (Tonkadur.Compute.compute state prompt_data.min) + (Tonkadur.Compute.compute state prompt_data.max) + (Tonkadur.Compute.compute state prompt_data.label) + ) + } + +prompt_integer : ( + Tonkadur.Types.PromptInstructionData -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +prompt_integer prompt_data state = + {state | + memorized_target = (Tonkadur.Compute.compute state prompt_data.address), + last_instruction_effect = + (PromptInteger + (Tonkadur.Compute.compute state prompt_data.min) + (Tonkadur.Compute.compute state prompt_data.max) + (Tonkadur.Compute.compute state prompt_data.label) + ) + } + +remove : ( + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +remove address state = + {state | + memory = + (Tonkadur.Types.apply_at_address + (Tonkadur.Types.value_to_list + (Tonkadur.Compute.compute state address) + ) + (\last_addr dict -> (Dict.remove last_addr dict)) + state.memory + ) + } + +resolve_choice : Tonkadur.Types.State -> Tonkadur.Types.State +resolve_choice state = + {state | last_instruction_effect = PromptChoice} + +set_pc : ( + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State +) +set_pc value state = + {state | + program_counter = + (Tonkadur.Types.value_to_int + (Tonkadur.Compute.compute state value) + ) + } + +set_random : ( + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State +) +set_random address min max state = + let + (value, next_random_seed) = + (Random.step + (Random.int + (Tonkadur.Types.value_to_int + (Tonkadur.Compute.compute state min) + (Tonkadur.Compute.compute state max) + ) + ) + state.random_seed + ) + in + {state | + memory = + (Tonkadur.Types.apply_at_address + (Tonkadur.Types.value_to_list + (Tonkadur.Compute.compute state address) + ) + (\last_addr dict -> (Dict.insert last_addr (IntValue value) dict)) + state.memory + ), + + random_seed = next_random_seed + } + +set : ( + Tonkadur.Types.Computation -> + Tonkadur.Types.Computation -> + Tonkadur.Types.State -> + Tonkadur.Types.State +) +set address value state = + {state | + memory = + (Tonkadur.Types.apply_at_address + (Tonkadur.Types.value_to_list + (Tonkadur.Compute.compute state address) + ) + (\last_addr dict -> + (Dict.insert + last_addr + (Tonkadur.Compute.compute state value) + dict + ) + ) + state.memory + ) + } + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +execute : ( + Tonkadur.Types.Instruction -> + Tonkadur.Types.State -> + Tonkadur.Types.State -> + ) +execute instruction state = + let new_state = {state | last_instruction_effect = Continue} in + case instruction of + (AddEventOption name parameters) -> + (increment_program_counter + (add_event_option name parameters new_state) + ) + + (AddTextOption label) -> + (increment_program_counter + (add_text_option name parameters new_state) + ) + + (Assert condition label) -> + (increment_program_counter + (assert condition label new_state) + ) + + (Display label) -> + (increment_program_counter (display label new_state)) + + End -> (end new_state) + (ExtraInstruction name parameters) -> + (extra_instruction name parameters new_state) + + (Initialize type_name address) -> + (increment_program_counter + (initialize type_name address new_state) + ) + (PromptCommand prompt_data) -> + (increment_program_counter (prompt_command prompt_data new_state)) + + (PromptInteger prompt_data) -> + (increment_program_counter (prompt_integer prompt_data new_state)) + + (PromptString prompt_data) -> + (increment_program_counter (prompt_string prompt_data new_state)) + + (Remove address) -> (increment_program_counter (remove address new_state)) + ResolveChoice -> (increment_program_counter (resolve_choice new_state)) + (SetPC value) -> (set_pc value new_state) + (SetRandom address min max) -> + (increment_program_counter (set_random address min max new_state)) + + (Set address value) -> + (increment_program_counter (set address value new_state)) + diff --git a/src/Tonkadur/PlayerInput.elm b/src/Tonkadur/PlayerInput.elm new file mode 100644 index 0000000..facf9e5 --- /dev/null +++ b/src/Tonkadur/PlayerInput.elm @@ -0,0 +1,85 @@ +module Tonkadur.PlayerInput exposing (..) + +-- Elm ------------------------------------------------------------------------- +import Dict +import List + +-- Tonkadur -------------------------------------------------------------------- +import Tonkadur.Types + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +select_choice : Int -> Tonkadur.Types.State -> Tonkadur.Types.State +select_choice index state = {state | last_choice_index = index} + +input_string : String -> Tonkadur.Types.State -> Tonkadur.Types.State +input_string string state = + {state | + memory = + (Tonkadur.Types.apply_at_address + (Tonkadur.Types.value_to_address state.memorized_target) + (\last_address dict -> + (Dict.insert last_address (StringValue string) dict) + ) + state.memory + ) + } + +input_int : Int -> Tonkadur.Types.State -> Tonkadur.Types.State +input_int int state = + {state | + memory = + (Tonkadur.Types.apply_at_address + (Tonkadur.Types.value_to_address state.memorized_target) + (\last_address dict -> + (Dict.insert last_address (IntValue int) dict) + ) + state.memory + ) + } + +input_command : ( + (List String) -> + Tonkadur.Types.State -> + Tonkadur.Types.State + ) +input_command commands state = + {state | + memory = + (Tonkadur.Types.apply_at_address + (Tonkadur.Types.value_to_address state.memorized_target) + (\last_address dict -> + (Dict.insert + last_address + (ListValue + (Dict.fromList + (List.indexedMap + (\index value -> + ( + ( + case (String.fromInt index) of + (Just i) -> i + Nothing -> "invalid_index" + ), + value + ) + ) + commands + ) + ) + ) + dict + ) + ) + state.memory + ) + } diff --git a/src/Tonkadur/Types.elm b/src/Tonkadur/Types.elm new file mode 100644 index 0000000..9df1df7 --- /dev/null +++ b/src/Tonkadur/Types.elm @@ -0,0 +1,268 @@ +module Tonkadur.Types exposing (..) + +-- Elm ------------------------------------------------------------------------- +import Dict +import List + +-------------------------------------------------------------------------------- +-- TYPES ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- +type alias TextData = + { + content : (List RichText), + effect_name : String, + effect_parameters : (List Value) + } + + +type RichText = + StringText String + | AugmentedText TextData + | NewlineText + +type Value = + BoolValue Bool + | FloatValue Float + | IntValue Int + | TextValue RichText + | StringValue String + | ListValue (Dict.Dict String Value) + | PointerValue (List String) + | StructureValue (Dict.Dict String Value) + +type Option = + Choice RichText + | Event (String, (List Value)) + +type Computation = + AddTextEffect (String, (List Computation), (List Computation)) + | Address Computation + | Cast (String, String, Computation) + | Constant (String, String) + | ExtraComputation (String, (List Computation)) + | IfElse (Computation, Computation, Computation) + | LastChoiceIndex + | Newline + | NextAllocableAddress + | Operation (String, Computation, Computation) + | RelativeAddress (Computation, Computation) + | Size Computation + | Text (List Computation) + | ValueOf Computation + +type alias PromptInstructionData = + { + min : Computation, + max : Computation, + address : Computation, + label : Computation + } +type Instruction = + AddEventOption (String, (List Computation)) + | AddTextOption Computation + | Assert (Computation, Computation) + | Display Computation + | End + | ExtraInstruction (String, (List Computation)) + | Initialize (String, Computation) + | PromptCommand PromptInstructionData + | PromptInteger PromptInstructionData + | PromptString PromptInstructionData + | Remove Computation + | ResolveChoice + | SetPC Computation + | SetRandom (Computation, Computation, Computation) + | Set (Computation, Computation) + +type InstructionEffect = + MustContinue + | MustEnd + | MustPromptCommand (Value, Value, Value) + | MustPromptInteger (Value, Value, Value) + | MustPromptString (Value, Value, Value) + | MustPromptChoice + | MustDisplay Value + | MustDisplayError Value + | MustExtraEffect (String, (List Value)) + +type alias State = + { + memory : (Dict.Dict String Value), + user_types : (Dict.Dict String Value), + sequences : (Dict.Dict String Int), + code : (List Instruction), + program_counter : Int, + allocated_data : Int, + last_choice_index : Int, + available_options : (List Option), + memorized_target : Value, + + last_instruction_effect : InstructionEffect + } + +-------------------------------------------------------------------------------- +-- LOCAL ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- EXPORTED -------------------------------------------------------------------- +-------------------------------------------------------------------------------- +value_to_bool : Value -> Bool +value_to_bool value = + case value of + (BoolValue result) -> result + _ -> False + +value_to_float : Value -> Float +value_to_float value = + case value of + (FloatValue result) -> result + _ -> 0.0 + +value_to_int : Value -> Int +value_to_int value = + case value of + (IntValue result) -> result + _ -> 0 + +value_to_text_or_string : Value -> RichText +value_to_text_or_string value = + case value of + (TextValue result) -> result + (StringValue string) -> (StringText string) + _ -> (StringText "") + +value_to_string : Value -> String +value_to_string value = + case value of + (StringValue result) -> result + (TextValue text) -> + case text of + (StringText result) -> result + (AugmentedText rich_text) -> + (String.concat + (List.map (value_to_string) rich_text.content) + ) + + NewlineText -> "\n" + + _ -> (StringText "") + +value_to_dict : Value -> (Dict.Dict String Value) +value_to_dict value = + case value of + (StructureValue dict) -> dict + (ListValue dict) -> dict + _ -> (Dict.empty) + +value_to_address : Value -> (List String) +value_to_address value = + case value of + (PointerValue result) -> result + _ -> [] + +no_text_effect : String +no_text_effect = "" + +append_text_content : RichText -> RichText -> RichText +append_text_content base addition = + case base of + (AugmentedText text_data) -> + case addition of + (AugmentedText other_text_data) -> + -- Optimize text to avoid increasing depth if no new effect is + -- introduced. + if (other_text_data.effect_name == (no_text_effect)) + then + (AugmentedText + {text_data | + content = + (List.append base.content other_text_data.content) + } + ) + else + (AugmentedText + {text_data | + content = + (List.append + base.content + (List.singleton other_text_data) + ) + } + ) + + other -> + (AugmentedText + {text_data | + content = + (List.append base.content (List.singleton other)) + } + ) + + non_augmented_text_data -> + (append_text_content + (append_text_content (AugmentedText (default_text_data)) base) + addition + ) + +default_text_data : TextData +default_text_data = + { + effect_name = (no_text_effect), + effect_parameters = [], + content = [] + } + +append_option : Option -> State -> State +append_option option state = + {state | + available_options = + (List.append state.available_options (List.singleton option)) + } + +get_default : State -> String -> Value +get_default state type_name = + case type_name of + "bool" -> (BoolValue False) + "float" -> (FloatValue 0.0) + "int" -> (IntValue 0) + "text" -> (TextValue (StringText "")) + "string" -> (StringValue "") + "list" -> (ListValue (Dict.empty)) + "ptr" -> (PointerValue []) + other -> + case (Dict.get other state.user_types) of + (Just default) -> default + Nothing -> (StringValue ("Unknown type '" + other + "'")) + +apply_at_address : ( + (List String) -> + ( + String -> + (Dict.Dict String Value) -> + (Dict.Dict String Value) + ) -> + (Dict.Dict String Value) -> + (Dict.Dict String Value) + ) +apply_at_address address fun memory = + case address of + [] -> memory + (last_element :: []) -> (fun last_element memory) + (next_element :: next_address) -> + (Dict.update + next_element + (\maybe_value -> + case maybe_value of + (Just value) -> + (Just + (apply_at_address + next_address + fun + (value_to_dict value) + ) + ) + + Nothing -> Nothing + ) + ) |


