Registrarse

[Script] Pokérdle: El Wordle de Pokémon

samuko

Profesional de WaH
¡Buenas! No sé si este es el foro correcto XD
He creado un Script para jugar al juego que la mayoría conoceréis: el Wordle. Consiste en adivinar una palabra de (normalmente) 5 letras probando con otras palabras y viendo las letras que coinciden. El Pokérdle consiste en adivinar una palabra relacionada con Pokémon: el nombre de una especie, un movimiento, una habilidad, un objeto...

Podéis copiar el Script en vuestro juego de RPG Maker o podéis jugarlo directamente en el link de descarga.
Poco más que decir, espero que os guste. :)

Ruby:
# =============================================================================
# ** Pokérdle by Samuko

# You can copy this page and paste in your Pokemon Essentials scripts.
# To use it, copy the "Data/wordle.dat" file and call method 'pbWordle'
# Credits: www.listapalabras.com
# =============================================================================

# letters = nº de letras
# eventstore = ID del evento en el que se almacenan los datos
# varresult = Variable para guardar el resultado: -1 = pierde, 0 = pospone, 1 = gana
# varattempts = Variable para guardar el número de intentos
# tries = Número de intentos. Por defecto, 6
# firsttime = :  true = Si se juega por primera vez. Por defecto, el valor contrario al Interruptor Local "A"
#  El evento de eventstore debe ser distinto al evento que llama esta función si
#  se quiere programar una partida diaria.
def pbWordle(letters,eventstore,varresult,varattempts,tries=6,firsttime=(!$game_self_switches[[$game_map.map_id,eventstore,"A"]] rescue false))
    data = load_data("Data/wordle.dat")
    store = $PokemonGlobal.eventvars[[$game_map.map_id,eventstore]] rescue nil # If paused
    word = store[0] if store
    inputs = store[1] if store
    dictionary = nil
    if letters == 5
        word = data[0].sample
        dictionary = data[0] | data[2]
    else
        word = data[1].sample
        dictionary = data[1] | data[3]
    end
    inputs = [] if !inputs
    WordleScene.start(word,tries,dictionary,inputs)
    Kernel.pbMessage(_INTL("Utiliza el ratón para escribir una palabra de {1} letras. Luego dale a 'OK'.",
        letters)) {    WordleScene.update } if firsttime
    att = nil
    result = WordleScene.scene { |attempt,input,matches|
        if firsttime && attempt == 1
            Kernel.pbMessage(_INTL("¡Muy bien! Veamos la palabra que has introducido.")) {WordleScene.update}
            Kernel.pbMessage(input.join("")) {WordleScene.update}
            green = Array.new(letters) { |i| matches[i] == 1 ? input[i] : nil    }.compact
            yellow = Array.new(letters) { |i| matches[i] == 0 ? input[i] : nil    }.compact
            black = Array.new(letters) { |i| matches[i] == -1 ? input[i] : nil    }.compact
            Kernel.pbMessage(_INTL("Las letras {1} coinciden en posición con la palabra.",green.join(", "))) {WordleScene.update} if !green.empty?
            Kernel.pbMessage(_INTL("Las letras {1} no coinciden en posición, pero están en la palabra.",yellow.join(", "))) {WordleScene.update} if !yellow.empty?
            Kernel.pbMessage(_INTL("Las letras {1} no están en la palabra.",black.join(", "))) {WordleScene.update} if !black.empty?
            Kernel.pbMessage(_INTL("¡Sigue así! Te quedan {1} intentos.",tries-attempt)) {WordleScene.update}
        end
        inputs.push(input)
        att = attempt
    }
    if result == 0 # Paused
        $PokemonGlobal.eventvars[[$game_map.map_id,eventstore]] = [word,inputs]
    else
        $PokemonGlobal.eventvars[[$game_map.map_id,eventstore]] = nil
    end if eventstore > 0
    pbSet(varattempts,att)
    pbSet(varresult,result)
    Kernel.pbMessage(_INTL("¡Enhorabuena! ¡Has acertado la palabra!")) {WordleScene.update} if firsttime && result == 1
    if result == -1
        Kernel.pbMessage(_INTL("¡Oh!... Bueno, lo importante es participar.")) {WordleScene.update}
        Kernel.pbMessage(_INTL("La palabra era '{1}'.",word)) {WordleScene.update}
    end
    WordleScene.dispose
end

module WordleScene
    GREY             = Color.new(198,198,198)
    BLACK            = Color.new(256,256,256)
    GREEN            = Color.new(0,255,0)
    YELLOW        = Color.new(255,192,0)
    DARKGREY    = Color.new(128,128,128)

    @@viewport = @@sprites = @@inputs = @@word = nil
    @@rect = @@attempt = @@matches = nil

    def self.start(word,tries,dictionary,inputs=[])
        @@inputs = inputs.clone
        @@word = word.split("")
        @@dictionary = dictionary
        @@tries = tries
        @@attempt = @@inputs.length
        @@matches = inputs.map { |a| self.match(a) }
        letters = word.length
        width = 32
        height = 32
        @@rect = Rect.new(0,0,width,height)
        @@viewport = Viewport.new(0,0,Graphics.width,Graphics.height); @@viewport.z = 99999
        @@sprites = {}
        @@sprites["bg"] = s = SpriteWrapper.new(@@viewport)
        s.z = 1
        s.bitmap = BitmapWrapper.new(Graphics.width,Graphics.height)
        s.bitmap.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(255,255,255))
        # Output
        for i in 0...letters
            for j in 0...@@tries
                @@sprites["tries#{i}#{j}"] = s = SpriteWrapper.new(@@viewport)
                s.bitmap = b = BitmapWrapper.new(width,height)
                s.y = 6 + 42*j
                s.x = (Graphics.width-(width+10)*(letters-1)-width)/2 + (width+10)*i # 5: 156 + 42y
                s.z = 5
            end
        end
        # Teclado
        k = "QWERTYUIOP".split("")
        for i in 0...10
            @@sprites["key_#{i}0"] = s = SpriteWrapper.new(@@viewport)
            s.bitmap = b = BitmapWrapper.new(width,height)
            s.y = 276
            s.x = 78 + (width+4)*i
            s.z = 10
        end
        k = "ASDFGHJKLZXCVBNM".split("")/9
        for j in 0...2
            for i in 0...9
                next if !k[j][i]
                @@sprites["key_#{i}#{j+1}"] = s = SpriteWrapper.new(@@viewport)
                s.bitmap = b = BitmapWrapper.new(width,height)
                s.y = 312 + (height+4)*j
                s.x = 96 + (width+4)*i
                s.z=10
            end
        end
        @@sprites["key_back"] = s = SpriteWrapper.new(@@viewport)
        s.bitmap = b = BitmapWrapper.new(68,height)
        s.y = 312 + (height+4)
        s.x = 348
        s.z=10
        @@sprites["key_enter"] = s = SpriteWrapper.new(@@viewport)
        s.bitmap = b = BitmapWrapper.new(width*2,height*2)
        s.y = 312
        s.x = 420
        s.z=10
        self.refresh
        pbFadeInAndShow(@@sprites)
    end

    def self.scene
        @@inputs.push([])
        loop do
            self.update
            if Input.triggerex?(Input::LeftMouseKey)
                input = self.getInput
                next self.draw_letter(input) if input.is_a?(String)
                next self.clear_last_letter if input == 0
                break if self.enter if input == 1
            elsif Input.triggerex?(Input::RightMouseKey)
                pbPlayCancelSE
                return 0 # Cancel
            end
        end
        # Here, there's a new word given
        @@attempt += 1
        yield(@@attempt,@@inputs.last,@@matches.last) if block_given?
        refresh_keyboard
        if @@inputs.last == @@word # WON!!
            return 1
        end
        if @@inputs.length >= @@tries # LOST!!
            return -1
        end
        # Continue
        self.scene { |a,b,c|   yield(a,b,c) if block_given? }
    end

    def self.draw_letter(letter)
        letters = @@inputs.last
        return false if letters.length >= @@word.length
        pbPlayCursorSE
        j_index = @@attempt
        i_index = letters.length
        letters.push(letter)
        @@sprites["tries#{i_index}#{j_index}"].bitmap.draw_text(@@rect,letter,1)
        return true
    end

    def self.draw_letter_ex(j,i)
        m = @@matches[j][i]
        b = @@sprites["tries#{i}#{j}"].bitmap
        b.clear
        b.fill_rect(@@rect,m==1 ? GREEN : (m==0 ? YELLOW : DARKGREY))
        b.draw_text(@@rect,@@inputs[j][i],1)
    end

    def self.clear_last_letter
        letters = @@inputs.last
        return false if letters.empty?
        j_index = @@attempt
        i_index = letters.length-1
        letters.pop
        b = @@sprites["tries#{i_index}#{j_index}"].bitmap
        b.clear
        b.fill_rect(@@rect,GREY)
        return true
    end

    def self.enter
        numlets = @@word.length
        letters = @@inputs.last
        j_index = @@attempt
        if letters.length < numlets
            Kernel.pbMessage(_INTL("\\r¡Debes introducir #{numlets} letras!")) {update}
            return false
        end
        # Not in dic
        if !(@@dictionary === letters.join(""))
            Kernel.pbMessage(_INTL("\\r¡Esa palabra no existe en el diccionario!")) {update}
            return false
        end
        matches = self.match(letters)
        @@matches.push(matches)
        # Animation
        numlets.times do |i|
            self.draw_letter_ex(j_index,i)
            pbPlayDecisionSE
            20.times { update }
        end
        return true
    end

    def self.match(letters)
        numlets = letters.length
        # Find matches
        matches = []
        for i in 0...numlets
            if letters[i] == @@word[i] # Full match
                matches.push(1)
            else
                if @@word === letters[i] # Word includes letter
                    matches.push(0)
                else
                    matches.push(-1)
                end
            end
        end
        # Now double check matches TODO
        for i in 0...numlets
            next if matches[i] != 0
            let = letters[i] # Letra que aparece en otra posicion
            eqls = @@word.filter { |l| l==let } # Not empty
            for j in 0...eqls.length
                next if i == j
                if letters[j] == let && matches[j] == 1 # !!!
                    matches[i] = -1
                end
            end
        end
        return matches
    end

    def self.update
        Graphics.update
        Input.update
        pbUpdateSpriteHash(@@sprites)
    end

    def self.getInput
        x,y = Mouse::getMousePos(true)
        return 1 if (312...376) === y && (420...484) === x # OK
        case y
        when 276...308
            i = (x-78)/36
            return "QWERTYUIOP".split("")[i] if (0...10) === i
        when 312...344
            i = (x-96)/36
            return "ASDFGHJKL".split("")[i] if (0...9) === i
        when 348...380
            i = (x-96)/36
            return "ZXCVBNM".split("")[i] if (0...7) === i
            return 0 if (7...9) === i # Delete
        end
        return nil
    end

    def self.refresh
        letters = @@word.length
        @@sprites["bg"].bitmap.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(255,255,255))
        # Output
        for i in 0...letters
            for j in 0...@@tries
                b = @@sprites["tries#{i}#{j}"].bitmap
                b.clear
                b.fill_rect(@@rect,GREY)
                pbSetSystemFont(b)
                if @@inputs[j] && @@inputs[j][i]
                    self.draw_letter_ex(j,i)
                end
            end
        end
        # Teclado
        refresh_keyboard
    end

    def self.refresh_keyboard
        #width = height = 32
        k = "QWERTYUIOP".split("")
        for i in 0...10
            b = @@sprites["key_#{i}0"].bitmap
            b.clear
            pbSetSystemFont(b)
            b.font.color = BLACK
            m = findMatch(k[i]) # => Integer: -2..1
            b.fill_rect(@@rect,[GREY,DARKGREY,YELLOW,GREEN][m+2])
            b.draw_text(@@rect,k[i],1)
        end
        k = "ASDFGHJKLZXCVBNM".split("")/9
        for j in 0...2
            for i in 0...9
                next if !k[j][i]
                b = @@sprites["key_#{i}#{j+1}"].bitmap
                pbSetSystemFont(b)
                b.font.color = BLACK
                m = findMatch(k[j][i]) # => Integer: -2..1
                b.fill_rect(@@rect,[GREY,DARKGREY,YELLOW,GREEN][m+2])
                b.draw_text(@@rect,k[j][i],1)
            end
        end
        b = @@sprites["key_back"].bitmap
        b.clear
        b.fill_rect(0,0,68,32,GREY)
        pbSetSystemFont(b)
        b.draw_text(0,0,68,32,"<-",1)
        b = @@sprites["key_enter"].bitmap
        b.fill_rect(0,0,32*2,32*2,GREY)
        pbSetSystemFont(b)
        b.draw_text(0,0,32*2,32*2,"OK",1)
    end

    def self.dispose
        pbFadeOutAndHide(@@sprites)
        pbDisposeSpriteHash(@@sprites)
        @@viewport.dispose
    end

    def self.findMatch(letter)
        m = -2
        for j in 0...@@inputs.length
            for i in 0...@@inputs[j].length
                if letter == @@inputs[j][i]
                    newm = @@matches[j][i]
                    m = newm if newm > m
                end
            end
        end
        return m
    end
end

def pbSaveWordle(letters,word,dictionary=false)
    data = load_data("Data/wordle.dat")
    i = dictionary ? 2 : 0
    i += 1 if letters != 5
    if word.is_a?(Array)
        data[i] += word
    else
        data[i].push(word)
    end
    save_data(data,"Data/wordle.dat")
end

def pbDeleteWordle(letters,word,dictionary)
    data = load_data("Data/wordle.dat")
    i = dictionary ? 2 : 0
    i += 1 if letters != 5
    if word.is_a?(Array)
        data[i] -= word
    else
        data[i].delete(word)
    end
    save_data(data,"Data/wordle.dat")
end

def pbWordleHas?(word,dictionary=false)
    data = load_data("Data/wordle.dat")
    return data.any? { |a| a.include?(word) }
end

class Array
    # Return a random element.
    def sample
        return self[rand(self.length)]
    end unless method_defined?(:sample)
   
    # Return the sum of its elements plus init.
    def sum(init=0)
        ret = init
        self.each do |i|
            ret += i # TypeError if i isn't a Numeric
        end
        return ret
    end unless method_defined?(:sum)
   
    # Group its elements into arrays of length=v
    # E.g. ["a","b","c","d"] / 2 => [["a","b"],["c","d"]]
    # E.g. ["a","b","c","d","e"] / 2 => [["a","b"],["c","d"],["e"]]
    # E.g. a = ["a","b","c","d","e"]
    #            a/=2 => [["a","b"],["c","d"],["e"]]
    #            a.delete_if {|it| it.length != 2}
    # E.g. ["a","b"]/0 => ZeroDivisionError
    # E.f. ["a","b"]/"a" => TypeError
    def /(v)
        ret = []
        for i in 0...self.length
            ret.push([]) if i % v == 0
            ret.last[ret.last.length] = self[i]
        end
        return ret
    end

    def any?(&block)
        return map(&block).include?(true)
    end unless method_defined?(:any?)

    def all?(&block)
        return !map(&block).include?(false)
    end unless method_defined?(:all?)

    def filter!(&block)
        return self.delete_if { |it| next !yield(it) }
    end unless method_defined?(:filter!)

    def filter(&block)
        return dup.filter!(&block)
    end unless method_defined?(:filter)
    alias intersect filter

    alias_method :===, :include?
end
Capturas

Captura de pantalla (105).png
Captura de pantalla (106).png
Varias cosas que aclarar
  • Se pueden poner palabras de los juegos o palabras españolas. Para ello he usado el diccionario de listapalabras.com el cual es limitado en cuanto a género, número y verbos.
  • Las letras en amarillo no funcionan del todo bien.
  • La interfaz es cutre, lo sé XD pero quería centrarme en el Script en sí más que en lo gráfico.
Cualquier aportación para mejorarlo es bienvenida. ^^
 
Arriba