Public
Script
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { z } from "npm:zod";
export const COLS = 7;
export const ROWS = 6;
export type Winner = {
kind: "winner";
winner: number;
};
export type Draw = {
kind: "draw";
};
export type Result = Winner | Draw;
export type InProgress = {
status: "in_progress";
next_player: number;
};
export type Over = {
status: "over";
result: Result;
};
export type Status = InProgress | Over;
const stringOrNumber = z.union([z.string(), z.number()]);
export const PlayerI = z.number().nonnegative().lte(1);
export const Slot = z.nullable(PlayerI);
export type Slot = z.infer<typeof Slot>;
export const Column = z.array(Slot).length(6);
export type Column = z.infer<typeof Column>;
export const Board = z.array(Column).length(7);
export type Board = z.infer<typeof Board>;
export const State = z.object({
next_player: PlayerI,
board: Board,
});
export type State = z.infer<typeof State>;
export const Action = z.object({
player: z.coerce.number().nonnegative().lte(1),
column: z.coerce.number().nonnegative().lt(COLS),
});
export type Action = z.infer<typeof Action>;
export function get(state: State, col: number, row: number): Slot {
return state.board[col][row];
}
export function set(state: State, col: number, row: number, slot: Slot): void {
state.board[col][row] = slot;
}
export type ActionCheck =
| "ok"
| "wrong_player"
| "column_full"
| "column_out_of_bounds";
export function check_action(state: State, action: Action): ActionCheck {
if (action.player !== state.next_player) {
return "wrong_player";
}
if (action.column < 0 || action.column >= COLS) {
return "column_out_of_bounds";
}
if (get(state, action.column, ROWS - 1) !== null) {
return "column_full";
}
return "ok";
}
function check_slots_eq(a: Slot, b: Slot, c: Slot, d: Slot): Slot {
if (a === b && b === c && c === d) {
return a;
}
return null;
}
export function status(state: State): Status {
// Check Vertical Win
for (let col = 0; col < COLS; col++) {
for (let row = 0; row < 3; row++) {
let check = check_slots_eq(
get(state, col, row + 0),
get(state, col, row + 1),
get(state, col, row + 2),
get(state, col, row + 3)
);
if (check !== null) {
return { status: "over", result: { kind: "winner", winner: check } };
}
}
}
// Check Horizontal Win
December 22, 2023