nim-libp2p/docs/tutorial_6_game/index.html

924 lines
88 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://status-im.github.io/nim-libp2p/docs/tutorial_6_game/">
<link rel="prev" href="../tutorial_5_discovery/">
<link rel="next" href="../circuitrelay/">
<link rel="icon" href="https://libp2p.io/img/logo_small.png">
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.26">
<title>Game - nim-libp2p</title>
<link rel="stylesheet" href="../assets/stylesheets/main.6543a935.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="blue-grey" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#tron-example" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="nim-libp2p" class="md-header__button md-logo" aria-label="nim-libp2p" data-md-component="logo">
<img src="https://libp2p.io/img/logo_small.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
nim-libp2p
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Game
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="blue-grey" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5m0 8a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3Z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="blue-grey" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 6H7c-3.31 0-6 2.69-6 6s2.69 6 6 6h10c3.31 0 6-2.69 6-6s-2.69-6-6-6zm0 10H7c-2.21 0-4-1.79-4-4s1.79-4 4-4h10c2.21 0 4 1.79 4 4s-1.79 4-4 4zM7 9c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>
</label>
</form>
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/status-im/nim-libp2p" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
status-im/nim-libp2p
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="nim-libp2p" class="md-nav__button md-logo" aria-label="nim-libp2p" data-md-component="logo">
<img src="https://libp2p.io/img/logo_small.png" alt="logo">
</a>
nim-libp2p
</label>
<div class="md-nav__source">
<a href="https://github.com/status-im/nim-libp2p" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
status-im/nim-libp2p
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" checked>
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Tutorials
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Tutorials
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial_1_connect/" class="md-nav__link">
<span class="md-ellipsis">
Simple connection
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial_2_customproto/" class="md-nav__link">
<span class="md-ellipsis">
Create a custom protocol
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial_3_protobuf/" class="md-nav__link">
<span class="md-ellipsis">
Protobuf
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial_4_gossipsub/" class="md-nav__link">
<span class="md-ellipsis">
GossipSub
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial_5_discovery/" class="md-nav__link">
<span class="md-ellipsis">
Discovery Manager
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Game
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Game
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#game-logic" class="md-nav__link">
<span class="md-ellipsis">
Game Logic
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#matchmaking" class="md-nav__link">
<span class="md-ellipsis">
Matchmaking
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../circuitrelay/" class="md-nav__link">
<span class="md-ellipsis">
Circuit Relay
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="/nim-libp2p/master/libp2p.html" class="md-nav__link">
<span class="md-ellipsis">
Reference
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#game-logic" class="md-nav__link">
<span class="md-ellipsis">
Game Logic
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#matchmaking" class="md-nav__link">
<span class="md-ellipsis">
Matchmaking
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="tron-example">Tron example</h1>
<p>In this tutorial, we will create a video game based on libp2p, using
all of the features we talked about in the last tutorials.</p>
<p>We will:
- Discover peers using the Discovery Manager
- Use GossipSub to find a play mate
- Create a custom protocol to play with him</p>
<p>While this may look like a daunting project, it's less than 150 lines of code.</p>
<p>The game will be a simple Tron. We will use <a href="https://github.com/ftsf/nico">nico</a>
as a game engine. (you need to run <code>nimble install nico</code> to have it available)</p>
<p><img alt="multiplay" src="https://user-images.githubusercontent.com/13471753/198852714-b55048e3-f233-4723-900d-2193ad259fe1.gif" /></p>
<p>We will start by importing our dependencies and creating our types
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">import</span><span class="w"> </span><span class="n">os</span>
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="kn">import</span><span class="w"> </span><span class="n">nico</span><span class="p">,</span><span class="w"> </span><span class="n">chronos</span><span class="p">,</span><span class="w"> </span><span class="n">stew</span><span class="o">/</span><span class="n">byteutils</span><span class="p">,</span><span class="w"> </span><span class="n">stew</span><span class="o">/</span><span class="n">endians2</span>
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="kn">import</span><span class="w"> </span><span class="n">libp2p</span>
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="kn">import</span><span class="w"> </span><span class="n">libp2p</span><span class="o">/</span><span class="n">protocols</span><span class="o">/</span><span class="n">rendezvous</span>
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="kn">import</span><span class="w"> </span><span class="n">libp2p</span><span class="o">/</span><span class="n">discovery</span><span class="o">/</span><span class="n">rendezvousinterface</span>
<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="kn">import</span><span class="w"> </span><span class="n">libp2p</span><span class="o">/</span><span class="n">discovery</span><span class="o">/</span><span class="n">discoverymngr</span>
<a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a>
<a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a><span class="k">const</span>
<a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="w"> </span><span class="n">directions</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">@[</span><span class="p">(</span><span class="n">K_UP</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="n">K_LEFT</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="n">K_DOWN</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="n">K_RIGHT</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="o">]</span>
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">32</span>
<a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a><span class="w"> </span><span class="n">tickPeriod</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.2</span>
<a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a>
<a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a><span class="k">type</span>
<a id="__codelineno-0-14" name="__codelineno-0-14" href="#__codelineno-0-14"></a><span class="w"> </span><span class="n">Player</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">ref</span><span class="w"> </span><span class="k">object</span>
<a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></a><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="nb">int</span>
<a id="__codelineno-0-16" name="__codelineno-0-16" href="#__codelineno-0-16"></a><span class="w"> </span><span class="n">currentDir</span><span class="p">,</span><span class="w"> </span><span class="n">nextDir</span><span class="p">:</span><span class="w"> </span><span class="nb">int</span>
<a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a><span class="w"> </span><span class="n">lost</span><span class="p">:</span><span class="w"> </span><span class="nb">bool</span>
<a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a><span class="w"> </span><span class="n">color</span><span class="p">:</span><span class="w"> </span><span class="nb">int</span>
<a id="__codelineno-0-19" name="__codelineno-0-19" href="#__codelineno-0-19"></a>
<a id="__codelineno-0-20" name="__codelineno-0-20" href="#__codelineno-0-20"></a><span class="w"> </span><span class="n">Game</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">ref</span><span class="w"> </span><span class="k">object</span>
<a id="__codelineno-0-21" name="__codelineno-0-21" href="#__codelineno-0-21"></a><span class="w"> </span><span class="n">gameMap</span><span class="p">:</span><span class="w"> </span><span class="nb">array</span><span class="o">[</span><span class="n">mapSize</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">mapSize</span><span class="p">,</span><span class="w"> </span><span class="nb">int</span><span class="o">]</span>
<a id="__codelineno-0-22" name="__codelineno-0-22" href="#__codelineno-0-22"></a><span class="w"> </span><span class="n">tickTime</span><span class="p">:</span><span class="w"> </span><span class="nb">float</span>
<a id="__codelineno-0-23" name="__codelineno-0-23" href="#__codelineno-0-23"></a><span class="w"> </span><span class="n">localPlayer</span><span class="p">,</span><span class="w"> </span><span class="n">remotePlayer</span><span class="p">:</span><span class="w"> </span><span class="n">Player</span>
<a id="__codelineno-0-24" name="__codelineno-0-24" href="#__codelineno-0-24"></a><span class="w"> </span><span class="n">peerFound</span><span class="p">:</span><span class="w"> </span><span class="n">Future</span><span class="o">[</span><span class="n">Connection</span><span class="o">]</span>
<a id="__codelineno-0-25" name="__codelineno-0-25" href="#__codelineno-0-25"></a><span class="w"> </span><span class="n">hasCandidate</span><span class="p">:</span><span class="w"> </span><span class="nb">bool</span>
<a id="__codelineno-0-26" name="__codelineno-0-26" href="#__codelineno-0-26"></a><span class="w"> </span><span class="n">tickFinished</span><span class="p">:</span><span class="w"> </span><span class="n">Future</span><span class="o">[</span><span class="nb">int</span><span class="o">]</span>
<a id="__codelineno-0-27" name="__codelineno-0-27" href="#__codelineno-0-27"></a>
<a id="__codelineno-0-28" name="__codelineno-0-28" href="#__codelineno-0-28"></a><span class="w"> </span><span class="n">GameProto</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">ref</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">LPProtocol</span>
<a id="__codelineno-0-29" name="__codelineno-0-29" href="#__codelineno-0-29"></a>
<a id="__codelineno-0-30" name="__codelineno-0-30" href="#__codelineno-0-30"></a><span class="k">proc</span><span class="w"> </span><span class="nf">new</span><span class="p">(</span><span class="err">_: type[Game]): Game =</span>
<a id="__codelineno-0-31" name="__codelineno-0-31" href="#__codelineno-0-31"></a><span class="w"> </span><span class="c"># Default state of a game</span>
<a id="__codelineno-0-32" name="__codelineno-0-32" href="#__codelineno-0-32"></a><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Game</span><span class="p">(</span>
<a id="__codelineno-0-33" name="__codelineno-0-33" href="#__codelineno-0-33"></a><span class="w"> </span><span class="n">tickTime</span><span class="p">:</span><span class="w"> </span><span class="o">-</span><span class="mf">3.0</span><span class="p">,</span><span class="w"> </span><span class="c"># 3 seconds of &quot;warm-up&quot; time</span>
<a id="__codelineno-0-34" name="__codelineno-0-34" href="#__codelineno-0-34"></a><span class="w"> </span><span class="n">localPlayer</span><span class="p">:</span><span class="w"> </span><span class="n">Player</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="mi">16</span><span class="p">,</span><span class="w"> </span><span class="n">currentDir</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="n">nextDir</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="p">:</span><span class="w"> </span><span class="mi">8</span><span class="p">),</span>
<a id="__codelineno-0-35" name="__codelineno-0-35" href="#__codelineno-0-35"></a><span class="w"> </span><span class="n">remotePlayer</span><span class="p">:</span><span class="w"> </span><span class="n">Player</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="mi">27</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="mi">16</span><span class="p">,</span><span class="w"> </span><span class="n">currentDir</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">nextDir</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="p">:</span><span class="w"> </span><span class="mi">12</span><span class="p">),</span>
<a id="__codelineno-0-36" name="__codelineno-0-36" href="#__codelineno-0-36"></a><span class="w"> </span><span class="n">peerFound</span><span class="p">:</span><span class="w"> </span><span class="n">newFuture</span><span class="o">[</span><span class="n">Connection</span><span class="o">]</span><span class="p">(),</span>
<a id="__codelineno-0-37" name="__codelineno-0-37" href="#__codelineno-0-37"></a><span class="w"> </span><span class="p">)</span>
<a id="__codelineno-0-38" name="__codelineno-0-38" href="#__codelineno-0-38"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">pos</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">..</span><span class="w"> </span><span class="n">result</span><span class="p">.</span><span class="n">gameMap</span><span class="p">.</span><span class="n">high</span><span class="p">:</span>
<a id="__codelineno-0-39" name="__codelineno-0-39" href="#__codelineno-0-39"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">pos</span><span class="w"> </span><span class="ow">mod</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">[</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">]</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">pos</span><span class="w"> </span><span class="ow">div</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="o">[</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">]</span><span class="p">:</span>
<a id="__codelineno-0-40" name="__codelineno-0-40" href="#__codelineno-0-40"></a><span class="w"> </span><span class="n">result</span><span class="p">.</span><span class="n">gameMap</span><span class="o">[</span><span class="n">pos</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">7</span>
</code></pre></div></p>
<h2 id="game-logic">Game Logic</h2>
<p>The networking during the game will work like this:</p>
<ul>
<li>Each player will have <code>tickPeriod</code> (0.1) seconds to choose
a direction that he wants to go to (default to current direction)</li>
<li>After <code>tickPeriod</code>, we will send our choosen direction to the peer,
and wait for his direction</li>
<li>Once we have both direction, we will "tick" the game, and restart the
loop, as long as both player are alive.</li>
</ul>
<p>This is a very simplistic scheme, but creating proper networking for
video games is an <a href="https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization">art</a></p>
<p>The main drawback of this scheme is that the more ping you have with
the peer, the slower the game will run. Or invertedly, the less ping you
have, the faster it runs!
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="k">proc</span><span class="w"> </span><span class="nf">update</span><span class="p">(</span><span class="n">g</span><span class="p">:</span><span class="w"> </span><span class="n">Game</span><span class="p">,</span><span class="w"> </span><span class="n">dt</span><span class="p">:</span><span class="w"> </span><span class="nb">float32</span><span class="p">)</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="w"> </span><span class="c"># Will be called at each frame of the game.</span>
<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="w"> </span><span class="c">#</span>
<a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="w"> </span><span class="c"># Because both Nico and Chronos have a main loop,</span>
<a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="w"> </span><span class="c"># they must share the control of the main thread.</span>
<a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a><span class="w"> </span><span class="c"># This is a hacky way to make this happen</span>
<a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a><span class="w"> </span><span class="n">waitFor</span><span class="p">(</span><span class="n">sleepAsync</span><span class="p">(</span><span class="mf">1.</span><span class="n">milliseconds</span><span class="p">))</span>
<a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a><span class="w"> </span><span class="c"># Don&#39;t do anything if we are still waiting for an opponent</span>
<a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">peerFound</span><span class="p">.</span><span class="n">finished</span><span class="p">())</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">isNil</span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">tickFinished</span><span class="p">):</span>
<a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a><span class="w"> </span><span class="k">return</span>
<a id="__codelineno-1-11" name="__codelineno-1-11" href="#__codelineno-1-11"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickTime</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">dt</span>
<a id="__codelineno-1-12" name="__codelineno-1-12" href="#__codelineno-1-12"></a>
<a id="__codelineno-1-13" name="__codelineno-1-13" href="#__codelineno-1-13"></a><span class="w"> </span><span class="c"># Update the wanted direction, making sure we can&#39;t go backward</span>
<a id="__codelineno-1-14" name="__codelineno-1-14" href="#__codelineno-1-14"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">..</span><span class="w"> </span><span class="n">directions</span><span class="p">.</span><span class="n">high</span><span class="p">:</span>
<a id="__codelineno-1-15" name="__codelineno-1-15" href="#__codelineno-1-15"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">currentDir</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="ow">mod</span><span class="w"> </span><span class="mi">4</span><span class="p">)</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">keyp</span><span class="p">(</span><span class="n">directions</span><span class="o">[</span><span class="n">i</span><span class="o">][</span><span class="mi">0</span><span class="o">]</span><span class="p">):</span>
<a id="__codelineno-1-16" name="__codelineno-1-16" href="#__codelineno-1-16"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">nextDir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span>
<a id="__codelineno-1-17" name="__codelineno-1-17" href="#__codelineno-1-17"></a>
<a id="__codelineno-1-18" name="__codelineno-1-18" href="#__codelineno-1-18"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickTime</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">tickPeriod</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickFinished</span><span class="p">.</span><span class="n">finished</span><span class="p">():</span>
<a id="__codelineno-1-19" name="__codelineno-1-19" href="#__codelineno-1-19"></a><span class="w"> </span><span class="c"># We choosen our next direction, let the networking know</span>
<a id="__codelineno-1-20" name="__codelineno-1-20" href="#__codelineno-1-20"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">currentDir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">nextDir</span>
<a id="__codelineno-1-21" name="__codelineno-1-21" href="#__codelineno-1-21"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickFinished</span><span class="p">.</span><span class="n">complete</span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">currentDir</span><span class="p">)</span>
<a id="__codelineno-1-22" name="__codelineno-1-22" href="#__codelineno-1-22"></a>
<a id="__codelineno-1-23" name="__codelineno-1-23" href="#__codelineno-1-23"></a><span class="k">proc</span><span class="w"> </span><span class="nf">tick</span><span class="p">(</span><span class="n">g</span><span class="p">:</span><span class="w"> </span><span class="n">Game</span><span class="p">,</span><span class="w"> </span><span class="n">p</span><span class="p">:</span><span class="w"> </span><span class="n">Player</span><span class="p">)</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-1-24" name="__codelineno-1-24" href="#__codelineno-1-24"></a><span class="w"> </span><span class="c"># Move player and check if he lost</span>
<a id="__codelineno-1-25" name="__codelineno-1-25" href="#__codelineno-1-25"></a><span class="w"> </span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">directions</span><span class="o">[</span><span class="n">p</span><span class="p">.</span><span class="n">currentDir</span><span class="o">][</span><span class="mi">1</span><span class="o">]</span>
<a id="__codelineno-1-26" name="__codelineno-1-26" href="#__codelineno-1-26"></a><span class="w"> </span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">directions</span><span class="o">[</span><span class="n">p</span><span class="p">.</span><span class="n">currentDir</span><span class="o">][</span><span class="mi">2</span><span class="o">]</span>
<a id="__codelineno-1-27" name="__codelineno-1-27" href="#__codelineno-1-27"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">gameMap</span><span class="o">[</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="o">]</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">:</span>
<a id="__codelineno-1-28" name="__codelineno-1-28" href="#__codelineno-1-28"></a><span class="w"> </span><span class="n">p</span><span class="p">.</span><span class="n">lost</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">true</span>
<a id="__codelineno-1-29" name="__codelineno-1-29" href="#__codelineno-1-29"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">gameMap</span><span class="o">[</span><span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">p</span><span class="p">.</span><span class="n">color</span>
<a id="__codelineno-1-30" name="__codelineno-1-30" href="#__codelineno-1-30"></a>
<a id="__codelineno-1-31" name="__codelineno-1-31" href="#__codelineno-1-31"></a><span class="k">proc</span><span class="w"> </span><span class="nf">mainLoop</span><span class="p">(</span><span class="n">g</span><span class="p">:</span><span class="w"> </span><span class="n">Game</span><span class="p">,</span><span class="w"> </span><span class="n">peer</span><span class="p">:</span><span class="w"> </span><span class="n">Connection</span><span class="p">)</span><span class="w"> </span><span class="sx">{.async.}</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-1-32" name="__codelineno-1-32" href="#__codelineno-1-32"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">lost</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">remotePlayer</span><span class="p">.</span><span class="n">lost</span><span class="p">):</span>
<a id="__codelineno-1-33" name="__codelineno-1-33" href="#__codelineno-1-33"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickTime</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mf">0.0</span><span class="p">:</span>
<a id="__codelineno-1-34" name="__codelineno-1-34" href="#__codelineno-1-34"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickTime</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<a id="__codelineno-1-35" name="__codelineno-1-35" href="#__codelineno-1-35"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickFinished</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">newFuture</span><span class="o">[</span><span class="nb">int</span><span class="o">]</span><span class="p">()</span>
<a id="__codelineno-1-36" name="__codelineno-1-36" href="#__codelineno-1-36"></a>
<a id="__codelineno-1-37" name="__codelineno-1-37" href="#__codelineno-1-37"></a><span class="w"> </span><span class="c"># Wait for a choosen direction</span>
<a id="__codelineno-1-38" name="__codelineno-1-38" href="#__codelineno-1-38"></a><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">dir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickFinished</span>
<a id="__codelineno-1-39" name="__codelineno-1-39" href="#__codelineno-1-39"></a><span class="w"> </span><span class="c"># Send it</span>
<a id="__codelineno-1-40" name="__codelineno-1-40" href="#__codelineno-1-40"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">peer</span><span class="p">.</span><span class="n">writeLp</span><span class="p">(</span><span class="n">toBytes</span><span class="p">(</span><span class="n">uint32</span><span class="p">(</span><span class="n">dir</span><span class="p">)))</span>
<a id="__codelineno-1-41" name="__codelineno-1-41" href="#__codelineno-1-41"></a>
<a id="__codelineno-1-42" name="__codelineno-1-42" href="#__codelineno-1-42"></a><span class="w"> </span><span class="c"># Get the one from the peer</span>
<a id="__codelineno-1-43" name="__codelineno-1-43" href="#__codelineno-1-43"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">remotePlayer</span><span class="p">.</span><span class="n">currentDir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">int</span><span class="w"> </span><span class="n">uint32</span><span class="p">.</span><span class="n">fromBytes</span><span class="p">(</span><span class="n">await</span><span class="w"> </span><span class="n">peer</span><span class="p">.</span><span class="n">readLp</span><span class="p">(</span><span class="mi">8</span><span class="p">))</span>
<a id="__codelineno-1-44" name="__codelineno-1-44" href="#__codelineno-1-44"></a><span class="w"> </span><span class="c"># Tick the players &amp; restart</span>
<a id="__codelineno-1-45" name="__codelineno-1-45" href="#__codelineno-1-45"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tick</span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">remotePlayer</span><span class="p">)</span>
<a id="__codelineno-1-46" name="__codelineno-1-46" href="#__codelineno-1-46"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tick</span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">)</span>
</code></pre></div>
We'll draw the map &amp; put some texts when necessary:
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="k">proc</span><span class="w"> </span><span class="nf">draw</span><span class="p">(</span><span class="n">g</span><span class="p">:</span><span class="w"> </span><span class="n">Game</span><span class="p">)</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">pos</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">gameMap</span><span class="p">:</span>
<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="w"> </span><span class="n">setColor</span><span class="p">(</span><span class="n">color</span><span class="p">)</span>
<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a><span class="w"> </span><span class="n">boxFill</span><span class="p">(</span><span class="n">pos</span><span class="w"> </span><span class="ow">mod</span><span class="w"> </span><span class="mi">32</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="n">pos</span><span class="w"> </span><span class="ow">div</span><span class="w"> </span><span class="mi">32</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)</span>
<a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">peerFound</span><span class="p">.</span><span class="n">finished</span><span class="p">()):</span>
<a id="__codelineno-2-7" name="__codelineno-2-7" href="#__codelineno-2-7"></a><span class="w"> </span><span class="s">&quot;Matchmaking..&quot;</span>
<a id="__codelineno-2-8" name="__codelineno-2-8" href="#__codelineno-2-8"></a><span class="w"> </span><span class="k">elif</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickTime</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="o">-</span><span class="mf">1.5</span><span class="p">:</span>
<a id="__codelineno-2-9" name="__codelineno-2-9" href="#__codelineno-2-9"></a><span class="w"> </span><span class="s">&quot;Welcome to Etron&quot;</span>
<a id="__codelineno-2-10" name="__codelineno-2-10" href="#__codelineno-2-10"></a><span class="w"> </span><span class="k">elif</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">tickTime</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mf">0.0</span><span class="p">:</span>
<a id="__codelineno-2-11" name="__codelineno-2-11" href="#__codelineno-2-11"></a><span class="w"> </span><span class="s">&quot;- &quot;</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">tickTime</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="s">&quot; -&quot;</span>
<a id="__codelineno-2-12" name="__codelineno-2-12" href="#__codelineno-2-12"></a><span class="w"> </span><span class="k">elif</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">remotePlayer</span><span class="p">.</span><span class="n">lost</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">lost</span><span class="p">:</span>
<a id="__codelineno-2-13" name="__codelineno-2-13" href="#__codelineno-2-13"></a><span class="w"> </span><span class="s">&quot;DEUCE&quot;</span>
<a id="__codelineno-2-14" name="__codelineno-2-14" href="#__codelineno-2-14"></a><span class="w"> </span><span class="k">elif</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">.</span><span class="n">lost</span><span class="p">:</span>
<a id="__codelineno-2-15" name="__codelineno-2-15" href="#__codelineno-2-15"></a><span class="w"> </span><span class="s">&quot;YOU LOOSE&quot;</span>
<a id="__codelineno-2-16" name="__codelineno-2-16" href="#__codelineno-2-16"></a><span class="w"> </span><span class="k">elif</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">remotePlayer</span><span class="p">.</span><span class="n">lost</span><span class="p">:</span>
<a id="__codelineno-2-17" name="__codelineno-2-17" href="#__codelineno-2-17"></a><span class="w"> </span><span class="s">&quot;YOU WON&quot;</span>
<a id="__codelineno-2-18" name="__codelineno-2-18" href="#__codelineno-2-18"></a><span class="w"> </span><span class="k">else</span><span class="p">:</span>
<a id="__codelineno-2-19" name="__codelineno-2-19" href="#__codelineno-2-19"></a><span class="w"> </span><span class="s">&quot;&quot;</span>
<a id="__codelineno-2-20" name="__codelineno-2-20" href="#__codelineno-2-20"></a><span class="w"> </span><span class="n">printc</span><span class="p">(</span><span class="n">text</span><span class="p">,</span><span class="w"> </span><span class="n">screenWidth</span><span class="w"> </span><span class="ow">div</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="n">screenHeight</span><span class="w"> </span><span class="ow">div</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span>
</code></pre></div></p>
<h2 id="matchmaking">Matchmaking</h2>
<p>To find an opponent, we will broadcast our address on a
GossipSub topic, and wait for someone to connect to us.
We will also listen to that topic, and connect to anyone
broadcasting his address.</p>
<p>If we are looking for a game, we'll send <code>ok</code> to let the
peer know that we are available, check that he is also available,
and launch the game.
<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="k">proc</span><span class="w"> </span><span class="nf">new</span><span class="p">(</span><span class="n">T</span><span class="p">:</span><span class="w"> </span><span class="n">typedesc</span><span class="o">[</span><span class="n">GameProto</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">g</span><span class="p">:</span><span class="w"> </span><span class="n">Game</span><span class="p">):</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="w"> </span><span class="k">proc</span><span class="w"> </span><span class="nf">handle</span><span class="p">(</span><span class="n">conn</span><span class="p">:</span><span class="w"> </span><span class="n">Connection</span><span class="p">,</span><span class="w"> </span><span class="n">proto</span><span class="p">:</span><span class="w"> </span><span class="nb">string</span><span class="p">)</span><span class="w"> </span><span class="sx">{.async.}</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="w"> </span><span class="k">defer</span><span class="p">:</span>
<a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">conn</span><span class="p">.</span><span class="n">closeWithEof</span><span class="p">()</span>
<a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">peerFound</span><span class="p">.</span><span class="n">finished</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">hasCandidate</span><span class="p">:</span>
<a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">conn</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a><span class="w"> </span><span class="k">return</span>
<a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">hasCandidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">true</span>
<a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">conn</span><span class="p">.</span><span class="n">writeLp</span><span class="p">(</span><span class="s">&quot;ok&quot;</span><span class="p">)</span>
<a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="s">&quot;ok&quot;</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">string</span><span class="p">.</span><span class="n">fromBytes</span><span class="p">(</span><span class="n">await</span><span class="w"> </span><span class="n">conn</span><span class="p">.</span><span class="n">readLp</span><span class="p">(</span><span class="mi">1024</span><span class="p">)):</span>
<a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">hasCandidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">false</span>
<a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a><span class="w"> </span><span class="k">return</span>
<a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">peerFound</span><span class="p">.</span><span class="n">complete</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<a id="__codelineno-3-14" name="__codelineno-3-14" href="#__codelineno-3-14"></a><span class="w"> </span><span class="c"># The handler of a protocol must wait for the stream to</span>
<a id="__codelineno-3-15" name="__codelineno-3-15" href="#__codelineno-3-15"></a><span class="w"> </span><span class="c"># be finished before returning</span>
<a id="__codelineno-3-16" name="__codelineno-3-16" href="#__codelineno-3-16"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">conn</span><span class="p">.</span><span class="n">join</span><span class="p">()</span>
<a id="__codelineno-3-17" name="__codelineno-3-17" href="#__codelineno-3-17"></a>
<a id="__codelineno-3-18" name="__codelineno-3-18" href="#__codelineno-3-18"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">T</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">codecs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">@[</span><span class="s">&quot;/tron/1.0.0&quot;</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">handler</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">handle</span><span class="p">)</span>
<a id="__codelineno-3-19" name="__codelineno-3-19" href="#__codelineno-3-19"></a>
<a id="__codelineno-3-20" name="__codelineno-3-20" href="#__codelineno-3-20"></a><span class="k">proc</span><span class="w"> </span><span class="nf">networking</span><span class="p">(</span><span class="n">g</span><span class="p">:</span><span class="w"> </span><span class="n">Game</span><span class="p">)</span><span class="w"> </span><span class="sx">{.async.}</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-3-21" name="__codelineno-3-21" href="#__codelineno-3-21"></a><span class="w"> </span><span class="c"># Create our switch, similar to the GossipSub example and</span>
<a id="__codelineno-3-22" name="__codelineno-3-22" href="#__codelineno-3-22"></a><span class="w"> </span><span class="c"># the Discovery examples combined</span>
<a id="__codelineno-3-23" name="__codelineno-3-23" href="#__codelineno-3-23"></a><span class="w"> </span><span class="k">let</span>
<a id="__codelineno-3-24" name="__codelineno-3-24" href="#__codelineno-3-24"></a><span class="w"> </span><span class="n">rdv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">RendezVous</span><span class="p">.</span><span class="n">new</span><span class="p">()</span>
<a id="__codelineno-3-25" name="__codelineno-3-25" href="#__codelineno-3-25"></a><span class="w"> </span><span class="n">switch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SwitchBuilder</span>
<a id="__codelineno-3-26" name="__codelineno-3-26" href="#__codelineno-3-26"></a><span class="w"> </span><span class="p">.</span><span class="n">new</span><span class="p">()</span>
<a id="__codelineno-3-27" name="__codelineno-3-27" href="#__codelineno-3-27"></a><span class="w"> </span><span class="p">.</span><span class="n">withRng</span><span class="p">(</span><span class="n">newRng</span><span class="p">())</span>
<a id="__codelineno-3-28" name="__codelineno-3-28" href="#__codelineno-3-28"></a><span class="w"> </span><span class="p">.</span><span class="n">withAddresses</span><span class="p">(</span><span class="o">@[</span><span class="n">MultiAddress</span><span class="p">.</span><span class="n">init</span><span class="p">(</span><span class="s">&quot;/ip4/0.0.0.0/tcp/0&quot;</span><span class="p">).</span><span class="n">tryGet</span><span class="p">()</span><span class="o">]</span><span class="p">)</span>
<a id="__codelineno-3-29" name="__codelineno-3-29" href="#__codelineno-3-29"></a><span class="w"> </span><span class="p">.</span><span class="n">withTcpTransport</span><span class="p">()</span>
<a id="__codelineno-3-30" name="__codelineno-3-30" href="#__codelineno-3-30"></a><span class="w"> </span><span class="p">.</span><span class="n">withYamux</span><span class="p">()</span>
<a id="__codelineno-3-31" name="__codelineno-3-31" href="#__codelineno-3-31"></a><span class="w"> </span><span class="p">.</span><span class="n">withNoise</span><span class="p">()</span>
<a id="__codelineno-3-32" name="__codelineno-3-32" href="#__codelineno-3-32"></a><span class="w"> </span><span class="p">.</span><span class="n">withRendezVous</span><span class="p">(</span><span class="n">rdv</span><span class="p">)</span>
<a id="__codelineno-3-33" name="__codelineno-3-33" href="#__codelineno-3-33"></a><span class="w"> </span><span class="p">.</span><span class="n">build</span><span class="p">()</span>
<a id="__codelineno-3-34" name="__codelineno-3-34" href="#__codelineno-3-34"></a><span class="w"> </span><span class="n">dm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DiscoveryManager</span><span class="p">()</span>
<a id="__codelineno-3-35" name="__codelineno-3-35" href="#__codelineno-3-35"></a><span class="w"> </span><span class="n">gameProto</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">GameProto</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<a id="__codelineno-3-36" name="__codelineno-3-36" href="#__codelineno-3-36"></a><span class="w"> </span><span class="n">gossip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">GossipSub</span><span class="p">.</span><span class="n">init</span><span class="p">(</span><span class="n">switch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">switch</span><span class="p">,</span><span class="w"> </span><span class="n">triggerSelf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">false</span><span class="p">)</span>
<a id="__codelineno-3-37" name="__codelineno-3-37" href="#__codelineno-3-37"></a><span class="w"> </span><span class="n">dm</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">RendezVousInterface</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">rdv</span><span class="p">))</span>
<a id="__codelineno-3-38" name="__codelineno-3-38" href="#__codelineno-3-38"></a>
<a id="__codelineno-3-39" name="__codelineno-3-39" href="#__codelineno-3-39"></a><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">mount</span><span class="p">(</span><span class="n">gossip</span><span class="p">)</span>
<a id="__codelineno-3-40" name="__codelineno-3-40" href="#__codelineno-3-40"></a><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">mount</span><span class="p">(</span><span class="n">gameProto</span><span class="p">)</span>
<a id="__codelineno-3-41" name="__codelineno-3-41" href="#__codelineno-3-41"></a>
<a id="__codelineno-3-42" name="__codelineno-3-42" href="#__codelineno-3-42"></a><span class="w"> </span><span class="n">gossip</span><span class="p">.</span><span class="n">subscribe</span><span class="p">(</span>
<a id="__codelineno-3-43" name="__codelineno-3-43" href="#__codelineno-3-43"></a><span class="w"> </span><span class="s">&quot;/tron/matchmaking&quot;</span><span class="p">,</span>
<a id="__codelineno-3-44" name="__codelineno-3-44" href="#__codelineno-3-44"></a><span class="w"> </span><span class="n">proc</span><span class="p">(</span><span class="n">topic</span><span class="p">:</span><span class="w"> </span><span class="nb">string</span><span class="p">,</span><span class="w"> </span><span class="n">data</span><span class="p">:</span><span class="w"> </span><span class="nb">seq</span><span class="o">[</span><span class="n">byte</span><span class="o">]</span><span class="p">)</span><span class="w"> </span><span class="sx">{.async.}</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-3-45" name="__codelineno-3-45" href="#__codelineno-3-45"></a><span class="w"> </span><span class="c"># If we are still looking for an opponent,</span>
<a id="__codelineno-3-46" name="__codelineno-3-46" href="#__codelineno-3-46"></a><span class="w"> </span><span class="c"># try to match anyone broadcasting its address</span>
<a id="__codelineno-3-47" name="__codelineno-3-47" href="#__codelineno-3-47"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">peerFound</span><span class="p">.</span><span class="n">finished</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">hasCandidate</span><span class="p">:</span>
<a id="__codelineno-3-48" name="__codelineno-3-48" href="#__codelineno-3-48"></a><span class="w"> </span><span class="k">return</span>
<a id="__codelineno-3-49" name="__codelineno-3-49" href="#__codelineno-3-49"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">hasCandidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">true</span>
<a id="__codelineno-3-50" name="__codelineno-3-50" href="#__codelineno-3-50"></a>
<a id="__codelineno-3-51" name="__codelineno-3-51" href="#__codelineno-3-51"></a><span class="w"> </span><span class="k">try</span><span class="p">:</span>
<a id="__codelineno-3-52" name="__codelineno-3-52" href="#__codelineno-3-52"></a><span class="w"> </span><span class="k">let</span>
<a id="__codelineno-3-53" name="__codelineno-3-53" href="#__codelineno-3-53"></a><span class="w"> </span><span class="p">(</span><span class="n">peerId</span><span class="p">,</span><span class="w"> </span><span class="n">multiAddress</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parseFullAddress</span><span class="p">(</span><span class="n">data</span><span class="p">).</span><span class="n">tryGet</span><span class="p">()</span>
<a id="__codelineno-3-54" name="__codelineno-3-54" href="#__codelineno-3-54"></a><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">dial</span><span class="p">(</span><span class="n">peerId</span><span class="p">,</span><span class="w"> </span><span class="o">@[</span><span class="n">multiAddress</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">gameProto</span><span class="p">.</span><span class="n">codec</span><span class="p">)</span>
<a id="__codelineno-3-55" name="__codelineno-3-55" href="#__codelineno-3-55"></a>
<a id="__codelineno-3-56" name="__codelineno-3-56" href="#__codelineno-3-56"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">stream</span><span class="p">.</span><span class="n">writeLp</span><span class="p">(</span><span class="s">&quot;ok&quot;</span><span class="p">)</span>
<a id="__codelineno-3-57" name="__codelineno-3-57" href="#__codelineno-3-57"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">await</span><span class="w"> </span><span class="n">stream</span><span class="p">.</span><span class="n">readLp</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="s">&quot;ok&quot;</span><span class="p">.</span><span class="n">toBytes</span><span class="p">:</span>
<a id="__codelineno-3-58" name="__codelineno-3-58" href="#__codelineno-3-58"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">hasCandidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">false</span>
<a id="__codelineno-3-59" name="__codelineno-3-59" href="#__codelineno-3-59"></a><span class="w"> </span><span class="k">return</span>
<a id="__codelineno-3-60" name="__codelineno-3-60" href="#__codelineno-3-60"></a><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">peerFound</span><span class="p">.</span><span class="n">complete</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span>
<a id="__codelineno-3-61" name="__codelineno-3-61" href="#__codelineno-3-61"></a><span class="w"> </span><span class="c"># We are &quot;player 2&quot;</span>
<a id="__codelineno-3-62" name="__codelineno-3-62" href="#__codelineno-3-62"></a><span class="w"> </span><span class="n">swap</span><span class="p">(</span><span class="n">g</span><span class="p">.</span><span class="n">localPlayer</span><span class="p">,</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">remotePlayer</span><span class="p">)</span>
<a id="__codelineno-3-63" name="__codelineno-3-63" href="#__codelineno-3-63"></a><span class="w"> </span><span class="k">except</span><span class="w"> </span><span class="n">CatchableError</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">exc</span><span class="p">:</span>
<a id="__codelineno-3-64" name="__codelineno-3-64" href="#__codelineno-3-64"></a><span class="w"> </span><span class="k">discard</span>
<a id="__codelineno-3-65" name="__codelineno-3-65" href="#__codelineno-3-65"></a><span class="w"> </span><span class="p">,</span>
<a id="__codelineno-3-66" name="__codelineno-3-66" href="#__codelineno-3-66"></a><span class="w"> </span><span class="p">)</span>
<a id="__codelineno-3-67" name="__codelineno-3-67" href="#__codelineno-3-67"></a>
<a id="__codelineno-3-68" name="__codelineno-3-68" href="#__codelineno-3-68"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<a id="__codelineno-3-69" name="__codelineno-3-69" href="#__codelineno-3-69"></a><span class="w"> </span><span class="k">defer</span><span class="p">:</span>
<a id="__codelineno-3-70" name="__codelineno-3-70" href="#__codelineno-3-70"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">stop</span><span class="p">()</span>
<a id="__codelineno-3-71" name="__codelineno-3-71" href="#__codelineno-3-71"></a>
<a id="__codelineno-3-72" name="__codelineno-3-72" href="#__codelineno-3-72"></a><span class="w"> </span><span class="c"># As explained in the last tutorial, we need a bootnode to be able</span>
<a id="__codelineno-3-73" name="__codelineno-3-73" href="#__codelineno-3-73"></a><span class="w"> </span><span class="c"># to find peers. We could use any libp2p running rendezvous (or any</span>
<a id="__codelineno-3-74" name="__codelineno-3-74" href="#__codelineno-3-74"></a><span class="w"> </span><span class="c"># node running tron). We will take it&#39;s MultiAddress from the command</span>
<a id="__codelineno-3-75" name="__codelineno-3-75" href="#__codelineno-3-75"></a><span class="w"> </span><span class="c"># line parameters</span>
<a id="__codelineno-3-76" name="__codelineno-3-76" href="#__codelineno-3-76"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">paramCount</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="p">:</span>
<a id="__codelineno-3-77" name="__codelineno-3-77" href="#__codelineno-3-77"></a><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="p">(</span><span class="n">peerId</span><span class="p">,</span><span class="w"> </span><span class="n">multiAddress</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">paramStr</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="n">parseFullAddress</span><span class="p">().</span><span class="n">tryGet</span><span class="p">()</span>
<a id="__codelineno-3-78" name="__codelineno-3-78" href="#__codelineno-3-78"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">peerId</span><span class="p">,</span><span class="w"> </span><span class="o">@[</span><span class="n">multiAddress</span><span class="o">]</span><span class="p">)</span>
<a id="__codelineno-3-79" name="__codelineno-3-79" href="#__codelineno-3-79"></a><span class="w"> </span><span class="k">else</span><span class="p">:</span>
<a id="__codelineno-3-80" name="__codelineno-3-80" href="#__codelineno-3-80"></a><span class="w"> </span><span class="n">echo</span><span class="w"> </span><span class="s">&quot;No bootnode provided, listening on: &quot;</span><span class="p">,</span><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">peerInfo</span><span class="p">.</span><span class="n">fullAddrs</span><span class="p">.</span><span class="n">tryGet</span><span class="p">()</span>
<a id="__codelineno-3-81" name="__codelineno-3-81" href="#__codelineno-3-81"></a>
<a id="__codelineno-3-82" name="__codelineno-3-82" href="#__codelineno-3-82"></a><span class="w"> </span><span class="c"># Discover peers from the bootnode, and connect to them</span>
<a id="__codelineno-3-83" name="__codelineno-3-83" href="#__codelineno-3-83"></a><span class="w"> </span><span class="n">dm</span><span class="p">.</span><span class="n">advertise</span><span class="p">(</span><span class="n">RdvNamespace</span><span class="p">(</span><span class="s">&quot;tron&quot;</span><span class="p">))</span>
<a id="__codelineno-3-84" name="__codelineno-3-84" href="#__codelineno-3-84"></a><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">discoveryQuery</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dm</span><span class="p">.</span><span class="n">request</span><span class="p">(</span><span class="n">RdvNamespace</span><span class="p">(</span><span class="s">&quot;tron&quot;</span><span class="p">))</span>
<a id="__codelineno-3-85" name="__codelineno-3-85" href="#__codelineno-3-85"></a><span class="w"> </span><span class="n">discoveryQuery</span><span class="p">.</span><span class="n">forEach</span><span class="p">:</span>
<a id="__codelineno-3-86" name="__codelineno-3-86" href="#__codelineno-3-86"></a><span class="w"> </span><span class="k">try</span><span class="p">:</span>
<a id="__codelineno-3-87" name="__codelineno-3-87" href="#__codelineno-3-87"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">peer</span><span class="o">[</span><span class="n">PeerId</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">peer</span><span class="p">.</span><span class="n">getAll</span><span class="p">(</span><span class="n">MultiAddress</span><span class="p">))</span>
<a id="__codelineno-3-88" name="__codelineno-3-88" href="#__codelineno-3-88"></a><span class="w"> </span><span class="k">except</span><span class="w"> </span><span class="n">CatchableError</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">exc</span><span class="p">:</span>
<a id="__codelineno-3-89" name="__codelineno-3-89" href="#__codelineno-3-89"></a><span class="w"> </span><span class="n">echo</span><span class="w"> </span><span class="s">&quot;Failed to dial a peer: &quot;</span><span class="p">,</span><span class="w"> </span><span class="n">exc</span><span class="p">.</span><span class="n">msg</span>
<a id="__codelineno-3-90" name="__codelineno-3-90" href="#__codelineno-3-90"></a>
<a id="__codelineno-3-91" name="__codelineno-3-91" href="#__codelineno-3-91"></a><span class="w"> </span><span class="c"># We will try to publish our address multiple times, in case</span>
<a id="__codelineno-3-92" name="__codelineno-3-92" href="#__codelineno-3-92"></a><span class="w"> </span><span class="c"># it takes time to establish connections with other GossipSub peers</span>
<a id="__codelineno-3-93" name="__codelineno-3-93" href="#__codelineno-3-93"></a><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="n">published</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">false</span>
<a id="__codelineno-3-94" name="__codelineno-3-94" href="#__codelineno-3-94"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">published</span><span class="p">:</span>
<a id="__codelineno-3-95" name="__codelineno-3-95" href="#__codelineno-3-95"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">sleepAsync</span><span class="p">(</span><span class="mf">500.</span><span class="n">milliseconds</span><span class="p">)</span>
<a id="__codelineno-3-96" name="__codelineno-3-96" href="#__codelineno-3-96"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">fullAddr</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">switch</span><span class="p">.</span><span class="n">peerInfo</span><span class="p">.</span><span class="n">fullAddrs</span><span class="p">.</span><span class="n">tryGet</span><span class="p">():</span>
<a id="__codelineno-3-97" name="__codelineno-3-97" href="#__codelineno-3-97"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">await</span><span class="w"> </span><span class="n">gossip</span><span class="p">.</span><span class="n">publish</span><span class="p">(</span><span class="s">&quot;/tron/matchmaking&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">fullAddr</span><span class="p">.</span><span class="n">bytes</span><span class="p">))</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">:</span>
<a id="__codelineno-3-98" name="__codelineno-3-98" href="#__codelineno-3-98"></a><span class="w"> </span><span class="n">published</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">false</span>
<a id="__codelineno-3-99" name="__codelineno-3-99" href="#__codelineno-3-99"></a><span class="w"> </span><span class="k">break</span>
<a id="__codelineno-3-100" name="__codelineno-3-100" href="#__codelineno-3-100"></a><span class="w"> </span><span class="n">published</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">true</span>
<a id="__codelineno-3-101" name="__codelineno-3-101" href="#__codelineno-3-101"></a>
<a id="__codelineno-3-102" name="__codelineno-3-102" href="#__codelineno-3-102"></a><span class="w"> </span><span class="n">discoveryQuery</span><span class="p">.</span><span class="n">stop</span><span class="p">()</span>
<a id="__codelineno-3-103" name="__codelineno-3-103" href="#__codelineno-3-103"></a>
<a id="__codelineno-3-104" name="__codelineno-3-104" href="#__codelineno-3-104"></a><span class="w"> </span><span class="c"># We now wait for someone to connect to us (or for us to connect to someone)</span>
<a id="__codelineno-3-105" name="__codelineno-3-105" href="#__codelineno-3-105"></a><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="n">peerConn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">peerFound</span>
<a id="__codelineno-3-106" name="__codelineno-3-106" href="#__codelineno-3-106"></a><span class="w"> </span><span class="k">defer</span><span class="p">:</span>
<a id="__codelineno-3-107" name="__codelineno-3-107" href="#__codelineno-3-107"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">peerConn</span><span class="p">.</span><span class="n">closeWithEof</span><span class="p">()</span>
<a id="__codelineno-3-108" name="__codelineno-3-108" href="#__codelineno-3-108"></a>
<a id="__codelineno-3-109" name="__codelineno-3-109" href="#__codelineno-3-109"></a><span class="w"> </span><span class="n">await</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="n">mainLoop</span><span class="p">(</span><span class="n">peerConn</span><span class="p">)</span>
<a id="__codelineno-3-110" name="__codelineno-3-110" href="#__codelineno-3-110"></a>
<a id="__codelineno-3-111" name="__codelineno-3-111" href="#__codelineno-3-111"></a><span class="k">let</span>
<a id="__codelineno-3-112" name="__codelineno-3-112" href="#__codelineno-3-112"></a><span class="w"> </span><span class="n">game</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Game</span><span class="p">.</span><span class="n">new</span><span class="p">()</span>
<a id="__codelineno-3-113" name="__codelineno-3-113" href="#__codelineno-3-113"></a><span class="w"> </span><span class="n">netFut</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">networking</span><span class="p">(</span><span class="n">game</span><span class="p">)</span>
<a id="__codelineno-3-114" name="__codelineno-3-114" href="#__codelineno-3-114"></a><span class="n">nico</span><span class="p">.</span><span class="n">init</span><span class="p">(</span><span class="s">&quot;Status&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Tron&quot;</span><span class="p">)</span>
<a id="__codelineno-3-115" name="__codelineno-3-115" href="#__codelineno-3-115"></a><span class="n">nico</span><span class="p">.</span><span class="n">createWindow</span><span class="p">(</span><span class="s">&quot;Tron&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="n">mapSize</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="kp">false</span><span class="p">)</span>
<a id="__codelineno-3-116" name="__codelineno-3-116" href="#__codelineno-3-116"></a><span class="n">nico</span><span class="p">.</span><span class="n">run</span><span class="p">(</span>
<a id="__codelineno-3-117" name="__codelineno-3-117" href="#__codelineno-3-117"></a><span class="w"> </span><span class="n">proc</span><span class="p">()</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-3-118" name="__codelineno-3-118" href="#__codelineno-3-118"></a><span class="w"> </span><span class="k">discard</span>
<a id="__codelineno-3-119" name="__codelineno-3-119" href="#__codelineno-3-119"></a><span class="w"> </span><span class="p">,</span>
<a id="__codelineno-3-120" name="__codelineno-3-120" href="#__codelineno-3-120"></a><span class="w"> </span><span class="n">proc</span><span class="p">(</span><span class="n">dt</span><span class="p">:</span><span class="w"> </span><span class="nb">float32</span><span class="p">)</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-3-121" name="__codelineno-3-121" href="#__codelineno-3-121"></a><span class="w"> </span><span class="n">game</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">dt</span><span class="p">)</span>
<a id="__codelineno-3-122" name="__codelineno-3-122" href="#__codelineno-3-122"></a><span class="w"> </span><span class="p">,</span>
<a id="__codelineno-3-123" name="__codelineno-3-123" href="#__codelineno-3-123"></a><span class="w"> </span><span class="n">proc</span><span class="p">()</span><span class="w"> </span><span class="o">=</span>
<a id="__codelineno-3-124" name="__codelineno-3-124" href="#__codelineno-3-124"></a><span class="w"> </span><span class="n">game</span><span class="p">.</span><span class="n">draw</span><span class="p">()</span>
<a id="__codelineno-3-125" name="__codelineno-3-125" href="#__codelineno-3-125"></a><span class="w"> </span><span class="p">,</span>
<a id="__codelineno-3-126" name="__codelineno-3-126" href="#__codelineno-3-126"></a><span class="p">)</span>
<a id="__codelineno-3-127" name="__codelineno-3-127" href="#__codelineno-3-127"></a><span class="n">waitFor</span><span class="p">(</span><span class="n">netFut</span><span class="p">.</span><span class="n">cancelAndWait</span><span class="p">())</span>
</code></pre></div>
And that's it! If you want to run this code locally, the simplest way is to use the
first node as a boot node for the second one. But you can also use any rendezvous node</p>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.instant", "search.highlight"], "search": "../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.ad660dcc.min.js"></script>
</body>
</html>