renamed class brisco to Room, some free funcs moved to static class funcs, split...
[brisk.git] / web / brisk.phh
1 <?php
2 /*
3  *  brisk - brisk.phh
4  *
5  *  Copyright (C) 2006-2007 matteo.nastasi@milug.org
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details. You should have received a
16  * copy of the GNU General Public License along with this program; if
17  * not, write to the Free Software Foundation, Inc, 59 Temple Place -
18  * Suite 330, Boston, MA 02111-1307, USA.
19  *
20  */
21
22 define(FTOK_PATH, "/var/lib/brisk");
23 define(LEGAL_PATH, "/tmp/legal_brisk");
24 define(PROXY_PATH, "/var/lib/brisk_proxy");
25 define(TABLES_N, 12);
26 define(PLAYERS_N, 3);
27 define(MAX_POINTS, 5);
28 define(MAX_PLAYERS, (20 + (PLAYERS_N * TABLES_N)));
29 define(SHM_DIMS, (50000 * MAX_PLAYERS));
30 // define(COMM_N, 6);
31 define(COMM_N, 12);
32 define(COMM_GEN_N, 50);
33 define(SESS_LEN, 13);
34 define(STREAM_TIMEOUT, 20);
35 define(EXPIRE_TIME_RD, 180);
36 define(EXPIRE_TIME_SMAMMA, 360); 
37 // BAN_TIME da allineare anche in commons.js
38 define(BAN_TIME, 900); 
39 define(GARBAGE_TIMEOUT, 10);
40 define(NICKSERV, "<i>SERVER</i>");
41 define(BRISK_DEBUG, FALSE);
42 // define(DEBUGGING, "local");
43
44 $G_false = FALSE;
45
46 $G_all_points = array( 11,10,4,3,2, 0,0,0,0,0 );
47 $G_brisk_version = "0.8.2";
48
49 $root_wellarr = Array ( 'Benvenuto in brisk (Ver. '.$G_brisk_version.'), <b>NOVITA\'</b>: nuovo layout che permette pi&ugrave; tavoli, pi&ugrave; tavoli.',
50                         'Se vuoi iscriverti alla <a target="_blank" href="http://www.milug.org/cgi-bin/mailman/listinfo/ml-briscola">Mailing List</a>, cliccala!' );
51 $table_wellarr = Array ( 'Benvenuto al tavolo. Se almeno tre giocatori non sbloccano l\'uscita cliccando il lucchetto, chi esce non pu&ograve; risedersi a un qualunque tavolo per '.floor(BAN_TIME/60).' minuti.');
52
53
54 $G_room_help= '
55 <div style=\\"text-align: left; padding: 8px;\\">
56 <b>Descrizione</b><br>
57 Questa &egrave; un\'implementazione della briscola in cinque, cos&igrave; come &egrave; spiegata su
58 <a target=\\"_blank\\" href=\\"http://it.wikipedia.org/wiki/Briscola#Gioco_a_5\\">Wikipedia</a>; in breve &egrave; la variante con l\'asta prima sulla carta e poi sui punti.<br><br>
59 <b>Configurazione del browser.</b><br>
60 Occorre abilitare i cookies.<br>
61 <br>
62 <b>Uso del sito</b><br>
63 Potete sedervi a un tavolo o rimanere in piedi.<br>
64 Se al vostro tavolo si raggiungono i 5 giocatori inizia automaticamente la partita.<br>
65 <br>
66 <b>Partita</b><br>
67 All\'inizio vengono distribuite le carte e parte l\'asta; per partecipare all\'asta, quando sar&agrave; il vostro turno, potrete scegliere se andare avanti o passare cliccando sulle icone corrispondenti. Se si arriva ai punti, scrivete nella textbox il vostro rilancio e cliccate PUNTI.<br><br>
68 Chi vince l\'asta dovr&agrave; decidere il seme della carta scelta e inizier&agrave; la mano.<br>
69 Per giocare le carte dovrete trascinarle nel quadrato al centro del vostro schermo.<br><br>
70 Il vostro turno &egrave; sempre segnalato da una cornice verde lampeggiante intorno al quadrato al centro del vostro schermo.<br><br>
71 Durante la partita, se vorrete ricaricare la pagina, usate l\'apposito bottone \\"reload\\" in basso a destra.<br>
72 Dopo che &egrave; iniziata una partita per uscirne dovete chiedere agli altri giocatori di sbloccarla cliccando sul lucchetto. Se non si segue questa prassi, una volta usciti, non vi potrete sedere a nessun tavolo per '.floor(BAN_TIME/60).' minuti.
73 <dl>
74 <dt><b>Comandi della chat</b>
75 <dd><b>/nick <i>&lt;nuovo_nickname&gt;</i></b> - cambio di nickname
76 <dd>.. to be continue ..
77 </dl>
78 </div>
79 ';
80
81 $G_room_about= '<br>
82 <div id=\\"header\\" class=\\"header\\">
83   <img class=\\"nobo\\" src=\\"img/brisk_logo64.png\\">
84   briscola chiamata in salsa ajax
85 </div>
86 <br><b>version '.$G_brisk_version.'</b><br><br>
87 Copyright 2006-2007 <a href=\\"mailto:brisk@alternativeoutput.it\\">Matteo Nastasi</a> (aka mop)<br><br>';
88
89
90 function xcape($s)
91 {
92   $from = array (   '\\',     '@',        '|' );
93   $to   = array ( '\\\\', '&#64;', '&brvbar;' );
94
95   return (str_replace($from, $to, htmlentities($s,ENT_COMPAT,"UTF-8")));
96 }
97
98
99 class Card {
100   var $value; /* 0 - 39 card value */
101   var $stat;  /* 'bunch', 'hand', 'table', 'take' */
102   var $owner; /* (table position 0-4) */
103   // var $pos;   /* Pos in hand. */
104   var $x;     /* When played the X position on the table of the owner. */
105   var $y;     /* When played the Y position on the table of the owner. */
106
107   function Card($value, $stat, $owner)
108   {
109     $this->value = $value;
110     $this->stat  = $stat; // Card stat
111     $this->owner = $owner;
112   }
113
114   function assign($stat,$owner)
115   {
116     $this->stat  = $stat; // Card stat
117     $this->owner = $owner;
118   }
119
120   function setpos($pos)
121   {
122     $this->pos   = $pos;
123   }
124
125   function play($x,$y)
126   {
127     $this->stat = 'table'; // Card stat
128     $this->x = $x;
129     $this->y = $y;
130   }
131
132   function take($newown)
133   {
134     $this->stat = 'take'; // Card stat
135     $this->owner = $newown;
136   }
137 }
138
139 class Table {
140   var $player;
141   var $player_n;
142   var $card;
143   var $mazzo;
144   var $gstart;
145   var $turn;
146
147   var $asta_pla;
148   var $asta_pla_n;
149   var $asta_card;
150   var $asta_pnt;
151   
152   var $mult;
153   var $points;    // points array
154   var $points_n;  // number of row of points
155   var $total;
156
157   var $asta_win;
158   var $briscola;
159   var $friend;
160   
161   var $old_reason;
162   var $old_asta_pnt;
163   var $old_pnt;
164   var $old_win;
165   var $old_friend;
166
167   function Table() 
168   {
169   }
170   
171   function &create() 
172   {
173     GLOBAL $G_false;
174
175     if (($thiz = new Table()) == FALSE)
176       return ($G_false);
177
178     $thiz->player    =   array();
179     $thiz->player_n  =   0;
180     $thiz->card      =  &$thiz->bunch_create();
181     $thiz->asta_pla  =   array(); // TRUE: in auction, FALSE: out of the auction
182     $thiz->asta_pla_n=  -1;
183     $thiz->asta_card =  -1;
184     $thiz->asta_pnt  =  -1;
185     $thiz->mult      =   1;
186     $thiz->points    =   array( );
187     $thiz->points_n  =   0;
188     $thiz->total     =   array( 0, 0, 0, 0, 0);
189     $thiz->asta_win  =  -1;
190     $thiz->briscola  =  -1;
191     $thiz->friend    =  -1;
192     $thiz->turn      =   0;
193     $thiz->old_reason = "";
194     $thiz->old_asta_pnt = -1;
195     $thiz->old_pnt      = -1;
196     $thiz->old_win   =  -1;
197     $thiz->old_friend=  -1;
198
199     return ($thiz);
200   }
201
202   function &bunch_create()
203   {
204     $ret = array();
205
206     for ($i = 0 ; $i < 40 ; $i++) {
207       $ret[$i] =& new Card($i, 'bunch', 'no_owner');
208     }
209
210     $oret = &$ret;
211     return ($oret);
212   }
213
214   function bunch_make()
215   {
216     $ct = array(0,0,0,0,0);
217     
218     mt_srand(make_seed());
219     
220     for ($i = 39 ; $i >= 0 ; $i--) 
221       $rest[$i] = $i;
222
223     for ($i = 39 ; $i >= 0 ; $i--) {
224       $rn = rand(0, $i);
225       
226       if ($rn == 0)
227         log_main("RND ZERO", "");
228       
229       $id = $rest[$rn];
230
231       $owner = $i % 5;
232       $this->card[$id]->assign('hand', $owner);
233
234       $rest[$rn] = $rest[$i];
235       // $pubbpos[$rn2] = $pubbpos[$i];
236     }
237   }
238
239   function init(&$userarr)
240   {
241     $this->mazzo    = rand(0,PLAYERS_N-1);
242     $this->points_n = 0;
243     $this->mult     = 1;
244     $this->old_win  =-1;
245     $this->old_reason = "";
246     for ($i = 0 ; $i < PLAYERS_N ; $i++) {
247       $this->total[$i] = 0;
248       $user_cur = &$userarr[$this->player[$i]];
249       $user_cur->exitislock = TRUE;
250     }
251
252     log_main("table::init","ci siamo");
253   }
254
255   function game_init(&$userarr)
256   {
257     log_rd2("XXX", "GSTART 4");
258
259     $this->gstart = ($this->mazzo+1) % PLAYERS_N;
260     $this->bunch_make();
261     
262     
263     $this->asta_pla_n = PLAYERS_N;
264     $this->asta_card = -1;
265     $this->asta_pnt  = 60;
266     $this->asta_win  = -1;
267     $this->briscola  = -1;
268     $this->friend    = -1;
269     $this->turn      =  0;
270     
271     for ($i = 0 ; $i < PLAYERS_N ; $i++) {
272       $this->asta_pla[$i] = TRUE;
273       $user_cur = &$userarr[$this->player[$i]];
274       $user_cur->subst = 'asta';
275       $user_cur->asta_card = -2;
276       $user_cur->asta_pnt  = -1;
277       $user_cur->handpt = $this->hand_points($i);
278       // SEE function calculate_points(&$table)
279     }
280   }
281
282   function game_next()
283   {
284     $this->mazzo  = ($this->mazzo + 1) % PLAYERS_N;
285   }
286
287   function getPlayer($idx)
288   {
289     return ($this->player[$idx]);
290   }
291
292   function setPlayer($idx, $player)
293   {
294     $this->player[$idx] = $player;
295   }
296
297   function user_add($idx)
298   {
299     $this->player[$this->player_n] = $idx;
300     $this->player_n++;
301     
302     return ($this->player_n - 1);
303   }
304   
305   function user_rem(&$room, &$user)
306   {
307     $tabpos = $user->table_pos;
308     
309     /* verifico la consistenza dei dati */
310     if ($room->user[$this->player[$tabpos]] == $user) {
311       
312       /* aggiorna l'array dei giocatori al tavolo. */
313       for ($i = $tabpos ; $i < $this->player_n-1 ; $i++) {
314         $this->player[$i] = $this->player[$i+1];
315         $user_cur = &$room->user[$this->player[$i]];
316         $user_cur->table_pos = $i;
317       }
318       $this->player_n--;
319     }
320     else {
321       log_main($user->sess, "INCONSISTENCY ON TABLE.");
322     }
323   }
324
325   function hand_points($idx)
326   {
327     GLOBAL $G_all_points; 
328     
329     $tot = 0;
330     
331     for ($i = 0 ; $i < 40 ; $i++) {
332       if ($this->card[$i]->owner != $idx)
333         continue;
334
335       $ctt = $this->card[$i]->value % 10;
336       $tot += $G_all_points[$ctt];
337     }
338
339     return ($tot);
340   }
341
342   function exitlock_show(&$userarr, $table_pos)
343   {
344     $ct = $this->exitlock_calc(&$userarr, $table_pos);
345
346     $ret = sprintf('exitlock_show(%d, %s);', $ct, 
347                    ($userarr[$this->player[$table_pos]]->exitislock ? 'true' : 'false'));
348     return ($ret);
349   }
350
351   function exitlock_calc(&$userarr, $table_pos)
352   {
353     $ct = 0;
354
355     for ($i = 0 , $ct = 0 ; $i < PLAYERS_N ; $i++) {    
356       if ($userarr[$this->player[$i]]->exitislock == FALSE)
357         $ct++;
358     }
359
360     return ($ct);
361   }
362 } // End class Table
363   
364 class User {
365   var $name;       // name of the user
366   var $sess;       // session of the user
367   var $ip;         // ip of the user
368   var $lacc;       // last access (for the cleanup)
369   var $laccwr;     // last access (for the cleanup)
370   var $bantime;    // timeout to temporary ban
371   var $stat;       // status (outdoor, room, table, game, ...)
372   var $subst;      // substatus for each status   
373   var $step;       // step of the current status
374   var $trans_step; // step to enable transition between pages (disable == -1)
375   var $comm;       // commands array
376   var $asta_card;  // 
377   var $asta_pnt;   //
378   var $handpt;     // Total card points at the beginning of the current hand.
379   var $exitislock; // Player can exit from the table ?
380   var $table;      // id of the current table (if in table state)
381   var $table_pos;  // idx on the table
382   var $the_end;    // Flag to change the end of the session
383
384   function User() {
385   }
386
387   function &create($name, $sess, $stat = "", $subst = "", $table = -1, $ip="0.0.0.0") {
388     GLOBAL $G_false;
389
390     if (($thiz = new User()) == FALSE)
391       return ($G_false);
392
393     $thiz->name  = $name;
394     $thiz->sess  = $sess;
395     $thiz->ip    = $ip;
396     $thiz->lacc   = time();
397     $thiz->laccwr = time();
398     $thiz->bantime = 0;
399     $thiz->stat  = $stat;
400     $thiz->subst  = $subst;
401     $thiz->step  = 1;
402     $thiz->trans_step  = -1;
403     $thiz->comm  = array();
404     $thiz->asta_card = -2;
405     $thiz->asta_pnt  = -1;
406     $thiz->handpt = -1;
407     $thiz->exitislock = TRUE;
408     
409     $thiz->table = $table;
410     
411     return ($thiz);
412   }
413
414   function stat_set($stat) {
415     $this->stat = "$stat";
416     
417     /*
418     if (validate_sess($this->sess)) {
419       $fp = fopen(PROXY_PATH."/".$this->sess.".stat", 'w');
420       fwrite($fp, sprintf("%s\n",$this->stat));
421       fclose($fp);
422     }
423     */
424   }
425
426   function step_set($step) {
427     $this->step = $step;
428     
429     do {
430       if (validate_sess($this->sess) == FALSE)
431         break;
432       if (($fp = @fopen(PROXY_PATH."/".$this->sess.".step", 'w')) == FALSE)
433         break;
434       fwrite($fp, pack("l",$this->step), 4);
435       fclose($fp);
436
437       return (TRUE);
438     } while (0);
439
440     return (FALSE);
441   }
442
443   function step_inc() {
444     $this->step++;
445     
446     if (validate_sess($this->sess)) {
447       $fp = fopen(PROXY_PATH."/".$this->sess.".step", 'w');
448       fwrite($fp, pack("l",$this->step), 4);
449       fclose($fp);
450
451       return (TRUE);
452     }
453     
454     return (FALSE);
455   }
456 }
457
458 function step_get($sess) {
459   $fp = FALSE;
460   $ct = 0;
461   do {
462     if (validate_sess($sess) == FALSE)
463       break;
464   $ct = 1;
465     if (($fp = @fopen(PROXY_PATH."/".$sess.".step", 'rb')) == FALSE)
466       break;
467   $ct = 2;
468     if (($s = fread($fp, 4)) == FALSE)
469       break;
470   $ct = 3;
471     if (strlen($s) != 4)
472       break;
473   $ct = 4;
474     $arr = unpack('l', $s);
475     fclose($fp);
476
477     // log_rd2($sess, "A0: ".$arr[0]."  A1: ".$arr[1]);
478     return ($arr[1]);
479   } while (0);
480
481   if ($fp != FALSE)
482     fclose($fp);
483
484   log_rd2($sess, "STEP_GET: return false ".$ct);
485   return (FALSE);
486 }
487
488 function step_unproxy($sess) {
489   log_rd2($sess, "UNPROXY: ".PROXY_PATH."/".$sess.".step");
490   @unlink(PROXY_PATH."/".$sess.".step");
491 }
492
493
494 class Room {
495   var $user;
496   var $table;
497   var $comm; // commands for many people
498   var $step; // current step of the comm array
499   var $garbage_timeout;
500
501   function Room () {
502     $this->user = array();
503
504     for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
505       $this->user[$i] =& User::create("", "");
506     }
507
508     for ($i = 0 ; $i < TABLES_N ; $i++) 
509       $this->table[$i] =& Table::create();
510     $this->garbage_timeout = 0;
511   }
512
513   function garbage_manager($force)
514   {
515     
516     /* Garbage collector degli utenti in timeout */
517     $curtime = time();
518     if ($force || $this->garbage_timeout < $curtime) {
519       
520       for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
521         $user_cur = &$this->user[$i];
522         if ($user_cur->sess == "")
523           continue;
524         
525         if ($user_cur->lacc + EXPIRE_TIME_RD < $curtime) { // Auto logout dell'utente
526           log_rd2($user_cur->sess, "AUTO LOGOUT.");
527
528           if ($user_cur->stat == 'table' || $user_cur->stat == 'room') {
529             log_auth($user_cur->sess, "Autologout session.");
530             
531             $tmp_sess = $user_cur->sess;
532             $user_cur->sess = "";
533             step_unproxy($tmp_sess);
534             $user_cur->name = "";
535             $user_cur->the_end = FALSE;
536             
537             log_rd2($user_cur->sess, "AUTO LOGOUT.");
538             if ($user_cur->subst == 'sitdown' || $user_cur->stat == 'table')
539               $this->room_wakeup(&$user_cur);
540             else if ($user_cur->subst == 'standup')
541               $this->room_outstandup(&$user_cur);
542             else
543               log_rd2($sess, "LOGOUT FROM WHAT ???");
544           }
545         }
546
547         if ($user_cur->laccwr + EXPIRE_TIME_SMAMMA < $curtime) { // lo rimettiamo in piedi
548           if ($user_cur->stat == 'room' && $user_cur->subst == 'sitdown') {
549             $this->room_wakeup(&$user_cur);
550             $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
551             $user_cur->comm[$user_cur->step % COMM_N] .=  show_notify("<br>Sei stato inattivo per ".(EXPIRE_TIME_SMAMMA/60.0)." minuti. <br><br>Quindi ritorni tra i <b>Giocatori in piedi</b>.", 0, "torna ai tavoli", 400, 100);
552             $user_cur->step_inc();
553           }
554         }
555       }
556       log_rd2($user_cur->sess, "GARBAGE UPDATED!");
557       
558       $this->garbage_timeout = time() + GARBAGE_TIMEOUT;
559     }
560
561     // BAN_IP_CLEAN
562
563   }
564
565
566   function room_wakeup(&$user)
567   {
568     $table_idx = $user->table;
569     $table = &$this->table[$table_idx];
570
571     log_main("WAKEUP", "begin function table:".$table_idx."  stat: ".$user->stat."  subst: ".$user->subst);
572
573     $curtime = time();
574
575     $from_table = ($user->stat == "table");
576     if ($from_table) {
577       log_main("WAKEUP", "from table [".$user->table."] nplayers_n: ".$this->table[$user->table]->player_n);
578
579       for ($i = 0 ; $i < $table->player_n ; $i++) {
580         $user_cur = &$this->user[$table->player[$i]];
581         log_main("PREIMPOST", "INLOOP name: ".$user_cur->name);
582
583         if ($user_cur != $user) {
584           $user_cur->stat_set("room");
585           $user_cur->subst = "sitdown";
586           $user_cur->laccwr = $curtime;
587         }
588         else if ($user->sess != "") {
589           $user_cur->stat_set("room");
590           $user_cur->subst = "standup";
591           $user_cur->laccwr = $curtime;
592           $user_cur->table = -1;
593         }
594       }
595     }
596     else {
597       $user->stat_set("room");
598       $user->subst = "standup";
599       $user->laccwr = $curtime;
600     }
601     /* aggiorna l'array dei giocatori al tavolo. */
602     $table->user_rem(&$this, &$user);
603
604     for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
605       $user_cur = &$this->user[$i];
606       if ($user_cur->sess == '' || $user_cur->stat != 'room')
607         continue;
608       
609       log_main("VALORI", "name: ".$user_cur->name."from_table: ".$from_table."  tab: ".$user_cur->table." taix: ".$table_idx."  ucur: ".$user_cur."  us: ".$user);
610
611       $ret = "gst.st = ".($user_cur->step+1)."; ";
612       if ($from_table && ($user_cur->table == $table_idx || $user_cur == $user)) {
613         $ret .= 'gst.st_loc++; the_end=true; window.onunload = null; document.location.assign("index.php");|';
614         // $ret .= 'gst.st_loc++; document.location.assign("index.php");|';
615         log_main("DOCUMENT.index.php", "from table");
616       }
617       else if ($user_cur->stat == "room") {
618         log_main("DOCUMENT.index.php", "from table");
619
620         $ret .= table_content($this, $user_cur, $table_idx);
621         $ret .= standup_content($this, $user_cur);
622         
623         $act_content = table_act_content(FALSE, 0, $table_idx, $user->table);
624         $ret .= sprintf('$("table_act%d").innerHTML = "%s";', $table_idx, $act_content);
625         
626         
627         if ($user_cur == $user) {
628           // set the new status 
629           $ret .=  'subst = "standup"; ';
630           // clean the action buttons in other tables
631           for ($e = 0 ; $e < TABLES_N ; $e++) {
632             if ($this->table[$e]->player_n < PLAYERS_N)
633               $ret .= sprintf('$("table_act%d").innerHTML = "%s";', $e, table_act_content(TRUE, 0, $e, $user->table));
634           }
635         }
636         else {
637           $act_content = table_act_content(($user_cur->subst == 'standup'), $table->player_n, $table_idx, $user_cur->table);
638           $ret .= sprintf('$("table_act%d").innerHTML = "%s";', $table_idx, $act_content);
639         }
640       }
641       log_wr($user_cur->sess, "ROOM_WAKEUP: ".$ret);
642       $user_cur->comm[$user_cur->step % COMM_N] = $ret;
643       $user_cur->step_inc();
644     }
645   }
646   
647
648
649
650   function room_outstandup(&$user)
651   {
652     $this->room_sitdown(&$user, -1);
653   }
654   
655   function table_update(&$user)
656   {
657     log_main("table_update", "pre - USER: ".$user->name);
658
659     $table_idx = $user->table;
660
661     if ($table_idx > -1) 
662       $table = &$this->table[$table_idx];
663     
664     for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
665       $ret = "";
666       $user_cur = &$this->user[$i];
667       if ($user_cur->sess == '' || $user_cur->stat != 'room')
668       continue;
669       
670       $ret = "gst.st = ".($user_cur->step+1)."; ";
671       if ($table_idx > -1)
672         $ret .= table_content($this, $user_cur, $table_idx);
673       
674       if ($user_cur == $user) {
675         $ret .= sprintf('$("myname").innerHTML = "<b>%s</b>: ";',  xcape($user->name));
676       }
677       $user_cur->comm[$user_cur->step % COMM_N] = $ret;
678       $user_cur->step_inc();
679     }
680
681     log_main("table_update", "post");
682   }
683
684   function room_sitdown(&$user, $table_idx)
685   {
686     log_main("room_sitdown", ($user == FALSE ? "USER: FALSE" : "USER: ".$user->name));
687
688     if ($table_idx > -1) 
689       $table = &$this->table[$table_idx];
690     
691     for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
692       $ret = "";
693       $user_cur = &$this->user[$i];
694       if ($user_cur->sess == '' || $user_cur->stat != 'room')
695       continue;
696       
697       $ret = "gst.st = ".($user_cur->step+1)."; ";
698       if ($table_idx > -1)
699       $ret .= table_content($this, $user_cur, $table_idx);
700       $ret .= standup_content($this, $user_cur);
701       
702       if ($user_cur == $user) {
703         $ret .=  'subst = "sitdown"; ';
704         // clean the action buttons in other tables
705         for ($e = 0 ; $e < TABLES_N ; $e++) {
706           $act_content = table_act_content(FALSE, 0, $e, $user_cur->table);
707           $ret .= sprintf('$("table_act%d").innerHTML = "%s";', $e, $act_content);
708         }
709       }
710       else if ($table_idx > -1) {
711         if ($table->player_n == PLAYERS_N) {
712           $act_content = table_act_content(($user_cur->subst == 'standup'), PLAYERS_N, $table_idx, $user_cur->table);
713           $ret .= sprintf('$("table_act%d").innerHTML = "%s";', $table_idx, $act_content);
714         }
715       }
716       $user_cur->comm[$user_cur->step % COMM_N] = $ret;
717       $user_cur->step_inc();
718     }
719   }
720
721   function chatt_send(&$user, $mesg)
722   {
723     if ($user->stat == 'table') {
724       $table = &$this->table[$user->table];
725     }
726     
727     $user_mesg = substr($mesg,6);
728     
729     $timecur = time();
730     
731     $dt = date("H:i ", $timecur);
732     if (strncmp($user_mesg, "/nick ", 6) == 0) {
733       log_main($user->sess, "chatt_send BEGIN");
734
735       if (($name_new = validate_name(substr($user_mesg, 6))) == FALSE) {
736           $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
737           $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Il nickname deve contenere almeno una lettera o una cifra.");', $dt.NICKSERV, xcape($name_new));
738           $user->step_inc();
739
740           return;
741       }
742       $user_mesg = "COMMAND ".$user_mesg;
743       // Search dup name
744       // change
745       // update local graph
746       // update remote graphs
747       for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
748         $user_cur = &$this->user[$i];
749         //      if ($user_cur->sess == '' || $user_cur->stat != 'room')
750         if ($user_cur->sess == '')
751           continue;
752         if ($user_cur->name == $name_new) {
753           $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
754           $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Nickname <b>%s</b> gi&agrave; in uso.");', $dt.NICKSERV, xcape($name_new));
755           $user->step_inc();
756           break;
757         }
758       }
759       if ($i == MAX_PLAYERS) {
760         $user->name = $name_new;
761
762       log_main($user->sess, "chatt_send start set");
763         
764
765         for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
766           log_main($user->sess, "chatt_send set loop");
767           
768           $user_cur = &$this->user[$i];
769           if ($user_cur->sess == '')
770             continue;
771           if ($user_cur->stat == 'room') {
772             if ($user->stat == 'room' && $user->subst == 'standup') {
773               $this->standup_update(&$user);
774             }
775             else if ($user->stat == 'room' && $user->subst == 'sitdown' ||
776                      $user->stat == 'table') {
777               log_main($user->sess, "chatt_send pre table update");
778
779               $this->table_update(&$user);
780
781               log_main($user->sess, "chatt_send post table update");
782             }
783           }
784           else if ($user_cur->stat == 'table' && $user_cur->table == $user->table) {
785             $table = &$this->table[$user->table];
786             
787             $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
788             $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('set_names(" %s", " %s", " %s", " %s", " %s"); ',
789                 xcape($this->user[$table->player[($user_cur->table_pos)%PLAYERS_N]]->name),
790                 xcape($this->user[$table->player[($user_cur->table_pos+1)%PLAYERS_N]]->name),
791                 xcape($this->user[$table->player[($user_cur->table_pos+2)%PLAYERS_N]]->name),
792                 (PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+3)%PLAYERS_N]]->name)),
793                 (PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+4)%PLAYERS_N]]->name)));
794             if ($user_cur == $user)
795               $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('$("myname").innerHTML = "<b>%s</b>";', 
796                                                                    xcape($user->name,ENT_COMPAT,"UTF-8"));
797             $user_cur->step_inc();
798           }
799         }
800       }
801     }
802     else {
803       for ($i = 0 ; $i < ($user->stat == 'room' ? MAX_PLAYERS : PLAYERS_N) ; $i++) {
804         if ($user->stat == 'room') {
805           $user_cur = &$this->user[$i];
806           if ($user_cur->sess == '' || $user_cur->stat != 'room')
807             continue;
808         }
809         else {
810           $user_cur = &$this->user[$table->player[$i]];
811         }
812         
813         $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
814         $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('chatt_sub("%s","%s");',
815                                                              $dt.xcape($user->name), xcape($user_mesg));
816         $user_cur->step_inc();
817       }
818       log_legal($timecur, $user->sess, $user->name, 
819                 ($user->stat == 'room' ? 'room' : 'table '.$user->table),$user_mesg);
820     }
821   }
822
823   function &get_user($sess, &$idx)
824   {
825     GLOBAL $PHP_SELF, $G_false;
826
827     if (validate_sess($sess)) {
828       for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
829         if (strcmp($sess, $this->user[$i]->sess) == 0) {
830           // find it
831           $idx = $i;
832           $ret = &$this->user[$i];
833           return ($ret);
834         }
835       }
836       log_main($sess, sprintf("get_user: Wrong sess from page [%s]",$PHP_SELF));
837       // for ($i = 0 ; $i < MAX_PLAYERS ; $i++) 
838       // log_main($sess, sprintf("get_user: Wrong sess compared with [%s]",$this->user[$i]->sess));
839     }
840     else {
841       log_main($sess, sprintf("get_user: Wrong strlen [%s]",$sess));
842     }
843
844     return ($G_false);
845   }
846
847   /*
848    * function &add_user(&$room, &$sess, &$idx, $name, $ip)
849    *
850    * RETURN VALUE:
851    *   if ($idx != -1 && ret == FALSE)  =>  duplicated nick
852    *   if ($idx == -2 && ret == FALSE)  =>  invalid name
853    *   if ($idx == -1 && ret == FALSE)  =>  no space left
854    *   if (ret == TRUE)                 =>  SUCCESS
855    */
856   function &add_user(&$sess, &$idx, $name, $ip)
857   {
858     GLOBAL $G_false;
859
860     $idx = -1;
861     $idfree = -1;
862     
863     if (($name_new = validate_name($name)) == FALSE) {
864       $idx = -2;
865       return ($G_false);
866     }
867
868     log_auth("XXX", sprintf("ARRIVA: [%s]", $sess));
869     if (validate_sess($sess) == FALSE) 
870       $sess = "";
871
872     for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
873       /* free user ? */
874       if (strcmp($sess, $this->user[$i]->sess) == 0) {
875         if ($idx == -1)
876           $idx = $i;
877       }
878       if ($idfree == -1 && strcmp("", $this->user[$i]->sess) == 0) {
879         $idfree = $i;
880       }
881       if (strcmp($this->user[$i]->name, $name_new) == 0) {
882         $idx = $i;
883         break;
884       }
885     }
886     if ($idx == -1)
887       $idx = $idfree;
888
889     log_auth("XXX", sprintf("TROVATO A QUESTO PUNTO [%d] sess [%s] name [%s]", $idx, $sess, $name_new));
890
891     if ($idx != -1 && $i == MAX_PLAYERS) {
892       /* SUCCESS */
893       $curtime = time();
894       if ($sess == "") {
895         $this->user[$idx]->sess = uniqid("");
896         $sess = $this->user[$idx]->sess;
897         
898       }
899       else {
900         $this->user[$idx]->sess = $sess;
901       }
902       $this->user[$idx]->name = $name_new;
903       $this->user[$idx]->stat_set("room");
904       // MOP $this->user[$idx]->step_set(0);
905       $this->user[$idx]->subst = "standup";
906       $this->user[$idx]->lacc =   $curtime;
907       $this->user[$idx]->laccwr = $curtime;
908       $this->user[$idx]->bantime = 0;
909       $this->user[$idx]->ip = $ip;
910       log_main("XXX", sprintf("TROVATO LIBERO A [%d] sess [%s] name [%s]", $idx, $sess, $name_new));
911       
912       return ($this->user[$idx]);
913     }
914
915     return ($G_false);
916   }
917   
918   function standup_update(&$user)
919   {
920     for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
921       $user_cur = &$this->user[$i];
922       if ($user_cur->sess == '')
923         continue;
924
925       log_main("STANDUP START", $user_cur->stat);
926       
927       if ($user_cur->stat == 'room') {
928         $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ".standup_content($this, $user_cur);
929         if ($user_cur == $user)
930           $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('$("myname").innerHTML = "<b>%s</b>: ";',  xcape($user->name));
931         
932         log_main("FROM STANDUP", "NAME: ".$user_cur->name." SENDED: ".$user_cur->comm[$user_cur->step % COMM_N]);
933         
934         $user_cur->step_inc();
935       }
936     }
937   }
938
939   // Static functions
940   function &init_data()
941   {
942     $room =& new Room();
943     
944     return $room;
945   }
946   
947
948   function &load_data() 
949   {
950     GLOBAL $G_false, $sess;
951     
952     if (($tok = ftok(FTOK_PATH."/main", "B")) == -1) {
953       echo "FTOK FAILED";
954       exit;
955     }
956     
957     if ($shm = shm_attach($tok, SHM_DIMS)) {
958       $room = @shm_get_var($shm, $tok);
959       
960       log_only($sess, "bri ==  ".($room == FALSE ?   "FALSE" : "TRUE")."  bri ===  ".($room === FALSE ? "FALSE" : "TRUE")."  bri isset ".(isset($room) ?   "TRUE" : "FALSE"));
961       if (isset($room)) 
962         log_only($sess, "bri count ".count($room));
963       
964       if ($room == FALSE) {
965         log_only($sess, "INIT MAIN DATA");
966         
967         $room =& Room::init_data();
968         if (shm_put_var($shm, $tok, $room) == FALSE) {
969           log_only($sess, "PUT_VAR FALLITA ".strlen(serialize($room)));
970           log_only($sess, serialize($room));
971         }
972       }
973       
974       shm_detach($shm);
975       
976       $ret = &$room;
977       return ($ret);
978     }
979     
980     return ($G_false);
981   }
982   
983
984   function save_data(&$room) 
985   {
986     GLOBAL $sess;
987     
988     $ret =   FALSE;
989     $shm =   FALSE;
990     $isacq = FALSE;
991     
992     // var_dump($room);
993     
994     if (($tok = ftok(FTOK_PATH."/main", "B")) == -1) 
995       return (FALSE);
996     
997     do {
998       $isacq = TRUE;
999       
1000       if (($shm = shm_attach($tok, SHM_DIMS)) == FALSE)
1001         break;
1002       
1003       // log_only($sess, "PUT_VAR DI ".strlen(serialize($room)));
1004       if (shm_put_var($shm, $tok, $room) == FALSE) {
1005         log_only($sess, "PUT_VAR FALLITA ".strlen(serialize($room)));
1006         log_only($sess, serialize($room));
1007         break;
1008       }
1009       // log_main("XXX", "QUI CI ARRIVA [".$room->user[0]->name."]");
1010       $ret = TRUE;
1011     } while (0);
1012     
1013     if ($shm)
1014       shm_detach($shm);
1015     
1016     return ($ret);
1017   }
1018
1019   function lock_data()
1020   {
1021     GLOBAL $sess; 
1022     
1023     //  echo "LOCK: ".FTOK_PATH."/main";
1024     //  exit;
1025     if (($tok = ftok(FTOK_PATH."/main", "B")) == -1) {
1026       echo "FTOK FAILED";
1027       exit;
1028     }
1029     // echo "FTOK ".$tok."<br>";
1030     if (($res = sem_get($tok)) == FALSE) {
1031       echo "SEM_GET FAILED";
1032       exit;
1033     }
1034     if (sem_acquire($res)) {   
1035       log_only($sess, "LOCK");
1036       return ($res);
1037     }
1038     else
1039       return (FALSE);
1040   }
1041   
1042   function unlock_data($res)
1043   {
1044     GLOBAL $sess; 
1045     
1046     log_only($sess, "UNLOCK");
1047
1048     return (sem_release($res));
1049   }
1050 } // end class Room
1051
1052 function make_seed()
1053 {
1054   list($usec, $sec) = explode(' ', microtime());
1055   return (float) $sec + ((float) $usec * 100000);
1056 }
1057
1058 function log_only2($sess, $log) {
1059   if (BRISK_DEBUG != TRUE)
1060     return;
1061   
1062
1063   if (($fp = @fopen("/tmp/brisk_only2.log", 'a')) != FALSE) {
1064     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1065     fclose($fp);
1066   }
1067 }
1068
1069 function log_only($sess, $log) {
1070   if (BRISK_DEBUG != TRUE)
1071     return;
1072   
1073
1074   if (($fp = @fopen("/tmp/brisk_only.log", 'a')) != FALSE) {
1075     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1076     fclose($fp);
1077   }
1078 }
1079
1080 function log_main($sess, $log) {
1081   if (BRISK_DEBUG != TRUE)
1082     return;
1083
1084   if (($fp = @fopen("/tmp/brisk_main.log", 'a')) != FALSE) {
1085     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1086     fclose($fp);
1087   }
1088 }
1089
1090 function log_rd($sess, $log) {
1091   if (BRISK_DEBUG != TRUE)
1092     return;
1093
1094   if (($fp = @fopen("/tmp/brisk_rd.log", 'a')) != FALSE) {
1095     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1096     fclose($fp);
1097   }
1098 }
1099
1100 function log_rd2($sess, $log) {
1101   if (BRISK_DEBUG != TRUE)
1102     return;
1103
1104   if (($fp = @fopen("/tmp/brisk_rd2.log", 'a')) != FALSE) {
1105     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1106     fclose($fp);
1107   }
1108 }
1109
1110 function log_send($sess, $log) {
1111   if (BRISK_DEBUG != TRUE)
1112     return;
1113
1114   if (($fp = @fopen("/tmp/brisk_send.log", 'a')) != FALSE) {
1115     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1116     fclose($fp);
1117   }
1118 }
1119
1120 function log_auth($sess, $log) {
1121   if (BRISK_DEBUG != TRUE)
1122     return;
1123
1124   if (($fp = @fopen("/tmp/brisk_auth.log", 'a')) != FALSE) {
1125     fwrite($fp, sprintf("SESS: [%d] [%s] [%s]\n", time(), $sess, $log));
1126     fclose($fp);
1127   }
1128 }
1129
1130 function log_lock($sess, $log) {
1131   if (BRISK_DEBUG != TRUE)
1132     return;
1133
1134   if (($fp = @fopen("/tmp/brisk_lock.log", 'a')) != FALSE) {
1135     fwrite($fp, sprintf("SESS: [%d] [%s] [%s]\n", time(), $sess, $log));
1136     fclose($fp);
1137   }
1138 }
1139
1140 function log_wr($sess, $log) {
1141   if (BRISK_DEBUG != TRUE)
1142     return;
1143
1144   if (($fp = @fopen("/tmp/brisk_wr.log", 'a')) != FALSE) {
1145     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1146     fclose($fp);
1147   }
1148 }
1149
1150 function log_load($sess, $log) {
1151   if (BRISK_DEBUG != TRUE)
1152     return;
1153
1154   if (($fp = @fopen("/tmp/brisk_load.log", 'a')) != FALSE) {
1155     fwrite($fp, sprintf("SESS: [%s] [%s]\n", $sess, $log));
1156     fclose($fp);
1157   }
1158 }
1159
1160 function log_legal($timecur, $sess, $name, $where, $mesg) 
1161 {
1162   GLOBAL $_SERVER;
1163
1164   if (($fp = @fopen(LEGAL_PATH, 'a')) != FALSE) {
1165     /* Unix time | session | nickname | IP | where was | mesg */
1166     fwrite($fp, sprintf("%ld|%s|%s|%s|%s|%s|\n", $timecur, $sess, $name, $_SERVER['REMOTE_ADDR'], $where , $mesg));
1167     fclose($fp);
1168   }
1169 }
1170
1171
1172
1173
1174 function lock_banlist()
1175 {
1176   if (($tok = ftok(FTOK_PATH."/main", "L")) == -1) {
1177     echo "FTOK FAILED";
1178     exit;
1179   }
1180   if (($res = sem_get($tok)) == FALSE) {
1181     echo "SEM_GET FAILED";
1182     exit;
1183   }
1184   if (sem_acquire($res)) 
1185     return ($res);
1186   else
1187     return (FALSE);
1188 }
1189
1190 function unlock_banlist($res)
1191 {
1192   return (sem_release($res));
1193 }
1194
1195 function table_act_content($isstanding, $sitted, $table, $cur_table)
1196 {
1197   $ret = "";
1198
1199   if ($isstanding) {
1200     if ($sitted < PLAYERS_N) {
1201       $ret = sprintf('<input type=\\"button\\" class=\\"button\\" name=\\"xhenter%d\\"  value=\\"Mi siedo.\\" onclick=\\"act_sitdown(%d);\\">', $table, $table);
1202     }
1203   }
1204   else {
1205     if ($table == $cur_table)
1206       $ret = sprintf('<input type=\\"button\\" class=\\"button\\" name=\\"xwakeup\\"  value=\\"Mi alzo.\\" onclick=\\"act_wakeup();\\">');
1207     else
1208       $ret = "";
1209   }
1210   return ($ret);
1211 }
1212
1213 function table_content($room, $user, $table_idx)
1214 {
1215   $content = "";
1216   $ret = "";
1217   // TODO
1218   //
1219   //   Si possono usare i dati nella classe table
1220   //
1221
1222   $sess = $user->sess;
1223   $table = &$room->table[$table_idx];
1224
1225   if ($user->stat != 'room')
1226     return;
1227
1228   for ($i = 0 ; $i < $table->player_n ; $i++) {
1229     $user_cur = &$room->user[$table->player[$i]];
1230
1231     if ($user_cur == $user) 
1232         { $hilion = "<b>"; $hilioff = "</b>"; }
1233       else
1234         { $hilion = ""; $hilioff = ""; }
1235
1236     log_main($user_cur->name, sprintf("IN TABLE [%d]", $table_idx));
1237     
1238     $content .= sprintf("%s%s%s<br>",$hilion, xcape($user_cur->name), $hilioff);
1239   }
1240   /*
1241   for ( ; $i < PLAYERS_N ; $i++)
1242     $content .= "<br>";
1243   */
1244
1245   $ret .= sprintf('$("table%d").innerHTML = "%s";', $table_idx, $content);
1246   
1247   return ($ret);
1248 }
1249
1250 function standup_content(&$room, $user)
1251 {
1252   $ret = "";
1253   $content = "";
1254
1255   if ($user->stat != 'room')
1256     return;
1257
1258   for ($e = 0 , $ct = 0 ; $ct < 4 && $e < MAX_PLAYERS ; $e++) {
1259     if ($room->user[$e]->sess == "" || $room->user[$e]->stat != "room" || $room->user[$e]->name == "")
1260       continue;
1261     $ct++;
1262   }
1263
1264   $content .= sprintf('<table cols=\\"%d\\" class=\\"table_standup\\">', $ct);
1265
1266   for ($e = 0 , $ct = 0 ; $e < MAX_PLAYERS ; $e++) {
1267     if ($room->user[$e]->sess == "" || $room->user[$e]->stat != "room" || $room->user[$e]->name == "")
1268       continue;
1269
1270
1271     if ($room->user[$e]->subst == "standup") {
1272       if (($ct % 4) == 0) {
1273         $content .= '<tr>';
1274       }
1275       if ($room->user[$e] == $user) 
1276         { $hilion = "<b>"; $hilioff = "</b>"; }
1277       else
1278         { $hilion = ""; $hilioff = ""; }
1279
1280       $content .= sprintf('<td class=\\"room_standup\\">%s%s%s</td>',$hilion, xcape($room->user[$e]->name), $hilioff);
1281       if (($ct % 4) == 3) {
1282         $content .= '</tr>';
1283       }
1284       $ct++;
1285     }
1286   }
1287   $content .= '</table>';
1288         
1289   $content2 = '<input class=\\"button\\" name=\\"logout\\" value=\\"Esco.\\" onclick=\\"window.onunload = null; act_logout();\\" type=\\"button\\">';
1290   $ret .= sprintf('$("standup").innerHTML = "%s";  $("esco").innerHTML = "%s";', 
1291                   $content, $content2);
1292
1293   return ($ret);
1294 }
1295
1296
1297 function show_notify($text, $tout, $butt, $w, $h)
1298 {
1299   log_main("SHOW_NOTIFY", $text);
1300   return sprintf('var noti = new notify(gst,"%s",%d,"%s",%d,%d);', $text, $tout, $butt, $w, $h);
1301 }
1302
1303 function briscola_show($room, $table, $user)
1304 {
1305   $ptnadd = "";
1306   $ret = "";
1307
1308   if ($table->asta_card == 9) 
1309     $ptnadd = sprintf("<br>con %d punti", $table->asta_pnt);
1310   
1311   /* text of caller cell */
1312   if ($user->table_pos == $table->asta_win) 
1313     $ret .= sprintf('$("callerinfo").innerHTML = "Chiami%s:";', $ptnadd);
1314   else 
1315     $ret .= sprintf('$("callerinfo").innerHTML = "Chiama %s%s:";', 
1316                     xcape($room->user[$table->player[$table->asta_win]]->name), $ptnadd);
1317
1318   $ret .= sprintf('$("caller").style.backgroundImage = \'url("img/brisk_caller_sand%d.png")\';',
1319                   $table->asta_win);
1320   $ret .= sprintf('$("callerimg").src = "img/%02d.png";', $table->briscola);
1321   $ret .= sprintf('$("caller").style.visibility = "visible";');
1322   $ret .= sprintf('$("chooseed").style.visibility = "hidden";');
1323   $ret .= sprintf('$("astalascio").style.visibility = "";');
1324   $ret .= sprintf('$("asta").style.visibility = "hidden";');
1325   $ret .= sprintf('show_astat(-2,-2,-2,-2,-2);');
1326   
1327   return ($ret);
1328 }
1329
1330
1331 function game_result($asta_pnt, $pnt)
1332 {
1333   if ($asta_pnt == 61) {
1334     if ($pnt > 60)
1335       return (1);
1336     else if ($pnt == 60)
1337       return (0);
1338     else
1339       return (-1);
1340   }
1341   else {
1342     if ($pnt >= $asta_pnt)
1343       return (1);
1344     else
1345       return (-1);
1346   }
1347 }
1348
1349 function multoval($mult)
1350 {
1351   if ($mult == 2)
1352     return ("doppio");
1353   else if ($mult == 4)
1354     return ("quadruplo");
1355   else
1356     return (sprintf("%d-plo", $mult));
1357 }
1358
1359 function show_table_info(&$room, &$table, $table_pos)
1360 {
1361   $ret = "";
1362   $user = &$room->user[$table->player[$table_pos]];
1363
1364   $pnt_min = $table->points_n - MAX_POINTS < 0 ? 0 : $table->points_n - MAX_POINTS;
1365   $noty = sprintf('<table class=\"points\"><tr><th></th>');
1366   
1367   // Names.
1368   for ($i = 0 ; $i < PLAYERS_N ; $i++) 
1369     $noty .= sprintf('<th class=\"td_points\">%s</th>', xcape($room->user[$table->player[$i]]->name));
1370   $noty .= sprintf("</tr>");
1371
1372   // Points.
1373   log_main("show_table_info", "pnt_min: ".$pnt_min."   Points_n: ".$table->points_n);
1374
1375   for ($i = $pnt_min ; $i < $table->points_n ; $i++) {
1376     $noty .= sprintf('<tr><th class=\"td_points\">%d</th>', $i+1);
1377     for ($e = 0 ; $e < PLAYERS_N ; $e++) 
1378       $noty .= sprintf('<td class=\"td_points\">%d</td>', $table->points[$i % MAX_POINTS][$e]);
1379     $noty .= "</tr>";
1380   }
1381
1382   // Total points.
1383   $noty .= '<tr><th class=\"td_points\">Tot.</th>';
1384   for ($e = 0 ; $e < PLAYERS_N ; $e++) 
1385     $noty .= sprintf('<td class=\"td_points\">%d</td>', $table->total[$e]);
1386   $noty .= "</tr></table>";
1387
1388   if ($table->old_reason != "") {
1389     $noty .= sprintf("<hr><b>%s</b><br>", xcape($table->old_reason));
1390   }
1391
1392   if ($table->old_win != -1) {
1393     $win = $table->player[$table->old_win];
1394     $fri = $table->player[$table->old_friend];
1395
1396     $wol = game_result($table->old_asta_pnt, $table->old_pnt);
1397
1398     if ($win != $fri) {
1399       $noty .= sprintf("<hr>Nell'ultima mano ha chiamato <b>%s</b>, il socio era <b>%s</b>,<br>", 
1400                        xcape($room->user[$win]->name),
1401                        xcape($room->user[$fri]->name));
1402       if ($table->old_pnt == 120) {
1403         $noty .= sprintf("hanno fatto <b>cappotto</b> EBBRAVI!.<hr>");
1404       }
1405       else {
1406         $noty .= sprintf("dovevano fare <b>%s</b> punti e ne hanno fatti <b>%d</b>: hanno <b>%s</b>.<hr>",
1407                          ($table->old_asta_pnt > 61 ? "almeno ".$table->old_asta_pnt :
1408                           'pi&ugrave; di 60'), $table->old_pnt,
1409                          ($wol == 1 ? "vinto" : ($wol == 0 ? "pareggiato" : "perso")));
1410       }
1411     }
1412     else {
1413       $noty .= sprintf("<hr>Nell'ultima mano <b>%s</b> si &egrave; chiamato in mano,<br>", 
1414                        xcape($room->user[$win]->name));
1415       if ($table->old_pnt == 120) {
1416         $noty .= sprintf("ha fatto <b>cappotto</b> EBBRAVO!.<hr>");
1417       }
1418       else {
1419         $noty .= sprintf("doveva fare <b>%s</b> punti e ne ha fatti <b>%d</b>: ha <b>%s</b>.<hr>",
1420                          ($table->old_asta_pnt > 61 ? "almeno ".$table->old_asta_pnt :
1421                           'pi&ugrave; di 60'), $table->old_pnt,
1422                          ($wol == 1 ? "vinto" : ($wol == 0 ? "pareggiato" : "perso")));
1423       }
1424     }
1425   }
1426   if ($table->mazzo == $table_pos) 
1427     $noty .= "Fai <b>tu</b> il mazzo,";
1428   else {
1429     $unam = xcape($room->user[$table->player[$table->mazzo]]->name);
1430     $noty .= "Il mazzo a <b>$unam</b>,";
1431   }
1432
1433   if ($user->subst == 'asta') {
1434     if ($table->asta_win == -1)  // auction case
1435       $curplayer = $table->gstart % PLAYERS_N;
1436     else 
1437       $curplayer = $table->asta_win;
1438   }
1439   else if ($user->subst == 'game') {
1440     $curplayer = ($table->gstart + $table->turn) % PLAYERS_N;
1441   }
1442
1443
1444   if ($curplayer == $table_pos) {
1445     $noty .= " tocca a <b>te</b> giocare.";
1446   }
1447   else {
1448     $unam = xcape($room->user[$table->player[$curplayer]]->name);
1449     $noty .= " tocca a <b>$unam</b> giocare.";
1450   }
1451
1452   if ($table->mult > 1) {
1453     $noty .= sprintf(" La partita vale <b>%s</b>.", multoval($table->mult));
1454   }
1455   $noty .= "<hr><br>";
1456
1457   $ret .= show_notify($noty, 3000, "torna alla partita", 500, 400);
1458   
1459   return ($ret);
1460 }
1461
1462 function root_wellcome($user)
1463 {
1464   GLOBAL $root_wellarr;
1465   $ret = "";
1466
1467   for ($i = 0 ; $i < count($root_wellarr) ; $i++)
1468     $ret .= sprintf('chatt_sub("ChanServ: ","%s");', str_replace('"', '\"', $root_wellarr[$i]));
1469
1470   return ($ret);
1471 }
1472
1473 function table_wellcome($user)
1474 {
1475   GLOBAL $table_wellarr;
1476   $ret = "";
1477
1478   for ($i = 0 ; $i < count($table_wellarr) ; $i++)
1479     $ret .= sprintf('chatt_sub("ChanServ: ","%s");', str_replace('"', '\"', $table_wellarr[$i]));
1480
1481   return ($ret);
1482 }
1483
1484 function show_room(&$room, &$user)
1485 {
1486   $ret = sprintf('gst.st = %d;',  $user->step);
1487   $ret .= sprintf('stat = "%s";',  $user->stat);
1488
1489   $ret .= root_wellcome($user);
1490   $ret .= sprintf('subst = "%s";', $user->subst);
1491   $ret .= sprintf('$("myname").innerHTML = "<b>%s</b>";', xcape($user->name,ENT_COMPAT,"UTF-8"));
1492   for ($i = 0 ; $i < TABLES_N ; $i++) {
1493     $ret .= table_content($room, $user, $i);
1494     $act_content = table_act_content(($user->subst == 'standup'), 
1495                                      $room->table[$i]->player_n, $i, $user->table);
1496     $ret .= sprintf('$("table_act%d").innerHTML = "%s";', $i, $act_content);
1497   }
1498   $ret .= standup_content($room, $user);
1499   
1500   return ($ret);
1501 }
1502
1503
1504
1505 /* show table 
1506 is_transition (is from room to table ?)
1507 is_again      (is another game)
1508
1509 Examples                    of $is_transition, $is_again:
1510   from reload of the page:              FALSE, FALSE
1511   from sitdown in room:                  TRUE, FALSE
1512   from table: asta cmd e tutti passano:  TRUE, TRUE
1513   from table: fine partita:              TRUE, TRUE
1514  */
1515 function show_table(&$room, &$user, $sendstep, $is_transition, $is_again)
1516 {
1517   $table_idx = $user->table;
1518   $table = &$room->table[$table_idx];
1519   $table_pos = $user->table_pos;
1520
1521   $ret = "table_init();";
1522   $ret .= $table->exitlock_show(&$room->user, $table_pos);
1523   if (!$is_again) {
1524     /* GENERAL STATUS */
1525     $ret .= sprintf( 'gst.st = %d; stat = "%s"; subst = "%s"; table_pos = %d;',
1526                      $sendstep, $user->stat, $user->subst, $table_pos);
1527     /* BACKGROUND */
1528     $ret .= "background_set();";
1529     
1530     /* USERS INFO */
1531     $ret .= sprintf('$("myname").innerHTML = "<b>%s</b>";', xcape($user->name,ENT_COMPAT,"UTF-8"));
1532     $ret .= sprintf('set_names(" %s", " %s", " %s", " %s", " %s"); ',
1533                     xcape($room->user[$table->player[($table_pos)%PLAYERS_N]]->name),
1534                     xcape($room->user[$table->player[($table_pos+1)%PLAYERS_N]]->name),
1535                     xcape($room->user[$table->player[($table_pos+2)%PLAYERS_N]]->name),
1536                     (PLAYERS_N == 3 ? "" :  xcape($room->user[$table->player[($table_pos+3)%PLAYERS_N]]->name)),
1537                     (PLAYERS_N == 3 ? "" :  xcape($room->user[$table->player[($table_pos+4)%PLAYERS_N]]->name)));
1538   }
1539   /* NOTIFY FOR THE CARD MAKER */
1540   if ($is_transition) { //  && $user->subst ==  "asta" superfluo
1541     $ret .= show_table_info(&$room, &$table, $table_pos);
1542   }
1543   if (!$is_again) 
1544     $ret .= table_wellcome($user);
1545
1546   if ($is_transition && !$is_again) { // appena seduti al tavolo, play della mucca
1547     $ret .= playsound("cow.mp3");
1548   }
1549
1550
1551   /* CARDS */
1552   if ($is_transition) { //  && $user->subst ==  "asta" superfluo
1553     $ret .= "|";
1554     
1555     for ($i = 0 ; $i < 8 ; $i++) {
1556       for ($e = 0 ; $e < PLAYERS_N ; $e++) {
1557         $ct = 0;
1558         for ($o = 0 ; $o < 40 && $ct < $i+1 ; $o++) {
1559           if ($table->card[$o]->owner == (($e + $table->gstart) % PLAYERS_N)) {
1560             $ct++;
1561             if ($ct == $i+1)
1562               break;
1563           }
1564         }
1565         log_rd($user->sess, "O ".$o." VAL ".$table->card[$o]->value." Owner: ".$table->card[$o]->owner);
1566         
1567         $ret .= sprintf( ' card_send(%d,%d,%d,%8.2f,%d);|', ($table->gstart + $e) % PLAYERS_N, 
1568                          $i, ((($e + PLAYERS_N - $table_pos + $table->gstart) % PLAYERS_N) == 0 ?
1569                               $table->card[$o]->value : -1), 
1570                          ($i == 7 && $e == (PLAYERS_N - 1) ? 1 : 0.5),$i+1);
1571       }
1572     }    
1573   }
1574   else {
1575     $taked  = array(0,0,0,0,0);
1576     $inhand = array(0,0,0,0,0);
1577     $ontabl  = array(-1,-1,-1,-1,-1);
1578     $cards  = array();
1579
1580     for ($i = 0 ; $i < 40 ; $i++) {
1581       if ($table->card[$i]->stat == 'hand') {
1582         if ($table->card[$i]->owner == $table_pos) {
1583           $cards[$inhand[$table->card[$i]->owner]] = $table->card[$i]->value;
1584         }
1585         $inhand[$table->card[$i]->owner]++;
1586       }
1587       else if ($table->card[$i]->stat == 'take') {
1588         log_main("Card taked:", $table->card[$i]->value."OWN: ".$table->card[$i]->owner);
1589         $taked[$table->card[$i]->owner]++;
1590       }
1591       else if ($table->card[$i]->stat == 'table') {
1592         $ontabl[$table->card[$i]->owner] = $i;
1593       }
1594     }
1595     $logg = "\n";
1596     for ($i = 0 ; $i < PLAYERS_N ; $i++) {
1597       $logg .= sprintf("INHAND: %d   IN TABLE %d   TAKED %d\n", $inhand[$i], $ontabl[$i], $taked[$i]);
1598     }
1599     log_main("Stat table:", $logg);
1600
1601     /* Set ours cards. */
1602     $oursarg = "";
1603     for ($i = 0 ; $i < $inhand[$table_pos] ; $i++) 
1604       $oursarg .= ($i == 0 ? "" : ", ").$cards[$i];
1605     for ($i = $inhand[$table_pos] ; $i < 8 ; $i++) 
1606       $oursarg .= ($i == 0 ? "" : ", ")."-1";
1607     $ret .= sprintf('card_setours(%s);', $oursarg);
1608
1609     /* Dispose all cards */
1610     for ($i = 0 ; $i < PLAYERS_N ; $i++) {
1611       /* Qui sotto al posto di + 1 c'era + ->gstart ... credo in modo errato */
1612       $ret .= sprintf('cards_dispose(%d,%d,%d);', $i,
1613                       $inhand[$i], $taked[$i]);
1614
1615       if ($ontabl[$i] != -1) {
1616         $ret .= sprintf('card_place(%d,%d,%d,%d,%d);',$i, $inhand[$i], 
1617                         $table->card[$ontabl[$i]]->value, 
1618                         $table->card[$ontabl[$i]]->x, $table->card[$ontabl[$i]]->y);
1619       }
1620     }
1621   }
1622
1623   /* Show auction */
1624   if ($user->subst == 'asta') {
1625
1626     /* show users auction status */
1627     $showst = "";
1628     for ($i = 0 ; $i < PLAYERS_N ; $i++) {
1629       $user_cur = &$room->user[$table->player[$i]];
1630       $showst .= sprintf("%s%d", ($i == 0 ? "" : ", "), 
1631                          ($user_cur->asta_card < 9 ? $user_cur->asta_card : $user_cur->asta_pnt));
1632     }
1633     if (PLAYERS_N == 3)
1634         $showst .= ",-2,-2";
1635     $ret .= sprintf('show_astat(%s);', $showst);
1636
1637     if ($table->asta_win != -1 && $table->asta_win == $table_pos) {
1638       /* show card chooser */
1639       $ret .= sprintf('choose_seed(%s); $("astalascio").style.visibility = ""; $("asta").style.visibility = "hidden";',
1640                       $table->asta_card);
1641     }
1642     else {
1643       /* show auction */
1644       if ($table_pos == ($table->gstart % PLAYERS_N) &&
1645           $table->asta_win == -1) 
1646         $ret .= sprintf('dispose_asta(%d,%d, %s);', 
1647                         $table->asta_card + 1, $table->asta_pnt+1, ($user->handpt <= 2 ? "true" : "false"));
1648       else
1649         $ret .= sprintf('dispose_asta(%d,%d, %s);',
1650                         $table->asta_card + 1, -($table->asta_pnt+1), ($user->handpt <= 2 ?  "true" : "false"));
1651     }
1652
1653     /* Remark */
1654     if ($table->asta_win == -1) { // auction case
1655       if ($table_pos == ($table->gstart % PLAYERS_N)) 
1656         $ret .= "remark_on();";
1657       else
1658         $ret .= "remark_off();";
1659     }
1660     else { // chooseed case
1661       if ($table_pos == $table->asta_win) 
1662         $ret .= "remark_on();";
1663       else
1664         $ret .= "remark_off();";
1665     }
1666   }
1667   else if ($user->subst == 'game') {
1668     /* HIGHLIGHT */
1669     if (($table->gstart + $table->turn) % PLAYERS_N == $table_pos) 
1670       $ret .= "is_my_time = true; remark_on();";
1671     else
1672       $ret .= "remark_off();";
1673     
1674     /* WHO CALL AND WATH */
1675     $ret .= briscola_show($room, $table, $user);
1676     
1677   }
1678   return ($ret);
1679   }
1680
1681 function calculate_winner(&$table)
1682 {
1683   $briontab = FALSE;
1684   $ontab = array();
1685   $ontid = array();
1686   $cur_win  =  -1;
1687   $cur_val  = 100;
1688   $cur_seed = $table->briscola - ($table->briscola % 10);
1689
1690   for ($i = 0 ; $i < 40 ; $i++) {
1691     if ($table->card[$i]->stat != "table")
1692       continue;
1693
1694     log_wr($sess, sprintf("Card On table: [%d]", $i));
1695
1696     $v = $table->card[$i]->value; 
1697     $ontab[$table->card[$i]->owner] = $v;
1698     $ontid[$table->card[$i]->owner] = $i;
1699     /* se briscola setto il flag */
1700     if (($v - ($v % 10)) == $cur_seed)
1701       $briontab = TRUE;
1702   }
1703
1704   if ($briontab == FALSE) {
1705     $cur_win  = $table->gstart;
1706     $cur_val  = $ontab[$cur_win];
1707     $cur_seed = $cur_val - ($cur_val % 10);
1708   }
1709
1710   for ($i = 0 ; $i < PLAYERS_N ; $i++) {
1711     if (($ontab[$i] - ($ontab[$i] % 10)) == $cur_seed) {
1712       if ($ontab[$i] < $cur_val) {
1713         $cur_val = $ontab[$i];
1714         $cur_win = $i;
1715       }
1716     }
1717   }
1718
1719   for ($i = 0 ; $i < PLAYERS_N ; $i++) {
1720     $table->card[$ontid[$i]]->owner = $cur_win;
1721     $table->card[$ontid[$i]]->stat =  "take"; // Card stat
1722   }
1723   return ($cur_win);
1724 }
1725
1726 function calculate_points(&$table)
1727 {
1728   GLOBAL $G_all_points; 
1729
1730   $pro = 0;
1731
1732   if ($table->asta_pnt == 60)
1733     $table->asta_pnt = 61;
1734
1735   $table->old_reason = "";
1736   $table->old_win = $table->asta_win;
1737   $table->old_friend = $table->friend;
1738   $table->old_asta_pnt = $table->asta_pnt;
1739
1740   for ($i = 0 ; $i < 40 ; $i++) {
1741     $ctt = $table->card[$i]->value % 10;
1742     $own = $table->card[$i]->owner;
1743     if ($own == $table->asta_win || $own == $table->friend) 
1744       $pro += $G_all_points[$ctt];
1745   }
1746
1747   log_wr("XXX", sprintf("PRO: [%d]", $pro));
1748
1749   
1750   if ($table->asta_pnt == 61 && $pro == 60) { // PATTA !
1751     $table->points[$table->points_n % MAX_POINTS] = array();
1752     for ($i = 0 ; $i < PLAYERS_N ; $i++) 
1753       $table->points[$table->points_n % MAX_POINTS][$i] = 0;
1754     $table->points_n++;
1755     $table->old_pnt = $pro;
1756     $table->mult *= 2;
1757
1758     return;
1759   }
1760
1761   if ($pro >= $table->asta_pnt) 
1762     $sig = 1;
1763   else
1764     $sig = -1;
1765
1766   $table->points[$table->points_n % MAX_POINTS] = array();
1767   for ($i = 0 ; $i < 5 ; $i++) {
1768     if ($i == $table->asta_win) 
1769       $pt = ($i == $table->friend ? 4 : 2);
1770     else if ($i == $table->friend) 
1771       $pt = 1;
1772     else
1773       $pt = -1;
1774
1775     log_wr("XXX", sprintf("PRO: pt[%d][%d] = %d", $table->points_n % MAX_POINTS, $i, $pt));
1776
1777     $pt = $pt * $sig * $table->mult * ($pro == 120 ? 2 : 1);
1778
1779     log_wr("XXX", sprintf("PRO:[%d][%d][%d]", $sig, $table->mult, ($pro == 120 ? 2 : 1)));
1780     
1781     $table->points[$table->points_n % MAX_POINTS][$i] = $pt;
1782     $table->total[$i] += $pt;
1783   }
1784   $table->points_n++;
1785   $table->old_pnt = $pro;
1786   $table->mult = 1;
1787 }
1788
1789 function validate_sess($sess) 
1790 {
1791   if (strlen($sess) == SESS_LEN) 
1792     return (TRUE);
1793   else
1794     return (FALSE);
1795 }
1796
1797 function validate_name($name) 
1798 {
1799   $name_new = str_replace(' ', '_', substr(trim($name),0,12));
1800
1801   for ($i = 0 ; $i < strlen($name_new) ; $i++) {
1802     $c = $name_new[$i];
1803     if (($c >= "a" && $c <= "z") || ($c >= "A" && $c <= "Z") || ($c >= "0" && $c <= "9"))
1804       return ($name_new);
1805   }
1806
1807   return (FALSE);
1808 }
1809
1810 function playsound($filename)
1811 {
1812   return (sprintf('playsound("flasou", "%s");', $filename));
1813 }
1814
1815 function secstoword($secs)
1816 {
1817   $mins = floor($secs / 60);
1818   $secs = $secs % 60;
1819   if ($mins > 0) 
1820     $ret = sprintf("%d minut%s%s", $mins, ($mins > 1 ? "i" : "o"), ($secs > 0 ? " e " : ""));
1821   
1822   if ($secs > 0)
1823     $ret .= sprintf("%d second%s", $secs, ($secs > 1 ? "i" : "o"));
1824   
1825   return ($ret);
1826 }
1827
1828 ?>