Skip to content

Commit

Permalink
wip moves
Browse files Browse the repository at this point in the history
  • Loading branch information
h908714124 committed Aug 2, 2024
1 parent 267b0de commit 20a0b6e
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 49 deletions.
22 changes: 12 additions & 10 deletions src/main/client/src/Game.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,20 +196,21 @@ export const Game = () => {
let game = JSON.parse(message.body)
setGameState(game)
})
let sub2 = stompClient.subscribe("/topic/move/" + gameId, (message) => {
let move = JSON.parse(message.body)
console.log(move) // TODO
})
doTry(async () => {
await tfetch("/api/game/hello", {
method: "POST",
let game = await tfetch("/api/game/" + gameId, {
headers: {
"Authorization": "Bearer " + auth.token,
"Content-Type": "application/json",
},
body: JSON.stringify({
id: gameId,
}),
})
setGameState(game)
})
return () => {
sub1.unsubscribe()
sub2.unsubscribe()
}
}, [setGameState, initialized, stompClient, gameId, auth])
if (!board.length) {
Expand Down Expand Up @@ -249,7 +250,7 @@ function showStone({ canvasRef, grid, stoneRadius }, grid_x, grid_y, style) {
ctx.fill()
}

function showTriangle({ isCursorInBounds, canvasRef, grid, stoneRadius, lastStoneXref, lastStoneYref }, board) {
function paintLastMove({ isCursorInBounds, canvasRef, grid, stoneRadius, lastStoneXref, lastStoneYref }, board) {
let grid_x = lastStoneXref.current
let grid_y = lastStoneYref.current
if (!isCursorInBounds(grid_x, grid_y)) {
Expand All @@ -261,11 +262,12 @@ function showTriangle({ isCursorInBounds, canvasRef, grid, stoneRadius, lastSton
"rgba(0,0,0)"
let [x, y] = grid[grid_y][grid_x]
let ctx = canvasRef.current.getContext("2d")
let length = stoneRadius * 0.875
ctx.fillStyle = style
ctx.beginPath()
ctx.moveTo(x, y)
ctx.lineTo(x + stoneRadius, y)
ctx.lineTo(x , y + stoneRadius)
ctx.lineTo(x + length, y)
ctx.lineTo(x , y + length)
ctx.fill()
}

Expand Down Expand Up @@ -328,7 +330,7 @@ function paintStones(context, board) {
}
}
}
showTriangle(context, board)
paintLastMove(context, board)
}

function paintStonesCounting(context, board, countingGroup) {
Expand Down
3 changes: 1 addition & 2 deletions src/main/client/src/feature/OpenGames.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,7 @@ function AcceptDialog({acceptableGame, onAccept}) {
<IconContext.Provider value={{
size: "1.25em",
className: twJoin(
"pl-[4px]",
"pr-[4px]",
"px-1",
handi === 0 && "text-slate-400",
)
}}>
Expand Down
47 changes: 30 additions & 17 deletions src/main/java/com/bernd/GameController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
import com.bernd.model.AcceptRequest;
import com.bernd.model.ActiveGame;
import com.bernd.model.Game;
import com.bernd.model.JoinGameRequest;
import com.bernd.model.Move;
import com.bernd.model.OpenGame;
import com.bernd.model.ViewGame;
import com.bernd.util.Auth;
import com.bernd.util.RandomString;
import java.security.Principal;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.core.MessageSendingOperations;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Objects;

@Controller
public class GameController {

Expand All @@ -37,39 +38,51 @@ public class GameController {
this.activeGames = activeGames;
}

@PostMapping(value = "/api/game/hello", consumes = "application/json")
public ResponseEntity<?> sayHello(@RequestBody JoinGameRequest request) {
Game game = games.get(request.id());
operations.convertAndSend("/topic/game/" + request.id(), game);
return ResponseEntity.ok().build();
@ResponseBody
@GetMapping(value = "/api/game/{id}")
public ViewGame getGame(@PathVariable String id) {
Game game = games.get(id);
if (game == null) {
return null;
}
return game.toView();
}

@MessageMapping("/game/move")
public void action(Move move) {
public void action(Move move, Principal principal) {
Game game = games.get(move.id());
if (game == null) {
return;
}
int moveNumber = game.moves().size();
int color = game.currentColor();
if (!principal.getName().equals(game.currentPlayer())) {
return; // discard
}
Game updated = game.update(move);
games.put(updated);
operations.convertAndSend("/topic/game/" + game.id(), updated);
operations.convertAndSend("/topic/move/" + game.id(), move.toView(color, moveNumber));
operations.convertAndSend("/topic/game/" + game.id(), updated.toView());
}

@ResponseBody
@PostMapping(value = "/api/create", consumes = "application/json")
public OpenGame newGame(@RequestBody OpenGame game) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
OpenGame result = openGames.put(game.withUser(Objects.toString(principal, ""))
String principal = Auth.getPrincipal();
OpenGame result = openGames.put(game.withUser(principal)
.withId(RandomString.get()));
operations.convertAndSend("/topic/lobby/open_games", openGames.games());
return result;
}

@PostMapping(value = "/api/accept", consumes = "application/json")
public ResponseEntity<?> accept(@RequestBody AcceptRequest acceptRequest) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
openGames.remove(Objects.toString(principal));
String principal = Auth.getPrincipal();
openGames.remove(principal);
OpenGame openGame = openGames.remove(acceptRequest.game().user().name());
Game fullGame = games.put(openGame.accept(principal.toString(), acceptRequest));
Game fullGame = games.put(openGame.accept(principal, acceptRequest));
activeGames.put(ActiveGame.fromGame(fullGame));
operations.convertAndSend("/topic/game/" + fullGame.id(), fullGame);
operations.convertAndSend("/topic/game/" + fullGame.id(), fullGame.toView());
operations.convertAndSend("/topic/lobby/open_games", openGames.games());
operations.convertAndSend("/topic/lobby/active_games", activeGames.games());
return ResponseEntity.ok().build();
Expand Down
25 changes: 13 additions & 12 deletions src/main/java/com/bernd/LobbyController.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package com.bernd;

import com.bernd.game.MoveList;
import com.bernd.model.ActiveGame;
import com.bernd.model.ActiveGameList;
import com.bernd.model.Game;
import com.bernd.model.MatchRequest;
import com.bernd.model.OpenGameList;
import com.bernd.model.User;
import com.bernd.model.ViewGame;
import com.bernd.util.Auth;
import com.bernd.util.RandomString;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.core.MessageSendingOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Objects;

import static com.bernd.game.Board.B;

@Controller
Expand All @@ -44,8 +44,8 @@ public class LobbyController {

@GetMapping(value = "/api/lobby/hello")
public ResponseEntity<?> sayHello() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
lobbyUsers.add(Objects.toString(principal));
String principal = Auth.getPrincipal();
lobbyUsers.add(principal);
operations.convertAndSend("/topic/lobby/users", lobbyUsers.users());
operations.convertAndSend("/topic/lobby/open_games", openGames.games());
operations.convertAndSend("/topic/lobby/active_games", activeGames.games());
Expand All @@ -66,25 +66,26 @@ public OpenGameList getOpenGames() {

@ResponseBody
@PostMapping(value = "/api/start_edit", consumes = "application/json")
public Game startEdit(@RequestBody MatchRequest request) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
lobbyUsers.remove(Objects.toString(principal));
User user = new User(Objects.toString(principal));
public ViewGame startEdit(@RequestBody MatchRequest request) {
String principal = Auth.getPrincipal();
lobbyUsers.remove(principal);
User user = new User(principal);
operations.convertAndSend("/topic/lobby/users", lobbyUsers.users());
Game game = games.put(new Game(
RandomString.get(),
user,
user,
true,
false,
Objects.toString(principal),
principal,
B,
false,
createEmptyBoard(request.dim()),
0,
new int[]{-1, -1}));
new int[]{-1, -1},
MoveList.create(request.dim())));
activeGames.put(ActiveGame.fromGame(game));
return game;
return game.toView();
}

public static int[][] createEmptyBoard(int dimension) {
Expand Down
121 changes: 121 additions & 0 deletions src/main/java/com/bernd/game/MoveList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.bernd.game;

import com.bernd.model.GameMove;
import com.bernd.model.Move;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.bernd.util.Util.divUp;

public final class MoveList {

private static final int LO = 0xffff;
private static final int HI = 0xffff0000;
private static final int WHITE = 0x1000;
private static final int PASS = 0x2000;
private static final int DATA = 0x0fff;

public static void main(String[] args) {
int n = 1024 * 4;
System.out.printf("%x\n", n);
System.out.println(n);
System.out.printf("%x\n", 2 * n);
System.out.println(2 * n);
}

private int pos;
private int capacity;
private final int dim;
private int[] buffer;

private MoveList(
int dim,
int[] buffer) {
this.capacity = dim * dim;
this.dim = dim;
this.buffer = buffer;
}

public static MoveList create(int dim, int size) {
return new MoveList(dim, new int[divUp(size, 2)]);
}

public static MoveList create(int dim) {
return new MoveList(dim, new int[16]);
}

public void add(int color, Move move) {
if (pos >= capacity) {
int newCapacity = 2 * capacity;
buffer = Arrays.copyOf(buffer, divUp(newCapacity, 2));
capacity = newCapacity;
}
int ptId;
if (move.pass()) {
ptId = PASS;
} else {
ptId = dim * move.y() + move.x();
}
if (color == Board.W) {
ptId |= WHITE;
}
set(ptId);
pos++;
}

public GameMove get(int i) {
int code = buffer[i / 2];
int ptId = i % 2 == 0 ? code & LO : (code >> 16);
int color = (ptId & WHITE) != 0 ? Board.W : Board.B;
if ((ptId & PASS) != 0) {
return new GameMove(i, color, true, -1, -1);
} else {
int data = ptId & DATA;
int x = data % dim;
int y = data / dim;
return new GameMove(i, color, true, x, y);
}
}

private void set(int ptId) {
int i = pos / 2;
if (pos % 2 == 0) {
buffer[i] = (buffer[i] & HI) | ptId;
} else {
buffer[i] = (ptId << 16) | (buffer[i] & LO);
}
}

public int size() {
return pos;
}

public List<GameMove> asList() {
List<GameMove> result = new ArrayList<>(size());
for (int i = 0; i < pos; i++) {
result.add(get(i));
}
return result;
}

public int dim() {
return dim;
}

@Override
public String toString() {
if (pos == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < pos; i++) {
sb.append("(")
.append(get(i))
.append("), ");
}
sb.setLength(sb.length() - 2);
sb.append("]");
return sb.toString();
}
}
Loading

0 comments on commit 20a0b6e

Please sign in to comment.