Buckets:

HuggingFaceDocBuilder's picture
download
raw
174 kB
import{s as ca,a as Ea,n as ua,o as Na}from"../chunks/scheduler.2b22cead.js";import{S as ha,i as ma,e as n,s as J,c as a,h as da,a as M,d as t,b as e,f as A,g as i,j as U,k as b,q as B,l as o,m as T,n as y,t as p,o as w,p as j}from"../chunks/index.1a0e8013.js";import{C as ga,H as I}from"../chunks/Heading.ed738213.js";import{C as r}from"../chunks/CodeBlock.8e4c193f.js";import{E as Aa}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.af82ea15.js";function ba(wM){let g,MT,eT,UT,Q,aT,k,iT,u,R,jM,zn,V,Hn,Ot,IM="<strong>What if RL environments were as easy to use as REST APIs?</strong>",_n,Zt,oM="That’s OpenEnv. Type-safe. Isolated. Production-ready. 🎯",Xn,Ft,rM='<a href="https://colab.research.google.com/github/huggingface/OpenEnv/blob/main/examples/OpenEnv_Tutorial.ipynb" rel="nofollow"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a> <a href="https://github.com/huggingface/OpenEnv" rel="nofollow"><img src="https://img.shields.io/badge/GitHub-huggingface%2FOpenEnv-blue?logo=github" alt="GitHub"/></a> <a href="https://opensource.org/licenses/BSD-3-Clause" rel="nofollow"><img src="https://img.shields.io/badge/License-BSD%203--Clause-green.svg" alt="License"/></a> <a href="https://pytorch.org/" rel="nofollow"><img src="https://img.shields.io/badge/PyTorch-EE4C2C?logo=pytorch&amp;logoColor=white" alt="PyTorch"/></a>',Dn,Wt,CM="Author: Sanyam Bhutani",yT,S,pT,f,cM="Let’s take a trip down memory lane:",wT,v,EM="It’s 2016, RL is popular. You read some papers, it looks promising.",jT,G,uM="But in real world: Cartpole is the best you can run on a gaming GPU.",IT,O,NM="What do you do beyond Cartpole?",oT,Z,hM="Fast-forward to 2025, GRPO is awesome and this time it’s not JUST in theory, it works well in practise and is really here!",rT,F,mM="The problem still remains, how do you take these RL algorithms and take them beyond Cartpole?",CT,W,dM="A huge part of RL is giving your algorithms environment access to learn.",cT,Y,gM="We are excited to introduce an Environment Spec for adding Open Environments for RL Training. This will allow you to focus on your experiments and allow everyone to bring their environments.",ET,$,AM="Focus on experiments, use OpenEnvironments, and build agents that go beyond Cartpole on a single spec.",uT,NT,hT,x,mT,z,bM='<tr><td width="50%"><p><strong>🎯 Part 1-2: The Fundamentals</strong></p> <ul><li>⚡ RL in 60 seconds</li> <li>🤔 Why existing solutions fall short</li> <li>💡 The OpenEnv solution</li></ul></td> <td width="50%"><p><strong>🏗️ Part 3-5: The Architecture</strong></p> <ul><li>🔧 How OpenEnv works</li> <li>🔍 Exploring real code</li> <li>🎮 OpenSpiel integration example</li></ul></td></tr> <tr><td width="50%"><p><strong>🎮 Part 6-8: Hands-On Demo</strong></p> <ul><li>🔌 Use existing OpenSpiel environment</li> <li>🤖 Test 4 different policies</li> <li>👀 Watch learning happen live</li></ul></td> <td width="50%"><p><strong>🔧 Part 9-10: Going Further</strong></p> <ul><li>🎮 Switch to other OpenSpiel games</li> <li>✨ Build your own integration</li> <li>🌐 Deploy to production</li></ul></td></tr>',dT,H,BM=`!!! tip “Pro Tip”
This notebook is designed to run top-to-bottom in Google Colab with zero setup!`,gT,_,QM="⏱️ <strong>Time</strong>: ~5 minutes | 📊 <strong>Difficulty</strong>: Beginner-friendly | 🎯 <strong>Outcome</strong>: Production-ready RL knowledge",AT,bT,BT,X,QT,D,kT,q,kM='<li><a href="#part-1-rl-in-60-seconds">Part 1: RL in 60 Seconds ⏱️</a></li> <li><a href="#part-2-the-problem-with-traditional-rl">Part 2: The Problem with Traditional RL 😤</a></li> <li><a href="#part-3-setup">Part 3: Setup 🛠️</a></li>',RT,L,VT,P,RM='<li><a href="#part-4-the-openenv-pattern">Part 4: The OpenEnv Pattern 🏗️</a></li> <li><a href="#part-5-example-integration---openspiel">Part 5: Example Integration - OpenSpiel 🎮</a></li>',ST,K,fT,ll,VM='<li><a href="#part-6-using-real-openspiel">Part 6: Interactive Demo 🎮</a></li> <li><a href="#part-7-four-policies">Part 7: Four Policies 🤖</a></li> <li><a href="#part-8-policy-competition">Part 8: Policy Competition! 🏆</a></li>',vT,sl,GT,tl,SM='<li><a href="#part-9-switching-to-other-games">Part 9: Using Real OpenSpiel 🎮</a></li> <li><a href="#part-10-create-your-own-integration">Part 10: Create Your Own Integration 🛠️</a></li>',OT,Tl,ZT,Jl,fM='<li><a href="#summary-your-journey">Summary: Your Journey 🎓</a></li> <li><a href="#resources">Resources 📚</a></li>',FT,WT,YT,el,vM="(part-1-rl-in-60-seconds)=",$T,nl,xT,Ml,GM="<strong>Reinforcement Learning is simpler than you think.</strong>",zT,Ul,OM="It’s just a loop:",HT,al,_T,il,ZM="That’s it. That’s RL.",XT,yl,FM="Let’s see it in action:",DT,pl,qT,wl,WM="<strong>Output:</strong>",LT,jl,PT,KT,lJ,Il,YM="(part-2-the-problem-with-traditional-rl)=",sJ,ol,tJ,rl,TJ,Cl,$M="Good question! Gym is great for research, but production needs more…",JJ,cl,xM="<thead><tr><th>Challenge</th> <th>Traditional Approach</th> <th>OpenEnv Solution</th></tr></thead> <tbody><tr><td><strong>Type Safety</strong></td> <td>❌ <code>obs[0][3]</code> - what is this?</td> <td>✅ <code>obs.info_state</code> - IDE knows!</td></tr> <tr><td><strong>Isolation</strong></td> <td>❌ Same process (can crash your training)</td> <td>✅ Docker containers (fully isolated)</td></tr> <tr><td><strong>Deployment</strong></td> <td>❌ “Works on my machine” 🤷</td> <td>✅ Same container everywhere 🐳</td></tr> <tr><td><strong>Scaling</strong></td> <td>❌ Hard to distribute</td> <td>✅ Deploy to Kubernetes ☸️</td></tr> <tr><td><strong>Language</strong></td> <td>❌ Python only</td> <td>✅ Any language (HTTP API) 🌐</td></tr> <tr><td><strong>Debugging</strong></td> <td>❌ Cryptic numpy errors</td> <td>✅ Clear type errors 🐛</td></tr></tbody>",eJ,El,nJ,ul,zM="<strong>“RL environments should be like microservices”</strong>",MJ,Nl,HM="Think of it like this: You don’t run your database in the same process as your web server, right? Same principle!",UJ,hl,_M="<li>🔒 <strong>Isolated</strong>: Run in containers (security + stability)</li> <li>🌐 <strong>Standard</strong>: HTTP API, works everywhere</li> <li>📦 <strong>Versioned</strong>: Docker images (reproducibility!)</li> <li>🚀 <strong>Scalable</strong>: Deploy to cloud with one command</li> <li>🛡️ <strong>Type-safe</strong>: Catch bugs before they happen</li> <li>🔄 <strong>Portable</strong>: Works on Mac, Linux, Windows, Cloud</li>",aJ,ml,iJ,dl,yJ,gl,XM=`!!! info “Key Insight”
You never see HTTP details - just clean Python methods!`,pJ,Al,wJ,bl,DM="<strong>Output:</strong>",jJ,Bl,IJ,oJ,rJ,Ql,qM="(part-4-the-openenv-pattern)=",CJ,kl,cJ,Rl,EJ,Vl,uJ,Sl,LM="Let’s explore the actual OpenEnv code to see how this works:",NJ,fl,hJ,vl,PM="<strong>Output:</strong>",mJ,Gl,dJ,gJ,AJ,Ol,KM="(part-5-example-integration---openspiel)=",bJ,Zl,BJ,Fl,QJ,Wl,lU="<strong>OpenSpiel</strong> is a library from DeepMind with <strong>70+ game environments</strong> for RL research.",kJ,Yl,RJ,$l,sU="We’ve wrapped <strong>6 OpenSpiel games</strong> following the OpenEnv pattern:",VJ,xl,tU="<thead><tr><th><strong>🎯 Single-Player</strong></th> <th><strong>👥 Multi-Player</strong></th></tr></thead> <tbody><tr><td>1. <strong>Catch</strong> - Catch falling ball</td> <td>5. <strong>Tic-Tac-Toe</strong> - Classic 3×3</td></tr> <tr><td>2. <strong>Cliff Walking</strong> - Navigate grid</td> <td>6. <strong>Kuhn Poker</strong> - Imperfect info poker</td></tr> <tr><td>3. <strong>2048</strong> - Tile puzzle</td> <td></td></tr> <tr><td>4. <strong>Blackjack</strong> - Card game</td> <td></td></tr></tbody>",SJ,zl,TU="This shows how OpenEnv can wrap <strong>any</strong> existing RL library!",fJ,Hl,vJ,_l,JU="<strong>Output:</strong>",GJ,Xl,OJ,Dl,ZJ,ql,FJ,Ll,eU="<strong>Output:</strong>",WJ,Pl,YJ,Kl,$J,ls,nU="The client <strong>inherits from HTTPEnvClient</strong> and implements 3 methods:",xJ,ss,MU="<li><code>_step_payload()</code> - Convert action → JSON</li> <li><code>_parse_result()</code> - Parse JSON → typed observation</li> <li><code>_parse_state()</code> - Parse JSON → state</li>",zJ,ts,UU="That’s it! The base class handles all HTTP communication.",HJ,_J,XJ,Ts,aU="(part-6-using-real-openspiel)=",DJ,Js,qJ,C,es,qn,Yt,iU="We’ll play <strong>Catch</strong> using OpenEnv’s <strong>OpenSpiel integration</strong> 🎯",Ln,$t,yU="This is a REAL environment running in production at companies!",Pn,xt,pU="<strong>Get ready for:</strong>",Kn,zt,wU="<li>🔌 Using existing environments (not building)</li> <li>🤖 Testing policies against real games</li> <li>📊 Live gameplay visualization</li> <li>🎯 Production-ready patterns</li>",LJ,ns,PJ,Ms,KJ,Us,jU="<strong>Rules:</strong>",le,as,IU="<li>10×5 grid</li> <li>Ball falls from random column</li> <li>Move paddle left/right to catch it</li>",se,is,oU="<strong>Actions:</strong>",te,ys,rU="<li><code>0</code> = Move LEFT ⬅️</li> <li><code>1</code> = STAY 🛑</li> <li><code>2</code> = Move RIGHT ➡️</li>",Te,ps,CU="<strong>Reward:</strong>",Je,ws,cU="<li><code>+1</code> if caught 🎉</li> <li><code>0</code> if missed 😢</li>",ee,js,EU="!!! note “Why Catch?”",ne,Is,uU=`<li><p>Simple rules (easy to understand)</p></li> <li><p>Fast episodes (~5 steps)</p></li> <li><p>Clear success/failure</p></li> <li><p>Part of OpenSpiel’s 70+ games!</p> <p><strong>💡 The Big Idea:</strong>
Instead of building this from scratch, we’ll USE OpenEnv’s existing OpenSpiel integration. Same interface, but production-ready!</p></li>`,Me,os,Ue,rs,NU="<strong>Output:</strong>",ae,Cs,ie,ye,pe,cs,hU="(part-7-four-policies)=",we,Es,je,us,mU="Let’s test 4 different AI strategies:",Ie,Ns,dU="<thead><tr><th>Policy</th> <th>Strategy</th> <th>Expected Performance</th></tr></thead> <tbody><tr><td><strong>🎲 Random</strong></td> <td>Pick random action every step</td> <td>~20% (pure luck)</td></tr> <tr><td><strong>🛑 Always Stay</strong></td> <td>Never move, hope ball lands in center</td> <td>~20% (terrible!)</td></tr> <tr><td><strong>🧠 Smart</strong></td> <td>Move paddle toward ball</td> <td>100% (optimal!)</td></tr> <tr><td><strong>📈 Learning</strong></td> <td>Start random, learn smart strategy</td> <td>~85% (improves over time)</td></tr></tbody>",oe,hs,gU="<strong>💡 These policies work with ANY OpenSpiel game!</strong>",re,ms,Ce,ds,AU="<strong>Output:</strong>",ce,gs,Ee,ue,Ne,As,bU="(part-8-policy-competition)=",he,bs,me,Bs,BU="Let’s run <strong>50 episodes</strong> for each policy against <strong>REAL OpenSpiel</strong> and see who wins!",de,Qs,QU="This is production code - every action is an HTTP call to the OpenSpiel server!",ge,ks,Ae,be,Be,Rs,kU="(part-9-switching-to-other-games)=",Qe,Vs,ke,Ss,Re,fs,RU="In Parts 6-8, we <strong>USED</strong> the existing OpenSpiel Catch environment:",Ve,vs,VU="<thead><tr><th>What We Did</th> <th>How It Works</th></tr></thead> <tbody><tr><td><strong>Imported</strong></td> <td>OpenSpielEnv client (pre-built)</td></tr> <tr><td><strong>Started</strong></td> <td>OpenSpiel server via uvicorn</td></tr> <tr><td><strong>Connected</strong></td> <td>HTTP client to server</td></tr> <tr><td><strong>Played</strong></td> <td>Real OpenSpiel Catch game</td></tr></tbody>",Se,Gs,SU="<strong>🎯 This is production code!</strong> Every action was an HTTP call to a real OpenSpiel environment.",fe,Os,ve,Zs,fU="The beauty of OpenEnv? <strong>Same code, different games!</strong>",Ge,Fs,Oe,Ws,vU="<strong>🎮 All 6 Games:</strong>",Ze,Ys,GU="<li>✅ <strong><code>catch</code></strong> - What we just used!</li> <li><strong><code>tic_tac_toe</code></strong> - Classic 3×3</li> <li><strong><code>kuhn_poker</code></strong> - Imperfect information poker</li> <li><strong><code>cliff_walking</code></strong> - Grid navigation</li> <li><strong><code>2048</code></strong> - Tile puzzle</li> <li><strong><code>blackjack</code></strong> - Card game</li>",Fe,$s,OU="<strong>All use the exact same OpenSpielEnv client!</strong>",We,xs,Ye,zs,$e,Hs,ZU="<strong>💡 Key Insight</strong>: You don’t rebuild anything - you just USE different games with the same client!",xe,ze,He,_s,FU="(part-10-create-your-own-integration)=",_e,Xs,Xe,Ds,De,qs,WU="Want to wrap your own environment in OpenEnv? Here’s how:",qe,Ls,Le,Ps,Pe,Ks,Ke,lt,ln,st,sn,tt,tn,Tt,Tn,Jt,Jn,et,en,nt,nn,Mt,Mn,Ut,YU="OpenEnv includes 3 complete examples:",Un,at,$U="<li><p><strong><code>src/envs/echo_env/</code></strong></p> <ul><li>Simplest possible environment</li> <li>Great for testing and learning</li></ul></li> <li><p><strong><code>src/envs/openspiel_env/</code></strong></p> <ul><li>Wraps external library (OpenSpiel)</li> <li>Shows integration pattern</li> <li>6 games in one integration</li></ul></li> <li><p><strong><code>src/envs/coding_env/</code></strong></p> <ul><li>Python code execution environment</li> <li>Shows complex use case</li> <li>Security considerations</li></ul></li>",an,it,xU="<strong>💡 Study these to understand the patterns!</strong>",yn,pn,wn,yt,zU="(summary-your-journey)=",jn,pt,In,wt,on,Ht,jt,c,It,lM,_t,HU="✅ <strong>RL Fundamentals</strong>",sM,Xt,_U="<li>The observe-act-reward loop</li> <li>What makes good policies</li> <li>Exploration vs exploitation</li>",tM,Dt,XU="✅ <strong>OpenEnv Architecture</strong>",TM,qt,DU="<li>Client-server separation</li> <li>Type-safe contracts</li> <li>HTTP communication layer</li>",JM,Lt,qU="✅ <strong>Production Patterns</strong>",eM,Pt,LU="<li>Docker isolation</li> <li>API design</li> <li>Reproducible deployments</li>",nM,E,ot,MM,Kt,PU="✅ <strong>Using Environments</strong>",UM,lT,KU="<li>Import OpenEnv clients</li> <li>Call reset/step/state</li> <li>Work with typed observations</li>",aM,sT,la="✅ <strong>Building Environments</strong>",iM,tT,sa="<li>Define type-safe models</li> <li>Implement Environment class</li> <li>Create HTTPEnvClient</li>",yM,TT,ta="✅ <strong>Testing &amp; Debugging</strong>",pM,JT,Ta="<li>Compare policies</li> <li>Visualize episodes</li> <li>Measure performance</li>",rn,rt,Cn,Ct,Ja="<thead><tr><th>Feature</th> <th>Traditional (Gym)</th> <th>OpenEnv</th> <th>Winner</th></tr></thead> <tbody><tr><td><strong>Type Safety</strong></td> <td>❌ Arrays, dicts</td> <td>✅ Dataclasses</td> <td>🏆 OpenEnv</td></tr> <tr><td><strong>Isolation</strong></td> <td>❌ Same process</td> <td>✅ Docker</td> <td>🏆 OpenEnv</td></tr> <tr><td><strong>Deployment</strong></td> <td>❌ Manual setup</td> <td>✅ K8s-ready</td> <td>🏆 OpenEnv</td></tr> <tr><td><strong>Language</strong></td> <td>❌ Python only</td> <td>✅ Any (HTTP)</td> <td>🏆 OpenEnv</td></tr> <tr><td><strong>Reproducibility</strong></td> <td>❌ “Works on my machine”</td> <td>✅ Same everywhere</td> <td>🏆 OpenEnv</td></tr> <tr><td><strong>Community</strong></td> <td>✅ Large ecosystem</td> <td>🟡 Growing</td> <td>🤝 Both!</td></tr></tbody>",cn,ct,ea=`!!! success “The Bottom Line”
OpenEnv brings <strong>production engineering</strong> to RL:`,En,Et,na="<li><p>Same environments work locally and in production</p></li> <li><p>Type safety catches bugs early</p></li> <li><p>Docker isolation prevents conflicts</p></li> <li><p>HTTP API works with any language</p> <p><strong>It’s RL for 2024 and beyond.</strong></p></li>",un,Nn,hn,ut,Ma="(resources)=",mn,Nt,dn,ht,gn,mt,Ua='<li><strong>🏠 OpenEnv GitHub</strong>: <a href="https://github.com/huggingface/OpenEnv" rel="nofollow">https://github.com/huggingface/OpenEnv</a></li> <li><strong>🎮 OpenSpiel</strong>: <a href="https://github.com/google-deepmind/open_spiel" rel="nofollow">https://github.com/google-deepmind/open_spiel</a></li> <li><strong>⚡ FastAPI Docs</strong>: <a href="https://fastapi.tiangolo.com/" rel="nofollow">https://fastapi.tiangolo.com/</a></li> <li><strong>🐳 Docker Guide</strong>: <a href="https://docs.docker.com/get-started/" rel="nofollow">https://docs.docker.com/get-started/</a></li> <li><strong>🔥 PyTorch</strong>: <a href="https://pytorch.org/" rel="nofollow">https://pytorch.org/</a></li>',An,dt,bn,gt,aa='<li><strong>Environment Creation Guide</strong>: <code>src/envs/README.md</code></li> <li><strong>OpenSpiel Integration</strong>: <code>src/envs/openspiel_env/README.md</code></li> <li><strong>Example Scripts</strong>: <code>examples/</code></li> <li><strong>RFC 001</strong>: <a href="https://github.com/huggingface/OpenEnv/pull/26" rel="nofollow">Baseline API Specs</a></li>',Bn,At,Qn,bt,ia="<strong>Openly governed by a technical committee including:</strong>",kn,Bt,ya="<li>🤗 Hugging Face</li> <li>⚡ Unsloth</li> <li>🌟 Reflection</li> <li>🔥 Meta PyTorch</li>",Rn,Qt,pa="<strong>Supported by amazing organizations and contributors.</strong>",Vn,kt,wa="<li>🚀 And many more!</li>",Sn,Rt,ja="Technical direction, RFCs, and release planning are coordinated in public through the OpenEnv repository.",fn,Vt,Ia="<strong>License</strong>: BSD 3-Clause (very permissive!)",vn,St,oa="<strong>Contributions</strong>: Always welcome! Check out the issues tab.",Gn,On,Zn,ft,Fn,vt,ra="<li>⭐ <strong>Star the repo</strong> to show support and stay updated</li> <li>🔄 <strong>Try modifying</strong> the Catch game (make it harder? bigger grid?)</li> <li>🎮 <strong>Explore</strong> other OpenSpiel games</li> <li>🛠️ <strong>Build</strong> your own environment integration</li> <li>💬 <strong>Share</strong> what you build with the community!</li>",Wn,Gt,Yn,nT,$n;return Q=new ga({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),k=new I({props:{title:"OpenEnv: Production RL Made Simple",local:"openenv-production-rl-made-simple",headingTag:"h1"}}),V=new I({props:{title:"From “Hello World” to RL Training in 5 Minutes ✨",local:"from-hello-world-to-rl-training-in-5-minutes-",headingTag:"h2"}}),S=new I({props:{title:"Why OpenEnv?",local:"why-openenv",headingTag:"h2"}}),x=new I({props:{title:"📋 What You’ll Learn",local:"-what-youll-learn",headingTag:"h2"}}),X=new I({props:{title:"📑 Table of Contents",local:"-table-of-contents",headingTag:"h2"}}),D=new I({props:{title:"Foundation",local:"foundation",headingTag:"h3"}}),L=new I({props:{title:"Architecture",local:"architecture",headingTag:"h3"}}),K=new I({props:{title:"Hands-On Demo",local:"hands-on-demo",headingTag:"h3"}}),sl=new I({props:{title:"Advanced",local:"advanced",headingTag:"h3"}}),Tl=new I({props:{title:"Wrap Up",local:"wrap-up",headingTag:"h3"}}),nl=new I({props:{title:"Part 1: RL in 60 Seconds ⏱️",local:"part-1-rl-in-60-seconds-",headingTag:"h2"}}),al=new r({props:{code:"d2hpbGUlMjBub3QlMjBkb25lJTNBJTBBJTIwJTIwJTIwJTIwb2JzZXJ2YXRpb24lMjAlM0QlMjBlbnZpcm9ubWVudC5vYnNlcnZlKCklMEElMjAlMjAlMjAlMjBhY3Rpb24lMjAlM0QlMjBwb2xpY3kuY2hvb3NlKG9ic2VydmF0aW9uKSUwQSUyMCUyMCUyMCUyMHJld2FyZCUyMCUzRCUyMGVudmlyb25tZW50LnN0ZXAoYWN0aW9uKSUwQSUyMCUyMCUyMCUyMHBvbGljeS5sZWFybihyZXdhcmQp",highlighted:`<span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> done:
observation = environment.observe()
action = policy.choose(observation)
reward = environment.step(action)
policy.learn(reward)`,lang:"python",wrap:!1}}),pl=new r({props:{code:"aW1wb3J0JTIwcmFuZG9tJTBBJTBBcHJpbnQoJTIyJUYwJTlGJThFJUIyJTIwJTIyJTIwJTJCJTIwJTIyJTNEJTIyKjU4JTIwJTJCJTIwJTIyJTIwJUYwJTlGJThFJUIyJTIyKSUwQXByaW50KCUyMiUyMCUyMCUyME51bWJlciUyMEd1ZXNzaW5nJTIwR2FtZSUyMC0lMjBUaGUlMjBTaW1wbGVzdCUyMFJMJTIwRXhhbXBsZSUyMiklMEFwcmludCglMjIlRjAlOUYlOEUlQjIlMjAlMjIlMjAlMkIlMjAlMjIlM0QlMjIqNTglMjAlMkIlMjAlMjIlMjAlRjAlOUYlOEUlQjIlMjIpJTBBJTBBJTIzJTIwRW52aXJvbm1lbnQlMjBzZXR1cCUwQXRhcmdldCUyMCUzRCUyMHJhbmRvbS5yYW5kaW50KDElMkMlMjAxMCklMEFndWVzc2VzX2xlZnQlMjAlM0QlMjAzJTBBJTBBcHJpbnQoZiUyMiU1Q24lRjAlOUYlOEUlQUYlMjBJJ20lMjB0aGlua2luZyUyMG9mJTIwYSUyMG51bWJlciUyMGJldHdlZW4lMjAxJTIwYW5kJTIwMTAuLi4lMjIpJTBBcHJpbnQoZiUyMiVGMCU5RiU5MiVBRCUyMFlvdSUyMGhhdmUlMjAlN0JndWVzc2VzX2xlZnQlN0QlMjBndWVzc2VzLiUyMExldCdzJTIwc2VlJTIwaG93JTIwcmFuZG9tJTIwZ3Vlc3NpbmclMjB3b3JrcyElNUNuJTIyKSUwQSUwQSUyMyUyMFRoZSUyMFJMJTIwTG9vcCUyMC0lMjBQdXJlJTIwcmFuZG9tJTIwcG9saWN5JTIwKG5vJTIwbGVhcm5pbmchKSUwQXdoaWxlJTIwZ3Vlc3Nlc19sZWZ0JTIwJTNFJTIwMCUzQSUwQSUyMCUyMCUyMCUyMCUyMyUyMFBvbGljeSUzQSUyMFJhbmRvbSUyMGd1ZXNzaW5nJTIwKG5vJTIwbGVhcm5pbmclMjB5ZXQhKSUwQSUyMCUyMCUyMCUyMGd1ZXNzJTIwJTNEJTIwcmFuZG9tLnJhbmRpbnQoMSUyQyUyMDEwKSUwQSUyMCUyMCUyMCUyMGd1ZXNzZXNfbGVmdCUyMC0lM0QlMjAxJTBBJTBBJTIwJTIwJTIwJTIwcHJpbnQoZiUyMiVGMCU5RiU5MiVBRCUyMEd1ZXNzJTIwJTIzJTdCMy1ndWVzc2VzX2xlZnQlN0QlM0ElMjAlN0JndWVzcyU3RCUyMiUyQyUyMGVuZCUzRCUyMiUyMCVFMiU4NiU5MiUyMCUyMiklMEElMEElMjAlMjAlMjAlMjAlMjMlMjBSZXdhcmQlMjBzaWduYWwlMjAoYnV0JTIwd2UncmUlMjBub3QlMjB1c2luZyUyMGl0ISklMEElMjAlMjAlMjAlMjBpZiUyMGd1ZXNzJTIwJTNEJTNEJTIwdGFyZ2V0JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcHJpbnQoJTIyJUYwJTlGJThFJTg5JTIwQ29ycmVjdCElMjAlMkIxMCUyMHBvaW50cyUyMiklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBicmVhayUwQSUyMCUyMCUyMCUyMGVsaWYlMjBhYnMoZ3Vlc3MlMjAtJTIwdGFyZ2V0KSUyMCUzQyUzRCUyMDIlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwcmludCglMjIlRjAlOUYlOTQlQTUlMjBXYXJtISUyMChjbG9zZSklMjIpJTBBJTIwJTIwJTIwJTIwZWxzZSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHByaW50KCUyMiVFMiU5RCU4NCVFRiVCOCU4RiUyMCUyMENvbGQhJTIwKGZhciklMjIpJTBBZWxzZSUzQSUwQSUyMCUyMCUyMCUyMHByaW50KGYlMjIlNUNuJUYwJTlGJTkyJTk0JTIwT3V0JTIwb2YlMjBndWVzc2VzLiUyMFRoZSUyMG51bWJlciUyMHdhcyUyMCU3QnRhcmdldCU3RC4lMjIpJTBBJTBBcHJpbnQoJTIyJTVDbiUyMiUyMCUyQiUyMCUyMiUzRCUyMio2MiklMEFwcmludCglMjIlRjAlOUYlOTIlQTElMjBUaGlzJTIwaXMlMjBSTCUzQSUyME9ic2VydmUlMjAlRTIlODYlOTIlMjBBY3QlMjAlRTIlODYlOTIlMjBSZXdhcmQlMjAlRTIlODYlOTIlMjBSZXBlYXQlMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwQnV0JTIwdGhpcyUyMHBvbGljeSUyMGlzJTIwdGVycmlibGUhJTIwSXQlMjBkb2Vzbid0JTIwbGVhcm4lMjBmcm9tJTIwcmV3YXJkcy4lMjIpJTBBcHJpbnQoJTIyJTNEJTIyKjYyJTIwJTJCJTIwJTIyJTVDbiUyMik=",highlighted:`<span class="hljs-keyword">import</span> random
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🎲 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">58</span> + <span class="hljs-string">&quot; 🎲&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; Number Guessing Game - The Simplest RL Example&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🎲 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">58</span> + <span class="hljs-string">&quot; 🎲&quot;</span>)
<span class="hljs-comment"># Environment setup</span>
target = random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)
guesses_left = <span class="hljs-number">3</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;\\n🎯 I&#x27;m thinking of a number between 1 and 10...&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;💭 You have <span class="hljs-subst">{guesses_left}</span> guesses. Let&#x27;s see how random guessing works!\\n&quot;</span>)
<span class="hljs-comment"># The RL Loop - Pure random policy (no learning!)</span>
<span class="hljs-keyword">while</span> guesses_left &gt; <span class="hljs-number">0</span>:
<span class="hljs-comment"># Policy: Random guessing (no learning yet!)</span>
guess = random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)
guesses_left -= <span class="hljs-number">1</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;💭 Guess #<span class="hljs-subst">{<span class="hljs-number">3</span>-guesses_left}</span>: <span class="hljs-subst">{guess}</span>&quot;</span>, end=<span class="hljs-string">&quot; → &quot;</span>)
<span class="hljs-comment"># Reward signal (but we&#x27;re not using it!)</span>
<span class="hljs-keyword">if</span> guess == target:
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🎉 Correct! +10 points&quot;</span>)
<span class="hljs-keyword">break</span>
<span class="hljs-keyword">elif</span> <span class="hljs-built_in">abs</span>(guess - target) &lt;= <span class="hljs-number">2</span>:
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🔥 Warm! (close)&quot;</span>)
<span class="hljs-keyword">else</span>:
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;❄️ Cold! (far)&quot;</span>)
<span class="hljs-keyword">else</span>:
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;\\n💔 Out of guesses. The number was <span class="hljs-subst">{target}</span>.&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n&quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">62</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;💡 This is RL: Observe → Act → Reward → Repeat&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; But this policy is terrible! It doesn&#x27;t learn from rewards.&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">62</span> + <span class="hljs-string">&quot;\\n&quot;</span>)`,lang:"python",wrap:!1}}),jl=new r({props:{code:"JUYwJTlGJThFJUIyJTIwJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTIwJUYwJTlGJThFJUIyJTBBJTIwJTIwJTIwTnVtYmVyJTIwR3Vlc3NpbmclMjBHYW1lJTIwLSUyMFRoZSUyMFNpbXBsZXN0JTIwUkwlMjBFeGFtcGxlJTBBJUYwJTlGJThFJUIyJTIwJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTIwJUYwJTlGJThFJUIyJTBBJTBBJUYwJTlGJThFJUFGJTIwSSdtJTIwdGhpbmtpbmclMjBvZiUyMGElMjBudW1iZXIlMjBiZXR3ZWVuJTIwMSUyMGFuZCUyMDEwLi4uJTBBJUYwJTlGJTkyJUFEJTIwWW91JTIwaGF2ZSUyMDMlMjBndWVzc2VzLiUyMExldCdzJTIwc2VlJTIwaG93JTIwcmFuZG9tJTIwZ3Vlc3NpbmclMjB3b3JrcyElMEElMEElRjAlOUYlOTIlQUQlMjBHdWVzcyUyMCUyMzElM0ElMjAyJTIwJUUyJTg2JTkyJTIwJUUyJTlEJTg0JUVGJUI4JThGJTIwJTIwQ29sZCElMjAoZmFyKSUwQSVGMCU5RiU5MiVBRCUyMEd1ZXNzJTIwJTIzMiUzQSUyMDEwJTIwJUUyJTg2JTkyJTIwJUYwJTlGJThFJTg5JTIwQ29ycmVjdCElMjAlMkIxMCUyMHBvaW50cyUwQSUwQSUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUwQSVGMCU5RiU5MiVBMSUyMFRoaXMlMjBpcyUyMFJMJTNBJTIwT2JzZXJ2ZSUyMCVFMiU4NiU5MiUyMEFjdCUyMCVFMiU4NiU5MiUyMFJld2FyZCUyMCVFMiU4NiU5MiUyMFJlcGVhdCUwQSUyMCUyMCUyMEJ1dCUyMHRoaXMlMjBwb2xpY3klMjBpcyUyMHRlcnJpYmxlISUyMEl0JTIwZG9lc24ndCUyMGxlYXJuJTIwZnJvbSUyMHJld2FyZHMuJTBBJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNE",highlighted:`🎲 ========================================================== 🎲
<span class="hljs-code"> Number Guessing Game - The Simplest RL Example</span>
🎲 ========================================================== 🎲
🎯 I&#x27;m thinking of a number between 1 and 10...
💭 You have 3 guesses. Let&#x27;s see how random guessing works!
💭 Guess #1: 2 → ❄️ Cold! (far)
💭 Guess #2: 10 → 🎉 Correct! +10 points
==============================================================
💡 This is RL: Observe → Act → Reward → Repeat
But this policy is terrible! It doesn&#x27;t learn from rewards.
==============================================================`,lang:"",wrap:!1}}),ol=new I({props:{title:"Part 2: The Problem with Traditional RL 😤",local:"part-2-the-problem-with-traditional-rl-",headingTag:"h2"}}),rl=new I({props:{title:"🤔 Why Can’t We Just Use OpenAI Gym?",local:"-why-cant-we-just-use-openai-gym",headingTag:"h3"}}),El=new I({props:{title:"💡 The OpenEnv Philosophy",local:"-the-openenv-philosophy",headingTag:"h3"}}),ml=new I({props:{title:"The Architecture",local:"the-architecture",headingTag:"h3"}}),dl=new r({props:{code:"JUUyJTk0JThDJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTkwJTBBJUUyJTk0JTgyJTIwJTIwWU9VUiUyMFRSQUlOSU5HJTIwQ09ERSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCVFMiU5NCU4MiUwQSVFMiU5NCU4MiUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCVFMiU5NCU4MiUwQSVFMiU5NCU4MiUyMCUyMGVudiUyMCUzRCUyME9wZW5TcGllbEVudiguLi4pJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTg2JTkwJTIwSW1wb3J0JTIwdGhlJTIwY2xpZW50JTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwcmVzdWx0JTIwJTNEJTIwZW52LnJlc2V0KCklMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlODYlOTAlMjBUeXBlLXNhZmUhJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwcmVzdWx0JTIwJTNEJTIwZW52LnN0ZXAoYWN0aW9uKSUyMCUyMCUyMCUyMCUyMCUyMCVFMiU4NiU5MCUyMFR5cGUtc2FmZSElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlOTQlODIlMEElRTIlOTQlODIlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlOTQlODIlMEElRTIlOTQlOTQlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlQUMlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlOTglMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlOTQlODIlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlOTQlODIlMjAlMjBIVFRQJTJGSlNPTiUyMChMYW5ndWFnZS1BZ25vc3RpYyklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlOTQlODIlMjAlMjBQT1NUJTIwJTJGcmVzZXQlMkMlMjBQT1NUJTIwJTJGc3RlcCUyQyUyMEdFVCUyMCUyRnN0YXRlJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JThDJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk2JUJDJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTkwJTBBJUUyJTk0JTgyJTIwJTIwRE9DS0VSJTIwQ09OVEFJTkVSJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwJUUyJTk0JThDJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTkwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwJUUyJTk0JTgyJTIwJTIwRmFzdEFQSSUyMFNlcnZlciUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCVFMiU5NCU4MiUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCVFMiU5NCU4MiUwQSVFMiU5NCU4MiUyMCUyMCVFMiU5NCU4MiUyMCUyMCVFMiU5NCU5NCVFMiU5NCU4MCUyMEVudmlyb25tZW50JTIwKHJlc2V0JTJDJTIwc3RlcCUyQyUyMHN0YXRlKSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCVFMiU5NCU4MiUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCVFMiU5NCU4MiUwQSVFMiU5NCU4MiUyMCUyMCVFMiU5NCU4MiUyMCUyMCUyMCUyMCUyMCVFMiU5NCU5NCVFMiU5NCU4MCUyMFlvdXIlMjBHYW1lJTJGU2ltdWxhdGlvbiUyMExvZ2ljJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwJUUyJTk0JTk0JUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTk4JTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTk0JTgyJTBBJUUyJTk0JTgyJTIwJTIwSXNvbGF0ZWQlMjAlRTIlODAlQTIlMjBSZXByb2R1Y2libGUlMjAlRTIlODAlQTIlMjBTZWN1cmUlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlOTQlODIlMEElRTIlOTQlOTQlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlOTg=",highlighted:`┌────────────────────────────────────────────────────────────┐
│ YOUR TRAINING CODE │
│ │
│ env = OpenSpielEnv(...) ← Import the client │
│ result = env.reset() ← Type-safe! │
│ result = env.step(action) ← Type-safe! │
│ │
└─────────────────┬──────────────────────────────────────────┘
│ HTTP/JSON (Language-Agnostic)
│ POST /reset, POST /step, GET /<span class="hljs-keyword">state</span>
┌─────────────────▼──────────────────────────────────────────┐
│ DOCKER CONTAINER │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ FastAPI Server │ │
│ │ └─ Environment (reset, step, <span class="hljs-keyword">state</span>) │ │
│ │ └─ Your Game/Simulation Logic │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ Isolated • Reproducible • Secure │
└────────────────────────────────────────────────────────────┘`,lang:"",wrap:!1}}),Al=new r({props:{code:"ZW52LnJlc2V0KCklMjAlMjAlMjAlMjAlMjMlMjBVbmRlciUyMHRoZSUyMGhvb2QlM0ElMjBIVFRQJTIwUE9TVCUyMHRvJTIwJTJGcmVzZXQlMEFlbnYuc3RlcCguLi4pJTIwJTIwJTIzJTIwVW5kZXIlMjB0aGUlMjBob29kJTNBJTIwSFRUUCUyMFBPU1QlMjB0byUyMCUyRnN0ZXAlMEFlbnYuc3RhdGUoKSUyMCUyMCUyMCUyMCUyMyUyMFVuZGVyJTIwdGhlJTIwaG9vZCUzQSUyMEhUVFAlMjBHRVQlMjB0byUyMCUyRnN0YXRlJTBBJTYwJTYwJTYwJTBBJTBBVGhlJTIwbWFnaWMlM0YlMjBPcGVuRW52JTIwaGFuZGxlcyUyMGFsbCUyMHRoZSUyMHBsdW1iaW5nLiUyMFlvdSUyMGZvY3VzJTIwb24lMjBSTCElMjAlRTIlOUMlQTglMEElMEEtLS0lMEElMEEocGFydC0zLXNldHVwKSUzRCUwQSUyMyUyMyUyMFBhcnQlMjAzJTNBJTIwU2V0dXAlMjAlRjAlOUYlOUIlQTAlRUYlQjglOEYlMEElMEEqKlJ1bm5pbmclMjBpbiUyMENvbGFiJTNGKiolMjBUaGlzJTIwY2VsbCUyMHdpbGwlMjBjbG9uZSUyME9wZW5FbnYlMjBhbmQlMjBpbnN0YWxsJTIwZGVwZW5kZW5jaWVzJTIwYXV0b21hdGljYWxseS4lMEElMEEqKlJ1bm5pbmclMjBsb2NhbGx5JTNGKiolMjBNYWtlJTIwc3VyZSUyMHlvdSdyZSUyMGluJTIwdGhlJTIwT3BlbkVudiUyMGRpcmVjdG9yeS4lMEElMEElNjAlNjAlNjBpcHl0aG9uMyUwQSUyMyUyMERldGVjdCUyMGVudmlyb25tZW50JTBBdHJ5JTNBJTBBaW1wb3J0JTIwZ29vZ2xlLmNvbGFiJTBBSU5fQ09MQUIlMjAlM0QlMjBUcnVlJTBBcHJpbnQoJTIyJUYwJTlGJThDJTkwJTIwUnVubmluZyUyMGluJTIwR29vZ2xlJTIwQ29sYWIlMjAtJTIwUGVyZmVjdCElMjIpJTBBZXhjZXB0JTIwSW1wb3J0RXJyb3IlM0ElMEFJTl9DT0xBQiUyMCUzRCUyMEZhbHNlJTBBcHJpbnQoJTIyJUYwJTlGJTkyJUJCJTIwUnVubmluZyUyMGxvY2FsbHklMjAtJTIwTmljZSElMjIpJTBBJTBBaWYlMjBJTl9DT0xBQiUzQSUwQXByaW50KCUyMiU1Q24lRjAlOUYlOTMlQTYlMjBDbG9uaW5nJTIwT3BlbkVudiUyMHJlcG9zaXRvcnkuLi4lMjIpJTBBIWdpdCUyMGNsb25lJTIwaHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGaHVnZ2luZ2ZhY2UlMkZPcGVuRW52LmdpdCUyMCUzRSUyMCUyRmRldiUyRm51bGwlMjAyJTNFJTI2MSUwQSUyNWNkJTIwT3BlbkVudiUwQSUwQXByaW50KCUyMiVGMCU5RiU5MyU5QSUyMEluc3RhbGxpbmclMjBkZXBlbmRlbmNpZXMlMjAodGhpcyUyMHRha2VzJTIwfjEwJTIwc2Vjb25kcykuLi4lMjIpJTBBIXBpcCUyMGluc3RhbGwlMjAtcSUyMGZhc3RhcGklMjB1dmljb3JuJTIwcmVxdWVzdHMlMEElMEFpbXBvcnQlMjBzeXMlMEFzeXMucGF0aC5pbnNlcnQoMCUyQyUyMCcuJTJGc3JjJyklMEFwcmludCglMjIlNUNuJUUyJTlDJTg1JTIwU2V0dXAlMjBjb21wbGV0ZSElMjBFdmVyeXRoaW5nJTIwaXMlMjByZWFkeSUyMHRvJTIwZ28hJTIwJUYwJTlGJThFJTg5JTIyKSUwQWVsc2UlM0ElMEFpbXBvcnQlMjBzeXMlMEFmcm9tJTIwcGF0aGxpYiUyMGltcG9ydCUyMFBhdGglMEFzeXMucGF0aC5pbnNlcnQoMCUyQyUyMHN0cihQYXRoLmN3ZCgpLnBhcmVudCUyMCUyRiUyMCdzcmMnKSklMEFwcmludCglMjIlRTIlOUMlODUlMjBVc2luZyUyMGxvY2FsJTIwT3BlbkVudiUyMGluc3RhbGxhdGlvbiUyMiklMEElMEFwcmludCglMjIlNUNuJUYwJTlGJTlBJTgwJTIwUmVhZHklMjB0byUyMGV4cGxvcmUlMjBPcGVuRW52JTIwYW5kJTIwYnVpbGQlMjBhbWF6aW5nJTIwdGhpbmdzISUyMiklMEFwcmludCglMjIlRjAlOUYlOTIlQTElMjBUaXAlM0ElMjBSdW4lMjBjZWxscyUyMHRvcC10by1ib3R0b20lMjBmb3IlMjB0aGUlMjBiZXN0JTIwZXhwZXJpZW5jZS4lNUNuJTIyKQ==",highlighted:`env.reset() <span class="hljs-comment"># Under the hood: HTTP POST to /reset</span>
env.step(...) <span class="hljs-comment"># Under the hood: HTTP POST to /step</span>
env.state() <span class="hljs-comment"># Under the hood: HTTP GET to /state</span>
\`\`\`
The magic? OpenEnv handles <span class="hljs-built_in">all</span> the plumbing. You focus on RL! ✨
---
(part-<span class="hljs-number">3</span>-setup)=
<span class="hljs-comment">## Part 3: Setup 🛠️</span>
**Running <span class="hljs-keyword">in</span> Colab?** This cell will clone OpenEnv <span class="hljs-keyword">and</span> install dependencies automatically.
**Running locally?** Make sure yo<span class="hljs-string">u&#x27;re in the OpenEnv directory.
\`\`\`ipython3
# Detect environment
try:
import google.colab
IN_COLAB = True
print(&quot;🌐 Running in Google Colab - Perfect!&quot;)
except ImportError:
IN_COLAB = False
print(&quot;💻 Running locally - Nice!&quot;)
if IN_COLAB:
print(&quot;\\n📦 Cloning OpenEnv repository...&quot;)
!git clone https://github.com/huggingface/OpenEnv.git &gt; /dev/null 2&gt;&amp;1
%cd OpenEnv
print(&quot;📚 Installing dependencies (this takes ~10 seconds)...&quot;)
!pip install -q fastapi uvicorn requests
import sys
sys.path.insert(0, &#x27;</span>./src<span class="hljs-string">&#x27;)
print(&quot;\\n✅ Setup complete! Everything is ready to go! 🎉&quot;)
else:
import sys
from pathlib import Path
sys.path.insert(0, str(Path.cwd().parent / &#x27;</span>src<span class="hljs-string">&#x27;))
print(&quot;✅ Using local OpenEnv installation&quot;)
print(&quot;\\n🚀 Ready to explore OpenEnv and build amazing things!&quot;)
print(&quot;💡 Tip: Run cells top-to-bottom for the best experience.\\n&quot;)</span>`,lang:"python",wrap:!1}}),Bl=new r({props:{code:"JUYwJTlGJTkyJUJCJTIwUnVubmluZyUyMGxvY2FsbHklMjAtJTIwTmljZSElMEElRTIlOUMlODUlMjBVc2luZyUyMGxvY2FsJTIwT3BlbkVudiUyMGluc3RhbGxhdGlvbiUwQSUwQSVGMCU5RiU5QSU4MCUyMFJlYWR5JTIwdG8lMjBleHBsb3JlJTIwT3BlbkVudiUyMGFuZCUyMGJ1aWxkJTIwYW1hemluZyUyMHRoaW5ncyElMEElRjAlOUYlOTIlQTElMjBUaXAlM0ElMjBSdW4lMjBjZWxscyUyMHRvcC10by1ib3R0b20lMjBmb3IlMjB0aGUlMjBiZXN0JTIwZXhwZXJpZW5jZS4=",highlighted:`💻 Running locally - Nice!
✅ Using local OpenEnv <span class="hljs-keyword">installation
</span>
🚀 Ready to explore OpenEnv <span class="hljs-keyword">and </span><span class="hljs-keyword">build </span>amazing things!
💡 Tip: Run cells top-to-<span class="hljs-keyword">bottom </span>for the <span class="hljs-keyword">best </span>experience.`,lang:"",wrap:!1}}),kl=new I({props:{title:"Part 4: The OpenEnv Pattern 🏗️",local:"part-4-the-openenv-pattern-",headingTag:"h2"}}),Rl=new I({props:{title:"Every OpenEnv Environment Has 3 Components:",local:"every-openenv-environment-has-3-components",headingTag:"h3"}}),Vl=new r({props:{code:"c3JjJTJGZW52cyUyRnlvdXJfZW52JTJGJTBBJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwJUYwJTlGJTkzJTlEJTIwbW9kZWxzLnB5JTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTg2JTkwJTIwVHlwZS1zYWZlJTIwY29udHJhY3RzJTBBJUUyJTk0JTgyJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwKEFjdGlvbiUyQyUyME9ic2VydmF0aW9uJTJDJTIwU3RhdGUpJTBBJUUyJTk0JTgyJTBBJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwJUYwJTlGJTkzJUIxJTIwY2xpZW50LnB5JTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTg2JTkwJTIwV2hhdCUyMFlPVSUyMGltcG9ydCUwQSVFMiU5NCU4MiUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMChIVFRQRW52Q2xpZW50JTIwaW1wbGVtZW50YXRpb24pJTBBJUUyJTk0JTgyJTBBJUUyJTk0JTk0JUUyJTk0JTgwJUUyJTk0JTgwJTIwJUYwJTlGJTk2JUE1JUVGJUI4JThGJTIwJTIwc2VydmVyJTJGJTBBJTIwJTIwJTIwJTIwJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwZW52aXJvbm1lbnQucHklMjAlMjAlMjAlMjAlRTIlODYlOTAlMjBHYW1lJTJGc2ltdWxhdGlvbiUyMGxvZ2ljJTBBJTIwJTIwJTIwJTIwJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwYXBwLnB5JTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJUUyJTg2JTkwJTIwRmFzdEFQSSUyMHNlcnZlciUwQSUyMCUyMCUyMCUyMCVFMiU5NCU5NCVFMiU5NCU4MCVFMiU5NCU4MCUyMERvY2tlcmZpbGUlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlRTIlODYlOTAlMjBDb250YWluZXIlMjBkZWZpbml0aW9u",highlighted:`<span class="hljs-attribute">src</span>/envs/your_env/
├── 📝 models<span class="hljs-selector-class">.py</span> ← Type-safe contracts
│ (Action, Observation, State)
├── 📱 client<span class="hljs-selector-class">.py</span> ← What YOU import
│ (HTTPEnvClient implementation)
└── 🖥️ server/
├── environment<span class="hljs-selector-class">.py</span> ← Game/simulation logic
├── app<span class="hljs-selector-class">.py</span> ← FastAPI server
└── Dockerfile ← Container definition`,lang:"",wrap:!1}}),fl=new r({props:{code:"JTIzJTIwSW1wb3J0JTIwT3BlbkVudidzJTIwY29yZSUyMGFic3RyYWN0aW9ucyUwQWZyb20lMjBjb3JlLmVudl9zZXJ2ZXIlMjBpbXBvcnQlMjBFbnZpcm9ubWVudCUyQyUyMEFjdGlvbiUyQyUyME9ic2VydmF0aW9uJTJDJTIwU3RhdGUlMEFmcm9tJTIwY29yZS5odHRwX2Vudl9jbGllbnQlMjBpbXBvcnQlMjBIVFRQRW52Q2xpZW50JTBBJTBBcHJpbnQoJTIyJTNEJTIyKjcwKSUwQXByaW50KCUyMiUyMCUyMCUyMCVGMCU5RiVBNyVBOSUyME9QRU5FTlYlMjBDT1JFJTIwQUJTVFJBQ1RJT05TJTIyKSUwQXByaW50KCUyMiUzRCUyMio3MCklMEElMEFwcmludCglMjIlMjIlMjIlMEElRjAlOUYlOTYlQTUlRUYlQjglOEYlMjAlMjBTRVJWRVIlMjBTSURFJTIwKHJ1bnMlMjBpbiUyMERvY2tlciklM0ElMEElMEElMjAlMjAlMjAlMjBjbGFzcyUyMEVudmlyb25tZW50KEFCQyklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAnJydCYXNlJTIwY2xhc3MlMjBmb3IlMjBhbGwlMjBlbnZpcm9ubWVudCUyMGltcGxlbWVudGF0aW9ucycnJyUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCU0MGFic3RyYWN0bWV0aG9kJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZGVmJTIwcmVzZXQoc2VsZiklMjAtJTNFJTIwT2JzZXJ2YXRpb24lM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAnJydTdGFydCUyMG5ldyUyMGVwaXNvZGUnJyclMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlNDBhYnN0cmFjdG1ldGhvZCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0ZXAoc2VsZiUyQyUyMGFjdGlvbiUzQSUyMEFjdGlvbiklMjAtJTNFJTIwT2JzZXJ2YXRpb24lM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAnJydFeGVjdXRlJTIwYWN0aW9uJTJDJTIwcmV0dXJuJTIwb2JzZXJ2YXRpb24nJyclMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlNDBwcm9wZXJ0eSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0YXRlKHNlbGYpJTIwLSUzRSUyMFN0YXRlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJycnR2V0JTIwZXBpc29kZSUyMG1ldGFkYXRhJycnJTBBJTBBJUYwJTlGJTkzJUIxJTIwQ0xJRU5UJTIwU0lERSUyMCh5b3VyJTIwdHJhaW5pbmclMjBjb2RlKSUzQSUwQSUwQSUyMCUyMCUyMCUyMGNsYXNzJTIwSFRUUEVudkNsaWVudChBQkMpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJycnQmFzZSUyMGNsYXNzJTIwZm9yJTIwSFRUUCUyMGNsaWVudHMnJyclMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBkZWYlMjByZXNldChzZWxmKSUyMC0lM0UlMjBTdGVwUmVzdWx0JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwSFRUUCUyMFBPU1QlMjAlMkZyZXNldCUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0ZXAoc2VsZiUyQyUyMGFjdGlvbiklMjAtJTNFJTIwU3RlcFJlc3VsdCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMEhUVFAlMjBQT1NUJTIwJTJGc3RlcCUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0YXRlKHNlbGYpJTIwLSUzRSUyMFN0YXRlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwSFRUUCUyMEdFVCUyMCUyRnN0YXRlJTBBJTIyJTIyJTIyKSUwQSUwQXByaW50KCUyMiUzRCUyMio3MCklMEFwcmludCglMjIlNUNuJUUyJTlDJUE4JTIwU2FtZSUyMGludGVyZmFjZSUyMG9uJTIwYm90aCUyMHNpZGVzJTIwLSUyMGNvbW11bmljYXRpb24lMjB2aWElMjBIVFRQISUyMiklMEFwcmludCglMjIlRjAlOUYlOEUlQUYlMjBZb3UlMjBmb2N1cyUyMG9uJTIwUkwlMkMlMjBPcGVuRW52JTIwaGFuZGxlcyUyMHRoZSUyMGluZnJhc3RydWN0dXJlLiU1Q24lMjIp",highlighted:`<span class="hljs-comment"># Import OpenEnv&#x27;s core abstractions</span>
<span class="hljs-keyword">from</span> core.env_server <span class="hljs-keyword">import</span> Environment, Action, Observation, State
<span class="hljs-keyword">from</span> core.http_env_client <span class="hljs-keyword">import</span> HTTPEnvClient
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 🧩 OPENENV CORE ABSTRACTIONS&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;&quot;&quot;
🖥️ SERVER SIDE (runs in Docker):
class Environment(ABC):
&#x27;&#x27;&#x27;Base class for all environment implementations&#x27;&#x27;&#x27;
@abstractmethod
def reset(self) -&gt; Observation:
&#x27;&#x27;&#x27;Start new episode&#x27;&#x27;&#x27;
@abstractmethod
def step(self, action: Action) -&gt; Observation:
&#x27;&#x27;&#x27;Execute action, return observation&#x27;&#x27;&#x27;
@property
def state(self) -&gt; State:
&#x27;&#x27;&#x27;Get episode metadata&#x27;&#x27;&#x27;
📱 CLIENT SIDE (your training code):
class HTTPEnvClient(ABC):
&#x27;&#x27;&#x27;Base class for HTTP clients&#x27;&#x27;&#x27;
def reset(self) -&gt; StepResult:
# HTTP POST /reset
def step(self, action) -&gt; StepResult:
# HTTP POST /step
def state(self) -&gt; State:
# HTTP GET /state
&quot;&quot;&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n✨ Same interface on both sides - communication via HTTP!&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🎯 You focus on RL, OpenEnv handles the infrastructure.\\n&quot;</span>)`,lang:"python",wrap:!1}}),Gl=new r({props:{code:"JTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTIwJTIwJTIwJUYwJTlGJUE3JUE5JTIwT1BFTkVOViUyMENPUkUlMjBBQlNUUkFDVElPTlMlMEElM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlMEElMEElRjAlOUYlOTYlQTUlRUYlQjglOEYlMjAlMjBTRVJWRVIlMjBTSURFJTIwKHJ1bnMlMjBpbiUyMERvY2tlciklM0ElMEElMEElMjAlMjAlMjAlMjBjbGFzcyUyMEVudmlyb25tZW50KEFCQyklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAnJydCYXNlJTIwY2xhc3MlMjBmb3IlMjBhbGwlMjBlbnZpcm9ubWVudCUyMGltcGxlbWVudGF0aW9ucycnJyUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCU0MGFic3RyYWN0bWV0aG9kJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZGVmJTIwcmVzZXQoc2VsZiklMjAtJTNFJTIwT2JzZXJ2YXRpb24lM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAnJydTdGFydCUyMG5ldyUyMGVwaXNvZGUnJyclMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlNDBhYnN0cmFjdG1ldGhvZCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0ZXAoc2VsZiUyQyUyMGFjdGlvbiUzQSUyMEFjdGlvbiklMjAtJTNFJTIwT2JzZXJ2YXRpb24lM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAnJydFeGVjdXRlJTIwYWN0aW9uJTJDJTIwcmV0dXJuJTIwb2JzZXJ2YXRpb24nJyclMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlNDBwcm9wZXJ0eSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0YXRlKHNlbGYpJTIwLSUzRSUyMFN0YXRlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJycnR2V0JTIwZXBpc29kZSUyMG1ldGFkYXRhJycnJTBBJTBBJUYwJTlGJTkzJUIxJTIwQ0xJRU5UJTIwU0lERSUyMCh5b3VyJTIwdHJhaW5pbmclMjBjb2RlKSUzQSUwQSUwQSUyMCUyMCUyMCUyMGNsYXNzJTIwSFRUUEVudkNsaWVudChBQkMpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJycnQmFzZSUyMGNsYXNzJTIwZm9yJTIwSFRUUCUyMGNsaWVudHMnJyclMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBkZWYlMjByZXNldChzZWxmKSUyMC0lM0UlMjBTdGVwUmVzdWx0JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwSFRUUCUyMFBPU1QlMjAlMkZyZXNldCUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0ZXAoc2VsZiUyQyUyMGFjdGlvbiklMjAtJTNFJTIwU3RlcFJlc3VsdCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMEhUVFAlMjBQT1NUJTIwJTJGc3RlcCUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRlZiUyMHN0YXRlKHNlbGYpJTIwLSUzRSUyMFN0YXRlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwSFRUUCUyMEdFVCUyMCUyRnN0YXRlJTBBJTBBJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTBBJUUyJTlDJUE4JTIwU2FtZSUyMGludGVyZmFjZSUyMG9uJTIwYm90aCUyMHNpZGVzJTIwLSUyMGNvbW11bmljYXRpb24lMjB2aWElMjBIVFRQISUwQSVGMCU5RiU4RSVBRiUyMFlvdSUyMGZvY3VzJTIwb24lMjBSTCUyQyUyME9wZW5FbnYlMjBoYW5kbGVzJTIwdGhlJTIwaW5mcmFzdHJ1Y3R1cmUu",highlighted:`======================================================================
🧩 OPENENV CORE ABSTRACTIONS
======================================================================
🖥️ SERVER SIDE (runs <span class="hljs-keyword">in</span> Docker):
<span class="hljs-keyword">class</span> <span class="hljs-title class_">Environment</span>(<span class="hljs-title class_ inherited__">ABC</span>):
<span class="hljs-string">&#x27;&#x27;&#x27;Base class for all environment implementations&#x27;&#x27;&#x27;</span>
<span class="hljs-meta"> @abstractmethod</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">reset</span>(<span class="hljs-params">self</span>) -&gt; Observation:
<span class="hljs-string">&#x27;&#x27;&#x27;Start new episode&#x27;&#x27;&#x27;</span>
<span class="hljs-meta"> @abstractmethod</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">step</span>(<span class="hljs-params">self, action: Action</span>) -&gt; Observation:
<span class="hljs-string">&#x27;&#x27;&#x27;Execute action, return observation&#x27;&#x27;&#x27;</span>
<span class="hljs-meta"> @property</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">state</span>(<span class="hljs-params">self</span>) -&gt; State:
<span class="hljs-string">&#x27;&#x27;&#x27;Get episode metadata&#x27;&#x27;&#x27;</span>
📱 CLIENT SIDE (your training code):
<span class="hljs-keyword">class</span> <span class="hljs-title class_">HTTPEnvClient</span>(<span class="hljs-title class_ inherited__">ABC</span>):
<span class="hljs-string">&#x27;&#x27;&#x27;Base class for HTTP clients&#x27;&#x27;&#x27;</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">reset</span>(<span class="hljs-params">self</span>) -&gt; StepResult:
<span class="hljs-comment"># HTTP POST /reset</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">step</span>(<span class="hljs-params">self, action</span>) -&gt; StepResult:
<span class="hljs-comment"># HTTP POST /step</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">state</span>(<span class="hljs-params">self</span>) -&gt; State:
<span class="hljs-comment"># HTTP GET /state</span>
======================================================================
✨ Same interface on both sides - communication via HTTP!
🎯 You focus on RL, OpenEnv handles the infrastructure.`,lang:"",wrap:!1}}),Zl=new I({props:{title:"Part 5: Example Integration - OpenSpiel 🎮",local:"part-5-example-integration---openspiel-",headingTag:"h2"}}),Fl=new I({props:{title:"What is OpenSpiel?",local:"what-is-openspiel",headingTag:"h3"}}),Yl=new I({props:{title:"OpenEnv’s Integration",local:"openenvs-integration",headingTag:"h3"}}),Hl=new r({props:{code:"ZnJvbSUyMGVudnMub3BlbnNwaWVsX2Vudi5jbGllbnQlMjBpbXBvcnQlMjBPcGVuU3BpZWxFbnYlMEElMEFwcmludCglMjIlM0QlMjIqNzApJTBBcHJpbnQoJTIyJTIwJTIwJTIwJUYwJTlGJTk0JThDJTIwSE9XJTIwT1BFTkVOViUyMFdSQVBTJTIwT1BFTlNQSUVMJTIyKSUwQXByaW50KCUyMiUzRCUyMio3MCklMEElMEFwcmludCglMjIlMjIlMjIlMEFjbGFzcyUyME9wZW5TcGllbEVudihIVFRQRW52Q2xpZW50JTVCT3BlblNwaWVsQWN0aW9uJTJDJTIwT3BlblNwaWVsT2JzZXJ2YXRpb24lNUQpJTNBJTBBJTBBJTIwJTIwJTIwJTIwZGVmJTIwX3N0ZXBfcGF5bG9hZChzZWxmJTJDJTIwYWN0aW9uJTNBJTIwT3BlblNwaWVsQWN0aW9uKSUyMC0lM0UlMjBkaWN0JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJycnQ29udmVydCUyMHR5cGVkJTIwYWN0aW9uJTIwdG8lMjBKU09OJTIwZm9yJTIwSFRUUCcnJyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMCU3QiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMmFjdGlvbl9pZCUyMiUzQSUyMGFjdGlvbi5hY3Rpb25faWQlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJnYW1lX25hbWUlMjIlM0ElMjBhY3Rpb24uZ2FtZV9uYW1lJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTdEJTBBJTBBJTIwJTIwJTIwJTIwZGVmJTIwX3BhcnNlX3Jlc3VsdChzZWxmJTJDJTIwcGF5bG9hZCUzQSUyMGRpY3QpJTIwLSUzRSUyMFN0ZXBSZXN1bHQlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAnJydQYXJzZSUyMEhUVFAlMjBKU09OJTIwcmVzcG9uc2UlMjBpbnRvJTIwdHlwZWQlMjBvYnNlcnZhdGlvbicnJyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMFN0ZXBSZXN1bHQoJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwb2JzZXJ2YXRpb24lM0RPcGVuU3BpZWxPYnNlcnZhdGlvbiguLi4pJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV3YXJkJTNEcGF5bG9hZCU1QidyZXdhcmQnJTVEJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZG9uZSUzRHBheWxvYWQlNUInZG9uZSclNUQlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjApJTBBJTBBJTIyJTIyJTIyKSUwQSUwQXByaW50KCUyMiVFMiU5NCU4MCUyMiUyMColMjA3MCklMEFwcmludCglMjIlNUNuJUUyJTlDJUE4JTIwVXNhZ2UlMjAod29ya3MlMjBmb3IlMjBBTEwlMjBPcGVuRW52JTIwZW52aXJvbm1lbnRzKSUzQSUyMiklMEFwcmludCglMjIlMjIlMjIlMEElMjAlMjBlbnYlMjAlM0QlMjBPcGVuU3BpZWxFbnYoYmFzZV91cmwlM0QlMjJodHRwJTNBJTJGJTJGbG9jYWxob3N0JTNBODAwMCUyMiklMEElMEElMjAlMjByZXN1bHQlMjAlM0QlMjBlbnYucmVzZXQoKSUwQSUyMCUyMCUyMyUyMFJldHVybnMlMjBTdGVwUmVzdWx0JTVCT3BlblNwaWVsT2JzZXJ2YXRpb24lNUQlMjAtJTIwVHlwZSUyMHNhZmUhJTBBJTBBJTIwJTIwcmVzdWx0JTIwJTNEJTIwZW52LnN0ZXAoT3BlblNwaWVsQWN0aW9uKGFjdGlvbl9pZCUzRDIlMkMlMjBnYW1lX25hbWUlM0QlMjJjYXRjaCUyMikpJTBBJTIwJTIwJTIzJTIwVHlwZSUyMGNoZWNrZXIlMjBrbm93cyUyMHRoaXMlMjBpcyUyMHZhbGlkISUwQSUwQSUyMCUyMHN0YXRlJTIwJTNEJTIwZW52LnN0YXRlKCklMEElMjAlMjAlMjMlMjBSZXR1cm5zJTIwT3BlblNwaWVsU3RhdGUlMEElMjIlMjIlMjIpJTBBJTBBcHJpbnQoJTIyJUUyJTk0JTgwJTIyJTIwKiUyMDcwKSUwQXByaW50KCUyMiU1Q24lRjAlOUYlOEUlQUYlMjBUaGlzJTIwcGF0dGVybiUyMHdvcmtzJTIwZm9yJTIwQU5ZJTIwZW52aXJvbm1lbnQlMjB5b3UlMjB3YW50JTIwdG8lMjB3cmFwISU1Q24lMjIp",highlighted:`<span class="hljs-keyword">from</span> envs.openspiel_env.client <span class="hljs-keyword">import</span> OpenSpielEnv
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 🔌 HOW OPENENV WRAPS OPENSPIEL&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;&quot;&quot;
class OpenSpielEnv(HTTPEnvClient[OpenSpielAction, OpenSpielObservation]):
def _step_payload(self, action: OpenSpielAction) -&gt; dict:
&#x27;&#x27;&#x27;Convert typed action to JSON for HTTP&#x27;&#x27;&#x27;
return {
&quot;action_id&quot;: action.action_id,
&quot;game_name&quot;: action.game_name,
}
def _parse_result(self, payload: dict) -&gt; StepResult:
&#x27;&#x27;&#x27;Parse HTTP JSON response into typed observation&#x27;&#x27;&#x27;
return StepResult(
observation=OpenSpielObservation(...),
reward=payload[&#x27;reward&#x27;],
done=payload[&#x27;done&#x27;]
)
&quot;&quot;&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;─&quot;</span> * <span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n✨ Usage (works for ALL OpenEnv environments):&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;&quot;&quot;
env = OpenSpielEnv(base_url=&quot;http://localhost:8000&quot;)
result = env.reset()
# Returns StepResult[OpenSpielObservation] - Type safe!
result = env.step(OpenSpielAction(action_id=2, game_name=&quot;catch&quot;))
# Type checker knows this is valid!
state = env.state()
# Returns OpenSpielState
&quot;&quot;&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;─&quot;</span> * <span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n🎯 This pattern works for ANY environment you want to wrap!\\n&quot;</span>)`,lang:"python",wrap:!1}}),Xl=new r({props:{code:"JTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTIwJTIwJTIwJUYwJTlGJTk0JThDJTIwSE9XJTIwT1BFTkVOViUyMFdSQVBTJTIwT1BFTlNQSUVMJTBBJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTBBY2xhc3MlMjBPcGVuU3BpZWxFbnYoSFRUUEVudkNsaWVudCU1Qk9wZW5TcGllbEFjdGlvbiUyQyUyME9wZW5TcGllbE9ic2VydmF0aW9uJTVEKSUzQSUwQSUwQSUyMCUyMCUyMCUyMGRlZiUyMF9zdGVwX3BheWxvYWQoc2VsZiUyQyUyMGFjdGlvbiUzQSUyME9wZW5TcGllbEFjdGlvbiklMjAtJTNFJTIwZGljdCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCcnJ0NvbnZlcnQlMjB0eXBlZCUyMGFjdGlvbiUyMHRvJTIwSlNPTiUyMGZvciUyMEhUVFAnJyclMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjAlN0IlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJhY3Rpb25faWQlMjIlM0ElMjBhY3Rpb24uYWN0aW9uX2lkJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIyZ2FtZV9uYW1lJTIyJTNBJTIwYWN0aW9uLmdhbWVfbmFtZSUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCU3RCUwQSUwQSUyMCUyMCUyMCUyMGRlZiUyMF9wYXJzZV9yZXN1bHQoc2VsZiUyQyUyMHBheWxvYWQlM0ElMjBkaWN0KSUyMC0lM0UlMjBTdGVwUmVzdWx0JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJycnUGFyc2UlMjBIVFRQJTIwSlNPTiUyMHJlc3BvbnNlJTIwaW50byUyMHR5cGVkJTIwb2JzZXJ2YXRpb24nJyclMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjBTdGVwUmVzdWx0KCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG9ic2VydmF0aW9uJTNET3BlblNwaWVsT2JzZXJ2YXRpb24oLi4uKSUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJld2FyZCUzRHBheWxvYWQlNUIncmV3YXJkJyU1RCUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGRvbmUlM0RwYXlsb2FkJTVCJ2RvbmUnJTVEJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwKSUwQSUwQSUwQSVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCUwQSUwQSVFMiU5QyVBOCUyMFVzYWdlJTIwKHdvcmtzJTIwZm9yJTIwQUxMJTIwT3BlbkVudiUyMGVudmlyb25tZW50cyklM0ElMEElMEElMjAlMjBlbnYlMjAlM0QlMjBPcGVuU3BpZWxFbnYoYmFzZV91cmwlM0QlMjJodHRwJTNBJTJGJTJGbG9jYWxob3N0JTNBODAwMCUyMiklMEElMEElMjAlMjByZXN1bHQlMjAlM0QlMjBlbnYucmVzZXQoKSUwQSUyMCUyMCUyMyUyMFJldHVybnMlMjBTdGVwUmVzdWx0JTVCT3BlblNwaWVsT2JzZXJ2YXRpb24lNUQlMjAtJTIwVHlwZSUyMHNhZmUhJTBBJTBBJTIwJTIwcmVzdWx0JTIwJTNEJTIwZW52LnN0ZXAoT3BlblNwaWVsQWN0aW9uKGFjdGlvbl9pZCUzRDIlMkMlMjBnYW1lX25hbWUlM0QlMjJjYXRjaCUyMikpJTBBJTIwJTIwJTIzJTIwVHlwZSUyMGNoZWNrZXIlMjBrbm93cyUyMHRoaXMlMjBpcyUyMHZhbGlkISUwQSUwQSUyMCUyMHN0YXRlJTIwJTNEJTIwZW52LnN0YXRlKCklMEElMjAlMjAlMjMlMjBSZXR1cm5zJTIwT3BlblNwaWVsU3RhdGUlMEElMEElRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlRTIlOTQlODAlMEElMEElRjAlOUYlOEUlQUYlMjBUaGlzJTIwcGF0dGVybiUyMHdvcmtzJTIwZm9yJTIwQU5ZJTIwZW52aXJvbm1lbnQlMjB5b3UlMjB3YW50JTIwdG8lMjB3cmFwIQ==",highlighted:`======================================================================
🔌 HOW OPENENV WRAPS OPENSPIEL
======================================================================
<span class="hljs-keyword">class</span> <span class="hljs-title class_">OpenSpielEnv</span>(HTTPEnvClient[OpenSpielAction, OpenSpielObservation]):
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_step_payload</span>(<span class="hljs-params">self, action: OpenSpielAction</span>) -&gt; <span class="hljs-built_in">dict</span>:
<span class="hljs-string">&#x27;&#x27;&#x27;Convert typed action to JSON for HTTP&#x27;&#x27;&#x27;</span>
<span class="hljs-keyword">return</span> {
<span class="hljs-string">&quot;action_id&quot;</span>: action.action_id,
<span class="hljs-string">&quot;game_name&quot;</span>: action.game_name,
}
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_parse_result</span>(<span class="hljs-params">self, payload: <span class="hljs-built_in">dict</span></span>) -&gt; StepResult:
<span class="hljs-string">&#x27;&#x27;&#x27;Parse HTTP JSON response into typed observation&#x27;&#x27;&#x27;</span>
<span class="hljs-keyword">return</span> StepResult(
observation=OpenSpielObservation(...),
reward=payload[<span class="hljs-string">&#x27;reward&#x27;</span>],
done=payload[<span class="hljs-string">&#x27;done&#x27;</span>]
)
──────────────────────────────────────────────────────────────────────
✨ Usage (works <span class="hljs-keyword">for</span> ALL OpenEnv environments):
env = OpenSpielEnv(base_url=<span class="hljs-string">&quot;http://localhost:8000&quot;</span>)
result = env.reset()
<span class="hljs-comment"># Returns StepResult[OpenSpielObservation] - Type safe!</span>
result = env.step(OpenSpielAction(action_id=<span class="hljs-number">2</span>, game_name=<span class="hljs-string">&quot;catch&quot;</span>))
<span class="hljs-comment"># Type checker knows this is valid!</span>
state = env.state()
<span class="hljs-comment"># Returns OpenSpielState</span>
──────────────────────────────────────────────────────────────────────
🎯 This pattern works <span class="hljs-keyword">for</span> ANY environment you want to wrap!`,lang:"",wrap:!1}}),Dl=new I({props:{title:"Type-Safe Models",local:"type-safe-models",headingTag:"h3"}}),ql=new r({props:{code:"JTIzJTIwSW1wb3J0JTIwT3BlblNwaWVsJTIwaW50ZWdyYXRpb24lMjBtb2RlbHMlMEFmcm9tJTIwZW52cy5vcGVuc3BpZWxfZW52Lm1vZGVscyUyMGltcG9ydCUyMCglMEElMjAlMjAlMjAlMjBPcGVuU3BpZWxBY3Rpb24lMkMlMEElMjAlMjAlMjAlMjBPcGVuU3BpZWxPYnNlcnZhdGlvbiUyQyUwQSUyMCUyMCUyMCUyME9wZW5TcGllbFN0YXRlJTBBKSUwQWZyb20lMjBkYXRhY2xhc3NlcyUyMGltcG9ydCUyMGZpZWxkcyUwQSUwQXByaW50KCUyMiUzRCUyMio3MCklMEFwcmludCglMjIlMjAlMjAlMjAlRjAlOUYlOEUlQUUlMjBPUEVOU1BJRUwlMjBJTlRFR1JBVElPTiUyMC0lMjBUWVBFLVNBRkUlMjBNT0RFTFMlMjIpJTBBcHJpbnQoJTIyJTNEJTIyKjcwKSUwQSUwQXByaW50KCUyMiU1Q24lRjAlOUYlOTMlQTQlMjBPcGVuU3BpZWxBY3Rpb24lMjAod2hhdCUyMHlvdSUyMHNlbmQpJTNBJTIyKSUwQXByaW50KCUyMiUyMCUyMCUyMCUyMiUyMCUyQiUyMCUyMiVFMiU5NCU4MCUyMiUyMColMjA2NCklMEFmb3IlMjBmaWVsZCUyMGluJTIwZmllbGRzKE9wZW5TcGllbEFjdGlvbiklM0ElMEElMjAlMjAlMjAlMjBwcmludChmJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwJTdCZmllbGQubmFtZSUzQTIwcyU3RCUyMCUzQSUyMCU3QmZpZWxkLnR5cGUlN0QlMjIpJTBBJTBBcHJpbnQoJTIyJTVDbiVGMCU5RiU5MyVBNSUyME9wZW5TcGllbE9ic2VydmF0aW9uJTIwKHdoYXQlMjB5b3UlMjByZWNlaXZlKSUzQSUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlMjIlMjAlMkIlMjAlMjIlRTIlOTQlODAlMjIlMjAqJTIwNjQpJTBBZm9yJTIwZmllbGQlMjBpbiUyMGZpZWxkcyhPcGVuU3BpZWxPYnNlcnZhdGlvbiklM0ElMEElMjAlMjAlMjAlMjBwcmludChmJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwJTdCZmllbGQubmFtZSUzQTIwcyU3RCUyMCUzQSUyMCU3QmZpZWxkLnR5cGUlN0QlMjIpJTBBJTBBcHJpbnQoJTIyJTVDbiVGMCU5RiU5MyU4QSUyME9wZW5TcGllbFN0YXRlJTIwKGVwaXNvZGUlMjBtZXRhZGF0YSklM0ElMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwJTIyJTIwJTJCJTIwJTIyJUUyJTk0JTgwJTIyJTIwKiUyMDY0KSUwQWZvciUyMGZpZWxkJTIwaW4lMjBmaWVsZHMoT3BlblNwaWVsU3RhdGUpJTNBJTBBJTIwJTIwJTIwJTIwcHJpbnQoZiUyMiUyMCUyMCUyMCVFMiU4MCVBMiUyMCU3QmZpZWxkLm5hbWUlM0EyMHMlN0QlMjAlM0ElMjAlN0JmaWVsZC50eXBlJTdEJTIyKSUwQSUwQXByaW50KCUyMiU1Q24lMjIlMjAlMkIlMjAlMjIlM0QlMjIqNzApJTBBcHJpbnQoJTIyJTVDbiVGMCU5RiU5MiVBMSUyMFR5cGUlMjBzYWZldHklMjBtZWFucyUzQSUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlRTIlOUMlODUlMjBZb3VyJTIwSURFJTIwYXV0b2NvbXBsZXRlcyUyMHRoZXNlJTIwZmllbGRzJTIyKSUwQXByaW50KCUyMiUyMCUyMCUyMCVFMiU5QyU4NSUyMFR5cG9zJTIwYXJlJTIwY2F1Z2h0JTIwYmVmb3JlJTIwcnVubmluZyUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlRTIlOUMlODUlMjBSZWZhY3RvcmluZyUyMGlzJTIwc2FmZSUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlRTIlOUMlODUlMjBTZWxmLWRvY3VtZW50aW5nJTIwY29kZSU1Q24lMjIp",highlighted:`<span class="hljs-comment"># Import OpenSpiel integration models</span>
<span class="hljs-keyword">from</span> envs.openspiel_env.models <span class="hljs-keyword">import</span> (
OpenSpielAction,
OpenSpielObservation,
OpenSpielState
)
<span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> fields
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 🎮 OPENSPIEL INTEGRATION - TYPE-SAFE MODELS&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n📤 OpenSpielAction (what you send):&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; &quot;</span> + <span class="hljs-string">&quot;─&quot;</span> * <span class="hljs-number">64</span>)
<span class="hljs-keyword">for</span> field <span class="hljs-keyword">in</span> fields(OpenSpielAction):
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot; • <span class="hljs-subst">{field.name:20s}</span> : <span class="hljs-subst">{field.<span class="hljs-built_in">type</span>}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n📥 OpenSpielObservation (what you receive):&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; &quot;</span> + <span class="hljs-string">&quot;─&quot;</span> * <span class="hljs-number">64</span>)
<span class="hljs-keyword">for</span> field <span class="hljs-keyword">in</span> fields(OpenSpielObservation):
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot; • <span class="hljs-subst">{field.name:20s}</span> : <span class="hljs-subst">{field.<span class="hljs-built_in">type</span>}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n📊 OpenSpielState (episode metadata):&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; &quot;</span> + <span class="hljs-string">&quot;─&quot;</span> * <span class="hljs-number">64</span>)
<span class="hljs-keyword">for</span> field <span class="hljs-keyword">in</span> fields(OpenSpielState):
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot; • <span class="hljs-subst">{field.name:20s}</span> : <span class="hljs-subst">{field.<span class="hljs-built_in">type</span>}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n&quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n💡 Type safety means:&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; ✅ Your IDE autocompletes these fields&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; ✅ Typos are caught before running&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; ✅ Refactoring is safe&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; ✅ Self-documenting code\\n&quot;</span>)`,lang:"python",wrap:!1}}),Pl=new r({props:{code:"JTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTIwJTIwJTIwJUYwJTlGJThFJUFFJTIwT1BFTlNQSUVMJTIwSU5URUdSQVRJT04lMjAtJTIwVFlQRS1TQUZFJTIwTU9ERUxTJTBBJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTBBJUYwJTlGJTkzJUE0JTIwT3BlblNwaWVsQWN0aW9uJTIwKHdoYXQlMjB5b3UlMjBzZW5kKSUzQSUwQSUyMCUyMCUyMCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCVFMiU5NCU4MCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMG1ldGFkYXRhJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwdHlwaW5nLkRpY3QlNUJzdHIlMkMlMjB0eXBpbmcuQW55JTVEJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwYWN0aW9uX2lkJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwaW50JTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwZ2FtZV9uYW1lJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwc3RyJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwZ2FtZV9wYXJhbXMlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjBEaWN0JTVCc3RyJTJDJTIwQW55JTVEJTBBJTBBJUYwJTlGJTkzJUE1JTIwT3BlblNwaWVsT2JzZXJ2YXRpb24lMjAod2hhdCUyMHlvdSUyMHJlY2VpdmUpJTNBJTBBJTIwJTIwJTIwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwZG9uZSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQSUyMCUzQ2NsYXNzJTIwJ2Jvb2wnJTNFJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwcmV3YXJkJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwdHlwaW5nLlVuaW9uJTVCYm9vbCUyQyUyMGludCUyQyUyMGZsb2F0JTJDJTIwTm9uZVR5cGUlNUQlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBtZXRhZGF0YSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQSUyMHR5cGluZy5EaWN0JTVCc3RyJTJDJTIwdHlwaW5nLkFueSU1RCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMGluZm9fc3RhdGUlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjBMaXN0JTVCZmxvYXQlNUQlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBsZWdhbF9hY3Rpb25zJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwTGlzdCU1QmludCU1RCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMGdhbWVfcGhhc2UlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjBzdHIlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBjdXJyZW50X3BsYXllcl9pZCUyMCUyMCUyMCUyMCUzQSUyMGludCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMG9wcG9uZW50X2xhc3RfYWN0aW9uJTIwJTNBJTIwT3B0aW9uYWwlNUJpbnQlNUQlMEElMEElRjAlOUYlOTMlOEElMjBPcGVuU3BpZWxTdGF0ZSUyMChlcGlzb2RlJTIwbWV0YWRhdGEpJTNBJTBBJTIwJTIwJTIwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwZXBpc29kZV9pZCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQSUyMHR5cGluZy5PcHRpb25hbCU1QnN0ciU1RCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMHN0ZXBfY291bnQlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjAlM0NjbGFzcyUyMCdpbnQnJTNFJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwZ2FtZV9uYW1lJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwc3RyJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwYWdlbnRfcGxheWVyJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwaW50JTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwb3Bwb25lbnRfcG9saWN5JTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwc3RyJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwZ2FtZV9wYXJhbXMlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjBEaWN0JTVCc3RyJTJDJTIwQW55JTVEJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwbnVtX3BsYXllcnMlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjBpbnQlMEElMEElM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlMEElMEElRjAlOUYlOTIlQTElMjBUeXBlJTIwc2FmZXR5JTIwbWVhbnMlM0ElMEElMjAlMjAlMjAlRTIlOUMlODUlMjBZb3VyJTIwSURFJTIwYXV0b2NvbXBsZXRlcyUyMHRoZXNlJTIwZmllbGRzJTBBJTIwJTIwJTIwJUUyJTlDJTg1JTIwVHlwb3MlMjBhcmUlMjBjYXVnaHQlMjBiZWZvcmUlMjBydW5uaW5nJTBBJTIwJTIwJTIwJUUyJTlDJTg1JTIwUmVmYWN0b3JpbmclMjBpcyUyMHNhZmUlMEElMjAlMjAlMjAlRTIlOUMlODUlMjBTZWxmLWRvY3VtZW50aW5nJTIwY29kZQ==",highlighted:`======================================================================
🎮 OPENSPIEL INTEGRATION - TYPE-SAFE MODELS
======================================================================
📤 OpenSpielAction (what you send):
────────────────────────────────────────────────────────────────
• metadata : typing.<span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, typing.<span class="hljs-type">Any</span>]
• action_id : <span class="hljs-built_in">int</span>
• game_name : <span class="hljs-built_in">str</span>
• game_params : <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]
📥 OpenSpielObservation (what you receive):
────────────────────────────────────────────────────────────────
• done : &lt;<span class="hljs-keyword">class</span> <span class="hljs-string">&#x27;bool&#x27;</span>&gt;
• reward : typing.<span class="hljs-type">Union</span>[<span class="hljs-built_in">bool</span>, <span class="hljs-built_in">int</span>, <span class="hljs-built_in">float</span>, NoneType]
• metadata : typing.<span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, typing.<span class="hljs-type">Any</span>]
• info_state : <span class="hljs-type">List</span>[<span class="hljs-built_in">float</span>]
• legal_actions : <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]
• game_phase : <span class="hljs-built_in">str</span>
• current_player_id : <span class="hljs-built_in">int</span>
• opponent_last_action : <span class="hljs-type">Optional</span>[<span class="hljs-built_in">int</span>]
📊 OpenSpielState (episode metadata):
────────────────────────────────────────────────────────────────
• episode_id : typing.<span class="hljs-type">Optional</span>[<span class="hljs-built_in">str</span>]
• step_count : &lt;<span class="hljs-keyword">class</span> <span class="hljs-string">&#x27;int&#x27;</span>&gt;
• game_name : <span class="hljs-built_in">str</span>
• agent_player : <span class="hljs-built_in">int</span>
• opponent_policy : <span class="hljs-built_in">str</span>
• game_params : <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]
• num_players : <span class="hljs-built_in">int</span>
======================================================================
💡 <span class="hljs-type">Type</span> safety means:
✅ Your IDE autocompletes these fields
✅ Typos are caught before running
✅ Refactoring <span class="hljs-keyword">is</span> safe
✅ Self-documenting code`,lang:"",wrap:!1}}),Kl=new I({props:{title:"How the Client Works",local:"how-the-client-works",headingTag:"h3"}}),Js=new I({props:{title:"Part 6: Using Real OpenSpiel 🎮",local:"part-6-using-real-openspiel-",headingTag:"h2"}}),es=new I({props:{title:"Now let’s USE a production environment!",local:"now-lets-use-a-production-environment",headingTag:"h3"}}),ns=new I({props:{title:"The Game: Catch 🔴🏓",local:"the-game-catch-",headingTag:"h3"}}),Ms=new r({props:{code:"JUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUYwJTlGJTk0JUI0JTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTBBJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTBBJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJTIwJTIwQmFsbCUwQSVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUwQSVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCUyMCUyMGZhbGxzJTBBJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTBBJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJUUyJUFDJTlDJTIwJTIwJTIwZG93biUwQSVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUwQSVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUwQSVFMiVBQyU5QyUyMCVFMiVBQyU5QyUyMCVGMCU5RiU4RiU5MyUyMCVFMiVBQyU5QyUyMCVFMiVBQyU5QyUwQSUyMCUyMCUyMCUyMCUyMFBhZGRsZQ==",highlighted:`⬜ ⬜ 🔴 ⬜ ⬜
⬜ ⬜ ⬜ ⬜ ⬜
⬜ ⬜ ⬜ ⬜ ⬜ <span class="hljs-built_in">Ball</span>
⬜ ⬜ ⬜ ⬜ ⬜
⬜ ⬜ ⬜ ⬜ ⬜ <span class="hljs-variable">falls</span>
⬜ ⬜ ⬜ ⬜ ⬜
⬜ ⬜ ⬜ ⬜ ⬜ <span class="hljs-variable">down</span>
⬜ ⬜ ⬜ ⬜ ⬜
⬜ ⬜ ⬜ ⬜ ⬜
⬜ ⬜ 🏓 ⬜ ⬜
<span class="hljs-variable">Paddle</span>`,lang:"",wrap:!1}}),os=new r({props:{code:"ZnJvbSUyMGVudnMub3BlbnNwaWVsX2VudiUyMGltcG9ydCUyME9wZW5TcGllbEVudiUwQWZyb20lMjBlbnZzLm9wZW5zcGllbF9lbnYubW9kZWxzJTIwaW1wb3J0JTIwKCUwQSUyMCUyMCUyMCUyME9wZW5TcGllbEFjdGlvbiUyQyUwQSUyMCUyMCUyMCUyME9wZW5TcGllbE9ic2VydmF0aW9uJTJDJTBBJTIwJTIwJTIwJTIwT3BlblNwaWVsU3RhdGUlMEEpJTBBZnJvbSUyMGRhdGFjbGFzc2VzJTIwaW1wb3J0JTIwZmllbGRzJTBBJTBBcHJpbnQoJTIyJUYwJTlGJThFJUFFJTIwJTIyJTIwJTJCJTIwJTIyJTNEJTIyKjY0JTIwJTJCJTIwJTIyJTIwJUYwJTlGJThFJUFFJTIyKSUwQXByaW50KCUyMiUyMCUyMCUyMCVFMiU5QyU4NSUyMEltcG9ydGluZyUyMFJlYWwlMjBPcGVuU3BpZWwlMjBFbnZpcm9ubWVudCElMjIpJTBBcHJpbnQoJTIyJUYwJTlGJThFJUFFJTIwJTIyJTIwJTJCJTIwJTIyJTNEJTIyKjY0JTIwJTJCJTIwJTIyJTIwJUYwJTlGJThFJUFFJTVDbiUyMiklMEElMEFwcmludCglMjIlRjAlOUYlOTMlQTYlMjBXaGF0JTIwd2UlMjBqdXN0JTIwaW1wb3J0ZWQlM0ElMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwT3BlblNwaWVsRW52JTIwLSUyMEhUVFAlMjBjbGllbnQlMjBmb3IlMjBPcGVuU3BpZWwlMjBnYW1lcyUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlRTIlODAlQTIlMjBPcGVuU3BpZWxBY3Rpb24lMjAtJTIwVHlwZS1zYWZlJTIwYWN0aW9ucyUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlRTIlODAlQTIlMjBPcGVuU3BpZWxPYnNlcnZhdGlvbiUyMC0lMjBUeXBlLXNhZmUlMjBvYnNlcnZhdGlvbnMlMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwT3BlblNwaWVsU3RhdGUlMjAtJTIwRXBpc29kZSUyMG1ldGFkYXRhJTVDbiUyMiklMEElMEFwcmludCglMjIlRjAlOUYlOTMlOEIlMjBPcGVuU3BpZWxPYnNlcnZhdGlvbiUyMGZpZWxkcyUzQSUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlMjIlMjAlMkIlMjAlMjIlRTIlOTQlODAlMjIlMjAqJTIwNjApJTBBZm9yJTIwZmllbGQlMjBpbiUyMGZpZWxkcyhPcGVuU3BpZWxPYnNlcnZhdGlvbiklM0ElMEElMjAlMjAlMjAlMjBwcmludChmJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwJTdCZmllbGQubmFtZSUzQTI1cyU3RCUyMCUzQSUyMCU3QmZpZWxkLnR5cGUlN0QlMjIpJTBBJTBBcHJpbnQoJTIyJTVDbiUyMiUyMCUyQiUyMCUyMiUzRCUyMio3MCklMEFwcmludCglMjIlNUNuJUYwJTlGJTkyJUExJTIwVGhpcyUyMGlzJTIwUkVBTCUyME9wZW5FbnYlMjBjb2RlJTIwLSUyMHVzZWQlMjBpbiUyMHByb2R1Y3Rpb24hJTIyKSUwQXByaW50KCUyMiUyMCUyMCUyMCVFMiU4MCVBMiUyMFdyYXBzJTIwNiUyME9wZW5TcGllbCUyMGdhbWVzJTIwKENhdGNoJTJDJTIwVGljLVRhYy1Ub2UlMkMlMjBQb2tlciUyQyUyMGV0Yy4pJTIyKSUwQXByaW50KCUyMiUyMCUyMCUyMCVFMiU4MCVBMiUyMFR5cGUtc2FmZSUyMGFjdGlvbnMlMjBhbmQlMjBvYnNlcnZhdGlvbnMlMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwV29ya3MlMjB2aWElMjBIVFRQJTIwKHdlJ2xsJTIwc2VlJTIwdGhhdCUyMG5leHQhKSU1Q24lMjIp",highlighted:`<span class="hljs-keyword">from</span> envs.openspiel_env <span class="hljs-keyword">import</span> OpenSpielEnv
<span class="hljs-keyword">from</span> envs.openspiel_env.models <span class="hljs-keyword">import</span> (
OpenSpielAction,
OpenSpielObservation,
OpenSpielState
)
<span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> fields
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🎮 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">64</span> + <span class="hljs-string">&quot; 🎮&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; ✅ Importing Real OpenSpiel Environment!&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🎮 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">64</span> + <span class="hljs-string">&quot; 🎮\\n&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;📦 What we just imported:&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • OpenSpielEnv - HTTP client for OpenSpiel games&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • OpenSpielAction - Type-safe actions&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • OpenSpielObservation - Type-safe observations&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • OpenSpielState - Episode metadata\\n&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;📋 OpenSpielObservation fields:&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; &quot;</span> + <span class="hljs-string">&quot;─&quot;</span> * <span class="hljs-number">60</span>)
<span class="hljs-keyword">for</span> field <span class="hljs-keyword">in</span> fields(OpenSpielObservation):
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot; • <span class="hljs-subst">{field.name:25s}</span> : <span class="hljs-subst">{field.<span class="hljs-built_in">type</span>}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n&quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n💡 This is REAL OpenEnv code - used in production!&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Wraps 6 OpenSpiel games (Catch, Tic-Tac-Toe, Poker, etc.)&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Type-safe actions and observations&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Works via HTTP (we&#x27;ll see that next!)\\n&quot;</span>)`,lang:"python",wrap:!1}}),Cs=new r({props:{code:"JUYwJTlGJThFJUFFJTIwJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTIwJUYwJTlGJThFJUFFJTBBJTIwJTIwJTIwJUUyJTlDJTg1JTIwSW1wb3J0aW5nJTIwUmVhbCUyME9wZW5TcGllbCUyMEVudmlyb25tZW50ISUwQSVGMCU5RiU4RSVBRSUyMCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUzRCUyMCVGMCU5RiU4RSVBRSUwQSUwQSVGMCU5RiU5MyVBNiUyMFdoYXQlMjB3ZSUyMGp1c3QlMjBpbXBvcnRlZCUzQSUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyME9wZW5TcGllbEVudiUyMC0lMjBIVFRQJTIwY2xpZW50JTIwZm9yJTIwT3BlblNwaWVsJTIwZ2FtZXMlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBPcGVuU3BpZWxBY3Rpb24lMjAtJTIwVHlwZS1zYWZlJTIwYWN0aW9ucyUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyME9wZW5TcGllbE9ic2VydmF0aW9uJTIwLSUyMFR5cGUtc2FmZSUyMG9ic2VydmF0aW9ucyUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyME9wZW5TcGllbFN0YXRlJTIwLSUyMEVwaXNvZGUlMjBtZXRhZGF0YSUwQSUwQSVGMCU5RiU5MyU4QiUyME9wZW5TcGllbE9ic2VydmF0aW9uJTIwZmllbGRzJTNBJTBBJTIwJTIwJTIwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJUUyJTk0JTgwJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwZG9uZSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQSUyMCUzQ2NsYXNzJTIwJ2Jvb2wnJTNFJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwcmV3YXJkJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwdHlwaW5nLlVuaW9uJTVCYm9vbCUyQyUyMGludCUyQyUyMGZsb2F0JTJDJTIwTm9uZVR5cGUlNUQlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBtZXRhZGF0YSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQSUyMHR5cGluZy5EaWN0JTVCc3RyJTJDJTIwdHlwaW5nLkFueSU1RCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMGluZm9fc3RhdGUlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjBMaXN0JTVCZmxvYXQlNUQlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBsZWdhbF9hY3Rpb25zJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwTGlzdCU1QmludCU1RCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMGdhbWVfcGhhc2UlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0ElMjBzdHIlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBjdXJyZW50X3BsYXllcl9pZCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQSUyMGludCUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMG9wcG9uZW50X2xhc3RfYWN0aW9uJTIwJTIwJTIwJTIwJTIwJTIwJTNBJTIwT3B0aW9uYWwlNUJpbnQlNUQlMEElMEElM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlMEElMEElRjAlOUYlOTIlQTElMjBUaGlzJTIwaXMlMjBSRUFMJTIwT3BlbkVudiUyMGNvZGUlMjAtJTIwdXNlZCUyMGluJTIwcHJvZHVjdGlvbiElMEElMjAlMjAlMjAlRTIlODAlQTIlMjBXcmFwcyUyMDYlMjBPcGVuU3BpZWwlMjBnYW1lcyUyMChDYXRjaCUyQyUyMFRpYy1UYWMtVG9lJTJDJTIwUG9rZXIlMkMlMjBldGMuKSUwQSUyMCUyMCUyMCVFMiU4MCVBMiUyMFR5cGUtc2FmZSUyMGFjdGlvbnMlMjBhbmQlMjBvYnNlcnZhdGlvbnMlMEElMjAlMjAlMjAlRTIlODAlQTIlMjBXb3JrcyUyMHZpYSUyMEhUVFAlMjAod2UnbGwlMjBzZWUlMjB0aGF0JTIwbmV4dCEp",highlighted:`🎮 ================================================================ 🎮
✅ Importing Real OpenSpiel Environment!
🎮 ================================================================ 🎮
📦 What we just imported:
• OpenSpielEnv - HTTP client <span class="hljs-keyword">for</span> OpenSpiel games
• OpenSpielAction - <span class="hljs-type">Type</span>-safe actions
• OpenSpielObservation - <span class="hljs-type">Type</span>-safe observations
• OpenSpielState - Episode metadata
📋 OpenSpielObservation fields:
────────────────────────────────────────────────────────────
• done : &lt;<span class="hljs-keyword">class</span> <span class="hljs-string">&#x27;bool&#x27;</span>&gt;
• reward : typing.<span class="hljs-type">Union</span>[<span class="hljs-built_in">bool</span>, <span class="hljs-built_in">int</span>, <span class="hljs-built_in">float</span>, NoneType]
• metadata : typing.<span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, typing.<span class="hljs-type">Any</span>]
• info_state : <span class="hljs-type">List</span>[<span class="hljs-built_in">float</span>]
• legal_actions : <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]
• game_phase : <span class="hljs-built_in">str</span>
• current_player_id : <span class="hljs-built_in">int</span>
• opponent_last_action : <span class="hljs-type">Optional</span>[<span class="hljs-built_in">int</span>]
======================================================================
💡 This <span class="hljs-keyword">is</span> REAL OpenEnv code - used <span class="hljs-keyword">in</span> production!
• Wraps <span class="hljs-number">6</span> OpenSpiel games (Catch, Tic-Tac-Toe, Poker, etc.)
• <span class="hljs-type">Type</span>-safe actions <span class="hljs-keyword">and</span> observations
• Works via HTTP (we<span class="hljs-string">&#x27;ll see that next!)</span>`,lang:"",wrap:!1}}),Es=new I({props:{title:"Part 7: Four Policies 🤖",local:"part-7-four-policies-",headingTag:"h2"}}),ms=new r({props:{code:"aW1wb3J0JTIwcmFuZG9tJTBBJTBBJTIzJTIwJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTIzJTIwUE9MSUNJRVMlMjAtJTIwRGlmZmVyZW50JTIwQUklMjBzdHJhdGVnaWVzJTIwKGFkYXB0ZWQlMjBmb3IlMjBPcGVuU3BpZWwpJTBBJTIzJTIwJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTBBJTBBY2xhc3MlMjBSYW5kb21Qb2xpY3klM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjJCYXNlbGluZSUzQSUyMFB1cmUlMjByYW5kb20lMjBndWVzc2luZy4lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjBuYW1lJTIwJTNEJTIwJTIyJUYwJTlGJThFJUIyJTIwUmFuZG9tJTIwR3Vlc3NlciUyMiUwQSUwQSUyMCUyMCUyMCUyMGRlZiUyMHNlbGVjdF9hY3Rpb24oc2VsZiUyQyUyMG9icyUzQSUyME9wZW5TcGllbE9ic2VydmF0aW9uKSUyMC0lM0UlMjBpbnQlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjByYW5kb20uY2hvaWNlKG9icy5sZWdhbF9hY3Rpb25zKSUwQSUwQSUwQWNsYXNzJTIwQWx3YXlzU3RheVBvbGljeSUzQSUwQSUyMCUyMCUyMCUyMCUyMiUyMiUyMkJhZCUyMHN0cmF0ZWd5JTNBJTIwTmV2ZXIlMjBtb3Zlcy4lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjBuYW1lJTIwJTNEJTIwJTIyJUYwJTlGJTlCJTkxJTIwQWx3YXlzJTIwU3RheSUyMiUwQSUwQSUyMCUyMCUyMCUyMGRlZiUyMHNlbGVjdF9hY3Rpb24oc2VsZiUyQyUyMG9icyUzQSUyME9wZW5TcGllbE9ic2VydmF0aW9uKSUyMC0lM0UlMjBpbnQlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjAxJTIwJTIwJTIzJTIwU1RBWSUwQSUwQSUwQWNsYXNzJTIwU21hcnRQb2xpY3klM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjJPcHRpbWFsJTNBJTIwTW92ZSUyMHBhZGRsZSUyMHRvd2FyZCUyMGJhbGwuJTIyJTIyJTIyJTBBJTIwJTIwJTIwJTIwbmFtZSUyMCUzRCUyMCUyMiVGMCU5RiVBNyVBMCUyMFNtYXJ0JTIwSGV1cmlzdGljJTIyJTBBJTBBJTIwJTIwJTIwJTIwZGVmJTIwc2VsZWN0X2FjdGlvbihzZWxmJTJDJTIwb2JzJTNBJTIwT3BlblNwaWVsT2JzZXJ2YXRpb24pJTIwLSUzRSUyMGludCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMFBhcnNlJTIwT3BlblNwaWVsJTIwb2JzZXJ2YXRpb24lMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjMlMjBGb3IlMjBDYXRjaCUzQSUyMGluZm9fc3RhdGUlMjBpcyUyMGElMjBmbGF0dGVuZWQlMjAxMHg1JTIwZ3JpZCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMEJhbGwlMjBwb3NpdGlvbiUyMGFuZCUyMHBhZGRsZSUyMHBvc2l0aW9uJTIwZW5jb2RlZCUyMGluJTIwdGhlJTIwdmVjdG9yJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwaW5mb19zdGF0ZSUyMCUzRCUyMG9icy5pbmZvX3N0YXRlJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwRmluZCUyMGJhbGwlMjBhbmQlMjBwYWRkbGUlMjBwb3NpdGlvbnMlMjBmcm9tJTIwaW5mb19zdGF0ZSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMENhdGNoJTIwdXNlcyUyMGElMjAxMHg1JTIwZ3JpZCUyQyUyMHNvJTIwNTAlMjB2YWx1ZXMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBncmlkX3NpemUlMjAlM0QlMjA1JTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwRmluZCUyMHBvc2l0aW9ucyUyMChiYWxsJTIwJTNEJTIwMS4wJTIwaW4lMjB0aGUlMjBmbGF0dGVuZWQlMjBncmlkJTJDJTIwcGFkZGxlJTIwJTNEJTIwMS4wJTIwaW4lMjB0aGUlMjBsYXN0JTIwcm93JTIwb2YlMjB0aGUlMjBmbGF0dGVuZWQlMjBncmlkKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGJhbGxfY29sJTIwJTNEJTIwTm9uZSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHBhZGRsZV9jb2wlMjAlM0QlMjBOb25lJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZm9yJTIwaWR4JTJDJTIwdmFsJTIwaW4lMjBlbnVtZXJhdGUoaW5mb19zdGF0ZSklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBpZiUyMGFicyh2YWwlMjAtJTIwMS4wKSUyMCUzQyUyMDAuMDElM0ElMjAlMjAlMjMlMjBCYWxsJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwYmFsbF9jb2wlMjAlM0QlMjBpZHglMjAlMjUlMjBncmlkX3NpemUlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBicmVhayUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGxhc3Rfcm93JTIwJTNEJTIwaW5mb19zdGF0ZSU1Qi1ncmlkX3NpemUlM0ElNUQlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwYWRkbGVfY29sJTIwJTNEJTIwbGFzdF9yb3cuaW5kZXgoMS4wKSUyMCUyMyUyMFBhZGRsZSUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGlmJTIwYmFsbF9jb2wlMjBpcyUyMG5vdCUyME5vbmUlMjBhbmQlMjBwYWRkbGVfY29sJTIwaXMlMjBub3QlMjBOb25lJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwaWYlMjBwYWRkbGVfY29sJTIwJTNDJTIwYmFsbF9jb2wlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjAyJTIwJTIwJTIzJTIwTW92ZSUyMFJJR0hUJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZWxpZiUyMHBhZGRsZV9jb2wlMjAlM0UlMjBiYWxsX2NvbCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMDAlMjAlMjAlMjMlMjBNb3ZlJTIwTEVGVCUwQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMDElMjAlMjAlMjMlMjBTVEFZJTIwKGZhbGxiYWNrKSUwQSUwQSUwQWNsYXNzJTIwTGVhcm5pbmdQb2xpY3klM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjJTaW11bGF0ZWQlMjBSTCUzQSUyMEVwc2lsb24tZ3JlZWR5JTIwZXhwbG9yYXRpb24uJTIyJTIyJTIyJTBBJTIwJTIwJTIwJTIwbmFtZSUyMCUzRCUyMCUyMiVGMCU5RiU5MyU4OCUyMExlYXJuaW5nJTIwQWdlbnQlMjIlMEElMEElMjAlMjAlMjAlMjBkZWYlMjBfX2luaXRfXyhzZWxmKSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNlbGYuc3RlcHMlMjAlM0QlMjAwJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwc2VsZi5zbWFydF9wb2xpY3klMjAlM0QlMjBTbWFydFBvbGljeSgpJTBBJTBBJTIwJTIwJTIwJTIwZGVmJTIwc2VsZWN0X2FjdGlvbihzZWxmJTJDJTIwb2JzJTNBJTIwT3BlblNwaWVsT2JzZXJ2YXRpb24pJTIwLSUzRSUyMGludCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNlbGYuc3RlcHMlMjAlMkIlM0QlMjAxJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwRGVjYXklMjBleHBsb3JhdGlvbiUyMHJhdGUlMjBvdmVyJTIwdGltZSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGVwc2lsb24lMjAlM0QlMjBtYXgoMC4xJTJDJTIwMS4wJTIwLSUyMChzZWxmLnN0ZXBzJTIwJTJGJTIwMTAwKSklMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBpZiUyMHJhbmRvbS5yYW5kb20oKSUyMCUzQyUyMGVwc2lsb24lM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjMlMjBFeHBsb3JlJTNBJTIwcmFuZG9tJTIwYWN0aW9uJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwcmFuZG9tLmNob2ljZShvYnMubGVnYWxfYWN0aW9ucyklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBlbHNlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwRXhwbG9pdCUzQSUyMHVzZSUyMHNtYXJ0JTIwc3RyYXRlZ3klMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjBzZWxmLnNtYXJ0X3BvbGljeS5zZWxlY3RfYWN0aW9uKG9icyklMEElMEElMEFwcmludCglMjIlRjAlOUYlQTQlOTYlMjAlMjIlMjAlMkIlMjAlMjIlM0QlMjIqNjQlMjAlMkIlMjAlMjIlMjAlRjAlOUYlQTQlOTYlMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwJUUyJTlDJTg1JTIwNCUyMFBvbGljaWVzJTIwQ3JlYXRlZCUyMChBZGFwdGVkJTIwZm9yJTIwT3BlblNwaWVsKSElMjIpJTBBcHJpbnQoJTIyJUYwJTlGJUE0JTk2JTIwJTIyJTIwJTJCJTIwJTIyJTNEJTIyKjY0JTIwJTJCJTIwJTIyJTIwJUYwJTlGJUE0JTk2JTVDbiUyMiklMEElMEFwb2xpY2llcyUyMCUzRCUyMCU1QlJhbmRvbVBvbGljeSgpJTJDJTIwQWx3YXlzU3RheVBvbGljeSgpJTJDJTIwU21hcnRQb2xpY3koKSUyQyUyMExlYXJuaW5nUG9saWN5KCklNUQlMEFmb3IlMjBpJTJDJTIwcG9saWN5JTIwaW4lMjBlbnVtZXJhdGUocG9saWNpZXMlMkMlMjAxKSUzQSUwQSUyMCUyMCUyMCUyMHByaW50KGYlMjIlMjAlMjAlMjAlN0JpJTdELiUyMCU3QnBvbGljeS5uYW1lJTdEJTIyKSUwQSUwQXByaW50KCUyMiU1Q24lRjAlOUYlOTIlQTElMjBUaGVzZSUyMHBvbGljaWVzJTIwd29yayUyMHdpdGglMjBPcGVuU3BpZWxPYnNlcnZhdGlvbiElMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwUmVhZCUyMGluZm9fc3RhdGUlMjAoZmxhdHRlbmVkJTIwZ3JpZCklMjIpJTBBcHJpbnQoJTIyJTIwJTIwJTIwJUUyJTgwJUEyJTIwVXNlJTIwbGVnYWxfYWN0aW9ucyUyMiklMEFwcmludCglMjIlMjAlMjAlMjAlRTIlODAlQTIlMjBXb3JrJTIwd2l0aCUyMEFOWSUyME9wZW5TcGllbCUyMGdhbWUlMjB0aGF0JTIwZXhwb3NlcyUyMHRoZXNlISU1Q24lMjIp",highlighted:`<span class="hljs-keyword">import</span> random
<span class="hljs-comment"># ============================================================================</span>
<span class="hljs-comment"># POLICIES - Different AI strategies (adapted for OpenSpiel)</span>
<span class="hljs-comment"># ============================================================================</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">RandomPolicy</span>:
<span class="hljs-string">&quot;&quot;&quot;Baseline: Pure random guessing.&quot;&quot;&quot;</span>
name = <span class="hljs-string">&quot;🎲 Random Guesser&quot;</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">select_action</span>(<span class="hljs-params">self, obs: OpenSpielObservation</span>) -&gt; <span class="hljs-built_in">int</span>:
<span class="hljs-keyword">return</span> random.choice(obs.legal_actions)
<span class="hljs-keyword">class</span> <span class="hljs-title class_">AlwaysStayPolicy</span>:
<span class="hljs-string">&quot;&quot;&quot;Bad strategy: Never moves.&quot;&quot;&quot;</span>
name = <span class="hljs-string">&quot;🛑 Always Stay&quot;</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">select_action</span>(<span class="hljs-params">self, obs: OpenSpielObservation</span>) -&gt; <span class="hljs-built_in">int</span>:
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span> <span class="hljs-comment"># STAY</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">SmartPolicy</span>:
<span class="hljs-string">&quot;&quot;&quot;Optimal: Move paddle toward ball.&quot;&quot;&quot;</span>
name = <span class="hljs-string">&quot;🧠 Smart Heuristic&quot;</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">select_action</span>(<span class="hljs-params">self, obs: OpenSpielObservation</span>) -&gt; <span class="hljs-built_in">int</span>:
<span class="hljs-comment"># Parse OpenSpiel observation</span>
<span class="hljs-comment"># For Catch: info_state is a flattened 10x5 grid</span>
<span class="hljs-comment"># Ball position and paddle position encoded in the vector</span>
info_state = obs.info_state
<span class="hljs-comment"># Find ball and paddle positions from info_state</span>
<span class="hljs-comment"># Catch uses a 10x5 grid, so 50 values</span>
grid_size = <span class="hljs-number">5</span>
<span class="hljs-comment"># Find positions (ball = 1.0 in the flattened grid, paddle = 1.0 in the last row of the flattened grid)</span>
ball_col = <span class="hljs-literal">None</span>
paddle_col = <span class="hljs-literal">None</span>
<span class="hljs-keyword">for</span> idx, val <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(info_state):
<span class="hljs-keyword">if</span> <span class="hljs-built_in">abs</span>(val - <span class="hljs-number">1.0</span>) &lt; <span class="hljs-number">0.01</span>: <span class="hljs-comment"># Ball</span>
ball_col = idx % grid_size
<span class="hljs-keyword">break</span>
last_row = info_state[-grid_size:]
paddle_col = last_row.index(<span class="hljs-number">1.0</span>) <span class="hljs-comment"># Paddle</span>
<span class="hljs-keyword">if</span> ball_col <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">and</span> paddle_col <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
<span class="hljs-keyword">if</span> paddle_col &lt; ball_col:
<span class="hljs-keyword">return</span> <span class="hljs-number">2</span> <span class="hljs-comment"># Move RIGHT</span>
<span class="hljs-keyword">elif</span> paddle_col &gt; ball_col:
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span> <span class="hljs-comment"># Move LEFT</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span> <span class="hljs-comment"># STAY (fallback)</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">LearningPolicy</span>:
<span class="hljs-string">&quot;&quot;&quot;Simulated RL: Epsilon-greedy exploration.&quot;&quot;&quot;</span>
name = <span class="hljs-string">&quot;📈 Learning Agent&quot;</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
self.steps = <span class="hljs-number">0</span>
self.smart_policy = SmartPolicy()
<span class="hljs-keyword">def</span> <span class="hljs-title function_">select_action</span>(<span class="hljs-params">self, obs: OpenSpielObservation</span>) -&gt; <span class="hljs-built_in">int</span>:
self.steps += <span class="hljs-number">1</span>
<span class="hljs-comment"># Decay exploration rate over time</span>
epsilon = <span class="hljs-built_in">max</span>(<span class="hljs-number">0.1</span>, <span class="hljs-number">1.0</span> - (self.steps / <span class="hljs-number">100</span>))
<span class="hljs-keyword">if</span> random.random() &lt; epsilon:
<span class="hljs-comment"># Explore: random action</span>
<span class="hljs-keyword">return</span> random.choice(obs.legal_actions)
<span class="hljs-keyword">else</span>:
<span class="hljs-comment"># Exploit: use smart strategy</span>
<span class="hljs-keyword">return</span> self.smart_policy.select_action(obs)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🤖 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">64</span> + <span class="hljs-string">&quot; 🤖&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; ✅ 4 Policies Created (Adapted for OpenSpiel)!&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🤖 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">64</span> + <span class="hljs-string">&quot; 🤖\\n&quot;</span>)
policies = [RandomPolicy(), AlwaysStayPolicy(), SmartPolicy(), LearningPolicy()]
<span class="hljs-keyword">for</span> i, policy <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(policies, <span class="hljs-number">1</span>):
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot; <span class="hljs-subst">{i}</span>. <span class="hljs-subst">{policy.name}</span>&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n💡 These policies work with OpenSpielObservation!&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Read info_state (flattened grid)&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Use legal_actions&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Work with ANY OpenSpiel game that exposes these!\\n&quot;</span>)`,lang:"python",wrap:!1}}),gs=new r({props:{code:"JUYwJTlGJUE0JTk2JTIwJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTNEJTIwJUYwJTlGJUE0JTk2JTBBJTIwJTIwJTIwJUUyJTlDJTg1JTIwNCUyMFBvbGljaWVzJTIwQ3JlYXRlZCUyMChBZGFwdGVkJTIwZm9yJTIwT3BlblNwaWVsKSElMEElRjAlOUYlQTQlOTYlMjAlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlM0QlMjAlRjAlOUYlQTQlOTYlMEElMEElMjAlMjAlMjAxLiUyMCVGMCU5RiU4RSVCMiUyMFJhbmRvbSUyMEd1ZXNzZXIlMEElMjAlMjAlMjAyLiUyMCVGMCU5RiU5QiU5MSUyMEFsd2F5cyUyMFN0YXklMEElMjAlMjAlMjAzLiUyMCVGMCU5RiVBNyVBMCUyMFNtYXJ0JTIwSGV1cmlzdGljJTBBJTIwJTIwJTIwNC4lMjAlRjAlOUYlOTMlODglMjBMZWFybmluZyUyMEFnZW50JTBBJTBBJUYwJTlGJTkyJUExJTIwVGhlc2UlMjBwb2xpY2llcyUyMHdvcmslMjB3aXRoJTIwT3BlblNwaWVsT2JzZXJ2YXRpb24hJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwUmVhZCUyMGluZm9fc3RhdGUlMjAoZmxhdHRlbmVkJTIwZ3JpZCklMEElMjAlMjAlMjAlRTIlODAlQTIlMjBVc2UlMjBsZWdhbF9hY3Rpb25zJTBBJTIwJTIwJTIwJUUyJTgwJUEyJTIwV29yayUyMHdpdGglMjBBTlklMjBPcGVuU3BpZWwlMjBnYW1lJTIwdGhhdCUyMGV4cG9zZXMlMjB0aGVzZSE=",highlighted:`🤖 ================================================================ 🤖
✅ <span class="hljs-number">4</span> Policies Created (Adapted <span class="hljs-keyword">for</span> OpenSpiel)!
🤖 ================================================================ 🤖
<span class="hljs-number">1.</span> 🎲 Random Guesser
<span class="hljs-number">2.</span> 🛑 <span class="hljs-keyword">Always</span> Stay
<span class="hljs-number">3.</span> 🧠 Smart Heuristic
<span class="hljs-number">4.</span> 📈 Learning Agent
💡 These policies <span class="hljs-keyword">work</span> <span class="hljs-keyword">with</span> OpenSpielObservation!
• <span class="hljs-keyword">Read</span> info_state (flattened grid)
• Use legal_actions
• <span class="hljs-keyword">Work</span> <span class="hljs-keyword">with</span> <span class="hljs-keyword">ANY</span> OpenSpiel game that exposes these!`,lang:"",wrap:!1}}),bs=new I({props:{title:"Part 8: Policy Competition! 🏆",local:"part-8-policy-competition-",headingTag:"h2"}}),ks=new r({props:{code:"ZGVmJTIwZXZhbHVhdGVfcG9saWNpZXMoZW52JTJDJTIwbnVtX2VwaXNvZGVzJTNENTApJTNBJTBBJTIwJTIwJTIwJTIwJTIyJTIyJTIyQ29tcGFyZSUyMGFsbCUyMHBvbGljaWVzJTIwb3ZlciUyMG1hbnklMjBlcGlzb2RlcyUyMHVzaW5nJTIwcmVhbCUyME9wZW5TcGllbC4lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjBwb2xpY2llcyUyMCUzRCUyMCU1QiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMFJhbmRvbVBvbGljeSgpJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwQWx3YXlzU3RheVBvbGljeSgpJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwU21hcnRQb2xpY3koKSUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMExlYXJuaW5nUG9saWN5KCklMkMlMEElMjAlMjAlMjAlMjAlNUQlMEElMEElMjAlMjAlMjAlMjBwcmludCglMjIlNUNuJUYwJTlGJThGJTg2JTIwJTIyJTIwJTJCJTIwJTIyJTNEJTIyKjY2JTIwJTJCJTIwJTIyJTIwJUYwJTlGJThGJTg2JTIyKSUwQSUyMCUyMCUyMCUyMHByaW50KGYlMjIlMjAlMjAlMjBQT0xJQ1klMjBTSE9XRE9XTiUyMC0lMjAlN0JudW1fZXBpc29kZXMlN0QlMjBFcGlzb2RlcyUyMEVhY2glMjIpJTBBJTIwJTIwJTIwJTIwcHJpbnQoZiUyMiUyMCUyMCUyMFBsYXlpbmclMjBhZ2FpbnN0JTIwUkVBTCUyME9wZW5TcGllbCUyMENhdGNoISUyMiklMEElMjAlMjAlMjAlMjBwcmludCglMjIlRjAlOUYlOEYlODYlMjAlMjIlMjAlMkIlMjAlMjIlM0QlMjIqNjYlMjAlMkIlMjAlMjIlMjAlRjAlOUYlOEYlODYlNUNuJTIyKSUwQSUwQSUyMCUyMCUyMCUyMHJlc3VsdHMlMjAlM0QlMjAlNUIlNUQlMEElMjAlMjAlMjAlMjBmb3IlMjBwb2xpY3klMjBpbiUyMHBvbGljaWVzJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcHJpbnQoZiUyMiVFMiU5QSVBMSUyMFRlc3RpbmclMjAlN0Jwb2xpY3kubmFtZSU3RC4uLiUyMiUyQyUyMGVuZCUzRCUyMiUyMCUyMiklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBzdWNjZXNzZXMlMjAlM0QlMjBzdW0ocnVuX2VwaXNvZGUoZW52JTJDJTIwcG9saWN5JTJDJTIwdmlzdWFsaXplJTNERmFsc2UpJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwZm9yJTIwXyUyMGluJTIwcmFuZ2UobnVtX2VwaXNvZGVzKSklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBzdWNjZXNzX3JhdGUlMjAlM0QlMjAoc3VjY2Vzc2VzJTIwJTJGJTIwbnVtX2VwaXNvZGVzKSUyMColMjAxMDAlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXN1bHRzLmFwcGVuZCgocG9saWN5Lm5hbWUlMkMlMjBzdWNjZXNzX3JhdGUlMkMlMjBzdWNjZXNzZXMpKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHByaW50KGYlMjIlRTIlOUMlOTMlMjBEb25lISUyMiklMEElMEElMjAlMjAlMjAlMjBwcmludCglMjIlNUNuJTIyJTIwJTJCJTIwJTIyJTNEJTIyKjcwKSUwQSUyMCUyMCUyMCUyMHByaW50KCUyMiUyMCUyMCUyMCVGMCU5RiU5MyU4QSUyMEZJTkFMJTIwUkVTVUxUUyUyMiklMEElMjAlMjAlMjAlMjBwcmludCglMjIlM0QlMjIqNzAlMjAlMkIlMjAlMjIlNUNuJTIyKSUwQSUwQSUyMCUyMCUyMCUyMCUyMyUyMFNvcnQlMjBieSUyMHN1Y2Nlc3MlMjByYXRlJTIwKGRlc2NlbmRpbmcpJTBBJTIwJTIwJTIwJTIwcmVzdWx0cy5zb3J0KGtleSUzRGxhbWJkYSUyMHglM0ElMjB4JTVCMSU1RCUyQyUyMHJldmVyc2UlM0RUcnVlKSUwQSUwQSUyMCUyMCUyMCUyMCUyMyUyMEF3YXJkJTIwbWVkYWxzJTIwdG8lMjB0b3AlMjAzJTBBJTIwJTIwJTIwJTIwbWVkYWxzJTIwJTNEJTIwJTVCJTIyJUYwJTlGJUE1JTg3JTIyJTJDJTIwJTIyJUYwJTlGJUE1JTg4JTIyJTJDJTIwJTIyJUYwJTlGJUE1JTg5JTIyJTJDJTIwJTIyJTIwJTIwJTIyJTVEJTBBJTBBJTIwJTIwJTIwJTIwZm9yJTIwaSUyQyUyMChuYW1lJTJDJTIwcmF0ZSUyQyUyMHN1Y2Nlc3NlcyklMjBpbiUyMGVudW1lcmF0ZShyZXN1bHRzKSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG1lZGFsJTIwJTNEJTIwbWVkYWxzJTVCaSU1RCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGJhciUyMCUzRCUyMCUyMiVFMiU5NiU4OCUyMiUyMColMjBpbnQocmF0ZSUyMCUyRiUyMDIpJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcHJpbnQoZiUyMiU3Qm1lZGFsJTdEJTIwJTdCbmFtZSUzQTI1cyU3RCUyMCU1QiU3QmJhciUzQSUzQzUwJTdEJTVEJTIwJTdCcmF0ZSUzQTUuMWYlN0QlMjUlMjAoJTdCc3VjY2Vzc2VzJTdEJTJGJTdCbnVtX2VwaXNvZGVzJTdEKSUyMiklMEElMEElMjAlMjAlMjAlMjBwcmludCglMjIlNUNuJTIyJTIwJTJCJTIwJTIyJTNEJTIyKjcwKSUwQSUyMCUyMCUyMCUyMHByaW50KCUyMiU1Q24lRTIlOUMlQTglMjBLZXklMjBJbnNpZ2h0cyUzQSUyMiklMEElMjAlMjAlMjAlMjBwcmludCglMjIlMjAlMjAlMjAlRTIlODAlQTIlMjBSYW5kb20lMjAofjIwJTI1KSUzQSUyMCUyMCUyMCUyMCUyMCUyMEJhc2VsaW5lJTIwLSUyMHB1cmUlMjBsdWNrJTIwJUYwJTlGJThFJUIyJTIyKSUwQSUyMCUyMCUyMCUyMHByaW50KCUyMiUyMCUyMCUyMCVFMiU4MCVBMiUyMEFsd2F5cyUyMFN0YXklMjAofjIwJTI1KSUzQSUyMEJhZCUyMHN0cmF0ZWd5JTIwLSUyMHN0YXlzJTIwY2VudGVyJTIwJUYwJTlGJTlCJTkxJTIyKSUwQSUyMCUyMCUyMCUyMHByaW50KCUyMiUyMCUyMCUyMCVFMiU4MCVBMiUyMFNtYXJ0JTIwKDEwMCUyNSklM0ElMjAlMjAlMjAlMjAlMjAlMjAlMjBPcHRpbWFsJTIwLSUyMHBlcmZlY3QlMjBwbGF5ISUyMCVGMCU5RiVBNyVBMCUyMiklMEElMjAlMjAlMjAlMjBwcmludCglMjIlMjAlMjAlMjAlRTIlODAlQTIlMjBMZWFybmluZyUyMCh+ODUlMjUpJTNBJTIwJTIwJTIwJTIwSW1wcm92ZXMlMjBvdmVyJTIwdGltZSUyMCVGMCU5RiU5MyU4OCUyMiklMEElMjAlMjAlMjAlMjBwcmludCglMjIlNUNuJUYwJTlGJThFJTkzJTIwVGhpcyUyMGlzJTIwUmVpbmZvcmNlbWVudCUyMExlYXJuaW5nJTIwJTJCJTIwT3BlbkVudiUyMGluJTIwYWN0aW9uJTNBJTIyKSUwQSUyMCUyMCUyMCUyMHByaW50KCUyMiUyMCUyMCUyMDEuJTIwV2UlMjBVU0VEJTIwZXhpc3RpbmclMjBPcGVuU3BpZWwlMjBlbnZpcm9ubWVudCUyMChkaWRuJ3QlMjBidWlsZCUyMGl0KSUyMiklMEElMjAlMjAlMjAlMjBwcmludCglMjIlMjAlMjAlMjAyLiUyMFR5cGUtc2FmZSUyMGNvbW11bmljYXRpb24lMjBvdmVyJTIwSFRUUCUyMiklMEElMjAlMjAlMjAlMjBwcmludCglMjIlMjAlMjAlMjAzLiUyMFNhbWUlMjBjb2RlJTIwd29ya3MlMjBmb3IlMjBBTlklMjBPcGVuU3BpZWwlMjBnYW1lJTIyKSUwQSUyMCUyMCUyMCUyMHByaW50KCUyMiUyMCUyMCUyMDQuJTIwUHJvZHVjdGlvbi1yZWFkeSUyMGFyY2hpdGVjdHVyZSU1Q24lMjIpJTBBJTBBJTIzJTIwUnVuJTIwdGhlJTIwZXBpYyUyMGNvbXBldGl0aW9uISUwQXByaW50KCUyMiVGMCU5RiU4RSVBRSUyMFN0YXJ0aW5nJTIwdGhlJTIwc2hvd2Rvd24lMjBhZ2FpbnN0JTIwUkVBTCUyME9wZW5TcGllbC4uLiU1Q24lMjIpJTBBZXZhbHVhdGVfcG9saWNpZXMoY2xpZW50JTJDJTIwbnVtX2VwaXNvZGVzJTNENTAp",highlighted:`<span class="hljs-keyword">def</span> <span class="hljs-title function_">evaluate_policies</span>(<span class="hljs-params">env, num_episodes=<span class="hljs-number">50</span></span>):
<span class="hljs-string">&quot;&quot;&quot;Compare all policies over many episodes using real OpenSpiel.&quot;&quot;&quot;</span>
policies = [
RandomPolicy(),
AlwaysStayPolicy(),
SmartPolicy(),
LearningPolicy(),
]
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n🏆 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">66</span> + <span class="hljs-string">&quot; 🏆&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot; POLICY SHOWDOWN - <span class="hljs-subst">{num_episodes}</span> Episodes Each&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot; Playing against REAL OpenSpiel Catch!&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🏆 &quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">66</span> + <span class="hljs-string">&quot; 🏆\\n&quot;</span>)
results = []
<span class="hljs-keyword">for</span> policy <span class="hljs-keyword">in</span> policies:
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;⚡ Testing <span class="hljs-subst">{policy.name}</span>...&quot;</span>, end=<span class="hljs-string">&quot; &quot;</span>)
successes = <span class="hljs-built_in">sum</span>(run_episode(env, policy, visualize=<span class="hljs-literal">False</span>)
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(num_episodes))
success_rate = (successes / num_episodes) * <span class="hljs-number">100</span>
results.append((policy.name, success_rate, successes))
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;✓ Done!&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n&quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 📊 FINAL RESULTS&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span> + <span class="hljs-string">&quot;\\n&quot;</span>)
<span class="hljs-comment"># Sort by success rate (descending)</span>
results.sort(key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-number">1</span>], reverse=<span class="hljs-literal">True</span>)
<span class="hljs-comment"># Award medals to top 3</span>
medals = [<span class="hljs-string">&quot;🥇&quot;</span>, <span class="hljs-string">&quot;🥈&quot;</span>, <span class="hljs-string">&quot;🥉&quot;</span>, <span class="hljs-string">&quot; &quot;</span>]
<span class="hljs-keyword">for</span> i, (name, rate, successes) <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(results):
medal = medals[i]
bar = <span class="hljs-string">&quot;█&quot;</span> * <span class="hljs-built_in">int</span>(rate / <span class="hljs-number">2</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f&quot;<span class="hljs-subst">{medal}</span> <span class="hljs-subst">{name:25s}</span> [<span class="hljs-subst">{bar:&lt;<span class="hljs-number">50</span>}</span>] <span class="hljs-subst">{rate:<span class="hljs-number">5.1</span>f}</span>% (<span class="hljs-subst">{successes}</span>/<span class="hljs-subst">{num_episodes}</span>)&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n&quot;</span> + <span class="hljs-string">&quot;=&quot;</span>*<span class="hljs-number">70</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n✨ Key Insights:&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Random (~20%): Baseline - pure luck 🎲&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Always Stay (~20%): Bad strategy - stays center 🛑&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Smart (100%): Optimal - perfect play! 🧠&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; • Learning (~85%): Improves over time 📈&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;\\n🎓 This is Reinforcement Learning + OpenEnv in action:&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 1. We USED existing OpenSpiel environment (didn&#x27;t build it)&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 2. Type-safe communication over HTTP&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 3. Same code works for ANY OpenSpiel game&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot; 4. Production-ready architecture\\n&quot;</span>)
<span class="hljs-comment"># Run the epic competition!</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;🎮 Starting the showdown against REAL OpenSpiel...\\n&quot;</span>)
evaluate_policies(client, num_episodes=<span class="hljs-number">50</span>)`,lang:"python",wrap:!1}}),Vs=new I({props:{title:"Part 9: Switching to Other Games 🎮",local:"part-9-switching-to-other-games-",headingTag:"h2"}}),Ss=new I({props:{title:"What We Just Used: Real OpenSpiel! 🎉",local:"what-we-just-used-real-openspiel-",headingTag:"h3"}}),Os=new I({props:{title:"🎮 6 Games Available - Same Interface!",local:"-6-games-available---same-interface",headingTag:"h3"}}),Fs=new r({props:{code:"JTIzJTIwV2UlMjBqdXN0JTIwdXNlZCUyMENhdGNoJTBBZW52JTIwJTNEJTIwT3BlblNwaWVsRW52KGJhc2VfdXJsJTNEJTIyaHR0cCUzQSUyRiUyRmxvY2FsaG9zdCUzQTgwMDAlMjIpJTBBJTIzJTIwZ2FtZV9uYW1lJTNEJTIyY2F0Y2glMjIlMjB3YXMlMjBzZXQlMjB2aWElMjBlbnZpcm9ubWVudCUyMHZhcmlhYmxlJTBBJTBBJTIzJTIwV2FudCUyMFRpYy1UYWMtVG9lJTIwaW5zdGVhZCUzRiUyMEp1c3QlMjBjaGFuZ2UlMjB0aGUlMjBnYW1lISUwQSUyMyUyMFN0YXJ0JTIwc2VydmVyJTIwd2l0aCUzQSUyME9QRU5TUElFTF9HQU1FJTNEdGljX3RhY190b2UlMjB1dmljb3JuJTIwLi4uJTBBJTIzJTIwU2FtZSUyMGNsaWVudCUyMGNvZGUlMjB3b3JrcyE=",highlighted:`<span class="hljs-comment"># We just used Catch</span>
env = OpenSpielEnv(base_url=<span class="hljs-string">&quot;http://localhost:8000&quot;</span>)
<span class="hljs-comment"># game_name=&quot;catch&quot; was set via environment variable</span>
<span class="hljs-comment"># Want Tic-Tac-Toe instead? Just change the game!</span>
<span class="hljs-comment"># Start server with: OPENSPIEL_GAME=tic_tac_toe uvicorn ...</span>
<span class="hljs-comment"># Same client code works!</span>`,lang:"python",wrap:!1}}),xs=new I({props:{title:"Try Another Game (Optional):",local:"try-another-game-optional",headingTag:"h3"}}),zs=new r({props:{code:"JTIzJTIwU3RvcCUyMHRoZSUyMGN1cnJlbnQlMjBzZXJ2ZXIlMjAoa2lsbCUyMHRoZSUyMHNlcnZlcl9wcm9jZXNzKSUwQSUyMyUyMFRoZW4lMjBzdGFydCUyMGElMjBuZXclMjBnYW1lJTNBJTBBJTBBc2VydmVyX3Byb2Nlc3MlMjAlM0QlMjBzdWJwcm9jZXNzLlBvcGVuKCUwQSUyMCUyMCUyMCUyMCU1QnN5cy5leGVjdXRhYmxlJTJDJTIwJTIyLW0lMjIlMkMlMjAlMjJ1dmljb3JuJTIyJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIyZW52cy5vcGVuc3BpZWxfZW52LnNlcnZlci5hcHAlM0FhcHAlMjIlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjItLWhvc3QlMjIlMkMlMjAlMjIwLjAuMC4wJTIyJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIyLS1wb3J0JTIyJTJDJTIwJTIyODAwMCUyMiU1RCUyQyUwQSUyMCUyMCUyMCUyMGVudiUzRCU3Qioqb3MuZW52aXJvbiUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMlBZVEhPTlBBVEglMjIlM0ElMjBmJTIyJTdCd29ya19kaXIlN0QlMkZzcmMlMjIlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJPUEVOU1BJRUxfR0FNRSUyMiUzQSUyMCUyMnRpY190YWNfdG9lJTIyJTJDJTIwJTIwJTIzJTIwQ2hhbmdlZCElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjJPUEVOU1BJRUxfQUdFTlRfUExBWUVSJTIyJTNBJTIwJTIyMCUyMiUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMk9QRU5TUElFTF9PUFBPTkVOVF9QT0xJQ1klMjIlM0ElMjAlMjJyYW5kb20lMjIlN0QlMkMlMEElMjAlMjAlMjAlMjAlMjMlMjAuLi4lMjByZXN0JTIwb2YlMjBjb25maWclMEEpJTBBJTBBJTIzJTIwU2FtZSUyMGNsaWVudCUyMHdvcmtzISUwQWNsaWVudCUyMCUzRCUyME9wZW5TcGllbEVudihiYXNlX3VybCUzRCUyMmh0dHAlM0ElMkYlMkZsb2NhbGhvc3QlM0E4MDAwJTIyKSUwQXJlc3VsdCUyMCUzRCUyMGNsaWVudC5yZXNldCgpJTIwJTIwJTIzJTIwTm93JTIwcGxheWluZyUyMFRpYy1UYWMtVG9lIQ==",highlighted:`<span class="hljs-comment"># Stop the current server (kill the server_process)</span>
<span class="hljs-comment"># Then start a new game:</span>
server_process = subprocess.Popen(
[sys.executable, <span class="hljs-string">&quot;-m&quot;</span>, <span class="hljs-string">&quot;uvicorn&quot;</span>,
<span class="hljs-string">&quot;envs.openspiel_env.server.app:app&quot;</span>,
<span class="hljs-string">&quot;--host&quot;</span>, <span class="hljs-string">&quot;0.0.0.0&quot;</span>,
<span class="hljs-string">&quot;--port&quot;</span>, <span class="hljs-string">&quot;8000&quot;</span>],
env={**os.environ,
<span class="hljs-string">&quot;PYTHONPATH&quot;</span>: <span class="hljs-string">f&quot;<span class="hljs-subst">{work_dir}</span>/src&quot;</span>,
<span class="hljs-string">&quot;OPENSPIEL_GAME&quot;</span>: <span class="hljs-string">&quot;tic_tac_toe&quot;</span>, <span class="hljs-comment"># Changed!</span>
<span class="hljs-string">&quot;OPENSPIEL_AGENT_PLAYER&quot;</span>: <span class="hljs-string">&quot;0&quot;</span>,
<span class="hljs-string">&quot;OPENSPIEL_OPPONENT_POLICY&quot;</span>: <span class="hljs-string">&quot;random&quot;</span>},
<span class="hljs-comment"># ... rest of config</span>
)
<span class="hljs-comment"># Same client works!</span>
client = OpenSpielEnv(base_url=<span class="hljs-string">&quot;http://localhost:8000&quot;</span>)
result = client.reset() <span class="hljs-comment"># Now playing Tic-Tac-Toe!</span>`,lang:"python",wrap:!1}}),Xs=new I({props:{title:"Part 10: Create Your Own Integration 🛠️",local:"part-10-create-your-own-integration-",headingTag:"h2"}}),Ds=new I({props:{title:"The 5-Step Pattern",local:"the-5-step-pattern",headingTag:"h3"}}),Ls=new I({props:{title:"Step 1: Define Types ( models.py )",local:"step-1-define-types--modelspy-",headingTag:"h3"}}),Ps=new r({props:{code:"ZnJvbSUyMGRhdGFjbGFzc2VzJTIwaW1wb3J0JTIwZGF0YWNsYXNzJTBBZnJvbSUyMGNvcmUuZW52X3NlcnZlciUyMGltcG9ydCUyMEFjdGlvbiUyQyUyME9ic2VydmF0aW9uJTJDJTIwU3RhdGUlMEElMEElNDBkYXRhY2xhc3MlMEFjbGFzcyUyMFlvdXJBY3Rpb24oQWN0aW9uKSUzQSUwQSUyMCUyMCUyMCUyMGFjdGlvbl92YWx1ZSUzQSUyMGludCUwQSUyMCUyMCUyMCUyMCUyMyUyMEFkZCUyMHlvdXIlMjBhY3Rpb24lMjBmaWVsZHMlMEElMEElNDBkYXRhY2xhc3MlMEFjbGFzcyUyMFlvdXJPYnNlcnZhdGlvbihPYnNlcnZhdGlvbiklM0ElMEElMjAlMjAlMjAlMjBzdGF0ZV9kYXRhJTNBJTIwTGlzdCU1QmZsb2F0JTVEJTBBJTIwJTIwJTIwJTIwZG9uZSUzQSUyMGJvb2wlMEElMjAlMjAlMjAlMjByZXdhcmQlM0ElMjBmbG9hdCUwQSUyMCUyMCUyMCUyMCUyMyUyMEFkZCUyMHlvdXIlMjBvYnNlcnZhdGlvbiUyMGZpZWxkcyUwQSUwQSU0MGRhdGFjbGFzcyUwQWNsYXNzJTIwWW91clN0YXRlKFN0YXRlKSUzQSUwQSUyMCUyMCUyMCUyMGVwaXNvZGVfaWQlM0ElMjBzdHIlMEElMjAlMjAlMjAlMjBzdGVwX2NvdW50JTNBJTIwaW50JTBBJTIwJTIwJTIwJTIwJTIzJTIwQWRkJTIweW91ciUyMHN0YXRlJTIwZmllbGRz",highlighted:`<span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> dataclass
<span class="hljs-keyword">from</span> core.env_server <span class="hljs-keyword">import</span> Action, Observation, State
<span class="hljs-meta">@dataclass</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">YourAction</span>(<span class="hljs-title class_ inherited__">Action</span>):
action_value: <span class="hljs-built_in">int</span>
<span class="hljs-comment"># Add your action fields</span>
<span class="hljs-meta">@dataclass</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">YourObservation</span>(<span class="hljs-title class_ inherited__">Observation</span>):
state_data: <span class="hljs-type">List</span>[<span class="hljs-built_in">float</span>]
done: <span class="hljs-built_in">bool</span>
reward: <span class="hljs-built_in">float</span>
<span class="hljs-comment"># Add your observation fields</span>
<span class="hljs-meta">@dataclass</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">YourState</span>(<span class="hljs-title class_ inherited__">State</span>):
episode_id: <span class="hljs-built_in">str</span>
step_count: <span class="hljs-built_in">int</span>
<span class="hljs-comment"># Add your state fields</span>`,lang:"python",wrap:!1}}),Ks=new I({props:{title:"Step 2: Implement Environment ( server/environment.py )",local:"step-2-implement-environment--serverenvironmentpy-",headingTag:"h3"}}),lt=new r({props:{code:"ZnJvbSUyMGNvcmUuZW52X3NlcnZlciUyMGltcG9ydCUyMEVudmlyb25tZW50JTBBJTBBY2xhc3MlMjBZb3VyRW52aXJvbm1lbnQoRW52aXJvbm1lbnQpJTNBJTBBJTIwJTIwJTIwJTIwZGVmJTIwcmVzZXQoc2VsZiklMjAtJTNFJTIwT2JzZXJ2YXRpb24lM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjMlMjBJbml0aWFsaXplJTIweW91ciUyMGdhbWUlMkZzaW11bGF0aW9uJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwWW91ck9ic2VydmF0aW9uKC4uLiklMEElMEElMjAlMjAlMjAlMjBkZWYlMjBzdGVwKHNlbGYlMkMlMjBhY3Rpb24lM0ElMjBBY3Rpb24pJTIwLSUzRSUyME9ic2VydmF0aW9uJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwRXhlY3V0ZSUyMGFjdGlvbiUyQyUyMHVwZGF0ZSUyMHN0YXRlJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwWW91ck9ic2VydmF0aW9uKC4uLiklMEElMEElMjAlMjAlMjAlMjAlNDBwcm9wZXJ0eSUwQSUyMCUyMCUyMCUyMGRlZiUyMHN0YXRlKHNlbGYpJTIwLSUzRSUyMFN0YXRlJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwc2VsZi5fc3RhdGU=",highlighted:`<span class="hljs-keyword">from</span> core.env_server <span class="hljs-keyword">import</span> Environment
<span class="hljs-keyword">class</span> <span class="hljs-title class_">YourEnvironment</span>(<span class="hljs-title class_ inherited__">Environment</span>):
<span class="hljs-keyword">def</span> <span class="hljs-title function_">reset</span>(<span class="hljs-params">self</span>) -&gt; Observation:
<span class="hljs-comment"># Initialize your game/simulation</span>
<span class="hljs-keyword">return</span> YourObservation(...)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">step</span>(<span class="hljs-params">self, action: Action</span>) -&gt; Observation:
<span class="hljs-comment"># Execute action, update state</span>
<span class="hljs-keyword">return</span> YourObservation(...)
<span class="hljs-meta"> @property</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">state</span>(<span class="hljs-params">self</span>) -&gt; State:
<span class="hljs-keyword">return</span> self._state`,lang:"python",wrap:!1}}),st=new I({props:{title:"Step 3: Create Client ( client.py )",local:"step-3-create-client--clientpy-",headingTag:"h3"}}),tt=new r({props:{code:"ZnJvbSUyMGNvcmUuaHR0cF9lbnZfY2xpZW50JTIwaW1wb3J0JTIwSFRUUEVudkNsaWVudCUwQWZyb20lMjBjb3JlLnR5cGVzJTIwaW1wb3J0JTIwU3RlcFJlc3VsdCUwQSUwQWNsYXNzJTIwWW91ckVudihIVFRQRW52Q2xpZW50JTVCWW91ckFjdGlvbiUyQyUyMFlvdXJPYnNlcnZhdGlvbiU1RCklM0ElMEElMjAlMjAlMjAlMjBkZWYlMjBfc3RlcF9wYXlsb2FkKHNlbGYlMkMlMjBhY3Rpb24lM0ElMjBZb3VyQWN0aW9uKSUyMC0lM0UlMjBkaWN0JTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIyJTIyJTIyQ29udmVydCUyMGFjdGlvbiUyMHRvJTIwSlNPTiUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMCU3QiUyMmFjdGlvbl92YWx1ZSUyMiUzQSUyMGFjdGlvbi5hY3Rpb25fdmFsdWUlN0QlMEElMEElMjAlMjAlMjAlMjBkZWYlMjBfcGFyc2VfcmVzdWx0KHNlbGYlMkMlMjBwYXlsb2FkJTNBJTIwZGljdCklMjAtJTNFJTIwU3RlcFJlc3VsdCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMiUyMiUyMlBhcnNlJTIwSlNPTiUyMHRvJTIwb2JzZXJ2YXRpb24lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjBTdGVwUmVzdWx0KCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG9ic2VydmF0aW9uJTNEWW91ck9ic2VydmF0aW9uKC4uLiklMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXdhcmQlM0RwYXlsb2FkJTVCJ3Jld2FyZCclNUQlMkMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBkb25lJTNEcGF5bG9hZCU1Qidkb25lJyU1RCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCklMEElMEElMjAlMjAlMjAlMjBkZWYlMjBfcGFyc2Vfc3RhdGUoc2VsZiUyQyUyMHBheWxvYWQlM0ElMjBkaWN0KSUyMC0lM0UlMjBZb3VyU3RhdGUlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjBZb3VyU3RhdGUoLi4uKQ==",highlighted:`<span class="hljs-keyword">from</span> core.http_env_client <span class="hljs-keyword">import</span> HTTPEnvClient
<span class="hljs-keyword">from</span> core.types <span class="hljs-keyword">import</span> StepResult
<span class="hljs-keyword">class</span> <span class="hljs-title class_">YourEnv</span>(HTTPEnvClient[YourAction, YourObservation]):
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_step_payload</span>(<span class="hljs-params">self, action: YourAction</span>) -&gt; <span class="hljs-built_in">dict</span>:
<span class="hljs-string">&quot;&quot;&quot;Convert action to JSON&quot;&quot;&quot;</span>
<span class="hljs-keyword">return</span> {<span class="hljs-string">&quot;action_value&quot;</span>: action.action_value}
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_parse_result</span>(<span class="hljs-params">self, payload: <span class="hljs-built_in">dict</span></span>) -&gt; StepResult:
<span class="hljs-string">&quot;&quot;&quot;Parse JSON to observation&quot;&quot;&quot;</span>
<span class="hljs-keyword">return</span> StepResult(
observation=YourObservation(...),
reward=payload[<span class="hljs-string">&#x27;reward&#x27;</span>],
done=payload[<span class="hljs-string">&#x27;done&#x27;</span>]
)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_parse_state</span>(<span class="hljs-params">self, payload: <span class="hljs-built_in">dict</span></span>) -&gt; YourState:
<span class="hljs-keyword">return</span> YourState(...)`,lang:"python",wrap:!1}}),Tt=new I({props:{title:"Step 4: Create Server ( server/app.py )",local:"step-4-create-server--serverapppy-",headingTag:"h3"}}),Jt=new r({props:{code:"ZnJvbSUyMGNvcmUuZW52X3NlcnZlciUyMGltcG9ydCUyMGNyZWF0ZV9mYXN0YXBpX2FwcCUwQWZyb20lMjAueW91cl9lbnZpcm9ubWVudCUyMGltcG9ydCUyMFlvdXJFbnZpcm9ubWVudCUwQSUwQWVudiUyMCUzRCUyMFlvdXJFbnZpcm9ubWVudCgpJTBBYXBwJTIwJTNEJTIwY3JlYXRlX2Zhc3RhcGlfYXBwKGVudiklMEElMEElMjMlMjBUaGF0J3MlMjBpdCElMjBPcGVuRW52JTIwY3JlYXRlcyUyMGFsbCUyMGVuZHBvaW50cyUyMGZvciUyMHlvdS4=",highlighted:`<span class="hljs-keyword">from</span> core.env_server <span class="hljs-keyword">import</span> create_fastapi_app
<span class="hljs-keyword">from</span> .your_environment <span class="hljs-keyword">import</span> YourEnvironment
env = YourEnvironment()
app = create_fastapi_app(env)
<span class="hljs-comment"># That&#x27;s it! OpenEnv creates all endpoints for you.</span>`,lang:"python",wrap:!1}}),et=new I({props:{title:"Step 5: Dockerize ( server/Dockerfile )",local:"step-5-dockerize--serverdockerfile-",headingTag:"h3"}}),nt=new r({props:{code:"RlJPTSUyMHB5dGhvbiUzQTMuMTEtc2xpbSUwQSUwQVdPUktESVIlMjAlMkZhcHAlMEFDT1BZJTIwcmVxdWlyZW1lbnRzLnR4dCUyMC4lMEFSVU4lMjBwaXAlMjBpbnN0YWxsJTIwLS1uby1jYWNoZS1kaXIlMjAtciUyMHJlcXVpcmVtZW50cy50eHQlMEElMEFDT1BZJTIwLiUyMC4lMEFDTUQlMjAlNUIlMjJ1dmljb3JuJTIyJTJDJTIwJTIyYXBwJTNBYXBwJTIyJTJDJTIwJTIyLS1ob3N0JTIyJTJDJTIwJTIyMC4wLjAuMCUyMiUyQyUyMCUyMi0tcG9ydCUyMiUyQyUyMCUyMjgwMDAlMjIlNUQ=",highlighted:`<span class="hljs-keyword">FROM</span> python:<span class="hljs-number">3.11</span>-slim
<span class="hljs-keyword">WORKDIR</span><span class="language-bash"> /app</span>
<span class="hljs-keyword">COPY</span><span class="language-bash"> requirements.txt .</span>
<span class="hljs-keyword">RUN</span><span class="language-bash"> pip install --no-cache-dir -r requirements.txt</span>
<span class="hljs-keyword">COPY</span><span class="language-bash"> . .</span>
<span class="hljs-keyword">CMD</span><span class="language-bash"> [<span class="hljs-string">&quot;uvicorn&quot;</span>, <span class="hljs-string">&quot;app:app&quot;</span>, <span class="hljs-string">&quot;--host&quot;</span>, <span class="hljs-string">&quot;0.0.0.0&quot;</span>, <span class="hljs-string">&quot;--port&quot;</span>, <span class="hljs-string">&quot;8000&quot;</span>]</span>`,lang:"dockerfile",wrap:!1}}),Mt=new I({props:{title:"🎓 Examples to Study",local:"-examples-to-study",headingTag:"h3"}}),pt=new I({props:{title:"🎓 Summary: Your Journey",local:"-summary-your-journey",headingTag:"h2"}}),wt=new I({props:{title:"What You Learned",local:"what-you-learned",headingTag:"h3"}}),It=new I({props:{title:"📚 Concepts",local:"-concepts",headingTag:"h3"}}),ot=new I({props:{title:"🛠️ Skills",local:"-skills",headingTag:"h3"}}),rt=new I({props:{title:"OpenEnv vs Traditional RL",local:"openenv-vs-traditional-rl",headingTag:"h3"}}),Nt=new I({props:{title:"📚 Resources",local:"-resources",headingTag:"h2"}}),ht=new I({props:{title:"🔗 Essential Links",local:"-essential-links",headingTag:"h3"}}),dt=new I({props:{title:"📖 Documentation Deep Dives",local:"-documentation-deep-dives",headingTag:"h3"}}),At=new I({props:{title:"🎓 Community & Support",local:"-community--support",headingTag:"h3"}}),ft=new I({props:{title:"🌈 What’s Next?",local:"-whats-next",headingTag:"h3"}}),Gt=new Aa({props:{source:"https://github.com/huggingface/openenv/blob/main/docs/source/tutorials/openenv-tutorial.md"}}),{c(){g=n("meta"),MT=J(),eT=n("p"),UT=J(),a(Q.$$.fragment),aT=J(),a(k.$$.fragment),iT=J(),u=n("div"),R=n("img"),zn=J(),a(V.$$.fragment),Hn=J(),Ot=n("p"),Ot.innerHTML=IM,_n=J(),Zt=n("p"),Zt.textContent=oM,Xn=J(),Ft=n("p"),Ft.innerHTML=rM,Dn=J(),Wt=n("p"),Wt.textContent=CM,yT=J(),a(S.$$.fragment),pT=J(),f=n("p"),f.textContent=cM,wT=J(),v=n("p"),v.textContent=EM,jT=J(),G=n("p"),G.textContent=uM,IT=J(),O=n("p"),O.textContent=NM,oT=J(),Z=n("p"),Z.textContent=hM,rT=J(),F=n("p"),F.textContent=mM,CT=J(),W=n("p"),W.textContent=dM,cT=J(),Y=n("p"),Y.textContent=gM,ET=J(),$=n("p"),$.textContent=AM,uT=J(),NT=n("hr"),hT=J(),a(x.$$.fragment),mT=J(),z=n("table"),z.innerHTML=bM,dT=J(),H=n("p"),H.textContent=BM,gT=J(),_=n("p"),_.innerHTML=QM,AT=J(),bT=n("hr"),BT=J(),a(X.$$.fragment),QT=J(),a(D.$$.fragment),kT=J(),q=n("ul"),q.innerHTML=kM,RT=J(),a(L.$$.fragment),VT=J(),P=n("ul"),P.innerHTML=RM,ST=J(),a(K.$$.fragment),fT=J(),ll=n("ul"),ll.innerHTML=VM,vT=J(),a(sl.$$.fragment),GT=J(),tl=n("ul"),tl.innerHTML=SM,OT=J(),a(Tl.$$.fragment),ZT=J(),Jl=n("ul"),Jl.innerHTML=fM,FT=J(),WT=n("hr"),YT=J(),el=n("p"),el.textContent=vM,$T=J(),a(nl.$$.fragment),xT=J(),Ml=n("p"),Ml.innerHTML=GM,zT=J(),Ul=n("p"),Ul.textContent=OM,HT=J(),a(al.$$.fragment),_T=J(),il=n("p"),il.textContent=ZM,XT=J(),yl=n("p"),yl.textContent=FM,DT=J(),a(pl.$$.fragment),qT=J(),wl=n("p"),wl.innerHTML=WM,LT=J(),a(jl.$$.fragment),PT=J(),KT=n("hr"),lJ=J(),Il=n("p"),Il.textContent=YM,sJ=J(),a(ol.$$.fragment),tJ=J(),a(rl.$$.fragment),TJ=J(),Cl=n("p"),Cl.textContent=$M,JJ=J(),cl=n("table"),cl.innerHTML=xM,eJ=J(),a(El.$$.fragment),nJ=J(),ul=n("p"),ul.innerHTML=zM,MJ=J(),Nl=n("p"),Nl.textContent=HM,UJ=J(),hl=n("ul"),hl.innerHTML=_M,aJ=J(),a(ml.$$.fragment),iJ=J(),a(dl.$$.fragment),yJ=J(),gl=n("p"),gl.textContent=XM,pJ=J(),a(Al.$$.fragment),wJ=J(),bl=n("p"),bl.innerHTML=DM,jJ=J(),a(Bl.$$.fragment),IJ=J(),oJ=n("hr"),rJ=J(),Ql=n("p"),Ql.textContent=qM,CJ=J(),a(kl.$$.fragment),cJ=J(),a(Rl.$$.fragment),EJ=J(),a(Vl.$$.fragment),uJ=J(),Sl=n("p"),Sl.textContent=LM,NJ=J(),a(fl.$$.fragment),hJ=J(),vl=n("p"),vl.innerHTML=PM,mJ=J(),a(Gl.$$.fragment),dJ=J(),gJ=n("hr"),AJ=J(),Ol=n("p"),Ol.textContent=KM,bJ=J(),a(Zl.$$.fragment),BJ=J(),a(Fl.$$.fragment),QJ=J(),Wl=n("p"),Wl.innerHTML=lU,kJ=J(),a(Yl.$$.fragment),RJ=J(),$l=n("p"),$l.innerHTML=sU,VJ=J(),xl=n("table"),xl.innerHTML=tU,SJ=J(),zl=n("p"),zl.innerHTML=TU,fJ=J(),a(Hl.$$.fragment),vJ=J(),_l=n("p"),_l.innerHTML=JU,GJ=J(),a(Xl.$$.fragment),OJ=J(),a(Dl.$$.fragment),ZJ=J(),a(ql.$$.fragment),FJ=J(),Ll=n("p"),Ll.innerHTML=eU,WJ=J(),a(Pl.$$.fragment),YJ=J(),a(Kl.$$.fragment),$J=J(),ls=n("p"),ls.innerHTML=nU,xJ=J(),ss=n("ol"),ss.innerHTML=MU,zJ=J(),ts=n("p"),ts.textContent=UU,HJ=J(),_J=n("hr"),XJ=J(),Ts=n("p"),Ts.textContent=aU,DJ=J(),a(Js.$$.fragment),qJ=J(),C=n("div"),a(es.$$.fragment),qn=J(),Yt=n("p"),Yt.innerHTML=iU,Ln=J(),$t=n("p"),$t.textContent=yU,Pn=J(),xt=n("p"),xt.innerHTML=pU,Kn=J(),zt=n("ul"),zt.innerHTML=wU,LJ=J(),a(ns.$$.fragment),PJ=J(),a(Ms.$$.fragment),KJ=J(),Us=n("p"),Us.innerHTML=jU,le=J(),as=n("ul"),as.innerHTML=IU,se=J(),is=n("p"),is.innerHTML=oU,te=J(),ys=n("ul"),ys.innerHTML=rU,Te=J(),ps=n("p"),ps.innerHTML=CU,Je=J(),ws=n("ul"),ws.innerHTML=cU,ee=J(),js=n("p"),js.textContent=EU,ne=J(),Is=n("ul"),Is.innerHTML=uU,Me=J(),a(os.$$.fragment),Ue=J(),rs=n("p"),rs.innerHTML=NU,ae=J(),a(Cs.$$.fragment),ie=J(),ye=n("hr"),pe=J(),cs=n("p"),cs.textContent=hU,we=J(),a(Es.$$.fragment),je=J(),us=n("p"),us.textContent=mU,Ie=J(),Ns=n("table"),Ns.innerHTML=dU,oe=J(),hs=n("p"),hs.innerHTML=gU,re=J(),a(ms.$$.fragment),Ce=J(),ds=n("p"),ds.innerHTML=AU,ce=J(),a(gs.$$.fragment),Ee=J(),ue=n("hr"),Ne=J(),As=n("p"),As.textContent=bU,he=J(),a(bs.$$.fragment),me=J(),Bs=n("p"),Bs.innerHTML=BU,de=J(),Qs=n("p"),Qs.textContent=QU,ge=J(),a(ks.$$.fragment),Ae=J(),be=n("hr"),Be=J(),Rs=n("p"),Rs.textContent=kU,Qe=J(),a(Vs.$$.fragment),ke=J(),a(Ss.$$.fragment),Re=J(),fs=n("p"),fs.innerHTML=RU,Ve=J(),vs=n("table"),vs.innerHTML=VU,Se=J(),Gs=n("p"),Gs.innerHTML=SU,fe=J(),a(Os.$$.fragment),ve=J(),Zs=n("p"),Zs.innerHTML=fU,Ge=J(),a(Fs.$$.fragment),Oe=J(),Ws=n("p"),Ws.innerHTML=vU,Ze=J(),Ys=n("ol"),Ys.innerHTML=GU,Fe=J(),$s=n("p"),$s.innerHTML=OU,We=J(),a(xs.$$.fragment),Ye=J(),a(zs.$$.fragment),$e=J(),Hs=n("p"),Hs.innerHTML=ZU,xe=J(),ze=n("hr"),He=J(),_s=n("p"),_s.textContent=FU,_e=J(),a(Xs.$$.fragment),Xe=J(),a(Ds.$$.fragment),De=J(),qs=n("p"),qs.textContent=WU,qe=J(),a(Ls.$$.fragment),Le=J(),a(Ps.$$.fragment),Pe=J(),a(Ks.$$.fragment),Ke=J(),a(lt.$$.fragment),ln=J(),a(st.$$.fragment),sn=J(),a(tt.$$.fragment),tn=J(),a(Tt.$$.fragment),Tn=J(),a(Jt.$$.fragment),Jn=J(),a(et.$$.fragment),en=J(),a(nt.$$.fragment),nn=J(),a(Mt.$$.fragment),Mn=J(),Ut=n("p"),Ut.textContent=YU,Un=J(),at=n("ol"),at.innerHTML=$U,an=J(),it=n("p"),it.innerHTML=xU,yn=J(),pn=n("hr"),wn=J(),yt=n("p"),yt.textContent=zU,jn=J(),a(pt.$$.fragment),In=J(),a(wt.$$.fragment),on=J(),Ht=n("table"),jt=n("tr"),c=n("td"),a(It.$$.fragment),lM=J(),_t=n("p"),_t.innerHTML=HU,sM=J(),Xt=n("ul"),Xt.innerHTML=_U,tM=J(),Dt=n("p"),Dt.innerHTML=XU,TM=J(),qt=n("ul"),qt.innerHTML=DU,JM=J(),Lt=n("p"),Lt.innerHTML=qU,eM=J(),Pt=n("ul"),Pt.innerHTML=LU,nM=J(),E=n("td"),a(ot.$$.fragment),MM=J(),Kt=n("p"),Kt.innerHTML=PU,UM=J(),lT=n("ul"),lT.innerHTML=KU,aM=J(),sT=n("p"),sT.innerHTML=la,iM=J(),tT=n("ul"),tT.innerHTML=sa,yM=J(),TT=n("p"),TT.innerHTML=ta,pM=J(),JT=n("ul"),JT.innerHTML=Ta,rn=J(),a(rt.$$.fragment),Cn=J(),Ct=n("table"),Ct.innerHTML=Ja,cn=J(),ct=n("p"),ct.innerHTML=ea,En=J(),Et=n("ul"),Et.innerHTML=na,un=J(),Nn=n("hr"),hn=J(),ut=n("p"),ut.textContent=Ma,mn=J(),a(Nt.$$.fragment),dn=J(),a(ht.$$.fragment),gn=J(),mt=n("ul"),mt.innerHTML=Ua,An=J(),a(dt.$$.fragment),bn=J(),gt=n("ul"),gt.innerHTML=aa,Bn=J(),a(At.$$.fragment),Qn=J(),bt=n("p"),bt.innerHTML=ia,kn=J(),Bt=n("ul"),Bt.innerHTML=ya,Rn=J(),Qt=n("p"),Qt.innerHTML=pa,Vn=J(),kt=n("ul"),kt.innerHTML=wa,Sn=J(),Rt=n("p"),Rt.textContent=ja,fn=J(),Vt=n("p"),Vt.innerHTML=Ia,vn=J(),St=n("p"),St.innerHTML=oa,Gn=J(),On=n("hr"),Zn=J(),a(ft.$$.fragment),Fn=J(),vt=n("ol"),vt.innerHTML=ra,Wn=J(),a(Gt.$$.fragment),Yn=J(),nT=n("p"),this.h()},l(l){const s=da("svelte-u9bgzb",document.head);g=M(s,"META",{name:!0,content:!0}),s.forEach(t),MT=e(l),eT=M(l,"P",{}),A(eT).forEach(t),UT=e(l),i(Q.$$.fragment,l),aT=e(l),i(k.$$.fragment,l),iT=e(l),u=M(l,"DIV",{align:!0});var m=A(u);R=M(m,"IMG",{src:!0,width:!0,alt:!0}),zn=e(m),i(V.$$.fragment,m),Hn=e(m),Ot=M(m,"P",{"data-svelte-h":!0}),U(Ot)!=="svelte-dqwr3"&&(Ot.innerHTML=IM),_n=e(m),Zt=M(m,"P",{"data-svelte-h":!0}),U(Zt)!=="svelte-1dgvh9j"&&(Zt.textContent=oM),Xn=e(m),Ft=M(m,"P",{"data-svelte-h":!0}),U(Ft)!=="svelte-10npbdt"&&(Ft.innerHTML=rM),Dn=e(m),Wt=M(m,"P",{"data-svelte-h":!0}),U(Wt)!=="svelte-wo7gof"&&(Wt.textContent=CM),m.forEach(t),yT=e(l),i(S.$$.fragment,l),pT=e(l),f=M(l,"P",{"data-svelte-h":!0}),U(f)!=="svelte-147i8a1"&&(f.textContent=cM),wT=e(l),v=M(l,"P",{"data-svelte-h":!0}),U(v)!=="svelte-1mep8fs"&&(v.textContent=EM),jT=e(l),G=M(l,"P",{"data-svelte-h":!0}),U(G)!=="svelte-3h5zwk"&&(G.textContent=uM),IT=e(l),O=M(l,"P",{"data-svelte-h":!0}),U(O)!=="svelte-1pwvial"&&(O.textContent=NM),oT=e(l),Z=M(l,"P",{"data-svelte-h":!0}),U(Z)!=="svelte-u3ba3d"&&(Z.textContent=hM),rT=e(l),F=M(l,"P",{"data-svelte-h":!0}),U(F)!=="svelte-13dejvb"&&(F.textContent=mM),CT=e(l),W=M(l,"P",{"data-svelte-h":!0}),U(W)!=="svelte-a6sebp"&&(W.textContent=dM),cT=e(l),Y=M(l,"P",{"data-svelte-h":!0}),U(Y)!=="svelte-1t9nmmv"&&(Y.textContent=gM),ET=e(l),$=M(l,"P",{"data-svelte-h":!0}),U($)!=="svelte-1wh8n1a"&&($.textContent=AM),uT=e(l),NT=M(l,"HR",{}),hT=e(l),i(x.$$.fragment,l),mT=e(l),z=M(l,"TABLE",{"data-svelte-h":!0}),U(z)!=="svelte-1ujwz7q"&&(z.innerHTML=bM),dT=e(l),H=M(l,"P",{"data-svelte-h":!0}),U(H)!=="svelte-1wlgfct"&&(H.textContent=BM),gT=e(l),_=M(l,"P",{"data-svelte-h":!0}),U(_)!=="svelte-xqa9wu"&&(_.innerHTML=QM),AT=e(l),bT=M(l,"HR",{}),BT=e(l),i(X.$$.fragment,l),QT=e(l),i(D.$$.fragment,l),kT=e(l),q=M(l,"UL",{"data-svelte-h":!0}),U(q)!=="svelte-16zxjx5"&&(q.innerHTML=kM),RT=e(l),i(L.$$.fragment,l),VT=e(l),P=M(l,"UL",{"data-svelte-h":!0}),U(P)!=="svelte-1phxpcb"&&(P.innerHTML=RM),ST=e(l),i(K.$$.fragment,l),fT=e(l),ll=M(l,"UL",{"data-svelte-h":!0}),U(ll)!=="svelte-412jsu"&&(ll.innerHTML=VM),vT=e(l),i(sl.$$.fragment,l),GT=e(l),tl=M(l,"UL",{"data-svelte-h":!0}),U(tl)!=="svelte-whbwpr"&&(tl.innerHTML=SM),OT=e(l),i(Tl.$$.fragment,l),ZT=e(l),Jl=M(l,"UL",{"data-svelte-h":!0}),U(Jl)!=="svelte-1rdx1k6"&&(Jl.innerHTML=fM),FT=e(l),WT=M(l,"HR",{}),YT=e(l),el=M(l,"P",{"data-svelte-h":!0}),U(el)!=="svelte-1ytaih1"&&(el.textContent=vM),$T=e(l),i(nl.$$.fragment,l),xT=e(l),Ml=M(l,"P",{"data-svelte-h":!0}),U(Ml)!=="svelte-1sra4qo"&&(Ml.innerHTML=GM),zT=e(l),Ul=M(l,"P",{"data-svelte-h":!0}),U(Ul)!=="svelte-1hq0szu"&&(Ul.textContent=OM),HT=e(l),i(al.$$.fragment,l),_T=e(l),il=M(l,"P",{"data-svelte-h":!0}),U(il)!=="svelte-12623bd"&&(il.textContent=ZM),XT=e(l),yl=M(l,"P",{"data-svelte-h":!0}),U(yl)!=="svelte-se3du"&&(yl.textContent=FM),DT=e(l),i(pl.$$.fragment,l),qT=e(l),wl=M(l,"P",{"data-svelte-h":!0}),U(wl)!=="svelte-1mvdyro"&&(wl.innerHTML=WM),LT=e(l),i(jl.$$.fragment,l),PT=e(l),KT=M(l,"HR",{}),lJ=e(l),Il=M(l,"P",{"data-svelte-h":!0}),U(Il)!=="svelte-5oozyk"&&(Il.textContent=YM),sJ=e(l),i(ol.$$.fragment,l),tJ=e(l),i(rl.$$.fragment,l),TJ=e(l),Cl=M(l,"P",{"data-svelte-h":!0}),U(Cl)!=="svelte-i67p0s"&&(Cl.textContent=$M),JJ=e(l),cl=M(l,"TABLE",{"data-svelte-h":!0}),U(cl)!=="svelte-18a95on"&&(cl.innerHTML=xM),eJ=e(l),i(El.$$.fragment,l),nJ=e(l),ul=M(l,"P",{"data-svelte-h":!0}),U(ul)!=="svelte-5fc4nf"&&(ul.innerHTML=zM),MJ=e(l),Nl=M(l,"P",{"data-svelte-h":!0}),U(Nl)!=="svelte-q35fwk"&&(Nl.textContent=HM),UJ=e(l),hl=M(l,"UL",{"data-svelte-h":!0}),U(hl)!=="svelte-r5r65e"&&(hl.innerHTML=_M),aJ=e(l),i(ml.$$.fragment,l),iJ=e(l),i(dl.$$.fragment,l),yJ=e(l),gl=M(l,"P",{"data-svelte-h":!0}),U(gl)!=="svelte-ryzf6q"&&(gl.textContent=XM),pJ=e(l),i(Al.$$.fragment,l),wJ=e(l),bl=M(l,"P",{"data-svelte-h":!0}),U(bl)!=="svelte-1mvdyro"&&(bl.innerHTML=DM),jJ=e(l),i(Bl.$$.fragment,l),IJ=e(l),oJ=M(l,"HR",{}),rJ=e(l),Ql=M(l,"P",{"data-svelte-h":!0}),U(Ql)!=="svelte-5vdevt"&&(Ql.textContent=qM),CJ=e(l),i(kl.$$.fragment,l),cJ=e(l),i(Rl.$$.fragment,l),EJ=e(l),i(Vl.$$.fragment,l),uJ=e(l),Sl=M(l,"P",{"data-svelte-h":!0}),U(Sl)!=="svelte-13qkwtj"&&(Sl.textContent=LM),NJ=e(l),i(fl.$$.fragment,l),hJ=e(l),vl=M(l,"P",{"data-svelte-h":!0}),U(vl)!=="svelte-1mvdyro"&&(vl.innerHTML=PM),mJ=e(l),i(Gl.$$.fragment,l),dJ=e(l),gJ=M(l,"HR",{}),AJ=e(l),Ol=M(l,"P",{"data-svelte-h":!0}),U(Ol)!=="svelte-xnymdh"&&(Ol.textContent=KM),bJ=e(l),i(Zl.$$.fragment,l),BJ=e(l),i(Fl.$$.fragment,l),QJ=e(l),Wl=M(l,"P",{"data-svelte-h":!0}),U(Wl)!=="svelte-1ulvbfl"&&(Wl.innerHTML=lU),kJ=e(l),i(Yl.$$.fragment,l),RJ=e(l),$l=M(l,"P",{"data-svelte-h":!0}),U($l)!=="svelte-11ajvx"&&($l.innerHTML=sU),VJ=e(l),xl=M(l,"TABLE",{"data-svelte-h":!0}),U(xl)!=="svelte-10odg88"&&(xl.innerHTML=tU),SJ=e(l),zl=M(l,"P",{"data-svelte-h":!0}),U(zl)!=="svelte-1qjt3rd"&&(zl.innerHTML=TU),fJ=e(l),i(Hl.$$.fragment,l),vJ=e(l),_l=M(l,"P",{"data-svelte-h":!0}),U(_l)!=="svelte-1mvdyro"&&(_l.innerHTML=JU),GJ=e(l),i(Xl.$$.fragment,l),OJ=e(l),i(Dl.$$.fragment,l),ZJ=e(l),i(ql.$$.fragment,l),FJ=e(l),Ll=M(l,"P",{"data-svelte-h":!0}),U(Ll)!=="svelte-1mvdyro"&&(Ll.innerHTML=eU),WJ=e(l),i(Pl.$$.fragment,l),YJ=e(l),i(Kl.$$.fragment,l),$J=e(l),ls=M(l,"P",{"data-svelte-h":!0}),U(ls)!=="svelte-13byqjp"&&(ls.innerHTML=nU),xJ=e(l),ss=M(l,"OL",{"data-svelte-h":!0}),U(ss)!=="svelte-1e9pr2e"&&(ss.innerHTML=MU),zJ=e(l),ts=M(l,"P",{"data-svelte-h":!0}),U(ts)!=="svelte-t9q2et"&&(ts.textContent=UU),HJ=e(l),_J=M(l,"HR",{}),XJ=e(l),Ts=M(l,"P",{"data-svelte-h":!0}),U(Ts)!=="svelte-6yjuva"&&(Ts.textContent=aU),DJ=e(l),i(Js.$$.fragment,l),qJ=e(l),C=M(l,"DIV",{style:!0});var d=A(C);i(es.$$.fragment,d),qn=e(d),Yt=M(d,"P",{"data-svelte-h":!0}),U(Yt)!=="svelte-cx2mlx"&&(Yt.innerHTML=iU),Ln=e(d),$t=M(d,"P",{"data-svelte-h":!0}),U($t)!=="svelte-mrbvl4"&&($t.textContent=yU),Pn=e(d),xt=M(d,"P",{"data-svelte-h":!0}),U(xt)!=="svelte-9gqed3"&&(xt.innerHTML=pU),Kn=e(d),zt=M(d,"UL",{"data-svelte-h":!0}),U(zt)!=="svelte-1syb72m"&&(zt.innerHTML=wU),d.forEach(t),LJ=e(l),i(ns.$$.fragment,l),PJ=e(l),i(Ms.$$.fragment,l),KJ=e(l),Us=M(l,"P",{"data-svelte-h":!0}),U(Us)!=="svelte-1sb7zhg"&&(Us.innerHTML=jU),le=e(l),as=M(l,"UL",{"data-svelte-h":!0}),U(as)!=="svelte-168m2ui"&&(as.innerHTML=IU),se=e(l),is=M(l,"P",{"data-svelte-h":!0}),U(is)!=="svelte-1nta3bs"&&(is.innerHTML=oU),te=e(l),ys=M(l,"UL",{"data-svelte-h":!0}),U(ys)!=="svelte-104dyvo"&&(ys.innerHTML=rU),Te=e(l),ps=M(l,"P",{"data-svelte-h":!0}),U(ps)!=="svelte-94aj12"&&(ps.innerHTML=CU),Je=e(l),ws=M(l,"UL",{"data-svelte-h":!0}),U(ws)!=="svelte-1pwfkd5"&&(ws.innerHTML=cU),ee=e(l),js=M(l,"P",{"data-svelte-h":!0}),U(js)!=="svelte-voieho"&&(js.textContent=EU),ne=e(l),Is=M(l,"UL",{"data-svelte-h":!0}),U(Is)!=="svelte-cs3wc8"&&(Is.innerHTML=uU),Me=e(l),i(os.$$.fragment,l),Ue=e(l),rs=M(l,"P",{"data-svelte-h":!0}),U(rs)!=="svelte-1mvdyro"&&(rs.innerHTML=NU),ae=e(l),i(Cs.$$.fragment,l),ie=e(l),ye=M(l,"HR",{}),pe=e(l),cs=M(l,"P",{"data-svelte-h":!0}),U(cs)!=="svelte-f80av3"&&(cs.textContent=hU),we=e(l),i(Es.$$.fragment,l),je=e(l),us=M(l,"P",{"data-svelte-h":!0}),U(us)!=="svelte-13ty1hx"&&(us.textContent=mU),Ie=e(l),Ns=M(l,"TABLE",{"data-svelte-h":!0}),U(Ns)!=="svelte-thn5hf"&&(Ns.innerHTML=dU),oe=e(l),hs=M(l,"P",{"data-svelte-h":!0}),U(hs)!=="svelte-3ez0lz"&&(hs.innerHTML=gU),re=e(l),i(ms.$$.fragment,l),Ce=e(l),ds=M(l,"P",{"data-svelte-h":!0}),U(ds)!=="svelte-1mvdyro"&&(ds.innerHTML=AU),ce=e(l),i(gs.$$.fragment,l),Ee=e(l),ue=M(l,"HR",{}),Ne=e(l),As=M(l,"P",{"data-svelte-h":!0}),U(As)!=="svelte-1qpu4mr"&&(As.textContent=bU),he=e(l),i(bs.$$.fragment,l),me=e(l),Bs=M(l,"P",{"data-svelte-h":!0}),U(Bs)!=="svelte-kempwn"&&(Bs.innerHTML=BU),de=e(l),Qs=M(l,"P",{"data-svelte-h":!0}),U(Qs)!=="svelte-m5903s"&&(Qs.textContent=QU),ge=e(l),i(ks.$$.fragment,l),Ae=e(l),be=M(l,"HR",{}),Be=e(l),Rs=M(l,"P",{"data-svelte-h":!0}),U(Rs)!=="svelte-1o5fq89"&&(Rs.textContent=kU),Qe=e(l),i(Vs.$$.fragment,l),ke=e(l),i(Ss.$$.fragment,l),Re=e(l),fs=M(l,"P",{"data-svelte-h":!0}),U(fs)!=="svelte-1ov8p0r"&&(fs.innerHTML=RU),Ve=e(l),vs=M(l,"TABLE",{"data-svelte-h":!0}),U(vs)!=="svelte-rbd6y9"&&(vs.innerHTML=VU),Se=e(l),Gs=M(l,"P",{"data-svelte-h":!0}),U(Gs)!=="svelte-1gas7wo"&&(Gs.innerHTML=SU),fe=e(l),i(Os.$$.fragment,l),ve=e(l),Zs=M(l,"P",{"data-svelte-h":!0}),U(Zs)!=="svelte-gvky0b"&&(Zs.innerHTML=fU),Ge=e(l),i(Fs.$$.fragment,l),Oe=e(l),Ws=M(l,"P",{"data-svelte-h":!0}),U(Ws)!=="svelte-1bf95mj"&&(Ws.innerHTML=vU),Ze=e(l),Ys=M(l,"OL",{"data-svelte-h":!0}),U(Ys)!=="svelte-pz67ff"&&(Ys.innerHTML=GU),Fe=e(l),$s=M(l,"P",{"data-svelte-h":!0}),U($s)!=="svelte-g15ej3"&&($s.innerHTML=OU),We=e(l),i(xs.$$.fragment,l),Ye=e(l),i(zs.$$.fragment,l),$e=e(l),Hs=M(l,"P",{"data-svelte-h":!0}),U(Hs)!=="svelte-1hfxpdg"&&(Hs.innerHTML=ZU),xe=e(l),ze=M(l,"HR",{}),He=e(l),_s=M(l,"P",{"data-svelte-h":!0}),U(_s)!=="svelte-1lky4i8"&&(_s.textContent=FU),_e=e(l),i(Xs.$$.fragment,l),Xe=e(l),i(Ds.$$.fragment,l),De=e(l),qs=M(l,"P",{"data-svelte-h":!0}),U(qs)!=="svelte-qjq0u2"&&(qs.textContent=WU),qe=e(l),i(Ls.$$.fragment,l),Le=e(l),i(Ps.$$.fragment,l),Pe=e(l),i(Ks.$$.fragment,l),Ke=e(l),i(lt.$$.fragment,l),ln=e(l),i(st.$$.fragment,l),sn=e(l),i(tt.$$.fragment,l),tn=e(l),i(Tt.$$.fragment,l),Tn=e(l),i(Jt.$$.fragment,l),Jn=e(l),i(et.$$.fragment,l),en=e(l),i(nt.$$.fragment,l),nn=e(l),i(Mt.$$.fragment,l),Mn=e(l),Ut=M(l,"P",{"data-svelte-h":!0}),U(Ut)!=="svelte-1o1vvxr"&&(Ut.textContent=YU),Un=e(l),at=M(l,"OL",{"data-svelte-h":!0}),U(at)!=="svelte-vr8qzd"&&(at.innerHTML=$U),an=e(l),it=M(l,"P",{"data-svelte-h":!0}),U(it)!=="svelte-xpj7m9"&&(it.innerHTML=xU),yn=e(l),pn=M(l,"HR",{}),wn=e(l),yt=M(l,"P",{"data-svelte-h":!0}),U(yt)!=="svelte-1o8m9nz"&&(yt.textContent=zU),jn=e(l),i(pt.$$.fragment,l),In=e(l),i(wt.$$.fragment,l),on=e(l),Ht=M(l,"TABLE",{});var Ca=A(Ht);jt=M(Ca,"TR",{});var xn=A(jt);c=M(xn,"TD",{width:!0,style:!0});var N=A(c);i(It.$$.fragment,N),lM=e(N),_t=M(N,"P",{"data-svelte-h":!0}),U(_t)!=="svelte-1vr33uo"&&(_t.innerHTML=HU),sM=e(N),Xt=M(N,"UL",{"data-svelte-h":!0}),U(Xt)!=="svelte-m84lyj"&&(Xt.innerHTML=_U),tM=e(N),Dt=M(N,"P",{"data-svelte-h":!0}),U(Dt)!=="svelte-1x4v1d4"&&(Dt.innerHTML=XU),TM=e(N),qt=M(N,"UL",{"data-svelte-h":!0}),U(qt)!=="svelte-v91uca"&&(qt.innerHTML=DU),JM=e(N),Lt=M(N,"P",{"data-svelte-h":!0}),U(Lt)!=="svelte-91807s"&&(Lt.innerHTML=qU),eM=e(N),Pt=M(N,"UL",{"data-svelte-h":!0}),U(Pt)!=="svelte-yf1s25"&&(Pt.innerHTML=LU),N.forEach(t),nM=e(xn),E=M(xn,"TD",{width:!0,style:!0});var h=A(E);i(ot.$$.fragment,h),MM=e(h),Kt=M(h,"P",{"data-svelte-h":!0}),U(Kt)!=="svelte-l2hxiw"&&(Kt.innerHTML=PU),UM=e(h),lT=M(h,"UL",{"data-svelte-h":!0}),U(lT)!=="svelte-1sedtxv"&&(lT.innerHTML=KU),aM=e(h),sT=M(h,"P",{"data-svelte-h":!0}),U(sT)!=="svelte-ktnw4c"&&(sT.innerHTML=la),iM=e(h),tT=M(h,"UL",{"data-svelte-h":!0}),U(tT)!=="svelte-b67dck"&&(tT.innerHTML=sa),yM=e(h),TT=M(h,"P",{"data-svelte-h":!0}),U(TT)!=="svelte-s2ejng"&&(TT.innerHTML=ta),pM=e(h),JT=M(h,"UL",{"data-svelte-h":!0}),U(JT)!=="svelte-1198i2y"&&(JT.innerHTML=Ta),h.forEach(t),xn.forEach(t),Ca.forEach(t),rn=e(l),i(rt.$$.fragment,l),Cn=e(l),Ct=M(l,"TABLE",{"data-svelte-h":!0}),U(Ct)!=="svelte-1qfha29"&&(Ct.innerHTML=Ja),cn=e(l),ct=M(l,"P",{"data-svelte-h":!0}),U(ct)!=="svelte-rdtjgl"&&(ct.innerHTML=ea),En=e(l),Et=M(l,"UL",{"data-svelte-h":!0}),U(Et)!=="svelte-j28w3j"&&(Et.innerHTML=na),un=e(l),Nn=M(l,"HR",{}),hn=e(l),ut=M(l,"P",{"data-svelte-h":!0}),U(ut)!=="svelte-xqk3m5"&&(ut.textContent=Ma),mn=e(l),i(Nt.$$.fragment,l),dn=e(l),i(ht.$$.fragment,l),gn=e(l),mt=M(l,"UL",{"data-svelte-h":!0}),U(mt)!=="svelte-152slk3"&&(mt.innerHTML=Ua),An=e(l),i(dt.$$.fragment,l),bn=e(l),gt=M(l,"UL",{"data-svelte-h":!0}),U(gt)!=="svelte-120rcor"&&(gt.innerHTML=aa),Bn=e(l),i(At.$$.fragment,l),Qn=e(l),bt=M(l,"P",{"data-svelte-h":!0}),U(bt)!=="svelte-s800wd"&&(bt.innerHTML=ia),kn=e(l),Bt=M(l,"UL",{"data-svelte-h":!0}),U(Bt)!=="svelte-t3e2bl"&&(Bt.innerHTML=ya),Rn=e(l),Qt=M(l,"P",{"data-svelte-h":!0}),U(Qt)!=="svelte-18dmhca"&&(Qt.innerHTML=pa),Vn=e(l),kt=M(l,"UL",{"data-svelte-h":!0}),U(kt)!=="svelte-xg09wq"&&(kt.innerHTML=wa),Sn=e(l),Rt=M(l,"P",{"data-svelte-h":!0}),U(Rt)!=="svelte-15hfh7e"&&(Rt.textContent=ja),fn=e(l),Vt=M(l,"P",{"data-svelte-h":!0}),U(Vt)!=="svelte-hxsby3"&&(Vt.innerHTML=Ia),vn=e(l),St=M(l,"P",{"data-svelte-h":!0}),U(St)!=="svelte-1d4miao"&&(St.innerHTML=oa),Gn=e(l),On=M(l,"HR",{}),Zn=e(l),i(ft.$$.fragment,l),Fn=e(l),vt=M(l,"OL",{"data-svelte-h":!0}),U(vt)!=="svelte-2e177m"&&(vt.innerHTML=ra),Wn=e(l),i(Gt.$$.fragment,l),Yn=e(l),nT=M(l,"P",{}),A(nT).forEach(t),this.h()},h(){b(g,"name","hf:doc:metadata"),b(g,"content",Ba),Ea(R.src,jM="https://upload.wikimedia.org/wikipedia/commons/1/10/PyTorch_logo_icon.svg")||b(R,"src",jM),b(R,"width","200"),b(R,"alt","PyTorch"),b(u,"align","center"),B(C,"text-align","center"),B(C,"background","linear-gradient(135deg, #667eea 0%, #764ba2 100%)"),B(C,"color","white"),B(C,"padding","30px"),B(C,"border-radius","15px"),B(C,"margin","30px 0"),b(c,"width","50%"),B(c,"vertical-align","top"),b(E,"width","50%"),B(E,"vertical-align","top")},m(l,s){o(document.head,g),T(l,MT,s),T(l,eT,s),T(l,UT,s),y(Q,l,s),T(l,aT,s),y(k,l,s),T(l,iT,s),T(l,u,s),o(u,R),o(u,zn),y(V,u,null),o(u,Hn),o(u,Ot),o(u,_n),o(u,Zt),o(u,Xn),o(u,Ft),o(u,Dn),o(u,Wt),T(l,yT,s),y(S,l,s),T(l,pT,s),T(l,f,s),T(l,wT,s),T(l,v,s),T(l,jT,s),T(l,G,s),T(l,IT,s),T(l,O,s),T(l,oT,s),T(l,Z,s),T(l,rT,s),T(l,F,s),T(l,CT,s),T(l,W,s),T(l,cT,s),T(l,Y,s),T(l,ET,s),T(l,$,s),T(l,uT,s),T(l,NT,s),T(l,hT,s),y(x,l,s),T(l,mT,s),T(l,z,s),T(l,dT,s),T(l,H,s),T(l,gT,s),T(l,_,s),T(l,AT,s),T(l,bT,s),T(l,BT,s),y(X,l,s),T(l,QT,s),y(D,l,s),T(l,kT,s),T(l,q,s),T(l,RT,s),y(L,l,s),T(l,VT,s),T(l,P,s),T(l,ST,s),y(K,l,s),T(l,fT,s),T(l,ll,s),T(l,vT,s),y(sl,l,s),T(l,GT,s),T(l,tl,s),T(l,OT,s),y(Tl,l,s),T(l,ZT,s),T(l,Jl,s),T(l,FT,s),T(l,WT,s),T(l,YT,s),T(l,el,s),T(l,$T,s),y(nl,l,s),T(l,xT,s),T(l,Ml,s),T(l,zT,s),T(l,Ul,s),T(l,HT,s),y(al,l,s),T(l,_T,s),T(l,il,s),T(l,XT,s),T(l,yl,s),T(l,DT,s),y(pl,l,s),T(l,qT,s),T(l,wl,s),T(l,LT,s),y(jl,l,s),T(l,PT,s),T(l,KT,s),T(l,lJ,s),T(l,Il,s),T(l,sJ,s),y(ol,l,s),T(l,tJ,s),y(rl,l,s),T(l,TJ,s),T(l,Cl,s),T(l,JJ,s),T(l,cl,s),T(l,eJ,s),y(El,l,s),T(l,nJ,s),T(l,ul,s),T(l,MJ,s),T(l,Nl,s),T(l,UJ,s),T(l,hl,s),T(l,aJ,s),y(ml,l,s),T(l,iJ,s),y(dl,l,s),T(l,yJ,s),T(l,gl,s),T(l,pJ,s),y(Al,l,s),T(l,wJ,s),T(l,bl,s),T(l,jJ,s),y(Bl,l,s),T(l,IJ,s),T(l,oJ,s),T(l,rJ,s),T(l,Ql,s),T(l,CJ,s),y(kl,l,s),T(l,cJ,s),y(Rl,l,s),T(l,EJ,s),y(Vl,l,s),T(l,uJ,s),T(l,Sl,s),T(l,NJ,s),y(fl,l,s),T(l,hJ,s),T(l,vl,s),T(l,mJ,s),y(Gl,l,s),T(l,dJ,s),T(l,gJ,s),T(l,AJ,s),T(l,Ol,s),T(l,bJ,s),y(Zl,l,s),T(l,BJ,s),y(Fl,l,s),T(l,QJ,s),T(l,Wl,s),T(l,kJ,s),y(Yl,l,s),T(l,RJ,s),T(l,$l,s),T(l,VJ,s),T(l,xl,s),T(l,SJ,s),T(l,zl,s),T(l,fJ,s),y(Hl,l,s),T(l,vJ,s),T(l,_l,s),T(l,GJ,s),y(Xl,l,s),T(l,OJ,s),y(Dl,l,s),T(l,ZJ,s),y(ql,l,s),T(l,FJ,s),T(l,Ll,s),T(l,WJ,s),y(Pl,l,s),T(l,YJ,s),y(Kl,l,s),T(l,$J,s),T(l,ls,s),T(l,xJ,s),T(l,ss,s),T(l,zJ,s),T(l,ts,s),T(l,HJ,s),T(l,_J,s),T(l,XJ,s),T(l,Ts,s),T(l,DJ,s),y(Js,l,s),T(l,qJ,s),T(l,C,s),y(es,C,null),o(C,qn),o(C,Yt),o(C,Ln),o(C,$t),o(C,Pn),o(C,xt),o(C,Kn),o(C,zt),T(l,LJ,s),y(ns,l,s),T(l,PJ,s),y(Ms,l,s),T(l,KJ,s),T(l,Us,s),T(l,le,s),T(l,as,s),T(l,se,s),T(l,is,s),T(l,te,s),T(l,ys,s),T(l,Te,s),T(l,ps,s),T(l,Je,s),T(l,ws,s),T(l,ee,s),T(l,js,s),T(l,ne,s),T(l,Is,s),T(l,Me,s),y(os,l,s),T(l,Ue,s),T(l,rs,s),T(l,ae,s),y(Cs,l,s),T(l,ie,s),T(l,ye,s),T(l,pe,s),T(l,cs,s),T(l,we,s),y(Es,l,s),T(l,je,s),T(l,us,s),T(l,Ie,s),T(l,Ns,s),T(l,oe,s),T(l,hs,s),T(l,re,s),y(ms,l,s),T(l,Ce,s),T(l,ds,s),T(l,ce,s),y(gs,l,s),T(l,Ee,s),T(l,ue,s),T(l,Ne,s),T(l,As,s),T(l,he,s),y(bs,l,s),T(l,me,s),T(l,Bs,s),T(l,de,s),T(l,Qs,s),T(l,ge,s),y(ks,l,s),T(l,Ae,s),T(l,be,s),T(l,Be,s),T(l,Rs,s),T(l,Qe,s),y(Vs,l,s),T(l,ke,s),y(Ss,l,s),T(l,Re,s),T(l,fs,s),T(l,Ve,s),T(l,vs,s),T(l,Se,s),T(l,Gs,s),T(l,fe,s),y(Os,l,s),T(l,ve,s),T(l,Zs,s),T(l,Ge,s),y(Fs,l,s),T(l,Oe,s),T(l,Ws,s),T(l,Ze,s),T(l,Ys,s),T(l,Fe,s),T(l,$s,s),T(l,We,s),y(xs,l,s),T(l,Ye,s),y(zs,l,s),T(l,$e,s),T(l,Hs,s),T(l,xe,s),T(l,ze,s),T(l,He,s),T(l,_s,s),T(l,_e,s),y(Xs,l,s),T(l,Xe,s),y(Ds,l,s),T(l,De,s),T(l,qs,s),T(l,qe,s),y(Ls,l,s),T(l,Le,s),y(Ps,l,s),T(l,Pe,s),y(Ks,l,s),T(l,Ke,s),y(lt,l,s),T(l,ln,s),y(st,l,s),T(l,sn,s),y(tt,l,s),T(l,tn,s),y(Tt,l,s),T(l,Tn,s),y(Jt,l,s),T(l,Jn,s),y(et,l,s),T(l,en,s),y(nt,l,s),T(l,nn,s),y(Mt,l,s),T(l,Mn,s),T(l,Ut,s),T(l,Un,s),T(l,at,s),T(l,an,s),T(l,it,s),T(l,yn,s),T(l,pn,s),T(l,wn,s),T(l,yt,s),T(l,jn,s),y(pt,l,s),T(l,In,s),y(wt,l,s),T(l,on,s),T(l,Ht,s),o(Ht,jt),o(jt,c),y(It,c,null),o(c,lM),o(c,_t),o(c,sM),o(c,Xt),o(c,tM),o(c,Dt),o(c,TM),o(c,qt),o(c,JM),o(c,Lt),o(c,eM),o(c,Pt),o(jt,nM),o(jt,E),y(ot,E,null),o(E,MM),o(E,Kt),o(E,UM),o(E,lT),o(E,aM),o(E,sT),o(E,iM),o(E,tT),o(E,yM),o(E,TT),o(E,pM),o(E,JT),T(l,rn,s),y(rt,l,s),T(l,Cn,s),T(l,Ct,s),T(l,cn,s),T(l,ct,s),T(l,En,s),T(l,Et,s),T(l,un,s),T(l,Nn,s),T(l,hn,s),T(l,ut,s),T(l,mn,s),y(Nt,l,s),T(l,dn,s),y(ht,l,s),T(l,gn,s),T(l,mt,s),T(l,An,s),y(dt,l,s),T(l,bn,s),T(l,gt,s),T(l,Bn,s),y(At,l,s),T(l,Qn,s),T(l,bt,s),T(l,kn,s),T(l,Bt,s),T(l,Rn,s),T(l,Qt,s),T(l,Vn,s),T(l,kt,s),T(l,Sn,s),T(l,Rt,s),T(l,fn,s),T(l,Vt,s),T(l,vn,s),T(l,St,s),T(l,Gn,s),T(l,On,s),T(l,Zn,s),y(ft,l,s),T(l,Fn,s),T(l,vt,s),T(l,Wn,s),y(Gt,l,s),T(l,Yn,s),T(l,nT,s),$n=!0},p:ua,i(l){$n||(p(Q.$$.fragment,l),p(k.$$.fragment,l),p(V.$$.fragment,l),p(S.$$.fragment,l),p(x.$$.fragment,l),p(X.$$.fragment,l),p(D.$$.fragment,l),p(L.$$.fragment,l),p(K.$$.fragment,l),p(sl.$$.fragment,l),p(Tl.$$.fragment,l),p(nl.$$.fragment,l),p(al.$$.fragment,l),p(pl.$$.fragment,l),p(jl.$$.fragment,l),p(ol.$$.fragment,l),p(rl.$$.fragment,l),p(El.$$.fragment,l),p(ml.$$.fragment,l),p(dl.$$.fragment,l),p(Al.$$.fragment,l),p(Bl.$$.fragment,l),p(kl.$$.fragment,l),p(Rl.$$.fragment,l),p(Vl.$$.fragment,l),p(fl.$$.fragment,l),p(Gl.$$.fragment,l),p(Zl.$$.fragment,l),p(Fl.$$.fragment,l),p(Yl.$$.fragment,l),p(Hl.$$.fragment,l),p(Xl.$$.fragment,l),p(Dl.$$.fragment,l),p(ql.$$.fragment,l),p(Pl.$$.fragment,l),p(Kl.$$.fragment,l),p(Js.$$.fragment,l),p(es.$$.fragment,l),p(ns.$$.fragment,l),p(Ms.$$.fragment,l),p(os.$$.fragment,l),p(Cs.$$.fragment,l),p(Es.$$.fragment,l),p(ms.$$.fragment,l),p(gs.$$.fragment,l),p(bs.$$.fragment,l),p(ks.$$.fragment,l),p(Vs.$$.fragment,l),p(Ss.$$.fragment,l),p(Os.$$.fragment,l),p(Fs.$$.fragment,l),p(xs.$$.fragment,l),p(zs.$$.fragment,l),p(Xs.$$.fragment,l),p(Ds.$$.fragment,l),p(Ls.$$.fragment,l),p(Ps.$$.fragment,l),p(Ks.$$.fragment,l),p(lt.$$.fragment,l),p(st.$$.fragment,l),p(tt.$$.fragment,l),p(Tt.$$.fragment,l),p(Jt.$$.fragment,l),p(et.$$.fragment,l),p(nt.$$.fragment,l),p(Mt.$$.fragment,l),p(pt.$$.fragment,l),p(wt.$$.fragment,l),p(It.$$.fragment,l),p(ot.$$.fragment,l),p(rt.$$.fragment,l),p(Nt.$$.fragment,l),p(ht.$$.fragment,l),p(dt.$$.fragment,l),p(At.$$.fragment,l),p(ft.$$.fragment,l),p(Gt.$$.fragment,l),$n=!0)},o(l){w(Q.$$.fragment,l),w(k.$$.fragment,l),w(V.$$.fragment,l),w(S.$$.fragment,l),w(x.$$.fragment,l),w(X.$$.fragment,l),w(D.$$.fragment,l),w(L.$$.fragment,l),w(K.$$.fragment,l),w(sl.$$.fragment,l),w(Tl.$$.fragment,l),w(nl.$$.fragment,l),w(al.$$.fragment,l),w(pl.$$.fragment,l),w(jl.$$.fragment,l),w(ol.$$.fragment,l),w(rl.$$.fragment,l),w(El.$$.fragment,l),w(ml.$$.fragment,l),w(dl.$$.fragment,l),w(Al.$$.fragment,l),w(Bl.$$.fragment,l),w(kl.$$.fragment,l),w(Rl.$$.fragment,l),w(Vl.$$.fragment,l),w(fl.$$.fragment,l),w(Gl.$$.fragment,l),w(Zl.$$.fragment,l),w(Fl.$$.fragment,l),w(Yl.$$.fragment,l),w(Hl.$$.fragment,l),w(Xl.$$.fragment,l),w(Dl.$$.fragment,l),w(ql.$$.fragment,l),w(Pl.$$.fragment,l),w(Kl.$$.fragment,l),w(Js.$$.fragment,l),w(es.$$.fragment,l),w(ns.$$.fragment,l),w(Ms.$$.fragment,l),w(os.$$.fragment,l),w(Cs.$$.fragment,l),w(Es.$$.fragment,l),w(ms.$$.fragment,l),w(gs.$$.fragment,l),w(bs.$$.fragment,l),w(ks.$$.fragment,l),w(Vs.$$.fragment,l),w(Ss.$$.fragment,l),w(Os.$$.fragment,l),w(Fs.$$.fragment,l),w(xs.$$.fragment,l),w(zs.$$.fragment,l),w(Xs.$$.fragment,l),w(Ds.$$.fragment,l),w(Ls.$$.fragment,l),w(Ps.$$.fragment,l),w(Ks.$$.fragment,l),w(lt.$$.fragment,l),w(st.$$.fragment,l),w(tt.$$.fragment,l),w(Tt.$$.fragment,l),w(Jt.$$.fragment,l),w(et.$$.fragment,l),w(nt.$$.fragment,l),w(Mt.$$.fragment,l),w(pt.$$.fragment,l),w(wt.$$.fragment,l),w(It.$$.fragment,l),w(ot.$$.fragment,l),w(rt.$$.fragment,l),w(Nt.$$.fragment,l),w(ht.$$.fragment,l),w(dt.$$.fragment,l),w(At.$$.fragment,l),w(ft.$$.fragment,l),w(Gt.$$.fragment,l),$n=!1},d(l){l&&(t(MT),t(eT),t(UT),t(aT),t(iT),t(u),t(yT),t(pT),t(f),t(wT),t(v),t(jT),t(G),t(IT),t(O),t(oT),t(Z),t(rT),t(F),t(CT),t(W),t(cT),t(Y),t(ET),t($),t(uT),t(NT),t(hT),t(mT),t(z),t(dT),t(H),t(gT),t(_),t(AT),t(bT),t(BT),t(QT),t(kT),t(q),t(RT),t(VT),t(P),t(ST),t(fT),t(ll),t(vT),t(GT),t(tl),t(OT),t(ZT),t(Jl),t(FT),t(WT),t(YT),t(el),t($T),t(xT),t(Ml),t(zT),t(Ul),t(HT),t(_T),t(il),t(XT),t(yl),t(DT),t(qT),t(wl),t(LT),t(PT),t(KT),t(lJ),t(Il),t(sJ),t(tJ),t(TJ),t(Cl),t(JJ),t(cl),t(eJ),t(nJ),t(ul),t(MJ),t(Nl),t(UJ),t(hl),t(aJ),t(iJ),t(yJ),t(gl),t(pJ),t(wJ),t(bl),t(jJ),t(IJ),t(oJ),t(rJ),t(Ql),t(CJ),t(cJ),t(EJ),t(uJ),t(Sl),t(NJ),t(hJ),t(vl),t(mJ),t(dJ),t(gJ),t(AJ),t(Ol),t(bJ),t(BJ),t(QJ),t(Wl),t(kJ),t(RJ),t($l),t(VJ),t(xl),t(SJ),t(zl),t(fJ),t(vJ),t(_l),t(GJ),t(OJ),t(ZJ),t(FJ),t(Ll),t(WJ),t(YJ),t($J),t(ls),t(xJ),t(ss),t(zJ),t(ts),t(HJ),t(_J),t(XJ),t(Ts),t(DJ),t(qJ),t(C),t(LJ),t(PJ),t(KJ),t(Us),t(le),t(as),t(se),t(is),t(te),t(ys),t(Te),t(ps),t(Je),t(ws),t(ee),t(js),t(ne),t(Is),t(Me),t(Ue),t(rs),t(ae),t(ie),t(ye),t(pe),t(cs),t(we),t(je),t(us),t(Ie),t(Ns),t(oe),t(hs),t(re),t(Ce),t(ds),t(ce),t(Ee),t(ue),t(Ne),t(As),t(he),t(me),t(Bs),t(de),t(Qs),t(ge),t(Ae),t(be),t(Be),t(Rs),t(Qe),t(ke),t(Re),t(fs),t(Ve),t(vs),t(Se),t(Gs),t(fe),t(ve),t(Zs),t(Ge),t(Oe),t(Ws),t(Ze),t(Ys),t(Fe),t($s),t(We),t(Ye),t($e),t(Hs),t(xe),t(ze),t(He),t(_s),t(_e),t(Xe),t(De),t(qs),t(qe),t(Le),t(Pe),t(Ke),t(ln),t(sn),t(tn),t(Tn),t(Jn),t(en),t(nn),t(Mn),t(Ut),t(Un),t(at),t(an),t(it),t(yn),t(pn),t(wn),t(yt),t(jn),t(In),t(on),t(Ht),t(rn),t(Cn),t(Ct),t(cn),t(ct),t(En),t(Et),t(un),t(Nn),t(hn),t(ut),t(mn),t(dn),t(gn),t(mt),t(An),t(bn),t(gt),t(Bn),t(Qn),t(bt),t(kn),t(Bt),t(Rn),t(Qt),t(Vn),t(kt),t(Sn),t(Rt),t(fn),t(Vt),t(vn),t(St),t(Gn),t(On),t(Zn),t(Fn),t(vt),t(Wn),t(Yn),t(nT)),t(g),j(Q,l),j(k,l),j(V),j(S,l),j(x,l),j(X,l),j(D,l),j(L,l),j(K,l),j(sl,l),j(Tl,l),j(nl,l),j(al,l),j(pl,l),j(jl,l),j(ol,l),j(rl,l),j(El,l),j(ml,l),j(dl,l),j(Al,l),j(Bl,l),j(kl,l),j(Rl,l),j(Vl,l),j(fl,l),j(Gl,l),j(Zl,l),j(Fl,l),j(Yl,l),j(Hl,l),j(Xl,l),j(Dl,l),j(ql,l),j(Pl,l),j(Kl,l),j(Js,l),j(es),j(ns,l),j(Ms,l),j(os,l),j(Cs,l),j(Es,l),j(ms,l),j(gs,l),j(bs,l),j(ks,l),j(Vs,l),j(Ss,l),j(Os,l),j(Fs,l),j(xs,l),j(zs,l),j(Xs,l),j(Ds,l),j(Ls,l),j(Ps,l),j(Ks,l),j(lt,l),j(st,l),j(tt,l),j(Tt,l),j(Jt,l),j(et,l),j(nt,l),j(Mt,l),j(pt,l),j(wt,l),j(It),j(ot),j(rt,l),j(Nt,l),j(ht,l),j(dt,l),j(At,l),j(ft,l),j(Gt,l)}}}const Ba='{"title":"OpenEnv: Production RL Made Simple","local":"openenv-production-rl-made-simple","sections":[{"title":"From “Hello World” to RL Training in 5 Minutes ✨","local":"from-hello-world-to-rl-training-in-5-minutes-","sections":[],"depth":2},{"title":"Why OpenEnv?","local":"why-openenv","sections":[],"depth":2},{"title":"📋 What You’ll Learn","local":"-what-youll-learn","sections":[],"depth":2},{"title":"📑 Table of Contents","local":"-table-of-contents","sections":[{"title":"Foundation","local":"foundation","sections":[],"depth":3},{"title":"Architecture","local":"architecture","sections":[],"depth":3},{"title":"Hands-On Demo","local":"hands-on-demo","sections":[],"depth":3},{"title":"Advanced","local":"advanced","sections":[],"depth":3},{"title":"Wrap Up","local":"wrap-up","sections":[],"depth":3}],"depth":2},{"title":"Part 1: RL in 60 Seconds ⏱️","local":"part-1-rl-in-60-seconds-","sections":[],"depth":2},{"title":"Part 2: The Problem with Traditional RL 😤","local":"part-2-the-problem-with-traditional-rl-","sections":[{"title":"🤔 Why Can’t We Just Use OpenAI Gym?","local":"-why-cant-we-just-use-openai-gym","sections":[],"depth":3},{"title":"💡 The OpenEnv Philosophy","local":"-the-openenv-philosophy","sections":[],"depth":3},{"title":"The Architecture","local":"the-architecture","sections":[],"depth":3}],"depth":2},{"title":"Part 4: The OpenEnv Pattern 🏗️","local":"part-4-the-openenv-pattern-","sections":[{"title":"Every OpenEnv Environment Has 3 Components:","local":"every-openenv-environment-has-3-components","sections":[],"depth":3}],"depth":2},{"title":"Part 5: Example Integration - OpenSpiel 🎮","local":"part-5-example-integration---openspiel-","sections":[{"title":"What is OpenSpiel?","local":"what-is-openspiel","sections":[],"depth":3},{"title":"OpenEnv’s Integration","local":"openenvs-integration","sections":[],"depth":3},{"title":"Type-Safe Models","local":"type-safe-models","sections":[],"depth":3},{"title":"How the Client Works","local":"how-the-client-works","sections":[],"depth":3}],"depth":2},{"title":"Part 6: Using Real OpenSpiel 🎮","local":"part-6-using-real-openspiel-","sections":[{"title":"Now let’s USE a production environment!","local":"now-lets-use-a-production-environment","sections":[],"depth":3},{"title":"The Game: Catch 🔴🏓","local":"the-game-catch-","sections":[],"depth":3}],"depth":2},{"title":"Part 7: Four Policies 🤖","local":"part-7-four-policies-","sections":[],"depth":2},{"title":"Part 8: Policy Competition! 🏆","local":"part-8-policy-competition-","sections":[],"depth":2},{"title":"Part 9: Switching to Other Games 🎮","local":"part-9-switching-to-other-games-","sections":[{"title":"What We Just Used: Real OpenSpiel! 🎉","local":"what-we-just-used-real-openspiel-","sections":[],"depth":3},{"title":"🎮 6 Games Available - Same Interface!","local":"-6-games-available---same-interface","sections":[],"depth":3},{"title":"Try Another Game (Optional):","local":"try-another-game-optional","sections":[],"depth":3}],"depth":2},{"title":"Part 10: Create Your Own Integration 🛠️","local":"part-10-create-your-own-integration-","sections":[{"title":"The 5-Step Pattern","local":"the-5-step-pattern","sections":[],"depth":3},{"title":"Step 1: Define Types ( models.py )","local":"step-1-define-types--modelspy-","sections":[],"depth":3},{"title":"Step 2: Implement Environment ( server/environment.py )","local":"step-2-implement-environment--serverenvironmentpy-","sections":[],"depth":3},{"title":"Step 3: Create Client ( client.py )","local":"step-3-create-client--clientpy-","sections":[],"depth":3},{"title":"Step 4: Create Server ( server/app.py )","local":"step-4-create-server--serverapppy-","sections":[],"depth":3},{"title":"Step 5: Dockerize ( server/Dockerfile )","local":"step-5-dockerize--serverdockerfile-","sections":[],"depth":3},{"title":"🎓 Examples to Study","local":"-examples-to-study","sections":[],"depth":3}],"depth":2},{"title":"🎓 Summary: Your Journey","local":"-summary-your-journey","sections":[{"title":"What You Learned","local":"what-you-learned","sections":[],"depth":3},{"title":"📚 Concepts","local":"-concepts","sections":[],"depth":3},{"title":"🛠️ Skills","local":"-skills","sections":[],"depth":3},{"title":"OpenEnv vs Traditional RL","local":"openenv-vs-traditional-rl","sections":[],"depth":3}],"depth":2},{"title":"📚 Resources","local":"-resources","sections":[{"title":"🔗 Essential Links","local":"-essential-links","sections":[],"depth":3},{"title":"📖 Documentation Deep Dives","local":"-documentation-deep-dives","sections":[],"depth":3},{"title":"🎓 Community & Support","local":"-community--support","sections":[],"depth":3},{"title":"🌈 What’s Next?","local":"-whats-next","sections":[],"depth":3}],"depth":2}],"depth":1}';function Qa(wM){return Na(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class va extends ha{constructor(g){super(),ma(this,g,Qa,ba,ca,{})}}export{va as component};

Xet Storage Details

Size:
174 kB
·
Xet hash:
ac980ef15342ae0320de59080ffa76d8e655470ace8eb3a888113226a067d496

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.