I'm human

This commit is contained in:
Niklas Kapelle 2024-05-24 23:15:28 +02:00
parent b47325a0dc
commit c31fb7d0ff
Signed by: niklas
GPG Key ID: 4EB651B36D841D16
13 changed files with 214 additions and 44 deletions

View File

@ -190,6 +190,10 @@ impl BlackjackGame {
} }
(GameState::Over, PlayMoves::Deal { players }) (GameState::Over, PlayMoves::Deal { players })
| (GameState::Starting, PlayMoves::Deal { players }) => { | (GameState::Starting, PlayMoves::Deal { players }) => {
// Reset everything
self.dealer_hand = Hand::new();
self.players = Vec::new();
// Create players // Create players
for _ in 0..players { for _ in 0..players {
self.players.push(Player::new()); self.players.push(Player::new());

View File

@ -4,9 +4,13 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Serialize, Deserialize)] #[derive(Clone, Copy, Serialize, Deserialize)]
pub enum CardSuit { pub enum CardSuit {
#[serde(rename = "S")]
Spades, Spades,
#[serde(rename = "C")]
Clubs, Clubs,
#[serde(rename = "H")]
Hearts, Hearts,
#[serde(rename = "D")]
Diamonds, Diamonds,
} }

View File

@ -122,7 +122,6 @@ impl<'de> Deserialize<'de> for Hand {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
// Deserialize into a Vec directly and wrap it in MyVecWrapper
let cards = Vec::<Card>::deserialize(deserializer)?; let cards = Vec::<Card>::deserialize(deserializer)?;
Ok(Hand { cards }) Ok(Hand { cards })
} }

View File

@ -6,10 +6,15 @@ use rocket::{
Build, Rocket, State, Build, Rocket, State,
}; };
use crate::{blackjack::{blackjack_game::BlackjackGame, gamestate::GameState, play_moves::PlayMoves, player::Player}, cards::card::Card}; use crate::{
blackjack::{
blackjack_game::BlackjackGame, gamestate::GameState, play_moves::PlayMoves, player::Player,
},
cards::{card::Card, hand::Hand},
};
#[get("/state")] #[get("/state")]
fn get_state(state: &State<MyState>) -> Json<GamestateJson> { fn get_state(state: &State<MyState>) -> Json<ExtendedGameState> {
Json(gamestate_as_json(&state.game.lock().unwrap())) Json(gamestate_as_json(&state.game.lock().unwrap()))
} }
@ -17,8 +22,8 @@ fn get_state(state: &State<MyState>) -> Json<GamestateJson> {
fn post_move( fn post_move(
state: &State<MyState>, state: &State<MyState>,
request: Json<PlayMoves>, request: Json<PlayMoves>,
) -> Result<Json<GamestateJson>, Status> { ) -> Result<Json<ExtendedGameState>, Status> {
let action = request.0; let action = request.into_inner();
if state.game.lock().unwrap().play(action) { if state.game.lock().unwrap().play(action) {
Ok(Json(gamestate_as_json(&state.game.lock().unwrap()))) Ok(Json(gamestate_as_json(&state.game.lock().unwrap())))
@ -32,23 +37,35 @@ struct MyState {
} }
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(tag = "type", rename_all = "camelCase", rename_all_fields = "camelCase")]
struct GamestateJson { enum ExtendedGameState {
state: GameState, Over {
dealer_upcard: Option<Card>, dealer_hand: Hand,
players: Vec<Player>, players: Vec<Player>,
},
Playing {
dealer_upcard: Card,
player_turn: usize,
hand_turn: usize,
players: Vec<Player>,
},
Starting,
} }
fn gamestate_as_json(game: &BlackjackGame) -> GamestateJson { fn gamestate_as_json(game: &BlackjackGame) -> ExtendedGameState {
match game.get_state() { match game.get_state() {
GameState::Starting => GamestateJson { GameState::Starting => ExtendedGameState::Starting,
state: *game.get_state(), GameState::Over => ExtendedGameState::Over {
dealer_upcard: None, dealer_hand: game.get_dealer_hand().clone(),
players: Vec::new(), players: game.get_players().clone(),
}, },
GameState::Over | GameState::PlayerTurn { .. } => GamestateJson { GameState::PlayerTurn {
state: *game.get_state(), player_index,
dealer_upcard: game.get_dealer_upcard().copied(), hand_index,
} => ExtendedGameState::Playing {
dealer_upcard: *game.get_dealer_upcard().unwrap(),
player_turn: *player_index,
hand_turn: *hand_index,
players: game.get_players().clone(), players: game.get_players().clone(),
}, },
} }

View File

@ -1,22 +1,9 @@
<script lang="ts"> <script lang="ts">
import {fetchState} from "./functions/fetchState"; import Blackjack from "./lib/Blackjack.svelte";
import { CardSuit } from "./types/CardSuit";
async function getState() {
let state = await fetchState();
console.debug(state);
if (state.dealerUpcard.suit == CardSuit.Spades){
console.debug("Heureka");
}else{
console.debug("FUCK");
}
}
</script> </script>
<main> <main>
<div>Hello world</div> <Blackjack/>
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" on:click={getState}>Get state</button>
</main> </main>

View File

@ -0,0 +1,15 @@
import type { Action } from "../types/Action";
import type { Gamestate } from "../types/Gamestate";
export async function doAction(action: Action): Promise<Gamestate> {
let res = await fetch("/api/state", {
method: "POST",
body: JSON.stringify(action),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
});
return await res.json();
}

View File

@ -1,3 +1,7 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
body {
@apply bg-blue-950 text-white;
}

View File

@ -0,0 +1,74 @@
<script lang="ts">
import { onMount } from "svelte";
import { doAction } from "../functions/doAction";
import type { Action } from "../types/Action";
import type { Gamestate } from "./../types/Gamestate";
import { fetchState } from "../functions/fetchState";
import Card from "./Card.svelte";
import PlayerHand from "./PlayerHand.svelte";
let state: Gamestate;
onMount(async () => {
state = await fetchState();
});
async function actionBtn(action: Action) {
state = await doAction(action);
}
</script>
{#if state}
{#if state.type == "starting"}
Game has not yet started. Press "Deal" to start.
{:else if state.type == "over"}
Game over. Press "Deal" to start again.
<br>
Player:
{#each state.players as player}
{#each player.hands as hand}
<PlayerHand playingHand={hand}/>
{/each}
{/each}
{:else if state.type == "playing"}
Dealer: <Card card={state.dealerUpcard} />
Player:
{#each state.players as player}
{#each player.hands as hand}
<PlayerHand playingHand={hand}/>
{/each}
{/each}
{/if}
{:else}
Loading...
{/if}
<div>
<button
class="action-btn bg-blue-700 hover:bg-blue-600"
on:click={() => actionBtn({ type: "Deal", players: 1 })}>Deal</button
>
<button
class="action-btn bg-green-700 hover:bg-green-600"
on:click={() => actionBtn({ type: "Hit" })}>Hit</button
>
<button
class="action-btn bg-red-700 hover:bg-red-600"
on:click={() => actionBtn({ type: "Stand" })}>Stand</button
>
<button
class="action-btn bg-orange-700 hover:bg-orange-600"
on:click={() => actionBtn({ type: "DoubleDown" })}>Double down</button
>
<button
class="action-btn bg-cyan-700 hover:bg-cyan-600"
on:click={() => actionBtn({ type: "Split" })}>Split</button
>
</div>
<style>
.action-btn {
@apply py-2 px-4 rounded text-white;
}
</style>

View File

@ -2,8 +2,9 @@
import type { Card } from "../types/Card"; import type { Card } from "../types/Card";
export let card: Card; export let card: Card;
console.debug(card);
</script> </script>
<div class="w-2 h-5"> <div class="w-32 h-36 bg-slate-400 m-1 p-2">
I am a {card.index} of {card.suit}! {card.index} of {card.suit}
</div> </div>

View File

@ -0,0 +1,11 @@
<script lang="ts">
import type { PlayingHand } from "../types/Gamestate";
import Card from "./Card.svelte";
export let playingHand: PlayingHand;
</script>
{#each playingHand.hand as hand}
<Card card={hand}/>
{/each}

View File

@ -0,0 +1,22 @@
export interface Deal {
type: "Deal",
players: Number
}
export interface Hit {
type: "Hit"
}
export interface Stand {
type: "Stand"
}
export interface DoubleDown{
type: "DoubleDown"
}
export interface Split {
type: "Split"
}
export type Action = Deal | Hit | Stand | DoubleDown | Split;

View File

@ -1,6 +1,6 @@
export enum CardSuit { export enum CardSuit {
Spades = "Spades", Spades = "S",
Clubs = "Clubs", Clubs = "C",
Hearts = "Hearts", Hearts = "H",
Diamonds = "Diamonds", Diamonds = "D",
} }

View File

@ -1,5 +1,37 @@
import type { Card } from "./Card"; import type { Card } from "./Card";
export interface Gamestate{ export interface Player {
dealerUpcard: Card, hands: [PlayingHand]
} }
export enum PlayingHandState {
Playing = "Playing",
Standing = "Standing",
DoubleDown = "DoubleDown",
Busted = "Busted",
Blackjack = "Blackjack",
Maxed = "Maxed",
}
export interface PlayingHand {
state: PlayingHandState,
hand: [Card]
}
export interface Over {
type: "over",
dealerHand: [Card],
players: [Player],
}
export interface Starting {
type: "starting",
}
export interface Playing {
type: "playing",
dealerUpcard: Card,
players: [Player],
}
export type Gamestate = Over | Starting | Playing;