Credit qwen3.8-flash-next-iq3xxs with Strata in OpenCode, with pixel marks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-05 15:17:05 +01:00
1 parent b4d834823b
commit 796143f20c
7 files changed
+63 -16

No files matched your search

+1
View File
@@ -1480,6 +1480,7 @@ async fn main() {
}
MenuAction::OpenRepo => platform::open_url(menu::REPO_URL),
MenuAction::OpenClaudeCode => platform::open_url(menu::CLAUDE_CODE_URL),
MenuAction::OpenOpenCode => platform::open_url(menu::OPENCODE_URL),
a @ (MenuAction::Login(..)
| MenuAction::Logout
| MenuAction::OpenAccount
+49 -15
View File
@@ -260,6 +260,7 @@ enum Btn {
Goals,
Repo,
ClaudeCode,
OpenCode,
Field(usize),
DoLogin,
Account,
@@ -292,6 +293,7 @@ enum Btn {
pub const REPO_URL: &str = "https://git.familie-zink.org/zink/dungeoncraft";
pub const CLAUDE_CODE_URL: &str = "https://claude.com/claude-code";
pub const OPENCODE_URL: &str = "https://opencode.ai";
// the game version (file VERSION, "vYYYYMM-NNNNN"): tools/bump_version.py raises it with every
// change, and the title screen and the pause menu show it
@@ -310,9 +312,27 @@ const CLAUDE_MARK: [&str; 5] = [
"....#.#....#.#....",
];
pub fn draw_claude_mark(x: f32, y: f32, px: f32) {
let c = Color::from_rgba(0xd9, 0x77, 0x57, 255);
for (r, row) in CLAUDE_MARK.iter().enumerate() {
// pixel renditions of the Qwen and the OpenCode mark (the second "made with" note)
const QWEN_MARK: [&str; 5] = [
"...###...",
".##.#.##.",
"#..###..#",
".##.#.##.",
"...###...",
];
const OPENCODE_MARK: [&str; 5] = [
"#######",
"#.....#",
"#.#...#",
"#..#.##",
"#######",
];
const CLAUDE_COL: Color = Color { r: 0xd9 as f32 / 255.0, g: 0x77 as f32 / 255.0, b: 0x57 as f32 / 255.0, a: 1.0 };
const QWEN_COL: Color = Color { r: 0x7b as f32 / 255.0, g: 0x6c as f32 / 255.0, b: 0xf6 as f32 / 255.0, a: 1.0 };
const OPENCODE_COL: Color = Color { r: 0.86, g: 0.86, b: 0.88, a: 1.0 };
fn draw_mark(mark: &[&str], x: f32, y: f32, px: f32, c: Color) {
for (r, row) in mark.iter().enumerate() {
for (k, ch) in row.chars().enumerate() {
if ch == '#' {
draw_rectangle(x + k as f32 * px, y + r as f32 * px, px, px, c);
@@ -321,6 +341,7 @@ pub fn draw_claude_mark(x: f32, y: f32, px: f32) {
}
}
pub enum MenuAction {
None,
Consumed,
@@ -353,6 +374,7 @@ pub enum MenuAction {
CampaignStart(usize),
OpenRepo,
OpenClaudeCode,
OpenOpenCode,
Login(String, String),
Logout,
OpenAccount,
@@ -646,6 +668,7 @@ impl Menu {
Some(Btn::NameField) => MenuAction::EditName,
Some(Btn::Repo) => MenuAction::OpenRepo,
Some(Btn::ClaudeCode) => MenuAction::OpenClaudeCode,
Some(Btn::OpenCode) => MenuAction::OpenOpenCode,
Some(Btn::Field(i)) => {
self.focus = i;
if matches!(self.page, Some(Page::Match { .. })) {
@@ -882,19 +905,30 @@ impl Menu {
pub fn draw_license(&mut self, gfx: &Gfx) {
let (sw, sh) = (sw(), sh());
let (mx, my) = mouse();
// "made with Claude Code" with the pixel mark, a link to Claude Code
let made = tr("menu.made_with");
// "made with" notes with their pixel marks, links to the tools:
// Claude Code, then qwen3.8-flash-next-iq3xxs with Strata in OpenCode
let px = (SMALL() * 2.0).round().max(2.0);
let mark_w = 18.0 * px;
let tw = gfx.measure(&made, SMALL());
let total = mark_w + CW() * 0.5 + tw;
let mx0 = grid_center(sw, total);
let my0 = sh - CH() * 4.0;
let r = Rect::new(mx0, my0, total, GH * SMALL() + 2.0);
let hot = r.contains(vec2(mx, my));
draw_claude_mark(mx0, my0 + (GH * SMALL() - 5.0 * px) * 0.5, px);
gfx.text(&made, mx0 + mark_w + CW() * 0.5, my0, SMALL(), if hot { FRAME_HI } else { Color::from_rgba(0xd9, 0x77, 0x57, 255) });
self.buttons.push((r, Btn::ClaudeCode));
let credits: [(&[&[&str]], &[Color], String, Color, Btn, f32); 2] = [
(&[&CLAUDE_MARK], &[CLAUDE_COL], tr("menu.made_with"), CLAUDE_COL, Btn::ClaudeCode, 4.6),
(&[&QWEN_MARK, &OPENCODE_MARK], &[QWEN_COL, OPENCODE_COL], tr("menu.made_with_qwen"), QWEN_COL, Btn::OpenCode, 3.6),
];
for (marks, cols, made, col, btn, row) in credits {
let widths: Vec<f32> = marks.iter().map(|m| m[0].len() as f32 * px).collect();
let mark_w: f32 = widths.iter().sum::<f32>() + px * 2.0 * (marks.len() as f32 - 1.0);
let tw = gfx.measure(&made, SMALL());
let total = mark_w + CW() * 0.5 + tw;
let mx0 = grid_center(sw, total);
let my0 = sh - CH() * row;
let r = Rect::new(mx0, my0, total, GH * SMALL() + 2.0);
let hot = r.contains(vec2(mx, my));
let mut x = mx0;
for (k, m) in marks.iter().enumerate() {
draw_mark(m, x, my0 + (GH * SMALL() - 5.0 * px) * 0.5, px, cols[k]);
x += widths[k] + px * 2.0;
}
gfx.text(&made, mx0 + mark_w + CW() * 0.5, my0, SMALL(), if hot { FRAME_HI } else { col });
self.buttons.push((r, btn));
}
let lic = tr("menu.license");
gfx.text(&lic, grid_center(sw, gfx.measure(&lic, SMALL())), sh - CH() * 2.5, SMALL(), DIM);
let ver = tr("menu.version");