summaryrefslogtreecommitdiff |
diff options
author | nsensfel <SpamShield0@noot-noot.org> | 2017-11-28 17:14:02 +0100 |
---|---|---|
committer | nsensfel <SpamShield0@noot-noot.org> | 2017-11-28 17:14:02 +0100 |
commit | f539b7072c357339328d9bfd54f1f1ed51828586 (patch) | |
tree | b6205dd79c78090831e812aceac177d2a9f35d28 /src | |
parent | 80358376b9300a0d73cb8b62dfa9fdd65240ca66 (diff) |
Trying to tidy up this mess.
Diffstat (limited to 'src')
-rw-r--r-- | src/battlemap.erl | 8 | ||||
-rw-r--r-- | src/character.erl | 16 | ||||
-rw-r--r-- | src/data/tile.erl (renamed from src/tile.erl) | 0 | ||||
-rw-r--r-- | src/io/database_shim.erl (renamed from src/database_shim.erl) | 59 | ||||
-rw-r--r-- | src/io/timed_cache.erl (renamed from src/timed_cache.erl) | 0 | ||||
-rw-r--r-- | src/io/timed_caches_manager.erl (renamed from src/timed_caches_manager.erl) | 0 | ||||
-rw-r--r-- | src/query/character_turn.erl | 179 | ||||
-rw-r--r-- | src/query/load_state.erl | 123 | ||||
-rw-r--r-- | src/timed_cache_data.hrl | 9 | ||||
-rw-r--r-- | src/type/battlemap.erl | 38 | ||||
-rw-r--r-- | src/type/battlemap/cross.erl (renamed from src/battlemap/cross.erl) | 2 | ||||
-rw-r--r-- | src/type/battlemap_instance.erl (renamed from src/battlemap_instance.erl) | 21 | ||||
-rw-r--r-- | src/type/battlemap_instance_shim.erl | 40 | ||||
-rw-r--r-- | src/type/battlemap_shim.erl (renamed from src/battlemap_shim.erl) | 17 | ||||
-rw-r--r-- | src/type/character.erl | 34 | ||||
-rw-r--r-- | src/type/character_instance.erl (renamed from src/character_instance.erl) | 48 | ||||
-rw-r--r-- | src/type/character_shim.erl (renamed from src/character_shim.erl) | 19 |
17 files changed, 524 insertions, 89 deletions
diff --git a/src/battlemap.erl b/src/battlemap.erl deleted file mode 100644 index ba89733..0000000 --- a/src/battlemap.erl +++ /dev/null @@ -1,8 +0,0 @@ --module(battlemap). --export([dist/2]). --include("timed_cache_data.hrl"). - --include("battlemap/cross.erl"). - -dist ({OX, OY}, {DX, DY}) -> - (abs(OX - DX) + abs(OY + DY)). diff --git a/src/character.erl b/src/character.erl deleted file mode 100644 index 4da1684..0000000 --- a/src/character.erl +++ /dev/null @@ -1,16 +0,0 @@ --module(character). --export -( - [ - get_movement_points/1, - get_attack_range/1, - get_max_health/1 - ] -). - --include("timed_cache_data.hrl"). - -get_movement_points (Char) -> Char#character.mov_pts. -get_attack_range (Char) -> Char#character.atk_rg. - -get_max_health (Char) -> Char#character.health. diff --git a/src/tile.erl b/src/data/tile.erl index cb5811b..cb5811b 100644 --- a/src/tile.erl +++ b/src/data/tile.erl diff --git a/src/database_shim.erl b/src/io/database_shim.erl index c840009..243051b 100644 --- a/src/database_shim.erl +++ b/src/io/database_shim.erl @@ -8,8 +8,6 @@ ] ). --include("timed_cache_data.hrl"). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -36,40 +34,21 @@ generate_char_instances (Battlemap, Characters) -> ( fun (Char) -> { - Char#character.id, - #character_instance - { - x = rand:uniform(Battlemap#battlemap.width - 1), - y = rand:uniform(Battlemap#battlemap.height - 1), - team = (rand:uniform(2) - 1), - health = Char#character.health - } + character:get_id(Char), + character_instance:new_instance_of + ( + Char, + (rand:uniform(2) - 1), % team, + { + rand:uniform(battlemap:get_width(Battlemap) - 1), % X + rand:uniform(battlemap:get_heigth(Battlemap) - 1) % Y + } + ) } end, Characters ). -generate_map_instance (CharInts) -> - #battlemap_instance - { - id = <<"0">>, - chars = dict:from_list(CharInts), - curr_player = 0, - players = array:from_list([<<"0">>, <<"1">>]), - rem_chars = - lists:filtermap - ( - fun ({K, V}) -> - case character_instance:get_owner(V) of - 0 -> {true, K}; - _ -> false - end - end, - CharInts - ), - last_turn = [] - }. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -79,21 +58,27 @@ generate_db (Heir) -> receive ok -> ok end, - Battlemap = battlemap_shim:generate(), - Characters = character_shim:generate(rand:uniform(12) + 4), + Players = [<<"0">>, <<"1">>], + Battlemap = battlemap_shim:generate_random(), + Characters = character_shim:generate_random(rand:uniform(12) + 4), CharacterInsts = generate_char_instances(Battlemap, Characters), - BattlemapInstance = generate_map_instance(CharacterInsts), - add_to_db({battlemap_db, Battlemap#battlemap.id}, Battlemap), + BattlemapInstance = + battlemap_instance_shim:generate_random + ( + CharacterInsts, + Players + ), + add_to_db({battlemap_db, battlemap:get_id(Battlemap)}, Battlemap), lists:map ( fun (Char) -> - add_to_db({character_db, Char#character.id}, Char) + add_to_db({character_db, character:get_id(Char)}, Char) end, Characters ), add_to_db ( - {battlemap_instance_db, BattlemapInstance#battlemap_instance.id}, + {battlemap_instance_db, battlemap_instance:get_id(BattlemapInstance)}, BattlemapInstance ). diff --git a/src/timed_cache.erl b/src/io/timed_cache.erl index c86caab..c86caab 100644 --- a/src/timed_cache.erl +++ b/src/io/timed_cache.erl diff --git a/src/timed_caches_manager.erl b/src/io/timed_caches_manager.erl index ad66fbb..ad66fbb 100644 --- a/src/timed_caches_manager.erl +++ b/src/io/timed_caches_manager.erl diff --git a/src/query/character_turn.erl b/src/query/character_turn.erl new file mode 100644 index 0000000..cf55585 --- /dev/null +++ b/src/query/character_turn.erl @@ -0,0 +1,179 @@ +-module(character_turn). +-record +( + input, + { + session_token, + player_id, + battlemap_id, + instance_id, + char_id, + path, + target_id + } +). +-record +( + query_state, + { + input, + battlemap, + battlemap_inst, + main_char, + main_char_inst, + main_char_new_loc, + target_char, + target_char_inst + } +). +-export([out/1]). + +parse_input (Req) -> + JSONReqMap = jiffy:decode(Req, [return_maps]), + #input + { + session_token = maps:get(<<"session_token">>, JSONReqMap), + player_id = maps:get(<<"player_id">>, JSONReqMap), + battlemap_id = maps:get(<<"battlemap_id">>, JSONReqMap), + instance_id = maps:get(<<"instance_id">>, JSONReqMap), + char_id = maps:get(<<"char_id">>, JSONReqMap), + path = maps:get(<<"path">>, JSONReqMap), + target_id = maps:get(<<"target_id">>, JSONReqMap) + }. + +fetch_data (Input) -> + Battlemap = timed_cache:fetch(battlemap_db, Input#input.battlemap_id), + BattlemapInst = + timed_cache:fetch + ( + battlemap_instance_db, + <<"0">> + ), + MainChar = timed_cache:fetch(character_db, Input#input.char_id), + MainCharInst = + battlemap_instance:get_char_instance + ( + BattlemapInst, + Input#input.char_id + ), + case Input#input.target_id of + <<"">> -> + TargetChar = nothing, + TargetCharInst = nothing; + + TargetID -> + TargetChar = timed_cache:fetch(character_db, TargetID), + TargetCharInst = + battlemap_instance:get_char_instance + ( + BattlemapInst, + TargetID + ) + end, + #query_state + { + input = Input, + battlemap = Battlemap, + battlemap_inst = BattlemapInst, + main_char = MainChar, + main_char_inst = MainCharInst, + main_char_new_loc = nothing, + target_char = TargetChar, + target_char_inst = TargetCharInst + }. + +assert_main_char_can_be_used (QueryState) -> + false = character_instance:is_dead(QueryState#query_state.main_char_inst), + true = + battlemap_instance:can_play_char_instance + ( + QueryState#query_state.battlemap_inst, + QueryState#query_state.input#input.player_id, + QueryState#query_state.input#input.char_id + ). + +handle_main_char_movement (QueryState) -> + {X, Y} = + battlemap:cross + ( + QueryState#query_state.battlemap, + character_instance:get_location(QueryState#query_state.main_char_inst), + character:get_movement_points(QueryState#query_state.main_char), + QueryState#query_state.input#input.path, + battlemap_instance:get_char_instances + ( + QueryState#query_state.battlemap_inst + ) + ), + QueryState#query_state + { + battlemap_inst = + battlemap_instance:set_char_instance + ( + battlemap_instance:post_play_char_instance + ( + QueryState#query_state.battlemap_inst, + QueryState#query_state.input#input.char_id + ), + QueryState#query_state.input#input.char_id, + character_instance:set_location + ( + QueryState#query_state.main_char_inst, + X, + Y + ) + ), + main_char_new_loc = {X, Y} + }. + +handle_target (QueryState) + when (QueryState#query_state.target_char_inst == nothing) -> + QueryState; +handle_target (QueryState) -> + TargetLoc = + character_instance:get_location(QueryState#query_state.main_char_inst), + Dist = + battlemap:dist(QueryState#query_state.main_char_new_loc, TargetLoc), + true = + (Dist =< character:get_attack_range(QueryState#query_state.main_char)), + %% TODO: test for (and handle) riposte. + QueryState#query_state + { + battlemap_inst = + battlemap_instance:set_char_instance + ( + QueryState#query_state.battlemap_inst, + QueryState#query_state.input#input.target_id, + character_instance:mod_health + ( + QueryState#query_state.target_char_inst, + -1, + character:get_max_health(QueryState#query_state.main_char) + ) + ) + }. + +handle (Req) -> + %%%% Parse + Input = parse_input(Req), + %%%% Fetch + QueryState = fetch_data(Input), + %%%% Calc + assert_main_char_can_be_used(QueryState), + NQueryState = handle_target(handle_main_char_movement(QueryState)), + %%%% Commit + database_shim:commit + ( + battlemap_instance_db, + <<"0">>, + NQueryState#query_state.battlemap_inst + ), + %%%% Reply + jiffy:encode([[<<"okay">>]]). + +out(A) -> + { + content, + "application/json; charset=UTF-8", + handle(A#arg.clidata) + }. diff --git a/src/query/load_state.erl b/src/query/load_state.erl new file mode 100644 index 0000000..f2818bd --- /dev/null +++ b/src/query/load_state.erl @@ -0,0 +1,123 @@ +-module(load_state). +-record(input, {session_token, player_id, battlemap_id, instance_id}). +-export([out/1]). + +parse_input (Req) -> + JSONReqMap = jiffy:decode(Req, [return_maps]), + #input + { + session_token = maps:get(<<"session_token">>, JSONReqMap), + player_id = maps:get(<<"player_id">>, JSONReqMap), + battlemap_id = maps:get(<<"battlemap_id">>, JSONReqMap), + instance_id = maps:get(<<"instance_id">>, JSONReqMap) + }. + +generate_set_map (Battlemap) -> + jiffy:encode + ( + { + [ + {<<"width">>, battlemap:get_width(Battlemap)}, + {<<"height">>, battlemap:get_height(Battlemap)}, + {<<"content">>, battlemap:list_tiles(Battlemap)} + ] + } + ). + +generate_add_char (Char, CharInstance, BattlemapInstance, PlayerID) -> + {X, Y} = character_instance:get_location(CharInstance), + CharID = character:get_id(Char), + jiffy:encode + ( + { + [ + {<<"id">>, character:get_id(Char)}, + {<<"name">>, character:get_name(Char)}, + {<<"icon">>, character:get_icon(Char)}, + {<<"portrait">>, character:get_portrait(Char)}, + {<<"loc_x">>, X}, + {<<"loc_y">>, Y}, + {<<"team">>, character_instance:get_owner(CharInstance)}, + {<<"mov_pts">>, character:get_movement_points(Char)}, + {<<"atk_rg">>, character:get_attack_range(Char)}, + { + <<"enabled">>, + battlemap_instance:can_play_char_instance + ( + BattlemapInstance, + PlayerID, + CharID + ) + } + ] + } + ). + +generate_reply (Battlemap, BattlemapInstance, Characters, PlayerID) -> + jiffy:encode + ( + [ + [ + <<"set_map">>, + generate_set_map(Battlemap) + ] + | + lists:map + ( + fun ({CharID, CharInstance}) -> + [ + <<"add_char">>, + generate_add_char + ( + CharID, + CharInstance, + BattlemapInstance, + PlayerID + ) + ] + end, + Characters + ) + ] + ). + +handle (Req) -> + %%%% Parse + Input = parse_input(Req), + %%%% Fetch + Battlemap = timed_cache:fetch(battlemap_db, Input#input.battlemap_id), + BattlemapInstance = + timed_cache:fetch + ( + battlemap_instance_db, + <<"0">> +% {Input#input.battlemap_id, Input#input.battlemap_instance_id} + ), + Characters = + lists:map + ( + fun ({CharID, CharInst}) -> + { + timed_cache:fetch(character_db, CharID), + CharInst + } + end, + battlemap_instance:list_characters(BattlemapInstance) + ), + %%%% Calc + %%%% Commit + %%%% Reply + generate_reply + ( + Battlemap, + BattlemapInstance, + Characters, + Input#input.player_id + ). + +out(A) -> + { + content, + "application/json; charset=UTF-8", + handle(A#arg.clidata) + }. diff --git a/src/timed_cache_data.hrl b/src/timed_cache_data.hrl deleted file mode 100644 index 89e0f41..0000000 --- a/src/timed_cache_data.hrl +++ /dev/null @@ -1,9 +0,0 @@ -%% TODO: add types. --record(battlemap, {id, width, height, content, instances}). --record(battlemap_instance, {id, chars, curr_player, players, rem_chars, last_turn}). --record(character, {id, name, icon, portrait, health, mov_pts, atk_rg}). --record(character_turn, {id, path, target}). --record(player, {id, battlemaps, characters}). - -%% Not stored in its own timed cache. --record(character_instance, {x, y, health, team}). diff --git a/src/type/battlemap.erl b/src/type/battlemap.erl new file mode 100644 index 0000000..cce1a76 --- /dev/null +++ b/src/type/battlemap.erl @@ -0,0 +1,38 @@ +-module(battlemap). +-record +( + battlemap, + { + id, + width, + height, + content, + instances + } +). +-export +( + [ + get_id/1, + get_width/1, + get_height/1, + list_tiles/1, + get_instances/1 + ] +). +-export +( + [dist/2] +). +-export([cross/5]). + +get_id (Battlemap) -> Battlemap#battlemap.id. +get_width (Battlemap) -> Battlemap#battlemap.width. +get_height (Battlemap) -> Battlemap#battlemap.height. +list_tiles (Battlemap) -> array:sparse_to_list(Battlemap#battlemap.content). +get_instances (Battlemap) -> Battlemap#battlemap.instances. + +-include("battlemap/cross.erl"). + +dist ({OX, OY}, {DX, DY}) -> + (abs(OX - DX) + abs(OY + DY)). diff --git a/src/battlemap/cross.erl b/src/type/battlemap/cross.erl index add9c27..aa1645e 100644 --- a/src/battlemap/cross.erl +++ b/src/type/battlemap/cross.erl @@ -1,5 +1,3 @@ --export([cross/5]). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/battlemap_instance.erl b/src/type/battlemap_instance.erl index afe6e32..26ca5b1 100644 --- a/src/battlemap_instance.erl +++ b/src/type/battlemap_instance.erl @@ -1,4 +1,22 @@ -module(battlemap_instance). +-record +( + battlemap_instance, + { + id, + chars, + curr_player, + players, + rem_chars, + last_turn + } +). +-export +( + [ + list_characters/1 + ] +). -export ( [ @@ -10,7 +28,8 @@ ] ). --include("timed_cache_data.hrl"). +list_characters (BattlemapInstance) -> + dict:to_list(BattlemapInstance#battlemap_instance.chars). get_char_instances (BattlemapInstance) -> lists:map diff --git a/src/type/battlemap_instance_shim.erl b/src/type/battlemap_instance_shim.erl new file mode 100644 index 0000000..80a1007 --- /dev/null +++ b/src/type/battlemap_instance_shim.erl @@ -0,0 +1,40 @@ +-module(battlemap_instance_shim). +-record +( + battlemap_instance, + { + id, + chars, + curr_player, + players, + rem_chars, + last_turn + } +). +-export +( + [ + generate_random/2 + ] +). + +generate_random (CharInsts, Players) -> + #battlemap_instance + { + id = <<"0">>, + chars = dict:from_list(CharInsts), + curr_player = 0, + players = array:from_list(Players), + rem_chars = + lists:filtermap + ( + fun ({K, V}) -> + case character_instance:get_owner(V) of + 0 -> {true, K}; + _ -> false + end + end, + CharInsts + ), + last_turn = [] + }. diff --git a/src/battlemap_shim.erl b/src/type/battlemap_shim.erl index f4042d2..1fb035e 100644 --- a/src/battlemap_shim.erl +++ b/src/type/battlemap_shim.erl @@ -1,13 +1,22 @@ -module(battlemap_shim). +-record +( + battlemap, + { + id, + width, + height, + content, + instances + } +). -export ( [ - generate/0 + generate_random/0 ] ). --include("timed_cache_data.hrl"). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -35,7 +44,7 @@ generate(Prev, Result, X, Y, BaseWidth) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -generate () -> +generate_random () -> Width = (rand:uniform(48) + 16), Height = (rand:uniform(48) + 16), #battlemap diff --git a/src/type/character.erl b/src/type/character.erl new file mode 100644 index 0000000..e5b6d9f --- /dev/null +++ b/src/type/character.erl @@ -0,0 +1,34 @@ +-module(character). +-record +( + character, + { + id, + name, + icon, + portrait, + health, + mov_pts, + atk_rg + } +). +-export +( + [ + get_id/1, + get_name/1, + get_icon/1, + get_portrait/1, + get_max_health/1, + get_movement_points/1, + get_attack_range/1 + ] +). + +get_id (Char) -> Char#character.id. +get_name (Char) -> Char#character.name. +get_icon (Char) -> Char#character.icon. +get_portrait (Char) -> Char#character.portrait. +get_max_health (Char) -> Char#character.health. +get_movement_points (Char) -> Char#character.mov_pts. +get_attack_range (Char) -> Char#character.atk_rg. diff --git a/src/character_instance.erl b/src/type/character_instance.erl index e1cf7fe..5432c99 100644 --- a/src/character_instance.erl +++ b/src/type/character_instance.erl @@ -1,16 +1,52 @@ -module(character_instance). +-record +( + character_instance, + { + x, + y, + health, + team + } +). -export ( [ - set_location/3, - mod_health/3, - is_dead/1, % is_alive is reserved. get_location/1, + get_current_health/1, get_owner/1 ] ). +-export +( + [ + new_instance_of/3 + ] +). +-export +( + [ + set_location/3, + mod_health/3, + is_dead/1 % is_alive is reserved. + ] +). + +get_location (CharInst) -> + {CharInst#character_instance.x, CharInst#character_instance.y}. + +get_current_health (CharInst) -> CharInst#character_instance.health. --include("timed_cache_data.hrl"). +get_owner (CharInst) -> CharInst#character_instance.team. + +new_instance_of (Char, Owner, {X, Y}) -> + #character_instance + { + x = X, + y = Y, + health = character:get_max_health(Char), + team = Owner + }. set_location (CharInst, X, Y) -> CharInst#character_instance @@ -34,7 +70,3 @@ mod_health (CharInst, MaxHealth, HealthMod) -> is_dead (CharInst) -> (CharInst#character_instance.health == 0). -get_location (CharInst) -> - {CharInst#character_instance.x, CharInst#character_instance.y}. - -get_owner (CharInst) -> CharInst#character_instance.team. diff --git a/src/character_shim.erl b/src/type/character_shim.erl index 47d9cac..0ad357d 100644 --- a/src/character_shim.erl +++ b/src/type/character_shim.erl @@ -1,13 +1,24 @@ -module(character_shim). +-record +( + character, + { + id, + name, + icon, + portrait, + health, + mov_pts, + atk_rg + } +). -export ( [ - generate/1 + generate_random/1 ] ). --include("timed_cache_data.hrl"). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -32,5 +43,5 @@ generate (N, Prev) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -generate (N) -> +generate_random (N) -> generate(N, []). |