<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
  <title>Paweł Dubiel Tech Blog</title>
  <link>https://paweldubiel.com/hi</link>
  <atom:link href="https://paweldubiel.com/hi/rss.xml" rel="self" type="application/rss+xml" />
  <description>AI, लैंग्वेज मॉडल और सॉफ़्टवेयर इंजीनियरिंग पर नोट्स।</description>
  <language>hi</language>
  <lastBuildDate>Mon, 12 Oct 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>मैंने AI agent को Amiga की floppy disks दीं। एक शाम बाद Pirates! Unity में चल रहा था</title>
  <link>https://paweldubiel.com/hi/articles/pirates-amiga-unity-port</link>
  <guid isPermaLink="true">https://paweldubiel.com/hi/articles/pirates-amiga-unity-port</guid>
  <pubDate>Sun, 11 Oct 2026 22:37:00 GMT</pubDate>
  <dc:creator>Paweł Dubiel</dc:creator>
  <category>ai</category>
  <category>agents</category>
  <category>coding</category>
  <category>llm</category>
  <description>मैंने एक coding agent को 1990 के Amiga वाले Sid Meier&apos;s Pirates! की चार floppy disk images दीं और कहा कि गेम को Unity में ले आए। काम Claude Code में Claude…</description>
  <content:encoded><![CDATA[<p>मैंने एक coding agent को 1990 के Amiga वाले Sid Meier's Pirates! की चार floppy disk images दीं और कहा कि गेम को Unity में ले आए। काम Claude Code में Claude Opus 5.5 ने किया। एक शाम के बाद गेम को title screen से लेकर duel, शहर और नक्शे पर समुद्री सफ़र से होते हुए समुद्री लड़ाई तक खेला जा सकता था, वह भी मूल graphics और sound के साथ। रफ़्तार से ज़्यादा अहम यह है कि नतीजे की जाँच कैसे हुई: फ़ैसलों की एक ही script को C# port पर भी चलाया गया और processor emulator में चल रहे मूल machine code पर भी। 802 runs में, यानी तुलना की गई करीब 60 लाख lines में, दोनों versions ने खिलाड़ी को एक ही चीज़ दिखाई।</p>
<p>मैं यहाँ इस काम के चरण इसलिए लिख रहा हूँ कि ये मिलकर एक ऐसा तरीका बनाते हैं जिसे किसी दूसरे गेम और किसी दूसरे model के साथ दोहराया जा सकता है। आख़िर में मैं इसी ढाँचे पर बना दूसरा project दिखाता हूँ: Centurion: Defender of Rome का DOS से JavaScript में port। दोनों सीखने के लिए बनाए गए निजी projects हैं: मूल गेम, उनके graphics और उनका sound copyright के तहत ही हैं, और मैं इन्हें बाँटता नहीं हूँ।</p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-title-screen.webp" alt="Unity port में Pirates! की title screen: सूर्यास्त के समय समुद्री डाकुओं का झंडा फहराता galleon, 1990 के मूल graphics में बना हुआ।" loading="eager" decoding="async" width="1600" height="900"></p>
<p><em>Unity में title screen। तस्वीर गेम की मूल files से run time पर decode होती है।</em></p>
<h2 id="disk-image-से-decompiled-code-तक">Disk image से decompiled code तक</h2>
<p>Agent ने शुरुआत files को पहचानने से की। Amiga की disk image (ADF) sectors की कच्ची नक़ल होती है, इसलिए उसके अंदर की चीज़ें निकालने के लिए Python की कुछ दर्जन lines काफ़ी थीं। गेम का program एक overlay executable निकला: उसका मुख्य हिस्सा memory में बना रहता है, और code के तीन और segments ज़रूरत पड़ने पर disk से पढ़े जाते हैं। Ghidra, जो एक मुफ़्त decompiler है, इस format को अपने आप नहीं समझता। Agent ने एक script लिखी जो सारे segments को एक ही image में तय addresses पर रखती है और overlays में जाने वाले 45 indirect jumps को सामान्य calls में बदल देती है। इसके बाद decompiler को करीब 630 functions एक ही program की तरह दिखे।</p>
<p>गेम के data में एक हैरानी छिपी थी। <code>.rez</code> extension वाली files की बनावट Macintosh resources जैसी है, क्योंकि Amiga वाला version ख़ुद Mac से किया गया port था। Format पहचान में आते ही agent ने 210 texts, strings की 82 lists, छह युगों के शहरों का data, तस्वीरें, animations, sprites और sounds निकाल लिए। Code का सबसे अच्छा नक्शा ये texts ही साबित हुए: "text दिखाओ" वाली routine को जो string number दिया जाता है, उसी से पता चल जाता है कि कोई function गेम की कौन-सी screen सँभालता है।</p>
<h2 id="तेरह-agents-code-पढ़ते-हैं-नौ-उसे-दोबारा-लिखते-हैं">तेरह agents code पढ़ते हैं, नौ उसे दोबारा लिखते हैं</h2>
<p>Decompiled code करीब 29 हज़ार lines का था, और उसमें functions या variables के कोई नाम नहीं थे। मुख्य agent ने उसे करीब 2 हज़ार lines के टुकड़ों में काटा और हर टुकड़ा एक अलग agent को एक ही लिखित brief के साथ दिया। हर agent को एक file लिखनी थी जिसमें उसके टुकड़े के हर function का ब्योरा हो: सटीक formulas, constants, random ranges, दिखाए जाने वाले texts के numbers, और पढ़े व लिखे जाने वाले global variables। Brief में एक वाक्य था जो आगे चलकर अहम साबित हुआ: ग़लत formula उस कमी से बदतर है जिस पर निशान लगा दिया गया हो। इसलिए agents को वह सब चिह्नित करना था जो वे तय नहीं कर पाए, और अस्पष्ट जगहों को assembly में जाँचना था। यहाँ decompiler ने functions के बहुत-से arguments खो दिए थे, क्योंकि 35 साल पुराना compiler 16-bit वाला <code>int</code> type इस्तेमाल करता था।</p>
<p>दूसरे चरण में भी बँटवारा वैसा ही था। नौ agents ने गेम के नियम C# में दोबारा लिखे, हर एक ने अपनी address range के लिए। इससे करीब 16 हज़ार lines का code बना, और गेम की state एक byte array में गई जिसे ठीक उसी तरह address किया जाता है जैसे मूल गेम की memory को। यह देखने में सुंदर नहीं लगता, लेकिन गलतियों की एक पूरी श्रेणी ख़त्म कर देता है। पुराना code structures को बेझिझक एक-दूसरे के ऊपर रख देता है और tables को उनकी शुरुआत से एक byte पहले से पढ़ लेता है। Memory image पर बने port को line दर line translate करके assembly से मिलाया जा सकता है, और constants की tables वहीं रहती हैं जहाँ code उन्हें ढूँढता है। Drawing, sound और controls की जगह एक interface के calls आ गए, जिसे engine अलग से implement करता है।</p>
<h2 id="oracle-processor-emulator-में-मूल-code">Oracle: processor emulator में मूल code</h2>
<p>Decompiled code पढ़ लेने से यह साबित नहीं होता कि port मूल गेम जैसा ही बर्ताव करता है। इसलिए agent ने तुलना करने वाला एक tool बनाया। Motorola 68000 processor का मूल machine code Unicorn emulator में चलता है। System routines, यानी menus, text boxes, input पढ़ना और drawing, की जगह Python functions लगाए गए। ये functions गेम के हर सवाल का जवाब एक सीधे-सादे decision generator के हिसाब से देते हैं और गेम ने जो कुछ दिखाया उसे दर्ज करते जाते हैं। C# port को फ़ैसलों का ठीक वही क्रम एक "scripted player" के ज़रिए मिलता है, जो Unity के बाहर चलता है। आख़िर में दोनों records की line दर line तुलना होती है। Texts में सोना, crew की संख्या, तारीखें और शहरों के नाम होते हैं, इसलिए records का मेल खाना नियमों की एक मज़बूत परीक्षा है।</p>
<p>पहले पूरे माप में 802 में से 800 runs मेल खाए। दोनों गड़बड़ियों की वजह एक ही थी: floating-point arithmetic। गेम एक software library इस्तेमाल करता है जो आज के processors की तरह round नहीं करती। उसमें 81 का वर्गमूल 8.999999999999998 आता है, और गेम नतीजों को काटकर पूर्णांक बना देता है, इसलिए सोने और crew के कुछ अनुपातों पर port में crew का morale एक अंक ज़्यादा निकल रहा था। इलाज यह था कि library की routines को instruction दर instruction दोबारा लिखा जाए: 1,572 instructions, 43 routines, और मूल code से निकाले गए 21,701 test vectors, जिनमें कोई अंतर नहीं मिला। इस बदलाव के बाद सभी 802 runs मेल खाते हैं, और 120 अतिरिक्त runs में duel, समुद्री सफ़र और समुद्र व ज़मीन की लड़ाइयों में गेम की state को frame दर frame मिलाया गया।</p>
<p>तुलना से 1990 के मूल गेम के दो bugs भी सामने आए: किसी शहर पर तिरछी दिशा से हमला करते समय null pointer के ज़रिए नक्शे को पढ़ना, और crew के शून्य हो जाने पर शून्य से भाग। ऐसी जगहों पर port को कोई एक बर्ताव चुनना पड़ता है, और तुलना वाले tool में एक switch है जो मूल code को भी उसी रास्ते पर चला देता है। नतीजे की सीमाएँ भी हैं। Tool न drawing की तुलना करता है, न sound की, और शादी, पूरा किया गया ख़ज़ाने का नक्शा या सबसे ऊँचे ranks जैसे दुर्लभ रास्ते बहुत कम परखे गए।</p>
<h2 id="presentation-और-वे-चीज़ें-जो-1990-में-नहीं-थीं">Presentation और वे चीज़ें जो 1990 में नहीं थीं</h2>
<p>जो layer खिलाड़ी को दिखती है, वह Unity में code से बनाई गई, बने-बनाए scenes के बिना। तस्वीरें और animations मूल resources से decode होते हैं, sprites अपने रंग मौजूदा screen की palette से लेते हैं, और music को गेम के चार-channel वाले sequencer को emulate करके audio files में render किया गया। Agent चलते हुए गेम को command line से चलाता था, screenshots लेता था और उन्हें देखता था। इससे कई ऐसी खामियाँ पकड़ में आईं जिन्हें नियमों का कोई test नहीं पकड़ता, जैसे browser version में sound का न होना, क्योंकि audio conversion के लिए ffmpeg program चाहिए था और वह install नहीं था।</p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-world-map.webp" alt="Unity port में Caribbean का नक्शा: शहरों वाले द्वीप, दिशा के pointer के साथ खिलाड़ी का जहाज़, और तूफ़ानी बादल।" loading="lazy" decoding="async" width="1600" height="900"></p>
<p><em>नक्शे पर समुद्री सफ़र। Background 160 गुणा 200 cells की terrain grid और मूल tiles से बना है।</em></p>
<p>पहली बार खेलने के बाद मैंने तीन बदलाव करवाए। ख़ज़ाने वाले बेड़े के पहुँचने की तारीख वाला सवाल मूल गेम का copy protection था और उसके लिए छपा हुआ manual चाहिए था; अब quiz बनी हुई है, लेकिन सही जवाब "कप्तान के notes" में दिखता है। शहरों की list सिर्फ़ शहर का data दिखाती थी, क्योंकि गेम मानकर चलता था कि खिलाड़ी के पास छपा हुआ नक्शा है; अब चुना हुआ शहर Caribbean के chart पर चिह्नित होता है। Duel screen को दोनों पक्षों की force, morale और weapon वाली एक table मिली, जिसका layout मूल गेम जैसा है। इन additions को बंद किया जा सकता है, और तुलना वाले tests इनके बिना चलते हैं, इसलिए records अब भी 1990 के code से मेल खाते हैं।</p>
<p><img src="https://paweldubiel.com/assets/pirates-amiga-original-duel-openretro.webp" alt="मूल Amiga गेम का screenshot: एक दीवार के सामने दो तलवारबाज़, और नीचे duel का शीर्षक तथा Force, Morale और Weapon की table।" loading="lazy" decoding="async" width="640" height="400"></p>
<p><em>मूल गेम में duel। Screenshot का स्रोत: OpenRetro Game Database।</em></p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-duel-panel.webp" alt="Unity port में duel: जहाज़ के deck पर तलवारबाज़, और नीचे शीर्षक तथा दोनों पक्षों की force, morale और weapon की table।" loading="lazy" decoding="async" width="1600" height="900"></p>
<p><em>वही screen port में। Table के आँकड़े duel की state से live पढ़े जाते हैं।</em></p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-city-chart.webp" alt="Caribbean का chart जिस पर Port-de-Paix शहर चिह्नित है, खिलाड़ी की स्थिति, और शहर के data व फ़्रांसीसी झंडे वाला एक box।" loading="lazy" decoding="async" width="1600" height="900"></p>
<p><em>मूल गेम में जोड़ी गई चीज़: Caribbean के chart पर चुना हुआ शहर।</em></p>
<h2 id="centurion-वही-ढाँचा-javascript-में-बढ़ाए-गए-gameplay-के-साथ">Centurion: वही ढाँचा JavaScript में, बढ़ाए गए gameplay के साथ</h2>
<p>दूसरा project है Centurion: Defender of Rome, 1990 का एक DOS गेम, जिसे बिना किसी emulator के JavaScript और Canvas element पर लाया गया। चरण वही थे, बस नाम अलग थे। Executable को पहले unpack करना पड़ा, क्योंकि वह EXEPACK tool से compress किया गया था। गेम के पाँच modules (ज़मीनी लड़ाई, gladiator arena, रथ दौड़, नौसैनिक लड़ाई और intro) एक overlay file में थे और एक ही data segment साझा करते थे। Campaign की state उस segment के 64 kilobytes की एक जीवित copy पर चलती है, क्योंकि गेम का engine 16-bit overflow, integer division और signed bytes पर टिका है, जिन्हें JavaScript के floating-point numbers अपने आप नहीं दोहराते। Save किया हुआ गेम मूल format से byte दर byte मेल खाता है, और tests इसकी जाँच करते हैं।</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-title-screen.webp" alt="Browser port में Centurion की title screen: भूमध्य सागर के नक्शे के ऊपर CENTURION शब्द, credits का panel, और Start Game, Difficulty तथा Game Options के buttons।" loading="lazy" decoding="async" width="1070" height="800"></p>
<p><em>Browser में Centurion की title screen, मूल graphics के साथ।</em></p>
<p>यहाँ मैं हूबहू port से आगे गया। मैंने बढ़ाए गए नियमों के लिए एक switch जोड़ा, जो default रूप से बंद रहता है: legions को मिलाना और एक province में कई legions, हल्के velites, युद्ध के हाथी और समुद्र से landing। इस port का code Pirates वाले models से अलग models ने लिखा: ज़्यादातर Gemini 3.8 Flash ने, और कुछ हिस्सा Codex के ज़रिए चलाए गए OpenAI के <code>gpt-6.1-sol</code> ने। यह चुनाव उन tools से तय हुआ जो मेरे पास मौजूद थे, models की किसी तुलना से नहीं।</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-game-options.webp" alt="Centurion port में game options का menu: Extra Features: OFF वाली entry, difficulty level, save और load, और बगल में rank व ख़ज़ाने के साथ Senate का mandate।" loading="lazy" decoding="async" width="1070" height="800"></p>
<p><em>Options menu। पहली entry उन बढ़ाए गए नियमों को चालू करती है जो मूल गेम में नहीं थे।</em></p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-province-screen.webp" alt="Centurion port में Italia province की screen: शहर का दृश्य, बनाए जाने वाले amphitheatre के साथ games का menu, और province की स्थिति: मिज़ाज, tribute, सैनिक।" loading="lazy" decoding="async" width="1086" height="818"></p>
<p><em>Games के menu के साथ province की screen।</em></p>
<h2 id="centurion-में-gemini-को-किन-दिक्कतों-का-सामना-करना-पड़ा">Centurion में Gemini को किन दिक्कतों का सामना करना पड़ा</h2>
<p>ज़्यादातर समय उन जगहों पर गया जहाँ decompiled code या files के नाम कुछ और इशारा करते थे और गेम असल में कुछ और करता था। Project के notes से पाँच उदाहरण:</p>
<ul>
<li><strong>बिना data के overlays।</strong> गेम के पाँचों modules एक ही file, <code>OVL0.OVL</code>, में रहते हैं और एक ही address पर load होते हैं, लेकिन सभी एक साझा data segment इस्तेमाल करते हैं। इसलिए किसी overlay का code अकेले Ghidra में खोलने पर न strings दिखती थीं, न tables। एक script ने हर overlay को data segment के साथ जोड़कर पाँच synthetic executables बनाए, और तभी जाकर decompiler ने minigames के code को campaign के structures से जोड़ा।</li>
<li><strong>जीते हुए provinces की सीमाएँ।</strong> Mouse से click होने वाले regions के नक्शे से province की रूपरेखा खींचने पर दाँतेदार रेखाएँ बनती थीं, जो हाथ से बने नक्शे पर ठीक नहीं बैठती थीं। Code में एक अलग ही तरीका निकला: नक्शे की तस्वीर में हर province का गहरे रंग का, एक pixel चौड़ा छिपा हुआ path है, और data की एक table 27 provinces में से हर एक के लिए एक शुरुआती बिंदु देती है। गेम उस path को शुरुआती बिंदु से शुरू करके साम्राज्य के रंग में दोबारा रंग देता है, और port भी यही करता है।</li>
<li><strong>पीछे की ओर खिसकते frames।</strong> मूल game loop 9–12 Hz पर चलता था, जबकि browser एक second में 60 बार draw करता है। तीन जगहों पर sprite एक पल के लिए एक frame पीछे चला जाता था। Intro वाला globe 10 steps में palette के 14 रंग खिसकाकर घूमता है, लेकिन table में पहले step का मान शून्य है; हर step पर palette खिसकाने से महाद्वीप हर चक्कर में एक बार झटका खाते थे। Marching करती cohorts और gladiators के वारों में क्रम को हूबहू दोहराना पड़ा: पहले बीच वाला frame, फिर स्थिति का बदलाव।</li>
<li><strong>भ्रामक file names।</strong> <code>BB1.CBM</code> और <code>BB2.CBM</code> bitmaps लड़ाई के banners जैसे लगते थे, और screen के ऊपरी हिस्से में draw करने पर पूरे युद्धक्षेत्र को ढक लेते थे। Code इन्हें तभी load करता है जब computer में VGA card न हो: ये पुराने EGA और CGA cards के लिए पूरी screen वाले backgrounds हैं। इसी routine से यह भी पता चला कि लड़ाई से पहले की तैनाती के दो चरण होते हैं। Formation चुनने पर उपलब्ध tactics की list बदल जाती है, और Cannae वाला दाँव wedge चुनने के बाद ही दिखता है।</li>
<li><strong>मुश्किल से सुनाई देने वाला music।</strong> AdLib sound card के driver के 17 tracks और 24 instruments decode करने के बाद धुनें सही थीं, लेकिन करीब −55 dB पर बज रही थीं। Driver को disassemble करने पर पता चला कि वह हर note पर, instrument में दर्ज attenuation में से note की velocity का एक चौथाई हिस्सा घटाता है। Code की एक line ने करीब 32 dB वापस ला दिए। दूसरी खामी browser की तरफ़ थी: बहुत छोटे notes पर Web Audio API में पहले से schedule किए गए volume changes को रद्द करने से वह attack भी मिट जाता था जो अभी चल ही रहा था, और note चुप हो जाता था।</li>
</ul>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-battle-tactics.webp" alt="Centurion port में ज़मीनी लड़ाई: wedge formation के लिए पाँच tactics की list, जिसमें Cannae Tactic भी है, और युद्धक्षेत्र पर तैनात टुकड़ियाँ।" loading="lazy" decoding="async" width="1086" height="818"></p>
<p><em>लड़ाई से पहले तैनाती का दूसरा चरण: wedge formation के लिए उपलब्ध tactics।</em></p>
<p>Circus Maximus की रथ दौड़ अपने आप में एक अलग काम थी। वहाँ रथ कोई एक तस्वीर नहीं है। रथ की तीन classes, सारथी के चार रंग, चार actions, मोड़ में झुकाव के सोलह कोण और सरपट दौड़ के तीन frames, इन सबके हर मेल के लिए अलग bitmap रखने का मतलब होता 2,300 से ज़्यादा frames, इसलिए गेम बनाने वालों ने memory में 16-byte वाले nodes का एक tree बनाया। हर node उसी level के अगले element की ओर और अपने पहले child की ओर इशारा करता है, और उसमें एक frame index, animation के एक के बाद एक आने वाले frames के offsets की table, और visibility का एक flag होता है। Root चार घोड़े हैं। रथ के hull में एक अतिरिक्त horizontal offset है, जिसमें मोड़ काटने की physics 0 से 15 pixels का झुकाव लिखती है, और सारथी उसका child है, इसलिए उसे वही स्थिति विरासत में मिलती है। यही वजह है कि मोड़ पर सारथी hull के साथ झुकता है, जबकि घोड़े track की धुरी पर ही दौड़ते रहते हैं। टूटते axle और लुढ़कते मलबे वाली शाखाएँ हर समय मौजूद रहती हैं; बस उनका visibility flag बंद रहता है।</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-chariot-sprite-tree.webp" alt="Centurion में रथ के sprite tree का diagram: चार घोड़ों वाला node, तीन classes में hull का node, crash की states वाले nodes, सारथी के चार animations, और बिना झुकाव तथा 12 pixels के झुकाव के साथ जोड़ा गया पूरा रथ।" loading="lazy" decoding="async" width="920" height="540"></p>
<p><em>गेम के data से दोबारा तैयार किया गया रथ का sprite tree। Diagram इसी project में मूल, decode किए गए resources से बनाया गया।</em></p>
<p>Track भी tiles से नहीं बना है। गेम coordinates के 72 stored जोड़ों को फैलाकर 368 control points बनाता है और track की चौड़ाई में स्थिति को 16 lanes में बाँटता है। Lane से मोड़ की सुरक्षित speed तय होती है, जिसका हिसाब (lane number + 15) × 4 से लगता है: अंदरूनी दीवार के पास यह 60 है, बाहरी barrier के पास 116–120। अंदर वाली lane सबसे छोटा रास्ता है, लेकिन इस सीमा से ऊपर की speed पर hairpin में घुसने से hull झुक जाता है, रथ बाहर की ओर धकेला जाता है और crash के लिए पासा फेंका जाता है; सीमा जितनी ज़्यादा लाँघी जाए, crash की संभावना उतनी बढ़ती जाती है। Speed bar पर लाल marker खिलाड़ी को यही सीमा दिखाता है।</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-circus-track-physics.webp" alt="Circus Maximus के track की geometry: stadium की तस्वीर पर रंगों से चिह्नित सीधे हिस्से, braking zones और hairpins, और सुरक्षित speed का chart जो अंदर वाली lane में 60 से बढ़कर बाहर वाली में 120 तक जाता है।" loading="lazy" decoding="async" width="880" height="500"></p>
<p><em>Track के 368 points और lane के हिसाब से मोड़ की सुरक्षित speed।</em></p>
<h2 id="games-के-अलावा-इस-काम-से-क्या-बचा">Games के अलावा इस काम से क्या बचा</h2>
<p>मैंने इस तरीके को एक skill के रूप में लिख लिया है, यानी निर्देशों का ऐसा set जिसे agent मिलता-जुलता काम मिलने पर load कर लेता है। इसमें दोनों projects से निकले तीन सिद्धांत हैं। गेम के नियम हूबहू port किए जाते हैं, और presentation की जगह एक interface आता है। Port मूल गेम का memory layout बनाए रखता है। नतीजे पर तब तक भरोसा नहीं किया जाता जब तक वह मूल code के साथ तुलना में पास न हो जाए। Skill में analysis और porting करने वाले agents के briefs और Pirates project की scripts भी शामिल हैं।</p>
<p>सबसे दिलचस्प नतीजा agents के बारे में नहीं, fans के बारे में है। जिसके पास कोई पसंदीदा गेम है और जिसे उसमें बरसों से किसी चीज़ की कमी खलती रही है, वह आज source code के बिना, जल्दी और कम ख़र्च में उसे अपने हिसाब से बदल सकता है। Pirates में जिस quiz के लिए छपा हुआ manual चाहिए था, वह अब ख़ुद जवाब बता देता है, और एक नक्शा जुड़ गया जो गेम में कभी था ही नहीं। Centurion में मैंने वे नियम जोड़े जो original में नहीं थे: legions को मिलाना, जंगी हाथी और समुद्र से उतरना। जब गेम के नियम C# या JavaScript का आम code बन जाते हैं, तो अगला बदलाव code का एक आम बदलाव होता है, binary को patch करना नहीं। इसी तरह गेम को किसी तेज़ engine या दूसरे platform पर भी ले जाया जा सकता है: Centurion browser में चलता है, और Pirates Linux और browser के लिए build होता है। यह तरीक़ा सिर्फ़ पुराने गेम तक सीमित भी नहीं है। Decompiler, processor emulator और records की तुलना किसी नए program पर भी वैसे ही काम करते हैं; ज़्यादा code का मतलब ज़्यादा काम है, कोई अलग तरीक़ा नहीं।</p>
<h2 id="स्रोत">स्रोत</h2>
<ul>
<li>दोनों projects की मेरी अपनी सामग्री: code analysis के notes, agents के लिए briefs, तुलना वाले tool की report (802 runs, मिले हुए अंतरों की list), और specifications के साथ Centurion port का विवरण। ये प्रकाशित नहीं हैं।</li>
<li>National Security Agency, <a href="https://github.com/NationalSecurityAgency/ghidra" rel="noopener noreferrer">Ghidra</a>, reverse engineering का वह suite जिससे दोनों गेम decompile किए गए।</li>
<li><a href="https://www.unicorn-engine.org/" rel="noopener noreferrer">Unicorn Engine</a>, वह processor emulator जिसमें मूल 68000 code चलाया गया।</li>
<li>OpenRetro Game Database, <a href="https://openretro.org/amiga/pirates" rel="noopener noreferrer">Amiga पर Pirates! का page</a>, मूल गेम के screenshot का स्रोत।</li>
</ul>]]></content:encoded>
</item>
<item>
  <title>लंबे METR horizon का मतलब उसी अनुपात में कठिन tasks नहीं है</title>
  <link>https://paweldubiel.com/hi/articles/a-longer-metr-horizon-does-not-mean-proportionally-harder-tasks</link>
  <guid isPermaLink="true">https://paweldubiel.com/hi/articles/a-longer-metr-horizon-does-not-mean-proportionally-harder-tasks</guid>
  <pubDate>Sun, 11 Oct 2026 15:03:00 GMT</pubDate>
  <dc:creator>Paweł Dubiel</dc:creator>
  <category>ai</category>
  <category>papers</category>
  <category>llm</category>
  <category>agents</category>
  <category>benchmarks</category>
  <description>एक टीम यह तय करना चाहती है कि agent के अगले version को programming के ज़्यादा लंबे tasks सौंपे जा सकते हैं या नहीं। इसलिए वह benchmark के उन नतीजों की तुलना…</description>
  <content:encoded><![CDATA[<p>एक टीम यह तय करना चाहती है कि agent के अगले version को programming के ज़्यादा लंबे tasks सौंपे जा सकते हैं या नहीं। इसलिए वह benchmark के उन नतीजों की तुलना करती है जो उस समय में बताए गए हैं जो इंसान को वह काम करने में लगा। ऐसे नतीजे को आसानी से इस बात का संकेत मान लिया जाता है कि अब कितना काम agent को दिया जा सकता है।</p>
<p>लेकिन इस व्याख्या के लिए यह जाँचना ज़रूरी है कि इंसान का लंबा काम सचमुच AI के लिए उसी हिसाब से कठिन task है या नहीं। अगर किसी दायरे में tasks agent के लिए लगभग बराबर कठिन हैं, तो उसकी सफलता में मामूली सुधार भी नतीजे को मिनटों के बड़े दायरे के पार खिसका सकता है।</p>
<p>तब agent चुनते समय हमें एक और जानकारी चाहिए: उन्हीं tasks को पूरा करने की संभावना कितनी बदली। अगर हम benchmark के ठीक उस हिस्से की तुलना कर रहे हों जहाँ समय कठिनाई में कम फ़र्क़ करता है, तो समय का multiplier अकेले versions के बीच के अंतर को बढ़ा-चढ़ाकर दिखा सकता है।</p>
<p><a href="https://metr.org/time-horizons/" rel="noopener noreferrer">METR ऐसे माप को</a> <a href="https://paweldubiel.com/hi/glossary/time-horizon">time horizon</a> कहता है। 50% threshold वाले रूप में यह इंसान के काम का वह समय है जिस पर fit किया गया curve अनुमान लगाता है कि agent की आधी कोशिशें सफल होंगी। यह किसी तय समय वाले tasks का औसत है, उनमें से हर एक के लिए गारंटी नहीं। यहाँ हम ख़ुद AI के चलने का समय नहीं नापते।</p>
<p>Preprint <a href="https://arxiv.org/abs/2610.12466" rel="noopener noreferrer"><em>On the estimation and validity of AI time horizons—a statistical look at the METR plot</em></a> में Drew T. Nguyen और William Fithian समय को कठिनाई में बदलने के इसी रूपांतरण का विश्लेषण करते हैं। AI evaluation और statistics के क्षेत्र का यह पेपर पहली बार 8 अक्टूबर 2026 को प्रकाशित हुआ। यह METR के data में इंसान के काम के 2 से 30 मिनट के बीच एक लगभग सपाट हिस्सा दिखाता है। इस दायरे के tasks, जाँचे गए agents के लिए, औसतन लगभग बराबर कठिन थे।</p>
<h2 id="संभावना-में-छोटा-बदलाव-threshold-को-दूर-तक-खिसका-सकता-है">संभावना में छोटा बदलाव threshold को दूर तक खिसका सकता है</h2>
<p>नीचे का उदाहरण समझाने के लिए किया गया मेरा अपना सरलीकरण है, किसी शोध का नतीजा नहीं। हमारे पास तीन tasks हैं: A, B और C, जिनमें इंसान को क्रमशः 3, 10 और 30 मिनट लगते हैं। दोनों agents में से हर एक, हर task को एक ही environment में 100 बार करता है। हम सफलता या असफलता दर्ज करते हैं।</p>





























<table><thead><tr><th>Task</th><th>इंसान का समय</th><th>पुराने agent की सफलताएँ</th><th>नए agent की सफलताएँ</th></tr></thead><tbody><tr><td>A</td><td>3 मिनट</td><td>100 में से 50</td><td>100 में से 52</td></tr><tr><td>B</td><td>10 मिनट</td><td>100 में से 49</td><td>100 में से 51</td></tr><tr><td>C</td><td>30 मिनट</td><td>100 में से 48</td><td>100 में से 50</td></tr></tbody></table>
<p>बात साफ़ रखने के लिए इन आवृत्तियों को ठीक-ठीक मालूम संभावनाएँ मान लेते हैं और बिंदुओं को घटते हुए curves से जोड़ देते हैं। पुराना agent 50% को 3 मिनट पर काटता है, नया 30 मिनट पर। Horizon दस गुना बढ़ जाता है, जबकि हर task पर सफलता सिर्फ़ 2 percentage points बढ़ी। हर agent की 300 कोशिशों में सफलताओं की संख्या 147 से 153 हुई।</p>
<p>तीनों tasks और सारी असफलताएँ माप में बनी रहती हैं। हम सिर्फ़ वह जगह चुनते हैं जहाँ curve threshold को काटता है; न कुछ छाँटते हैं, न किसी चीज़ को इनाम देते हैं। इस काल्पनिक test की लागत agent की 600 पूरी कोशिशें है। असली प्रयोग में इतनी संख्याओं के आधार पर 2 percentage points के अंतर को पक्का नहीं माना जा सकता। Curve fit करना पड़ता है और अनिश्चितता का अनुमान लगाना पड़ता है।</p>
<p>यह उदाहरण दिखाता है कि लगभग सपाट curve से horizon कैसे पढ़ा जाता है। शोध में उसकी शक्ल पहले बहुत-से tasks और systems से तय करनी पड़ती है। अगर किसी दूसरे दायरे में curve कहीं तेज़ी से गिरता है, तो horizon के उसी multiplier के लिए सफलता की संभावना में ज़्यादा बढ़ोतरी चाहिए। इसीलिए 3 से 30 मिनट तक का और 30 मिनट से 5 घंटे तक का सफ़र परिभाषा से ही तरक़्क़ी के बराबर हिस्से नहीं हैं।</p>
<h2 id="इंसान-के-समय-को-ai-के-लिए-कठिनाई-से-मिलाना-पड़ता-है">इंसान के समय को AI के लिए कठिनाई से मिलाना पड़ता है</h2>
<p>शुरुआती बिंदु नतीजों की तालिका है: किस agent ने कौन-सा task किया, कितनी बार और किस नतीजे के साथ। हमें इंसान का समय और task का परिवार भी मालूम है। हमें ऐसी कोई एक वस्तुनिष्ठ संख्या मालूम नहीं जो AI के लिए उसकी कठिनाई बताए।</p>
<p>लेखकों का baseline मानता है कि इंसान के समय का हर अगला दोगुना होना कठिनाई को एक जैसे क़दम से बढ़ाता है। वह सभी agents के लिए curves का एक साझा slope इस्तेमाल करता है; agents आपस में क्षमता के स्तर में अलग होते हैं। यह हर system के लिए अलग regression से, जो शुरू में इस्तेमाल होता था, ज़्यादा मज़बूत संदर्भ बिंदु है।</p>
<p>पहला प्रस्ताव तय क़दम की जगह data से सीखा गया, monotonic, spline क़िस्म का curve रखता है: आसानी से जुड़े हुए टुकड़े, जो तेज़ या धीमे बढ़ सकते हैं। लंबा समय अब भी अनुमानित कठिनाई को घटाता नहीं, लेकिन बढ़ोतरी का एक समान होना ज़रूरी नहीं।</p>
<p>दूसरा प्रस्ताव, जिसे पेपर में Model 2 कहा गया है, <a href="https://paweldubiel.com/hi/glossary/item-response-theory">item response theory, IRT</a> का इस्तेमाल करता है। यह सफलताओं और असफलताओं के pattern से agents की क्षमता और tasks की कठिनाई का एक साथ अनुमान लगाता है। यह एक ही परिवार के tasks की समानता और कोशिशों के नतीजों के अतिरिक्त बिखराव को भी ध्यान में रखता है। इससे एक ही agent–task जोड़े की कई दोहराई गई कोशिशों को पूरे benchmark के बारे में उतनी ही नई, स्वतंत्र जानकारियाँ नहीं मान लिया जाता।</p>
<p>पहला क़दम जिसमें baseline और नए तरीके अलग होते हैं, इंसान के समय को कठिनाई में बदलना है। Agents के input नतीजे वही रहते हैं। यानी नई fit, AI का एक भी जवाब बदले बिना, horizon को बदल सकती है।</p>
<h2 id="gpt-4o-के-उन्हीं-नतीजों-से-अलग-horizon-निकला">GPT-4o के उन्हीं नतीजों से अलग horizon निकला</h2>
<p>लेखक METR Time Horizon 1.1 के दर्ज नतीजों का दोबारा विश्लेषण करते हैं: 228 tasks और 26 AI systems। चित्र 1 में GPT-4o का horizon साझा slope वाले baseline के हिसाब से 7.2 मिनट है और Model 2 के हिसाब से 4.4 मिनट। ये उन्हीं कोशिशों से निकले दो अनुमान हैं; न यह GPT-4o के काम में गिरावट है, न उसके inference की लागत की तुलना।</p>
<p>ज़्यादा लचीला curve बस noise पर बेहतर fit हो सकता था। इसलिए लेखक tasks के उन पूरे परिवारों पर नतीजों के अनुमान को जाँचते हैं जो fit में इस्तेमाल नहीं हुए। पाँच हिस्सों वाले validation में वे 79 परिवारों को बाँटते हैं, एक ही task की अलग-अलग कोशिशों को नहीं। Measure और नतीजों को weight देने के तरीके के सभी 12 मेलों में दोनों नए तरीकों के point estimates बेहतर हैं। इसका मतलब सफलता के अनुमान में कम ग़लती है, ख़ुद agents की सफलता में बढ़ोतरी नहीं। <a href="https://arxiv.org/html/2610.12466v1#S2.SS5" rel="noopener noreferrer">§2.4–2.5 और चित्र 2</a></p>
<p>यह बढ़त बराबर नहीं बँटती। Fit सबसे ज़्यादा GPT-4 के दौर के systems के लिए सुधरती है, जिनके horizons बताए गए सपाट दायरे से होकर गुज़रते हैं। सबसे ताक़तवर systems के लिए तुलना किए गए curves लगभग एक-दूसरे पर आ जाते हैं। अलग-अलग systems के अनुमान भी कुल नतीजे के मुकाबले कहीं कम निर्णायक हैं। <a href="https://arxiv.org/html/2610.12466v1#A1" rel="noopener noreferrer">परिशिष्ट A</a></p>
<details>
<summary>प्रयोग का ब्योरा</summary>
<p><strong>Data और setting।</strong> यह METR के सार्वजनिक नतीजों का दोबारा विश्लेषण है, agents को नए सिरे से चलाने की कोई श्रृंखला नहीं। Tasks software पर काम से जुड़े हैं और उनकी सफलता का मूल्यांकन अपने आप होता है। इंसान का समय आम तौर पर सफल कोशिशों के समयों का geometric mean है; कुछ मान विशेषज्ञों के आकलन से आए हैं। AI के inference का समय नापे जा रहे horizon का variable नहीं है।</p>
<p><strong>Model और checkpoint का चुनाव।</strong> लेखक न नए LLM train करते हैं, न उनका सबसे अच्छा checkpoint चुनते हैं। वे METR के पहले के evaluations के दर्ज नतीजे इस्तेमाल करते हैं। GPT-4o एक API model है, जिसके parameters की संख्या सार्वजनिक नहीं की गई। यह विश्लेषण weights चुनने की उसकी भीतरी प्रक्रिया तय नहीं करता। Statistical fits में maximum likelihood का तरीका इस्तेमाल होता है; Model 2 EM algorithm और integrals के numerical approximation का इस्तेमाल करता है। Curves की शक्ल के charts पूरे data पर बने हैं, जबकि ऊपर बताई गई prediction की गुणवत्ता की तुलना परिवारों के हिसाब से किए गए बँटवारे पर टिकी है।</p>
<p><strong>Measures।</strong> इस set में marginal log score, यानी binary <a href="https://paweldubiel.com/glossary/cross-entropy" hreflang="pl">cross-entropy [Polski]</a>, Brier score, और 50% तथा 80% के thresholds के पास की ग़लती के smoothed measures शामिल हैं। Cross-entropy पक्के भरोसे से किए गए ग़लत अनुमानों को भारी सज़ा देता है; Brier score संभावना और सफलता/असफलता वाले नतीजे के अंतर का वर्ग नापता है। कम मान बेहतर है। चारों measures में से हर एक को weight देने के तीन तरीकों पर निकाला गया: बराबर tasks, बराबर परिवार, और METR का इस्तेमाल किया हुआ बीच का रूप। हम इन्हें जोड़कर सुधार का कोई एक प्रतिशत नहीं बनाते।</p>
<p><strong>लागत और अनिश्चितता।</strong> नए विश्लेषण के लिए statistical fits चाहिए, validation के हर बँटवारे के लिए अलग से भी, लेकिन जाँचे जा रहे LLMs के अतिरिक्त calls नहीं चाहिए। पेपर यह नहीं बताता कि estimator को अपनाने से समय या पैसे की कितनी बचत होती है। मुख्य तुलना के uncertainty intervals tasks के परिवारों के हिसाब से निकाले गए हैं। हर measure का बेहतर point estimate यह नहीं बताता कि हर अलग contrast सांख्यिकीय रूप से निर्णायक है।</p>
</details>
<h2 id="लंबे-tasks-के-लिए-scale-को-दोबारा-जाँचना-ज़रूरी-है">लंबे tasks के लिए scale को दोबारा जाँचना ज़रूरी है</h2>
<p>पेपर सपाट हिस्से की वजह तय नहीं करता और यह नहीं दिखाता कि वह हर benchmark में दिखेगा। वह यह भी साबित नहीं करता कि METR के tasks programmer के पूरे काम का प्रतिनिधित्व करते हैं। लेखक तरक़्क़ी के देखे गए exponential trend पर सवाल नहीं उठाते; वे यह जाँचते हैं कि इंसान के काम के समय वाले axis पर फ़ासलों का क्या मतलब है।</p>
<p>व्यावहारिक उपयोग यह है कि horizon के साथ tasks के तय दायरों के लिए सफलता की संभावना का chart भी रखा जाए। इससे दिखता है कि horizon की छलाँग भरोसेमंदी में किसी साफ़ बदलाव से मेल खाती है या नहीं। अपने benchmark में लंबे tasks जोड़ते समय, अब तक के curve को आगे बढ़ाने से पहले, अलग रखे गए परिवारों पर यह जाँच लेना ठीक रहेगा कि उनका समय अब भी agent के लिए कठिनाई का अनुमान देता है या नहीं।</p>
<h2 id="स्रोत">स्रोत</h2>
<ul>
<li>Drew T. Nguyen, William Fithian, <a href="https://arxiv.org/abs/2610.12466" rel="noopener noreferrer"><em>On the estimation and validity of AI time horizons—a statistical look at the METR plot</em></a>, preprint, 2026, v1। arXiv:2610.12466; DOI: 10.48550/arXiv.2610.12466। <a href="https://arxiv.org/html/2610.12466v1" rel="noopener noreferrer">पूरा पाठ</a>।</li>
<li>METR, <a href="https://metr.org/time-horizons/" rel="noopener noreferrer"><em>Task-Completion Time Horizons of Frontier AI Models</em></a>, माप की परिभाषा, evaluation की प्रक्रिया और सीमाएँ। Page पर लिखा है कि chart अब सक्रिय रूप से update नहीं किया जाता।</li>
</ul>]]></content:encoded>
</item>
<item>
  <title>SemiAnalysis ने AI subscriptions की limits की तुलना की</title>
  <link>https://paweldubiel.com/hi/articles/semianalysis-compares-ai-subscription-limits</link>
  <guid isPermaLink="true">https://paweldubiel.com/hi/articles/semianalysis-compares-ai-subscription-limits</guid>
  <pubDate>Sat, 10 Oct 2026 11:06:52 GMT</pubDate>
  <dc:creator>Paweł Dubiel</dc:creator>
  <category>ai</category>
  <description>SemiAnalysis ने 5 अक्टूबर 2026 के अपने विश्लेषण में AI subscriptions की असली limits की तुलना की है। लेखक जाँचते हैं कि अलग-अलग तरह के tokens usage के meters…</description>
  <content:encoded><![CDATA[<p>SemiAnalysis ने <a href="https://newsletter.semianalysis.com/p/anthropic-subscriptions-offer-5x" rel="noopener noreferrer">5 अक्टूबर 2026 के अपने विश्लेषण</a> में AI subscriptions की असली limits की तुलना की है। लेखक जाँचते हैं कि अलग-अलग तरह के <a href="https://paweldubiel.com/glossary/token" hreflang="pl">tokens [Polski]</a> usage के meters को कितना आगे खिसकाते हैं, और फिर उपलब्ध कोटे को इस हिसाब में बदलते हैं कि ठीक उतना ही इस्तेमाल API के ज़रिए कितने का पड़ता।</p>
<p>उनके माप के मुताबिक, agents के काम में tokens के जो अनुपात उन्होंने माने हैं, उन पर Opus 5.5 वाला Claude, API की दरों के हिसाब से, GPT-6.1 Sol वाली OpenAI की तुलना में रखी गई subscriptions से करीब पाँच गुना ज़्यादा मूल्य देता है। यह उपलब्ध इस्तेमाल का माप है; काम पूरा करने में models कितने कारगर हैं, इसकी तुलना यहाँ नहीं की गई।</p>
<p>लेख यह भी दिखाता है कि OpenAI के नए Pro 200 में tokens का कोटा आधा कर देने का क्या असर पड़ा, और एक पकड़े गए A/B test का ब्योरा देता है, जिसमें एक account की limits करीब 20% कम थीं। यानी subscription का मूल्य इस पर भी निर्भर करता है कि usage गिनने के नियम कैसे बदलते रहते हैं।</p>
<p>बिचौलिया सेवाओं की अंतिम तुलना सिर्फ़ paid subscribers के लिए उपलब्ध है।</p>]]></content:encoded>
</item>
</channel>
</rss>