• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

CreatureEvent Chess System

Strack

Member
Joined
May 15, 2009
Messages
199
Reaction score
14
Hi all. At first, sorry for my English.
Long time no posting so I decided to bring here one of the systems in my OT.

Credits: 100% Strack (Although i used mock's function onMoveItem)

Requires: onMoveItem() -> http://otland.net/f35/creaturescript-onmoveitem-moveitem-frompos-position-cid-96742/

Description: As u all know, tibia have some chess pieces, but u can move them as u like. My system put the pieces on the board, teleport each player to their position inside chess board, and controls that every movement is correct (each player can only move their own pieces, white pieces begin, 1 movement per turn, and each piece have their movement as in real Chess)

Here we go:

creaturescripts.xml
XML:
<event type="moveitem" name="moverpieza" event="script" value="moverpieza.lua"/>

/scripts/moverpieza.lua:
Lua:
--Credits: Strack -> [url=http://otland.net/members/strack/]View Profile: Strack - OtLand[/url]

local storage = 14757 -- storage chess system (color)
local storageMovements = 14758 -- storage chess system (movimientos)

local globalPlayer1 = 10000 -- player blanco
local globalPlayer2 = 10001 -- player negro

local newpos = {x=933,y=1016,z=7} -- pos cuando se acaba la partida 

local negras = {
peon = 2632,
torre = 2633,
caballo = 2634,
alfil = 2635,
reina = 2637,
rey = 2636
}
local blancas = {
peon = 2626,
torre = 2627,
caballo = 2628,
alfil = 2629,
reina = 2631,
rey = 2630
}

local esquinaS = {x=934, y=1017, z=8} --esquina superior izquiera del tablero
local esquinaI = {x=941, y=1024, z=8} --esquina inferior derecha del tablero

function getColor(itemid)
   return isInArray(negras, itemid) and 'negro' or 'blanco'
end

function checkColorMove(color1, topos) -- TRUE == MISMO COLORES == NO AVANZA
local fichaId = getThingFromPos(topos).itemid
   return color1 == getColor(fichaId) 
end

function casillaOcupada(pos) --TRUE == CASILLA OCUPADA POR BLANCO O NEGRO
pos.stackpos = 1
local thing = getThingFromPos(pos)
   return (isInArray(negras, thing.itemid) or isInArray(blancas, thing.itemid)) or false
end

function eliminarPieza(cid,ficha,pos)
   doRemoveItem(ficha.uid)
   doSendMagicEffect(pos, CONST_ME_CAKE)
   setPlayerStorageValue(cid, storageMovements, getPlayerStorageValue(cid, storageMovements)+1)
   
   if blancas.rey == ficha.itemid or negras.rey == ficha.itemid then
      local enemyname = getGlobalStorageValue(globalPlayer1) ~= getCreatureName(cid) and getGlobalStorageValue(globalPlayer1) or getGlobalStorageValue(globalPlayer2)
      acabarPartida(cid,getCreatureByName(enemyname))
   end
   return true
end

function acabarPartida(winner,loser)
   doPlayerSendTextMessage(winner,25,'Has eliminado a su rey, ganas la partida en '..getPlayerStorageValue(winner, storageMovements)..' movimientos.')
   doPlayerSendTextMessage(loser,25,'Has perdido!')
   
   registrarBBDD(getCreatureName(winner),tonumber(getPlayerStorageValue(winner, storageMovements)))
   
   setGlobalStorageValue(globalPlayer1,-1)
   setGlobalStorageValue(globalPlayer2,-1)
   
   setPlayerStorageValue(winner, storageMovements, -1)
   setPlayerStorageValue(loser, storageMovements, -1)   
   
   setPlayerStorageValue(winner, storage, -1)
   setPlayerStorageValue(loser, storage, -1)
   
   doTeleportThing(winner,newpos)
   doTeleportThing(loser,newpos)
   doSendMagicEffect(newpos,10)

return true
end

function registrarBBDD(winnername, moves)

   local sentencia = [[
   CREATE TABLE IF NOT EXISTS `chess_game` (
   `id` INT(11) NOT NULL AUTO_INCREMENT,
   `player1` VARCHAR(255) NOT NULL DEFAULT '0',
   `player2` VARCHAR(255) NOT NULL DEFAULT '0',
   `winner` VARCHAR(255) NOT NULL DEFAULT '0',
   `reason` VARCHAR(255) NOT NULL DEFAULT '0',
   `moves` INT(11) NOT NULL DEFAULT '0',
   PRIMARY KEY (`id`))
   ]]
   db.executeQuery(sentencia)
   
   local reason = "Derrota enemiga"
   db.executeQuery('INSERT INTO `chess_game` (`player1` ,`player2` ,`winner` ,`reason` ,`moves`) VALUES ("' .. getGlobalStorageValue(globalPlayer1) .. '", "' .. getGlobalStorageValue(globalPlayer2) .. '", "' .. winnername .. '", "'..reason..'", ' .. moves .. ');')
   
return true
end

function movimientoCorrecto(cid, pieza, color, frompos, topos)
local distance = getDistanceBetween(frompos, topos)
local ficha = getThingFromPos({x=topos.x, y=topos.y, z=topos.z, stackpos = 1})
local itemid = ficha.itemid
   if pieza == 'peon' then 
      if distance == 2 and frompos.x == topos.x and not casillaOcupada(topos) then -- primer movimiento de peon desde la salida
         if (color == 'blanco' and frompos.y > topos.y and frompos.y == esquinaI.y-1) or 
         (color == 'negro' and frompos.y < topos.y and frompos.y == esquinaS.y+1) then 
            setPlayerStorageValue(cid, storageMovements, getPlayerStorageValue(cid, storageMovements)+1)
            return true         
         end
      end
      if distance > 1 then return false end
      if frompos.y == topos.y then return false end -- si se mueve de lado
      if (color == 'blanco' and frompos.y < topos.y) or (color=='negro' and frompos.y > topos.y) then -- chekea que avancen hacia alante
         return false end
      if topos.x ~= frompos.x then 
         if casillaOcupada(topos) then --chekea que alla blanco o negro sino no entra
            if checkColorMove(color, topos) then return false end
            return eliminarPieza(cid,ficha,topos)
         else return false
         end
      end
      if not casillaOcupada(topos) then --return true 
      else return false
      end
   elseif pieza == 'torre' then
      if frompos.x ~= topos.x and frompos.y ~= topos.y then return false end
      if frompos.x ~= topos.x then
         for i=1, math.abs(frompos.x - topos.x)-1 do
            if frompos.x < topos.x then
               if casillaOcupada({x=frompos.x+i, y=frompos.y, z=frompos.z}) then return false end
            else
               if casillaOcupada({x=frompos.x-i, y=frompos.y, z=frompos.z}) then return false end
            end
         end
         if casillaOcupada(topos) then 
            if checkColorMove(color, topos) then return false end
            return eliminarPieza(cid,ficha,topos)
         end
      else
         for i=1, math.abs(frompos.y - topos.y)-1 do
            if frompos.y < topos.y then
               if casillaOcupada({x=frompos.x, y=frompos.y+i, z=frompos.z}) then return false end
            else
               if casillaOcupada({x=frompos.x, y=frompos.y-i, z=frompos.z}) then return false end
            end
         end
         if casillaOcupada(topos) then 
            if checkColorMove(color, topos) then return false end
            return eliminarPieza(cid,ficha,topos)
         end
      end
      --return true
   elseif pieza == 'alfil' then
      if (math.abs(frompos.x-topos.x))-(math.abs(frompos.y-topos.y)) ~= 0 then return false end
      if frompos.x < topos.x then
         for i=1, math.abs(frompos.x - topos.x)-1 do
            if frompos.y > topos.y then
               if casillaOcupada({x=frompos.x+i, y=frompos.y-i, z=frompos.z}) then return false end
            else
               if casillaOcupada({x=frompos.x+i, y=frompos.y+i, z=frompos.z}) then return false end
            end
         end
      else
         for i=1, math.abs(frompos.x - topos.x)-1 do
            if frompos.y > topos.y then
               if casillaOcupada({x=frompos.x-i, y=frompos.y-i, z=frompos.z}) then return false end
            else
               if casillaOcupada({x=frompos.x-i, y=frompos.y+i, z=frompos.z}) then return false end
            end
         end
      end
      if casillaOcupada(topos) then
         if checkColorMove(color, topos) then return false end
         return eliminarPieza(cid,ficha,topos)
      end
      --return true
   elseif pieza == 'reina' then
      if frompos.x == topos.x or frompos.y == topos.y or (math.abs(frompos.x-topos.x))-(math.abs(frompos.y-topos.y)) == 0 then
         local to = math.abs(frompos.x - topos.x)
         if to == 0 then
            to = math.abs(frompos.y - topos.y)
         end
         for i=1, to-1 do -- si es de i=1 a 0 no entramos en el for
            if frompos.x == topos.x and frompos.y > topos.y then -- hacia arriba
               if casillaOcupada({x=frompos.x, y=frompos.y-i, z=frompos.z}) then return false end
            elseif frompos.x == topos.x and frompos.y < topos.y then -- hacia abajo
               if casillaOcupada({x=frompos.x, y=frompos.y+i, z=frompos.z}) then return false end
            elseif frompos.y == topos.y and frompos.x < topos.x then -- hacia derecha
               if casillaOcupada({x=frompos.x+i, y=frompos.y, z=frompos.z}) then return false end
            elseif frompos.y == topos.y and frompos.x > topos.x then -- hacia izquiera
               if casillaOcupada({x=frompos.x-i, y=frompos.y, z=frompos.z}) then return false end
            elseif frompos.x < topos.x and frompos.y > topos.y then -- diagonal hacia derecha arriba
               if casillaOcupada({x=frompos.x+i, y=frompos.y-i, z=frompos.z}) then return false end
            elseif frompos.x < topos.x and frompos.y < topos.y then -- diagonal hacia derecha abajo
               if casillaOcupada({x=frompos.x+i, y=frompos.y+i, z=frompos.z}) then return false end
            elseif frompos.x > topos.x and frompos.y > topos.y then -- diagonal hacia izquierda arriba
               if casillaOcupada({x=frompos.x-i, y=frompos.y-i, z=frompos.z}) then return false end
            else -- diagonal hacia izquierda abajo
               if casillaOcupada({x=frompos.x-i, y=frompos.y+i, z=frompos.z}) then return false end
            end
         end
         if casillaOcupada(topos) then
            if checkColorMove(color, topos) then return false end
            return eliminarPieza(cid,ficha,topos)
         end
         --return true
      else return false
      end
   elseif pieza == 'rey' then
      if distance > 1 then return false end
      if casillaOcupada(topos) then
         if checkColorMove(color, topos) then return false end
         return eliminarPieza(cid,ficha,topos)
      end
      --return true
   elseif pieza == 'caballo' then
      if distance ~= 2 then return false end -- los movimientos del caballo siempre estan a distancia 2
      if frompos.x == topos.x or frompos.y == topos.y then return false end -- nunca caera en el mismo x ni y 
      --(ahora las unicas posibilidades son x-y 2-1, o 1-2)
      if math.abs(frompos.x - topos.x) == 1 and math.abs(frompos.y - topos.y) == 1 then return false end -- movimiento no L {x-y:(2-1 o 1-2)}
      if math.abs(frompos.x - topos.x) == 2 and math.abs(frompos.y - topos.y) == 2 then return false end -- movimiento no L {x-y:(2-1 o 1-2)}
      --cualquier movimiento posible ahora es correcto, tansolo chekar encima de Qué cae.
      if casillaOcupada(topos) then
         if checkColorMove(color, topos) then return false end
         return eliminarPieza(cid,ficha,topos)
      end
      --return true
   end
   --blancas reducen la Y al avanzar, negras aumentan la Y al avanzar
   
setPlayerStorageValue(cid, storageMovements, getPlayerStorageValue(cid, storageMovements)+1)
return true
end

function onMoveItem(moveItem, frompos, position, cid)

   if posEnArea(frompos, esquinaS.x, esquinaI.x, esquinaS.y, esquinaI.y, esquinaS.z) then
      if not posEnArea(position, esquinaS.x, esquinaI.x, esquinaS.y, esquinaI.y, esquinaS.z) then
         return doPlayerSendTextMessage(cid,25,'Las piezas no han de salir del tablero') and false
      end
   end
   if posEnArea(position, esquinaS.x, esquinaI.x, esquinaS.y, esquinaI.y, esquinaS.z) then
      if not(isInArray(negras, moveItem.itemid) or isInArray(blancas, moveItem.itemid)) then
         doPlayerSendTextMessage(cid,25,'No se pueden tirar objetos al tablero!')
         return false
      end
      local piece = table.find(blancas, moveItem.itemid)
      local color = 'blanco'
      if piece==nil then 
         piece = table.find(negras, moveItem.itemid)
         color = 'negro'
      end
      
      if getPlayerStorageValue(cid,storage) ~= color then
         doPlayerSendTextMessage(cid,25,'Tansolo puedes mover las fichas de tu color!')
         return false
      end
      
      if (color == 'blanco' and getPlayerStorageValue(cid, storageMovements) > getPlayerStorageValue(getCreatureByName(getGlobalStorageValue(globalPlayer2)), storageMovements)) or
      (color == 'negro' and getPlayerStorageValue(cid, storageMovements) == getPlayerStorageValue(getCreatureByName(getGlobalStorageValue(globalPlayer1)), storageMovements)) then
         doPlayerSendTextMessage(cid,25,'Es el turno de tu adversario!')
         return false
      end
         
      if movimientoCorrecto(cid, piece, color, frompos, position) then --moveItem(topos...) --el mismo metodo ya matara la ficha si la hay
         if piece == 'peon' and ((color == 'blanco' and position.y == esquinaS.y) or (color == 'negro' and position.y == esquinaI.y)) then
            local cambio = color=='blanco' and blancas.reina or negras.reina
            return doTransformItem(moveItem.uid, cambio) and true
         end
         return true
      else
         return doPlayerSendTextMessage(cid,25,'Movimiento incorrecto.') and false
      end
   end
   return true
end

actions.xml:
XML:
<!-- Ajedrez (con lever), poner fichar en el tablero -->
   <action actionid="7002" event="script" value="chesslever.lua"/>

/scripts/chesslever.lua:
Lua:
--Credits: Strack -> [url=http://otland.net/members/strack/]View Profile: Strack - OtLand[/url]

local player1pos = {x = 937, y = 1014, z = 8, stackpos=253}
local player2pos = {x = 939, y = 1014, z = 8, stackpos=253}

local player1newpos = {x = 937, y = 1022, z = 8} -- blancas
local player2newpos = {x = 937, y = 1019, z = 8} -- negras

local esquinaS = {x=934, y=1017, z=8} --esquina superior izquiera del tablero
local esquinaI = {x=941, y=1024, z=8} --esquina inferior derecha del tablero

local storage = 14757 -- storage chess system (color)
local storageMovements = 14758 -- storage chess system (movimientos)

local globalPlayer1 = 10000 -- player blanco
local globalPlayer2 = 10001 -- player negro

local negras = {
peon = 2632,
torre = 2633,
caballo = 2634,
alfil = 2635,
reina = 2637,
rey = 2636
}
local blancas = {
peon = 2626,
torre = 2627,
caballo = 2628,
alfil = 2629,
reina = 2631,
rey = 2630
}

local order = {'torre','caballo','alfil','rey','reina','alfil','caballo','torre'}

local function reiniciarTablero()
   for tablerox = esquinaS.x, esquinaI.x do
      for tableroy = esquinaS.y, esquinaI.y do
         tableropos = {x=tablerox, y=tableroy, z=8, stackpos=1}
         tableroItem = getThingfromPos(tableropos)
         if table.find(blancas, tableroItem.itemid) or table.find(negras, tableroItem.itemid) then
            doRemoveItem(tableroItem.uid)
         end
      end
   end
   
   for i=0,7 do
      doCreateItem(negras[order[i+1]], {x=esquinaS.x+i,y=esquinaS.y,z=esquinaS.z}) -- linea 1
      doCreateItem(negras.peon, {x=esquinaS.x+i,y=esquinaS.y+1,z=esquinaS.z}) -- peones
      
      doCreateItem(blancas[order[i+1]], {x=esquinaS.x+i,y=esquinaI.y,z=esquinaI.z}) -- linea 1
      doCreateItem(blancas.peon, {x=esquinaS.x+i,y=esquinaI.y-1,z=esquinaI.z}) -- peones
   end
   
end

function onUse(cid, item, frompos, item2, topos)
   if item.itemid == 1945 then
      player1 = getThingfromPos(player1pos)
      player2 = getThingfromPos(player2pos)

      if player1.itemid > 0 and player2.itemid > 0 then
         player1level = getPlayerLevel(player1.uid)
         player2level = getPlayerLevel(player2.uid)

         for tablerox = esquinaS.x, esquinaI.x do
            for tableroy = esquinaS.y, esquinaI.y do
               tableropos = {x=tablerox, y=tableroy, z=8, stackpos=253}
               tablerocreature = getThingfromPos(tableropos)
               if tablerocreature.itemid > 0 then
                  doPlayerSendCancel(cid,"Espera a que terminen los que estan jugando.")
               return 1
               end
            end
         end
         
         reiniciarTablero()

         doSendMagicEffect(player1pos,CONST_ME_POFF)
         doSendMagicEffect(player2pos,CONST_ME_POFF)

         doTeleportThing(player1.uid,player1newpos)
         doTeleportThing(player2.uid,player2newpos)

         doSendMagicEffect(player1newpos,10)
         doSendMagicEffect(player1newpos,10)
         
         setPlayerStorageValue(player1.uid, storage, 'blanco')
         setPlayerStorageValue(player2.uid, storage, 'negro')
         
         setPlayerStorageValue(player1.uid, storageMovements, 0)
         setPlayerStorageValue(player2.uid, storageMovements, 0)
         
         setGlobalStorageValue(globalPlayer1,getCreatureName(player1.uid))
         setGlobalStorageValue(globalPlayer2,getCreatureName(player2.uid))
         
         --doPlayerSendTextMessage(cid,25,"Player 1: "..getGlobalStorageValue(globalPlayer1))
         --doPlayerSendTextMessage(cid,25,"Player 2: "..getGlobalStorageValue(globalPlayer2))
      else
         doPlayerSendCancel(cid,"Necesitas dos players para jugar.")
      end
   else
      return 0
      end
   return 1
end

talkactions.xml:
XML:
<talkaction words="!surrender" event="script" value="surrenderChess.lua"/>

/scripts/surrenderChess.lua:
Lua:
--Credits: Strack -> [url=http://otland.net/members/strack/]View Profile: Strack - OtLand[/url]

local esquinaS = {x=934, y=1017, z=8} --esquina superior izquiera del tablero
local esquinaI = {x=941, y=1024, z=8} --esquina inferior derecha del tablero

local storage = 14757 -- storage chess system (color)
local storageMovements = 14758 -- storage chess system (movimientos)

local globalPlayer1 = 10000 -- player blanco
local globalPlayer2 = 10001 -- player negro

local newpos = {x=933,y=1016,z=7} -- pos cuando abandona la partida 

function posEnArea(pos, x1, x2, y1, y2, zz)
   if pos.z ~= zz then return false end

   for areax = x1, x2 do
      for areay = y1, y2 do
         if areax == pos.x and areay == pos.y then
            return true
         end
      end
   end
   return false
end

function registrarBBDD(winnername, moves)

   local sentencia = [[
   CREATE TABLE IF NOT EXISTS `chess_game` (
   `id` INT(11) NOT NULL AUTO_INCREMENT,
   `player1` VARCHAR(255) NOT NULL DEFAULT '0',
   `player2` VARCHAR(255) NOT NULL DEFAULT '0',
   `winner` VARCHAR(255) NOT NULL DEFAULT '0',
   `reason` VARCHAR(255) NOT NULL DEFAULT '0',
   `moves` INT(11) NOT NULL DEFAULT '0',
   PRIMARY KEY (`id`))
   ]]
   db.executeQuery(sentencia)
   
   local reason = "Abandono enemigo"
   db.executeQuery('INSERT INTO `chess_game` (`player1` ,`player2` ,`winner` ,`reason` ,`moves`) VALUES ("' .. getGlobalStorageValue(globalPlayer1) .. '", "' .. getGlobalStorageValue(globalPlayer2) .. '", "' .. winnername .. '", "'..reason..'", ' .. moves .. ');')
   
return true
end

function onSay(cid, words, param, channel)
   
local cidpos = getCreaturePosition(cid)
local cidname = getCreatureName(cid)

   if not posEnArea(cidpos,esquinaS.x,esquinaI.x,esquinaS.y,esquinaI.y,esquinaS.z) then
      doPlayerSendTextMessage(cid,25,'No estas dentro del tablero de ajedrez.')
      doSendMagicEffect(cidpos,CONST_ME_POFF)
      return false
   end
   
   if getPlayerStorageValue(cid, storage) == -1 or (getGlobalStorageValue(globalPlayer1) ~= cidname and getGlobalStorageValue(globalPlayer2) ~= cidname) then
      doPlayerSendTextMessage(cid,25,'No estas en una partida ahora mismo.')
      doSendMagicEffect(cidpos,CONST_ME_POFF)
      return false
   end
   
local enemyname = getGlobalStorageValue(globalPlayer1) ~= cidname and getGlobalStorageValue(globalPlayer1) or getGlobalStorageValue(globalPlayer2)
local enemy = getCreatureByName(enemyname)
   
   registrarBBDD(enemyname,tonumber(getPlayerStorageValue(enemy, storageMovements)))
   
   setGlobalStorageValue(globalPlayer1,-1)
   setGlobalStorageValue(globalPlayer2,-1)
   
   setPlayerStorageValue(cid, storageMovements, -1)
   setPlayerStorageValue(enemy, storageMovements, -1)   
   
   setPlayerStorageValue(cid, storage, -1)
   setPlayerStorageValue(enemy, storage, -1)
   
   doTeleportThing(cid,newpos)
   doTeleportThing(enemy,newpos)
   doSendMagicEffect(newpos,10)
   
   doPlayerSendTextMessage(cid,25,'Has perdido!')
   doPlayerSendTextMessage(enemy,25,'Has ganado!')

return true
end


Now, an image and some explanations about how to configure it.



Lua:
local esquinaS = {x=934, y=1017, z=8} --esquina superior izquiera del tablero
local esquinaI = {x=941, y=1024, z=8} --esquina inferior derecha del tablero
these are the corners of the board, 'esquinaS' upper left corner, 'esquinaI' lower right corner.

Lua:
local storage = 14757 -- storage chess system (color)
local storageMovements = 14758 -- storage chess system (movimientos)
make sure these storages are not being used

Lua:
local globalPlayer1 = 10000 -- player blanco
local globalPlayer2 = 10001 -- player negro
not many ppl use this kind of storage, but make sure they are not being used

Lua:
local newpos = {x=933,y=1016,z=7} -- pos cuando abandona la partida
where the players will be tp when match finishes

Lua:
local player1pos = {x = 937, y = 1014, z = 8, stackpos=253}
local player2pos = {x = 939, y = 1014, z = 8, stackpos=253}
in chesslever.lua, where the players must be to use the switch

Lua:
local player1newpos = {x = 937, y = 1022, z = 8} -- blancas
local player2newpos = {x = 937, y = 1019, z = 8} -- negras
in chesslever.lua, where players will be tp when using switch

Lua:
local negras = {
peon = 2632,
torre = 2633,
caballo = 2634,
alfil = 2635,
reina = 2637,
rey = 2636
}
local blancas = {
peon = 2626,
torre = 2627,
caballo = 2628,
alfil = 2629,
reina = 2631,
rey = 2630
}
I suppose that in almost every OT this ID are the same, if not, just edit them here.

Hope you enjoy it.

Regards, Strack.
 
Looks very nice, can be shorted. But yeah looks nice :D
 
Thanks, and yes, can be shorted but not so much I think. I just made it this way to make it easy to understand for every1
 
This looks really cool, its actually pretty funny that Sportacus and I were just talking about this a few days ago, problem was that I have never played chess so I had no idea what the rules were :( glad to see someone does though!
 
Back
Top