Dibujos hechos por la tortuga de BloquePy

El mundo de la tortuga

BloquePy retoma el espíritu de Logo — aprender programando, viendo cada instrucción convertirse en dibujo — y lo combina con el poder real de Python. Pero no se queda ahí: le suma su propia capa, Patches, un "ambiente" de fondo pensado para simulaciones completas, y un panel de datos para graficar, medir y exportar lo que esa simulación va haciendo. El resultado es un concepto nuevo: ya no solo dibujar figuras, sino modelar mundos y analizarlos — física, química, biología, patrones — arrastrando bloques. Esta página muestra todo lo que se puede hacer con la tortuga, y al final hay 19 programas completos para descargar y probar en Modo Libre.

En el CodeVerse cuentan que este taller ya estaba aquí mucho antes de que alguien lo encontrara — y que quien lo dejó así, a medio terminar, todavía sigue construyendo.

De bloques a simulación, en un solo programa

Este es un programa completo armado en Modo libre — no hay nada acá que no esté explicado más abajo en esta misma página: un mapa de calor sobre Patches, seis agentes con forma y color distintos dejando una cola de cometa (fadetrail) mientras orbitan, ocho flechas que apuntan de verdad hacia donde crece el calor (gradient), una leyenda de color, y un remate de sonido (play_note) al terminar. Nada de esto es una simulación de cómo se vería el código — es exactamente el código que corre.

Programa armado con bloques a la izquierda, y a la derecha el lienzo con un mapa de calor radial, seis agentes (ave, abeja, computadora, servidor, lobo, oveja) dejando colas de cometa de colores, ocho flechas apuntando al centro, y la leyenda de color
El programa (izquierda) y lo que dibuja al ejecutarlo (derecha)

El fondo es Patches pintado con heatcolor(...) según qué tan lejos está cada celda del centro — el mismo número que después usan las flechas: cada una se para en su celda con .patch(mundo) y se orienta con setheading(mundo.gradient(...)), así que apuntan de verdad hacia donde el calor crece más rápido, no a un ángulo fijo. Los seis agentes giran en anillos de radio distinto con un simple forward + right repetido, y fadetrail(40) hace que solo se vean los últimos 40 pasos de cada uno — la cola de cometa, en vez de una espiral que nunca se borra.

LO BASICO

Movimiento y rumbo

Cada tortuga nace en el centro (0, 0), mirando hacia arriba (rumbo 0°) — todo lo demás parte de ahí.

🐢

Crear una tortuga

No existe una tortuga "por defecto" — siempre se crea así, guardada en una variable. Todo lo demás se opera con .metodo() sobre esa variable.

t1 = Turtle()
➡️

Avanzar / retroceder

Camina en la dirección de su rumbo actual (o la contraria), dejando rastro si el lápiz está abajo.

t1.forward(50)
t1.backward(50)
↩️

Girar

Gira relativo a hacia donde ya miraba — no es un ángulo absoluto.

t1.right(90)
t1.left(90)
🎯

Saltar directo a un punto

Va en línea recta a (x, y) sin importar el rumbo — si el lápiz está abajo, dibuja esa línea recta.

t1.goto(30, 40)
🧭

Fijar el rumbo (absoluto)

A diferencia de right/left, este ángulo NO es relativo a donde miraba antes — 0° es arriba, 90° derecha, 180° abajo, 270° izquierda.

t1.setheading(90)

Círculo de un solo bloque

Aproxima un círculo con un polígono de muchos lados cortos — positivo gira a la izquierda, negativo a la derecha, mismo signo que el turtle real.

t1.circle(50)
DIBUJAR

Lápiz, color y relleno

Decidir si el movimiento deja rastro, de qué color, de qué grosor, y si encierra una figura rellena.

✏️

Levantar / bajar el lápiz

Con el lápiz arriba, moverse NO deja rastro — útil para reposicionar sin dibujar una línea de por medio.

t1.penup()
t1.pendown()
🎨

Color

Acepta un nombre conocido, un hexadecimal, o una tupla (r, g, b) de 0 a 255.

t1.color("red")
t1.color("#00FF00")
t1.color((255, 0, 0))

Grosor del trazo

1 es el grosor de siempre. Útil para representar una magnitud (masa, intensidad) con el ancho de la línea además del color.

t1.pensize(3)
🟩

Relleno

Un bloque en forma de C: todo lo que la tortuga camine ADENTRO se convierte en un contorno relleno al cerrar el bloque. Usa el color del trazo salvo que se fije uno propio con fillcolor(...).

t1.fill():
    t1.forward(60)
    t1.right(120)
    ... (repetir)
🌈

Color de relleno aparte

Cambia solo el color con el que se pinta ADENTRO — el trazo se queda con su propio color, para un contorno de un color y un relleno de otro.

t1.color("black")
t1.fillcolor("yellow")
☄️

Rastro tipo cola de cometa

A partir de ahora, el rastro de t1 nunca guarda más de esa cantidad de trazos — los más viejos se van cayendo solos, con un degradado de transparencia (el más nuevo opaco, el más viejo casi invisible). Sin esto, el rastro crece para siempre.

t1.fadetrail(60)
CONSULTAR

Preguntarle su propio estado

Leer dónde está o hacia dónde mira, para decidir algo con un if — por ejemplo, rebotar a mano en un borde.

📍

Posición actual

Las coordenadas (x, y) donde está parada ahora mismo.

t1.xcor()
t1.ycor()
🧭

Rumbo actual

El ángulo hacia donde mira ahora — el mismo número que usaría setheading(...) para dejarla igual.

t1.heading()
AGENTES

Forma y visibilidad

Vestir a cada tortuga según qué representa en la simulación, y "matarla" sin perder su estado.

🦎

Cambiar de forma

Trece formas disponibles hoy — pensadas para depredador-presa, parvadas, ciudad/bosque, diagramas de campo vectorial, y redes.

t1.shape("turtle")
t1.shape("wolf") · "sheep" · "bee" · "ant" · "bird"
"arbol" · "vehiculo" · "persona" · "point" · "flecha"
"computadora" · "servidor"
👻

Ocultar / mostrar

Oculta SOLO el ícono — no borra el rastro ya dibujado ni el estado de la tortuga: se le puede seguir preguntando .xcor(), etc. Es el mecanismo de "matar" a una presa cazada, o "apagar" una celda de un autómata celular sin perder su lugar en una lista.

t1.hideturtle()
t1.showturtle()
ENTRE AGENTES

Detectar a otras tortugas

Medir, apuntar y decidir "¿ya la encontré?" sin tener que escribir la fórmula de distancia a mano.

📏

Distancia a otra

Reemplaza la fórmula sqrt(...) que había que escribir a mano antes.

t1.distance(t2)
🧲

Rumbo hacia otra

Pensado para perseguir: setheading(towards(...)) seguido de forward(...) camina derecho hacia ella.

t1.setheading(t1.towards(t2))
t1.forward(20)
🤝

¿Se están tocando?

Verdadero/falso: ¿están lo bastante cerca como para contar como "encontradas"? Sin que tengas que inventar tu propio umbral con distance(...).

if t1.touching(t2):
🎯

La más cercana de un grupo

De una lista de tortugas, la más cercana a t1 (sin contarse a sí misma si aparece adentro) — reemplaza el for + comparación a mano de "¿cuál está más cerca?". Pensado para "la oveja huye del lobo más cercano".

mas_cercano = t1.nearest(lobos)
t1.setheading(t1.towards(mas_cercano))
🎱

Rebotar contra otra

Refleja el RUMBO de t1 como si hubiera chocado contra t2 (rebote tipo billar) — no mueve ni toca a t2. Para que las DOS reboten, llamalo también al revés. Pensado para simulaciones tipo partículas/gases.

if t1.touching(t2):
    t1.bounce(t2)
    t2.bounce(t1)
SIN MOVERSE

Marcas permanentes

Dejar una huella, un punto o un texto en el lienzo, sin que sea un agente vivo más.

👣

Sello

Deja una copia congelada en la posición actual — SIEMPRE una huella neutral, nunca la forma/color real de quien la dejó, para que se note a simple vista que es una marca y no un agente.

t1.stamp()
t1.clearstamps()
🔴

Punto

Un círculo de color fijo, sin mover a la tortuga — a diferencia de stamp(), no copia ningún ícono. Útil para marcar una posición como "partícula".

t1.dot(20)
🔤

Texto

Escribe cualquier valor en la posición actual — para etiquetar un contador directo en el lienzo, no solo en la terminal aparte.

t1.write("generación 5")
AJUSTE, NO CODIGO

Bordes del mundo

Qué le pasa a una tortuga cuando se sale del lienzo — se elige con el ícono de engranaje, no con un bloque.

A diferencia de todo lo demás en esta página, esto NO es un bloque que arrastras — es un ajuste del lienzo (el ícono de engranaje junto al de la chuleta de funciones), configurable por separado para el eje horizontal y el vertical.

🕊️

Libre

La tortuga puede salirse del lienzo — el comportamiento de siempre.

🌀

Infinito

Reaparece por el borde opuesto, como Pac-Man — el mundo se envuelve.

🏓

Rebota

Rebota como una pelota, sin cruzar el borde.

🧱

Pared

Se queda pegada al borde, sin cruzarlo.

MAS DE UN AGENTE

Varias tortugas a la vez

Cada tortuga creada es un objeto independiente, con su propio color, rastro y estado — todas conviven en el mismo lienzo.

No hace falta ningún bloque especial para "varias tortugas": basta con crear más de una y guardarlas donde convenga — sueltas en variables (lobo, oveja1, oveja2...) o juntas en una lista para recorrerlas con un for. Así están armadas las simulaciones de depredador-presa, parvadas y colonias de esta página: cada agente vive su propia vida, y el comportamiento de grupo — una parvada que vuela junta, una manada que persigue — surge solo de que muchos agentes simples conviven en el mismo lienzo.

JUEGOS Y SIMULACIONES INTERACTIVAS

Teclado y mouse

Leer lo que el jugador está haciendo AHORA MISMO, mientras el programa corre — algo que el turtle real de Python no trae de fábrica. Solo en Modo libre, tocando primero el lienzo para que agarre el foco de teclado.

⌨️

¿Está la tecla sostenida?

Verdadero mientras la tecla siga apretada — para movimiento continuo dentro de un ciclo. Nombres: "arriba"/"abajo"/"izquierda"/"derecha"/"espacio"/"enter"/"escape", o cualquier letra/dígito tal cual ("a", "1").

if key_pressed("derecha"):
    t1.forward(3)

¿Se acaba de apretar?

Verdadero UNA sola vez por apretón — se consume al leerse, así que no se repite en cada vuelta del ciclo mientras se sostiene. Para saltar/disparar, no para moverse. Con "escape" es la forma normal de cortar un while True: interactivo desde tu propio programa.

if key_just_pressed("espacio"):
    t1.stamp()
🖱️

Posición del mouse

Mismo sistema de coordenadas que xcor()/ycor() — útil para "seguir al mouse" o "aparecer donde tocaron".

mouse_x()
mouse_y()
👆

Clic sostenido / clic suelto

mouse_down() es continuo (para "arrastrar y pintar"); mouse_clicked() se consume igual que key_just_pressed.

if mouse_clicked():
    t1.goto(mouse_x(), mouse_y())
INSPIRADO EN NETLOGO

Patches: el ambiente

Una cuadrícula de fondo separada de las tortugas — celdas que solo tienen color, pensadas para simulaciones con MUCHAS celdas (mapas de calor, autómatas celulares, rastro de feromona).

Python real no tiene un concepto equivalente — esto es una pieza propia de BloquePy. Es el terreno ideal para todo lo que se piensa como una cuadrícula grande de celdas en vez de un puñado de agentes: un mapa de calor, un autómata celular, un rastro de feromona que se desvanece. Las tortugas y Patches conviven en el mismo lienzo — los agentes se mueven sobre el ambiente, y el ambiente puede reaccionar a ellos.

Crear la cuadrícula

Filas × columnas — una cuadrícula de celdas de color, independiente de las tortugas. Un 3er argumento opcional decide qué pasa en el borde: "wrap" (de siempre, el mundo se envuelve) o "wall" — una celda de borde tiene MENOS vecinas reales en vez de envolver, para cuando envolver no tiene sentido físico (un incendio no debería reaparecer del otro lado del mapa).

mundo = Patches(20, 20)
mundo = Patches(20, 20, "wall")

Leer / escribir una celda

Como una lista de listas — el segundo índice es obligatorio (indexar solo la fila da un objeto intermedio, no un color).

mundo[fila][columna] = "red"
mundo[fila][columna] = (0, 255, 0)
print(mundo[fila][columna])

Las 8 vecinas (con diagonales)

Devuelve una lista de 8 colores (r, g, b), uno por cada celda vecina — el mundo se envuelve en los bordes (la última fila es vecina de la primera).

mundo.neighbors(fila, columna)

Las 4 vecinas (sin diagonales)

Igual que neighbors, pero solo arriba/abajo/izquierda/derecha, EN ESE ORDEN — las diagonales no cuentan. En modo "wall", si una de las 4 no existe (estás en el borde) se omite de la lista en vez de inventarla.

mundo.neighbors4(fila, columna)

Difundir el color

Un paso de difusión: cada celda se mezcla un poco con el promedio de color de sus 8 vecinas (0 = nada cambia, 1 = queda exacto en el promedio). Corre de una sola vez sobre TODA la cuadrícula, mucho más rápido que hacerlo celda por celda a mano.

mundo.diffuse(0.3)

Además del color, cada celda guarda por separado un número — pensado para una cantidad real (temperatura, concentración, nivel de agua) que necesitás para hacer cuentas, sin que pintar la celda de otro color te lo borre. Mismas cuatro operaciones que el color, pero sobre ese número:

Leer el número de una celda

El número guardado en esa celda, independiente de su color — empieza en 0 si nunca se escribió.

mundo.value(fila, columna)

Escribir el número de una celda

A diferencia del color, el número no se escribe con = — es su propio bloque, con la fila, la columna y el valor nuevo.

mundo.setvalue(fila, columna, 8.5)

Números de las vecinas (8 y 4)

Como neighbors/neighbors4, pero devuelve una lista de NÚMEROS en vez de colores, en el mismo orden fijo (arriba, abajo, izquierda, derecha para la de 4) — el orden es justo lo que hace falta para calcular un gradiente a mano (derecha - izquierda). Para eso ya existe mundo.gradient(...) más abajo, que lo hace por vos.

mundo.neighborvalues(fila, columna)
mundo.neighborvalues4(fila, columna)

Difundir el número

Lo mismo que diffuse, pero mezclando el NÚMERO de cada celda con el de sus vecinas — así es como se simula una difusión real (calor, una sustancia) sin que el color quede de por medio.

mundo.diffusevalue(0.3)

Ninguno de los dos canales (color ni número) "evapora" solo — si querés que un rastro se desvanezca con el tiempo (como una feromona), hay que bajarlo a mano, celda por celda, antes de difundir (ver el ejemplo de hormigas más abajo).

diffuse/diffusevalue mezclan TODA la cuadrícula parejo — pero a veces una parte del terreno tiene que quedarse quieta y bloquear el paso, como una roca en medio de un río o una pared en un incendio. Para eso existen las celdas "impermeables": se marcan una vez, y a partir de ahí se comportan como una pared real — ni cambian ellas, ni dejan que sus vecinas "las vean" al promediar.

Marcar (o desmarcar) una celda

A partir de ahora, diffuse/diffusevalue ignoran por completo esta celda — no la cambian, y las celdas vecinas dejan de contarla en su propio promedio, como si no existiera. False la vuelve a dejar normal.

mundo.setsealed(fila, columna, True)
mundo.setsealed(fila, columna, False)

¿Está sellada?

False para cualquier celda que nunca se haya tocado con setsealed — útil dentro de un if antes de decidir algo sobre esa celda (ej. no dejar que un agente camine por ahí).

mundo.sealed(fila, columna)

A diferencia de pintar la celda de un color "de pared", sellarla no cambia cómo se ve — solo cómo se comporta ante la difusión. Si además querés que se vea distinta, pintala vos con mundo[fila][columna] = ... por separado.

Y para conectar los dos mundos — una tortuga que necesita saber sobre qué celda está parada, sin convertir xcor()/ycor() a fila/columna a mano cada vez:

¿Sobre qué celda está parada la tortuga?

Convierte la posición ACTUAL de la tortuga (xcor()/ycor()) en la fila y columna de mundo que le corresponden, sin hacer esa cuenta a mano. Se le pasa la cuadrícula porque puede haber más de una a la vez.

f, c = t1.patch(mundo)
mundo[f][c] = "red"

Y para no tener que inventar tu propia fórmula de "número a color" cada vez que armás un mapa de calor:

Número → color (frío a cálido)

Convierte un número a un color azul→blanco→rojo, recortado al rango que le des — reemplaza el min([255, ...])/max([...]) a mano que hacía falta antes para pintar un mapa de calor.

mundo[f][c] = mundo.heatcolor(mundo.value(f, c), 0, 100)

Leyenda de color

Dibuja una franja de color con etiqueta en la esquina del lienzo, explicando qué significan los colores — mismo colormap y rango que heatcolor(...), así que nunca se desincroniza de lo que de verdad se pintó.

mundo.legend("temperatura", 0, 100)

Y para diagramas de campo vectorial de verdad — flechas que apuntan hacia donde un número crece más rápido:

Dirección de mayor crecimiento (gradiente)

El ángulo (mismo sistema que heading()) hacia donde el número guardado con setvalue(...) crece más rápido en esa celda — calculado con diferencias finitas sobre las 4 vecinas ortogonales. Combinalo con la forma "flecha" (la única que rota y no es un ícono de animal) para armar un diagrama de campo vectorial: una tortuga quieta por celda, cada una apuntando a su propio gradiente.

f = Turtle()
f.shape("flecha")
f.setheading(mundo.gradient(fila, columna))
PROPIO DE BLOQUEPY

Atributos propios: datos con nombre

Cuando una tortuga o una celda necesitan cargar SU PROPIO dato (energía, edad, humedad) — sin inventar una lista paralela que hay que mantener alineada a mano.

Antes de esto, la única forma de que cada tortuga cargara un dato propio era una lista paralela indexada por orden de creación (energia[i] para la tortuga ovejas[i]) — funciona, pero es fácil que las dos listas se desalineen sin darse cuenta. Con atributos propios, cada tortuga o celda carga su propio estado directamente, sin ninguna lista de por medio.

Tortuga: leer/escribir como un diccionario

Una tortuga se indexa con un texto, igual que un diccionario — sin ningún bloque nuevo, reusa el mismo [ ] que ya usás con listas.

t1["energia"] = 100
t1["energia"] = t1["energia"] - 1
print(t1["energia"])

Celda de Patches: guardar un dato con nombre

A diferencia de la tortuga, una celda de Patches YA se indexa con [fila][columna] para su color — así que un atributo con nombre usa su propio bloque de método en vez de un tercer [ ]. Una celda puede cargar cuantos atributos quiera, cada uno con su propio nombre (temperatura Y humedad a la vez, interactuando entre sí — ver el ejemplo de cambio climático más abajo).

mundo.setattr(fila, columna, "humedad", 0.6)
mundo.attr(fila, columna, "humedad")

Leer un atributo que nunca se asignó da un error claro (KeyError), igual que leer una clave que no existe en un diccionario — asignalo primero.

PROPIO DE BLOQUEPY

Panel de datos: ver más allá del dibujo

Un ícono junto al de la tortuga abre un panel aparte con gráficas en vivo, lecturas fijas y controles ajustables — para que una simulación deje de ser solo un dibujo y se pueda medir, comparar y llevarse a otro lado.

Tampoco existe en Python real — es la otra pieza propia de BloquePy, pensada para la pregunta que un dibujo por sí solo no responde: "¿cómo está cambiando esto en el tiempo?", "¿cómo se compara una variable con otra?", "¿cómo está repartido este valor entre todos mis agentes ahora mismo?". Las tres se contestan arrastrando un bloque más a la simulación que ya tenías, sin herramientas externas.

📈 Graficar en el tiempo

Agrega un punto a una curva cada vez que se llama — llamalo una vez por vuelta de tu ciclo principal para ver la curva crecer en vivo, mientras la simulación sigue corriendo. Varias curvas con nombres distintos se grafican juntas, mismo eje de tiempo.

plot("población", n)

🔀 Comparar dos variables entre sí

Como plot, pero los DOS ejes son valores reales, no uno de ellos el tiempo — por ejemplo población de presas contra población de depredadores, para ver el ciclo que forman entre sí.

plot_xy("fase", presas, depredadores)

📊 Ver cómo se reparte un valor ahora

Un histograma: cuántos de tus agentes caen en cada rango de un valor, en ESTE instante — la energía de cada lobo, la edad de cada oveja. A diferencia de plot, cada llamada reemplaza la foto anterior; no es la evolución en el tiempo, es la distribución ahora mismo. Pasale una lista completa (una que ya venías armando con .append(...)).

histogram("energía", lobosEnergia)

🔢 Lectura fija en vivo

Un número (o cualquier valor) que se actualiza cada vez que se llama, sin gráfica ni historial — para un contador o estado que solo importa AHORA, sin ensuciar el lienzo con write(...).

monitor("recolectada", n)

🎚️ Control ajustable mientras corre

Un parámetro que se vuelve un control deslizable en el panel — arrastralo y la simulación reacciona EN VIVO, sin pausar ni volver a escribir el número en el bloque. Llamalo dentro de tu ciclo principal para que cada vuelta lea el valor actual del control.

velocidad = slider("velocidad", 1, 10, 5)

🎯 Repetir exactamente la misma corrida

Siembra el generador de azar — con la misma semilla, random()/randint(...) dan siempre la misma secuencia. Útil para comparar dos variantes de una regla bajo exactamente las mismas condiciones de azar, o para reproducir un resultado interesante que salió al pasar.

random_seed(1)

⏱️ Reloj propio de la simulación

Un contador de vueltas que lleva la cuenta por vos — llamá tick() una vez por vuelta de tu ciclo principal, y ticks() te dice cuántas van. Útil como eje del tiempo en plot(...), o para saber cuánto lleva corriendo la simulación.

tick()
ticks()

⏳ Pausa real

Pausa la ejecución esa cantidad de segundos de verdad. A diferencia del deslizador de velocidad (que solo frena el movimiento de una tortuga), esto frena CUALQUIER vuelta de un ciclo — necesario en un while True: que espera algo (un clic, una tecla) sin mover ni sonar nada mientras tanto, para que esa espera no corra sin frenos.

wait(0.5)

Y para resumir una población entera sin escribir el for+contador a mano cada vez:

Contar cuántos cumplen una condición

Cuántos elementos de la lista cumplen la condición que le des — como filter(...), pero devuelve CUÁNTOS pasaron en vez de la lista filtrada. Con una lista de verdadero/falso, count(lista) solo (sin función) cuenta los verdaderos. La condición tiene que ser un lambda ya guardado en una variable, no se puede escribir en línea dentro del hueco.

es_visible = lambda oveja: oveja.xcor() > 0
count(es_visible, ovejas)

Promedio y dispersión

mean(...) es el promedio de una lista de números. stdev(...) es qué tan dispersos están respecto a ese promedio (desviación estándar, necesita al menos 2 valores) — juntos resumen una población entera en dos números, listos para plot(...)/monitor(...).

mean(energias)
stdev(energias)

Ruido con forma de campana

Un decimal al azar alrededor de un valor central — a diferencia de random()/randint(...) (parejos), la mayoría de los resultados caen CERCA del centro. Para variación biológica entre individuos o ruido de medición realista.

gauss(20, 3)

Junto al panel hay dos botones más, sin bloque de por medio: pausar y avanzar de a una instrucción (para ver el efecto de una sola línea a la vez, en vez de todo de un tirón) y guardar la gráfica — como imagen, o como un archivo de datos que después se puede abrir con Python (pandas, matplotlib) o cualquier otra herramienta para seguir analizando fuera de BloquePy.

PROPIO DE BLOQUEPY — SIN BLOQUES NUEVOS

Experimento: correr muchas veces y comparar

Un ícono de matraz junto a la barra de Modo libre corre el MISMO programa muchas veces, variando un parámetro, y junta el resultado de cada corrida en una tabla exportable.

Para ver "¿cómo cambia mi resultado si subo este parámetro?" antes había que correr a mano una y otra vez, anotando cada vez. Experimento lo automatiza — y no necesita NINGÚN bloque nuevo: usa el mismo slider(...) y monitor(...) que ya conocés.

Qué pide el diálogo

El nombre de un slider(...) que tu programa ya declara (con el MISMO mínimo y máximo — tienen que coincidir exacto), cuántos valores probar entre esos dos extremos, cuántas repeticiones por valor, y un tope de pasos por corrida (un while True: se corta ahí y se toma la foto igual, es el caso esperado).

Qué junta

Cada corrida es headless (sin animación, así se pueden correr decenas rápido) y termina en una fila de una tabla: el valor del parámetro, la repetición, y el último valor de cada monitor(...) que tu programa haya llamado — exportable a CSV, listo para pandas.

PROPIO DE BLOQUEPY

Sonido: notas para armar melodías

Un sintetizador simple, no un reproductor de archivos — cada nota se genera por código en el momento, como los bloques de nota de Minecraft, pero con nombre de solfeo y pensado para escribirse en un ciclo.

Python real no tiene nada parecido a esto — es otra pieza propia de BloquePy. La idea no es reproducir un archivo de audio, sino tocar una nota como quien dibuja una línea: un bloque, un resultado inmediato, y una secuencia de bloques que ya arma una melodía completa.

🎵 Tocar una nota

Toca esa nota durante el tiempo indicado (en segundos) y ESPERA a que termine antes de seguir con la línea siguiente — por eso varias llamadas seguidas dentro de un for ya suenan en orden, como una melodía, sin necesitar un bloque de "esperar" aparte.

play_note("do4", 0.3)
play_note("sol#3", 0.3)

🤫 Silencio (una pausa)

No suena nada, pero espera el mismo tiempo que cualquier nota — para dejar un espacio dentro de una melodía, en vez de que dos notas se sientan pegadas.

play_note("silencio", 0.3)

🎼 Una melodía completa

Una lista de notas recorrida con un for — cada vuelta toca la nota que le toca y espera antes de la siguiente, así que el orden de la lista es el orden de la melodía.

melodia = ["do4", "mi4", "sol4", "do5"]
for nota in melodia:
    play_note(nota, 0.25)

Las notas van de do a si, con la octava pegada al final ("la4", no "la 4") — cuanto más alta la octava, más agudo el sonido. "#" antes de la octava da el sostenido de esa nota ("fa#3"). "la4" es la afinación real de referencia: exactamente 440 Hz, la misma que usa un diapasón o un piano afinado.

Ejemplo real para descargar: "La Cucaracha", la canción tradicional mexicana completa, 101 notas en una lista recorrida con un for.

CHULETA COMPLETA

Tabla de funciones: tortuga y Patches

Todas las funciones propias del mundo de la tortuga en un solo lugar — qué hace cada una y qué devuelve, para no tener que ir capítulo por capítulo buscando una.

"Devuelve" es lo que te da la función para usar en una expresión (guardarlo en una variable, meterlo en un if, etc.) — nada quiere decir que es un bloque de acción suelto, no algo que se pueda leer.

🐢 Tortuga (t1 = Turtle())

FunciónQué haceDevuelve
Turtle()Crea una tortuga nueva, en (0,0) mirando arriba.🐢 una tortuga
t1.forward(n)Avanza n pasos en la dirección de su rumbo.— nada
t1.backward(n)Retrocede n pasos.— nada
t1.right(grados)Gira a la derecha, relativo a hacia donde ya miraba.— nada
t1.left(grados)Gira a la izquierda, relativo a hacia donde ya miraba.— nada
t1.goto(x, y)Salta directo a un punto, sin importar el rumbo.— nada
t1.setheading(grados)Fija el rumbo ABSOLUTO (0°=arriba, 90°=derecha...).— nada
t1.circle(radio)Dibuja un círculo aproximado con polígono de muchos lados.— nada
t1.penup()Levanta el lápiz — moverse ya no deja rastro.— nada
t1.pendown()Baja el lápiz — moverse vuelve a dejar rastro.— nada
t1.color(c)Cambia el color del trazo (nombre, hex, o tupla r,g,b).— nada
t1.fillcolor(c)Cambia el color de relleno, sin tocar el del trazo.— nada
t1.pensize(n)Cambia el grosor del trazo.— nada
t1.fadetrail(n)El rastro nunca guarda más de n trazos — los viejos se desvanecen solos.— nada
t1.fill(): ...Bloque en C — rellena la figura que dibuje adentro.— nada
t1.shape(nombre)Cambia la forma del ícono ("wolf", "sheep", "bee"...).— nada
t1.hideturtle()Oculta el ícono, sin borrar su estado ni el rastro.— nada
t1.showturtle()Vuelve a mostrar el ícono.— nada
t1.stamp()Deja una copia congelada — huella neutral, no un agente vivo.— nada
t1.clearstamps()Borra todos los sellos que dejó esta tortuga.— nada
t1.dot(diametro)Dibuja un punto de color fijo, sin mover a la tortuga.— nada
t1.write(valor)Escribe texto/número en el lienzo, en su posición actual.— nada
t1.xcor()Coordenada x donde está parada ahora.🔢 número
t1.ycor()Coordenada y donde está parada ahora.🔢 número
t1.heading()Rumbo actual, en grados.🔢 número
t1.distance(t2)Distancia en línea recta a otra tortuga.🔢 número
t1.towards(t2)Rumbo que apunta directo hacia otra tortuga.🔢 número (grados)
t1.touching(t2)¿Están lo bastante cerca como para contar como encontradas?✅ booleano
t1.nearest(lista)La tortuga de la lista más cercana a t1 (sin contarse a sí misma).🐢 una tortuga
t1.bounce(t2)Refleja el RUMBO de t1 como si hubiera chocado con t2 (rebote tipo billar).— nada
t1["clave"] = valorCrea o actualiza un atributo propio de ESTA tortuga.— nada
t1["clave"]Lee un atributo propio (KeyError si nunca se asignó).🔢 lo que sea que guardaste
t1.patch(mundo)La celda (fila, columna) de mundo que le corresponde a la posición actual de t1 — convierte xcor()/ycor() sin hacerlo a mano.🔢 tupla (fila, columna)

🌐 Patches (mundo = Patches(f, c))

FunciónQué haceDevuelve
Patches(filas, columnas)Crea la cuadrícula de celdas, aparte de las tortugas.🌐 el ambiente
Patches(filas, columnas, modo)Igual, con el modo de borde: "wrap" (de siempre) o "wall".🌐 el ambiente
mundo[fila][columna]Lee el color de una celda.🎨 color
mundo[fila][columna] = colorEscribe el color de una celda.— nada
mundo.neighbors(fila, columna)Color de las 8 celdas vecinas (con diagonales).🎨 lista de colores
mundo.neighbors4(fila, columna)Color de las 4 celdas vecinas (sin diagonales).🎨 lista de colores
mundo.diffuse(porcentaje)Difunde el COLOR de toda la cuadrícula con sus vecinas.— nada
mundo.value(fila, columna)Lee el número guardado en una celda (aparte del color).🔢 número
mundo.setvalue(fila, columna, v)Escribe el número de una celda.— nada
mundo.neighborvalues(fila, columna)Número de las 8 celdas vecinas (con diagonales).🔢 lista de números
mundo.neighborvalues4(fila, columna)Número de las 4 celdas vecinas (sin diagonales).🔢 lista de números
mundo.diffusevalue(porcentaje)Difunde el NÚMERO de toda la cuadrícula con sus vecinas.— nada
mundo.setattr(fila, columna, clave, v)Crea o actualiza un atributo CON NOMBRE de una celda.— nada
mundo.attr(fila, columna, clave)Lee un atributo con nombre (KeyError si nunca se asignó).🔢 lo que sea que guardaste
mundo.setsealed(fila, columna, valor)Marca (o desmarca) una celda como "impermeable": deja de cambiar con diffuse()/diffusevalue(), y sus vecinas dejan de "verla" al promediar — actúa como una pared real.— nada
mundo.sealed(fila, columna)¿Esa celda está marcada impermeable?✅ booleano
mundo.heatcolor(valor, mín, máx)Convierte un número a color frío→cálido (azul→blanco→rojo), recortado al rango.🎨 color
mundo.legend(etiqueta, mín, máx)Dibuja una franja de color con etiqueta en el lienzo, explicando el mapa de calor.— nada
mundo.gradient(fila, columna)Ángulo hacia donde el número (setvalue) crece más rápido en esa celda — para diagramas de campo vectorial con shape("flecha").🔢 número (grados)
EL RESTO DEL LENGUAJE

Funciones generales útiles en simulaciones

No son de la tortuga — son del lenguaje en general, pero aparecen todo el tiempo en las simulaciones de esta página.

🎲

Al azar

Un decimal entre 0 y 1, o un entero entre a y b (incluidos ambos) — calcan el módulo random de Python real.

random()
randint(-30, 30)
📐

Matemáticas

Para física de verdad (órbitas, atracción entre partículas) — mismos nombres que el módulo math real.

sqrt(x) · sin(x) · cos(x) · pi
🪄

Funciones propias

Como cualquier función de Python — útil para empaquetar una regla que se repite mucho (ver Mundo 6 de la Wiki, "Los Hechizos").

def distancia_al_cuadrado(a, b):
    return ...

Descarga y prueba: 19 simulaciones completas

Cada una es un archivo .bloquepy.json real — el mismo árbol de bloques que se guarda desde Modo Libre, no un resumen. Descárgalo y en la app: Modo libre → ícono de importar → elegí el archivo. Quedan agrupados por lo que más se parece a enseñar en clase.

Física

☀️

Sistema solar

Gravedad real (F = μ/r²) con towards()/distance() — un planeta en órbita circular que no se dispara ni cae, con velocidad tangencial inicial calculada a mano.

Descargar

🌌

Colapso gravitacional

La misma física, pero SIN un sol fijo: varias partículas que se atraen TODAS entre sí — atracción mutua real, no un cuerpo central privilegiado.

Descargar

Química

💧

Moléculas de agua

Dos átomos de H se enlazan a un O por distance(), con cupo máximo por átomo — "Molécula de agua formada" se anuncia justo al completarse, ni antes ni después.

Descargar

💎

Crecimiento cristalino (DLA)

Un caminante al azar sobre Patches que se pega en cuanto neighbors() reporta un vecino "cristal" — el cristal crece más allá de la semilla, celda por celda.

Descargar

Biología

🐦

Parvada (boids)

Varias aves que giran hacia el centro de masa de la parvada (cohesión) Y hacia el rumbo promedio de sus vecinas (alineación), con algo de ruido — comportamiento de grupo sin que nadie lo dirija.

Descargar

🔥

Incendio forestal

Cuadrícula de árboles (Turtle() con forma propia) — una chispa se propaga a sus vecinas con una probabilidad de contagio, y cada árbol pasa por 2 fases de quemado antes de quedar como ceniza.

Descargar

🐜

Hormigas buscando comida

Hormigas que vagan al azar hasta tocar la comida, y depositan una feromona real (Patches que se evapora y se difunde) al volver al nido — las demás la siguen y refuerzan la ruta.

Descargar

🐑

Lobos y ovejas: dinámica de poblaciones

La que mejor muestra el panel de datos completo: lobos que persiguen con towards(), ovejas que se reproducen, dos curvas de población en vivo (plot), un retrato de fase presas-depredadores (plot_xy), un histograma de energía de los lobos (histogram), y dos sliders para ajustar la caza y la reproducción mientras corre.

Descargar

Clima

El mismo mecanismo que ya usa el mapa de calor (Patches + diffusevalue) alcanza para un modelo de clima de juguete — simplificado a propósito, no un pronóstico real: la idea es entender la retroalimentación, no predecirla.

🌡️

Cambio climático: temperatura y humedad

Una cuadrícula donde cada celda tiene su propia temperatura (values, con diffusevalue esparciéndola entre celdas) Y su propia humedad (mundo.setattr(...)/mundo.attr(...), el atributo con nombre nuevo) — más humedad hace que el calor se amplifique un poco más, el mismo tipo de retroalimentación (vapor de agua) detrás del calentamiento real. Un slider("emisiones", ...) controla cuánto se fuerza el sistema, y plot/monitor muestran cómo la temperatura promedio se acomoda con el tiempo. Abrí Experimento después de correrlo para ver cómo cambia la temperatura de equilibrio al variar las emisiones, en muchas corridas de una.

Descargar

🌊

Río con compuerta

Una represa de banco a banco (mundo.setsealed(...), celdas "impermeables" que diffusevalue nunca cruza) con una sola compuerta abierta — el agua entra constante por un lado y solo llega al otro por esa rendija. Un sensor (Turtle() con .patch(mundo)) se pasea por la orilla leyendo el nivel bajo de sí mismo, graficado contra ticks() — el ciclo principal termina con while ticks() < 120: en vez de contar pasos a mano.

Descargar

Redes y ciencias sociales

La tortuga no solo dibuja figuras ni vive en una cuadrícula — una lista de listas ya alcanza para representar un grafo (quién está conectado con quién), y sin(...)/cos(...)/pi para acomodar los nodos en un círculo. Sin ninguna pieza nueva del lenguaje. Para una topología cliente-servidor, shape("computadora") (4 colores al azar) y shape("servidor") dan íconos propios en vez de puntos genéricos.

🕸️

Difusión en una red social

La más reciente: 16 nodos en un anillo con unos pocos atajos al azar ("mundo pequeño") — un rumor se contagia de vecino a vecino con una probabilidad ajustable (slider), hasta que a cada quien "ya no le interesa". Tres curvas de población en vivo (plot) trazan la curva de epidemia clásica, contadas con count(...) y una comprensión de listas.

Descargar

📡

Red cliente-servidor: mandar un mensaje

43 nodos (un servidor y 36 computadoras repartidas en 6 grupos, acomodados con sin/cos — nada puesto a mano) con shape("servidor")/shape("computadora"). Hacé clic en cualquier computadora del lienzo: el mensaje sale del servidor y viaja salto por salto hasta ahí (siguiendo quién es el "padre" de cada nodo), con sonido en cada salto y una cola tipo cometa (fadetrail) para ver cómo trafica. wait(...) mantiene el ciclo esperando el próximo clic sin trabarse; key_just_pressed("escape") lo corta cuando quieras.

Descargar

Matemáticas y patrones

🔺

Triángulo fractal (Sierpinski)

Un triángulo que se repite dentro de sí mismo cada vez más chico — geometría recursiva dibujada de verdad, no solo descrita.

Descargar

🐆

Patrón de Turing

Reacción-difusión entre dos sustancias sobre Patches — el mismo tipo de regla matemática detrás de las manchas de un animal, dibujada punto por punto.

Descargar

🟢

Juego de la Vida (Conway)

El autómata celular clásico: cada celda vive o muere según cuántas vecinas tiene vivas — reglas simples, comportamiento sorprendente.

Descargar

🌡️

Mapa de calor con difusión

Ovejas que "pastan" sobre una cuadrícula de Patches, dejando una marca que se esparce con diffuse() — la versión final de tres iteraciones que se fueron simplificando a medida que Patches creció.

Descargar

Algoritmos

No toda simulación es sobre un fenómeno natural — a veces la tortuga es el escenario ideal para VER un algoritmo clásico de ciencias de la computación funcionando de verdad, paso a paso, en vez de solo leerlo en un pizarrón.

🧭

Laberinto: camino más corto (BFS)

Un laberinto dibujado sobre Patches a partir de un mapa de texto, resuelto con búsqueda en anchura (BFS) real — cola, diccionario de visitados y de "padres" para reconstruir el camino, todo con tuplas (fila, columna) como clave de diccionario (marca cada celda visitada sin inventar una clave de texto). Al terminar, colorea el camino más corto encontrado y una tortuga lo recorre paso a paso.

Descargar

🕸️

Grafo con recorrido (BFS)

6 nodos con nombre, conectados por 7 aristas (no todos con todos) — un diccionario de posiciones, otro de vecinos, y una lista de tuplas para las aristas: cero piezas nuevas del lenguaje. La tortuga dibuja las aristas en gris y los nodos en azul, y luego el mismo BFS de siempre (cola con una lista, visitados con un diccionario) va coloreando cada nodo de rojo en el orden en que lo visita, mientras la terminal imprime ese orden.

Descargar

Sonido

🪳

La Cucaracha

La melodía completa de la canción tradicional mexicana, nota por nota, con play_note(...) — 101 notas guardadas en una lista y recorridas con un solo for, mientras la terminal va imprimiendo cada una a medida que suena.

Descargar

Por qué esto importa para enseñar

La tortuga da retroalimentación visual inmediata a cosas que de otro modo son abstractas: un ciclo for deja de ser "repite esto N veces" y se vuelve un dibujo que crece vuelta por vuelta; un ángulo deja de ser un número suelto y se vuelve la esquina de un polígono; una variable dentro de un ciclo se vuelve una espiral que crece de verdad. Con Patches y varias tortugas a la vez, el salto es más grande: de dibujar figuras a modelar sistemas — física, química, biología, matemáticas — con retroalimentación visual inmediata en cada uno.