├── README.txt
├── commands.lua
├── depends.txt
├── init.lua
├── misc_commands.lua
├── mod.conf
├── robogui.lua
├── scripts
├── avl_tree~.lua
├── battle_bot_arena.lua
├── battle_minesweeper.lua
├── blackbox_game.lua
├── command_robot.lua
├── copy_paste.lua
├── craft_guide.lua
├── farm_walker.lua
├── fractal_bot.lua
├── games
│ ├── 2d rubik square.lua
│ ├── CTF_bot.lua
│ ├── battle_bot_arena.lua
│ ├── battle_minesweeper_game.lua
│ ├── blackbox_game.lua
│ ├── casino_bot.lua
│ ├── checkers.lua
│ ├── connect4.lua
│ ├── cyberpunk_2077_puzzle_gen.lua
│ ├── fallout_hacking.lua
│ ├── go.lua
│ ├── hacking_game.lua
│ ├── hide_and_seek.lua
│ ├── hide_and_seek_1.lua
│ ├── hide_and_seek_new.lua
│ ├── high_scores_for_games
│ ├── lights_out.lua
│ ├── maze_generator.lua
│ ├── mensch_argere_dich_nicht.lua
│ ├── minesweeper_game.lua
│ ├── nonogram.lua
│ ├── paint_game.lua
│ ├── rubik.lua
│ ├── simple_box_push.lua
│ ├── simple_layout_gen.lua
│ ├── sliding_puzzle_game.lua
│ ├── sokoban.txt
│ ├── sokoban3d.lua
│ ├── sokoban_game.lua
│ ├── switching_game.lua
│ ├── tank_bot.lua
│ └── wordle.lua
├── graphics
│ ├── painting.lua
│ └── painting_import.lua
├── gui
│ ├── craft_guide.lua
│ ├── file_manager.lua
│ ├── gui_2player_coop_edit.lua
│ ├── gui_deposit_withdraw_demo.lua
│ ├── gui_interact_demo_board.lua
│ ├── scrolling_inventory.lua
│ └── wiki.lua
├── hash_table_implementation.lua
├── http
│ ├── http_demo.lua
│ └── webcommands
│ │ ├── minetest_webcommands.js
│ │ └── webcommands.lua
├── math
│ ├── calender.lua
│ ├── enigma.lua
│ ├── fractal_bot.lua
│ ├── mandelbrot.lua
│ ├── multiplication.lua
│ └── perm2cycles.lua
├── messenger.lua
├── minesweeper.lua
├── minesweeper_game.lua
├── misc
│ ├── activity_generator.lua
│ ├── all_unicode_chars.lua
│ ├── charcoal_maker.lua
│ ├── chat_board.lua
│ ├── compact_inventory.lua
│ └── flower_gunnew 6.lua
├── multiplication.lua
├── music
│ └── music_playback.lua
├── perm2cycles.lua
├── pine_tree_harvest.lua
├── player_appearance.lua
├── programming
│ ├── block_save.lua
│ ├── brainfuck generator.lua
│ ├── brainfuck.lua
│ ├── code_parser_strings_identify.lua
│ ├── hash_table_implementation.lua
│ ├── natural language.lua
│ ├── natural language1.lua
│ ├── os_show_demo.lua
│ ├── parser - lines - words.lua
│ ├── perm2cycles.lua
│ ├── radix_sort.lua
│ ├── rndscript.lua
│ ├── robot2irc.lua
│ ├── room_finder.lua
│ ├── serialize.lua
│ └── turtle_with_loops.lua
├── radix_sort.lua
├── redstone_emulator.lua
├── serialization.lua
├── server mods
│ ├── chatlog.lua
│ └── colored chat.lua
├── shop.lua
├── shop
│ └── digital_money.lua
├── simple_layout_gen.lua
├── simple_parser.lua
├── simulators
│ ├── genetic_trust.lua
│ ├── group_assembly.lua
│ ├── horse_race.lua
│ ├── layout_designer.lua
│ ├── nuclear.lua
│ ├── pathfinder.lua
│ ├── redstone_emulator.lua
│ ├── room_walker.lua
│ ├── trust_game.lua
│ ├── turtle_with_loops.lua
│ └── turtlebot.lua
├── sokoban.txt
├── sokoban_game.lua
├── spawn_quiz.lua
├── substring_search.lua
├── terrain_smoother.lua
├── tree_harvest.lua
├── utils
│ ├── 3d printer.lua
│ ├── chatlog.lua
│ ├── copy_paste.lua
│ ├── helper_chat_bot.lua
│ ├── helper_chat_bot2.lua
│ ├── language translator.lua
│ ├── object_lister.lua
│ ├── resource_display.lua
│ ├── serverbot.lua
│ ├── simple_house_builder.lua
│ ├── text_printer.lua
│ └── text_width_formatter.lua
└── web
│ ├── https_server.py
│ ├── index.html
│ ├── irc bot.lua
│ └── run_server.bat
├── settings.lua
├── sounds
├── Dtmf0.ogg
├── Dtmf1.ogg
├── Dtmf2.ogg
├── Dtmf3.ogg
├── Dtmf4.ogg
├── Dtmf5.ogg
├── Dtmf6.ogg
├── Dtmf7.ogg
├── Dtmf8.ogg
├── Dtmf9.ogg
└── piano.ogg
└── textures
├── 000.png
├── 001.png
├── 002.png
├── 003.png
├── 004.png
├── 005.png
├── 006.png
├── 007.png
├── 008.png
├── 009.png
├── 010.png
├── 011.png
├── 012.png
├── 013.png
├── 014.png
├── 015.png
├── 016.png
├── 017.png
├── 018.png
├── 019.png
├── 020.png
├── 021.png
├── 022.png
├── 023.png
├── 024.png
├── 025.png
├── 026.png
├── 027.png
├── 028.png
├── 029.png
├── 030.png
├── 031.png
├── 032.png
├── 033.png
├── 034.png
├── 035.png
├── 036.png
├── 037.png
├── 038.png
├── 039.png
├── 040.png
├── 041.png
├── 042.png
├── 043.png
├── 044.png
├── 045.png
├── 046.png
├── 047.png
├── 048.png
├── 049.png
├── 050.png
├── 051.png
├── 052.png
├── 053.png
├── 054.png
├── 055.png
├── 056.png
├── 057.png
├── 058.png
├── 059.png
├── 060.png
├── 061.png
├── 062.png
├── 063.png
├── 064.png
├── 065.png
├── 066.png
├── 067.png
├── 068.png
├── 069.png
├── 070.png
├── 071.png
├── 072.png
├── 073.png
├── 074.png
├── 075.png
├── 076.png
├── 077.png
├── 078.png
├── 079.png
├── 080.png
├── 081.png
├── 082.png
├── 083.png
├── 084.png
├── 085.png
├── 086.png
├── 087.png
├── 088.png
├── 089.png
├── 090.png
├── 091.png
├── 092.png
├── 093.png
├── 094.png
├── 095.png
├── 096.png
├── 097.png
├── 098.png
├── 099.png
├── 100.png
├── 101.png
├── 102.png
├── 103.png
├── 104.png
├── 105.png
├── 106.png
├── 107.png
├── 108.png
├── 109.png
├── 110.png
├── 111.png
├── 112.png
├── 113.png
├── 114.png
├── 115.png
├── 116.png
├── 117.png
├── 118.png
├── 119.png
├── 120.png
├── 121.png
├── 122.png
├── 123.png
├── 124.png
├── 125.png
├── 126.png
├── 127.png
├── 128.png
├── 129.png
├── 130.png
├── 131.png
├── 132.png
├── 133.png
├── 134.png
├── 135.png
├── 136.png
├── 137.png
├── 138.png
├── 139.png
├── 140.png
├── 141.png
├── 142.png
├── 143.png
├── 144.png
├── 145.png
├── 146.png
├── 147.png
├── 148.png
├── 149.png
├── 150.png
├── 151.png
├── 152.png
├── 153.png
├── 154.png
├── 155.png
├── 156.png
├── 157.png
├── 158.png
├── 159.png
├── 160.png
├── 161.png
├── 162.png
├── 163.png
├── 164.png
├── 165.png
├── 166.png
├── 167.png
├── 168.png
├── 169.png
├── 170.png
├── 171.png
├── 172.png
├── 173.png
├── 174.png
├── 175.png
├── 176.png
├── 177.png
├── 178.png
├── 179.png
├── 180.png
├── 181.png
├── 182.png
├── 183.png
├── 184.png
├── 185.png
├── 186.png
├── 187.png
├── 188.png
├── 189.png
├── 190.png
├── 191.png
├── 192.png
├── 193.png
├── 194.png
├── 195.png
├── 196.png
├── 197.png
├── 198.png
├── 199.png
├── 200.png
├── 201.png
├── 202.png
├── 203.png
├── 204.png
├── 205.png
├── 206.png
├── 207.png
├── 208.png
├── 209.png
├── 210.png
├── 211.png
├── 212.png
├── 213.png
├── 214.png
├── 215.png
├── 216.png
├── 217.png
├── 218.png
├── 219.png
├── 220.png
├── 221.png
├── 222.png
├── 223.png
├── 224.png
├── 225.png
├── 226.png
├── 227.png
├── 228.png
├── 229.png
├── 230.png
├── 231.png
├── 232.png
├── 233.png
├── 234.png
├── 235.png
├── 236.png
├── 237.png
├── 238.png
├── 239.png
├── 240.png
├── 241.png
├── 242.png
├── 243.png
├── 244.png
├── 245.png
├── 246.png
├── 247.png
├── 248.png
├── 249.png
├── 250.png
├── 251.png
├── 252.png
├── 253.png
├── 254.png
├── 255.png
├── arrow.png
├── basic_machine_side.png
├── black_screen.png
├── chars.png
├── control.png
├── cpu.png
├── face-back.png
├── face.png
├── face3.png
├── left-hand.png
├── legs.png
├── puzzle_NOT.png
├── puzzle_button_off.png
├── puzzle_button_on.png
├── puzzle_checker.png
├── puzzle_delayer.png
├── puzzle_diode.png
├── puzzle_equalizer.png
├── puzzle_giver.png
├── puzzle_piston.png
├── puzzle_platform.png
├── puzzle_setter.png
├── puzzle_switch_off.png
├── puzzle_switch_off1.png
├── puzzle_switch_on.png
├── puzzle_switch_on1.png
├── right-hand.png
├── robochars.png
├── robot_button.png
├── robot_button0.png
├── robot_button1.png
├── robot_button2.png
├── robot_button3.png
├── robot_button4.png
├── robot_button5.png
├── robot_button6.png
├── robot_button7.png
├── robot_button8.png
├── robot_button9.png
├── robot_side.png
├── topface.png
└── white_screen.png
/README.txt:
--------------------------------------------------------------------------------
1 | BASIC_ROBOT: lightweight robot mod for multiplayer
2 | minetest 0.4.14
3 | (c) 2016 rnd
4 |
5 | MANUAL:
6 | 1. ingame help: right click spawner (basic_robot:spawner) and click help button
7 |
8 | ---------------------------------------------------------------------
9 | This program is free software: you can redistribute it and/or modify
10 | it under the terms of the GNU General Public License as published by
11 | the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | This program is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU General Public License for more details.
18 |
19 | You should have received a copy of the GNU General Public License
20 | along with this program. If not, see .
21 | ----------------------------------------------------------------------
22 |
23 |
24 | GAMEPLAY:
25 |
26 | - robot has limited operations available every run ( 1 run per 1 second).
27 | - while using for loops, while loops or function calls it is limited to default 48 such code executions per run
28 | - while using 'physical' operations like move/dig robot has (default) 10 operations available per run. Default costs are
29 | move=2, dig = 6, insert = 2, place = 2, machine.generate = 6, machine.smelt = 6, machine.grind = 6,
--------------------------------------------------------------------------------
/depends.txt:
--------------------------------------------------------------------------------
1 | default
--------------------------------------------------------------------------------
/mod.conf:
--------------------------------------------------------------------------------
1 | name = basic_robot
2 | depends = default
3 | optional_depends =
4 | description = your ingame robot companion. learn how to program and make games
--------------------------------------------------------------------------------
/scripts/farm_walker.lua:
--------------------------------------------------------------------------------
1 | if not init then
2 | init = true
3 | angle = 90
4 | walk = {["default:dirt"] = 1}
5 | stop = {["wool:white"] = 1}
6 | end
7 |
8 | node = read_node.forward_down()
9 | if walk[node] then
10 | move.forward()
11 | elseif stop[node] then
12 | self.reset(); angle = 90
13 | else
14 | turn.angle(angle);move.forward(); turn.angle(angle); angle = - angle
15 | end
--------------------------------------------------------------------------------
/scripts/fractal_bot.lua:
--------------------------------------------------------------------------------
1 | -- robot can construct classic fractals like menger sponge, jerusalem cube, sierpinski triangles,..
2 | -- use: build a pattern at position 1,1,1 relative to robot. when run robot will analyse pattern and construct fractal
3 | if not init then
4 | minetest.forceload_block(self.pos(),true)
5 | init = true; local spos = self.spawnpos();
6 |
7 | offsets = {["default:dirt"] = 0, ["default:wood"] = -1, ["default:cobble"] = 1}
8 |
9 | read_form = function(fractal) -- read shape from world
10 | local form = {}; local i = 0;
11 | local spos = self.spawnpos(); spos.x = spos.x+1;spos.y = spos.y+1;spos.z = spos.z+1;
12 | local nx = 0; local ny = 0; local nz = 0;
13 | fractal.form = {}
14 |
15 | for x = 0,fractal.nx-1 do
16 | for y = 0,fractal.ny-1 do
17 | for z = 0,fractal.nz-1 do
18 | local node = _G.minetest.get_node({x=spos.x+x,y=spos.y+y,z=spos.z+z}).name;
19 | local offset = offsets[node] or 0;
20 | if node~= "air" then
21 | form[i] = {x,y,z,offset}; i=i+1
22 | if nx1 or math.abs(dz)>1 then return false end
28 | local x1=bot[1]+dx; local z1=bot[2]+dz;
29 | if math.abs(x1)>10 or math.abs(z1)>10 then return false end
30 | if arena[x1] and arena[x1][z1] and arena[x1][z1][1] == 0 then else return false end
31 |
32 | keyboard.set({x=centerpos.x+bot[1],y=centerpos.y,z=centerpos.z+bot[2]},0);
33 | keyboard.set({x=centerpos.x+x1,y=centerpos.y,z=centerpos.z+z1},TYPE);
34 | arena[bot[1]][bot[2]] = {0,0}
35 | arena[x1][z1] = {TYPE,i}
36 |
37 | bot[1]=x1;bot[2]=z1;
38 | end
39 |
40 | attack_bot = function(i,dx,dz)
41 | local bot = bots[TYPE][i];if not bot then return false end
42 | if math.abs(dx)>1 or math.abs(dz)>1 then return false end
43 | local x1=bot[1]+dx; local z1=bot[2]+dz;
44 | if math.abs(x1)>10 or math.abs(z1)>10 then return false end
45 | if arena[x1] and arena[x1][z1] and arena[x1][z1][1] == 0 then return false end
46 | local type = arena[x1][z1][1]; local idx = arena[x1][z1][2];
47 | local tbot = bots[type][idx];
48 | if not tbot then return false end
49 | tbot[3]=tbot[3]-5;
50 | if tbot[3]<=0 then
51 | keyboard.set({x=centerpos.x+tbot[1],y=centerpos.y,z=centerpos.z+tbot[2]},0);
52 | table.remove(bots[type],idx);
53 | arena[x1][z1] = {0,0}
54 | end
55 | end
56 |
57 | read_arena = function(x,z)
58 | local data = arena[x][z];
59 | if not data then return end
60 | return {data[1],data[2]};
61 | end
62 |
63 | read_bots = function (type, idx)
64 | local data = bots[type][idx];
65 | if not data then return end
66 | return {data[1],data[2],data[3]}
67 | end
68 | end
69 |
70 | if t%10 == 0 then
71 | spawn_bot(0,-10,4)
72 | spawn_bot(0,10,5)
73 | end
74 | t=t+1
75 | self.label(#bots[4] .. " " .. #bots[5])
76 |
77 | -- PROGRAM RULES:
78 | -- not allowed to modify api code: TYPE, bots,t,s, spawn_bot, move_bot, attack_bot, read_arena, read_bots
79 | -- only allowed to move bot or attack, but not to dig/place
80 |
81 | TYPE = 4+(t%2);
82 | DIR = - DIR
83 |
84 | if TYPE == 5 then
85 | _G.setfenv(prog1, _G.basic_robot.data[self.name()].sandbox )
86 | _,err = pcall(prog1)
87 | else
88 | _G.setfenv(prog2, _G.basic_robot.data[self.name()].sandbox )
89 | _,err = pcall(prog2)
90 | end
91 | if err then say(err) self.remove() end
--------------------------------------------------------------------------------
/scripts/games/casino_bot.lua:
--------------------------------------------------------------------------------
1 | -- rnd 2017
2 | if not s then
3 | s=0
4 | player0 ="";
5 | reward = "default:gold_ingot 6"
6 | price = "default:gold_ingot";
7 | self.spam(1)
8 | end
9 | if s==0 then
10 | local player = find_player(5);
11 | if player then
12 | player=player[1]
13 | if player~=player0 then
14 | self.label("Hello " .. player .. ". Please insert one gold ingot in chest to play.\nYou need to roll 6 on dice to win 6 gold.")
15 | player0 = player
16 | end
17 | else
18 | self.label(colorize("red","Come and win 6 gold!"))
19 | end
20 | if check_inventory.forward(price) then
21 | take.forward("default:gold_ingot");
22 | self.label("Thank you for your gold. rolling the dice!")
23 | s=1
24 | end
25 | elseif s==1 then
26 | roll = math.random(6);
27 | if roll == 6 then
28 | self.label("#YOU WIN!")
29 | say("#WE HAVE A WINNER! get 6 gold in chest!")
30 | insert.forward(reward)
31 | s=2
32 | else
33 | self.label(":( you rolled " .. roll.. ". Put gold in to try again.")
34 | s=0
35 | end
36 | elseif s==2 then
37 | if not check_inventory.forward(reward) then s=0 self.label("Please insert one gold to continue playing") end
38 | end
--------------------------------------------------------------------------------
/scripts/games/connect4.lua:
--------------------------------------------------------------------------------
1 | -- CONNECT, coded in 20 minutes by rnd
2 | if not data then
3 | m=10;n=10;turn = 0; num = 4;
4 |
5 | self.spam(1);t0 = _G.minetest.get_gametime();
6 | spawnpos = self.spawnpos() -- place mines
7 | self.listen_punch(self.pos()) -- attach punch listener
8 | state = 0; -- 0 signup 1 game
9 | players = {};
10 | data = {};
11 | for i = 1,m do data[i]={}; for j = 1,n do data[i][j]=0 end end
12 | for i = 1,m do for j = 1,n do -- render game
13 | if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:buttonlight_gray" then
14 | keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},13)
15 | end
16 | end end
17 |
18 | get_count_in_dir = function(dir,x,y)
19 | local r = num; -- num=4? in a row
20 | local snode = data[x][y];local count = 1;
21 | for j = 1,2 do
22 | for i = 1,r-1 do
23 | local x1 = x + dir[1]*i;local y1 = y + dir[2]*i;
24 | if not data[x1] or not data[x1][y1] then break end; if data[x1][y1]~= snode then break end
25 | count = count +1
26 | end
27 | dir[1]=-dir[1];dir[2]=-dir[2];
28 | end
29 | return count
30 | end
31 |
32 | get_count = function(x,y)
33 | local c1 = get_count_in_dir({0,1},x,y); local c2 = get_count_in_dir({1,0},x,y)
34 | local c3 = get_count_in_dir({1,1},x,y); local c4 = get_count_in_dir({1,-1},x,y)
35 | if c2>c1 then c1 = c2 end; if c3>c1 then c1 = c3 end; if c4>c1 then c1 = c4 end
36 | return c1
37 | end
38 |
39 | self.label("TRY TO GET FIRST " .. num .. " IN A ROW! : GREEN starts play. 2 players punch to join game.")
40 | end
41 |
42 | event = keyboard.get();
43 | if event then
44 | local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
45 | if x<1 or x>m or z<1 or z>n then
46 | elseif event.type == 13 then --if event.type == 2 then
47 | if state == 0 then
48 | if #players<2 then players[#players+1] = event.puncher -- 1 is green, turn 0 = green
49 | else state = 1 end
50 | if #players==2 then state = 1 end
51 | end
52 | if event.puncher == players[1] then -- green
53 | if turn~=0 then return end -- ignore if not player turn
54 | else
55 | if turn~=1 then return end
56 | end
57 | keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4+turn);
58 | data[x][z] = 4+turn;
59 | if get_count(x,z) == num then say("CONGRATULATIONS! " .. event.puncher .. " has "..num .. " in a row"); self.remove(); goto END end
60 | turn = 1-turn
61 | if state == 1 then
62 | local msg = ""; if turn == 0 then msg = "GREEN " else msg = "BLUE" end
63 | self.label(msg .. " : " .. players[turn+1])
64 | end
65 | end
66 | end
67 | ::END::
--------------------------------------------------------------------------------
/scripts/games/cyberpunk_2077_puzzle_gen.lua:
--------------------------------------------------------------------------------
1 | --cyberpunk 2077 'breach protocol puzzle' generator
2 | --by rnd, 20 min
3 |
4 |
5 | if not init then init = true
6 | n=4; -- size of square
7 | steps = n*n; -- length of sequence
8 | tries = n*10; -- how many tries in current row/col before giving up
9 |
10 | tb = {};
11 | for i = 1,n do
12 | tb[i] ={}; local tbi = tb[i]
13 | for j = 1,n do
14 | tbi[j] = (i-1)*n+j
15 | end
16 | end
17 |
18 | --make random path col/row/col... starting at random position
19 |
20 | row = true;
21 | posi = 1; -- row
22 | posj = 1; -- col
23 | path = {}
24 | used = {}; -- [num] = true, when taken
25 |
26 | for i = 1, steps do
27 | if row then
28 | local tmp = posj;
29 | local s = 0
30 | while (tmp == posj or used[tb[posi][tmp]]) and s < tries do
31 | tmp = math.random(n);
32 | s=s+1
33 | end
34 | if s == tries then say("stuck at lenght " .. #path) break end
35 | posj = tmp
36 | else
37 | local tmp = posi;
38 | local s = 0
39 | while (tmp == posi or used[tb[tmp][posj]]) and s < tries do
40 | tmp = math.random(n);
41 | s=s+1
42 | end
43 | if s == tries then say("stuck at lenght " .. #path) break end
44 | posi = tmp
45 | end
46 | row = not row
47 | path[#path+1] = tb[posi][posj];
48 | used[path[#path]] = true
49 | end
50 |
51 | local ret = {};
52 | for i = 1,n do
53 | for j = 1,n do
54 | ret[#ret+1] = string.format("%02d",(i-1)*n+j).." ";
55 | end
56 | ret[#ret+1] = "\n"
57 | end
58 |
59 |
60 | self.label(table.concat(path," ") .. "\n\n"..table.concat(ret))
61 |
62 | end
63 |
64 |
65 |
--------------------------------------------------------------------------------
/scripts/games/high_scores_for_games:
--------------------------------------------------------------------------------
1 | -- high scores for multiple levels of game
2 | if not init then init = true
3 | init_score = function(levels, tops, default_value) -- [level] = {{name,score}, ...}
4 | local data = {} for i = 1, levels do data[i] = {} for j = 1,tops do data[i][j] = {"-",default_value} end end return data
5 | end
6 |
7 | add_score = function(data,name,score,level)
8 | local datal = data[level]; local tops = #datal;
9 | local j;for i = 1,tops do if score>datal[i][2] then j = i break end end
10 | if not j then return end; for i=tops,j+1,-1 do datal[i][1] = datal[i-1][1];datal[i][2] = datal[i-1][2] end
11 | datal[j] = {name,score}
12 | end
13 |
14 | _,text = book.read(1); data = minetest.deserialize(text)
15 | if not data then data = init_score(1,5,-999) end
16 |
17 | add_score(data,"pl1",-50,1)
18 | add_score(data,"pl2",-40,1)
19 |
20 | book.write(1,"score", minetest.serialize(data))
21 |
22 | self.label(serialize(data))
23 | end
--------------------------------------------------------------------------------
/scripts/games/simple_box_push.lua:
--------------------------------------------------------------------------------
1 | -- simple box pushing game, rnd
2 |
3 | if not init then
4 | spos = self.spawnpos(); spos.x = spos.x +5; spos.z = spos.z +5;
5 |
6 | for i = 1, 2 do -- set up 4 boxes
7 | for j = 1,2 do
8 | puzzle.set_node({x=spos.x+i,y=spos.y,z=spos.z+j}, {name = "basic_robot:buttonwhite"})
9 | end
10 | end
11 |
12 | init = true
13 | players = find_player(5);
14 | if not players then say("no players nearby") self.remove() end
15 | self.label("BOX PUSH demo. punch the white box to move it around.\npush it into blue block to make it disappear.")
16 |
17 | pushables = {[1] = true} -- button types
18 | canpushnodes = {["air"] = 1, ["basic_robot:buttonblue"] = 2} -- 1 push node, 2 absorb node
19 |
20 | self.listen_punch(self.pos()) -- robot will now read punch button events in 32x32 box area
21 | end
22 |
23 | event = keyboard.get()
24 |
25 | if event then -- there was punch event
26 | local boxtype = event.type
27 | if pushables[boxtype] then
28 | player = puzzle.get_player(event.puncher)
29 | local pos = player:getpos();
30 | local boxpos = {x = event.x, y = event.y, z = event.z};
31 | local diff = { pos.x-boxpos.x, pos.z-boxpos.z};
32 |
33 | local newx,newz
34 | if math.abs(diff[1])>math.abs(diff[2]) then -- punch in x-direction
35 | newx = boxpos.x - (diff[1]>0 and 1 or -1)
36 | newz = boxpos.z
37 | else
38 | newx = boxpos.x
39 | newz = boxpos.z - (diff[2]>0 and 1 or -1)
40 | end
41 |
42 | local newnode = puzzle.get_node({x=newx, y= boxpos.y, z= newz}).name
43 |
44 |
45 | local canpush = canpushnodes[newnode]
46 | if canpush then
47 | local oldnode = puzzle.get_node(boxpos).name
48 | puzzle.set_node(boxpos,{name= "air"}) -- remove node
49 | if canpush == 1 then -- simply move the box
50 | newnode = oldnode
51 | elseif canpush == 2 then -- absorb the box
52 | newnode = newnode
53 | end
54 |
55 | puzzle.set_node({x=newx, y= boxpos.y, z= newz}, {name = newnode})
56 | end
57 | end
58 | --say(serialize(event))
59 | end
--------------------------------------------------------------------------------
/scripts/games/simple_layout_gen.lua:
--------------------------------------------------------------------------------
1 | if not data then
2 | m=50;n=50; minescount = m*n/10;
3 |
4 | t0 = _G.minetest.get_gametime();
5 | data = {}; spawnpos = self.spawnpos();
6 | for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
7 |
8 | get_mine_count = function(i,j)
9 | if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
10 | for k = -1,1 do for l = -1,1 do
11 | if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
12 | end end
13 | return count
14 | end
15 |
16 | for i = 1,m do for j = 1,n do
17 | if get_mine_count(i,j) > 0 or (data[i] and data[i][j] == 1) then
18 | _G.minetest.swap_node({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}, {name = "basic_robot:buttonFFFFFF"})
19 | else
20 | _G.minetest.swap_node({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}, {name = "default:dirt"})
21 | end
22 | end end
23 | end
24 | self.remove()
--------------------------------------------------------------------------------
/scripts/games/sliding_puzzle_game.lua:
--------------------------------------------------------------------------------
1 | -- sliding unscramble game by rnd, made in 20 minutes
2 | if not init then
3 | reward = "default:gold_ingot"
4 | size = 3;
5 |
6 | init = true
7 | spos = self.spawnpos(); spos.y = spos.y + 1
8 | board = {};
9 | local players = find_player(4);
10 | if not players then say("#sliding puzzle game: no players") self.remove() end
11 | name = players[1];
12 |
13 | minetest.chat_send_player(name, "#SLIDING GAME: try to sort numbers in increasing order, starting from top left")
14 |
15 | create_board = function(n)
16 | local k = 0;
17 | local ret = scramble(n*n, os.time())
18 | for i = 1,n do
19 | board[i]={};
20 | for j = 1,n do
21 | k=k+1
22 | board[i][j]=17+ret[k] -- 7 numbers, 82 letters
23 | end
24 | end
25 | board[math.random(n)][math.random(n)] = 0
26 | end
27 |
28 | render_board = function()
29 | local n = #board;
30 | for i = 1,n do
31 | for j = 1,n do
32 | keyboard.set({x=spos.x+i, y = spos.y, z=spos.z+j}, board[i][j])
33 | end
34 | end
35 | end
36 |
37 | check_score = function() -- check how many places are increasing in order, starting top left
38 | local n = #board;
39 | local cmax = 0;
40 | local score = 0;
41 | for j = n,1,-1 do
42 | for i = 1,n do
43 | local b = board[i][j];
44 | if b==0 or b1 and board[i-1][j] == 0 then return i-1,j end
53 | if i<#board and board[i+1][j] == 0 then return i+1,j end
54 | if j>1 and board[i][j-1] == 0 then return i,j-1 end
55 | if j<#board and board[i][j+1] == 0 then return i,j+1 end
56 | return nil
57 | end
58 |
59 |
60 | scramble = function(n,seed)
61 | _G.math.randomseed(seed);
62 | local ret = {}; for i = 1,n do ret[i]=i end
63 | for j = n,2,-1 do
64 | local k = math.random(j);
65 | if k~=j then
66 | local tmp = ret[k]; ret[k] = ret[j]; ret[j] = tmp
67 | end
68 | end
69 | return ret
70 | end
71 |
72 | create_board(size)
73 | render_board()
74 | self.listen_punch(self.pos()) -- attach punch listener
75 |
76 | end
77 |
78 | event = keyboard.get();
79 | if event and event.y == spos.y then
80 | local x = event.x-spos.x;
81 | local z = event.z-spos.z;
82 | if x<1 or x>size or z<1 or z>size then
83 | else
84 | local i,j = find_hole(x,z);
85 | if i then
86 | local tmp = board[x][z];
87 | keyboard.set({x=spos.x+x, y = spos.y, z=spos.z+z}, board[i][j])
88 | board[x][z] = board[i][j]
89 | board[i][j] = tmp;
90 | keyboard.set({x=spos.x+i, y = spos.y, z=spos.z+j}, tmp)
91 | end
92 | local score = check_score()
93 | self.label("score : " .. score)
94 | if score >= size*size-2 then
95 | minetest.chat_send_player(name, "CONGRATULATIONS! YOU SOLVED PUZZLE. REWARD WAS DROPPED ON TOP OF ROBOT.")
96 | pos = self.pos(); pos.y = pos.y+2;
97 | minetest.add_item(pos, _G.ItemStack(reward))
98 | self.remove()
99 | end
100 | end
101 |
102 | end
--------------------------------------------------------------------------------
/scripts/games/switching_game.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | SWITCHING GAME by rnd, 2018
3 |
4 | lights:
5 | 0110
6 |
7 | switches, each one toggles certain lights like: s1 1001 (toggles light with 1)
8 |
9 | PROBLEM:
10 | hit switches in correct order to turn on all lights
11 |
12 | GENERATE RANDOM CHALLENGE:
13 | start with all lights on and apply random sequence of switches
14 |
15 | TODO: instead of simply 0/1 switches have ones that advance +1 mod p (p can be say 3 or more)
16 |
17 |
18 | REMARKS: application of 2 different switches is commutative ( obvious, since just x->x+1 mod p)
19 | --]]
20 | if not init then
21 |
22 | init = true
23 | numlights = 2;
24 | numswitches = 2;
25 | states = 10;
26 |
27 | lights = {}; -- states of lights, initialy 1,1,...,1
28 | for i = 1, numlights do lights[i] = 0 end
29 | switches = {}
30 |
31 | --switches = {{1,0,0,1},{1,1,1,1}};
32 | make_random_switches = function(lights, switches,count)
33 | for i = 1, count do
34 | switches[i] = {};
35 | local switch = switches[i];
36 | for j = 1, #lights do switch[j] = math.random(states)-1 end
37 | end
38 | end
39 | make_random_switches(lights,switches, numswitches)
40 |
41 |
42 | pos = self.spawnpos(); pos.x = pos.x + 1;-- pos.z = pos.z + 1
43 |
44 | apply_switch = function(switches,lights,idx)
45 | local switch = switches[idx];
46 | for i = 1, #switch do
47 | local state = lights[i] + switch[i];
48 | if state >= states then state = state - states end
49 | lights[i] = state
50 | end
51 | end
52 |
53 | randomize = function(switches, lights, steps) -- randomize lights
54 | for i = 1, steps do
55 | local idx = math.random(#switches);
56 | apply_switch(switches,lights,idx);
57 | end
58 | end
59 |
60 | render_lights = function() for i = 1, #lights do keyboard.set({x=pos.x+i-1,y=pos.y+1, z=pos.z}, 7+lights[i]) end end
61 | render_switches = function(mode)
62 | if mode then
63 | for i = 1, #switches do keyboard.set({x=pos.x+i-1,y=pos.y, z=pos.z}, 1+i) end
64 | else
65 | for i = 1, #switches do keyboard.set({x=pos.x+i-1,y=pos.y, z=pos.z}, 0) end
66 | end
67 | end
68 |
69 | check_lights = function()
70 | for i = 1, #lights do if lights[i] ~= 0 then return false end end
71 | return true
72 | end
73 | step = 0
74 |
75 | randomize(switches,lights, math.min((#switches)^states,10000))
76 | if check_lights() then randomize(switches,lights, #switches + states) end
77 |
78 | render_lights(); render_switches(true)
79 |
80 |
81 | self.label("GOAL OF GAME: punch buttons with numbers in correct order to turn all blocks to 0")
82 | self.listen_punch(self.pos()) -- attach punch listener
83 |
84 | --self.label(serialize(switches))
85 | end
86 |
87 |
88 | event = keyboard.get()
89 | if event then
90 | local idx = event.x-pos.x+1;
91 | if event.y==pos.y and idx>=1 and idx <= #switches then
92 | apply_switch(switches, lights, idx)
93 | render_lights()
94 | step = step + 1
95 | if check_lights() then
96 | self.label("DONE IN " .. step .. " STEPS !")
97 | render_switches(false)
98 | else
99 | self.label("STEP " .. step)
100 | end
101 | end
102 | end
--------------------------------------------------------------------------------
/scripts/games/tank_bot.lua:
--------------------------------------------------------------------------------
1 | -- rnd 2017
2 | -- instructions: put 7 buttons around bot(top one left empty)
3 | -- clockwise: empty, green, yellow,blue, red, blue,yellow,green.
4 | -- those buttons serve as controls
5 |
6 | if not s then
7 | name = self.name();
8 | direction = 1;
9 | s=0;
10 | self.label("TANK ROBOT. control with colored buttons")
11 | user=find_player(4); if user then user = user[1] end
12 |
13 | speed = 7 + math.random(7);turn.angle(math.random(360));
14 | pitch = 0
15 |
16 | gravity = 1+math.random(2);
17 | if user then
18 | say("TANK ROBOT, ready. ".. user .. " in control")
19 | else
20 | say("no player found nearby. deactivating"); self.remove()
21 | s=-1
22 | end
23 | pos = self.spawnpos();
24 | end
25 |
26 | ppos = player.getpos(user); ppos.x=ppos.x-pos.x;ppos.y=ppos.y-pos.y;ppos.z=ppos.z-pos.z;
27 | if ppos.x^2+ppos.y^2+ppos.z^2>10 then
28 | local obj = _G.minetest.get_player_by_name(user);
29 | if obj then say("deserter " .. user .. " killed for abandoning the tank!") obj:set_hp(0) end
30 | self.remove()
31 | else
32 | local obj = _G.minetest.get_player_by_name(user);
33 | if obj then
34 | if obj:get_hp() == 0 then
35 | say("TANK DESTROYED!")
36 | self.remove()
37 | end
38 | end
39 | end
40 |
41 | if s == 0 then
42 | event = keyboard.get();
43 | if event and event.puncher==user then
44 | --self.label(event.x-pos.x .. " " .. event.y-pos.y .. " " .. event.z-pos.z .. " T " .. event.type)
45 | event.x = event.x-pos.x;event.y = event.y-pos.y;event.z = event.z-pos.z;
46 | if event.x == 0 and event.y == 0 and event.z == 1 then
47 | self.fire(speed, pitch,gravity)
48 | s=1;self.label("BOOM")
49 | _G.minetest.sound_play("tnt_explode",{pos = self.pos(), max_hear_distance = 256, gain = 1})
50 | elseif event.x == direction*1 and event.y == 0 and event.z == direction*1 then
51 | turn.angle(2)
52 | elseif event.x == -1*direction and event.y == 0 and event.z == 1*direction then
53 | turn.angle(-2)
54 | elseif event.x == 1*direction and event.y == 0 and event.z == 0 then
55 | turn.angle(40)
56 | elseif event.x == -1*direction and event.y == 0 and event.z == 0 then
57 | turn.angle(-40)
58 | elseif event.x == 1*direction and event.y == 0 and event.z == -1*direction then
59 | pitch = pitch + 5; if pitch> 85 then pitch = 85 end
60 | self.label("pitch " .. pitch)
61 | elseif event.x == -1*direction and event.y == 0 and event.z == -1*direction then
62 | pitch = pitch - 5; if pitch<-10 then pitch = -10 end
63 | self.label("pitch " .. pitch)
64 | end
65 | end
66 | end
67 |
68 | if s == 1 then
69 | local pos = self.fire_pos();
70 | if pos then
71 | self.label("HIT")
72 | msg = "";
73 | _G.minetest.sound_play("tnt_explode",{pos = pos, max_hear_distance = 256, gain = 1})
74 |
75 | local objs=_G.minetest.get_objects_inside_radius(pos, 4);
76 | for _,obj in pairs(objs) do
77 | if obj:is_player() then
78 | obj:set_hp(0)
79 | msg = msg .. obj:get_player_name() .. " is dead, "
80 | end
81 | end
82 | s = 0
83 | if msg~="" then say(msg) end
84 | end
85 | end
--------------------------------------------------------------------------------
/scripts/graphics/painting_import.lua:
--------------------------------------------------------------------------------
1 | -- painting import from minetest 'painting mod' to robot canvas by rnd
2 | -- stand near image and run "get_texture()" command in remote control
3 |
4 | if not init then
5 | self.label("PAINTING IMPORTER")
6 | pname = "rnd"
7 | player = minetest.get_player_by_name(pname)
8 |
9 | get_texture = function()
10 |
11 |
12 | local pos = player:get_pos(); local radius = 2
13 | local objs = minetest.get_objects_inside_radius(pos, radius)
14 | local obj = {};
15 |
16 | local ret = {};
17 | for i=1,#objs do
18 | if not objs[i]:is_player() then obj = objs[i] break end
19 | end
20 |
21 | if obj then
22 | local tex = obj:get_properties().textures
23 | local out = tex[1] or ""
24 | if string.sub(out,1,9) == "[combine:" then
25 | local pcolors = {"black","blue","brown","cyan","darkgreen","darkgrey","green","grey",
26 | "magenta","orange","pink","red","violet","white","yellow"}
27 | local ipcolors = {}; for i = 1,#pcolors do ipcolors[pcolors[i]] = i end
28 |
29 | local ret = {};
30 | local i =0; local j = 1; local k = 0; local size = 16;
31 | --ret[1] = {}
32 | for word in out:gmatch("=(%a+)%.png") do
33 | ret[#ret+1] = string.char(96 + (ipcolors[word] or 1))
34 | end
35 |
36 | local rret = {};
37 | for i = 1, size do rret[i] = {} for j = 1,size do rret[i][j] = 0 end end
38 |
39 | k = 0 -- rotate 90 right
40 | for j = 1,size do
41 | for i = size,1,-1 do
42 | k = k + 1
43 | rret[size-i+1][size-j+1] = ret[k]
44 | end
45 | end
46 |
47 | ret = {}; for i = 1, size do for j = 1, size do ret[#ret+1]= rret[i][j] end end -- write back
48 |
49 | out = table.concat(ret,"")
50 | book.write(1,"IMPORTED_PAINTING", out)
51 | minetest.chat_send_player(pname, "PAINTING FOUND, saved in robot library in book 1.")
52 | end
53 | else return "empty"
54 | end
55 | end
56 |
57 | init = true
58 | end
--------------------------------------------------------------------------------
/scripts/gui/file_manager.lua:
--------------------------------------------------------------------------------
1 | -- file 'manager' by rnd
2 |
3 | if not init then
4 | fmver = "2018/12/09"
5 | local players = find_player(4);
6 | if not players then self.remove() end
7 | pname = players[1];
8 | size = 8;
9 | vsize = 6.5;
10 |
11 | path = "/";
12 | pathlist = {}
13 | folderlist = {};
14 | filelist = {};
15 |
16 | render_page = function()
17 | local foldlist = minetest.get_dir_list(path,true) -- only folders
18 | if foldlist then folderlist = foldlist else folderlist = {} end
19 | for i = 1,#foldlist do foldlist[i] = "*"..foldlist[i] end
20 | foldlist[#foldlist+1] = "*.."
21 | local fillist = minetest.get_dir_list(path,false)
22 | if fillist then filelist = fillist else filelist = {} end
23 | local content = table.concat(folderlist,",") .. ",-------------------," .. table.concat(filelist,",")
24 | return "size[" .. size .. "," .. size .. "] label[0,-0.25;ROBOT FILE MANAGER " .. fmver .. " by rnd\nPATH " .. minetest.formspec_escape(path) .. "] textlist[-0.25,0.75;" .. (size+1) .. "," .. (vsize+1) .. ";wiki;".. content .. ";1]";
25 | end
26 |
27 | page = {}
28 | self.show_form(pname,render_page())
29 | init = true
30 | self.read_form()
31 | end
32 |
33 | sender,fields = self.read_form()
34 | if sender then
35 | local fsel = fields.wiki;
36 | if fsel and string.sub(fsel,1,3) == "DCL" then
37 | local sel = tonumber(string.sub(fsel,5)) or 1; -- selected line
38 | local fold = folderlist[sel];
39 | if fold and string.sub(fold,1,1) == "*" then
40 | if fold == "*.." then -- go back
41 | if #pathlist>0 then
42 | local i = string.len(pathlist[#pathlist]);
43 | if i>0 then
44 | pathlist[#pathlist] = nil
45 | path = string.sub(path,1,-i-2);
46 | end
47 | end
48 | else
49 | pathlist[#pathlist+1] = string.sub(fold,2)
50 | path = path .. "/".. pathlist[#pathlist]
51 | end
52 |
53 | self.show_form(pname,render_page())
54 | end
55 | end
56 | --self.label(fsel);
57 | end
--------------------------------------------------------------------------------
/scripts/gui/gui_2player_coop_edit.lua:
--------------------------------------------------------------------------------
1 | -- gui demo by rnd
2 | -- 2 player cooperative editing of image with 2 colors
3 |
4 | if not init then
5 | _G.basic_robot.data[self.name()].obj:get_luaentity().timestep = 0.25
6 | init = true
7 | name = "rnd"
8 | otherrobotname = "rnd2" -- on other robot do name of this robot
9 | drawcolor = 3; -- other robot has reversed colors
10 | otherdrawcolor = 4
11 |
12 | color = {"black","white","blue","green"}
13 | data = {};
14 | n = 20;
15 |
16 | for i = 1,n do
17 | data[i]={};
18 | --local y = math.floor(f(i));
19 | for j = 1,n do
20 | data[i][j] = 1--(n-j>y) and 2 or 1
21 | end
22 | end
23 |
24 | get_form = function()
25 | local form = "size[10,10] "; ret = {};
26 |
27 | for i = 1,n do
28 | for j = 1,n do
29 | ret[#ret+1] = "image_button["..((i-1)*0.5)..","..((j-1)*0.5)..";0.7,0.63;wool_"..color[data[i][j]]..".png;"..((i-1)*n+j-1) .. ";] "
30 | end
31 | end
32 | return form .. table.concat(ret,"")
33 | end
34 |
35 | self.show_form(name,get_form())
36 | self.read_form()
37 | end
38 |
39 | sender,mail = self.read_mail()
40 | if mail then
41 | local x = mail[1]; local y = mail[2];
42 | if data[x][y]==1 then data[x][y] = otherdrawcolor else data[x][y] = 1 end
43 | self.show_form(name,get_form())
44 | end
45 |
46 | sender,fields = self.read_form()
47 | if fields then
48 | if fields.quit then self.remove() end
49 | local sel = 0;
50 | for k,v in pairs(fields) do
51 | if k ~="quit" then sel = tonumber(k); break end
52 | end
53 | local x = 1+math.floor(sel/n); local y = 1+sel % n;
54 | if data[x][y]==1 then data[x][y] = drawcolor else data[x][y] = 1 end
55 | self.send_mail(otherrobotname,{x,y})
56 | self.show_form(name,get_form())
57 | end
--------------------------------------------------------------------------------
/scripts/gui/gui_deposit_withdraw_demo.lua:
--------------------------------------------------------------------------------
1 |
2 | if not init then init = true
3 |
4 | deposit = function(pname)
5 | _, text = book.read(1);
6 | local data = deserialize(text) or {};
7 |
8 | local player = _G.minetest.get_player_by_name(pname)
9 | local inv = player:get_inventory();
10 | local pstack = inv:get_stack("main", 1);
11 | local iname = pstack:to_string()
12 |
13 |
14 | item, count = _G.string.match(iname,"(%S+)%s?(%d*)");
15 | item = item or "";if item == "" then return end
16 |
17 | count = tonumber(count) or 1;
18 |
19 | --say("item " .. item .. ", count " .. count)
20 |
21 | data[pname] = data[pname] or {};
22 | local pdata = data[pname];
23 |
24 | pdata[item] = pdata[item] or {};
25 |
26 | local t = minetest.get_gametime()
27 | pdata[item][1] = (pdata[item][1] or 0) + count
28 | pdata[item][2] = t;
29 |
30 | inv:set_stack("main", 1, _G.ItemStack(""))
31 |
32 | book.write(1,"",serialize(data))
33 | local form = "size [5,5] label[0,0; You deposited " .. item .. "( " .. count .. " pieces)]"
34 | self.show_form(pname, form)
35 | --say(pname .. " deposited " .. item .. "( " .. count .. " pieces) ")
36 | end
37 |
38 | check = function(pname)
39 | _, text = book.read(1);
40 | local data = deserialize(text) or {};
41 | data[pname] = data[pname] or {};
42 |
43 | --say(serialize(data[pname]))
44 | return serialize(data[pname])
45 | end
46 |
47 | withdraw = function(pname)
48 | _, text = book.read(1);
49 | local data = deserialize(text) or {};
50 | data[pname] = data[pname] or {};
51 |
52 | local player = _G.minetest.get_player_by_name(pname)
53 | local inv = player:get_inventory();
54 | local pdata = data[pname]
55 | local t0 = minetest.get_gametime();
56 |
57 | for k,v in pairs(pdata) do
58 | local t = t0 - v[2]; -- time since last deposit
59 | local a = (1+interests/100)^t;
60 | self.label("deposited time " .. t .. ", deposited quantity " .. v[1] .. ", new quantity : " .. math.floor(a*tonumber(v[1])) )
61 | inv:add_item("main", _G.ItemStack(k .. " " .. math.floor(a*tonumber(v[1]))) )
62 | end
63 | data[pname] = nil;
64 | book.write(1,"",serialize(data))
65 | end
66 |
67 |
68 | function show(pname)
69 | local itemlist = check(pname)
70 | local form = "size [5,5] button[0,0;2,1;DEPOSIT;DEPOSIT] button[0,1;2,1;WITHDRAW;WITHDRAW]" ..
71 | "textarea[0,2.5;6,3;STORAGE;YOUR DEPOSITS;" .. minetest.formspec_escape(itemlist) .. "]"
72 | self.show_form(pname, form)
73 | end
74 |
75 |
76 | interests = 5; -- interest rate per second (demo)
77 | local players = find_player(4)
78 | if not players then self.remove() end
79 | show(players[1])
80 |
81 | end
82 |
83 | sender,fields = self.read_form()
84 | if sender then
85 | if fields.DEPOSIT then
86 | deposit(sender)
87 | show(sender)
88 | elseif fields.WITHDRAW then
89 | withdraw(sender)
90 | show(sender)
91 | end
92 |
93 | --say(sender .. " clicked " .. serialize(fields))
94 | end
--------------------------------------------------------------------------------
/scripts/gui/gui_interact_demo_board.lua:
--------------------------------------------------------------------------------
1 | -- gui demo by rnd
2 |
3 | if not init then
4 | init = true
5 | name = "rnd"
6 | color = {"white","black"}
7 | data = {};
8 | n = 20;
9 |
10 | f = function(x) return 7*(1+math.sin(x/2)) end
11 |
12 | for i = 1,n do
13 | data[i]={};
14 | local y = math.floor(f(i));
15 | for j = 1,n do
16 | data[i][j] = (n-j>y) and 2 or 1
17 | end
18 | end
19 |
20 | get_form = function()
21 | local form = "size[10,10] "; ret = {};
22 |
23 | for i = 1,n do
24 | for j = 1,n do
25 | ret[#ret+1] = "image_button["..((i-1)*0.5)..","..((j-1)*0.5)..";0.7,0.63;wool_"..color[data[i][j]]..".png;"..((i-1)*n+j-1) .. ";] "
26 | end
27 | end
28 | return form .. table.concat(ret,"")
29 | end
30 |
31 | self.show_form(name,get_form())
32 | self.read_form()
33 | end
34 |
35 | sender,fields = self.read_form()
36 | if fields then
37 | if fields.quit then self.remove() end
38 | local sel = 0;
39 | for k,v in pairs(fields) do
40 | if k ~="quit" then sel = tonumber(k); break end
41 | end
42 | local x = 1+math.floor(sel/n); local y = 1+sel % n;
43 | data[x][y] = 3 - data[x][y]
44 | --self.label(x .. " " .. y)
45 | self.show_form(name,get_form())
46 | end
--------------------------------------------------------------------------------
/scripts/gui/scrolling_inventory.lua:
--------------------------------------------------------------------------------
1 | if not init then
2 | text = " hello world "
3 | name = "rnd"
4 | m = 8;
5 | idx = 0;
6 | n = string.len(text)
7 |
8 | player = puzzle.get_player(name)
9 | inv = player:get_inventory()
10 | inv:set_list("main",{})
11 | init = true
12 |
13 | end
14 |
15 | for i = 1, m do
16 | local j = (idx+i)%n + 1
17 | local c = string.byte(text,j)-97;
18 | if c<0 or c>30 then c = -97 end
19 | inv:set_stack("main", i,puzzle.ItemStack("basic_robot:button_" ..(97+c)))
20 | end
21 |
22 | idx = (idx + 1) % n
23 | --self.remove()
--------------------------------------------------------------------------------
/scripts/gui/wiki.lua:
--------------------------------------------------------------------------------
1 | -- ROBOT WIKI by rnd
2 | -- to do: ability for multiple links in 1 line
3 |
4 |
5 | if not init then
6 | _G.basic_robot.data[self.name()].obj:get_luaentity().timestep = 0.1
7 | local players = find_player(4);
8 | if not players then self.remove() end
9 | pname = players[1];
10 | size = 8;
11 | vsize = 8;
12 | linesize = 60; -- break up longer lines
13 |
14 | wiki = { -- example of wiki pages
15 | ["MAIN PAGE"] =
16 | {
17 | "-- WIKI CONTENTS -- ", "",
18 | "double click link marked with [] or press enter while selected.","",
19 | "[Viewing wiki]",
20 | "[Editing wiki]"
21 | },
22 |
23 | ["Viewing wiki"] = {
24 | "back to [MAIN PAGE]","",
25 | " ** Viewing wiki",
26 | "double click link marked with [] or press enter while selected."
27 | },
28 |
29 | ["Editing wiki"] = {
30 | "back to [MAIN PAGE]","",
31 | " ** Editing wiki",
32 | "Edit wiki table and write in entries"
33 | }
34 | }
35 |
36 | for k,v in pairs(wiki) do
37 | local pages = wiki[k]; for i = 1,#pages do pages[i] = minetest.formspec_escape(pages[i]) end
38 | end
39 |
40 |
41 | current = "MAIN PAGE";
42 |
43 | render_page = function()
44 | local content = table.concat(wiki[current],",")
45 | return "size[" .. size .. "," .. size .. "] textlist[-0.25,-0.25;" .. (size+1) .. "," .. (vsize+1) .. ";wiki;".. content .. ";1]";
46 | end
47 |
48 | page = {}
49 | self.show_form(pname,render_page())
50 | init = true
51 | end
52 |
53 | sender,fields = self.read_form()
54 | if sender then
55 | local fsel = fields.wiki;
56 | if fsel and string.sub(fsel,1,3) == "DCL" then
57 | local sel = tonumber(string.sub(fsel,5)) or 1; -- selected line
58 | local address = current or "main";
59 | local pages = wiki[address];
60 |
61 | local link = _G.string.match(pages[sel] or "", "\\%[([%w%s]+)\\%]")
62 | if wiki[link] then
63 | current = link;
64 | self.show_form(pname,render_page())
65 | --robot_show_help(name)
66 | end
67 | end
68 | end
--------------------------------------------------------------------------------
/scripts/hash_table_implementation.lua:
--------------------------------------------------------------------------------
1 | if not get_hash then
2 |
3 | get_hash = function(s,p)
4 | if not s then return end
5 | local h = 0; local n = string.len(s);local m = 4; -- put 4 characters together
6 | local r = 0;local i = 0;
7 | while i maxlen then maxlen = length; maxidx = i end
43 | count = count + 1
44 | end
45 | end
46 |
47 | if maxlen>0 then
48 | local data = hashdb[maxidx];
49 | say("number of used hash entries is " .. count .. ", average " .. (step/count) .. " entries per hash, "..
50 | " max length of list is " .. maxlen .. " at hash ".. maxidx )--.. " : " ..
51 | --string.gsub(_G.dump(data),"\n","") )
52 |
53 | end
54 | end
55 |
56 | -- LOAD DICTIONARY WORDS into hashtable
57 |
58 | lang = "german"
59 |
60 | fname = "F:\\games\\rpg\\minetest-0415server\\mods\\basic_translate\\"..lang;
61 | local f = _G.assert(_G.io.open(fname, "r"));local dicts = f:read("*all");f:close()
62 |
63 | step = 0; maxwords = 10000;
64 | i=0
65 | dict = {}; -- for comparison
66 |
67 | while(step {
24 | res.statusCode = 200;
25 | res.setHeader('Content-Type', 'text/plain');
26 |
27 | var msg = req.url;
28 | if (msg == '/favicon.ico') return // prevent passing this as request
29 |
30 |
31 | var pos = msg.indexOf("/",1); // gets the 2nd / in /part1/part2/...
32 | var cmd = msg.substring(1,pos);
33 | var response = ""
34 | var ip = req.connection.remoteAddress;
35 |
36 | switch(cmd)
37 | {
38 | case "mtmsg":
39 | response = msg.substring(pos+1);
40 | mtreq = response
41 | break
42 | case "getmtmsg":
43 | response = mtreq; mtreq = ''
44 | break
45 | case "getwebmsg":
46 | response = webreq; webreq = ''
47 | break
48 | case "webmsg":
49 | webreq = ip + ' ' + msg.substring(pos+1);
50 | response = 'request received: ' + webreq + '\nuse /getmtmsg to view response from minetest'
51 | break
52 | default:
53 | response = 'INSTRUCTIONS. url options:\n'+
54 | '1./mtmsg/msg will store msg as message received from minetest ( minetest_message). note that msg cant contain spaces or newlines\n'+
55 | '2./getwebmsg/ will reply = IP + " " + webmessage\n'+
56 | '3./webmsg/msg will store message as webmessage\n'+
57 | '4./getmtmsg will reply with minetest_message\n'
58 | }
59 |
60 | if (msg!='' && cmd != 'getwebmsg') console.log('ip ' + ip + ', msg ' + msg)
61 | res.write(response); res.end()
62 | return
63 | });
64 |
65 | // make server listen
66 | server.listen(port, hostname, () => {
67 | console.log(`Server running at http://${hostname}:${port}/`);
68 | });
--------------------------------------------------------------------------------
/scripts/http/webcommands/webcommands.lua:
--------------------------------------------------------------------------------
1 | -- webcommands : access url like: 192.168.0.10/hello_world
2 |
3 | --[[ instructions:
4 | 1.download nodejs server from
5 | https://nodejs.org/dist/v10.14.2/node-v10.14.2-win-x86.zip
6 | 2. run nodejs server using run.bat
7 | :loop
8 | node $path/minetest_webcommands.js
9 | goto loop
10 | 3. run robot and type 'http://192.168.0.10/webmsg/hello this is a test' into browser
11 | (you need to write your router address here, i.e. ip accessible from internet OR lan address)
12 | --]]
13 |
14 | if not fetch then
15 | address = "192.168.0.10";
16 | fetch = _G.basic_robot.http_api.fetch;
17 | state = 0 -- ready to fetch new command
18 | -- WARNING: this is run outside pcall and can crash server if errors!
19 | result = function(res) -- res.data is string containing result
20 | state = 0
21 | if not res.succeeded then self.label("#ERROR: data couldn't be downloaded :\n" .. minetest.serialize(res) ) return end
22 | if res.data == "" then return end
23 | local req = res.data; req = string.gsub(req,"%%20"," ")
24 | if res.data then
25 | self.label(os.date("%X") ..', cmd : ' .. req)
26 | local i = string.find(req," !")
27 | if i then
28 | run_commmand(string.sub(req,i+2))
29 | end
30 | end
31 | end
32 |
33 | admin = minetest.setting_get("name")
34 | run_commmand = function(message)
35 | local cmd, param = _G.string.match(message, "([^ ]+) *(.*)")
36 | if not param then
37 | param = ""
38 | end
39 | local cmd_def = minetest.chatcommands[cmd]
40 | if cmd_def then
41 | cmd_def.func(admin, param)
42 | else
43 | minetest.chat_send_all(admin..": "..message)
44 | end
45 | end
46 |
47 | MT2web = function(message)
48 | message = string.gsub(message," ","%%20") -- NOTE: if you send request that has 'space' in it there will be error 400!
49 | fetch({url = "http://".. address .. "/mtmsg/"..message, timeout = 5}, result)
50 | end
51 | MT2web("minetest robot started and listening.")
52 | end
53 |
54 |
55 |
56 | if state == 0 then
57 | fetch({url = "http://"..address.."/getwebmsg/", timeout = 5}, result)
58 | state = 1
59 | end
--------------------------------------------------------------------------------
/scripts/math/calender.lua:
--------------------------------------------------------------------------------
1 | -- calender by rnd, 30 minutes with bugfixes
2 |
3 | dayofweek = function(y,m,d)
4 | local offsets = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
5 | if m<3 then y=y-1 end
6 | return (y+math.floor(y/4)-math.floor(y/100)+math.floor(y/400)+offsets[m]+d) % 7+1
7 | end
8 |
9 | y=2000
10 | m=8
11 | d=1
12 | --say(dayofweek(y,m,d))
13 |
14 |
15 |
16 | make_calender = function(y,m)
17 | local start_day = dayofweek(y,m,1)
18 | local months = {31,29,31,30,31,30,31,31,30,31,30,31};
19 | if y%4==0 and (y%100~=0 or y%400 == 0) then months[2]= 30 end -- feb has 30 days on leap year
20 | local out = minetest.colorize("red",m.."/"..y).."\nsun mon tue wed thu fri sat\n"
21 | out = out .. string.rep("__ ",start_day-1)
22 | local i = start_day;
23 | local idx = 1;
24 | while idx<=months[m] do
25 | out = out .. string.format("%02d",idx) .. " ";
26 | if i%7 ==0 then out = out .."\n" end
27 | idx = idx+1
28 | i=i+1
29 | end
30 |
31 |
32 | return out
33 | end
34 |
35 | ret = {}
36 | for m = 1,12 do
37 | ret[#ret+1]=make_calender(y,m)
38 | end
39 |
40 | self.label(table.concat(ret,"\n\n"))
--------------------------------------------------------------------------------
/scripts/math/fractal_bot.lua:
--------------------------------------------------------------------------------
1 | -- robot can construct classic fractals like menger sponge, jerusalem cube, sierpinski triangles,..
2 | -- use: build a pattern at position 1,1,1 relative to robot. when run robot will analyse pattern and construct fractal
3 | if not init then
4 | minetest.forceload_block(self.pos(),true)
5 | init = true; local spos = self.spawnpos();
6 |
7 | offsets = {["default:dirt"] = 0, ["default:wood"] = -1, ["default:cobble"] = 1}
8 |
9 | read_form = function(fractal) -- read shape from world
10 | local form = {}; local i = 0;
11 | local spos = self.spawnpos(); spos.x = spos.x+1;spos.y = spos.y+1;spos.z = spos.z+1;
12 | local nx = 0; local ny = 0; local nz = 0;
13 | fractal.form = {}
14 |
15 | for x = 0,fractal.nx-1 do
16 | for y = 0,fractal.ny-1 do
17 | for z = 0,fractal.nz-1 do
18 | local node = _G.minetest.get_node({x=spos.x+x,y=spos.y+y,z=spos.z+z}).name;
19 | local offset = offsets[node] or 0;
20 | if node~= "air" then
21 | form[i] = {x,y,z,offset}; i=i+1
22 | if nx1 then return -1 end
27 |
28 | local zrn=zr^2-zi^2+cr;
29 | local zin=2*zr*zi+ci
30 | if (zrn-zr)^2+(zin-zi)^2< delta then return 1 end
31 |
32 | for i = 1, itermax do
33 | local zrn=zr^2-zi^2+cr;
34 | local zin=2*zr*zi+ci
35 | if (zrn-zr)^2+(zin-zi)^2< delta then return i-1 end
36 | zr=zrn
37 | zi=zin
38 | end
39 | return itermax-1
40 | end
41 |
42 | pos = self.pos()
43 | local nnodes = #nodes
44 | for x=1,n do
45 | for y=1,n do
46 | cr=2*x/n-1; ci=2*y/n-1
47 | local col = get_pixel()
48 | if col>0 then
49 | col = math.floor(nnodes*col/itermax)
50 | minetest.swap_node({x=pos.x+x,y=pos.y,z=pos.z+y},{name = nodes[col+1]})
51 | end
52 | end
53 | end
54 |
55 | self.remove()
56 |
57 | end
58 |
59 |
60 |
--------------------------------------------------------------------------------
/scripts/math/perm2cycles.lua:
--------------------------------------------------------------------------------
1 | if not perm2cycles then
2 |
3 | perm2cycles = function(perm)
4 | local n = #perm;
5 | local i = 1; -- already reached number
6 | local ret = {};
7 | local visited = {};
8 | local step = 0;
9 |
10 | while (true) do
11 | local cycle = {i}
12 | local j=i;
13 |
14 | while (true) do
15 | step = step +1
16 | if step > 2*n then return {} end
17 | j=perm[j];
18 | visited[j] = 1;
19 | if j and j~=cycle[1] then cycle[#cycle+1]=j else break end
20 | end
21 |
22 | i=n+1;
23 | for k=1,n do -- find smallest non visited yet
24 | if not visited[k] and k cycles = " .. arr2string(cycles) )
82 |
83 | end
--------------------------------------------------------------------------------
/scripts/messenger.lua:
--------------------------------------------------------------------------------
1 | if not s then
2 | s=0
3 | msgsize = 2500;
4 | _,text = book.read(1);text = text or "";
5 | write_msg = function(sender,msg)
6 |
7 | local newsize = string.len(text)+string.len(msg);
8 | if newsize>msgsize then return "messages space exceeded" end
9 | text = text .. "\n"..os.date() .. " " .. sender .. ": " .. msg;
10 | book.write(1,"messages",text)
11 | end
12 |
13 | end
14 |
15 | --textarea[X,Y;W,H;name;label;default]
16 | --button[X,Y;W,H;name;label]
17 | if s == 0 then
18 | players = find_player(4);
19 | if players and players[1] then
20 | s=1
21 | local form = "size[8,4.5]" ..
22 | "textarea[0,0;9,4.5;msg;MESSAGE FOR ADMIN;]"..
23 | "button_exit[-0.5,4.15;2,1;send;send]"
24 | self.show_form(players[1],form)
25 | end
26 | elseif s==1 then
27 | sender,fields = self.read_form();
28 | if sender then
29 | if fields.send then
30 | msg = fields.msg;
31 | if msg and msg~="" then
32 | write_msg(sender,msg);activate.up(1)
33 | _G.minetest.chat_send_player(sender,"#mailbot: message has been stored")
34 | end
35 | end
36 | self.remove()
37 | end
38 | end
--------------------------------------------------------------------------------
/scripts/minesweeper.lua:
--------------------------------------------------------------------------------
1 | if not data then
2 | m=10;n=10; minescount = 32;
3 |
4 | t0 = _G.minetest.get_gametime();
5 | data = {}; spawnpos = self.spawnpos() -- place mines
6 | for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
7 | if not data[1] then data[1] = {} end if not data[2] then data[2] = {} end -- create 2x2 safe area
8 | data[1][1] = 0;data[1][2] = 0;data[2][1] = 0;data[2][2] = 0;
9 |
10 | minescount = 0;
11 | for i = 1,m do for j = 1,n do -- render game
12 | if data[i] and data[i][j] == 1 then minescount = minescount + 1 end
13 | if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:button808080" then
14 | keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},2)
15 | end
16 | end end
17 | keyboard.set({x=spawnpos.x+1,y=spawnpos.y,z=spawnpos.z+1},4) -- safe start spot
18 | get_mine_count = function(i,j)
19 | if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
20 | for k = -1,1 do for l = -1,1 do
21 | if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
22 | end end
23 | return count
24 | end
25 | chk_mines = function()
26 | local count = minescount;
27 | for i=1,m do for j=1,n do
28 | if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})=="basic_robot:buttonFF8080" and data[i] and data[i][j]==1 then
29 | count=count-1
30 | end
31 | end end
32 | return count
33 | end
34 | say("minesweeper " .. m .. "x" ..n .. " with " .. minescount .. " mines ")
35 | self.label("find all hidden mines! mark mine by standing on top of block and punch,\notherwise it will uncover the block (and possibly explode).")
36 |
37 | end
38 |
39 | event = keyboard.get();
40 | if event then
41 | local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
42 | if x<1 or x>m or z<1 or z>n then
43 | if x == 0 and z == 1 then
44 | local count = chk_mines();
45 | if count == 0 then
46 | t0 = _G.minetest.get_gametime() - t0;
47 | say("congratulations! " .. event.puncher .. " discovered all mines in " .. t0 .. " s")
48 | _G.minetest.add_item({x=spawnpos.x,y=spawnpos.y+1,z=spawnpos.z},_G.itemstack("default:diamond 5")) -- diamond reward
49 | else
50 | say("FAIL! " .. count .. " mines remaining ")
51 | end
52 | self.remove()
53 | end
54 | elseif event.type == 2 then
55 | local ppos = player.getpos(event.puncher)
56 | if ppos and math.abs(ppos.x-event.x)<0.5 and math.abs(ppos.z-event.z)<0.5 then -- just mark mine
57 | if keyboard.read({x=event.x,y=event.y,z=event.z})~="basic_robot:button808080" then
58 | keyboard.set({x=event.x,y=event.y,z=event.z},2)
59 | else
60 | keyboard.set({x=event.x,y=event.y,z=event.z},3)
61 | end
62 | else
63 | if data[x] and data[x][z]==1 then
64 | say("boom! "..event.puncher .. " is dead ");keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},3);self.remove()
65 | else
66 | local count = get_mine_count(x,z);
67 | if count == 0 then keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4)
68 | else keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},7+count) end
69 | end
70 | end
71 | end
72 | end
--------------------------------------------------------------------------------
/scripts/misc/all_unicode_chars.lua:
--------------------------------------------------------------------------------
1 | --ALL UNICODE by rnd, 2021
2 |
3 | -- range to 32-1550, then 7400-10000
4 | --cyrillic 0410-042F: 1040-1071
5 | --cyrilic 0430-044F: 1072-1103
6 | if not init then init = true
7 |
8 | function utf8(decimal)
9 | local bytemarkers = { {0x7FF,192}, {0xFFFF,224}, {0x1FFFFF,240} }
10 | if decimal<128 then return string.char(decimal) end
11 | local charbytes = {}
12 | for bytes,vals in ipairs(bytemarkers) do
13 | if decimal<=vals[1] then
14 | for b=bytes+1,2,-1 do
15 | local mod = decimal%64
16 | decimal = (decimal-mod)/64
17 | charbytes[b] = string.char(128+mod)
18 | end
19 | charbytes[1] = string.char(vals[2]+decimal)
20 | break
21 | end
22 | end
23 | return table.concat(charbytes)
24 | end
25 |
26 | ret= {"ALL UNICODE\n0 = "}
27 |
28 | for i = 1550, 4000 do
29 | if i%25==0 then ret[#ret+1] = "\n"..(i).. " = " end
30 | ret[#ret+1] = utf8(i)
31 | end
32 | self.label(table.concat(ret))
33 |
34 |
35 | end
--------------------------------------------------------------------------------
/scripts/misc/charcoal_maker.lua:
--------------------------------------------------------------------------------
1 | -- coal maker mod idea in 30 minutes by rnd
2 | -- build dirt box around 3x3x3 area filled with wood, remove one boundary wood (lower one) and start fire there. start robot then!
3 |
4 | check_firebox = function(pos)
5 | local p = minetest.find_node_near(pos, 5, "fire:basic_flame") -- locate fire nearby!
6 | if not p or minetest.get_node(p).name ~= "fire:basic_flame" then say("light fire first!"); self.remove() end
7 | d=3; -- inner size of box, area filled with wood
8 | local dirs = {{-1,0,0},{1,0,0},{0,0,-1},{0,0,1}};local dir1,dir2; -- position of vertices on dirt box
9 | for i = 1,#dirs do
10 | local dir = dirs[i];
11 | if minetest.get_node({x=p.x+d*dir[1],y=p.y+d*dir[2],z=p.z+d*dir[3]}).name == "default:dirt" and
12 | minetest.get_node({x=p.x+(d-1)*dir[1],y=p.y+(d-1)*dir[2],z=p.z+(d-1)*dir[3]}).name == "default:wood" then dir2 = dirs[i]; break end
13 | end
14 | if not dir2 then say("error, place fire in correct place in correctly built dirt box!") self.remove() end
15 | dir1 = {dir2[3], dir2[2], -dir2[1]};
16 | local v1 = {x=p.x-(d-1)*dir1[1]-dir2[1],y=p.y-1,z=p.z-(d-1)*dir1[3]-dir2[3]}
17 | local v2 = {x=p.x+(d-1)*dir1[1]+(d)*dir2[1],y=p.y+d,z=p.z+(d-1)*dir1[3]+(d)*dir2[3]}
18 | local res = minetest.find_nodes_in_area(v1,v2,{"default:wood","default:dirt"},true);
19 | if (#(res["default:dirt"] or {})) == 97 and #(res["default:wood"] or {})==26 then
20 | say("all ok. making charcoal now!")
21 | minetest.swap_node(p,{name = "air"}) -- turn off fire!
22 | else say("fail! check that you built dirt box/wood correctly!")
23 | end
24 | end
25 |
26 | check_firebox(self.pos())
27 | self.remove()
--------------------------------------------------------------------------------
/scripts/misc/chat_board.lua:
--------------------------------------------------------------------------------
1 | -- simple chat board by rnd
2 | if not init then init = true
3 |
4 | pos = self.pos()
5 |
6 |
7 | write_text = function(text,size)
8 | for x=0,size-1 do
9 | for y = size-1,0,-1 do
10 | local c = (string.byte(text, (size-1-y)*size+(x+1)) or 32)-97
11 | puzzle.set_node({x=pos.x+x+1,y=pos.y+y,z=pos.z},{name = "basic_robot:button_"..(97+c)})
12 | end
13 | end
14 | end
15 |
16 | self.listen(1)
17 |
18 | end
19 |
20 | speaker,msg= self.listen_msg()
21 | if msg then
22 | write_text(msg,15)
23 | end
--------------------------------------------------------------------------------
/scripts/misc/compact_inventory.lua:
--------------------------------------------------------------------------------
1 | compact_inventory = function(item)
2 | local size = 32
3 | local count = 0
4 |
5 | for i = 1,size do
6 | local stringname = check_inventory.self("","main",i);
7 | local itemname, j = stringname:match("(%S+) (%d+)")
8 | if itemname == item then
9 | count = count + tonumber(j)
10 | end
11 | end
12 |
13 | say(string.format("total count of %s is %s",item,count))
14 |
15 | insert.forward(string.format("%s %s",item,count)) -- will join all items together
16 | end
--------------------------------------------------------------------------------
/scripts/misc/flower_gunnew 6.lua:
--------------------------------------------------------------------------------
1 | if not name then
2 | name = "rnd"
3 | player = minetest.get_player_by_name(name)
4 |
5 | texs = {
6 | "flowers_chrysanthemum_green.png",
7 | "flowers_dandelion_white.png",
8 | "flowers_dandelion_yellow.png",
9 | "flowers_geranium.png",
10 | "flowers_mushroom_brown.png",
11 | "flowers_mushroom_red.png",
12 | "flowers_rose.png",
13 | "flowers_tulip.png",
14 | "flowers_tulip_black.png",
15 | "flowers_viola.png",
16 | }
17 | local ent = _G.basic_robot.data[self.name()].obj:get_luaentity();
18 | ent.timestep = 0.25
19 | _G.minetest.forceload_block(self.pos(),true)
20 |
21 | add_part = function(pos)
22 | local vdir = player:get_look_dir()
23 | local speed = 8
24 | vdir.x=vdir.x*speed
25 | vdir.y=vdir.y*speed
26 | vdir.z=vdir.z*speed
27 |
28 | minetest.add_particle(
29 | {
30 | pos = {x=pos.x, y=pos.y+1.5, z=pos.z},
31 | velocity = vdir, --{x=0, y=0, z=0},
32 | acceleration = {x=0, y=-1, z=0},
33 | expirationtime = 15,
34 | size = 10,
35 | collisiondetection = true,
36 | collision_removal = false,
37 | object_collision = false,
38 | vertical = false,
39 | texture = texs[math.random(#texs)],
40 | glow = 0
41 | })
42 | end
43 | p1 = player:getpos();
44 | end
45 |
46 | p2 = player:getpos()
47 | local dist = ((p2.x-p1.x)^2+(p2.y-p1.y)^2+(p2.z-p1.z)^2)^0.5
48 | if player:get_wielded_item():to_string()=="flowers:dandelion_yellow" then add_part(p2) end
49 |
50 | --if dist>1 then p1 = player:getpos() add_part(p1) end
51 |
--------------------------------------------------------------------------------
/scripts/music/music_playback.lua:
--------------------------------------------------------------------------------
1 | --rnd music robot v12/10/2019, 22:00
2 | --tuning by Jozet
3 |
4 | --@F2 E D C G3 G F2 E D C G3 G F2 A A F E G G E D E F D C3 C
5 |
6 | if not init then
7 | _G.minetest.forceload_block(self.pos(),true)
8 | song = nil
9 | self.listen(1)
10 | local ent = _G.basic_robot.data[self.name()].obj:get_luaentity();
11 | dt = 0.001
12 | ent.timestep = dt -- time step
13 |
14 | pitches = { -- definitions of note pitches
15 | 0.59,
16 | 0.62,
17 | 0.67,
18 | 0.7,
19 | 0.74,
20 | 0.79,
21 | 0.845,
22 | 0.89,
23 | 0.945,
24 | 1,
25 | 1.05,
26 | 1.12,
27 | 1.19,
28 | 1.25,
29 | 1.34,
30 | 1.41,
31 | 1.48,
32 | 1.58,
33 | 1.68,
34 | 1.78,
35 | 1.88,
36 | 2.0,
37 | 2.15,
38 | 2.28
39 | }
40 |
41 | notenames = { -- definition of note names
42 | C = 1,
43 | Db = 2,
44 | D = 3,
45 | Eb = 4,
46 | E = 5,
47 | F = 6,
48 | Gb = 7,
49 | G = 8,
50 | Ab = 9,
51 | A = 10,
52 | Bb = 11,
53 | B = 12,
54 | ["2C"] = 13,
55 | ["2Db"] = 14,
56 | ["2D"] = 15,
57 | ["2Eb"] = 16,
58 | ["2E"] = 17,
59 | ["2F"] = 18,
60 | ["2Gb"] = 19,
61 | ["2G"] = 20,
62 | ["2Ab"] = 21,
63 | ["2A"] = 22,
64 | ["2Bb"] = 23,
65 | ["2B"] = 24
66 | }
67 |
68 | say("available notes : C Db D Eb E F Gb G Ab A Bb B 2C 2Db 2D 2Eb 2E 2F 2Gb 2G 2Ab 2A 2Bb 2B . example: @A5 A A A A10 A A A , number after note name denotes change of tempo. To replay last song do @R")
69 |
70 |
71 | songdata = {}
72 | t=0 -- current timer
73 | idx = 0 -- current note to play
74 | tempo = 1 -- default pause
75 |
76 | parse_song = function()
77 | songdata = {} -- reset song data
78 | for notepart in string.gmatch(song,"([^ ]+)") do -- parse song
79 | if notepart then
80 | local note,duration;
81 | note,duration = _G.string.match(notepart,"(%d*%a+)(%d*)")
82 | if not duration or duration == "" then duration = 0 end
83 | songdata[#songdata+1] = {notenames[note], tonumber(duration)}
84 | end
85 | end
86 | tempo = 3; -- default tempo
87 | t=0
88 | idx = 0 -- reset current idx
89 | end
90 |
91 | init = true
92 |
93 | end
94 |
95 | if not song then
96 | speaker,msg = self.listen_msg()
97 | if msg and string.find(msg,"@") then
98 | song = string.sub(msg,2)
99 | if song ~= "R" then -- R for replay
100 | parse_song()
101 | self.label("playing song by " .. speaker.. ", " .. song )
102 | else
103 | idx = 0; t = 0; -- try play again!
104 | end
105 | end
106 | elseif t<=1 then -- play next note!
107 | idx = idx+1
108 | if idx>#songdata then
109 | self.label("song " .. song .. ". ended.")
110 | song = nil
111 | else
112 | if songdata[idx][2]>0 then tempo = songdata[idx][2] end
113 | t = tempo;
114 | self.sound( "piano",{
115 | pos = self.pos(), gain = 1000.0, pitch = pitches[ songdata[idx][1] ],
116 | max_hear_distance = 1000000
117 | })
118 | end
119 | else
120 | t=t-1
121 | end
--------------------------------------------------------------------------------
/scripts/perm2cycles.lua:
--------------------------------------------------------------------------------
1 | if not perm2cycles then
2 |
3 | perm2cycles = function(perm)
4 | local n = #perm;
5 | local i = 1; -- already reached number
6 | local ret = {};
7 | local visited = {};
8 | local step = 0;
9 |
10 | while (true) do
11 | local cycle = {i}
12 | local j=i;
13 |
14 | while (true) do
15 | step = step +1
16 | if step > 2*n then return {} end
17 | j=perm[j];
18 | visited[j] = 1;
19 | if j and j~=cycle[1] then cycle[#cycle+1]=j else break end
20 | end
21 |
22 | i=n+1;
23 | for k=1,n do -- find smallest non visited yet
24 | if not visited[k] and k cycles = " .. arr2string(cycles) )
82 |
83 | end
--------------------------------------------------------------------------------
/scripts/pine_tree_harvest.lua:
--------------------------------------------------------------------------------
1 | -- PINE TREE HARVEST by rnd1
2 | if not harvest then
3 | harvest = {};
4 | harvest.s = -1 -- -1 idle, 0 expect tree
5 | harvest.tree = "default:pine_tree";harvest.wood = "default:wood";harvest.sapling = "default:pine_sapling";
6 | harvest.step = function()
7 | local s=harvest.s;
8 | if s == 0 then -- did we bump into tree
9 | local node = read_node.forward();
10 | if node == harvest.tree then
11 | dig.forward(); move.forward(); harvest.s = 1 -- found tree, moving in
12 | self.label("im digging up tree ")
13 | end
14 | elseif s == 1 then -- climbing up
15 | dig.up(); move.up(); place.down(harvest.wood);
16 | local node = read_node.up();
17 | if node ~= harvest.tree then
18 | harvest.s = 2 -- top
19 | self.label("i reached top of tree")
20 | end
21 | elseif s == 2 then -- going down
22 | local node = read_node.down();
23 | if node == harvest.wood then
24 | dig.down(); move.down()
25 | self.label("im going back down")
26 | else
27 | pickup(8);
28 | move.backward();place.forward(harvest.sapling);move.forward();
29 | harvest.s = -1 -- idle
30 | self.label("i finished cutting tree")
31 | end
32 | end
33 | end
34 | end
35 |
36 | --harvest walk init
37 | if not angle then
38 | sender,mail = self.read_mail(); if sender == "rnd1" then harvest.s = tonumber(mail) or 0 end
39 | wall = "default:cobble";
40 | angle = 90
41 | end
42 |
43 | if harvest.s~=-1 then
44 | harvest.step()
45 | elseif harvest.s==-1 then
46 | node = read_node.forward();
47 | if node==harvest.tree then
48 | harvest.s = 0;
49 | self.label("i found tree")
50 | else
51 | self.label("im walking")
52 | if not move.forward() then
53 | if node == wall then
54 | self.label("i hit wall")
55 | turn.angle(angle);
56 | if move.forward() then
57 | move.forward();move.forward();turn.angle(angle); angle = -angle
58 | else
59 | turn.angle(-angle);angle = - angle
60 | end
61 | end
62 | end
63 | end
64 | end
65 | self.send_mail("rnd1",harvest.s) -- remember state in case of reactivation
--------------------------------------------------------------------------------
/scripts/player_appearance.lua:
--------------------------------------------------------------------------------
1 | if not init then
2 | self.set_properties({
3 | visual = "mesh", mesh = "character.b3d",
4 | textures = {"character.png"},
5 | visual_size = {x = 2, y = 2}
6 | });
7 | move.up()
8 | init = 1;
9 |
10 | animation = {
11 | -- Standard animations.
12 | stand = { x= 0, y= 79, },
13 | lay = { x=162, y=166, },
14 | walk = { x=168, y=187, },
15 | mine = { x=189, y=198, },
16 | walk_mine = { x=200, y=219, },
17 | sit = { x= 81, y=160, },
18 | }
19 | self.set_animation(animation.stand.x,animation.stand.y, 15, 0)
20 | t=0
21 | end
--------------------------------------------------------------------------------
/scripts/programming/brainfuck generator.lua:
--------------------------------------------------------------------------------
1 | N = 30; -- length of program (without ])
2 |
3 | desired_frequencies = {
4 | [">"] = 10,
5 | ["<"] = 10,
6 | ["-"]=10,
7 | ["+"]=20,
8 | ["."]=10,
9 | [","]=10,
10 | ["["]=10, -- matching "]" will be inserted automatically!
11 | }
12 | matching_parenthesis = "]";
13 | routine_lower = 1; routine_higher = 5; -- specify range, how many characters in routine [.....]
14 |
15 | generate_selections = function(desired_frequency)
16 | local sum = 0
17 | for k,v in pairs(desired_frequency) do sum = sum + v end
18 | local isum = 0; local count = 0; local selections = {}
19 | for k,v in pairs(desired_frequency) do count = count +1 isum = isum + desired_frequency[k]/sum; selections[count] = {isum,k} end
20 | return selections
21 | end
22 |
23 | choose = function(selections, rnd)
24 | local low, mid, high;
25 | low = 1; high = #selections; mid = math.floor((low+high)/2)
26 | local step = 0;
27 | while high-low>1 and step < 20 do
28 | step = step + 1
29 | if rnd <= selections[mid][1] then high = mid else low = mid end
30 | mid = math.floor((low+high)/2)
31 | end
32 | return selections[mid][2]
33 | end
34 |
35 |
36 | generate_program = function(desired_frequencies,N, routine_lower, routine_higher)
37 | local selections = generate_selections(desired_frequencies);
38 |
39 | local ret = {};
40 | local count = 0
41 | local stack = {};
42 |
43 | for count = 1, N do
44 | local choice = choose(selections, math.random());
45 | if choice == "[" then
46 | local i = count + math.random(routine_lower,routine_higher)
47 | if i > N then i = N end
48 | stack[#stack+1] = i;
49 | end
50 | ret[count] = choice
51 | end
52 |
53 | for i = 1,#stack do local j = stack[i] ret[j]=ret[j]..matching_parenthesis end
54 | return table.concat(ret)
55 | end
56 |
57 | say(generate_program(desired_frequencies,N, routine_lower, routine_higher))
58 |
59 | self.remove()
--------------------------------------------------------------------------------
/scripts/programming/brainfuck.lua:
--------------------------------------------------------------------------------
1 | -- BRAINFUCK interpreter by rnd, 2017
2 | -- https://en.wikipedia.org/wiki/Brainfuck
3 |
4 | if not ram then
5 | prog = "+++.>++++++.<[->+<]>."
6 | ramsize = 10
7 | maxsteps = 100; step=0; -- for RUN state only
8 |
9 | n = string.len(prog);ram = {};for i = 1, ramsize do ram[i]=0 end -- init ram
10 | pointer = 1 -- ram pointer
11 | instruction = 1 -- instruction pointer
12 | self.spam(1)
13 |
14 | RUNNING = 1; END = 2; RUN = 3;
15 | state = RUNNING
16 |
17 | get_ram = function() msg = "" for i = 1,ramsize do msg = msg .. ram[i] .. "," end return msg end
18 |
19 | cmdset = {
20 | [">"] = function() pointer = pointer + 1; if pointer > ramsize then pointer = 1 end end,
21 | ["<"] = function() pointer = pointer - 1; if pointer > ramsize then pointer = 1 end end,
22 | ["+"] = function() ram[pointer]=ram[pointer]+1 end,
23 | ["-"] = function() ram[pointer]=ram[pointer]-1 end,
24 | ["."] = function() say(ram[pointer]) end,
25 | [","] = function() ram[pointer] = tonumber(read_text.forward("infotext") or "") or 0 end,
26 | ["["] = function()
27 | if ram[pointer] == 0 then
28 | local lvl = 0
29 | for j = instruction, n, 1 do
30 | if string.sub(prog,j,j) == "]" then lvl = lvl - 1 if lvl == 0 then
31 | self.label("JMP " .. j ) instruction = j return
32 | end end
33 | if string.sub(prog,j,j) == "[" then lvl = lvl + 1 end
34 | end
35 | end
36 | end,
37 | ["]"] = function()
38 | if ram[pointer] ~= 0 then
39 | local lvl = 0
40 | for j = instruction, 1, -1 do
41 | if string.sub(prog,j,j) == "]" then lvl = lvl - 1 end
42 | if string.sub(prog,j,j) == "[" then lvl = lvl + 1 if lvl == 0 then
43 | self.label("JMP " .. j ) instruction = j return
44 | end end
45 | end
46 | end
47 | end,
48 | }
49 | end
50 |
51 | -- EXECUTION
52 | if state == RUNNING then
53 | c = string.sub(prog,instruction,instruction) or "";
54 | if c and cmdset[c] then cmdset[c]() end
55 | self.label("ins ptr " .. instruction .. ", ram ptr " .. pointer .. ": " .. ram[pointer] .. "\n" .. string.sub(prog, instruction).."\n"..get_ram())
56 | instruction = instruction + 1; if instruction > n then state = END end
57 |
58 | -- RUN THROUGH
59 | elseif state == RUN then
60 | while (step n then self.label("ram : " .. get_ram()) step = maxsteps state = END end
65 | end
66 | end
--------------------------------------------------------------------------------
/scripts/programming/code_parser_strings_identify.lua:
--------------------------------------------------------------------------------
1 | function identify_strings(code) -- returns list of positions {start,end} of literal strings in lua code
2 |
3 | local i = 0; local j; local length = string.len(code);
4 | local mode = 0; -- 0: not in string, 1: in '...' string, 2: in "..." string, 3. in [==[ ... ]==] string
5 | local modes = {
6 | {"'","'"},
7 | {"\"","\""},
8 | {"%[=*%[","%]=*%]"}
9 | }
10 | local ret = {}
11 | while i < length do
12 | i=i+1
13 |
14 | local jmin = length+1;
15 | if mode == 0 then -- not yet inside string
16 | for k=1,#modes do
17 | j = string.find(code,modes[k][1],i);
18 | if j and j maxlen then maxlen = length; maxidx = i end
43 | count = count + 1
44 | end
45 | end
46 |
47 | if maxlen>0 then
48 | local data = hashdb[maxidx];
49 | say("number of used hash entries is " .. count .. ", average " .. (step/count) .. " entries per hash, "..
50 | " max length of list is " .. maxlen .. " at hash ".. maxidx )--.. " : " ..
51 | --string.gsub(_G.dump(data),"\n","") )
52 |
53 | end
54 | end
55 |
56 | -- LOAD DICTIONARY WORDS into hashtable
57 |
58 | lang = "german"
59 |
60 | fname = "F:\\games\\rpg\\minetest-0415server\\mods\\basic_translate\\"..lang;
61 | local f = _G.assert(_G.io.open(fname, "r"));local dicts = f:read("*all");f:close()
62 |
63 | step = 0; maxwords = 10000;
64 | i=0
65 | dict = {}; -- for comparison
66 |
67 | while(step 'hello', 6
4 |
5 | get_next_word = function(code, ibeg,iend) -- attempt to return next word, starting from position ibeg. returns word, index after word
6 | if not ibeg or not iend then return end
7 | local j = string.find(code,"%w",ibeg); -- where is start of word?
8 | if not j or j>iend then return "", iend+1 end -- no words present
9 | ibeg = j;
10 | j = string.find(code,"%W",j);--where is end of word?
11 | if not j or j>iend then return string.sub(code,ibeg,iend-1),iend+1 end
12 | return string.sub(code,ibeg,j-1), j
13 | end
14 |
15 | text = [[
16 | hello world
17 | today
18 | day night
19 | ]]
20 | ibeg = 1; iend = string.find(text,"\n",ibeg) or string.len(text) -- where is next new line
21 | say("INIT LINE " .. ibeg .. " " .. iend .. " LINE '" .. string.sub(text,ibeg,iend-1) .."'")
22 |
23 |
24 | for i = 1,10 do
25 |
26 |
27 | word, ibeg = get_next_word(text,ibeg,iend)
28 | say("word '" .. word.."', end " .. ibeg)
29 | if ibeg>=iend then -- newline!
30 | --say("newline")
31 | local j = ibeg;
32 | iend = string.find(text,"\n", iend+1) -- find next newline
33 |
34 | if not iend then say("END") iend = string.len(text) break end -- end of text!
35 | say("LINE " .. ibeg .. " " .. iend .. " LINE '" .. string.sub(text,ibeg,iend-1) .."'")
36 | end
37 |
38 | end
39 |
40 | self.remove()
--------------------------------------------------------------------------------
/scripts/programming/perm2cycles.lua:
--------------------------------------------------------------------------------
1 | if not perm2cycles then
2 |
3 | perm2cycles = function(perm)
4 | local n = #perm;
5 | local i = 1; -- already reached number
6 | local ret = {};
7 | local visited = {};
8 | local step = 0;
9 |
10 | while (true) do
11 | local cycle = {i}
12 | local j=i;
13 |
14 | while (true) do
15 | step = step +1
16 | if step > 2*n then return {} end
17 | j=perm[j];
18 | visited[j] = 1;
19 | if j and j~=cycle[1] then cycle[#cycle+1]=j else break end
20 | end
21 |
22 | i=n+1;
23 | for k=1,n do -- find smallest non visited yet
24 | if not visited[k] and k cycles = " .. arr2string(cycles) )
82 |
83 | end
--------------------------------------------------------------------------------
/scripts/programming/robot2irc.lua:
--------------------------------------------------------------------------------
1 | -- send data from robot to irc client, rnd 2018 ( works on vanessae skyblock)
2 |
3 | if not init then
4 | ircchat = minetest.registered_chatcommands["irc_msg"].func;
5 | name = "r_n_d" -- client on irc you want to send msg too
6 | ircchat("ROBOT", name .." " .. "hello irc world") -- chat will appear as coming from on skyblock
7 | init = true
8 | end
9 |
10 |
--------------------------------------------------------------------------------
/scripts/programming/room_finder.lua:
--------------------------------------------------------------------------------
1 | -- room finder by rnd (45 minutes)
2 | -- given starting position it explores 3d world to find enclosed area of room, up to max 2000 nodes
3 |
4 | if not init then init = true
5 | local rpos = self.pos()
6 | local radius = 16
7 | bpos = minetest.find_node_near(rpos, radius,"beds:bed_bottom");bpos.y=bpos.y+1 -- bed
8 | --say(bpos.x .. " " .. bpos.y .. " " .. bpos.z)
9 |
10 |
11 | walls = { -- define possible walls here
12 | ["default:cobble"]=true, ["default:wood"] = true,
13 | ["default:obsidian_glass"]=true,["default:glass"] = true,
14 | ["doors:door_obsidian_glass_a"]=true,["doors:door_obsidian_glass_b"]=true,
15 | ["doors:hidden"] = true,
16 | }
17 |
18 |
19 | local find_room = function(bpos)
20 |
21 |
22 | local cbdata = {bpos} -- explore boundary
23 | local cdata = {[minetest.hash_node_position(bpos)] = true} -- db of room pos
24 | local dirs = {{x=-1,y=0,z=0},{x=1,y=0,z=0},{x=0,y=-1,z=0},{x=0,y=1,z=0},{x=0,y=0,z=-1},{x=0,y=0,z=1}}
25 | local ccount = 1
26 |
27 | crawl_step = function()
28 | local pos = cbdata[#cbdata];cbdata[#cbdata] = nil;
29 | for i = 1,#dirs do
30 | local p = {x=pos.x+dirs[i].x,y=pos.y+dirs[i].y,z=pos.z+dirs[i].z}
31 | if not cdata[minetest.hash_node_position(p)] and not walls[minetest.get_node(p).name] then
32 | cdata[minetest.hash_node_position(p)] = true
33 | cbdata[#cbdata+1] = p
34 | ccount = ccount +1
35 | end
36 | end
37 | end
38 |
39 |
40 | local maxsteps = 2000;
41 | local step = 0
42 |
43 | while #cbdata>0 and step"] = function() turn.right() end,
12 | ["<"] = function() turn.left() end,
13 | ["p"] = function() place.down("default:dirt") end,
14 | ["P"] = function() place.forward_down("default:dirt") end,
15 | }
16 |
17 | program = "R3[Pfu]<"
18 | loop = {start = 1, quit = 1, count = 1};
19 |
20 | step = 1
21 | end
22 |
23 | c = string.sub(program,step,step)
24 | if c == "R" then -- loop
25 | local i = string.find(program,"%[",step+1);
26 | loop.count = tonumber(string.sub(program,step+1, i-1)) or 1;
27 | loop.start = i+1;
28 | i = string.find(program,"]",i+1);
29 | loop.quit = i-1
30 | step = loop.start-1
31 | else -- normal command
32 | command = commands[c];
33 | if command then
34 | command()
35 | elseif step>string.len(program) then
36 | step = 0
37 | end
38 | end
39 |
40 |
41 | self.label(step)
42 | step = step +1
43 | if loop.count>0 then -- are we in loop?
44 | if step>loop.quit then loop.count = loop.count - 1; step = loop.start end
45 | if loop.count == 0 then step = loop.quit + 2 end
46 | end
--------------------------------------------------------------------------------
/scripts/serialization.lua:
--------------------------------------------------------------------------------
1 | if not itemlist then
2 | inv2string = function(name)
3 | local inv = _G.minetest.get_player_by_name(name):get_inventory()
4 | local list = ""
5 |
6 | for i = 1,32 do
7 | local item = inv:get_stack("main", i):to_string()
8 | list = list .. item .. ","
9 | end
10 | return name .. "," .. list
11 | end
12 |
13 | string2inv = function(str)
14 | local i = string.find(str,",");
15 | local name = string.sub(str,1,i-1);
16 | local step = 0
17 | local invlist = {};
18 | while i and step < 33 do
19 | step = step +1
20 | local i1 = string.find(str,",",i+1)
21 | if not i1 then break end
22 | invlist[#invlist+1]=string.sub(str,i+1,i1-1)
23 | i=i1
24 | end
25 | return name, invlist
26 | end
27 |
28 | array2string = function(array)
29 | if _G.type(array) ~= "table" then return array end
30 | local ret = "{";
31 | for i =1,#array-1 do
32 | ret = ret .. array2string(array[i]) .. ","
33 | end
34 | ret = ret .. array2string(array[#array])
35 | return ret .. "}"
36 | end
37 |
38 | string2array = function(str)
39 | if not string.find(str,"{") then return str end
40 | local lvl = 1; local n = string.len(str);
41 | local i1,i2,count;
42 | count = 0; --1 = {}, 2 = ,
43 | local arr = {}; i1 = 2;
44 | for i =2,n do
45 | local c = string.sub(str,i,i);
46 | if c == "{" then
47 | lvl = lvl+1
48 | elseif c == "}" then
49 | lvl = lvl -1
50 | elseif c == "," and lvl == 1 then
51 | i2 = i;
52 | count = count+1
53 | arr[count] = string2array(string.sub(str,i1,i2-1)); i1 = i2+1
54 | end
55 | end
56 | if i1< n then count = count+1 ; arr[count] = string2array(string.sub(str,i1,n-1)) end
57 | return arr
58 | end
59 |
60 | local arr = {{1,{2,4}},{3,4},{0,{2}},-2};
61 | --local arr = {1,2,3}
62 | self.spam(1)
63 | say("original array : ".. string.gsub(_G.dump(arr),"\n","") )
64 | local str = array2string(arr);
65 | say("array2string : " .. str)
66 | local arr1 = string2array(str);
67 | say("string2array: " .. string.gsub(_G.dump(arr1),"\n",""))
68 |
69 | player = find_player(2);
70 | itemlist = {};
71 | if player then
72 | local list = inv2string(player[1])
73 | local name,invlist = string2inv(list)
74 | list = "UNIT TEST inv2string\n"..list .. "\nUNIT TEST string2inv\n".. "name = " .. name .."\n".. string.gsub(_G.dump(invlist),"\n","")
75 | form = "size[8,8.5]" ..
76 | "textarea[0,0;7.75,7.5;list;list;" .. list .. "]";
77 | self.show_form(player[1],form)
78 | end
79 | end
80 |
81 | sender,fields = self.read_form();
82 | if sender then
83 | if fields.list then
84 | if string.sub(fields.list,1,3) == "DCL" then
85 | local sel = tonumber(string.sub(fields.list,5)) or 1
86 | say("you selected item " .. itemlist[sel])
87 | end
88 | end
89 | if fields.quit then self.remove() end
90 | end
--------------------------------------------------------------------------------
/scripts/server mods/chatlog.lua:
--------------------------------------------------------------------------------
1 | --rnd 2017
2 | if not logdata then
3 | self.label("chatlog bot");
4 | _G.minetest.forceload_block(self.pos(),true)
5 | n = 500; -- store so many messsages before repeating
6 | maxresults = 100 -- display at most 'this' result
7 |
8 | logdata = {}; -- circular array to hold messages
9 | idx = 1;
10 | insert_log = function(logdata,text) -- store new message
11 | idx = idx +1;
12 | if idx > n then idx = 1 end
13 | logdata[idx] = text;
14 | end
15 |
16 | retrieve_log = function(logdata,count,filter) -- return last k messages, with filter only selected messages
17 |
18 | local k = 0;
19 | local i=idx; local j=0; local ret = {}
20 |
21 | for j = 1,n do
22 | if not logdata[i] then break end
23 | if filter and not string.find(logdata[i], filter) then
24 | else
25 | ret[#ret+1] = logdata[i]
26 | k=k+1
27 | if k>=count then break end -- enough results
28 | end
29 | i=i-1; if i < 1 then i = n end
30 | end
31 | return table.concat(ret,"\n")
32 | end
33 |
34 | self.listen(1)
35 | end
36 |
37 | speaker, msg = self.listen_msg()
38 | if msg then
39 | if string.sub(msg,1,4) == "?log" then
40 | local j = string.find(msg," ",7); -- find first argument
41 | local k;local text;
42 | if j then k = tonumber(string.sub(msg,6,j-1)) else k = tonumber(string.sub(msg,6)) end -- if there was first argument find second
43 | k = k or maxresults;
44 | if j then text = retrieve_log(logdata,k,string.sub(msg,j+1)) else text = retrieve_log(logdata,k) end
45 | local form = "size[8,8]".. "textarea[0.,0;11.,9.5;text;chatlog;".. text .. "]"
46 | self.show_form(speaker, form)
47 | else
48 | insert_log(logdata, os.date("%X") .. " " .. speaker .. "> " .. msg)
49 | end
50 | end
--------------------------------------------------------------------------------
/scripts/server mods/colored chat.lua:
--------------------------------------------------------------------------------
1 | -- with current mods there are 4 registered chat responses so we add 5th
2 | -- CHANGE COLOR OF CHAT FOR CERTAIN PLAYERS
3 |
4 | if not rom.color_chat_messages then rom.color_chat_messages = 1+#minetest.registered_on_chat_messages end
5 |
6 | colors = {"cyan", "LawnGreen"}
7 | chatgroup = {}; -- players in here will see chat without colors
8 | --say("chat " .. rom.chat_messages)
9 |
10 | minetest.registered_on_chat_messages[rom.color_chat_messages] =
11 | function(name,message)
12 | if message == "nocolor" then
13 | chatgroup[name] = not chatgroup[name]
14 | minetest.chat_send_all("colored chat display " .. (chatgroup[name] and "DISABLED" or "ENABLED") .. " for " .. name)
15 | return false
16 | else
17 | --message = os.date("%X") .. " " .. name .." <> " .. message;
18 | local newmessage = "["..name .."] " .. message;
19 | local player = minetest.get_player_by_name(name);
20 | local pos1 = player:get_pos();
21 |
22 | for _,player in pairs(minetest.get_connected_players()) do
23 | local name = player:get_player_name()
24 | local pos2 = player:get_pos();
25 | local dist = math.sqrt((pos2.x-pos1.x)^2+(pos2.y-pos1.y)^2+ (pos2.z-pos1.z)^2)
26 | local length = string.len(name);
27 | local color = 1; -- default
28 | if (chatgroup[name] or dist>32 or dist == 0) then color = 0 end
29 | if string.find(message,string.lower(name)) then color = 2 end
30 |
31 | if color == 0 then
32 | minetest.chat_send_player(name, newmessage)
33 | else
34 | minetest.chat_send_player(name, minetest.colorize(colors[color], newmessage))
35 | end
36 |
37 | end
38 | end
39 | return true
40 | end
41 |
42 | self.remove()
--------------------------------------------------------------------------------
/scripts/simple_layout_gen.lua:
--------------------------------------------------------------------------------
1 | if not data then
2 | m=50;n=50; minescount = m*n/10;
3 |
4 | t0 = _G.minetest.get_gametime();
5 | data = {}; spawnpos = self.spawnpos();
6 | for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
7 |
8 | get_mine_count = function(i,j)
9 | if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
10 | for k = -1,1 do for l = -1,1 do
11 | if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
12 | end end
13 | return count
14 | end
15 |
16 | for i = 1,m do for j = 1,n do
17 | if get_mine_count(i,j) > 0 or (data[i] and data[i][j] == 1) then
18 | _G.minetest.swap_node({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}, {name = "basic_robot:buttonFFFFFF"})
19 | else
20 | _G.minetest.swap_node({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}, {name = "default:dirt"})
21 | end
22 | end end
23 | end
24 | self.remove()
--------------------------------------------------------------------------------
/scripts/simple_parser.lua:
--------------------------------------------------------------------------------
1 | if not text then
2 | text = "diamond 3;mese 4;gold 2;diamond 1;"
3 | function parse(text)
4 | ret = {};
5 | for a,b in text:gmatch("(%w+) (%w+)%;") do
6 | ret[a] = (ret[a] or 0) + (tonumber(b) or 0)
7 | end
8 | return ret
9 | end
10 |
11 | function export(array)
12 | ret = "";
13 | for k,v in pairs(array) do
14 | ret = ret .. (_G.tostring(k) or "") .. " " .. (_G.tostring(v) or "") ..";"
15 | end
16 | return ret
17 | end
18 | say("input: " .. text)
19 | local arr = parse(text);
20 | say("parsed text: " .. string.gsub(_G.dump(arr),"\n",""))
21 | say("back to string :" .. export(arr))
22 | end
--------------------------------------------------------------------------------
/scripts/simulators/horse_race.lua:
--------------------------------------------------------------------------------
1 | if not init then init = true
2 | horses = {10,5,5,5,5,5}; -- ratings, probability that horse wins is proportional to its rating
3 |
4 |
5 |
6 | local rndseed = 1;
7 | local random = function(n)
8 | rndseed = (48271*rndseed)% 2147483647;
9 | return rndseed % n
10 | end
11 |
12 | -- race simulation: output is winner, 2nd, 3rd, ...
13 | -- algorithm sketch: first choose 1st, then from remainder select 2nd, then ...
14 |
15 | race = function(horses)
16 |
17 | rndseed = os.time()
18 | local n = #horses; local sum = 0
19 | local res = {};
20 | for i = 1,n do sum = sum + horses[i]; res[i]=i end
21 |
22 | for i = 1,n do
23 | -- select random idx from i..n as winner of i-th round
24 | local sel = random(sum);
25 | --find first j such that partial sums i,..,j exceed sel ( probability that horse will be selected is proportional to its rating)
26 | local psum = 0; local j = n
27 | for k = i,n do
28 | psum = psum + horses[res[k]]
29 | if psum>= sel then j = k break end
30 | end
31 | --dout(i..". j= " ..j .. ", sel " .. sel )
32 |
33 | --swap j-th and i-th to put selected horse on i-th position
34 | local tmp = res[j]; res[j] = res[i]; res[i] = tmp
35 | sum = sum - horses[ tmp ] -- remove winner from sum
36 | end
37 | return res
38 | end
39 |
40 | self.label( serialize(race(horses)) )
41 |
42 | end
--------------------------------------------------------------------------------
/scripts/simulators/nuclear.lua:
--------------------------------------------------------------------------------
1 | -- rnd 2017
2 | if not data then
3 | data = {FUEL = 1.8,TV=0,T=0,P=0,E=0;}
4 |
5 | generate_nuclear_power = function(CONTROL,COOLING)
6 | if COOLING>1 then COOLING = 1 elseif COOLING<0 then COOLING = 0 end
7 | if CONTROL>1 then CONTROL = 1 elseif CONTROL<0 then CONTROL = 0 end
8 | --data = ...
9 | local FUEL = data.FUEL;
10 | local TV = data.TV;
11 | local T = data.T;
12 | local P = data.P;
13 | local E = data.E;
14 |
15 | -- reactor specifications
16 | local TVmax = 10000;
17 | local FUELC = 2; -- critical mass for fuel
18 | local DECAYRATE = 1-0.01; -- how much fuel decays per time step
19 | local COOLINGCOEF = 1; -- how efficient is cooling per 1 unit of power (how many degrees are cooled)
20 | local PCOEF = 1; -- how efficiently temperature is converted to power
21 |
22 | local TGV = FUEL/(1-(FUEL/FUELC)^2);
23 | if TGV>TVmax then TGV = TVmax end; if FUEL>FUELC then TGV = TVmax end -- basic temperature generation speed generated in core
24 | TV = TV + TGV* CONTROL - P*COOLING*COOLINGCOEF; -- temperature change speed
25 | T = T + TV ;
26 | P = 0.5*P + T*PCOEF; P = P - P*COOLING -- produced power
27 | FUEL = FUEL*DECAYRATE;
28 | if P<0 then P = 0 end if T<0 then T = 0 end E=E+P;
29 |
30 | data.FUEL = FUEL;
31 | data.T = T;
32 | data.TV = TV;
33 | data.P = P;
34 | data.E = E
35 | return E, P, T, FUEL, TV
36 | end
37 |
38 | render = function(data) -- data should be normalized [0,1]
39 | local tname = "pix.png";
40 | local obj = _G.basic_robot.data[self.name()].obj;
41 | local n = 150; local m = n;
42 | local length = #data; if length == 0 then return end
43 | local hsize = 1; local wsize=hsize;
44 | local tex = "[combine:"..(wsize*m).."x"..(hsize*n);
45 | for i = 1,length do
46 | j=math.floor((1-data[i])*m);
47 | local ix = math.floor((i/length)*n)
48 | tex = tex .. ":"..(ix*wsize).."," .. (j*hsize) .. "="..tname
49 | end
50 | obj:set_properties({visual = "sprite",textures = {tex}})
51 | end
52 |
53 | tdata = {};
54 | COOLING = 0.03
55 |
56 | end
57 |
58 | -- generate_nuclear_power(CONTROL, COOLING)
59 | -- CONTROL = 0.20; -- control rods; 1 = no control, between 0 and 1
60 | -- COOLING = 0.03; -- how much power assigned for cooling, in ratio of output power P; between 0 and 1
61 |
62 |
63 | E,P,T,FUEL,TV = generate_nuclear_power(0.2,COOLING)
64 | -- cooling strategy
65 | if TV < 0 then COOLING = 0.0 elseif T>90 then COOLING = 0.03 else COOLING = 0 end
66 |
67 | tdata[#tdata+1]=math.min(T/100,1);
68 | render(tdata)
69 |
70 | self.label( "T " .. T .. "\nTV " .. TV .. "\nP ".. P .. "\nFUEL " .. FUEL .. "\nTOTAL ENERGY PRODUCED " .. E )
--------------------------------------------------------------------------------
/scripts/simulators/pathfinder.lua:
--------------------------------------------------------------------------------
1 | -- pathfinder robot
2 |
3 | if not init then
4 | max_jump = 1
5 | max_drop = 1
6 | searchdistance = 10
7 | move.forward(); move.down()
8 | pos1 = self.pos()
9 | pos2 = {x = -70 , y = -1, z = -123 }
10 | path = minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,"Dijkstra")
11 | if not path then say("i dont know how to get there :(") self.remove() end
12 |
13 | say("im going to " .. pos2.x .. " " .. pos2.y .. " " .. pos2.z .. ", will be there in " .. #path .. " seconds")
14 | -- self.label(serialize(path))
15 | step = 0
16 | obj = _G.basic_robot.data[self.name()].obj
17 | init = true
18 | end
19 |
20 | if step<#path then
21 | step = step + 1
22 | pos = path[step]
23 | obj:setpos(pos)
24 | if step == #path then say("arrived at destination.") end
25 | end
--------------------------------------------------------------------------------
/scripts/simulators/room_walker.lua:
--------------------------------------------------------------------------------
1 | --TODO: unfinished
2 | if not init then
3 | state = 0
4 | init = true
5 | walkdb = {};
6 | spos = self.spawnpos();
7 | step = 0
8 | startstep = 0; -- mark the step when next walk around begins
9 |
10 | local get_dir = function()
11 | local dir = self.viewdir()
12 | end
13 |
14 | rot_left = function(dir) local tmp = dir.x;dir.x = -dir.z; dir.z = tmp end
15 |
16 | rot_right = function(dir) local tmp = dir.x;dir.x = dir.z; dir.z = -tmp end
17 |
18 | end
19 |
20 | if state == 0 then
21 | if not move.forward() then state = 1; turn.right(); startstep = 1 end
22 | elseif state == 1 then
23 | step = step + 1
24 | local pos = self.pos();
25 | local x = pos.x-spos.x; local z = pos.z-spos.z;
26 | if not walkdb[x] then walkdb[x] = {} end walkdb[x][z] = step; -- add position
27 | local dir = self.viewdir();
28 |
29 | local node = read_node.left();
30 |
31 |
32 |
33 | rot_left(dir) -- rotate left
34 | local xr = x + dir.x; local zr = z + dir.z
35 |
36 | if node == "air" and (not dir[xr] or not dir[xr][zr]) then turn.left() end
37 | if not move.forward() and (not dir[xn] or not dir[xn][zn]) then turn.right() move.forward() end
38 | end
39 |
40 | self.label(state)
--------------------------------------------------------------------------------
/scripts/simulators/turtle_with_loops.lua:
--------------------------------------------------------------------------------
1 | -- simple turtlebot with loops, rnd, 30 mins
2 |
3 | if not init then
4 | init = true
5 | commands = {
6 | ["f"] = function() move.forward() end,
7 | ["l"] = function() move.left() end,
8 | ["r"] = function() move.right() end,
9 | ["u"] = function() move.up() end,
10 | ["d"] = function() move.down() end,
11 | [">"] = function() turn.right() end,
12 | ["<"] = function() turn.left() end,
13 | ["p"] = function() place.down("default:dirt") end,
14 | ["P"] = function() place.forward_down("default:dirt") end,
15 | }
16 |
17 | program = "R3[Pfu]<"
18 | loop = {start = 1, quit = 1, count = 1};
19 |
20 | step = 1
21 | end
22 |
23 | c = string.sub(program,step,step)
24 | if c == "R" then -- loop
25 | local i = string.find(program,"%[",step+1);
26 | loop.count = tonumber(string.sub(program,step+1, i-1)) or 1;
27 | loop.start = i+1;
28 | i = string.find(program,"]",i+1);
29 | loop.quit = i-1
30 | step = loop.start-1
31 | else -- normal command
32 | command = commands[c];
33 | if command then
34 | command()
35 | elseif step>string.len(program) then
36 | step = 0
37 | end
38 | end
39 |
40 |
41 | self.label(step)
42 | step = step +1
43 | if loop.count>0 then -- are we in loop?
44 | if step>loop.quit then loop.count = loop.count - 1; step = loop.start end
45 | if loop.count == 0 then step = loop.quit + 2 end
46 | end
--------------------------------------------------------------------------------
/scripts/simulators/turtlebot.lua:
--------------------------------------------------------------------------------
1 | if not cmd then
2 | cmd = {
3 | ["f"] = function() move.forward() end,
4 | ["b"] = function() move.backward() end,
5 | ["l"] = function() move.left() end,
6 | ["r"] = function() move.right() end,
7 | ["u"] = function() move.up() end,
8 | ["d"] = function() move.down() end,
9 | ["a"] = function() activate.forward(1) end,
10 | ["<"] = function() turn.left() end,
11 | [">"] = function() turn.right() end,
12 | }
13 | i=0;
14 | prog = read_text.right(); s=0
15 | prog = string.gsub(prog,"%s","");
16 | --say(prog)
17 | self.label("RUNNING PROGRAM: " .. prog);n=string.len(prog);
18 | if string.sub(prog,1,1) == " " then self.label("WRITE A PROGRAM FIRST!") s=1 end
19 |
20 | end
21 |
22 | if s == 0 then
23 | i=i+1; if i > n then self.label("PROGRAM ENDED");s=1 end;
24 | if s == 0 then
25 | c=string.sub(prog,i,i)
26 | if cmd[c] then cmd[c]() else self.label("INVALID PROGRAM INSTRUCTION : " .. c) s=1 end
27 | end
28 | end
--------------------------------------------------------------------------------
/scripts/spawn_quiz.lua:
--------------------------------------------------------------------------------
1 | if not s then
2 | s=0
3 | t=0
4 | option = {"A","B","C","D","E"}
5 | generate_question = function()
6 | local a = math.random(10)+0;
7 | local b = math.random(10)+0;
8 | local c = math.random(20)-10;
9 | local d = a*b+c;
10 | msg = "To get out solve the math problem\n";
11 | msg = msg .. colorize("LawnGreen",a.." * "..b.." + "..c .. " = ?\n\n")
12 | problem = a.."*"..b.."+"..c .. " = ?";
13 | correct = math.random(5);
14 | local frm = "";
15 |
16 | for i =1,5 do
17 | local offset = 0;
18 | if i~=correct then offset = math.random(10)-5; if offset == 0 then offset = -1 end end
19 | frm = frm .. "button_exit[".. -0.1+(i-1)*1.25 ..",0.75;1.25,1;" .. i .. ";".. d + offset .. "]"
20 | end
21 |
22 | local form = "size[6,1.25]" .. "label[0.05,-0.3;".. msg.."] "..frm .. "button_exit[4.9,-0.25;1.2,1;cancel;cancel]";
23 | return form, correct
24 | end
25 |
26 | selection = 1;
27 | question = "";
28 | problem = "";
29 | end
30 |
31 |
32 | if t%4 == 0 then
33 | t = 0; form,selection = generate_question();
34 | for _,obj in pairs(_G.minetest.get_objects_inside_radius({x=2,y=2,z=0}, 1)) do
35 | if obj:is_player() then
36 | local pname = obj:get_player_name();
37 | self.show_form(pname,form)
38 | end
39 | end
40 | end
41 | t=t+1;
42 |
43 |
44 | sender,fields = self.read_form()
45 | if sender then
46 | player = _G.minetest.get_player_by_name(sender);
47 | if player then
48 |
49 | answer = 0;
50 | for i = 1,5 do if fields[_G.tostring(i)] then answer = i end end
51 |
52 | if answer == correct then
53 | player:setpos({x=0,y=2,z=3})
54 | --inv = player:get_inventory(); inv:add_item("main", "default:apple")
55 | --_G.minetest.chat_send_player(sender,"