diff --git a/app/src/lib/join.svelte b/app/src/lib/join.svelte
index 442acf3..8c281a5 100644
--- a/app/src/lib/join.svelte
+++ b/app/src/lib/join.svelte
@@ -23,13 +23,13 @@
{#if roomCode}
{roomCode}
@@ -33,7 +55,7 @@
Your Board
{}}
/>
@@ -42,7 +64,7 @@
Opponent's Board
= 0 ? 'scale-[1.01]' : 'opacity-60'}
board={gameState.opponentBoard}
callback={(i, j) => gameState.attack(i, j)}
/>
diff --git a/migrations/0001_battleship.sql b/migrations/0001_battleship.sql
index f42da13..fcfa698 100644
--- a/migrations/0001_battleship.sql
+++ b/migrations/0001_battleship.sql
@@ -24,15 +24,21 @@ CREATE TABLE IF NOT EXISTS rooms (
)
);
+CREATE TABLE IF NOT EXISTS abandoned_players (
+ time TIMESTAMP PRIMARY KEY,
+ id CHAR(16) NOT NULL,
+ CONSTRAINT fk_player_id FOREIGN KEY (id) REFERENCES players (id) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
ALTER TABLE players
ADD CONSTRAINT fk_room_code FOREIGN KEY (room_code) REFERENCES rooms (code) ON DELETE
SET NULL;
ALTER TABLE rooms
ADD CONSTRAINT fk_player1 FOREIGN KEY (player1_id) REFERENCES players (id) ON DELETE
-SET NULL,
+SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT fk_player2 FOREIGN KEY (player2_id) REFERENCES players (id) ON DELETE
-SET NULL;
+SET NULL ON UPDATE CASCADE;
-- delete room if both players are null
CREATE OR REPLACE FUNCTION delete_room() RETURNS TRIGGER AS $$ BEGIN IF (
diff --git a/src/board.rs b/src/board.rs
index e47d57f..0cb83e8 100644
--- a/src/board.rs
+++ b/src/board.rs
@@ -2,9 +2,9 @@ use std::ops::{Deref, DerefMut};
use axum::Json;
use rand::Rng;
-use serde::Deserialize;
+use serde::{Deserialize, Serialize};
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Serialize)]
pub struct Board(pub [[char; 10]; 10]);
impl From for Vec {
@@ -109,6 +109,31 @@ impl Board {
Some(bounds)
}
+ pub fn mark_redundant(mut self) -> Self {
+ for i in 0..10 {
+ for j in 0..10 {
+ if self[i][j] == 'h' {
+ for (dx, dy) in [(-1, -1), (1, 1), (1, -1), (-1, 1)].iter() {
+ let (tx, ty) = ((i as i32 + dx) as usize, (j as i32 + dy) as usize);
+ if (0..10).contains(&tx) && (0..10).contains(&ty) {
+ self[tx][ty] = 'm';
+ }
+ }
+ if self.has_sunk((i, j)).is_some() {
+ for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)].iter() {
+ let (tx, ty) = ((i as i32 + dx) as usize, (j as i32 + dy) as usize);
+ if (0..10).contains(&tx) && (0..10).contains(&ty) && self[tx][ty] == 'e'
+ {
+ self[tx][ty] = 'm';
+ }
+ }
+ }
+ }
+ }
+ }
+ self
+ }
+
// fn validate_syntax(&self) -> bool {
// self
// .iter()
diff --git a/src/game.rs b/src/game.rs
index 087c3dc..2048c96 100644
--- a/src/game.rs
+++ b/src/game.rs
@@ -1,3 +1,4 @@
+use serde::Serialize;
use socketioxide::socket::Sid;
use thiserror::Error;
@@ -9,8 +10,8 @@ pub type Result = std::result::Result;
#[derive(Debug, Error)]
pub enum Error {
- #[error("Room full")]
- RoomFull,
+ #[error("Room full, potential replacement {0:?}")]
+ RoomFull(Option),
#[error("Room not full")]
RoomNotFull,
#[error("Already in room")]
@@ -23,7 +24,25 @@ pub enum Error {
Sqlx(#[from] sqlx::Error),
}
+#[derive(Debug, sqlx::Type, PartialEq, Serialize)]
+#[sqlx(type_name = "STAT", rename_all = "lowercase")]
+pub enum Status {
+ Waiting,
+ P1Turn,
+ P2Turn,
+}
+
+pub async fn room_if_player_exists(sid: &str, pool: &sqlx::PgPool) -> Result