No description
  • Rust 95.5%
  • Shell 4.5%
Find a file
Jonatas Oliveira a146d58d08
Some checks failed
ci/woodpecker/push/pipelines/1 Pipeline was successful
ci/woodpecker/push/pipelines/2 Pipeline was successful
CI / Test Suite (push) Has been cancelled
CI / Test Suite-1 (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Clippy-1 (push) Has been cancelled
CI / Rustfmt (push) Has been cancelled
CI / Rustfmt-1 (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Build-1 (push) Has been cancelled
chore(hooks): rodar o pipeline localmente antes de cada commit
`.githooks/pre-commit` executa aqui o que o Woodpecker executa no
servidor: lint do proprio pipeline, `cargo fmt --check`, clippy com
`-D warnings`, build e testes. Ele e gerado a partir do
`.woodpecker/pipelines.yml` deste repositorio, entao os dois nao podem
divergir -- mudou o piso de cobertura no pipeline, regera-se o hook.

As etapas caras (cobertura, auditoria, mutacao, a perna MSRV) ficam
atras de `PRE_COMMIT_COMPLETO=1`. Pedi-las a cada commit e pedir que o
hook seja desligado; elas sao para antes do push.

O lint do pipeline entrou por experiencia recente: um `: ` sem aspas num
`echo` fazia o YAML virar mapa e o Woodpecker recusava o arquivo inteiro,
sem que ninguem percebesse que o CI nunca rodava.

Ativacao, uma vez por clone: `git config core.hooksPath .githooks`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PhdPjHUuVhXaitwT4mG53t
2026-09-04 12:41:51 +02:00
.cargo test: add property-based and mutation-guard suites 2026-09-02 10:32:23 +02:00
.githooks chore(hooks): rodar o pipeline localmente antes de cada commit 2026-09-04 12:41:51 +02:00
.github/workflows Corrige tela de vitória e adiciona Chave de Ouro + CI/CD 2025-11-14 13:19:04 +00:00
.woodpecker fix(ci): keep the tool-installing steps off the MSRV leg 2026-09-02 16:32:48 +02:00
assets/sounds Adiciona tela de vitória com estatísticas e créditos animados 2025-11-14 13:00:02 +00:00
src style: apply rustfmt and the edition 2024 formatting 2026-09-02 10:32:23 +02:00
tests test: add property-based and mutation-guard suites 2026-09-02 10:32:23 +02:00
.gitignore build(deps): upgrade to Rust 1.98, edition 2024 and rand 0.10 2026-09-02 10:32:07 +02:00
.mutants-teto test: add property-based and mutation-guard suites 2026-09-02 10:32:23 +02:00
AUDIO_SETUP.md Adiciona tela de vitória com estatísticas e créditos animados 2025-11-14 13:00:02 +00:00
Cargo.lock build(deps): upgrade to Rust 1.98, edition 2024 and rand 0.10 2026-09-02 10:32:07 +02:00
Cargo.toml fix(build): declare the real minimum toolchain, not the local one 2026-09-02 15:33:44 +02:00
LICENSE docs: add the GPLv3 licence text and describe the test layers 2026-09-02 10:32:34 +02:00
README.md chore(hooks): rodar o pipeline localmente antes de cada commit 2026-09-04 12:41:51 +02:00

Rogue - Dungeon Crawler em ASCII

Um clone didático do clássico jogo Rogue, implementado em Rust com macroquad.

🎮 Sobre o Jogo

Rogue é um dungeon crawler roguelike clássico onde você explora dungeons geradas proceduralmente, enfrenta monstros, coleta tesouros e procura o lendário Amuleto de Yendor.

Características

  • Geração Procedural: Cada dungeon é única, gerada com algoritmo de salas e corredores
  • 🎯 3 Níveis: Dificuldade crescente com monstros mais fortes
  • ⚔️ Sistema de Combate: Combate baseado em turnos com ataque e defesa
  • 🗝️ Portas Secretas: Descubra passagens ocultas
  • 🚪 Portas de Teleporte: Todas as portas (+) são portais que teleportam você para outras áreas!
  • 💣 Armadilhas: Cuidado onde pisa!
  • 💰 Tesouros: Ouro, poções, armas e armaduras
  • 📈 Sistema de Progressão: Ganhe XP e suba de nível
  • 📊 Estatísticas: Rastreamento completo de monstros mortos, tesouros coletados e equipamentos
  • 🏆 Tela de Vitória: Veja suas estatísticas e créditos ao vencer o jogo
  • 🎬 Créditos Animados: Créditos finais em estilo cinematográfico
  • 🎨 Arte ASCII: Visual clássico roguelike
  • 🔊 Suporte a Áudio: Sistema preparado para efeitos sonoros (veja AUDIO_SETUP.md)

🎯 Objetivo

Desça pelos 3 níveis da dungeon e encontre o Amuleto de Yendor (") para vencer!

Ao pegar o Amuleto, você verá:

  1. 📊 Tela de Estatísticas: Suas conquistas da jornada

    • Monstros mortos
    • Tesouros coletados
    • Equipamentos encontrados
    • Ouro acumulado
    • Nível final alcançado
    • Dano causado e recebido
  2. 🎬 Créditos Cinematográficos: Pressione ESPAÇO para ver os créditos descendo como em filmes!

🕹️ Controles

  • W/A/S/D ou Setas: Mover
  • H: Mostrar legenda do jogo
  • ESPAÇO: Avançar para créditos (na tela de vitória)
  • R: Reiniciar jogo
  • Q/ESC: Sair do jogo

🗺️ Símbolos do Mapa

Terreno

  • # - Parede
  • . - Chão
  • + - Porta
  • > - Escadas (próximo nível)
  • ^ - Armadilha (quando revelada)

Entidades

  • @ - Você (o herói)
  • r - Rato (fraco)
  • g - Goblin (médio)
  • o - Orc (forte)
  • T - Troll (muito forte)
  • D - Dragão (boss)

Itens

  • $ - Ouro
  • ! - Poção de cura
  • ) - Arma (aumenta ataque)
  • ] - Armadura (aumenta defesa)
  • " - Amuleto de Yendor (objetivo!)

🏗️ Arquitetura do Código

O projeto está organizado de forma modular e didática:

Módulos

map.rs - Geração de Dungeons

  • Algoritmo: Salas e corredores (rooms and corridors)
  • Processo:
    1. Gera salas aleatórias sem sobreposição
    2. Conecta salas com corredores em L
    3. Adiciona portas, armadilhas e portas secretas

Conceitos-chave:

- Room: Estrutura retangular com posição e dimensões
- Tile: Enum representando tipos de terreno
- Map::generate(): Método principal de geração procedural

entities.rs - Jogador, Monstros e Itens

  • Player: HP, ataque, defesa, XP, level
  • Monster: Diferentes tipos com stats balanceados
  • Item: Tesouros e equipamentos

Conceitos-chave:

- Position: Sistema de coordenadas
- MonsterType::for_level(): Spawna monstros apropriados
- Item::apply(): Aplica efeitos ao jogador

game.rs - Lógica Principal

  • Gerenciamento de estado: Playing, Victory, Defeat
  • Sistema de turnos: Jogador move → Monstros agem
  • Combate: Damage = Ataque - Defesa (mínimo 1)
  • Interações: Portas, armadilhas, itens, escadas

Conceitos-chave:

- Game::move_player(): Processa movimento e interações
- Game::monster_turn(): IA dos monstros
- Game::generate_level(): Cria novo nível

render.rs - Renderização ASCII

  • Macroquad: Biblioteca para desenhar texto como gráficos
  • Sistema de cores: Diferentes cores para diferentes elementos
  • UI: Stats do jogador, mensagens, controles

Conceitos-chave:

- Renderer::draw_char(): Desenha caractere ASCII na grid
- Colors: Paleta de cores para elementos
- window_config(): Configuração da janela

main.rs - Loop Principal

  • Game Loop: Input → Update → Render
  • Async: Usa macroquad::main macro
  • Input Handling: Processa teclas WASD/Arrow

🧪 Testes

Quatro camadas, cada uma respondendo a uma pergunta diferente.

cargo test                     # todas: 102 testes
cargo test --lib               # unidade — as regras, uma a uma
cargo test --test integration_tests  # integração — partidas inteiras
cargo test --test spider       # propriedade — varre o espaço de entradas
cargo test --test mutantes     # travas nascidas do cargo-mutants

Unidade (src/*.rs)

Vivem ao lado do código que testam, dentro de #[cfg(test)] mod tests. Cobrem cada regra isolada: intersecção de salas, dano e cura, level up, o Cow do cache de mensagens, o Deref do HitPoints, o pool de objetos com Arc<Mutex<_>>.

Integração (tests/integration_tests.rs)

Montam um Game de verdade e jogam. Uma partida de 500 comandos que cobra estado coerente do começo ao fim; descer os três níveis até o fundo; matar um monstro e receber o XP; pisar na armadilha e conferir que ela não dispara duas vezes; pegar o Amuleto e vencer.

Propriedade (tests/spider/)

Em vez de fixar casos, varrem o espaço de entradas com proptest e cobram invariantes. Isso importa especialmente aqui porque a dungeon é gerada por sorteio: um teste de exemplo só consegue olhar o mapa que ele mesmo montou. As propriedades valem para qualquer mapa que o gerador produza — toda dungeon é jogável, nenhuma sala vaza para fora, toda porta leva a uma casa caminhável, perseguir sempre alcança o alvo.

Mutação (tests/mutantes/ + cargo mutants)

Cobertura diz que a linha executou. Mutação diz se alguém conferiu o resultado. A ferramenta injeta um defeito de cada vez e roda a suíte; se ela continua verde, aquele defeito é invisível.

cargo mutants          # tem de ficar dentro do teto em .mutants-teto

Foi assim que se descobriu que, mesmo com 93% de cobertura, dava para trocar o nome de todo monstro por "xyzzy" ou achatar os atributos de todos em (1, 1, 1, 1) sem quebrar nada — as asserções perguntavam se os valores eram positivos, não se eram os certos.

O teto de sobreviventes fica em .mutants-teto, versionado, e só pode cair: quem abrir um buraco novo quebra o build.

🚀 Como Executar

Pré-requisitos

Compilar e Executar

# Clone o repositório
git clone <repo-url>
cd rogue

# Executar em modo debug
cargo run

# Executar em modo release (mais rápido)
cargo run --release

📚 Aprendendo com o Código

Este projeto é didático e demonstra:

1. Geração Procedural

  • Como criar dungeons aleatórias mas jogáveis
  • Algoritmo de salas e corredores
  • Validação de conectividade

2. Game Design

  • Sistema de combate balanceado
  • Curva de dificuldade (3 níveis)
  • Feedback ao jogador (mensagens coloridas)

3. Padrões Rust

  • Ownership e borrowing
  • Enums para tipos de entidades
  • Pattern matching
  • Testes unitários

4. Arquitetura de Jogos

  • Separação de responsabilidades (MVC-like)
  • Game loop assíncrono
  • Sistema de entidades

5. Macroquad

  • Renderização de texto
  • Input handling
  • Window configuration

🎓 Conceitos de Roguelike

Geração Procedural

Cada partida é única! O mapa é gerado aleatoriamente usando:

  1. Criação de salas sem sobreposição
  2. Corredores conectando salas adjacentes
  3. Distribuição aleatória de itens e monstros

Permadeath

Quando você morre, recomeça do zero. Sem saves!

Sistema de Turnos

O jogo espera sua ação. Pense antes de agir!

Exploração

Descubra portas secretas explorando as paredes.

🔊 Adicionar Efeitos Sonoros (Opcional)

O jogo está preparado para suportar efeitos sonoros! Para adicionar áudio:

  1. Siga as instruções no arquivo AUDIO_SETUP.md
  2. Baixe sons gratuitos de licença CC0 dos sites recomendados
  3. Coloque os arquivos na pasta assets/sounds/
  4. Descomente o código no arquivo src/audio.rs
  5. Descomente a dependência quad-snd no Cargo.toml

Sons suportados:

  • 🗡️ Ataque a monstros
  • 💀 Morte de monstros
  • 💰 Coletar itens/tesouros
  • 🚪 Teleporte por portas
  • ❤️ Receber dano
  • 🏆 Vitória

🔧 Melhorias Futuras

Ideias para expandir o jogo:

  • Field of View (FOV) - Fog of war
  • Inventário completo
  • Mais tipos de itens (scrolls, wands)
  • Mais monstros e comportamentos de IA
  • Salas especiais (tesouros, boss rooms)
  • Sistema de fome
  • Identificação de itens
  • Salvar/carregar jogo
  • Sistema de estatísticas do jogador
  • Tela de vitória com estatísticas
  • Créditos animados
  • Sistema de portas de teleporte
  • Estrutura para efeitos sonoros

📖 Recursos de Aprendizado

📝 Licença

GPL-3.0-or-later — veja LICENSE. Projeto educacional, livre para uso, estudo e modificação.

🤝 Contribuindo

Sinta-se livre para fazer fork, modificar e aprender com o código!


Divirta-se explorando as dungeons! 🗡️🛡️

Verificações antes do commit

O .githooks/pre-commit roda aqui o que o Woodpecker roda no servidor. Ele é gerado a partir do .woodpecker/pipelines.yml deste repositório, então os comandos não podem divergir do CI. Ative uma vez por clone -- o hook é versionado, a configuração que aponta para ele não é:

git config core.hooksPath .githooks

A cada git commit: lint do pipeline, cargo fmt --check, clippy com -D warnings, build e testes. Antes de um push, o nível completo, que acrescenta cobertura, auditoria de dependências, teste de mutação e a perna MSRV 1.90:

PRE_COMMIT_COMPLETO=1 git commit ...

Para pular de propósito, git commit --no-verify. Um hook que não se pode pular é um hook que todo mundo desativa; o CI continua sendo a rede que não se pula.