7 ) return 64; /* error code */ $index=$y*8+$x; return $index; } /* Convert index [0..63] to board coordinate [a-h][1-8] */ function i2bc($index) { if ($index<0 || $index>63) return ''; $y=floor($index/8)+1; $x=chr(($index%8)+97); $coord=$x.$y; return $coord; } /* Get full name of chessman from chessman identifier. */ function getCMName($short) { $name='empty'; switch ($short) { case 'P': $name='Pawn'; break; case 'R': $name='Rook'; break; case 'N': $name='Knight'; break; case 'B': $name='Bishop'; break; case 'K': $name='King'; break; case 'Q': $name='Queen'; break; } return $name; } /* Get difference in chessmen for each class (pawn=0,queen=5). * Positive value = White has more, Negative value = Black has more. */ function getCMDiff($board) { $diff = array(0,0,0,0,0); for ($i=0;$i<64;$i++) { switch ($board[$i]) { case 'wP': $diff[0]++; break; case 'wN': $diff[1]++; break; case 'wB': $diff[2]++; break; case 'wR': $diff[3]++; break; case 'wQ': $diff[4]++; break; case 'bP': $diff[0]--; break; case 'bN': $diff[1]--; break; case 'bB': $diff[2]--; break; case 'bR': $diff[3]--; break; case 'bQ': $diff[4]--; break; } } for ($i=0;$i<5;$i++) if ($diff[$i] != 0) return $diff; return null; } /** Return URL to game with id $gid. */ function getGameURL( $gid ) { /* XXX access $_SERVER; otherwise $GLOBALS seems to be empty; * maybe a bug in PHP? */ $temp = $_SERVER['SERVER_NAME']; // dummy access $prot=($GLOBALS['_SERVER']['HTTPS']=='on')?'https':'http'; $script=$GLOBALS['_SERVER']['SCRIPT_NAME']; /* $script is the script calling this function but we want to redirect * to board.php so we have to replace the name (can't use board.php * directly since we don't know path to script on server). */ $script = dirname($script)."/board.php"; return $prot.'://'.$GLOBALS['_SERVER']['HTTP_HOST'].$script.'?gid='.$gid; } ?> 1) $list[$j]=$moves[1]; else $list[$j]='???'; if (count($moves)>2) $list[1+$j]=$moves[2]; else if ($i<$game['curmove']) $list[1+$j]='???'; /* Note: Possibly missing move of black in current move * is not set '' or something to easily allow undo of move * via unset(). '' or even null would be counted as existing * list item. */ } $game['mhistory']=$list; /* Get chatter */ $game['chatter']=array(); for ($i=4+$game['curmove'],$j=0;$i2419200/*four weeks*/ && $game['archived']==0) $game['p_mayabort']=1; else if (!empty($game['p_color']) && $game['archived']==0 && $game['p_maymove']==1 && (($game['p_color']=='w' && $game['curmove']==0)|| ($game['p_color']=='b' && $game['curmove']==1))) $game['p_mayabort']=1; /* Check whether player may undo (only possible if game not finished) */ if ($game['lastmove']!='x' && $game['archived']==0 && (($game['curplyr']=='b' && $game['white']==$uid) || ($game['curplyr']=='w' && $game['black']==$uid)) && ($game['curstate']=='D' || $game['curstate']=='?') && time()-$game['ts_last']<1200) $game['p_mayundo']=1; else $game['p_mayundo']=0; return $game; } /* Load game info and return it as array. If $location is not null it is either * 'opengames' or 'archive'. If set only that one location is checked. Return * null if error occured. * archived: resides in archive * ts_start: timestamp of starting date (secs) * ts_last: timestamp of last move (secs) * white: name of white player * black: name of black player * curmove: number of current move (start at 0) * curplyr: color of current player (w or b) * curstate: state of game (w/b=white/black won,-=draw,D=draw offered,?=open) */ function ioLoadGameInfo($location,$gid) { global $res_games,$res_archive; $game=array(); /* Load raw game data */ if (($location==null || $location=='opengames') && file_exists("$res_games/$gid")) { $raw=file("$res_games/$gid"); $game['archived']=0; } else if (($location==null || $location=='archive') && file_exists("$res_archive/$gid")) { $raw=file("$res_archive/$gid"); $game['archived']=1; } else return null; /* NB: this is required since usort in loadInfos will destroy the index * key. Therefore each entry needs to know the game id. */ $game['gid']=$gid; /* Build time stamps */ $aux=explode(' ',trim($raw[0])); $game['ts_start']=mktime($aux[3],$aux[4],0,$aux[1],$aux[2],$aux[0]); $game['ts_last']=mktime($aux[8],$aux[9],0,$aux[6],$aux[7],$aux[5]); /* Parse header */ $hdr=explode(' ',trim($raw[1])); $game['white']=$hdr[0]; $game['black']=$hdr[1]; $game['curmove']=$hdr[2]; $game['curplyr']=$hdr[3]; $game['curstate']=$hdr[4]; return $game; } /* Load array of game infos according to the given filter criteria. null for a * criteria means any value. $location must be set either 'opengames' or * 'archive'. * Always returns an array but it may be empty if no matching games were found * and entries are sorted most recent first. */ function compareTimestamp($a,$b) { if ($a['ts_last']==$b['ts_last']) return 0; else if ($a['ts_last']<$b['ts_last']) return 1; else return -1; } function ioLoadGameInfoList($location,$player,$pcolor,$opponent) { global $res_games,$res_archive; if ($location=='archive') $dirname=$res_archive; else $dirname=$res_games; $infos=array(); $hdir=opendir($dirname); while ($entry=readdir($hdir)) { if ($entry=='.' || $entry=='..') continue; if ($player!=null || $opponent!=null) { if ($opponent!=null && strpos($entry,'-'.$opponent.'-')===false) continue; if ($player!=null) { if (strpos($entry,'-'.$player.'-')===false) continue; if ($pcolor!=null) { $fields=explode('-',$entry); if ($pcolor=='w' && $fields[1]!=$player) continue; else if ($pcolor=='b' && $fields[2]!=$player) continue; } } } $infos[$entry]=ioLoadGameInfo($location,$entry); } closedir($hdir); /* NB: sort will destroy index key, therefore $infos['gid'] is used * later instead. */ if (count($infos)>0) usort($infos,'compareTimestamp'); return $infos; } /* Save an open game and update last move time stamp to current time. Chatter * must have been updated already (newest is first in list). */ function ioSaveGame($game,$gid) { global $res_games; $hfile=fopen("$res_games/$gid",'w'); fwrite($hfile,date('Y m d H i ',$game['ts_start'])); fwrite($hfile,date('Y m d H i',time())); fwrite($hfile,"\n"); fwrite($hfile,$game['white'].' '.$game['black'].' '); fwrite($hfile,$game['curmove'].' '.$game['curplyr'].' '); fwrite($hfile,$game['curstate'].' '.$game['wcs'].' '.$game['wcl'].' '); fwrite($hfile,$game['bcs'].' '.$game['bcl'].' '.$game['w2spm'].' '); fwrite($hfile,$game['b2spm'].' '.$game['lastmove'].' '); fwrite($hfile,$game['lastkill'].' '.$game['oscf'].' '); fwrite($hfile,$game['olcf']."\n"); for ($i=0;$i<64;$i++) if ($game['board'][$i]!='' && $game['board'][$i][0]=='w') { $c=i2bc($i); fwrite($hfile,$game['board'][$i][1].$c.' '); } fwrite($hfile,"\n"); for ($i=0;$i<64;$i++) if ($game['board'][$i]!='' && $game['board'][$i][0]=='b') { $c=i2bc($i); fwrite($hfile,$game['board'][$i][1].$c.' '); } fwrite($hfile,"\n"); for ($i=0,$j=1;$i',$bcomment); } $bcomment=''.$black.': '.$bcomment; $game['chatter']=array($bcomment); /* Save game to file */ $gfname=sprintf('%s-%s-%s-',date('YmdHi',$game['ts_start']),$white,$black); ioSaveGame($game,$gfname); return $gfname; } /* Update login history of user (add new new timestamp). * XXX no access locking since user won't log in twice the same time... */ function ioUpdateLoginHistory($uid) { global $res_users; if (!file_exists("$res_users/lhistory/$uid")) { /* Create default values (login every 48 hours) */ $hfile=fopen("$res_users/lhistory/$uid",'w'); $ts=time(); for ($i=0;$i<14;$i++) { fwrite($hfile,$ts."\n"); $ts-=172800; } fclose($hfile); return; } $list=file("$res_users/lhistory/$uid"); $hfile=fopen("$res_users/lhistory/$uid",'w'); $ts=time(); fwrite($hfile,$ts."\n"); for ($i=0;$i<13;$i++) fwrite($hfile,$list[$i]); fclose($hfile); } /* Compute activity from login history: A time stamp in last week (compared to * current time) scores four points. For every week more one point is * substraced. Timestamps older than four weeks are ignored. The final score * is doubled. Fresher logins count more than older ones. */ function ioGetUserActivity($uid) { global $res_users; if (!file_exists("$res_users/lhistory/$uid")) return 0; $list=file("$res_users/lhistory/$uid"); $score=0; $cur=time(); for ($i=0;$i<14;$i++) { if ($cur - $list[$i] <= 604800) $score += 4; else if ($cur - $list[$i] <= 2*604800) $score += 3; else if ($cur - $list[$i] <= 3*604800) $score += 2; else if ($cur - $list[$i] <= 4*604800) $score += 1; } if ($score<0) $score=0; if ($score>50) $score=50; return $score*2; } /* Load list of all users as name=>name. */ function ioLoadUserList() { global $res_users; include($res_users.'/accounts.php'); $list=array(); foreach ($passwords as $usr=>$pwd) $list[$usr]=$usr; return $list; } /* Load user password or return null if not found. */ function ioLoadUserPassword($uid) { global $res_users; include($res_users.'/accounts.php'); if (isset($passwords[$uid])) return $passwords[$uid]; return null; } /* Get email address of user. Return null if not present. */ function ioLoadUserEmailAddress($uid) { global $res_users; include($res_users.'/accounts.php'); if (isset($mail_addresses[$uid])) return $mail_addresses[$uid]; return null; } /* Load user theme. */ function ioLoadUserTheme($uid) { return 'default'; /* XXX always default for now */ } /* Load stats of user. Always return array but values are all zero if not found. * wins: number of wins * draws: number of draws * losses: number of losses * rating: current ELO rating * rgames: number of rating change games (update every 5 games) * rchange: base value of next rating modification */ function ioLoadUserStats($uid) { global $res_users; $usr=array(); $usr['wins']=0; $usr['draws']=0; $usr['losses']=0; $usr['rating']=0; $usr['rgames']=0; $usr['rchange']=0; $uf=file($res_users.'/stats'); foreach ($uf as $entry) if (strncmp($entry,$uid.':',strlen($uid)+1)==0) { /* name:wins:draws:losses:rating:rgames:rmod */ $info=explode(':',$entry); $usr['wins']=$info[1]; $usr['draws']=$info[2]; $usr['losses']=$info[3]; /* XXX backward compatibility: Always assume average * opponent strength of 1200. If less than 5 games * store sum of opponent strength in 'rchange' (to get * initial strength later, see rating system) otherwise * compute initial strength by considering all game * results (not only first five since these can't be * figured out anymore - gives better initial rating * anyway). */ if (count($info)<5) { $num=$info[1]+$info[2]+$info[3]; if ($num<5) { $usr['rgames']=$num; $usr['rchange']=$num*1200; } else { $rating=getInitRating($info[1],$info[2], $info[3],1200); $usr['rating']=floor($rating); } } else { $usr['rating']=$info[4]; $usr['rgames']=$info[5]; $usr['rchange']=$info[6]; } break; } return $usr; } /* Save user stats to file: replace if entry exists or append if it is new. */ function ioSaveUserStats($uid,$stats) { global $res_users; $statstr=sprintf('%s:%s:%s:%s:%s:%s:%s',$uid, $stats['wins'],$stats['draws'], $stats['losses'],$stats['rating'], $stats['rgames'],$stats['rchange']); $new=1; /* Load and possible replace */ $uf=file($res_users.'/stats'); foreach ($uf as $key=>$entry) if (strncmp($entry,$uid.':',strlen($uid)+1)==0) { $new=0; $uf[$key]=$statstr."\n"; } /* Save and possibly append */ $hfile=fopen($res_users.'/stats','w'); foreach ($uf as $entry) fwrite($hfile,$entry); if ($new) fwrite($hfile,$statstr."\n"); fclose($hfile); } /* Load (and decrypt) private notes of user related to opponent. */ function _decrypt($notes,$key) { if (strlen($key)==0) return $notes; $aux=explode(' ',$notes); $high=$aux[1]; $low=$aux[2]; for ($i=0,$j=0;$i$note) { fwrite($hfile,"'".$opp."'=>'".$note."'"); if ($i+1<$n) fwrite($hfile,','); fwrite($hfile,"\n"); $i++; } fwrite($hfile,'); ?>'); fclose($hfile); } ?>