Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
••
IT NachrichtenMicrosoft puts Brad Smith in charge of communications(25.09.2026 um 00:08 Uhr)
••
IT Nachrichten25. September(25.09.2026 um 00:05 Uhr)
•
IT NachrichtenCI-Solution GmbH von Crossware übernommen(25.09.2026 um 00:01 Uhr)
•
IT NachrichtenInsta360 GO Ultra erhält KI-Sprachassistenten mit Gemini(24.09.2026 um 21:30 Uhr)
••
AI & KI NachrichtenMaryland Governor Draws New Boundaries for Data Centers(25.09.2026 um 00:04 Uhr)
••••
IT NachrichtenMicrosoft puts Brad Smith in charge of communications(25.09.2026 um 00:08 Uhr)
••
IT Nachrichten25. September(25.09.2026 um 00:05 Uhr)
•
IT NachrichtenCI-Solution GmbH von Crossware übernommen(25.09.2026 um 00:01 Uhr)
•
IT NachrichtenInsta360 GO Ultra erhält KI-Sprachassistenten mit Gemini(24.09.2026 um 21:30 Uhr)
••
AI & KI NachrichtenMaryland Governor Draws New Boundaries for Data Centers(25.09.2026 um 00:04 Uhr)
••
Intelligence View
⚡ tsecurity.de Intelligence

Learning Crystal with Battlesnake

Recently I've been interested in Crystal lang so I worked on a Battlesnake implementation to get more practice under my belt. I'm sharing an overview of it in this post and the code is open source on GitHub. Battlesnake is a multiplayer…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Recently I've been interested in Crystal lang so I worked on a Battlesnake implementation to get more practice under my belt. I'm sharing an overview of it in this post and the code is open source on GitHub.



Battlesnake is a multiplayer game where a small server you write plays a survival-style snake game paired with snakes implemented by others.






The app



I'm using Kemal for framework. The simplicity (Ruby/Sinatra similarity) won me over when paired with Crystal performance. This is what the entire Battlenake API implementation looks like at the time of this writing:




get "/" do
{
"apiversion": "1",
"author": "fdocr",
"color": ENV["SNAKE_COLOR"] ||= "#e3dada",
"head": ENV["SNAKE_HEAD"] ||= "default",
"tail": ENV["SNAKE_TAIL"] ||= "default",
"version": \{\{ `shards version "#{__DIR__}"`.chomp.stringify \}\}
}.to_json
end

post "/start" do |env|
context = BattleSnake::Context.from_json(env.params.json.to_json)
end

post "/move" do |env|
context = BattleSnake::Context.from_json(env.params.json.to_json)

case ENV["STRATEGY"] ||= "RandomValid"
when "RandomValid"
move = Strategy::RandomValid.new(context).move
when "ChaseClosestFood"
move = Strategy::ChaseClosestFood.new(context).move
when "ChaseRandomFood"
move = Strategy::ChaseRandomFood.new(context).move
when "CautiousCarol"
move = Strategy::CautiousCarol.new(context).move
else
move = Strategy::RandomValid.new(context).move
end

res = { "move": move, "shout": "Moving #{move}!" }
res.to_json
end

post "/end" do |env|
context = BattleSnake::Context.from_json(env.params.json.to_json)
end






Quite Ruby-like so I hope it's easy to follow along whether you've written Crystal before or not.



/start + /end aren't actually doing anything other than parsing the payload provided and / responds with the snake's skin customizations. /move picks from the existing strategies to respond based on an ENV variable.



The devil is in the details since the bulk of the logic lives in the models (parse game context from request payload, house a few utility methods, etc), strategies to respond with a move and utility algorithms. They all feel easy to follow along though.



IMO notes/thoughts so far:




I haven't felt the need to work with macros yet so it's been very similar to a Ruby project.



Reworking data structures on the fly (while working/re-working strategies) took some new time/energy to get right compared to Ruby. There's been close to 0 debugging time related to exceptions I would've likely had to catch when putting together a Ruby script because of the compiler (maybe? likely?).



I have a clunky env.params.json.to_json up there that bothers me a bit. I think that could be cleaned up by figuring out the way to get the raw (String) payload instead of the Kemal parsed (Hash/Object) parameter though. That's a TODO for now.







Strategies & Algorithms implemented



Since Crystal is object oriented I created an abstract/virtual class that all strategies inherit from.




  • RandomValid considers all the valid moves for your snake on the current context and picks one at random

    • Takes into account walls and other snakes' current position



  • ChaseClosestFood and ChaseRandomFood both aim towards food on the board and differ in how they pick their target (Closest vs Random)

    • They re-use RandomValid in some scenarios (i.e. can't reach food)

    • They use A* search algorithm to find the best route towards a target (food in this case but can be used on any Point on the board)


The re-usability of strategies makes for a cool way to mix & match them, meaning I can build on top of each other or existing algorithms. The food chaser ones won all the challenges (not sure if challenges are still a thing after the recent UI revamp) so that started to show some potential.



CautiousCarol is a heuristic strategy I implemented and looks like this:




# Strategy that chases the closest available food from the board with caution
# against head-to-head collisions. When a potentially dangerous move is in the
# way it analyzes the other valid moves available and picks the one with the
# most open area of the board to avoid enclosed spaces.
class Strategy::CautiousCarol < Strategy::Base
def move
valid_moves = @context.valid_moves(@context.you.head)
return RandomValid.new(@context).move if valid_moves[:moves].empty?

# Check for head-to-head collision possibilities
dangerous_moves = [] of BattleSnake::Point
enemies = @context.board.snakes.reject { |s| s.id == @context.you.id }
enemies.each do |snake|
next if snake.head <=> @context.you.head > 2
next if snake.body.size < @context.you.body.size

# Check if we share valid moves (meeting point for collision)
@context.valid_moves(snake.head)[:neighbors].values.each do |point|
meeting_point = valid_moves[:neighbors].values.find do |p|
(point <=> p).zero?
end
next if meeting_point.nil?
dangerous_moves << point
end
end

# Attempt to chase closest food unless dangerous move is detected
closest_food = ChaseClosestFood.new(@context).move
target_point = @context.you.head.move(closest_food)
safe_move = dangerous_moves.find { |p| (p <=> target_point).zero? }.nil?
return closest_food if safe_move

# Leftover valid moves (not chasing closest food anymore) & fallback to
# RandomValid if no other moves are available (likely run into own death)
safe_moves = valid_moves[:moves].reject { |move| move == closest_food }
return RandomValid.new(@context).move if safe_moves.size.zero?

# Use flood fill to pick the valid move with more space to spare as an
# attempt to avoid small areas
flood_fills = {} of Int32 => String
contexts = [] of BattleSnake::Context
safe_moves.size.times { contexts << @context.dup }
safe_moves.each_with_index do |move, i|
contexts[i].move(@context.you.id, move)
area_size = Utils.flood_fill(@context.you.head, contexts[i]).size
flood_fills[area_size] = move
end

# Pick the direction with the largest available area
flood_fills[flood_fills.keys.sort.last]
end
end






That's likely a lot to take in, but if interested in comparing it to Ruby or other languages give it a try and ask me about it. I'm not that experienced in Crystal so there are likely details that could improve this.



Overall there's model manipulation (i.e. using the snakes from the board of the current context), utility method usage from the models (i.e. calls to @context.valid_moves), reusing of RandomValid & ChaseClosestFood strategies, and Utils.flood_fill, which is my implementation of Flood Fill algorithm.



My first version of this strategy was a clunky attempt to brute-force a "look ahead" simulation of all possible scenarios. I scrapped that idea in favor of the above for now.






Leaderboard results



That first version of CautiosCarol performed "alright". I was surprised it earned points and ranked on the board overall since I knew it wasn't great. After a couple of days on the Standard leaderboard (4 players on 11x11 board) it ranked like this out of ~100 snakes.



Standard leaderboard first run



After the fix with the code above on CautiousCarol and another couple of days on the same leaderboard I saw some improvement:



Standard leaderboard first run



I also realized that same snake could rank on the Duels leaderboard too (1v1 on 11x11 board). Apparently CautiousCarol performs better there (in ranking position but fewer points so I'm not sure how much better really 😅)



Duels leaderboard run






Conclusions



Crystal has felt easy to read and write for me, quite nice to use overall and very similar to Ruby in lots of ways (specially at this level without diving into macros). The project is open source on GitHub if interested in checking it out.



I hope this is the first of a few posts on other specific Crystal learnings I had while experimenting here. Also might update if I come up with new/better strategies.



Pura vida.

SOC Incident Playbook: Remote Code Execution (RCE) Defense
Syntax validiert (0 Fehler)
title: Detect Exploitation - Learning Crystal with Battlesnake
id: 1f00182a-b760-4555-baf1-6fc0461a0496
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-25
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-25"
        description = "YARA Signature for "
    strings:
        $str = "Learning Crystal with Battlesn" ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("Learning Crystal with Battlesnake")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*Learning Crystal with Battlesnake*"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "Learning Crystal with Battlesnake"
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc
🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Learning Crystal with Battlesnake.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Learning Crystal with Battlesnake

Thematisch verwandte Begriffe: Learning, Crystal, with, Battlesnake · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-82585 | The Botslab G980H dash camera firmware transmits sensitive information o…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel • Rechts: nächster Artikel • unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...
↗ Original-Quelle