-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d6d1c6c
commit 942cdcd
Showing
50 changed files
with
5,800 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
161 changes: 161 additions & 0 deletions
161
test4.gno.land/extracted/p/flippando:805111/flippandoserver.gno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package flippandoserver | ||
|
||
type GameBoard struct { | ||
Board []int64 `json:"board"` | ||
TileType string `json:"tileType"` | ||
GameTiles []int64 `json:"gameTiles"` | ||
BoardSize int `json:"boardSize"` | ||
} | ||
|
||
type positions struct { | ||
position1 int | ||
position2 int | ||
} | ||
|
||
// position1 - int, postion2 - int | ||
|
||
type inTransit struct { | ||
tokenId int | ||
inTransit bool | ||
} | ||
|
||
// creates game object and initializes board | ||
func CreateGameBoard(tileType string, boardSize int, seed int64) ([]int64, []int64, int) { | ||
// Initialize the board and gameTiles slices based on boardSize | ||
board := make([]int64, boardSize) | ||
|
||
// Initialize the gameTiles slice with a length that is the square root of boardSize | ||
gameTilesLength := int(sqrt(float64(boardSize))) | ||
gameTiles := make([]int64, gameTilesLength) | ||
// @todo make call to generateRandomNumbers, so you can create the actual gameTiles array, | ||
rng := int64(4) | ||
if tileType == "squareGrid" { | ||
rng = int64(16) | ||
} else if tileType == "greyGradient" || tileType == "redGradient" || tileType == "blueGradient" || tileType == "greenGradient" { | ||
rng = int64(8) | ||
} else if tileType == "hexagrams" { | ||
rng = int64(4) | ||
// adjust for bigger board | ||
if len(gameTiles) == 8 { | ||
gameTiles = make([]int64, 4) | ||
} | ||
} else if tileType == "dice" { | ||
rng = int64(6) | ||
// adjust for bigger board | ||
if len(gameTiles) == 8 { | ||
gameTiles = make([]int64, 6) | ||
} | ||
} | ||
// Generating random numbers for gameTiles | ||
generatedNumbers := GenerateRandomNumbers(len(gameTiles), 1, int(rng), seed) | ||
for i, num := range generatedNumbers { | ||
gameTiles[i] = int64(num) | ||
} | ||
|
||
// we're returning discrete value, and do the json marshaling in realm | ||
return board, gameTiles, boardSize; | ||
} | ||
|
||
func FlipTiles(board []int64, solvedBoard []int64, gameTiles []int64, positions []int64, seed int64) ([]int64, []int64) { | ||
// - returns the current game board, and the solved game board | ||
|
||
randomNumberSlice := GenerateRandomNumbers(2, 1, len(gameTiles), seed) | ||
|
||
// Safety check for 'positions' slice | ||
if len(positions) < 2 { | ||
return nil, nil | ||
} | ||
|
||
// Safety check for 'randomNumberSlice' | ||
if randomNumberSlice == nil || len(randomNumberSlice) < 2 { | ||
return nil, nil | ||
} | ||
|
||
// position hasn't been discovered before | ||
if board[positions[0]] == 0 { | ||
board[positions[0]] = gameTiles[randomNumberSlice[0] - 1] | ||
} | ||
|
||
if board[positions[1]] == 0 { | ||
board[positions[1]] = gameTiles[randomNumberSlice[1] -1] | ||
} | ||
|
||
// values are equal, update solved board | ||
if board[positions[0]] == board[positions[1]] { | ||
solvedBoard[positions[0]] = board[positions[0]] | ||
solvedBoard[positions[1]] = board[positions[1]] | ||
} | ||
|
||
// enforce solvability | ||
quantumThreshold := int(sqrt(float64(len(board)))) | ||
unsolvedTiles := 0 | ||
|
||
for j := 0; j < len(board); j++ { | ||
if solvedBoard[j] == 0 { | ||
unsolvedTiles++ | ||
} | ||
} | ||
|
||
if unsolvedTiles <= quantumThreshold { | ||
// replace the board with solvedBoard and redeploy | ||
if board[positions[0]] != board[positions[1]] { | ||
board[positions[0]] = board[positions[1]] | ||
solvedBoard[positions[0]] = board[positions[0]] | ||
solvedBoard[positions[1]] = board[positions[1]] | ||
} | ||
} | ||
|
||
return board, solvedBoard | ||
|
||
} | ||
|
||
func GenerateRandomNumbers(howMany, min, max int, seed int64) []int { | ||
if min > max || howMany <= 0 || (max-min+1) < howMany { | ||
return nil | ||
} | ||
|
||
r := New(seed) | ||
numbers := make([]int, 0, howMany) | ||
seen := make(map[int]bool) | ||
|
||
for len(numbers) < howMany { | ||
randomNumber := r.Intn(max-min+1) + min | ||
|
||
// If the number hasn't been generated before, add it to the slice and the map | ||
if !seen[randomNumber] { | ||
seen[randomNumber] = true | ||
numbers = append(numbers, randomNumber) | ||
} | ||
} | ||
|
||
return numbers | ||
} | ||
|
||
|
||
func sqrt(x float64) float64 { | ||
if x == 0 || x == 1 { | ||
return x | ||
} | ||
|
||
// Start with an initial guess | ||
guess := x / 2.0 | ||
prevGuess := 0.0 | ||
|
||
// Use a small threshold to determine when to stop the approximation | ||
const threshold = 0.00001 | ||
|
||
// Use math.Abs to calculate the absolute value | ||
abs := func(f float64) float64 { | ||
if f < 0 { | ||
return -f | ||
} | ||
return f | ||
} | ||
|
||
for abs(guess-prevGuess) > threshold { | ||
prevGuess = guess | ||
guess = 0.5 * (guess + x/guess) | ||
} | ||
|
||
return guess | ||
} |
122 changes: 122 additions & 0 deletions
122
test4.gno.land/extracted/p/flippando:805111/flippandoserver_test.gno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package flippandoserver | ||
|
||
import ( | ||
"sort" | ||
"math" | ||
"std" | ||
"testing" | ||
"time" | ||
"encoding/json" | ||
"strconv" | ||
"errors" | ||
|
||
"gno.land/p/demo/testutils" | ||
"gno.land/p/demo/ufmt" | ||
) | ||
|
||
func TestCreateGameBoard(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
tileType string | ||
boardSize int | ||
seed int64 | ||
maxTileVal int | ||
}{ | ||
{"SquareGrid", "squareGrid", 4, 12345, 16}, | ||
{"Hexagrams", "hexagrams", 4, 12345, 4}, | ||
{"Dice", "dice", 4, 12345, 6}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
board, gameTiles, size := CreateGameBoard(tt.tileType, tt.boardSize, tt.seed) | ||
|
||
// Test the length of the board | ||
if len(board) != tt.boardSize { | ||
t.Errorf("Expected board length of %d, got %d", tt.boardSize, len(board)) | ||
} | ||
|
||
// Test the length of gameTiles | ||
expectedGameTilesLength := int(sqrt(float64(tt.boardSize))) | ||
if len(gameTiles) != expectedGameTilesLength { | ||
t.Errorf("Expected gameTiles length of %d, got %d", expectedGameTilesLength, len(gameTiles)) | ||
} | ||
|
||
// Check if gameTiles values are within the expected range | ||
for _, tile := range gameTiles { | ||
if tile < 1 || tile > int64(tt.maxTileVal) { | ||
t.Errorf("gameTiles contains a value out of expected range (1 to %d): got %d", tt.maxTileVal, tile) | ||
} | ||
} | ||
|
||
// Check if the gameTiles values are unique | ||
uniqueTiles := make(map[int64]bool) | ||
for _, tile := range gameTiles { | ||
if uniqueTiles[tile] { | ||
t.Errorf("Duplicate tile found in gameTiles: %d", tile) | ||
} | ||
uniqueTiles[tile] = true | ||
} | ||
|
||
// Test the returned board size | ||
if size != tt.boardSize { | ||
t.Errorf("Expected returned board size to be %d, got %d", tt.boardSize, size) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestGenerateRandomNumbers(t *testing.T) { | ||
tests := []struct { | ||
howMany int | ||
min int | ||
max int | ||
seed int64 | ||
expect int | ||
}{ | ||
{5, 1, 10, 123, 5}, | ||
{3, 5, 7, 456, 3}, | ||
{10, 1, 5, 789, 0}, | ||
{0, 1, 10, 101, 0}, | ||
{-2, 1, 10, 112, 0}, | ||
{5, 10, 5, 123, 0}, | ||
} | ||
|
||
for _, tt := range tests { | ||
got := GenerateRandomNumbers(tt.howMany, tt.min, tt.max, tt.seed) | ||
|
||
if len(got) != tt.expect { | ||
t.Errorf("expected %d numbers but got %d", tt.expect, len(got)) | ||
} | ||
|
||
// Check for uniqueness | ||
numSet := make(map[int]bool) | ||
for _, num := range got { | ||
if numSet[num] { | ||
t.Errorf("duplicate number found: %d", num) | ||
} | ||
numSet[num] = true | ||
} | ||
|
||
// Check if numbers are within range | ||
for _, num := range got { | ||
if num < tt.min || num > tt.max { | ||
t.Errorf("number %d out of range [%d, %d]", num, tt.min, tt.max) | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
// Helper function to compare two slices for equality | ||
func sliceEqual(a, b []int64) bool { | ||
if len(a) != len(b) { | ||
return false | ||
} | ||
for i := range a { | ||
if a[i] != b[i] { | ||
return false | ||
} | ||
} | ||
return true | ||
} |
Oops, something went wrong.