Coder Social home page Coder Social logo

bradygaster / rockpaperorleans Goto Github PK

View Code? Open in Web Editor NEW
36.0 3.0 14.0 633 KB

A distributed dotnet game written as multiple microservices that play rock, paper, scissors. You can send in a pull request with your own player logic and we'll host it for you.

C# 63.19% HTML 27.34% Dockerfile 0.24% Bicep 9.23%
azd-templates azure dotnet orleans

rockpaperorleans's Introduction

Rock, Paper, Orleans

Rock, Paper, Orleans (RPO) is a game built using dotnet, .NET Aspire, and Orleans. The idea behind RPO is that you write a "player bot" in which you implement your player logic. The game engine essentially runs forever as a dotnet Worker service (which we may tweak later to run as an Orleans timer). Players wait in a lobby, and are matchmade each round randomly. The game is played, the winner and loser recorded, and the next game started.

Prerequisites

To get this project up and running on your own machine and in your own Azure subscription, you'll need to install .NET Aspire. If you want to deploy the app to Azure Container Apps, you'll need an Azure subscription, too.

Getting Started

Here's what RPO looks like when you have it up and running. In this screenshot, we're using the dark theme, and we have all the default players (at the time of v1's release) running in the app.

Rock, Paper, Orleans running in the browser.

The game topology consists of a series of Visual Studio projects you'll find in the src folder. Here's a breakout of these projects so you understand what's what.

Project Purpose
GameController The dotnet worker service project that hosts the game engine, or the "game loop". This project's front door is the Orleans Dashboard, as this is the one silo in the solution that hosts Grains.
Leaderboard This is the front-end UI of the app.
Players Hosts the more basic players in the app.
Rando Hosts the "random" player and the "slow random" player, which emulates a player taking a longer period of time to perform their move. Also contains the Captain Obvious player, which demonstrates implementing a simple logic flow in a player's implementation.
.Abstractions This project contains the various Grain interfaces or abstractions, as well as any models (the "nouns" in the system as well as the behavioral abstractions) are contained here.
.Grains Implementations of the Grain interfaces.
RockPaperOrleans Infrastructure and convenience classes that simplify the programming model of building and hosting players.
AppHost The .NET Aspire orchestration or App Host project.
Defaults The .NET Aspire defaults project most of the other projects reference.

Running the app

Whether you run the app using Visual Studio, VS Code, or the command line, just run the App Host project.

Deploying the app

We used AZD to make this process easier. You'll find that we adhered to the AZD-friendly layout for the infra parts, where our Bicep files and ARM parameter files are located. This makes deployment as simple as:

  1. azd init - allow azd to infer what it should do based on azd's integration with dotnet run for Aspire projects.
  2. azd up to create the supporting Azure resources and deploy the app.

Writing a player

To write a player, you create a new class that inherits from BasePlayerGrain. You can override any of the methods, but you're only required to implement the Go() method. Go is where all the logic for your player is stored.

Let's walk through some of the players we shipped with v1 of RPO give you an overview of how to write a player bot, and then later, how to host it (don't worry, it's simple).

Players Examples

In the Players project, there are a series of very-basic players that behave in very-obvious ways.

public class AlwaysPaper : BasePlayerGrain
{
    public override Task<Play> Go(Player opponent) => Task.FromResult(Play.Paper);
}

public class AlwaysRock : BasePlayerGrain
{
    public override Task<Play> Go(Player opponent) => Task.FromResult(Play.Rock);
}

public class AlwaysScissors : BasePlayerGrain
{
    public override Task<Play> Go(Player opponent) => Task.FromResult(Play.Scissors);
}

Rando Examples

The Rando project contains, obviously, the Rando player, which, probably-also-obviously, throws random moves.

One day we'll implement logic to control a bot that just stops or is too slow, but for now we'll control that using code reviews.

The code for Rando is, again, probably pretty obvious in nature.

public class Rando : BasePlayerGrain
{
    public override Task<Play> Go(Player opponent) => Task.FromResult((Play)Random.Shared.Next(0, 3));
}

Mr. Presumptive

MrPresumptive bases his move off the name of the player, or more generally, a component of the name of the player using very-very-basic pattern matching.

public class MrPresumptive : BasePlayerGrain
{
    public override Task<Play> Go(Player opponent)
    {
        var result = opponent.Name switch
        {
            { } name when name.Contains("scissors", StringComparison.OrdinalIgnoreCase) => Play.Rock,
            { } name when name.Contains("rock", StringComparison.OrdinalIgnoreCase) => Play.Paper,
            { } name when name.Contains("paper", StringComparison.OrdinalIgnoreCase) => Play.Scissors,
            _ => (Play)Random.Shared.Next(0, 3)
        };

        return Task.FromResult(result);
    }
}

Hosting a player

Both Rando and Players show examples of how to host multiple players in one Kestrel host. We've provided the extension method AddRockPaperOrleans you can use on the WebApplicationBuilder of your own host code, and the AddPlayer<T> method which takes any BasePlayerGrain inheritor.

That means you can host multiple players, like our Players host:

builder.AddRockPaperOrleans(siloBuilder => 
    siloBuilder.AddPlayer<AlwaysPaper>()
               .AddPlayer<AlwaysRock>()
               .AddPlayer<AlwaysScissors>());

Logs

RPO has a ton of logs to aid with development-time and debugging. You'll want to update the appsettings.json to "turn down the log verbosity" to warning or lower once you're ready to deploy "for real" or you'll have a LOT of logs.

Your bot can do better!

We'd like you to write your own player, so feel free to send a pull request. When you do, please either add your player to the Players project, or write your own host. In addition, please add your own workflow in the .github folder, so we can deploy your player separately if you're hosting it on your own.

rockpaperorleans's People

Contributors

bradygaster avatar jongio avatar reubenbond avatar rjygraham avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

rockpaperorleans's Issues

Updating/work-with this template for GHA and Azd Devcontainer feature.

We are updating this template to support new features in Github Action and Azd Devcontainer.

  1. For the Github Action feature: We will remove two lines of code on container image and add GHA code after checkout step in the .github/workflow/provision.yml and provision_and_deploy.yml files. (Shown as below)

image

  1. For the Azd Devcontainer feature: We will remove dockerfile in .devcontainer folder and add the following code in devcontainer.json file,
"ghcr.io/azure/azure-dev/azd:latest": {}

and image also need to be add instead of build. Such as:
image

@rajeshkamal5050 , @bradygaster , @jongio for notification.

Invalid reference format: repository name must be lowercase

Describe the issue:
When executing the azd package command, building service 'gamecontroller' needs your repository name must be lowercase.
image

Repro Steps:

  1. azd init -t <template_name>
  2. azd package

Environment:
OS: Windows
Azd version: azd version 0.7.0-beta.2-pr.2672227 (commit dec4eb2c9f5932d3bd41f7e66b41c775c050ad48)

Expected behavior:
Execute the azd package command can pass.

@rajeshkamal5050, @bradygaster for notification.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.