basic_robot/scripts/games/battle_minesweeper_game.lua

189 lines
6.3 KiB
Lua

if not data then
m=10;n=10;
players = {};
paused = true
turn = 2;
turntimeout = 5
shorttimeout = 1
shortround = false
turnmessage = ""
t = 0;
SIGNUP = 0; GAME = 1; INTERMISSION = 2
state = SIGNUP
t0 = _G.minetest.get_gametime();spawnpos = self.spawnpos() -- place mines
data = {};
init_game = function()
abilitypoints = {0,0}; -- points to use ability, step outside ring to use them in following round
shortround = false
data = {}; minescount = 32
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
if not data[1] then data[1] = {} end if not data[2] then data[2] = {} end -- create 2x2 safe area
data[1][1] = 0;data[1][2] = 0;data[2][1] = 0;data[2][2] = 0;
minescount = 0;
for i = 1,m do for j = 1,n do -- render game
if data[i] and data[i][j] == 1 then minescount = minescount + 1 end
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:button808080" then
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},2)
end
end end
keyboard.set({x=spawnpos.x+1,y=spawnpos.y,z=spawnpos.z+1},4) -- safe start spot
end
get_mine_count = function(i,j)
if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
for k = -1,1 do for l = -1,1 do
if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
end end
return count
end
chk_mines = function()
local count = minescount;
for i=1,m do for j=1,n do
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
count=count-1
end
end end
return count
end
near_chat = function(msg)
end
greeting = function()
_G.minetest.chat_send_all(colorize("red",
"#BATTLE MINESWEEPER : two player battle in minesweeper. say join to play.\nRules: "..
"1. each player has 5 second turn to make a move 2. if you dont make move you lose\n"..
"3. if you make move in other player turn you lose. 4. if you hit bomb or mark bomb falsely you lose\n"..
"5. by playing fast you get ability charge. when you collect 10 you can step out of ring when your round ends and opponent will only have 2s to play his turn."
))
end
player_lost = function ()
for i=1,#players do
local player = _G.minetest.get_player_by_name(players[i]);
if player then player:setpos({x=spawnpos.x,y=spawnpos.y+10,z=spawnpos.z}) end
end
_G.minetest.sound_play("electric_zap",{pos=spawnpos, max_hear_distance = 100})
state = INTERMISSION; t = 0
end
function change_turn()
shortround = false -- reset ability if activated
if turn == 1 then
_G.minetest.sound_play("default_break_glass",{pos=spawnpos, max_hear_distance = 100})
else
_G.minetest.sound_play("default_cool_lava",{pos=spawnpos, max_hear_distance = 100})
end
if paused == false then
say(players[turn] .. " lost : didn't make a move fast enough ");
player_lost()
else
local player = minetest.get_player_by_name(players[turn])
local ppos = player:getpos()
local x = ppos.x - spawnpos.x;local y = ppos.y - spawnpos.y;local z = ppos.z - spawnpos.z;
local points = abilitypoints[turn]
if x<1 or x>m or z<1 or z>n then -- outside area
local points = abilitypoints[turn]
if points>=10 then -- do we have enough points?
shortround = true -- next round will be shorter, 2s
_G.minetest.sound_play("grinder",{pos=spawnpos, max_hear_distance = 100})
abilitypoints[turn] = abilitypoints[turn]-10
end
end
if turn == 1 then turn = 2 else turn = 1 end
turnmessage = "turn " .. turn .. " " .. players[turn] .. ",charge " .. abilitypoints[turn] .. "\n"
self.label(turnmessage)
t=0
paused = false
end
end
init_game()
greeting()
self.listen(1)
end
if state == SIGNUP then
speaker,msg = self.listen_msg()
if speaker then
if msg == "join" then
players[#players+1] = speaker;
local plist = ""; for i=1,#players do plist = plist .. players[i] .. ", " end
_G.minetest.chat_send_all("BATTLE MINESWEEPER, current players : " .. plist)
if #players >= 2 then
state = GAME
change_turn();
keyboard.get(); t=0;
for i = 1, #players do
local player = _G.minetest.get_player_by_name(players[i]);
if player then player:setpos({x=spawnpos.x,y=spawnpos.y+1,z=spawnpos.z}) end
end
_G.minetest.chat_send_all(colorize("red","BATTLE MINESWEEPER " .. m .. "x" ..n .. " with " .. minescount .. " mines.\n" .. players[turn] .. " its your move!"))
init_game()
end
end
end
elseif state == GAME then
t = t + 1;
if (t>turntimeout) or (shortround and t>shorttimeout) then -- change of turn
change_turn()
else
self.label(turnmessage .. " " .. (turntimeout-t+1))
end
event = keyboard.get();
if event and event.type == 2 and not paused then
if event.puncher == players[turn] then
local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
local points = abilitypoints[turn]
if x<1 or x>m or z<1 or z>n then -- outside area
else
local ppos = player.getpos(event.puncher)
points = points + math.max(turntimeout-t-2,0); if points>40 then points = 40 end
abilitypoints[turn] = points
if ppos and math.abs(ppos.x-event.x)<0.5 and math.abs(ppos.z-event.z)<0.5 then -- just mark mine
if data[x] and data[x][z] == 1 then
if keyboard.read({x=event.x,y=event.y,z=event.z})~="basic_robot:button808080" then
keyboard.set({x=event.x,y=event.y,z=event.z},2)
else
keyboard.set({x=event.x,y=event.y,z=event.z},3)
end
else
say(event.puncher .. " lost : marked a bomb where it was none! ");
player_lost()
end
else
if data[x] and data[x][z]==1 then
_G.minetest.sound_play("tnt_boom",{pos=spawnpos, max_hear_distance = 100})
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},3)
say(event.puncher .. " lost : punched a bomb! ");
player_lost()
else
local count = get_mine_count(x,z);
if count == 0 then keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4)
else keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},7+count) end
end
end
end
paused = true
else
say(event.puncher .. " lost : played out of his/her turn"); player_lost()
end
end
elseif state == INTERMISSION then
t=t+1; if t> 15 then state = SIGNUP;players = {}; paused = true; greeting() end
end