forked from ArchipelagoMW/Archipelago
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
randomly generate EotU coordinates, put them in slot data, and unit t…
…est the generation
- Loading branch information
Showing
4 changed files
with
143 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from typing import List | ||
from random import Random | ||
|
||
|
||
two_point_coordinates = 6 * 5 | ||
three_point_coordinates = 6 * 5 * 4 | ||
four_point_coordinates = 6 * 5 * 4 * 3 | ||
five_point_coordinates = 6 * 5 * 4 * 3 * 2 | ||
six_point_coordinates = 6 * 5 * 4 * 3 * 2 * 1 | ||
|
||
total_possible_coordinates = (two_point_coordinates + three_point_coordinates + four_point_coordinates + | ||
five_point_coordinates + six_point_coordinates) | ||
|
||
|
||
def generate_random_coordinates(random: Random) -> List[List[int]]: | ||
selections = [ | ||
random.randint(0, total_possible_coordinates - 1), | ||
random.randint(0, total_possible_coordinates - 1), | ||
random.randint(0, total_possible_coordinates - 1), | ||
] | ||
selected_coordinates = list(map(get_coordinate_for_number, selections)) | ||
map(validate_coordinate, selected_coordinates) | ||
return selected_coordinates | ||
|
||
|
||
def validate_coordinate(coordinate: List[int]) -> None: | ||
assert len(coordinate) >= 2 | ||
assert len(coordinate) <= 6 | ||
assert len(set(coordinate)) == len(coordinate) | ||
|
||
|
||
# Here, the number represents an index into the list of all possible coordinates of any length | ||
def get_coordinate_for_number(coord_index: int) -> List[int]: | ||
assert coord_index < total_possible_coordinates | ||
|
||
if coord_index < two_point_coordinates: | ||
return get_coordinate_points_for_number(2, two_point_coordinates, coord_index) | ||
coord_index -= two_point_coordinates | ||
|
||
if coord_index < three_point_coordinates: | ||
return get_coordinate_points_for_number(3, three_point_coordinates, coord_index) | ||
coord_index -= three_point_coordinates | ||
|
||
if coord_index < four_point_coordinates: | ||
return get_coordinate_points_for_number(4, four_point_coordinates, coord_index) | ||
coord_index -= four_point_coordinates | ||
|
||
if coord_index < five_point_coordinates: | ||
return get_coordinate_points_for_number(5, five_point_coordinates, coord_index) | ||
coord_index -= five_point_coordinates | ||
|
||
return get_coordinate_points_for_number(6, six_point_coordinates, coord_index) | ||
|
||
|
||
# Now the number represents an index into the list of all possible coordinates of one specific length | ||
def get_coordinate_points_for_number(point_count: int, possible_coords: int, coord_index: int) -> List[int]: | ||
points_not_taken = [0, 1, 2, 3, 4, 5] | ||
coord_points = [] | ||
bucket_size = possible_coords | ||
|
||
while len(coord_points) < point_count: | ||
bucket_size //= len(points_not_taken) | ||
point_choice = coord_index // bucket_size | ||
|
||
point_num = points_not_taken[point_choice] | ||
points_not_taken.remove(point_num) | ||
coord_points.append(point_num) | ||
|
||
coord_index %= bucket_size | ||
|
||
return coord_points |
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
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
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,62 @@ | ||
import json | ||
import unittest | ||
|
||
from ..Coordinates import get_coordinate_for_number, total_possible_coordinates, validate_coordinate | ||
|
||
|
||
class TestCoordinateGeneration(unittest.TestCase): | ||
def test_generate_specific_coordinates(self): | ||
self.assertListEqual(get_coordinate_for_number(0), [0, 1]) | ||
self.assertListEqual(get_coordinate_for_number(1), [0, 2]) | ||
self.assertListEqual(get_coordinate_for_number(2), [0, 3]) | ||
self.assertListEqual(get_coordinate_for_number(3), [0, 4]) | ||
self.assertListEqual(get_coordinate_for_number(4), [0, 5]) | ||
self.assertListEqual(get_coordinate_for_number(5), [1, 0]) | ||
self.assertListEqual(get_coordinate_for_number(6), [1, 2]) | ||
|
||
# jump to where we switch from 2-point to 3-point coords | ||
self.assertListEqual(get_coordinate_for_number(29), [5, 4]) | ||
self.assertListEqual(get_coordinate_for_number(30), [0, 1, 2]) | ||
|
||
# jump to the very end | ||
self.assertListEqual(get_coordinate_for_number(1949), [5, 4, 3, 2, 1, 0]) | ||
|
||
def test_generate_every_coordinate(self): | ||
all_possible_coordinates = set() | ||
|
||
for coordinate_number in range(0, total_possible_coordinates): | ||
coordinate = get_coordinate_for_number(coordinate_number) | ||
all_possible_coordinates.add(json.dumps(coordinate)) | ||
# every coordinate is valid | ||
validate_coordinate(coordinate) | ||
|
||
# every coordinate is unique | ||
self.assertEqual(len(all_possible_coordinates), total_possible_coordinates) | ||
|
||
# an attempt was made to iterate through all 1950 coordinates and compare to the get_*() outputs, but | ||
# it turns out it was far easier to make get_*() correct than this test correct so I abandoned that | ||
# in case I change my mind, here's how far I got: | ||
# | ||
# coordinate = [0, 1] | ||
# for coordinate_number in range(1, total_possible_coordinates): | ||
# index = 1 | ||
# value = coordinate[-index] | ||
# while value in coordinate and index <= len(coordinate): | ||
# value += 1 | ||
# if value > 5: | ||
# index += 1 | ||
# if index > len(coordinate): | ||
# break | ||
# value = coordinate[-index] | ||
# if index <= len(coordinate): | ||
# coordinate[-index] = value | ||
# for index in range(index - 1, 0, -1): | ||
# coordinate[-index] = 0 | ||
# while len(set(coordinate)) != len(coordinate): | ||
# coordinate[-index] += 1 | ||
# else: | ||
# coordinate = list(range(0, index)) | ||
# | ||
# validate_coordinate(coordinate) | ||
# self.assertListEqual(get_coordinate_for_number(coordinate_number), coordinate, | ||
# f"coordinate number {coordinate_number} did not match get_coordinate_for_number") |