Giter VIP home page Giter VIP logo

doppelkopf's People

Contributors

davidkaufmann avatar dependabot[bot] avatar hamvocke avatar lkoehl 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

doppelkopf's Issues

Multiplayer mode

Not an issue, but an update/announcement.

For the past few months I've tried building a multiplayer mode into the existing game. I started with a spike back in December 2020 - which confirmed my original (and naive) idea that it'd be possible to retrofit a multiplayer mode into this game somehow. As someone who's completely new to building multiplayer game servers, this spike validated a few initial assumptions around the tech stack (a JS front end, socket.io and a Flask backend) and the flow it'd take to establish a multiplayer game (establishing connections, joining game rooms, dispatching messages, handling disconnects/reconnects).

The following months I've tried bringing multiplayer into this code base. And while I made some progress over the last few months, today I'm officially announcing that I will not continue working on a multiplayer mode for this code base.

Why?

There's a few main reasons why I'm stopping multiplayer development

  1. The progress I've made is far from where I want it to be. I keep running in circles when it comes to establishing and maintaining a server connection and doing it in a resilient way.
  2. Working on a multiplayer mode (in this code base) seems to be hard on the schedule I can dedicate to this project. I've got one or two hours here and there that I am willing and able to spend on this code base. That's not enough to keep your head wrapped around complex set up flows and as a consequence I find myself rebuilding the same mental context over and over and over again whenever I want to tackle the next step. Even TDD doesn't seem to help here.
  3. Singleplayer mode development is completely stalling as a consequene. Multiplayer has been grabbing my entire focus (with a short detour to migrating everything to TypeScript).
  4. There's an inevitable challenge looming on the horizon (even if we solved the multiplayer setup flow): This game started as a singleplayer game and as a consequence, the entire game logic sits within the clients. While it's possible to build a client-authoritative game server (where one client becomes the leader and determines the "correct" game state) it sucks to build a game server this way. The multiplayer experience will always be lacking since server-side validation can't become a thing unless we get the game logic to the server.

What did I learn?

That's not to say there's nothing to learn from this experience. I did build a bunch of things that were somewhat working.

Screenshot 2021-07-31 at 17-06-50 Doppelkopf

There's a "lobby" kind of concept (called waitingRoom in our code). A player can start a game on the server. The server will create a game room that players can join. The server keeps track of all games, all players and the games that players have joined. The player starting a game can share a link to the game with other players. When opening the link, those players will establish a socket connection and join the right game until the room is full (4 players joined). In the meantime, the WaitingRoom component will show who's waiting for the game to start.

What's next?

  1. Short term: I'll remove the multiplayer code (socketClient.ts, multiplayerHandler.ts, WaitingRoom.vue, waitingRoom.ts and others) from the code base. I'm even thinking about nuking the entire backend/ project since it ceases to have any reason to exist. I'll drop all "multiplayer" related tasks from the project backlog.
  2. Long-term: This project is supposed to be a singleplayer game and I'll keep it that way. I'd rather do one thing and do it well instead of shoe-horning a half-assed multiplayer solution into a code base that started with a different purpose.
  3. Mid-term: I'll play around with the idea of creating a multiplayer game server from scratch. In a new repo, completely outside of this project. This allows me to experiment a bit more and might lead up to a new version of this game in the distant future. Maybe it'll end getting me nowhere. And that's okay.

Scrollable Scorecard

Right now the scorecard isn't scrollable. After playing multiple rounds the points appear not readable outside of the screen.

Accessibility improvements

I really want this game to be playable by everyone who wants to play it, regardless of disabilities or other limitations.

One of the things we can do to improve here is to take care about proper accessibility. I'm far away from being an expert and need to read up on a lot of topics to get a better overview of what needs improvement, but here's a rough list of things to check and improve from the top of my head:

  1. make sure things work well for people using screen readers
  2. allow picking a color scheme (or using a default color scheme that has this) that works for people with impaired vision or color blindness
  3. allow keyboard navigation throughout
  4. make sure that zooming in doesn't break the game

UI Improvements

Playing the Game for the first time on mobile I believe I saw a few UI Flaws.
default ui
Image you play the game on a relatively small device, we have the issue that flexbox wraps into the next line, creating 3 cards in the first row and one in the second. Technically we still know that the order doesn't change, seeing the last card wrapping into the second line is really inconvenient, especially when cards just keep 'plopping' in. I strongly believe having static card slots where players drop their cards will simulate a real table and will improve intuition and therefore usability.

Another issue with this screenshot becomes clear when asking yourself the question. Who started the round? You need to calculate back. I suggest highlighting the player who actually started the trick will be another quick and dirty benefit to the game.

Take a look at the attached screenshot (which was modified using paint) to get a feeling what i mean.
Indeed, another great and easy improvement would be to highlight the winner of the trick with another colour.

suggested improvements

Colourwise I like yellow since it's different to the blue and red colour scheme and blends into the current scheme very well (obviously not this yellow).
Technically i would suggest using gridview and the order property for the card-layout.

Feature Ideas

Think about the game some things come to my mind where this could be going and how it can be improved.

First something about the visuals:

  • the notification bar is spamable to so other content is seeable. Limiting it to 1 seems reasonable because right now i cant think for a moment to display to notifications at the same time or within the 4 seconds its shown.
  • Since there is a RingQueue it would be nice to have a visual indicator who’s turn it is.
  • It annoys me a little, that the cards of the player are not centered, because the trick stack is included for the centering. Centering the cards and therefore push everything now as it is just a little to the right, when looking at the human player.
  • The scorecard. I would think it is a great idea to display the last played round at the top to make it easily seeable. This would mean a flip of the table.
  • Longer Names are truncated. There should be a nice way to show names fully, no matter the screen size. Font scaling or a little different design could be possible
  • Aligning the text to the left at the results and on the right in the points table isn’t doing it for me. Maybe always aligning the text to the right might be an idea

Functionality

  • Adding settings to the game. And moving the language option into there.
  • Table Settings to allow for different game rules to be turned on or off, like „Schweinchen“, „Zweite Dulle sticht die Erste“ or „Charly am End“
    -Thinking way further it would be nice to play online against friends

Backups

Currently the infrastructure is in a throwaway state. Servers hardly store any state and if they do it's not a big deal if that data gets lost. Servers can be rebuild, configuration restored automatically.

Once the app sees some real-world usage, keeping data around becomes more important. We need to come up with a way to backup data periodically and restore that data when we re-build our infrastructure.

Things to think about when backing up:

  • SQL databases (toggle states, high-level metrics)
  • server logs (NGINX, Gunicorn)

Charlie Bug

Currently there is a bug with Charlie extra point calculation. Sometimes Charlie doesn't win the trick, nor is caugth but still points are added.
Tests are all positive and logic behind this seems very reasonable.

I couldn't completely reproduce, but I believe there is some sort of issue with rounds and the when the trick.setLastTrickInRound() function is called.

This issue is open to keep track of this, since I'm completely aware of this for some time now.

Improve current trick design

As discussed in #34: The current trick shows up as a linear view of the cards that have been played. On small viewports, cards can wrap into a new line if the space available isn't wide enough. This makes it hard to track which player has played a card and looks rather unnatural to people who ever played the game in real life.

Let's improve the current trick design by placing cards closer to the player who played the card. A combination of CSS's grid and the playerPosition property could be useful here.

image

Don't truncate long names

See #7:

Longer Names are truncated. There should be a nice way to show names fully, no matter the screen size. Font scaling or a little different design could be possible

Simplify deployment

Currently deployments and infrastructure are quite tied to a lot of back-and-forth in approaches. This makes maintaining infrastructure quite messy and introduces a high barrier to entry for people who want to get started with setting up the entire project on their hosts.

I want to simplify infrastructure and deployments to:

  • build docker containers for both frontend and backend
  • push those containers to a registry
  • pull and spin up all containers using docker-compose
  • avoid having to configure servers using state-management software like ansible (as we're doing right now)

Anouncement Bug

announcement_bug_cropped

Gabriele announced kontra and I had the kontra dropdown open, announcing only milliseconds later.
To be honest I don't remember if we got an extra point (don't think so), but announcing twice shouldn't be possible by game logic.

add storybook.js to the project again

With the upgrade to vue-cli 3 the storybook dependency broke. Adding storybook will create certain config artifacts (e.g. .babelrc) that break compatibility with vue-cli. Waiting for this issue to be resolved until I try again.

Add game actions to the console

This should be some kind of gamelog.
To be honest I don't know if this is a good idea for production (since remembering played cards is kind of a mandatory strategy), but it's definately for dev.
I was serving the game on my local machine, when I experienced an error and wanted to check for the latest cards i played, but couldn't find a way.
Maybe it's just me and there are ways to look into such things, but adding some sort of gamelog would be really convenient.

Restart game with shitty cards

Official Doppelkopf rules say that you can request the cards to be dealt again if your hand is too shitty to play:

https://de.wikipedia.org/wiki/Doppelkopf#Einmischen

We should come up with a way to either do this automatically or let the user request a new hand if their hand matches these criteria:

  • 5 kings (or 9s if you play with 9s)
  • 4 9s and 4 kings
  • 4 9s of all 4 suits (or 4 kings of all 4 suits)
  • 7 cards with a value of 10 or higher
  • only trumps that are lower or equal than the king of diamonds

Center hand of cards

See #7:

It annoys me a little, that the cards of the player are not centered, because the trick stack is included for the centering. Centering the cards and therefore push everything now as it is just a little to the right, when looking at the human player.

Offline Mode

Doppelkopf should work even when offline.

Using Service Workers should allow to cache content and redirect network requests to hit local caches. All communication to servers should be optional (telemetry, feature toggles) and use fallbacks for offline mode (either queue requests, rely on local storage or use default values).

An upgrade to vue-cli > 3.0 could simplify this by using the PWA plugin it provides. A first attempt at upgrading has failed due to incompatibilities with jest/vue-cli/storybook. In a couple of weeks I'll retry the upgrade and see if the PWA plugin helps resolve this issue.

Small issue with Doppelkopf logo on Mobile

There aren't any issues with developer tools, but definately when browsing. I've tested with firefox mobile and safari on iPhone 7 and 8, with iOS 14.6.
See attached screenshots:

dev tools safari firefox

Faster game iteration

See #7

Displaying a finished trick doesn't seem necessary anymore since we're able to show the previous trick #68.
Implementing a timer based next trick action with a short but reasonable wait time would eliminate the necessity of pressing the next trick button and therefore making the game faster.
For extremely fast paced play it would additionally make sense to make the finished trick clickable, triggering the next trick action.
On a UX perspective this adds the possibility to remove the next trick button completely, making space for the trick or other UI components.

Affinities

After announcements have landed, we have another way for players to reveal which party they belong to (until now they could only do so by playing a queen of clubs).

Whenever a player (human or computer) makes a move that's clearly showing that they belong to the Re or Kontra party (announcing or playing a queen of clubs) they reveal information that's relevant for other players and will change the way they collaborate with that player. We should track this kind of bilateral information between players as something I'd love to call "affinities". We can use affinities for a couple of things:

  • show a "re" or "kontra" party badge next to a player's name once it's 100% clear they belong to a given party
  • tweak computer player's behavior to play high-ranked cards if it's clear that their partner is going to win the trick
  • show a "fox caught" notification once it's clear to all players that this is a fox caught by the opposing party

An affinity value for another player could be a scale ranging from -1 (opponent) over 0 (unknown) to 1 (collaborator).

Keep in mind that affinities are always asynchronous information. One player might now that another player is their collaborator while the other player might be completely clueless.

An example:

  • Player 1 announces "Re", Player 2 and 3 are Kontra, Player 4 holds the other queen of clubs. With the announcement, the affinities for the players shift as follows:
    • Player 4 to Player 1: 1
    • Player 3 to Player 1: -1
    • Player 2 to Player 1: -1
    • Player 4 remains completely unchanged (0 for all)

To implement this, we need to react to certain affinity events in the game. Playing the queen of spades is one of them, announcing is another one. Later on, we can even expand this to include things that look likely but are not 100% clear signs of affinity - a player serving with a fox (or another high value card) early in he game. These events could shift the affinity score slightly (to be tweaked) in one direction.

The game instance could provide an affinityEvent method that will be triggered whenever an affinity event happens - a trick gets added a queen of clubs or a player makes an announcement. This method could go on and call every player in the current round to handle the given affinity event. There they could evaluate which player triggered the event, look at their own state ("am I Re? an I Kontra?") and update their affinities towards the player who triggered the event.

More than one Fox in the trick

Currently finding a fox relies on the findFox() function. This will return the first Fox and check it's state.
This behaviour is a source to at least two problems.

  • catching two foxes within a trick will count only 1 point
  • saving and catching a fox in this order will achieve zero points, since findFox() will calculate the extra on this card and saving a fox is worth only the points

I will fix this issue, prepare for a PR soon 👍

building docker: COPY dist/ /var/www ERROR: Service 'webserver' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder832339339/dist: no such file or directory

When i build the docker, i get an error in ubuntu 20.04:
in the backend directory i type:
docker-compose build

after that i get the following error:

Building webserver
Step 1/7 : FROM caddy:2-alpine
---> 2c73dc9258a8
Step 2/7 : COPY dist/ /var/www
ERROR: Service 'webserver' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder832339339/dist: no such file or directory

Improve AI

Currently the AI plays random valid cards. This is the most trivial, non-predictable implementation but of course doesn't make sense for anyone seeking real fun and a challenging game.

We could implement different computer player personas that the human player can choose from. Each with a different approach of playing and therefore with a different difficulty.

Some ideas to approach implementation:

  • heuristics-based, e.g. calculating Erwartungswert
  • simulation-based (Monte Carlo) - calculate outcomes for all possible moves and pick the best one
  • reinforcement learning - the most tricky one, but could be super fun. Train an AI with reinforcement learning

Notification bar: limit number of messages displayed

See #7:

the notification bar is spamable to so other content is seeable. Limiting it to 1 seems reasonable because right now i cant think for a moment to display to notifications at the same time or within the 4 seconds its shown.

Scorecard Problem on Wedding

When playing a wedding the score isn't calculated correctly.
Obviously a wedding hasn't been implemented yet, nonetheless it will run the game as a "silent wedding"/"stille Hochzeit" ("silent solo"/"stiller Solo"). Summing all Points together should always equal zero, which isn't the case.

See images for details:

Weddingbug
Weddingbug_again

Define colors in a central place

At the moment, different shades of the game's colors are defined within the vue component files. This will ultimately become a maintenance mess and lead to colors drifting apart.

Let's define colors and their different shades centrally, e.g. in src/assets/vars.css.

UI Feature: Last trick played

As mentioned in issue #43, it would be a decent addition to have an additional button within the UI to see the last trick.

I can imagine one of these icons in the top right corner, next to the settings icon: ActivityIcon, InfoIcon or RotateCcwIcon from the icon pack we're currently using.

Pressing the icon could display a modal, using parts of the vue trick component, displaying the trick with the appropriate grid, maybe even showing the names.
Currently we're going a "functionality before design" approach, so don't spend too much time on optics - we can polish and make everything shiny later 😃👍🏻

Add speech bubbles as notfications

See #7

Adding speech bubbles instead of the notifications would probably be an improvement for user experience.
Speech bubbles are commonly known and due to the very specific form easilyrecognizable. In it's nature of having white background colour a buuble would have high contrast to the game board and therefore easily to spot.

I can think of drawbacks though:
Speech bubbles are hard to stack. They suggest appearing at similar or the same position. They have different content and therefore different sizes. Current notifications do stack very well. Regarding issue #9 this might not be relevant though.

Highlight winner of a trick

Discussed in #34: At the moment, we show "The trick goes to: " under the current trick. This is an obvious but not really smooth way of showing who's going to win the trick. The implementation was simple and stuck around for a while now but I think we can improve this design-wise.

Instead of showing the text message underneath the current trick, we can instead highlight the name of the winning player to signal that they're going to win the trick. The icon set we're using has a badge icon we could use and display next to the player name, for example.

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.