Last active
September 22, 2021 13:01
-
-
Save benthebear/8198f6fc93515824de47abc1074faff3 to your computer and use it in GitHub Desktop.
tilescape.php
This file contains hidden or 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
<?php | |
/* | |
Any given tile | |
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 | |
*/ | |
?> | |
<html> | |
<head> | |
<style type="text/css"> | |
html { | |
} | |
h1 { | |
margin:auto; | |
text-align: center; | |
} | |
table { | |
font-size:10px; | |
font-family: sans-serif; | |
border-collapse: collapse; | |
} | |
table, tr, td { | |
margin:0px; | |
padding:0px; | |
box-sizing: border-box; | |
} | |
td { | |
} | |
.room { | |
border:1px solid black; | |
margin:auto; | |
background-color:dimgray; | |
padding:20px; | |
} | |
/* The Outer Table */ | |
.tabletop { | |
background-color:dimgray; | |
margin:auto; | |
} | |
.tabletop-row { | |
} | |
.tabletop, | |
.tabeltop th, | |
.tabletop td { | |
} | |
/* Each Tile */ | |
.tile { | |
visibility:hidden; | |
} | |
.tile, | |
.tile th, | |
.tile td { | |
border:1px solid gray; | |
} | |
.tile td { | |
text-align: center; | |
width:20px; | |
height:21px; | |
} | |
.tile td div { | |
} | |
.solid { | |
color: white; | |
background-color:black; | |
} | |
.open { | |
background-color: ivory; | |
} | |
.library .all-tiles { | |
display:flex; | |
flex-wrap:wrap; | |
align-items: end; | |
align-content: flex-start; | |
justify-content: flex-start; | |
} | |
.library .single-tile { | |
margin-left:10px; | |
width:120px; | |
} | |
.library .single-tile h3 { | |
font-size:12px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1 id="title" data-show="0">Tilescape</h1> | |
<?php | |
class tile { | |
public $grid; | |
public $sides; | |
public $opensides_count; | |
public $type; | |
public $name; | |
public $position_x; | |
public $position_y; | |
public $number; | |
public function __construct($type, $number){ | |
$this->type = $type; | |
$this->number = $number; | |
$this->init_grid(); | |
if(!is_array($grid)){ | |
$this->grid = array(); | |
}else{ | |
$this->grid = $grid; | |
} | |
$this->fill_grid_by_type($type); | |
$this->calculate_open_sides(); | |
} | |
public function init_grid(){ | |
$this->set_all_fields("open"); | |
} | |
public function set_all_fields($state){ | |
for($i=1; $i<=25; $i++){ | |
$this->grid[$i] = $state; | |
} | |
} | |
public function set_fields_open($fields){ | |
$this->set_field_state($fields, "open"); | |
} | |
public function set_fields_solid($fields){ | |
$this->set_field_state($fields, "solid"); | |
} | |
public function set_field_state($fields, $state){ | |
foreach($fields as $fieldid){ | |
$this->grid[$fieldid] = $state; | |
} | |
} | |
public function calculate_open_sides(){ | |
$opensides_count = 0; | |
if($this->grid[3] == "open"){ | |
$this->opensides_count ++; | |
$this->sides['top'] = "open"; | |
}else{ | |
$this->sides['top'] = "solid"; | |
} | |
if($this->grid[11] == "open"){ | |
$this->opensides_count ++; | |
$this->sides['left'] = "open"; | |
}else{ | |
$this->sides['left'] = "solid"; | |
} | |
if($this->grid[15] == "open"){ | |
$this->opensides_count ++; | |
$this->sides['right'] = "open"; | |
}else{ | |
$this->sides['right'] = "solid"; | |
} | |
if($this->grid[23] == "open"){ | |
$this->opensides_count ++; | |
$this->sides['bottom'] = "open"; | |
}else{ | |
$this->sides['bottom'] = "solid"; | |
} | |
} | |
public function fill_grid_by_type($type){ | |
switch($type){ | |
case(0): | |
$this->name = "Start Tile"; | |
$this->set_all_fields("open"); | |
break; | |
case(1): | |
$this->name = "Narrow dead end"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(8,13,18,23)); | |
break; | |
case(2): | |
$this->name = "Narrow straight corridor"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,13,18,23)); | |
break; | |
case(3): | |
$this->name = "Narrow full-junction"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,11,12,13,14,15,18,23)); | |
break; | |
case(4): | |
$this->name = "Narrow y-junction"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,13,14,15,18,23)); | |
break; | |
case(5): | |
$this->name = "Narrow turn"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(13,14,15,18,23)); | |
break; | |
case(6): | |
$this->name = "Dead end Room"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(7,8,9,12,13,14,17,18,19,23)); | |
break; | |
case(7): | |
$this->name = "Walk-through room Room"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,7,8,9,12,13,14,17,18,19,23)); | |
break; | |
case(8): | |
$this->name = "Narrow turn room"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(7,8,9,12,13,14,15,17,18,19,23)); | |
break; | |
case(9): | |
$this->name = "4 Doors room"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,7,8,9,11,12,13,14,15,17,18,19,23)); | |
break; | |
case(10): | |
$this->name = "Y-junction room"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(7,8,9,11,12,13,14,15,17,18,19,23)); | |
break; | |
case(11): | |
$this->name = "Dead end smalll Room"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(7,8,9,12,13,14,18,23)); | |
break; | |
case(12): | |
$this->name = "Twisting corridor"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,9,14,18,19,23)); | |
break; | |
case(13): | |
$this->name = "Alcoves"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,7,8,9,13,17,18,19,23)); | |
break; | |
case(14): | |
$this->name = "Narrow straight corridor with bulge"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,9,13,14,18,19,23)); | |
break; | |
case(15): | |
$this->name = "Narrow diagonal y-junction"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,9,14,15,18,19,23)); | |
break; | |
case(16): | |
$this->name = "Wide straight corridor"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,5,6,10,11,15,16,21,25)); | |
break; | |
case(17): | |
$this->name = "Wide turn"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,2,3,4,5,6,11,16,21,25)); | |
break; | |
case(18): | |
$this->name = "Wide y-junction"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,2,3,4,5,21,25)); | |
break; | |
case(19): | |
$this->name = "Wide full junction"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,5,21,25)); | |
break; | |
case(20): | |
$this->name = "Wide diagonal y-junction"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,5,6,7,11,12,13,14,16,17,21,25)); | |
break; | |
case(21): | |
$this->name = "Narrowing straight corridor"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,12,13,14,17,18,19,22,23,24)); | |
break; | |
case(22): | |
$this->name = "Wide t-junction with narrow corridor"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(11,12,13,14,15,17,18,19,22,23,24)); | |
break; | |
case(23): | |
$this->name = "Wide t-junction with narrow corridor"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,8,11,12,13,14,15,17,18,19,22,23,24)); | |
break; | |
case(24): | |
$this->name = "Wide straight corridor with two narrow junctions"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,5,6,10,16,20,21,25)); | |
break; | |
case(25): | |
$this->name = "Wide straight corridor with one narrow junctions"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,5,6,10,15,16,20,21,25)); | |
break; | |
case(26): | |
$this->name = "Open area"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array()); | |
break; | |
case(27): | |
$this->name = "Almost open area"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(21,25)); | |
break; | |
case(28): | |
$this->name = "Wide junction with one narrow turn"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,2,4,5,21,25)); | |
break; | |
case(29): | |
$this->name = "Wide turn with two narrow junctions"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,2,4,5,6,16,21,25)); | |
break; | |
case(30): | |
$this->name = "Wide corridor end three narrow junctions"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,2,4,5,6,10,16,20,21,25)); | |
break; | |
case(31): | |
$this->name = "Wide dead end"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(1,2,3,4,5,6,10,11,15,16,20,21,25)); | |
break; | |
case(32): | |
$this->name = "Double turn"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,7,8,11,12,14,15,18,19,23)); | |
break; | |
case(33): | |
$this->name = "Stronger Double turn"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(2,3,7,11,12,23,24,19,14,15)); | |
break; | |
case(34): | |
$this->name = "Central Pillar"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(8,12,13,14,18)); | |
break; | |
case(35): | |
$this->name = "Four Pillars"; | |
$this->set_all_fields("open"); | |
$this->set_fields_solid(array(7,9,17,19)); | |
break; | |
case(36): | |
$this->name = "Narrow full-junction with pillar"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,7,8,9,11,12,14,15,17,18,19,23)); | |
break; | |
case(37): | |
$this->name = "Narrow full-junction with pillar"; | |
$this->set_all_fields("solid"); | |
$this->set_fields_open(array(3,7,8,9,12,14,15,17,18,19,23)); | |
break; | |
} | |
} | |
public function rotate_tile_cockwise(){ | |
$new_grid = array(); | |
$new_grid[1] = $this->grid[21]; | |
$new_grid[2] = $this->grid[16]; | |
$new_grid[3] = $this->grid[11]; | |
$new_grid[4] = $this->grid[6]; | |
$new_grid[5] = $this->grid[1]; | |
$new_grid[6] = $this->grid[22]; | |
$new_grid[7] = $this->grid[17]; | |
$new_grid[8] = $this->grid[12]; | |
$new_grid[9] = $this->grid[7]; | |
$new_grid[10] = $this->grid[2]; | |
$new_grid[11] = $this->grid[23]; | |
$new_grid[12] = $this->grid[18]; | |
$new_grid[13] = $this->grid[13]; | |
$new_grid[14] = $this->grid[8]; | |
$new_grid[15] = $this->grid[3]; | |
$new_grid[16] = $this->grid[24]; | |
$new_grid[17] = $this->grid[19]; | |
$new_grid[18] = $this->grid[14]; | |
$new_grid[19] = $this->grid[9]; | |
$new_grid[20] = $this->grid[4]; | |
$new_grid[21] = $this->grid[25]; | |
$new_grid[22] = $this->grid[20]; | |
$new_grid[23] = $this->grid[15]; | |
$new_grid[24] = $this->grid[10]; | |
$new_grid[25] = $this->grid[5]; | |
$this->grid = $new_grid; | |
$this->calculate_open_sides(); | |
} | |
public function render($print = false, $visibility = "hidden"){ | |
$output = ""; | |
$output .= "<table id='tile-number-".$this->number."' class='table-tile tile tile-type-".$this->type." tile-number-".$this->number."' style='visibility:".$visibility.";'>\n"; | |
for($y = 1; $y<=5; $y++){ | |
$output .= "<tr>\n"; | |
for($x = 1; $x<=5; $x++){ | |
$pos = (($y*5)-5)+$x; | |
$output .= "<td class='".$this->grid[$pos]."'>"; | |
if($pos == 13){ | |
$output .= $this->number; | |
}else{ | |
$output .= " "; | |
} | |
$output .= "</td>\n"; | |
} | |
$output .= "</tr>\n"; | |
} | |
$output .= "</table>\n"; | |
if($print){ | |
print $output; | |
return true; | |
}else{ | |
return $output; | |
} | |
} | |
} | |
class tabletop { | |
public $grid = array(); | |
public $tiles = array(); | |
public $availables = array(); // An array of X/Y-positions on the table currently avaiable to add a new tile. | |
public $logs = array(); | |
public $lowest_x = -1; | |
public $lowest_y = -1; | |
public $highest_x = 1; | |
public $highest_y = 1; | |
public function __construct(){ | |
$start_tile = new tile(0,0); | |
$position_x = 0; | |
$position_y = 0; | |
$start_tile->position_x = $position_x; | |
$start_tile->position_y = $position_y; | |
$this->grid[$position_x][$position_x] = $start_tile; | |
$this->tiles[] = $start_tile; | |
} | |
public function calculate_all_availables(){ | |
// Reset all Availables | |
$this->availables = array(); | |
// Go through each current tile | |
foreach($this->tiles as $tile){ | |
$position_x = $tile->position_x; | |
$position_y = $tile->position_y; | |
// Check wether the 4 postions around that tile a available | |
// if so, add that position to the list of Availables. | |
if(!isset($this->grid[$position_x][$position_y-1])){ | |
$this->availables[] = array($position_x, $position_y-1); | |
} | |
if(!isset($this->grid[$position_x+1][$position_y])){ | |
$this->availables[] = array($position_x+1, $position_y); | |
} | |
if(!isset($this->grid[$position_x][$position_y+1])){ | |
$this->availables[] = array($position_x, $position_y+1); | |
} | |
if(!isset($this->grid[$position_x-1][$position_y])){ | |
$this->availables[] = array($position_x-1, $position_y); | |
} | |
} | |
} | |
public function add_a_tile($type = 1, $number){ | |
$new_tile = new tile($type, $number); | |
$this->log[] = "<b>Trying to add Tile No. ".$new_tile->number." type ".$new_tile->type." </b>"; | |
$new_tile = $this->try_to_add_tile($new_tile); | |
if($new_tile){ | |
// Place the Tile in the Grid | |
$this->calculate_new_maximums($new_tile->position_x, $new_tile->position_y); | |
$this->grid[$new_tile->position_x][$new_tile->position_y] = $new_tile; | |
$this->tiles[] = $new_tile; | |
}else{ | |
$this->log[] = "Couldn't place tile! Skipping it."; | |
} | |
} | |
public function try_to_add_tile($new_tile){ | |
// Position the Tile | |
$this->calculate_all_availables(); | |
$rand_available_position = rand(0,count($this->availables)-1); | |
$new_position = $this->availables[$rand_available_position]; | |
// Set new positions | |
$new_x = $new_position[0]; | |
$new_y = $new_position[1]; | |
$new_tile->position_x = $new_x; | |
$new_tile->position_y = $new_y; | |
$this->log[] = "Trying to add Tile at $new_x / $new_y"; | |
// Adjust current maximum expansion of the table; | |
$this->calculate_new_maximums($new_x, $new_y); | |
// Maybe rotate the Tile. | |
$result = $this->rotate_tile_best($new_tile); | |
if(!$result and count($this->availables)>0){ | |
$this->log[] = "Could not find a matching rotation, trying another available"; | |
unset($this->availables[$rand_available_position]); | |
$result = $this->try_to_add_tile($new_tile); | |
}else{ | |
$this->log[] = "No matching available position"; | |
} | |
return $result; | |
} | |
public function calculate_new_maximums($new_x, $new_y){ | |
if($new_x < $this->lowest_x){ | |
$this->lowest_x = $new_x; | |
} | |
if($new_x > $this->highest_x){ | |
$this->highest_x = $new_x; | |
} | |
if($new_y < $this->lowest_y){ | |
$this->lowest_y = $new_y; | |
} | |
if($new_y > $this->highest_y){ | |
$this->highest_y = $new_y; | |
} | |
} | |
public function render($print = false){ | |
$output = ""; | |
$output .= "<div class='room'>"; | |
$output .= "<table class='tabletop'>\n"; | |
for($i = $this->lowest_y; $i <= $this->highest_y; $i++){ | |
$output .= "<tr class='tabletop-row'>\n"; | |
for($j = $this->lowest_x; $j <= $this->highest_x; $j++){ | |
$output .= "<td>\n"; | |
if(isset($this->grid[$j][$i]->type)){ | |
$output .= "".$this->grid[$j][$i]->render(); | |
}else{ | |
$output .= " "; | |
} | |
$output .= "</td>\n"; | |
} | |
$output .= "</tr>\n"; | |
} | |
$output .= "</table>\n"; | |
$output .= "</div>"; | |
return $this->print_or_return($output, $print); | |
} | |
public function get_all_adjacent_tiles($x, $y){ | |
$adjacent_tiles = array(); | |
if(isset($this->grid[$x][$y-1])){ | |
$adjacent_tiles['top'] = $this->grid[$x][$y-1]; | |
} | |
if(isset($this->grid[$x+1][$y])){ | |
$adjacent_tiles['right'] = $this->grid[$x+1][$y]; | |
} | |
if(isset($this->grid[$x][$y+1])){ | |
$adjacent_tiles['bottom'] = $this->grid[$x][$y+1]; | |
} | |
if(isset($this->grid[$x-1][$y])){ | |
$adjacent_tiles['left'] = $this->grid[$x-1][$y]; | |
} | |
return $adjacent_tiles; | |
} | |
public function rotate_tile_random($title){ | |
$rotations = rand(1,4); | |
for($i = 1; $i<$rotations; $i++){ | |
$new_tile->rotate_tile_cockwise(); | |
$this->log[] = "Turned current Tile randomly"; | |
} | |
return $tile; | |
} | |
public function rotate_tile_best($tile){ | |
// Get the adjacent tiles | |
$adjacent_tiles = $this->get_all_adjacent_tiles($tile->position_x, $tile->position_y); | |
// Calculate the fitting connection for each possible rotation | |
$this->log[] = "Tile ".$tile->number." is open ".print_r($tile->sides, true); | |
// Fist: Search the best fitting rotation | |
$highest_hits = 0; | |
$highest_rotation = 0; | |
for($rotation = 0; $rotation < 4; $rotation++){ | |
$current_hits = 0; | |
if($tile->sides['top'] == "open" and isset($adjacent_tiles['top']) and $adjacent_tiles['top']->sides['bottom'] == "open"){ | |
$current_hits ++; | |
$this->log[] = "Top hit"; | |
} | |
if($tile->sides['right'] == "open" and isset($adjacent_tiles['right']) and $adjacent_tiles['right']->sides['left'] == "open"){ | |
$current_hits ++; | |
$this->log[] = "Right hit"; | |
} | |
if($tile->sides['bottom'] == "open" and isset($adjacent_tiles['bottom']) and $adjacent_tiles['bottom']->sides['top'] == "open"){ | |
$current_hits ++; | |
$this->log[] = "Bottom hit"; | |
} | |
if($tile->sides['left'] == "open" and isset($adjacent_tiles['left']) and $adjacent_tiles['left']->sides['right'] == "open"){ | |
$current_hits ++; | |
$this->log[] = "Left hit"; | |
} | |
$this->log[] = "Rotation $rotation with $current_hits hits."; | |
$tile->rotate_tile_cockwise(); | |
if($current_hits > $highest_hits){ | |
$highest_hits = $current_hits; | |
$highest_rotation = $rotation; | |
} | |
} | |
// Second: Turn the Tile that often, again | |
for($i = 1; $i <= $highest_rotation; $i++){ | |
$tile->rotate_tile_cockwise(); | |
} | |
if($highest_hits == 0){ | |
return false; | |
}else{ | |
$this->log[] = "Rotated tile to best position with $highest_hits as the highest hit $highest_rotation times."; | |
return $tile; | |
} | |
} | |
public function print_logs($print = false){ | |
$output = ""; | |
$output .= "<h2>Logs</h2>\n"; | |
$output .= "<ol>"; | |
foreach($this->log as $log){ | |
$output .= "<li>$log</li>\n"; | |
} | |
$output .= "</ol>\n"; | |
return $this->print_or_return($output, $print); | |
} | |
public function print_or_return($output, $print=false){ | |
if($print){ | |
print $output; | |
return true; | |
}else{ | |
return $output; | |
} | |
} | |
public function render_library(){ | |
$output = ""; | |
$output .= "<div class='library'>\n"; | |
$output .= "<h2>Tile Library</h2>\n"; | |
$output .= "<div class='all-tiles'>\n"; | |
for($i = 0; $i<38; $i++){ | |
$tile = new tile($i, $i); | |
$output .= "<div class='single-tile'>\n"; | |
$output .= "<h3>".$tile->name."</h3>"; | |
$output .= $tile->render(false, "visible"); | |
$output .= "</div>\n"; | |
} | |
$output .= "</div>\n"; | |
$output .= "</div>\n"; | |
return $output; | |
} | |
} | |
$tabletop = new tabletop(); | |
for($i=1; $i<32; $i++){ | |
$tabletop->add_a_tile(rand(1,37), $i); | |
} | |
print $tabletop->render(); | |
print $tabletop->render_library(); | |
print $tabletop->print_logs(); | |
?> | |
<script type="text/javascript"> | |
function show(tileid){ | |
//alert(tileid); | |
if(document.getElementById(tileid)){ | |
if (document.getElementById(tileid).style.visibility == "hidden"){ | |
document.getElementById(tileid).style.visibility = "visible"; | |
} | |
} | |
} | |
function showtiles(){ | |
var number; | |
number = document.getElementById('title').getAttribute('data-show'); | |
show("tile-number-"+number); | |
number = Number(number)+1; | |
document.getElementById('title').setAttribute('data-show', number); | |
} | |
var myVar = setInterval(showtiles, 1000); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment