Collective development of a server for variants

How about supporting multiple classes of stones (i.e., different types of stones with varying capabilities)? Or radically different winning objectives, like the capture of a special type of stone?

3 Likes

I legit think implementing chess would be a good test of the extensibility of the project haha

3 Likes

Okay I think the big question for me is how do we start?

  • Like are we doing “green field” or extending an existing project?

  • If green field, what tech stack? One theme I saw in the existing projects was that there needs to be a way to share code between client and server bc of all the rulesets and whatnot. That could be a good reason to do a node.js server, but compiling to webasm works too.

  • If existing, would it be a fork? I think it’d be nice for everyone who’s contributing to have push-to-main priviledges (at least at first)

3 Likes

I don’t know yet. Maybe we should take a look at Variant Go Server and sketch out how certain features could be implemented? And maybe how we’d implement them if we were doing it from scratch?

hiden wall of text

I don’t have much experience as a programmer, I started working as a junior software engineer in July last year. Plust I didn’t study informatics but mathematics, so I don’t feel qualified to answer questions such as “what programming language / sdk’s should we use?” etc.

I think that is useful, plus I believe that we need to be able to communicate between client and server in both directions.

In general I like the idea of making variants combineable, like variant go server does. And for this purpose it would be nice to extend VGS. But I can see some drawbacks.
Probably the more variants we support, the more difficult will it be to implement them in a compatible way (I think it might be helpful to categorise them by what parts of the rules they change, e.g. the board layout, the move sequence, the objective etc.). And the bigger the project, the more work to change some integral parts.
Plus I believe that combining many variants is maybe not as exciting as trying out one new variant. For example if we have four variants that can be combined freely, that makes 16 possibilities. Trying everything might be a bit overwhelming.
For those reasons I don’t mind starting a new project. But I’m also down to try to extend VGS (or one of the others) :slight_smile:

3 Likes

If you’re doing things on graphs, potentially supporting hex boards, there’s other go variants or Go inspired games one could think of also like

  • hex go (go on a hexagonal board)
  • trigo (two moves per player on a hex board, except Black plays one stone on the first move)
  • Blooms (hex board, but two colors per player, and the objective is N captures. Place one or two stones each turn but of different colors. First player places only one stone)
  • Keil (hex board, but connections are not just being adjacent, it’s about having mutually adjacent points that don’t contain the other player color)
  • Redstone (normal grid but captures are redstones, no passing, capture all opponents stones to win)
4 Likes

If I understand it correctly, Keil is an example for a variant that cannot (feasibly) be played on any grid. If you were to apply Keil’s definition of connectivity and liberties to a rectangular board, then any stone would immediately be captured due to having no liberty … then all moves are illegal. Just goes to show that combining variants can be tricky.

Regardless these are certainly some good ideas!

3 Likes

I have a suggestion: We discuss which basic elements we need and then we decide whether it is easier to change an existing project or start something from scratch.
Currently we know that:

  • There will be different variants which define the rules of the game
  • The game will be played on a board. A board consists of intersections (nodes) which are connected to other intersections. Boards are mostly represented in 2D, but might also be represented in 3D or something else.
  • At certain times certain players are allowed to place stones on (empty) board intersections (or if chess, move stones/pieces from one intersection to another)
  • If multiple players are allowed to make moves at the same time, rules for collision handling are needed.
  • Stones have different attributes (e.g. colors, visiblity, display colors)
  • Stones (may) form groups with other stones, normally by being adjacent to each other.
  • Stones/groups can be removed, e.g. when all adjacent intersections are occupied by stones of a different color.
  • Players can be eliminated i.e. lose the possibility to place stones/make moves.
  • Win conditions define the result of a game and may vary between variants.

Currently I’m tending towards building something new, because of Variant Go Server’s biases towards chinese scoring, alternating moves, intersections with x-y-coordinates, but we could probably use a lot of the existing code, so I still think changing Variant Go Server might be a viable option too.

2 Likes

To expand on these points:

  • Go and Go variants have a scoring phase where players need to agree on dead stones (even it they arent fully surrounded).

That’s a difficult UX topic even without variants!

Variant Go Server

One question: has anyone managed to get the server running? I tried and failed, but that’s says more about my (lack of) docker experience than anything else…

2 Likes

this might be the reason for

One way to bypass the UX problem that is the scoring phase is to use area scoring with the exception that dead stones have to be captured (i.e. Tromp Taylor Scoring)

AFAIK that is how dipgo does it (or at least used to do it), and maybe VGS too …? I’m not entirely sure.

1 Like

I’ve been thinking how to model a game in an abstract (mathematical) way that doesn’t restrict ourselves too much, but still helps by providing some structure. (Just to be sure, I’m not proposing we use these as part of our data structure.) Here’s the ideas I came up with:

A game has a list of players.

At all times a game has a game-state. (contains all informations needed for rule considerations, might e.g. include information that defines …

  • the board position
  • previous game-states
  • which player has which informations

etc.)

A game has rounds. (discrete time units where players make decisions. I find this a sensible assumption unless we want to include “real-time” variants.)

During each round, all players have options. (can depend on the game-state, and a player can have zero options)

A game has a transition function, which takes the game-state and all options chosen by players this round as input, and replaces the current game-state by a new one whenever we proceed to the next round.

The game ends when reaching a game-state where all players have zero options.

I believe these assumptions facilitate all variants that we listed so far. (although I’m not 100% confident :sweat_smile:) There are still unanswered questions such as

  • under what circumstances do we proceed to the next round? (e.g. when all players made a choice, or after a fixed time etc.)
  • are there mechanics working outside the turn-based system? (e.g. resignation)

Not sure if any of this helps though, sorry if I’m being too abstract here.

4 Likes

True, that’s something to consider too.

No, I didn’t try it yet.

I think it’s good to think about it like that. And that’s a perspective I haven’t discovered in the code of VGS, it seems that its code evolved variant by variant (“if this variant, do this” pops up a lot in the code) and it’s lacking some sort of abstraction layer.

2 Likes

To propose a simpler alternative, what if the server only handled keeping track of a sequence of board positions, allowing various combinations of colors but making no attempt to enforce any particular rules? Like Vsotvep MulticolorGo but with a recorded game history and a chat window. If we got that much done, maybe additional modules later could implement some rules.

2 Likes

I think we’re on the same page as far as abstract representation goes!

Confession: I’ve actually been working on something, just to kind of see if I could crank out a prototype. Turns out it’s hard to try to build a backend, frontend and middle end from scratch at the same time :laughing:

Anyway, here's what I've got so far for an abstract base class
/**
 * An abstract class that can represent any game on the server
 */
export abstract class AbstractGame<
  GameConfig = object,
  GameState = object,
  DeadStones = string
> {
  private phase_: GamePhase = "play";
  private result_: string = "";

  constructor(protected readonly config: GameConfig) {}

  /**
   * Play one move by the specified player.
   *
   * May throw if the move was invalid and we should return that information
   * to the user
   */
  abstract playMove(move: MovesType): void;

  /** Returns complete representation of the game. */
  abstract exportState(): GameState;

  /**
   * Returns the list of players that need to play a move the next round.
   */
  abstract nextToPlay(): number[];

  /**
   * Total number of players required for this game.  The players will be
   * referenced by number (zero-indexed).
   */
  abstract numPlayers(): number;

  get phase(): GamePhase {
    return this.phase_;
  }
  protected set phase(p: GamePhase) {
    this.phase_ = p;
  }

  // Scoring

  /** Sets the dead stones on the board */
  setDeadStones(_dead_stones: DeadStones): void {
    // Subclasses may reimplement this function if there is a scoring phase.
  }

  /** Ends the scoring phase and finalizes the result.
   *
   * This should likely be reimplemented if setDeadStones has been reimplemented.
   */
  finalizeScore() {
    this.phase_ = "gameover";
  }

  /** Get result.  Will only be called when phase() is "gameover" */
  get result(): string {
    return this.result_;
  }
  /** Sets the result of the game. */
  protected set result(res: string) {
    this.result_ = res;
  }

  canResign(player_: number): boolean {
    return this.numPlayers() === 2;
  }
  resign(player: number) {
    this.phase_ = "gameover";
    const opponent = 1 - player;
    this.result_ = `Player ${opponent} + R`;
  }
}
export interface MovesType {
  [player: number]: string;
}

export type GamePhase = "play" | "scoring" | "gameover";

The only thing that doesn’t feel abstract is the scoring, but as you mentioned, this can be avoided by using Tromp-Taylor scoring. Still, I think at some point, we might want to implement more mainstream score agreement.

I wasn’t going to share the codebase before I had some running game, but if either of you has interest in checking it out/getting it running, I’m happy to make the repo public.

2 Likes

Interesting idea. In the end I’d want a server that does enforce the rules, but building on what you’ve proposed could be a way to go.

Nice work. And yes, keeping track of so many things at the same time can be hard, focusing on what is important for whatever -end one is working on should help.

Some variants don’t even have scoring, like Go Battle Royale (and chess).

2 Likes

It’s just the running joke now I suppose :slight_smile:

2 Likes

What programming languages does everybody know? Recently I gained a bit experience with Typescript (with Angular) and some more with C#.
(long time ago C++ and even longer ago Delphi)

1 Like

I normally use JavaScript, C# or Java. I have used TypeScript too, but never set up a project.

2 Likes

What happens if everyone passes?

Mostly TS/JS, Python, C++. A little Java too. I’m okay learning something new if y’all are leaning a certain way.

I think I’ve mentioned before I lean toward something node/js just because of the shared code, but it’s not a requirement!

1 Like

Me too. Although deno might be a modern alternative for node. And I’d like to try more TypeScript to get more experience, but I’d be okay with plain JS or something else too.

2 Likes