m_reps = array();
foreach( $reps as $word => $r){
$this->m_reps[ game_upper( $word)] = $r;
}
$this->m_average_reps=0;
foreach( $reps as $r)
$this->m_average_reps += $r;
if( count( $reps))
$this->m_average_reps /= count( $reps);
$this->m_input_answers = array();
foreach( $answers as $word => $answer){
$this->m_input_answers[ game_upper( $word)] = $answer;
}
$this->m_words = array();
$maxlen = 0;
foreach( $this->m_input_answers as $word => $answer)
{
$len = textlib::strlen( $word);
if( $len > $maxlen){
$maxlen = $len;
}
}
$N20 = $maxlen;
if( $N20 < 15)
$N20 = 15;
$this->m_N20min = round( $N20 - $N20/4);
$this->m_N20max = round( $N20 + $N20/4);
if( $this->m_N20max > $maxcols and $maxcols > 0){
$this->m_N20max = $maxcols;
}
if( $this->m_N20min > $this->m_N20max){
$this->m_N20min = $this->m_N20max;
}
$this->m_words = array();
foreach( $this->m_input_answers as $word => $answer)
{
$len =textlib::strlen( $word);
if( $len <= $this->m_N20max){
$this->m_words[] = game_upper( $word);
}
}
$this->randomize();
return count( $this->m_words);
}
function randomize()
{
$n = count( $this->m_words);
for($j=0; $j <= $n/4; $j++)
{
$i = array_rand( $this->m_words);
$this->swap( $this->m_words[ $i], $this->m_words[ 0]);
}
}
function computedata( &$crossm, &$crossd, &$letters, $maxwords)
{
$t1 = time();
$ctries = 0;
$m_best_score = 0;
$m_best_connectors = $m_best_filleds = $m_best_spaces = 0;
$m_best_N20 = 0;
$nochange = 0;
for(;;)
{
//selects the size of the cross
$N20 = mt_rand( $this->m_N20min, $this->m_N20max);
if( !$this->computenextcross( $N20, $t1, $ctries, $maxwords, $nochange))
break;
$ctries++;
if (time() - $t1 > $this->m_time_limit - 3){
break;
}
if( $nochange > 10)
break;
}
$this->computepuzzleinfo( $this->m_best_N20, $this->m_best_cross_pos, $this->m_best_cross_dir, $this->m_best_cross_word, false);
set_time_limit( 30);
return $this->savepuzzle( $crossm, $crossd, $ctries, time()-$t1);
}
function computenextcross( $N20, $t1, $ctries, $maxwords, &$nochange)
{
$MAXW = $N20;
$N21 = $N20 + 1;
$N22 = $N20 + 2;
$N2222 = $N22 * $N22;
$base_puzzle = str_repeat('0', $N22) .
str_repeat('0' . str_repeat('.', $N20) . '0', $N20) .
str_repeat('0', $N22);
$cross_pos = array();
$cross_dir = array();
$cross_word = array();
$magics = array();
for ($n = 2; $n < $N21; $n++)
{
$a = array();
for ($r = 2; $r < ($n + 2); $r++)
$a[] = $r;
uasort($a, array( $this, 'cmp_magic'));
$magics[ $n] = $a;
}
uasort($this->m_words, array( $this, 'cmp'));
$words = ';' . implode(';', $this->m_words) . ';';
$puzzle = $base_puzzle;
$row = mt_rand(3, max( 3, $N20-3));
$col = mt_rand(3, max( 3, $N20-3));
$pos = $N22 * $row + $col;
$poss = array();
$ret = $this->scan_pos($pos, 'h', true, $puzzle, $words, $magics, $poss, $cross_pos, $cross_dir, $cross_word, $N20);
while ($s = sizeof($poss))
{
$p = array_shift($poss);
if ($this->scan_pos($p[0], $p[1], false, $puzzle, $words, $magics, $poss, $cross_pos, $cross_dir, $cross_word, $N20)){
$n_words = count( $cross_word);
if( $maxwords){
if( $n_words >= $maxwords){
break;
}
}
}
if (time() - $t1 > $this->m_time_limit - 3){
return false;
}
}
$n_words = count( $cross_word);
$score = $this->computescore( $puzzle, $N20, $N22, $N2222, $n_words, $n_connectors, $n_filleds, $cSpaces, $cross_word);
if ($score > $this->m_best_score)
{
$this->m_best_cross_pos = $cross_pos;
$this->m_best_cross_dir = $cross_dir;
$this->m_best_cross_word = $cross_word;
$this->m_best_puzzle = $puzzle;
$this->m_bests = array('Words' => "$n_words * 5 = " . ($n_words * 5),
'Connectors' => "$n_connectors * 3 = " . ($n_connectors * 3),
'Filled in spaces' => $n_filleds,
"N20" => $N20
);
$this->m_best_score = $score;
$this->m_best_connectors = $n_connectors;
$this->m_best_filleds = $n_filleds;
$this->m_best_spaces = $cSpaces;
$this->m_best_N20 = $N20;
$nochange = 0;
}else
{
$nochange++;
}
return true;
}
function computescore( $puzzle, $N20, $N22, $N2222, $n_words, &$n_connectors, &$n_filleds, &$cSpaces, $cross_word)
{
$n_connectors = $n_filleds = 0;
$puzzle00 = str_replace('.', '0', $puzzle);
$used=0;
for ($n = 0; $n < $N2222; $n++)
{
if ($puzzle00[$n]){
$used ++;
if (($puzzle00[$n - 1] or $puzzle00[$n + 1]) and ($puzzle00[$n - $N22] or $puzzle00[$n + $N22])){
$n_connectors++;
} else{
$n_filleds++;
}
}
}
$cSpaces = substr_count( $puzzle, ".");
$score = ($n_words * 5) + ($n_connectors * 3) + $n_filleds;
$sum_rep = 0;
foreach( $cross_word as $word){
$word = textlib::substr( $word, 1, -1);
if( array_key_exists( $word, $this->m_reps))
$sum_rep += $this->m_reps[ $word] - $this->m_average_reps;
}
return $score-10*$sum_rep;
}
function computepuzzleinfo( $N20, $cross_pos, $cross_dir, $cross_word, $bPrint=false)
{
$bPrint=false;
$N22 = $N20 + 2;
$this->m_mincol = $N22;
$this->m_maxcol = 0;
$this->m_minrow = $N22;
$this->m_maxrow = 0;
$this->m_cletter = 0;
if( count( $cross_word) == 0){
return;
}
if( $bPrint)
echo "
PuzzleInfo N20=$N20 words=".count($cross_word)."
";
for($i = 0; $i < count($cross_pos); $i++)
{
$pos = $cross_pos[ $i];
$col = $pos % $N22;
$row = floor( $pos / $N22);
$dir = $cross_dir[ $i];
$len = textlib::strlen($cross_word[ $i])-3;
if( $bPrint)
echo "col=$col row=$row dir=$dir word=".$cross_word[ $i]."
";
$this->m_cletter += $len;
if( $col < $this->m_mincol)
$this->m_mincol = $col;
if( $row < $this->m_minrow)
$this->m_minrow = $row;
if( $dir == 'h')
$col += $len;
else
$row += $len;
if( $col > $this->m_maxcol)
$this->m_maxcol = $col;
if( $row > $this->m_maxrow)
$this->m_maxrow = $row;
}
if( $bPrint)
echo "mincol={$this->m_mincol} maxcol={$this->m_maxcol} minrow={$this->m_minrow} maxrow={$this->m_maxrow}
";
if( $this->m_mincol > $this->m_maxcol)
$this->m_mincol = $this->m_maxcol;
if( $this->m_minrow > $this->m_maxrow)
$this->m_minrow = $this->m_maxrow;
}
function savepuzzle( &$crossm, &$crossd, $ctries, $time)
{
$N22 = $this->m_best_N20 + 2;
$cols = $this->m_maxcol - $this->m_mincol + 1;
$rows = $this->m_maxrow - $this->m_minrow + 1;
//if( $cols < $rows)
// $bSwapColRow = 1;
//else
$bSwapColRow = 0;
if( $bSwapColRow)
{
Swap( $cols, $rows);
Swap( $this->m_mincol, $this->m_minrow);
Swap( $this->m_maxcol, $this->m_maxrow);
}
$crossm = new stdClass();
$crossm->datebegin = time();
$crossm->time = $time;
$crossm->cols = $cols;
$crossm->rows = $rows;
$crossm->words = count( $this->m_best_cross_pos);
$crossm->wordsall = count( $this->m_input_answers);
$crossm->createscore = $this->m_best_score;
$crossm->createtries = $ctries;
$crossm->createtimelimit = $this->m_time_limit;
$crossm->createconnectors = $this->m_best_connectors;
$crossm->createfilleds = $this->m_best_filleds;
$crossm->createspaces = $this->m_best_spaces;
for($i = 0; $i < count($this->m_best_cross_pos); $i++)
{
$pos = $this->m_best_cross_pos[ $i];
$col = $pos % $N22;
$row = floor( ($pos-$col) / $N22);
$col += - $this->m_mincol + 1;
$row += - $this->m_minrow + 1;
$dir = $this->m_best_cross_dir[ $i];
$word = $this->m_best_cross_word[ $i];
$word = substr( $word, 1, strlen( $word)-2);
$rec = new stdClass();
$rec->col = $col;
$rec->row = $row;
$rec->horizontal = ($dir == "h" ? 1 : 0);
$rec->answertext = $word;
$rec->questiontext = $this->m_input_answers[ $word];
if( $rec->horizontal)
$key = sprintf( 'h%10d %10d', $rec->row, $rec->col);
else
$key = sprintf( 'v%10d %10d', $rec->col, $rec->row);
$crossd[ $key] = $rec;
}
if( count( $crossd) > 1){
ksort( $crossd);
}
return (count( $crossd) > 0);
}
function swap( &$a, &$b)
{
$temp = $a;
$a = $b;
$b = $temp;
}
function displaycross($puzzle, $N20)
{
$N21 = $N20 + 1;
$N22 = $N20 + 2;
$N2222 = $N22 * $N22;
$N2221 = $N2222 - 1;
$N2200 = $N2222 - $N22;
$ret = "
"; } elseif ( $c == '0') { $ret .= " | "; } elseif ($c == '.') { $ret .= " | "; } else { if ((textlib::substr( $puzzle, $n - 1, 1) > '0' or textlib::substr( $puzzle, $n + 1, 1) > '0') and (textlib::substr( $puzzle, $n - $N22, 1) > '0' or textlib::substr( $puzzle, $n + $N22, 1) > '0')) { $ret .= " | $c | "; } else { $ret .= "$c | "; } } if ($n == $N2221) { return "$ret